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