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