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