Finish previous change.
[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
502add23
RS
3621#ifdef X_IO_BUG
3622 if (! event_found)
3623 /* On some systems, an X bug causes Emacs to get no more events
3624 when the window is destroyed. Detect that. */
3625 XNoOp (x_current_display);
3626#endif /* X_IO_BUG */
3627
dc6f92b8
JB
3628#ifdef HAVE_SELECT
3629 if (expected && ! event_found)
3630 {
3631 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3632 there is an EOF condition; in other words, that X has died.
3633 Act as if there had been a hangup. */
dc6f92b8 3634 int fd = ConnectionNumber (x_current_display);
307feb1f 3635 SELECT_TYPE mask, junk1, junk2;
66f55a9d 3636 EMACS_TIME timeout;
dc6f92b8 3637
61c3ce62
RS
3638 FD_ZERO (&mask);
3639 FD_SET (fd, &mask);
66f55a9d 3640 EMACS_SET_SECS_USECS (timeout, 0, 0);
307feb1f
RS
3641 FD_ZERO (&junk1);
3642 FD_ZERO (&junk2);
3643 if (0 != select (fd + 1, &mask, &junk1, &junk2, &timeout)
dc6f92b8
JB
3644 && !XStuffPending ())
3645 kill (getpid (), SIGHUP);
3646 }
61c3ce62 3647#endif /* HAVE_SELECT */
dc6f92b8 3648
f451eb13 3649#ifndef HAVE_X11
f676886a 3650 if (updating_frame == 0)
dc6f92b8 3651 x_do_pending_expose ();
f451eb13 3652#endif
dc6f92b8
JB
3653
3654 UNBLOCK_INPUT;
3655 return count;
3656}
3657
3658#ifndef HAVE_X11
3659/* Read and process only Expose events
3660 until we get an ExposeCopy event; then return.
3661 This is used in insert/delete line.
3662 We assume input is already blocked. */
3663
3664static void
3665x_read_exposes ()
3666{
f676886a 3667 struct frame *f;
dc6f92b8
JB
3668 XKeyPressedEvent event;
3669
3670 while (1)
3671 {
3672 /* while there are more events*/
3673 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3674 switch (event.type)
3675 {
3676 case ExposeWindow:
3677 if (event.subwindow != 0)
3678 break; /* duplicate event */
f676886a
JB
3679 f = x_window_to_frame (event.window);
3680 if (event.window == f->display.x->icon_desc)
dc6f92b8 3681 {
f676886a 3682 refreshicon (f);
dc6f92b8
JB
3683 break;
3684 }
c118dd06 3685 if (event.window == FRAME_X_WINDOW (f))
dc6f92b8
JB
3686 {
3687 expose_all_windows = 1;
f676886a 3688 f->display.x->needs_exposure = 1;
dc6f92b8
JB
3689 break;
3690 }
3691 break;
3692
3693 case ExposeRegion:
3694 if (event.subwindow != 0)
3695 break; /* duplicate event */
f676886a
JB
3696 f = x_window_to_frame (event.window);
3697 if (event.window == f->display.x->icon_desc)
dc6f92b8 3698 {
f676886a 3699 refreshicon (f);
dc6f92b8
JB
3700 break;
3701 }
3702 /* If window already needs full redraw, ignore this rectangle. */
f676886a 3703 if (expose_all_windows && f->display.x->needs_exposure)
dc6f92b8
JB
3704 break;
3705 /* Put the event on the queue of rectangles to redraw. */
3706 if (enqueue_event (&event, &x_expose_queue))
3707 /* If it is full, we can't record the rectangle,
3708 so redraw this entire window. */
3709 {
3710 /* Say must check all windows' needs_exposure flags. */
3711 expose_all_windows = 1;
f676886a 3712 f->display.x->needs_exposure = 1;
dc6f92b8
JB
3713 }
3714 break;
3715
3716 case ExposeCopy:
3717 return;
3718 }
3719 }
3720}
3721#endif /* HAVE_X11 */
3722
dc6f92b8 3723\f
f451eb13
JB
3724/* Drawing the cursor. */
3725
3726
dc6f92b8
JB
3727/* Draw a hollow box cursor. Don't change the inside of the box. */
3728
3729static void
f676886a
JB
3730x_draw_box (f)
3731 struct frame *f;
dc6f92b8 3732{
12ba150f
JB
3733 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3734 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
f676886a
JB
3735 int width = FONT_WIDTH (f->display.x->font);
3736 int height = FONT_HEIGHT (f->display.x->font);
dc6f92b8
JB
3737
3738#ifdef HAVE_X11
c118dd06 3739 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
f676886a 3740 f->display.x->cursor_gc,
dc6f92b8 3741 left, top, width - 1, height - 1);
c118dd06
JB
3742#else /* ! defined (HAVE_X11) */
3743 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3744 left, top, width, 1,
f676886a 3745 f->display.x->cursor_pixel);
dc6f92b8 3746
c118dd06 3747 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3748 left, top, 1, height,
f676886a 3749 f->display.x->cursor_pixel);
dc6f92b8 3750
c118dd06 3751 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3752 left+width-1, top, 1, height,
f676886a 3753 f->display.x->cursor_pixel);
dc6f92b8 3754
c118dd06 3755 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3756 left, top+height-1, width, 1,
f676886a 3757 f->display.x->cursor_pixel);
c118dd06 3758#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3759}
3760
f676886a 3761/* Clear the cursor of frame F to background color,
dc6f92b8
JB
3762 and mark the cursor as not shown.
3763 This is used when the text where the cursor is
3764 is about to be rewritten. */
3765
3766static void
f676886a
JB
3767clear_cursor (f)
3768 struct frame *f;
dc6f92b8
JB
3769{
3770 int mask;
3771
f451eb13 3772 if (! FRAME_VISIBLE_P (f)
f676886a 3773 || f->phys_cursor_x < 0)
dc6f92b8
JB
3774 return;
3775
3776#ifdef HAVE_X11
f676886a 3777 x_display_cursor (f, 0);
c118dd06
JB
3778#else /* ! defined (HAVE_X11) */
3779 XPixSet (FRAME_X_WINDOW (f),
12ba150f
JB
3780 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3781 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
f676886a
JB
3782 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3783 f->display.x->background_pixel);
c118dd06 3784#endif /* ! defined (HAVE_X11) */
f676886a 3785 f->phys_cursor_x = -1;
dc6f92b8
JB
3786}
3787
f676886a 3788/* Redraw the glyph at ROW, COLUMN on frame F, in the style
90e65f07
JB
3789 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3790 glyph drawn. */
dc6f92b8
JB
3791
3792static void
f676886a
JB
3793x_draw_single_glyph (f, row, column, glyph, highlight)
3794 struct frame *f;
dc6f92b8 3795 int row, column;
90e65f07 3796 GLYPH glyph;
dc6f92b8
JB
3797 int highlight;
3798{
f676886a 3799 dumpglyphs (f,
12ba150f
JB
3800 CHAR_TO_PIXEL_COL (f, column),
3801 CHAR_TO_PIXEL_ROW (f, row),
07e34cb0 3802 &glyph, 1, highlight);
dc6f92b8
JB
3803}
3804
dc6f92b8 3805static void
dbc4e1c1 3806x_display_bar_cursor (f, on)
f676886a 3807 struct frame *f;
dc6f92b8
JB
3808 int on;
3809{
f676886a 3810 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
90e65f07 3811
49d838ea
JB
3812 /* This is pointless on invisible frames, and dangerous on garbaged
3813 frames; in the latter case, the frame may be in the midst of
3814 changing its size, and curs_x and curs_y may be off the frame. */
3815 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dbc4e1c1
JB
3816 return;
3817
3818 if (! on && f->phys_cursor_x < 0)
3819 return;
3820
f676886a 3821 /* If we're not updating, then we want to use the current frame's
1113d9db 3822 cursor position, not our local idea of where the cursor ought to be. */
f676886a 3823 if (f != updating_frame)
1113d9db 3824 {
f676886a
JB
3825 curs_x = FRAME_CURSOR_X (f);
3826 curs_y = FRAME_CURSOR_Y (f);
1113d9db
JB
3827 }
3828
dbc4e1c1
JB
3829 /* If there is anything wrong with the current cursor state, remove it. */
3830 if (f->phys_cursor_x >= 0
3831 && (!on
3832 || f->phys_cursor_x != curs_x
3833 || f->phys_cursor_y != curs_y
3834 || f->display.x->current_cursor != bar_cursor))
3835 {
3836 /* Erase the cursor by redrawing the character underneath it. */
3837 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3838 f->phys_cursor_glyph,
3839 current_glyphs->highlight[f->phys_cursor_y]);
3840 f->phys_cursor_x = -1;
3841 }
3842
3843 /* If we now need a cursor in the new place or in the new form, do it so. */
3844 if (on
3845 && (f->phys_cursor_x < 0
3846 || (f->display.x->current_cursor != bar_cursor)))
3847 {
3848 f->phys_cursor_glyph
3849 = ((current_glyphs->enable[curs_y]
3850 && curs_x < current_glyphs->used[curs_y])
3851 ? current_glyphs->glyphs[curs_y][curs_x]
3852 : SPACEGLYPH);
3853 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3854 f->display.x->cursor_gc,
3855 CHAR_TO_PIXEL_COL (f, curs_x),
3856 CHAR_TO_PIXEL_ROW (f, curs_y),
3857 1, FONT_HEIGHT (f->display.x->font));
3858
3859 f->phys_cursor_x = curs_x;
3860 f->phys_cursor_y = curs_y;
3861
3862 f->display.x->current_cursor = bar_cursor;
3863 }
3864
3865 if (updating_frame != f)
3866 XFlushQueue ();
3867}
3868
3869
3870/* Turn the displayed cursor of frame F on or off according to ON.
3871 If ON is nonzero, where to put the cursor is specified
3872 by F->cursor_x and F->cursor_y. */
3873
3874static void
3875x_display_box_cursor (f, on)
3876 struct frame *f;
3877 int on;
3878{
3879 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3880
49d838ea
JB
3881 /* This is pointless on invisible frames, and dangerous on garbaged
3882 frames; in the latter case, the frame may be in the midst of
3883 changing its size, and curs_x and curs_y may be off the frame. */
3884 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dc6f92b8
JB
3885 return;
3886
3887 /* If cursor is off and we want it off, return quickly. */
f676886a 3888 if (!on && f->phys_cursor_x < 0)
dc6f92b8
JB
3889 return;
3890
dbc4e1c1
JB
3891 /* If we're not updating, then we want to use the current frame's
3892 cursor position, not our local idea of where the cursor ought to be. */
3893 if (f != updating_frame)
3894 {
3895 curs_x = FRAME_CURSOR_X (f);
3896 curs_y = FRAME_CURSOR_Y (f);
3897 }
3898
dc6f92b8
JB
3899 /* If cursor is currently being shown and we don't want it to be
3900 or it is in the wrong place,
3901 or we want a hollow box and it's not so, (pout!)
3902 erase it. */
f676886a 3903 if (f->phys_cursor_x >= 0
dc6f92b8 3904 && (!on
f676886a
JB
3905 || f->phys_cursor_x != curs_x
3906 || f->phys_cursor_y != curs_y
dbc4e1c1 3907 || (f->display.x->current_cursor != hollow_box_cursor
f676886a 3908 && (f != x_highlight_frame))))
dc6f92b8
JB
3909 {
3910 /* Erase the cursor by redrawing the character underneath it. */
f676886a
JB
3911 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3912 f->phys_cursor_glyph,
3913 current_glyphs->highlight[f->phys_cursor_y]);
3914 f->phys_cursor_x = -1;
dc6f92b8
JB
3915 }
3916
3917 /* If we want to show a cursor,
3918 or we want a box cursor and it's not so,
3919 write it in the right place. */
3920 if (on
f676886a 3921 && (f->phys_cursor_x < 0
dbc4e1c1 3922 || (f->display.x->current_cursor != filled_box_cursor
f676886a 3923 && f == x_highlight_frame)))
dc6f92b8 3924 {
f676886a 3925 f->phys_cursor_glyph
1113d9db
JB
3926 = ((current_glyphs->enable[curs_y]
3927 && curs_x < current_glyphs->used[curs_y])
3928 ? current_glyphs->glyphs[curs_y][curs_x]
90e65f07 3929 : SPACEGLYPH);
f676886a 3930 if (f != x_highlight_frame)
dc6f92b8 3931 {
f676886a 3932 x_draw_box (f);
dbc4e1c1 3933 f->display.x->current_cursor = hollow_box_cursor;
dc6f92b8
JB
3934 }
3935 else
3936 {
f676886a
JB
3937 x_draw_single_glyph (f, curs_y, curs_x,
3938 f->phys_cursor_glyph, 2);
dbc4e1c1 3939 f->display.x->current_cursor = filled_box_cursor;
dc6f92b8
JB
3940 }
3941
f676886a
JB
3942 f->phys_cursor_x = curs_x;
3943 f->phys_cursor_y = curs_y;
dc6f92b8
JB
3944 }
3945
f676886a 3946 if (updating_frame != f)
dc6f92b8
JB
3947 XFlushQueue ();
3948}
3949
f676886a
JB
3950x_display_cursor (f, on)
3951 struct frame *f;
dc6f92b8
JB
3952 int on;
3953{
dbc4e1c1 3954 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
f676886a 3955 x_display_box_cursor (f, on);
dbc4e1c1 3956 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
f676886a 3957 x_display_bar_cursor (f, on);
dbc4e1c1
JB
3958 else
3959 /* Those are the only two we have implemented! */
3960 abort ();
dc6f92b8
JB
3961}
3962\f
3963/* Icons. */
3964
f676886a 3965/* Refresh bitmap kitchen sink icon for frame F
dc6f92b8
JB
3966 when we get an expose event for it. */
3967
f676886a
JB
3968refreshicon (f)
3969 struct frame *f;
dc6f92b8
JB
3970{
3971#ifdef HAVE_X11
3972 /* Normally, the window manager handles this function. */
c118dd06 3973#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
3974 int mask;
3975
f676886a
JB
3976 if (f->display.x->icon_bitmap_flag)
3977 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
dc6f92b8
JB
3978 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3979 icon_bitmap, GXcopy, AllPlanes);
3980 else
3981 {
f676886a 3982 extern struct frame *selected_frame;
dc6f92b8
JB
3983 struct Lisp_String *str;
3984 unsigned char *string;
3985
3986 string
f676886a 3987 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
dc6f92b8 3988
f676886a 3989 if (f->display.x->icon_label != string)
dc6f92b8 3990 {
f676886a
JB
3991 f->display.x->icon_label = string;
3992 XChangeWindow (f->display.x->icon_desc,
dc6f92b8
JB
3993 XQueryWidth (string, icon_font_info->id) + 10,
3994 icon_font_info->height + 10);
3995 }
3996
f676886a 3997 XText (f->display.x->icon_desc, 5, 5, string,
dc6f92b8
JB
3998 str->size, icon_font_info->id,
3999 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
4000 }
4001 XFlushQueue ();
c118dd06 4002#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4003}
4004
dbc4e1c1 4005/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
4006
4007int
f676886a
JB
4008x_bitmap_icon (f)
4009 struct frame *f;
dc6f92b8
JB
4010{
4011 int mask;
4012 Window icon_window;
4013
c118dd06 4014 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
4015 return 1;
4016
4017#ifdef HAVE_X11
8583db58
RS
4018 if (! icon_bitmap)
4019 icon_bitmap =
4020 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
4021 gnu_bits, gnu_width, gnu_height);
f676886a
JB
4022 x_wm_set_icon_pixmap (f, icon_bitmap);
4023 f->display.x->icon_bitmap_flag = 1;
c118dd06 4024#else /* ! defined (HAVE_X11) */
f676886a 4025 if (f->display.x->icon_desc)
dc6f92b8 4026 {
c118dd06 4027 XClearIconWindow (FRAME_X_WINDOW (f));
f676886a 4028 XDestroyWindow (f->display.x->icon_desc);
dc6f92b8
JB
4029 }
4030
f676886a 4031 icon_window = XCreateWindow (f->display.x->parent_desc,
dc6f92b8
JB
4032 0, 0, sink_width, sink_height,
4033 2, WhitePixmap, (Pixmap) NULL);
4034
4035 if (icon_window == 0)
4036 return 1;
4037
c118dd06 4038 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
dc6f92b8
JB
4039 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
4040
f676886a
JB
4041 f->display.x->icon_desc = icon_window;
4042 f->display.x->icon_bitmap_flag = 1;
dc6f92b8
JB
4043
4044 if (icon_bitmap == 0)
4045 icon_bitmap
4046 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
c118dd06 4047#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4048
4049 return 0;
4050}
4051
4052
f676886a 4053/* Make the x-window of frame F use a rectangle with text. */
dc6f92b8
JB
4054
4055int
f676886a
JB
4056x_text_icon (f, icon_name)
4057 struct frame *f;
dc6f92b8
JB
4058 char *icon_name;
4059{
4060#ifndef HAVE_X11
4061 int mask;
4062 int width;
4063 Window icon_window;
4064 char *X_DefaultValue;
4065 Bitmap b1;
4066
dc6f92b8
JB
4067#ifndef WhitePixel
4068#define WhitePixel 1
c118dd06 4069#endif /* WhitePixel */
dc6f92b8
JB
4070
4071#ifndef BlackPixel
4072#define BlackPixel 0
c118dd06
JB
4073#endif /* BlackPixel */
4074#endif /* HAVE_X11 */
dc6f92b8 4075
c118dd06 4076 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
4077 return 1;
4078
dc6f92b8
JB
4079#ifdef HAVE_X11
4080 if (icon_name)
f676886a 4081 f->display.x->icon_label = icon_name;
dc6f92b8 4082 else
f676886a
JB
4083 if (! f->display.x->icon_label)
4084 f->display.x->icon_label = " *emacs* ";
dc6f92b8 4085
dfeccd2d 4086#if 0
c118dd06 4087 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
f676886a 4088 (char *) f->display.x->icon_label);
dfeccd2d 4089#endif
dc6f92b8 4090
f676886a 4091 f->display.x->icon_bitmap_flag = 0;
b1c884c3 4092 x_wm_set_icon_pixmap (f, 0);
c118dd06 4093#else /* ! defined (HAVE_X11) */
dbc4e1c1
JB
4094 if (icon_font_info == 0)
4095 icon_font_info
4096 = XGetFont (XGetDefault (XDISPLAY
59653951 4097 (char *) XSTRING (Vinvocation_name)->data,
dbc4e1c1
JB
4098 "BodyFont"));
4099
f676886a 4100 if (f->display.x->icon_desc)
dc6f92b8 4101 {
c118dd06 4102 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
f676886a 4103 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
dc6f92b8
JB
4104 }
4105
4106 if (icon_name)
f676886a 4107 f->display.x->icon_label = (unsigned char *) icon_name;
dc6f92b8 4108 else
f676886a
JB
4109 if (! f->display.x->icon_label)
4110 f->display.x->icon_label = XSTRING (f->name)->data;
dc6f92b8 4111
f676886a
JB
4112 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
4113 icon_window = XCreateWindow (f->display.x->parent_desc,
4114 f->display.x->left_pos,
4115 f->display.x->top_pos,
dc6f92b8
JB
4116 width + 10, icon_font_info->height + 10,
4117 2, BlackPixmap, WhitePixmap);
4118
4119 if (icon_window == 0)
4120 return 1;
4121
c118dd06 4122 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
dc6f92b8
JB
4123 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
4124
f676886a
JB
4125 f->display.x->icon_desc = icon_window;
4126 f->display.x->icon_bitmap_flag = 0;
4127 f->display.x->icon_label = 0;
c118dd06 4128#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4129
4130 return 0;
4131}
4132\f
4746118a
JB
4133/* Handling X errors. */
4134
12ba150f
JB
4135/* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4136 X server's connection, or an error reported via the X protocol. */
16bd92ea 4137
4746118a 4138static SIGTYPE
c118dd06 4139x_connection_closed ()
4746118a
JB
4140{
4141 if (_Xdebug)
4142 abort ();
12ba150f 4143
1cd2d6d4 4144 shut_down_emacs (0, 1, Qnil);
12ba150f
JB
4145
4146 exit (70);
4746118a
JB
4147}
4148
8922af5f
JB
4149/* An X error handler which prints an error message and then kills
4150 Emacs. This is what's normally installed as Xlib's handler for
4151 protocol errors. */
c118dd06
JB
4152static int
4153x_error_quitter (display, error)
4154 Display *display;
4155 XErrorEvent *error;
4156{
4157 char buf[256];
dc6f92b8 4158
c118dd06
JB
4159 /* Note that there is no real way portable across R3/R4 to get the
4160 original error handler. */
dc6f92b8 4161
c118dd06
JB
4162 XGetErrorText (display, error->error_code, buf, sizeof (buf));
4163 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
4164 buf, error->request_code);
dc6f92b8 4165
e09f9351 4166#if 0
12ba150f
JB
4167 /* While we're testing Emacs 19, we'll just dump core whenever we
4168 get an X error, so we can figure out why it happened. */
4169 abort ();
e09f9351 4170#endif
12ba150f 4171
c118dd06 4172 x_connection_closed ();
dc6f92b8
JB
4173}
4174
8922af5f
JB
4175/* A handler for X IO errors which prints an error message and then
4176 kills Emacs. This is what is always installed as Xlib's handler
4177 for I/O errors. */
4178static int
4179x_io_error_quitter (display)
4180 Display *display;
4181{
4182 fprintf (stderr, "Connection to X server %s lost.\n",
4183 XDisplayName (DisplayString (display)));
4184
e09f9351 4185#if 0
8922af5f
JB
4186 /* While we're testing Emacs 19, we'll just dump core whenever we
4187 get an X error, so we can figure out why it happened. */
4188 abort ();
e09f9351 4189#endif
8922af5f
JB
4190
4191 x_connection_closed ();
4192}
4193
c118dd06 4194/* A buffer for storing X error messages. */
cef13e55
RS
4195static char *x_caught_error_message;
4196#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
c118dd06
JB
4197
4198/* An X error handler which stores the error message in
4199 x_caught_error_message. This is what's installed when
4200 x_catch_errors is in effect. */
4201static int
4202x_error_catcher (display, error)
4203 Display *display;
4204 XErrorEvent *error;
4205{
4206 XGetErrorText (display, error->error_code,
cef13e55 4207 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
c118dd06
JB
4208}
4209
4210
4211/* Begin trapping X errors.
dc6f92b8 4212
c118dd06
JB
4213 After calling this function, X protocol errors no longer cause
4214 Emacs to exit; instead, they are recorded in x_cfc_error_message.
dc6f92b8 4215
c118dd06
JB
4216 Calling x_check_errors signals an Emacs error if an X error has
4217 occurred since the last call to x_catch_errors or x_check_errors.
4218
4219 Calling x_uncatch_errors resumes the normal error handling. */
4220
4221void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
4222
4223void
4224x_catch_errors ()
dc6f92b8 4225{
c118dd06
JB
4226 /* Make sure any errors from previous requests have been dealt with. */
4227 XSync (x_current_display, False);
dc6f92b8 4228
c118dd06 4229 /* Set up the error buffer. */
60f9aad3 4230 x_caught_error_message
cef13e55
RS
4231 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4232 x_caught_error_message[0] = '\0';
16bd92ea 4233
c118dd06
JB
4234 /* Install our little error handler. */
4235 XHandleError (x_error_catcher);
4236}
16bd92ea 4237
c118dd06
JB
4238/* If any X protocol errors have arrived since the last call to
4239 x_catch_errors or x_check_errors, signal an Emacs error using
4240 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4241void
4242x_check_errors (format)
4243 char *format;
4244{
4245 /* Make sure to catch any errors incurred so far. */
4246 XSync (x_current_display, False);
16bd92ea 4247
cef13e55 4248 if (x_caught_error_message[0])
c118dd06 4249 {
cef13e55 4250 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
dc6f92b8 4251
cef13e55 4252 sprintf (buf, format, x_caught_error_message);
c118dd06
JB
4253 x_uncatch_errors ();
4254 error (buf);
4255 }
4256}
4257
4258void
4259x_uncatch_errors ()
4260{
9ac0d9e0 4261 xfree (x_caught_error_message);
cef13e55 4262 x_caught_error_message = 0;
c118dd06 4263 XHandleError (x_error_quitter);
dc6f92b8
JB
4264}
4265
dc6f92b8
JB
4266#if 0
4267static unsigned int x_wire_count;
4268x_trace_wire ()
4269{
4270 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4271}
c118dd06 4272#endif /* ! 0 */
dc6f92b8
JB
4273
4274\f
f451eb13
JB
4275/* Changing the font of the frame. */
4276
f676886a 4277/* Set the font of the x-window specified by frame F
dc6f92b8 4278 to the font named NEWNAME. This is safe to use
f676886a 4279 even before F has an actual x-window. */
dc6f92b8
JB
4280
4281#ifdef HAVE_X11
4282
2224a5fc
RS
4283struct font_info
4284{
4285 XFontStruct *font;
4286 char *name;
4287};
4288
dc6f92b8 4289/* A table of all the fonts we have already loaded. */
2224a5fc 4290static struct font_info *x_font_table;
dc6f92b8
JB
4291
4292/* The current capacity of x_font_table. */
4293static int x_font_table_size;
4294
4295/* The number of fonts actually stored in x_font_table.
4296 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4297 0 <= n_fonts <= x_font_table_size. */
4298static int n_fonts;
4299
b5cf7a0e 4300Lisp_Object
f676886a
JB
4301x_new_font (f, fontname)
4302 struct frame *f;
dc6f92b8
JB
4303 register char *fontname;
4304{
dc6f92b8
JB
4305 int already_loaded;
4306 int n_matching_fonts;
4307 XFontStruct *font_info;
4308 char **font_names;
4309
4310 /* Get a list of all the fonts that match this name. Once we
4311 have a list of matching fonts, we compare them against the fonts
4312 we already have by comparing font ids. */
2224a5fc
RS
4313 font_names = (char **) XListFonts (x_current_display, fontname,
4314 1024, &n_matching_fonts);
0c94f6ee
JB
4315 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4316 find any matches; font_names == 0 is the only clue. */
4317 if (! font_names)
4318 n_matching_fonts = 0;
4319
5835f860
RS
4320 /* Don't just give up if n_matching_fonts is 0.
4321 Apparently there's a bug on Suns: XListFontsWithInfo can
4322 fail to find a font, but XLoadQueryFont may still find it. */
dc6f92b8 4323
90e65f07 4324 /* See if we've already loaded a matching font. */
5835f860
RS
4325 already_loaded = -1;
4326 if (n_matching_fonts != 0)
4327 {
4328 int i, j;
dc6f92b8 4329
5835f860
RS
4330 for (i = 0; i < n_fonts; i++)
4331 for (j = 0; j < n_matching_fonts; j++)
2224a5fc 4332 if (!strcmp (x_font_table[i].name, font_names[j]))
5835f860
RS
4333 {
4334 already_loaded = i;
4335 fontname = font_names[j];
4336 goto found_font;
4337 }
4338 }
dc6f92b8
JB
4339 found_font:
4340
4341 /* If we have, just return it from the table. */
2224a5fc
RS
4342 if (already_loaded >= 0)
4343 f->display.x->font = x_font_table[already_loaded].font;
90e65f07 4344
dc6f92b8
JB
4345 /* Otherwise, load the font and add it to the table. */
4346 else
4347 {
9696f58b 4348 int i;
dc6f92b8
JB
4349 XFontStruct *font;
4350
9696f58b 4351 /* Try to find a character-cell font in the list. */
f126bd67
JB
4352#if 0
4353 /* A laudable goal, but this isn't how to do it. */
9696f58b
JB
4354 for (i = 0; i < n_matching_fonts; i++)
4355 if (! font_info[i].per_char)
4356 break;
f126bd67
JB
4357#else
4358 i = 0;
4359#endif
9696f58b 4360
5835f860
RS
4361 /* See comment above. */
4362 if (n_matching_fonts != 0)
9696f58b
JB
4363 fontname = font_names[i];
4364
dc6f92b8
JB
4365 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
4366 if (! font)
5835f860 4367 {
2224a5fc 4368 /* Free the information from XListFonts. */
5835f860 4369 if (n_matching_fonts)
2224a5fc 4370 XFreeFontNames (font_names);
5835f860
RS
4371 return Qnil;
4372 }
dc6f92b8
JB
4373
4374 /* Do we need to create the table? */
4375 if (x_font_table_size == 0)
4376 {
4377 x_font_table_size = 16;
4378 x_font_table
2224a5fc
RS
4379 = (struct font_info *) xmalloc (x_font_table_size
4380 * sizeof (x_font_table[0]));
dc6f92b8
JB
4381 }
4382 /* Do we need to grow the table? */
4383 else if (n_fonts >= x_font_table_size)
4384 {
90e65f07 4385 x_font_table_size *= 2;
dc6f92b8 4386 x_font_table
2224a5fc
RS
4387 = (struct font_info *) xrealloc (x_font_table,
4388 (x_font_table_size
4389 * sizeof (x_font_table[0])));
dc6f92b8
JB
4390 }
4391
dff815ef 4392 x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
2224a5fc
RS
4393 bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1);
4394 f->display.x->font = x_font_table[n_fonts++].font = font;
dc6f92b8 4395 }
2224a5fc 4396
f676886a 4397 /* Now make the frame display the given font. */
c118dd06 4398 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 4399 {
f676886a
JB
4400 XSetFont (x_current_display, f->display.x->normal_gc,
4401 f->display.x->font->fid);
4402 XSetFont (x_current_display, f->display.x->reverse_gc,
4403 f->display.x->font->fid);
4404 XSetFont (x_current_display, f->display.x->cursor_gc,
4405 f->display.x->font->fid);
4406
4407 x_set_window_size (f, f->width, f->height);
dc6f92b8
JB
4408 }
4409
b5cf7a0e
JB
4410 {
4411 Lisp_Object lispy_name = build_string (fontname);
4412
4413
2224a5fc 4414 /* Free the information from XListFonts. The data
b5cf7a0e 4415 we actually retain comes from XLoadQueryFont. */
2224a5fc 4416 XFreeFontNames (font_names);
b5cf7a0e
JB
4417
4418 return lispy_name;
4419 }
dc6f92b8 4420}
c118dd06 4421#else /* ! defined (HAVE_X11) */
f676886a
JB
4422x_new_font (f, newname)
4423 struct frame *f;
dc6f92b8
JB
4424 register char *newname;
4425{
4426 FONT_TYPE *temp;
4427 int mask;
4428
4429 temp = XGetFont (newname);
4430 if (temp == (FONT_TYPE *) 0)
4431 return 1;
4432
f676886a
JB
4433 if (f->display.x->font)
4434 XLoseFont (f->display.x->font);
dc6f92b8 4435
f676886a 4436 f->display.x->font = temp;
dc6f92b8 4437
c118dd06 4438 if (FRAME_X_WINDOW (f) != 0)
f676886a 4439 x_set_window_size (f, f->width, f->height);
dc6f92b8
JB
4440
4441 return 0;
4442}
c118dd06 4443#endif /* ! defined (HAVE_X11) */
dc6f92b8 4444\f
f676886a
JB
4445x_calc_absolute_position (f)
4446 struct frame *f;
dc6f92b8
JB
4447{
4448#ifdef HAVE_X11
6dba1858
RS
4449 Window win, child;
4450 int win_x = 0, win_y = 0;
4451
4452 /* Find the position of the outside upper-left corner of
4453 the inner window, with respect to the outer window. */
4454 if (f->display.x->parent_desc != ROOT_WINDOW)
4455 {
4456 BLOCK_INPUT;
4457 XTranslateCoordinates (x_current_display,
4458
4459 /* From-window, to-window. */
4460 f->display.x->window_desc,
4461 f->display.x->parent_desc,
4462
4463 /* From-position, to-position. */
4464 0, 0, &win_x, &win_y,
4465
4466 /* Child of win. */
4467 &child);
4468 UNBLOCK_INPUT;
4469 }
4470
4471 /* Treat negative positions as relative to the leftmost bottommost
4472 position that fits on the screen. */
f676886a 4473 if (f->display.x->left_pos < 0)
31ea78fd 4474 f->display.x->left_pos = (x_screen_width
69388238 4475 - 2 * f->display.x->border_width - win_x
31ea78fd
JB
4476 - PIXEL_WIDTH (f)
4477 + f->display.x->left_pos);
dc6f92b8 4478
f676886a 4479 if (f->display.x->top_pos < 0)
31ea78fd 4480 f->display.x->top_pos = (x_screen_height
69388238 4481 - 2 * f->display.x->border_width - win_y
31ea78fd
JB
4482 - PIXEL_HEIGHT (f)
4483 + f->display.x->top_pos);
6dba1858 4484
c118dd06 4485#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
4486 WINDOWINFO_TYPE parentinfo;
4487
c118dd06 4488 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
dc6f92b8 4489
f676886a
JB
4490 if (f->display.x->left_pos < 0)
4491 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4492 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
dc6f92b8 4493
f676886a
JB
4494 if (f->display.x->top_pos < 0)
4495 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4496 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
c118dd06 4497#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4498}
4499
f676886a
JB
4500x_set_offset (f, xoff, yoff)
4501 struct frame *f;
dc6f92b8
JB
4502 register int xoff, yoff;
4503{
f676886a
JB
4504 f->display.x->top_pos = yoff;
4505 f->display.x->left_pos = xoff;
4506 x_calc_absolute_position (f);
dc6f92b8
JB
4507
4508 BLOCK_INPUT;
3afe33e7
RS
4509#ifdef USE_X_TOOLKIT
4510 XMoveWindow (XDISPLAY XtWindow (f->display.x->widget),
4511 f->display.x->left_pos, f->display.x->top_pos);
4512#else /* not USE_X_TOOLKIT */
c118dd06 4513 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
f676886a 4514 f->display.x->left_pos, f->display.x->top_pos);
3afe33e7 4515#endif /* not USE_X_TOOLKIT */
dc6f92b8 4516#ifdef HAVE_X11
6dba1858 4517 x_wm_set_size_hint (f, 0, xoff, yoff);
c118dd06 4518#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4519 UNBLOCK_INPUT;
4520}
4521
f676886a 4522/* Call this to change the size of frame F's x-window. */
dc6f92b8 4523
f676886a
JB
4524x_set_window_size (f, cols, rows)
4525 struct frame *f;
b1c884c3 4526 int cols, rows;
dc6f92b8
JB
4527{
4528 int pixelwidth, pixelheight;
4529 int mask;
dc6f92b8 4530
80fd1fe2
FP
4531#ifdef USE_X_TOOLKIT
4532 BLOCK_INPUT;
4533 EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
4534 UNBLOCK_INPUT;
4535
4536#else /* not USE_X_TOOLKIT */
4537
dc6f92b8
JB
4538 BLOCK_INPUT;
4539
b1c884c3 4540 check_frame_size (f, &rows, &cols);
6dba1858
RS
4541 f->display.x->vertical_scroll_bar_extra
4542 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4543 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
4544 : 0);
f451eb13
JB
4545 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4546 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8
JB
4547
4548#ifdef HAVE_X11
6dba1858 4549 x_wm_set_size_hint (f, 0, 0, 0);
c118dd06
JB
4550#endif /* ! defined (HAVE_X11) */
4551 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
b1c884c3
JB
4552
4553 /* Now, strictly speaking, we can't be sure that this is accurate,
4554 but the window manager will get around to dealing with the size
4555 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
4556 ConfigureNotify event gets here.
4557
4558 We could just not bother storing any of this information here,
4559 and let the ConfigureNotify event set everything up, but that
4560 might be kind of confusing to the lisp code, since size changes
4561 wouldn't be reported in the frame parameters until some random
4562 point in the future when the ConfigureNotify event arrives. */
8922af5f 4563 change_frame_size (f, rows, cols, 0, 0);
b1c884c3
JB
4564 PIXEL_WIDTH (f) = pixelwidth;
4565 PIXEL_HEIGHT (f) = pixelheight;
4566
dbc4e1c1
JB
4567 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4568 receive in the ConfigureNotify event; if we get what we asked
4569 for, then the event won't cause the screen to become garbaged, so
4570 we have to make sure to do it here. */
4571 SET_FRAME_GARBAGED (f);
4572
dc6f92b8
JB
4573 XFlushQueue ();
4574 UNBLOCK_INPUT;
80fd1fe2 4575#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
4576}
4577
4578#ifndef HAVE_X11
f676886a
JB
4579x_set_resize_hint (f)
4580 struct frame *f;
dc6f92b8 4581{
12ba150f
JB
4582 XSetResizeHint (FRAME_X_WINDOW (f),
4583 2 * f->display.x->internal_border_width,
f676886a 4584 2 * f->display.x->internal_border_width,
12ba150f
JB
4585 FONT_WIDTH (f->display.x->font),
4586 FONT_HEIGHT (f->display.x->font));
dc6f92b8 4587}
c118dd06 4588#endif /* HAVE_X11 */
dc6f92b8 4589\f
f451eb13 4590/* Mouse warping, focus shifting, raising and lowering. */
dc6f92b8 4591
f676886a
JB
4592x_set_mouse_position (f, x, y)
4593 struct frame *f;
dc6f92b8
JB
4594 int x, y;
4595{
4596 int pix_x, pix_y;
4597
4466efa5 4598#if 0 /* Let the user ask for this if he wants it. */
f676886a 4599 x_raise_frame (f);
4466efa5 4600#endif
dc6f92b8 4601
12ba150f
JB
4602 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4603 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
f451eb13
JB
4604
4605 if (pix_x < 0) pix_x = 0;
4606 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4607
4608 if (pix_y < 0) pix_y = 0;
4609 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
4610
4611 BLOCK_INPUT;
dc6f92b8 4612
c118dd06 4613 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
dc6f92b8
JB
4614 UNBLOCK_INPUT;
4615}
4616
4617#ifdef HAVE_X11
f676886a
JB
4618x_focus_on_frame (f)
4619 struct frame *f;
dc6f92b8 4620{
1fb20991 4621#if 0 /* This proves to be unpleasant. */
f676886a 4622 x_raise_frame (f);
1fb20991 4623#endif
6d4238f3
JB
4624#if 0
4625 /* I don't think that the ICCCM allows programs to do things like this
4626 without the interaction of the window manager. Whatever you end up
f676886a 4627 doing with this code, do it to x_unfocus_frame too. */
c118dd06 4628 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
dc6f92b8 4629 RevertToPointerRoot, CurrentTime);
c118dd06 4630#endif /* ! 0 */
dc6f92b8
JB
4631}
4632
f676886a
JB
4633x_unfocus_frame (f)
4634 struct frame *f;
dc6f92b8 4635{
6d4238f3 4636#if 0
f676886a
JB
4637 /* Look at the remarks in x_focus_on_frame. */
4638 if (x_focus_frame == f)
dc6f92b8
JB
4639 XSetInputFocus (x_current_display, PointerRoot,
4640 RevertToPointerRoot, CurrentTime);
c118dd06 4641#endif /* ! 0 */
dc6f92b8
JB
4642}
4643
c118dd06 4644#endif /* ! defined (HAVE_X11) */
dc6f92b8 4645
f676886a 4646/* Raise frame F. */
dc6f92b8 4647
f676886a
JB
4648x_raise_frame (f)
4649 struct frame *f;
dc6f92b8 4650{
3a88c238 4651 if (f->async_visible)
dc6f92b8
JB
4652 {
4653 BLOCK_INPUT;
3afe33e7
RS
4654#ifdef USE_X_TOOLKIT
4655 XRaiseWindow (XDISPLAY XtWindow (f->display.x->widget));
4656#else /* not USE_X_TOOLKIT */
c118dd06 4657 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 4658#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
4659 XFlushQueue ();
4660 UNBLOCK_INPUT;
4661 }
4662}
4663
f676886a 4664/* Lower frame F. */
dc6f92b8 4665
f676886a
JB
4666x_lower_frame (f)
4667 struct frame *f;
dc6f92b8 4668{
3a88c238 4669 if (f->async_visible)
dc6f92b8
JB
4670 {
4671 BLOCK_INPUT;
3afe33e7
RS
4672#ifdef USE_X_TOOLKIT
4673 XLowerWindow (XDISPLAY XtWindow (f->display.x->widget));
4674#else /* not USE_X_TOOLKIT */
c118dd06 4675 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 4676#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
4677 XFlushQueue ();
4678 UNBLOCK_INPUT;
4679 }
4680}
4681
dbc4e1c1
JB
4682static void
4683XTframe_raise_lower (f, raise)
4684 FRAME_PTR f;
4685 int raise;
4686{
4687 if (raise)
4688 x_raise_frame (f);
4689 else
4690 x_lower_frame (f);
4691}
4692
4693
dc6f92b8
JB
4694/* Change from withdrawn state to mapped state. */
4695
f676886a
JB
4696x_make_frame_visible (f)
4697 struct frame *f;
dc6f92b8
JB
4698{
4699 int mask;
4700
dc6f92b8 4701 BLOCK_INPUT;
dc6f92b8 4702
f676886a 4703 if (! FRAME_VISIBLE_P (f))
90e65f07
JB
4704 {
4705#ifdef HAVE_X11
4706 if (! EQ (Vx_no_window_manager, Qt))
f676886a 4707 x_wm_set_window_state (f, NormalState);
3afe33e7
RS
4708#ifdef USE_X_TOOLKIT
4709 XtPopup (f->display.x->widget, XtGrabNone);
4710#else /* not USE_X_TOOLKIT */
c118dd06 4711 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3afe33e7 4712#endif /* not USE_X_TOOLKIT */
ab648270 4713 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
c118dd06
JB
4714 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4715#else /* ! defined (HAVE_X11) */
4716 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
f676886a
JB
4717 if (f->display.x->icon_desc != 0)
4718 XUnmapWindow (f->display.x->icon_desc);
dc6f92b8 4719
90e65f07 4720 /* Handled by the MapNotify event for X11 */
3a88c238
JB
4721 f->async_visible = 1;
4722 f->async_iconified = 0;
dc6f92b8 4723
f676886a 4724 /* NOTE: this may cause problems for the first frame. */
90e65f07 4725 XTcursor_to (0, 0);
c118dd06 4726#endif /* ! defined (HAVE_X11) */
90e65f07 4727 }
dc6f92b8 4728
dc6f92b8 4729 XFlushQueue ();
90e65f07 4730
dc6f92b8
JB
4731 UNBLOCK_INPUT;
4732}
4733
4734/* Change from mapped state to withdrawn state. */
4735
f676886a
JB
4736x_make_frame_invisible (f)
4737 struct frame *f;
dc6f92b8
JB
4738{
4739 int mask;
4740
9319ae23
RS
4741 /* Don't keep the highlight on an invisible frame. */
4742 if (x_highlight_frame == f)
4743 x_highlight_frame = 0;
4744
4745 if (! f->async_visible && ! f->async_iconified)
dc6f92b8
JB
4746 return;
4747
4748 BLOCK_INPUT;
c118dd06
JB
4749
4750#ifdef HAVE_X11R4
4751
4752 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4753 DefaultScreen (x_current_display)))
4754 {
4755 UNBLOCK_INPUT_RESIGNAL;
eb8c3be9 4756 error ("can't notify window manager of window withdrawal");
c118dd06
JB
4757 }
4758
4759#else /* ! defined (HAVE_X11R4) */
dc6f92b8 4760#ifdef HAVE_X11
16bd92ea 4761
c118dd06 4762 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
4763 if (! EQ (Vx_no_window_manager, Qt))
4764 {
16bd92ea 4765 XEvent unmap;
dc6f92b8 4766
16bd92ea 4767 unmap.xunmap.type = UnmapNotify;
c118dd06 4768 unmap.xunmap.window = FRAME_X_WINDOW (f);
16bd92ea
JB
4769 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4770 unmap.xunmap.from_configure = False;
4771 if (! XSendEvent (x_current_display,
4772 DefaultRootWindow (x_current_display),
4773 False,
4774 SubstructureRedirectMask|SubstructureNotifyMask,
4775 &unmap))
4776 {
4777 UNBLOCK_INPUT_RESIGNAL;
4778 error ("can't notify window manager of withdrawal");
4779 }
dc6f92b8
JB
4780 }
4781
16bd92ea 4782 /* Unmap the window ourselves. Cheeky! */
c118dd06
JB
4783 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4784
4785#else /* ! defined (HAVE_X11) */
dc6f92b8 4786
c118dd06 4787 XUnmapWindow (FRAME_X_WINDOW (f));
3a88c238 4788 f->async_visible = 0; /* Handled by the UnMap event for X11 */
f676886a 4789 if (f->display.x->icon_desc != 0)
c118dd06
JB
4790 XUnmapWindow (f->display.x->icon_desc);
4791
4792#endif /* ! defined (HAVE_X11) */
4793#endif /* ! defined (HAVE_X11R4) */
dc6f92b8
JB
4794
4795 XFlushQueue ();
4796 UNBLOCK_INPUT;
4797}
4798
dc6f92b8
JB
4799/* Change window state from mapped to iconified. */
4800
f676886a
JB
4801x_iconify_frame (f)
4802 struct frame *f;
dc6f92b8
JB
4803{
4804 int mask;
3afe33e7 4805 int result;
dc6f92b8 4806
9319ae23
RS
4807 /* Don't keep the highlight on an invisible frame. */
4808 if (x_highlight_frame == f)
4809 x_highlight_frame = 0;
4810
3a88c238 4811 if (f->async_iconified)
dc6f92b8
JB
4812 return;
4813
3afe33e7
RS
4814#ifdef USE_X_TOOLKIT
4815 BLOCK_INPUT;
4816 result = XIconifyWindow (x_current_display,
4817 XtWindow(f->display.x->widget),
4818 DefaultScreen (x_current_display));
4819 UNBLOCK_INPUT;
4820
4821 if (!result)
4822 error ("Can't notify window manager of iconification.");
4823
4824 f->async_iconified = 1;
8c002a25
KH
4825
4826 BLOCK_INPUT;
4827 XFlushQueue ();
4828 UNBLOCK_INPUT;
3afe33e7
RS
4829#else /* not USE_X_TOOLKIT */
4830
dc6f92b8
JB
4831 BLOCK_INPUT;
4832
4833#ifdef HAVE_X11
16bd92ea
JB
4834 /* Since we don't know which revision of X we're running, we'll use both
4835 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4836
4837 /* X11R4: send a ClientMessage to the window manager using the
4838 WM_CHANGE_STATE type. */
4839 {
4840 XEvent message;
4841
c118dd06 4842 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea
JB
4843 message.xclient.type = ClientMessage;
4844 message.xclient.message_type = Xatom_wm_change_state;
4845 message.xclient.format = 32;
4846 message.xclient.data.l[0] = IconicState;
4847
4848 if (! XSendEvent (x_current_display,
4849 DefaultRootWindow (x_current_display),
4850 False,
4851 SubstructureRedirectMask | SubstructureNotifyMask,
4852 &message))
dc6f92b8
JB
4853 {
4854 UNBLOCK_INPUT_RESIGNAL;
4855 error ("Can't notify window manager of iconification.");
4856 }
16bd92ea 4857 }
dc6f92b8 4858
16bd92ea
JB
4859 /* X11R3: set the initial_state field of the window manager hints to
4860 IconicState. */
4861 x_wm_set_window_state (f, IconicState);
dc6f92b8 4862
a9c00105
RS
4863 if (!FRAME_VISIBLE_P (f))
4864 {
4865 /* If the frame was withdrawn, before, we must map it. */
4866 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4867 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4868 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4869 }
4870
3a88c238 4871 f->async_iconified = 1;
c118dd06
JB
4872#else /* ! defined (HAVE_X11) */
4873 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
dc6f92b8 4874
3a88c238 4875 f->async_visible = 0; /* Handled in the UnMap event for X11. */
f676886a 4876 if (f->display.x->icon_desc != 0)
dc6f92b8 4877 {
f676886a
JB
4878 XMapWindow (XDISPLAY f->display.x->icon_desc);
4879 refreshicon (f);
dc6f92b8 4880 }
c118dd06 4881#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4882
4883 XFlushQueue ();
4884 UNBLOCK_INPUT;
8c002a25 4885#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
4886}
4887
c0ff3fab 4888/* Destroy the X window of frame F. */
dc6f92b8 4889
c0ff3fab 4890x_destroy_window (f)
f676886a 4891 struct frame *f;
dc6f92b8 4892{
dc6f92b8 4893 BLOCK_INPUT;
c0ff3fab
JB
4894
4895 if (f->display.x->icon_desc != 0)
4896 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4897 XDestroyWindow (XDISPLAY f->display.x->window_desc);
3afe33e7
RS
4898#ifdef USE_X_TOOLKIT
4899 XtDestroyWidget (f->display.x->widget);
4900#endif /* USE_X_TOOLKIT */
4901
07e34cb0 4902 free_frame_faces (f);
dc6f92b8 4903 XFlushQueue ();
dc6f92b8 4904
9ac0d9e0 4905 xfree (f->display.x);
c0ff3fab 4906 f->display.x = 0;
f676886a
JB
4907 if (f == x_focus_frame)
4908 x_focus_frame = 0;
4909 if (f == x_highlight_frame)
4910 x_highlight_frame = 0;
c0ff3fab
JB
4911
4912 UNBLOCK_INPUT;
dc6f92b8
JB
4913}
4914\f
f451eb13
JB
4915/* Manage event queues for X10. */
4916
dc6f92b8
JB
4917#ifndef HAVE_X11
4918
4919/* Manage event queues.
4920
4921 This code is only used by the X10 support.
4922
4923 We cannot leave events in the X queue and get them when we are ready
4924 because X does not provide a subroutine to get only a certain kind
4925 of event but not block if there are no queued events of that kind.
4926
4927 Therefore, we must examine events as they come in and copy events
4928 of certain kinds into our private queues.
4929
4930 All ExposeRegion events are put in x_expose_queue.
69388238 4931 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
dc6f92b8
JB
4932
4933
4934/* Write the event *P_XREP into the event queue *QUEUE.
4935 If the queue is full, do nothing, but return nonzero. */
4936
4937int
4938enqueue_event (p_xrep, queue)
4939 register XEvent *p_xrep;
4940 register struct event_queue *queue;
4941{
4942 int newindex = queue->windex + 1;
4943 if (newindex == EVENT_BUFFER_SIZE)
4944 newindex = 0;
4945 if (newindex == queue->rindex)
4946 return -1;
4947 queue->xrep[queue->windex] = *p_xrep;
4948 queue->windex = newindex;
4949 return 0;
4950}
4951
4952/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4953 If *QUEUE is empty, do nothing and return 0. */
4954
4955int
4956dequeue_event (p_xrep, queue)
4957 register XEvent *p_xrep;
4958 register struct event_queue *queue;
4959{
4960 if (queue->windex == queue->rindex)
4961 return 0;
4962 *p_xrep = queue->xrep[queue->rindex++];
4963 if (queue->rindex == EVENT_BUFFER_SIZE)
4964 queue->rindex = 0;
4965 return 1;
4966}
4967
4968/* Return the number of events buffered in *QUEUE. */
4969
4970int
4971queue_event_count (queue)
4972 register struct event_queue *queue;
4973{
4974 int tem = queue->windex - queue->rindex;
4975 if (tem >= 0)
4976 return tem;
4977 return EVENT_BUFFER_SIZE + tem;
4978}
4979
4980/* Return nonzero if mouse input is pending. */
4981
4982int
4983mouse_event_pending_p ()
4984{
4985 return queue_event_count (&x_mouse_queue);
4986}
c118dd06 4987#endif /* HAVE_X11 */
dc6f92b8 4988\f
f451eb13
JB
4989/* Setting window manager hints. */
4990
dc6f92b8
JB
4991#ifdef HAVE_X11
4992
6dba1858
RS
4993/* SPEC_X and SPEC_Y are the specified positions.
4994 We look only at their sign, to decide the gravity. */
4995
4996x_wm_set_size_hint (f, prompting, spec_x, spec_y)
f676886a 4997 struct frame *f;
dc6f92b8 4998 long prompting;
6dba1858 4999 int spec_x, spec_y;
dc6f92b8
JB
5000{
5001 XSizeHints size_hints;
3afe33e7
RS
5002
5003#ifdef USE_X_TOOLKIT
5004 Window window = XtWindow(f->display.x->widget);
5005#else /* not USE_X_TOOLKIT */
c118dd06 5006 Window window = FRAME_X_WINDOW (f);
3afe33e7 5007#endif /* not USE_X_TOOLKIT */
dc6f92b8 5008
f7f79491 5009 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 5010
f676886a
JB
5011 flexlines = f->height;
5012
5013 size_hints.x = f->display.x->left_pos;
5014 size_hints.y = f->display.x->top_pos;
5015 size_hints.height = PIXEL_HEIGHT (f);
5016 size_hints.width = PIXEL_WIDTH (f);
5017 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
5018 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
f7f79491 5019#if 0
12ba150f
JB
5020 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
5021 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
f7f79491 5022#endif
b1c884c3 5023 {
b0342f17
JB
5024 int base_width, base_height;
5025
f451eb13
JB
5026 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5027 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17
JB
5028
5029 {
5030 int min_rows = 0, min_cols = 0;
5031 check_frame_size (f, &min_rows, &min_cols);
5032
5033 /* The window manager uses the base width hints to calculate the
5034 current number of rows and columns in the frame while
5035 resizing; min_width and min_height aren't useful for this
5036 purpose, since they might not give the dimensions for a
5037 zero-row, zero-column frame.
5038
5039 We use the base_width and base_height members if we have
5040 them; otherwise, we set the min_width and min_height members
5041 to the size for a zero x zero frame. */
5042
5043#ifdef HAVE_X11R4
5044 size_hints.flags |= PBaseSize;
5045 size_hints.base_width = base_width;
5046 size_hints.base_height = base_height;
5047 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5048 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5049#else
5050 size_hints.min_width = base_width;
5051 size_hints.min_height = base_height;
5052#endif
5053 }
b1c884c3 5054
b1c884c3 5055 }
dc6f92b8
JB
5056
5057 if (prompting)
5058 size_hints.flags |= prompting;
5059 else
5060 {
5061 XSizeHints hints; /* Sometimes I hate X Windows... */
5062
82ee0df4
RS
5063 if (XGetNormalHints (x_current_display, window, &hints) == 0)
5064 hints.flags = 0;
dc6f92b8
JB
5065 if (hints.flags & PSize)
5066 size_hints.flags |= PSize;
5067 if (hints.flags & PPosition)
5068 size_hints.flags |= PPosition;
5069 if (hints.flags & USPosition)
5070 size_hints.flags |= USPosition;
5071 if (hints.flags & USSize)
5072 size_hints.flags |= USSize;
5073 }
2554751d 5074#if defined (PWinGravity)
6dba1858
RS
5075 switch (((spec_x < 0) << 1) + (spec_y < 0))
5076 {
5077 case 0:
5078 size_hints.win_gravity = NorthWestGravity;
5079 break;
5080 case 1:
3afe33e7 5081 size_hints.win_gravity = NorthEastGravity;
6dba1858
RS
5082 break;
5083 case 2:
3afe33e7 5084 size_hints.win_gravity = SouthWestGravity;
6dba1858
RS
5085 break;
5086 case 3:
5087 size_hints.win_gravity = SouthEastGravity;
5088 break;
5089 }
5090 size_hints.flags |= PWinGravity;
2554751d 5091#endif /* PWinGravity */
6dba1858 5092
b0342f17
JB
5093#ifdef HAVE_X11R4
5094 XSetWMNormalHints (x_current_display, window, &size_hints);
5095#else
dc6f92b8 5096 XSetNormalHints (x_current_display, window, &size_hints);
b0342f17 5097#endif
dc6f92b8
JB
5098}
5099
5100/* Used for IconicState or NormalState */
f676886a
JB
5101x_wm_set_window_state (f, state)
5102 struct frame *f;
dc6f92b8
JB
5103 int state;
5104{
3afe33e7
RS
5105#ifdef USE_X_TOOLKIT
5106 Window window = XtWindow(f->display.x->widget);
5107#else /* not USE_X_TOOLKIT */
c118dd06 5108 Window window = FRAME_X_WINDOW (f);
3afe33e7 5109#endif /* not USE_X_TOOLKIT */
dc6f92b8 5110
16bd92ea
JB
5111 f->display.x->wm_hints.flags |= StateHint;
5112 f->display.x->wm_hints.initial_state = state;
b1c884c3 5113
16bd92ea 5114 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
5115}
5116
f676886a
JB
5117x_wm_set_icon_pixmap (f, icon_pixmap)
5118 struct frame *f;
dc6f92b8
JB
5119 Pixmap icon_pixmap;
5120{
c118dd06 5121 Window window = FRAME_X_WINDOW (f);
dc6f92b8 5122
dbc4e1c1
JB
5123 if (icon_pixmap)
5124 {
5125 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
5126 f->display.x->wm_hints.flags |= IconPixmapHint;
5127 }
5128 else
5129 f->display.x->wm_hints.flags &= ~IconPixmapHint;
b1c884c3 5130
16bd92ea 5131 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
5132}
5133
f676886a
JB
5134x_wm_set_icon_position (f, icon_x, icon_y)
5135 struct frame *f;
dc6f92b8
JB
5136 int icon_x, icon_y;
5137{
c118dd06 5138 Window window = FRAME_X_WINDOW (f);
dc6f92b8 5139
16bd92ea
JB
5140 f->display.x->wm_hints.flags |= IconPositionHint;
5141 f->display.x->wm_hints.icon_x = icon_x;
5142 f->display.x->wm_hints.icon_y = icon_y;
b1c884c3 5143
16bd92ea 5144 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
5145}
5146
5147\f
f451eb13
JB
5148/* Initialization. */
5149
3afe33e7
RS
5150#ifdef USE_X_TOOLKIT
5151static XrmOptionDescRec emacs_options[] = {
5152 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5153 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5154
5155 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5156 XrmoptionSepArg, NULL},
5157 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5158
5159 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5160 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5161 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5162 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5163 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5164 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5165 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5166};
5167#endif /* USE_X_TOOLKIT */
5168
dc6f92b8
JB
5169void
5170x_term_init (display_name)
5171 char *display_name;
5172{
f676886a 5173 Lisp_Object frame;
dc6f92b8 5174 char *defaultvalue;
3afe33e7
RS
5175 int argc = 0;
5176 char** argv = 0;
041b69ac 5177#ifndef F_SETOWN_BUG
dc6f92b8
JB
5178#ifdef F_SETOWN
5179 extern int old_fcntl_owner;
c118dd06 5180#endif /* ! defined (F_SETOWN) */
041b69ac 5181#endif /* F_SETOWN_BUG */
6d4238f3 5182
f676886a 5183 x_focus_frame = x_highlight_frame = 0;
dc6f92b8 5184
3afe33e7 5185#ifdef USE_X_TOOLKIT
5c94b90b 5186 argv = (char **) XtMalloc (3 * sizeof (char *));
3afe33e7
RS
5187 argv [0] = "";
5188 argv [1] = "-display";
5189 argv [2] = display_name;
5190 argc = 3;
5191 Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
5192 emacs_options, XtNumber(emacs_options),
5193 &argc, argv,
5194 NULL, NULL, 0);
5195 XtFree (argv);
5196 x_current_display = XtDisplay (Xt_app_shell);
5197
5198#else /* not USE_X_TOOLKIT */
dc6f92b8 5199 x_current_display = XOpenDisplay (display_name);
3afe33e7 5200#endif /* not USE_X_TOOLKIT */
dc6f92b8 5201 if (x_current_display == 0)
041b69ac
JB
5202 fatal ("X server %s not responding.\n\
5203Check the DISPLAY environment variable or use \"-d\"\n",
dc6f92b8
JB
5204 display_name);
5205
5206#ifdef HAVE_X11
5207 {
dc6f92b8
JB
5208#if 0
5209 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 5210#endif /* ! 0 */
8c86eccd 5211 hostname = get_system_name ();
59653951 5212 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
60fb3ee1
JB
5213 + strlen (hostname)
5214 + 2);
59653951 5215 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
dc6f92b8 5216 }
28430d3c
JB
5217
5218 /* Figure out which modifier bits mean what. */
5219 x_find_modifier_meanings ();
f451eb13 5220
ab648270 5221 /* Get the scroll bar cursor. */
d56a553a
RS
5222 x_vertical_scroll_bar_cursor
5223 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
f451eb13 5224
d56a553a 5225#if 0
28430d3c
JB
5226 /* Watch for PropertyNotify events on the root window; we use them
5227 to figure out when to invalidate our cache of the cut buffers. */
5228 x_watch_cut_buffer_cache ();
d56a553a 5229#endif
28430d3c 5230
a4fc7360 5231 if (ConnectionNumber (x_current_display) != 0)
61c3ce62
RS
5232 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display));
5233 change_input_fd (ConnectionNumber (x_current_display));
6d4238f3 5234
c118dd06 5235#endif /* ! defined (HAVE_X11) */
dc6f92b8 5236
041b69ac 5237#ifndef F_SETOWN_BUG
dc6f92b8 5238#ifdef F_SETOWN
61c3ce62 5239 old_fcntl_owner = fcntl (ConnectionNumber (x_current_display), F_GETOWN, 0);
dc6f92b8 5240#ifdef F_SETOWN_SOCK_NEG
61c3ce62
RS
5241 /* stdin is a socket here */
5242 fcntl (ConnectionNumber (x_current_display), F_SETOWN, -getpid ());
c118dd06 5243#else /* ! defined (F_SETOWN_SOCK_NEG) */
61c3ce62 5244 fcntl (ConnectionNumber (x_current_display), F_SETOWN, getpid ());
c118dd06
JB
5245#endif /* ! defined (F_SETOWN_SOCK_NEG) */
5246#endif /* ! defined (F_SETOWN) */
041b69ac 5247#endif /* F_SETOWN_BUG */
dc6f92b8
JB
5248
5249#ifdef SIGIO
5250 init_sigio ();
c118dd06 5251#endif /* ! defined (SIGIO) */
dc6f92b8 5252
dc6f92b8
JB
5253 expose_all_windows = 0;
5254
f676886a 5255 clear_frame_hook = XTclear_frame;
dc6f92b8
JB
5256 clear_end_of_line_hook = XTclear_end_of_line;
5257 ins_del_lines_hook = XTins_del_lines;
5258 change_line_highlight_hook = XTchange_line_highlight;
5259 insert_glyphs_hook = XTinsert_glyphs;
5260 write_glyphs_hook = XTwrite_glyphs;
5261 delete_glyphs_hook = XTdelete_glyphs;
5262 ring_bell_hook = XTring_bell;
5263 reset_terminal_modes_hook = XTreset_terminal_modes;
5264 set_terminal_modes_hook = XTset_terminal_modes;
5265 update_begin_hook = XTupdate_begin;
5266 update_end_hook = XTupdate_end;
5267 set_terminal_window_hook = XTset_terminal_window;
5268 read_socket_hook = XTread_socket;
5269 cursor_to_hook = XTcursor_to;
5270 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 5271 mouse_position_hook = XTmouse_position;
f451eb13 5272 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 5273 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
5274 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
5275 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
5276 redeem_scroll_bar_hook = XTredeem_scroll_bar;
5277 judge_scroll_bars_hook = XTjudge_scroll_bars;
dc6f92b8 5278
f676886a 5279 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
5280 char_ins_del_ok = 0; /* just as fast to write the line */
5281 line_ins_del_ok = 1; /* we'll just blt 'em */
5282 fast_clear_end_of_line = 1; /* X does this well */
f676886a 5283 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
5284 off the bottom */
5285 baud_rate = 19200;
5286
b30b24cb
RS
5287 /* Try to use interrupt input; if we can't, then start polling. */
5288 Fset_input_mode (Qt, Qnil, Qt, Qnil);
5289
c118dd06
JB
5290 /* Note that there is no real way portable across R3/R4 to get the
5291 original error handler. */
5292 XHandleError (x_error_quitter);
8922af5f 5293 XHandleIOError (x_io_error_quitter);
dc6f92b8
JB
5294
5295 /* Disable Window Change signals; they are handled by X events. */
5296#ifdef SIGWINCH
5297 signal (SIGWINCH, SIG_DFL);
c118dd06 5298#endif /* ! defined (SIGWINCH) */
dc6f92b8 5299
c118dd06 5300 signal (SIGPIPE, x_connection_closed);
dc6f92b8 5301}
55123275
JB
5302
5303void
5304syms_of_xterm ()
5305{
ab648270 5306 staticpro (&last_mouse_scroll_bar);
e53cb100 5307 last_mouse_scroll_bar = Qnil;
55123275 5308}
c118dd06
JB
5309#endif /* ! defined (HAVE_X11) */
5310#endif /* ! defined (HAVE_X_WINDOWS) */