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