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