(delete-frame): Don't use delete-frame as event name.
[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;
68be917d 973 row = c >> (BITS_PER_INT - 8);
0cdd0c9f
RS
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;
68be917d 1018 row = c >> (BITS_PER_INT - 8);
0cdd0c9f
RS
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;
6c183ba5
RS
3268#ifdef HAVE_X_I18N
3269 Status status_return;
3270#endif
dc6f92b8 3271
9ac0d9e0 3272 if (interrupt_input_blocked)
dc6f92b8 3273 {
9ac0d9e0 3274 interrupt_input_pending = 1;
dc6f92b8
JB
3275 return -1;
3276 }
3277
9ac0d9e0 3278 interrupt_input_pending = 0;
dc6f92b8 3279 BLOCK_INPUT;
c0a04927
RS
3280
3281 /* So people can tell when we have read the available input. */
3282 input_signal_count++;
3283
dc6f92b8
JB
3284 if (numchars <= 0)
3285 abort (); /* Don't think this happens. */
3286
7a13e894
RS
3287 /* Find the display we are supposed to read input for.
3288 It's the one communicating on descriptor SD. */
3289 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
3290 {
3291#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 3292#ifdef FIOSNBIO
7a13e894
RS
3293 /* If available, Xlib uses FIOSNBIO to make the socket
3294 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3295 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3296 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3297 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 3298#endif /* ! defined (FIOSNBIO) */
7a13e894 3299#endif
dc6f92b8 3300
7a13e894
RS
3301#if 0 /* This code can't be made to work, with multiple displays,
3302 and appears not to be used on any system any more.
3303 Also keyboard.c doesn't turn O_NDELAY on and off
3304 for X connections. */
dc6f92b8
JB
3305#ifndef SIGIO
3306#ifndef HAVE_SELECT
7a13e894
RS
3307 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
3308 {
3309 extern int read_alarm_should_throw;
3310 read_alarm_should_throw = 1;
3311 XPeekEvent (dpyinfo->display, &event);
3312 read_alarm_should_throw = 0;
3313 }
c118dd06
JB
3314#endif /* HAVE_SELECT */
3315#endif /* SIGIO */
7a13e894 3316#endif
dc6f92b8 3317
7a13e894
RS
3318 /* For debugging, this gives a way to fake an I/O error. */
3319 if (dpyinfo == XTread_socket_fake_io_error)
3320 {
3321 XTread_socket_fake_io_error = 0;
3322 x_io_error_quitter (dpyinfo->display);
3323 }
dc6f92b8 3324
7a13e894 3325 while (XPending (dpyinfo->display) != 0)
dc6f92b8 3326 {
7a13e894
RS
3327 XNextEvent (dpyinfo->display, &event);
3328 event_found = 1;
3329
3330 switch (event.type)
3331 {
3332 case ClientMessage:
c047688c 3333 {
7a13e894
RS
3334 if (event.xclient.message_type
3335 == dpyinfo->Xatom_wm_protocols
3336 && event.xclient.format == 32)
c047688c 3337 {
7a13e894
RS
3338 if (event.xclient.data.l[0]
3339 == dpyinfo->Xatom_wm_take_focus)
c047688c 3340 {
19126e11 3341 f = x_window_to_frame (dpyinfo, event.xclient.window);
7a13e894
RS
3342 /* Since we set WM_TAKE_FOCUS, we must call
3343 XSetInputFocus explicitly. But not if f is null,
3344 since that might be an event for a deleted frame. */
6c183ba5
RS
3345#ifdef HAVE_X_I18N
3346 /* Not quite sure this is needed -pd */
3347 if (f)
3348 XSetICFocus (FRAME_XIC (f));
3349#endif
7a13e894
RS
3350 if (f)
3351 XSetInputFocus (event.xclient.display,
3352 event.xclient.window,
3353 RevertToPointerRoot,
3354 event.xclient.data.l[1]);
3355 /* Not certain about handling scroll bars here */
c047688c 3356 }
7a13e894
RS
3357 else if (event.xclient.data.l[0]
3358 == dpyinfo->Xatom_wm_save_yourself)
3359 {
3360 /* Save state modify the WM_COMMAND property to
3361 something which can reinstate us. This notifies
3362 the session manager, who's looking for such a
3363 PropertyNotify. Can restart processing when
3364 a keyboard or mouse event arrives. */
3365 if (numchars > 0)
3366 {
19126e11
KH
3367 f = x_top_window_to_frame (dpyinfo,
3368 event.xclient.window);
7a13e894
RS
3369
3370 /* This is just so we only give real data once
3371 for a single Emacs process. */
3372 if (f == selected_frame)
3373 XSetCommand (FRAME_X_DISPLAY (f),
3374 event.xclient.window,
3375 initial_argv, initial_argc);
3376 else
3377 XSetCommand (FRAME_X_DISPLAY (f),
3378 event.xclient.window,
3379 0, 0);
3380 }
3381 }
3382 else if (event.xclient.data.l[0]
3383 == dpyinfo->Xatom_wm_delete_window)
1fb20991 3384 {
19126e11
KH
3385 struct frame *f
3386 = x_any_window_to_frame (dpyinfo,
3387 event.xclient.window);
1fb20991 3388
7a13e894
RS
3389 if (f)
3390 {
3391 if (numchars == 0)
3392 abort ();
1fb20991 3393
7a13e894
RS
3394 bufp->kind = delete_window_event;
3395 XSETFRAME (bufp->frame_or_window, f);
3396 bufp++;
3397
3398 count += 1;
3399 numchars -= 1;
3400 }
1fb20991 3401 }
c047688c 3402 }
7a13e894
RS
3403 else if (event.xclient.message_type
3404 == dpyinfo->Xatom_wm_configure_denied)
3405 {
3406 }
3407 else if (event.xclient.message_type
3408 == dpyinfo->Xatom_wm_window_moved)
3409 {
3410 int new_x, new_y;
19126e11
KH
3411 struct frame *f
3412 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 3413
7a13e894
RS
3414 new_x = event.xclient.data.s[0];
3415 new_y = event.xclient.data.s[1];
1fb20991 3416
7a13e894
RS
3417 if (f)
3418 {
7556890b
RS
3419 f->output_data.x->left_pos = new_x;
3420 f->output_data.x->top_pos = new_y;
7a13e894 3421 }
1fb20991 3422 }
5627c40e 3423#if defined (USE_X_TOOLKIT) && defined (HAVE_X11R5)
7a13e894
RS
3424 else if (event.xclient.message_type
3425 == dpyinfo->Xatom_editres)
3426 {
19126e11
KH
3427 struct frame *f
3428 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 3429 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 3430 &event, NULL);
7a13e894 3431 }
5627c40e 3432#endif /* USE_X_TOOLKIT and HAVE_X11R5 */
7a13e894
RS
3433 }
3434 break;
dc6f92b8 3435
7a13e894 3436 case SelectionNotify:
3afe33e7 3437#ifdef USE_X_TOOLKIT
19126e11 3438 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 3439 goto OTHER;
3afe33e7 3440#endif /* not USE_X_TOOLKIT */
7a13e894
RS
3441 x_handle_selection_notify (&event);
3442 break;
d56a553a 3443
7a13e894 3444 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 3445#ifdef USE_X_TOOLKIT
19126e11 3446 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 3447 goto OTHER;
3afe33e7 3448#endif /* USE_X_TOOLKIT */
7a13e894
RS
3449 {
3450 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 3451
7a13e894
RS
3452 if (numchars == 0)
3453 abort ();
d56a553a 3454
7a13e894
RS
3455 bufp->kind = selection_clear_event;
3456 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3457 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3458 SELECTION_EVENT_TIME (bufp) = eventp->time;
3459 bufp++;
d56a553a 3460
7a13e894
RS
3461 count += 1;
3462 numchars -= 1;
3463 }
3464 break;
dc6f92b8 3465
7a13e894 3466 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 3467#ifdef USE_X_TOOLKIT
19126e11 3468 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 3469 goto OTHER;
3afe33e7 3470#endif /* USE_X_TOOLKIT */
7a13e894 3471 if (x_queue_selection_requests)
19126e11 3472 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
3473 &event);
3474 else
3475 {
3476 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 3477
7a13e894
RS
3478 if (numchars == 0)
3479 abort ();
3480
3481 bufp->kind = selection_request_event;
3482 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3483 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
3484 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3485 SELECTION_EVENT_TARGET (bufp) = eventp->target;
3486 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
3487 SELECTION_EVENT_TIME (bufp) = eventp->time;
3488 bufp++;
3489
3490 count += 1;
3491 numchars -= 1;
3492 }
3493 break;
3494
3495 case PropertyNotify:
3afe33e7 3496#ifdef USE_X_TOOLKIT
19126e11 3497 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 3498 goto OTHER;
3afe33e7 3499#endif /* not USE_X_TOOLKIT */
7a13e894
RS
3500 x_handle_property_notify (&event);
3501 break;
dc6f92b8 3502
7a13e894 3503 case ReparentNotify:
19126e11 3504 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
3505 if (f)
3506 {
3507 int x, y;
7556890b 3508 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 3509 x_real_positions (f, &x, &y);
7556890b
RS
3510 f->output_data.x->left_pos = x;
3511 f->output_data.x->top_pos = y;
7a13e894
RS
3512 }
3513 break;
3bd330d4 3514
7a13e894 3515 case Expose:
19126e11 3516 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 3517 if (f)
dc6f92b8 3518 {
7a13e894
RS
3519 if (f->async_visible == 0)
3520 {
3521 f->async_visible = 1;
3522 f->async_iconified = 0;
3523 SET_FRAME_GARBAGED (f);
3524 }
3525 else
19126e11
KH
3526 dumprectangle (x_window_to_frame (dpyinfo,
3527 event.xexpose.window),
7a13e894
RS
3528 event.xexpose.x, event.xexpose.y,
3529 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
3530 }
3531 else
7a13e894
RS
3532 {
3533 struct scroll_bar *bar
3534 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 3535
7a13e894
RS
3536 if (bar)
3537 x_scroll_bar_expose (bar, &event);
3afe33e7 3538#ifdef USE_X_TOOLKIT
7a13e894
RS
3539 else
3540 goto OTHER;
3afe33e7 3541#endif /* USE_X_TOOLKIT */
7a13e894
RS
3542 }
3543 break;
dc6f92b8 3544
7a13e894
RS
3545 case GraphicsExpose: /* This occurs when an XCopyArea's
3546 source area was obscured or not
3547 available.*/
19126e11 3548 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
3549 if (f)
3550 {
3551 dumprectangle (f,
3552 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
3553 event.xgraphicsexpose.width,
3554 event.xgraphicsexpose.height);
3555 }
3afe33e7 3556#ifdef USE_X_TOOLKIT
7a13e894
RS
3557 else
3558 goto OTHER;
3afe33e7 3559#endif /* USE_X_TOOLKIT */
7a13e894 3560 break;
dc6f92b8 3561
7a13e894
RS
3562 case NoExpose: /* This occurs when an XCopyArea's
3563 source area was completely
3564 available */
3565 break;
dc6f92b8 3566
7a13e894 3567 case UnmapNotify:
91ea2a7a 3568 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
3569 if (f) /* F may no longer exist if
3570 the frame was deleted. */
3571 {
3572 /* While a frame is unmapped, display generation is
3573 disabled; you don't want to spend time updating a
3574 display that won't ever be seen. */
3575 f->async_visible = 0;
3576 /* We can't distinguish, from the event, whether the window
3577 has become iconified or invisible. So assume, if it
3578 was previously visible, than now it is iconified.
3579 We depend on x_make_frame_invisible to mark it iconified. */
3580 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
3581 f->async_iconified = 1;
bddd097c
KH
3582
3583 bufp->kind = iconify_event;
3584 XSETFRAME (bufp->frame_or_window, f);
3585 bufp++;
3586 count++;
3587 numchars--;
7a13e894 3588 }
3afe33e7 3589#ifdef USE_X_TOOLKIT
7a13e894 3590 goto OTHER;
3afe33e7 3591#endif /* USE_X_TOOLKIT */
7a13e894 3592 break;
dc6f92b8 3593
7a13e894
RS
3594 case MapNotify:
3595 /* We use x_top_window_to_frame because map events can come
3596 for subwindows and they don't mean that the frame is visible. */
19126e11 3597 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
3598 if (f)
3599 {
3600 f->async_visible = 1;
3601 f->async_iconified = 0;
dc6f92b8 3602
7a13e894
RS
3603 /* wait_reading_process_input will notice this and update
3604 the frame's display structures. */
3605 SET_FRAME_GARBAGED (f);
bddd097c 3606
d806e720
RS
3607 if (f->iconified)
3608 {
3609 bufp->kind = deiconify_event;
3610 XSETFRAME (bufp->frame_or_window, f);
3611 bufp++;
3612 count++;
3613 numchars--;
3614 }
78aa2ba5
KH
3615 else
3616 /* Force a redisplay sooner or later
3617 to update the frame titles
3618 in case this is the second frame. */
3619 record_asynch_buffer_change ();
7a13e894 3620 }
3afe33e7 3621#ifdef USE_X_TOOLKIT
7a13e894 3622 goto OTHER;
3afe33e7 3623#endif /* USE_X_TOOLKIT */
7a13e894 3624 break;
dc6f92b8 3625
7a13e894
RS
3626 /* Turn off processing if we become fully obscured. */
3627 case VisibilityNotify:
3628 break;
dc6f92b8 3629
7a13e894 3630 case KeyPress:
19126e11 3631 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 3632
7a13e894
RS
3633 if (f != 0)
3634 {
3635 KeySym keysym, orig_keysym;
3636 /* al%imercury@uunet.uu.net says that making this 81 instead of
3637 80 fixed a bug whereby meta chars made his Emacs hang. */
3638 unsigned char copy_buffer[81];
3639 int modifiers;
64bb1782 3640
7a13e894
RS
3641 event.xkey.state
3642 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
3643 extra_keyboard_modifiers);
3644 modifiers = event.xkey.state;
3a2712f9 3645
7a13e894 3646 /* This will have to go some day... */
752a043f 3647
7a13e894
RS
3648 /* make_lispy_event turns chars into control chars.
3649 Don't do it here because XLookupString is too eager. */
3650 event.xkey.state &= ~ControlMask;
5d46f928
RS
3651 event.xkey.state &= ~(dpyinfo->meta_mod_mask
3652 | dpyinfo->super_mod_mask
3653 | dpyinfo->hyper_mod_mask
3654 | dpyinfo->alt_mod_mask);
3655
6c183ba5
RS
3656#ifdef HAVE_X_I18N
3657 if (FRAME_XIC (f))
3658 {
3659 /* The necessity of the following line took me
3660 a full work-day to decipher from the docs!! */
3661 if (XFilterEvent (&event, None))
3662 break;
3663 nbytes = XmbLookupString (FRAME_XIC (f),
3664 &event.xkey, copy_buffer,
3665 80, &keysym,
3666 &status_return);
3667 }
3668 else
3669 nbytes = XLookupString (&event.xkey, copy_buffer,
3670 80, &keysym, &compose_status);
3671#else
0299d313
RS
3672 nbytes = XLookupString (&event.xkey, copy_buffer,
3673 80, &keysym, &compose_status);
6c183ba5 3674#endif
dc6f92b8 3675
7a13e894 3676 orig_keysym = keysym;
55123275 3677
7a13e894
RS
3678 if (numchars > 1)
3679 {
3680 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
3681 || keysym == XK_Delete
3682 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
3683 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 3684#ifdef HPUX
7a13e894
RS
3685 /* This recognizes the "extended function keys".
3686 It seems there's no cleaner way.
3687 Test IsModifierKey to avoid handling mode_switch
3688 incorrectly. */
3689 || ((unsigned) (keysym) >= XK_Select
3690 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
3691#endif
3692#ifdef XK_dead_circumflex
7a13e894 3693 || orig_keysym == XK_dead_circumflex
69388238
RS
3694#endif
3695#ifdef XK_dead_grave
7a13e894 3696 || orig_keysym == XK_dead_grave
69388238
RS
3697#endif
3698#ifdef XK_dead_tilde
7a13e894 3699 || orig_keysym == XK_dead_tilde
69388238
RS
3700#endif
3701#ifdef XK_dead_diaeresis
7a13e894 3702 || orig_keysym == XK_dead_diaeresis
69388238
RS
3703#endif
3704#ifdef XK_dead_macron
7a13e894 3705 || orig_keysym == XK_dead_macron
69388238
RS
3706#endif
3707#ifdef XK_dead_degree
7a13e894 3708 || orig_keysym == XK_dead_degree
69388238
RS
3709#endif
3710#ifdef XK_dead_acute
7a13e894 3711 || orig_keysym == XK_dead_acute
69388238
RS
3712#endif
3713#ifdef XK_dead_cedilla
7a13e894 3714 || orig_keysym == XK_dead_cedilla
69388238
RS
3715#endif
3716#ifdef XK_dead_breve
7a13e894 3717 || orig_keysym == XK_dead_breve
69388238
RS
3718#endif
3719#ifdef XK_dead_ogonek
7a13e894 3720 || orig_keysym == XK_dead_ogonek
69388238
RS
3721#endif
3722#ifdef XK_dead_caron
7a13e894 3723 || orig_keysym == XK_dead_caron
69388238
RS
3724#endif
3725#ifdef XK_dead_doubleacute
7a13e894 3726 || orig_keysym == XK_dead_doubleacute
69388238
RS
3727#endif
3728#ifdef XK_dead_abovedot
7a13e894 3729 || orig_keysym == XK_dead_abovedot
c34790e0 3730#endif
7a13e894
RS
3731 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
3732 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
3733 /* Any "vendor-specific" key is ok. */
3734 || (orig_keysym & (1 << 28)))
3735 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
3736#ifndef HAVE_X11R5
3737#ifdef XK_Mode_switch
7a13e894 3738 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
3739#endif
3740#ifdef XK_Num_Lock
7a13e894 3741 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
3742#endif
3743#endif /* not HAVE_X11R5 */
7a13e894 3744 ))
dc6f92b8 3745 {
10e6549c
RS
3746 if (temp_index == sizeof temp_buffer / sizeof (short))
3747 temp_index = 0;
7a13e894
RS
3748 temp_buffer[temp_index++] = keysym;
3749 bufp->kind = non_ascii_keystroke;
3750 bufp->code = keysym;
e0c1aef2 3751 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
3752 bufp->modifiers
3753 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3754 modifiers);
1113d9db 3755 bufp->timestamp = event.xkey.time;
dc6f92b8 3756 bufp++;
7a13e894
RS
3757 count++;
3758 numchars--;
dc6f92b8 3759 }
7a13e894
RS
3760 else if (numchars > nbytes)
3761 {
3762 register int i;
3763
3764 for (i = 0; i < nbytes; i++)
3765 {
3766 if (temp_index == sizeof temp_buffer / sizeof (short))
3767 temp_index = 0;
3768 temp_buffer[temp_index++] = copy_buffer[i];
3769 bufp->kind = ascii_keystroke;
3770 bufp->code = copy_buffer[i];
3771 XSETFRAME (bufp->frame_or_window, f);
3772 bufp->modifiers
3773 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3774 modifiers);
3775 bufp->timestamp = event.xkey.time;
3776 bufp++;
3777 }
3778
3779 count += nbytes;
3780 numchars -= nbytes;
3781 }
3782 else
3783 abort ();
dc6f92b8 3784 }
10e6549c
RS
3785 else
3786 abort ();
dc6f92b8 3787 }
7a13e894 3788 break;
f451eb13 3789
7a13e894
RS
3790 /* Here's a possible interpretation of the whole
3791 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3792 FocusIn event, you have to get a FocusOut event before you
3793 relinquish the focus. If you haven't received a FocusIn event,
3794 then a mere LeaveNotify is enough to free you. */
f451eb13 3795
7a13e894 3796 case EnterNotify:
19126e11 3797 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
6d4238f3 3798
7a13e894 3799 if (event.xcrossing.focus) /* Entered Window */
dc6f92b8 3800 {
7a13e894
RS
3801 /* Avoid nasty pop/raise loops. */
3802 if (f && (!(f->auto_raise)
3803 || !(f->auto_lower)
3804 || (event.xcrossing.time - enter_timestamp) > 500))
3805 {
0f941935 3806 x_new_focus_frame (dpyinfo, f);
7a13e894
RS
3807 enter_timestamp = event.xcrossing.time;
3808 }
dc6f92b8 3809 }
0f941935
KH
3810 else if (f == dpyinfo->x_focus_frame)
3811 x_new_focus_frame (dpyinfo, 0);
7a13e894
RS
3812 /* EnterNotify counts as mouse movement,
3813 so update things that depend on mouse position. */
3814 if (f)
3815 note_mouse_movement (f, &event.xmotion);
3afe33e7 3816#ifdef USE_X_TOOLKIT
7a13e894 3817 goto OTHER;
3afe33e7 3818#endif /* USE_X_TOOLKIT */
7a13e894 3819 break;
dc6f92b8 3820
7a13e894 3821 case FocusIn:
19126e11 3822 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 3823 if (event.xfocus.detail != NotifyPointer)
0f941935 3824 dpyinfo->x_focus_event_frame = f;
7a13e894 3825 if (f)
0f941935 3826 x_new_focus_frame (dpyinfo, f);
f9e24cb9 3827
6c183ba5
RS
3828#ifdef HAVE_X_I18N
3829 if (f && FRAME_XIC (f))
3830 XSetICFocus (FRAME_XIC (f));
3831#endif
3832
3afe33e7 3833#ifdef USE_X_TOOLKIT
7a13e894 3834 goto OTHER;
3afe33e7 3835#endif /* USE_X_TOOLKIT */
7a13e894 3836 break;
f451eb13 3837
10c5e63d 3838
7a13e894 3839 case LeaveNotify:
19126e11 3840 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 3841 if (f)
10c5e63d 3842 {
7a13e894
RS
3843 if (f == dpyinfo->mouse_face_mouse_frame)
3844 /* If we move outside the frame,
3845 then we're certainly no longer on any text in the frame. */
3846 clear_mouse_face (dpyinfo);
3847
3848 if (event.xcrossing.focus)
0f941935 3849 x_mouse_leave (dpyinfo);
10c5e63d 3850 else
7a13e894 3851 {
0f941935
KH
3852 if (f == dpyinfo->x_focus_event_frame)
3853 dpyinfo->x_focus_event_frame = 0;
3854 if (f == dpyinfo->x_focus_frame)
3855 x_new_focus_frame (dpyinfo, 0);
7a13e894 3856 }
10c5e63d 3857 }
3afe33e7 3858#ifdef USE_X_TOOLKIT
7a13e894 3859 goto OTHER;
3afe33e7 3860#endif /* USE_X_TOOLKIT */
7a13e894 3861 break;
dc6f92b8 3862
7a13e894 3863 case FocusOut:
19126e11 3864 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 3865 if (event.xfocus.detail != NotifyPointer
0f941935
KH
3866 && f == dpyinfo->x_focus_event_frame)
3867 dpyinfo->x_focus_event_frame = 0;
3868 if (f && f == dpyinfo->x_focus_frame)
3869 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 3870
6c183ba5
RS
3871#ifdef HAVE_X_I18N
3872 if (f && FRAME_XIC (f))
3873 XUnsetICFocus (FRAME_XIC (f));
3874#endif
3875
3afe33e7 3876#ifdef USE_X_TOOLKIT
7a13e894 3877 goto OTHER;
3afe33e7 3878#endif /* USE_X_TOOLKIT */
7a13e894 3879 break;
dc6f92b8 3880
7a13e894 3881 case MotionNotify:
dc6f92b8 3882 {
7a13e894
RS
3883 if (dpyinfo->grabbed && last_mouse_frame
3884 && FRAME_LIVE_P (last_mouse_frame))
3885 f = last_mouse_frame;
3886 else
19126e11 3887 f = x_window_to_frame (dpyinfo, event.xmotion.window);
7a13e894
RS
3888 if (f)
3889 note_mouse_movement (f, &event.xmotion);
3890 else
3891 {
3892 struct scroll_bar *bar
3893 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 3894
7a13e894
RS
3895 if (bar)
3896 x_scroll_bar_note_movement (bar, &event);
b8009dd1 3897
7a13e894
RS
3898 /* If we move outside the frame,
3899 then we're certainly no longer on any text in the frame. */
3900 clear_mouse_face (dpyinfo);
3901 }
dc6f92b8 3902 }
3afe33e7 3903#ifdef USE_X_TOOLKIT
7a13e894 3904 goto OTHER;
3afe33e7 3905#endif /* USE_X_TOOLKIT */
7a13e894 3906 break;
dc6f92b8 3907
7a13e894 3908 case ConfigureNotify:
19126e11 3909 f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
7a13e894 3910 if (f
2d7fc7e8 3911#ifdef USE_X_TOOLKIT
7556890b 3912 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
3a35ab44 3913#endif
2d7fc7e8 3914 )
af395ec1 3915 {
2d7fc7e8
RS
3916#ifndef USE_X_TOOLKIT
3917 /* In the toolkit version, change_frame_size
3918 is called by the code that handles resizing
3919 of the EmacsFrame widget. */
7a13e894 3920
7a13e894
RS
3921 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3922 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3923
3924 /* Even if the number of character rows and columns has
3925 not changed, the font size may have changed, so we need
3926 to check the pixel dimensions as well. */
3927 if (columns != f->width
3928 || rows != f->height
7556890b
RS
3929 || event.xconfigure.width != f->output_data.x->pixel_width
3930 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894
RS
3931 {
3932 change_frame_size (f, rows, columns, 0, 1);
3933 SET_FRAME_GARBAGED (f);
3934 }
2d7fc7e8 3935#endif
af395ec1 3936
2d7fc7e8
RS
3937 /* Formerly, in the USE_X_TOOLKIT version,
3938 we did not test send_event here. */
3939 if (1
3940#ifndef USE_X_TOOLKIT
3941 && ! event.xconfigure.send_event
3942#endif
3943 )
7a13e894
RS
3944 {
3945 Window win, child;
3946 int win_x, win_y;
3947
3948 /* Find the position of the outside upper-left corner of
3949 the window, in the root coordinate system. Don't
3950 refer to the parent window here; we may be processing
3951 this event after the window manager has changed our
3952 parent, but before we have reached the ReparentNotify. */
3953 XTranslateCoordinates (FRAME_X_DISPLAY (f),
3954
3955 /* From-window, to-window. */
2d7fc7e8 3956 event.xconfigure.window,
7a13e894
RS
3957 FRAME_X_DISPLAY_INFO (f)->root_window,
3958
3959 /* From-position, to-position. */
3960 -event.xconfigure.border_width,
3961 -event.xconfigure.border_width,
3962 &win_x, &win_y,
3963
3964 /* Child of win. */
3965 &child);
3966 event.xconfigure.x = win_x;
3967 event.xconfigure.y = win_y;
3968 }
3a35ab44 3969
7556890b
RS
3970 f->output_data.x->pixel_width = event.xconfigure.width;
3971 f->output_data.x->pixel_height = event.xconfigure.height;
3972 f->output_data.x->left_pos = event.xconfigure.x;
3973 f->output_data.x->top_pos = event.xconfigure.y;
7a13e894
RS
3974
3975 /* What we have now is the position of Emacs's own window.
3976 Convert that to the position of the window manager window. */
fd13dbb2 3977 {
7a13e894
RS
3978 int x, y;
3979 x_real_positions (f, &x, &y);
7556890b
RS
3980 f->output_data.x->left_pos = x;
3981 f->output_data.x->top_pos = y;
2d7fc7e8
RS
3982 /* Formerly we did not do this in the USE_X_TOOLKIT
3983 version. Let's try making them the same. */
3984/* #ifndef USE_X_TOOLKIT */
7a13e894
RS
3985 if (y != event.xconfigure.y)
3986 {
3987 /* Since the WM decorations come below top_pos now,
3988 we must put them below top_pos in the future. */
7556890b 3989 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 3990 x_wm_set_size_hint (f, (long) 0, 0);
7a13e894 3991 }
2d7fc7e8 3992/* #endif */
fd13dbb2 3993 }
7a13e894 3994 }
2d7fc7e8
RS
3995#ifdef USE_X_TOOLKIT
3996 goto OTHER;
3997#else
7a13e894 3998 break;
2d7fc7e8 3999#endif
dc6f92b8 4000
7a13e894
RS
4001 case ButtonPress:
4002 case ButtonRelease:
4003 {
4004 /* If we decide we want to generate an event to be seen
4005 by the rest of Emacs, we put it here. */
4006 struct input_event emacs_event;
4007 emacs_event.kind = no_event;
dc6f92b8 4008
7a13e894 4009 bzero (&compose_status, sizeof (compose_status));
9b07615b 4010
9f67f20b
RS
4011 if (dpyinfo->grabbed && last_mouse_frame
4012 && FRAME_LIVE_P (last_mouse_frame))
4013 f = last_mouse_frame;
4014 else
2224b905 4015 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 4016
7a13e894
RS
4017 if (f)
4018 {
0f941935 4019 if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
7a13e894
RS
4020 construct_mouse_click (&emacs_event, &event, f);
4021 }
4022 else
4023 {
4024 struct scroll_bar *bar
4025 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 4026
7a13e894
RS
4027 if (bar)
4028 x_scroll_bar_handle_click (bar, &event, &emacs_event);
7a13e894
RS
4029 }
4030
4031 if (event.type == ButtonPress)
4032 {
4033 dpyinfo->grabbed |= (1 << event.xbutton.button);
4034 last_mouse_frame = f;
4035 }
3afe33e7
RS
4036 else
4037 {
7a13e894 4038 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 4039 }
23faf38f 4040
7a13e894
RS
4041 if (numchars >= 1 && emacs_event.kind != no_event)
4042 {
4043 bcopy (&emacs_event, bufp, sizeof (struct input_event));
4044 bufp++;
4045 count++;
4046 numchars--;
4047 }
3afe33e7
RS
4048
4049#ifdef USE_X_TOOLKIT
2224b905
RS
4050 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
4051 /* For a down-event in the menu bar,
4052 don't pass it to Xt right now.
4053 Instead, save it away
4054 and we will pass it to Xt from kbd_buffer_get_event.
4055 That way, we can run some Lisp code first. */
4056 if (f && event.type == ButtonPress)
4057 {
7556890b
RS
4058 if (f->output_data.x->saved_button_event == 0)
4059 f->output_data.x->saved_button_event
2224b905 4060 = (XButtonEvent *) xmalloc (sizeof (XButtonEvent));
7556890b 4061 bcopy (&event, f->output_data.x->saved_button_event,
2224b905
RS
4062 sizeof (XButtonEvent));
4063 if (numchars >= 1)
4064 {
4065 bufp->kind = menu_bar_activate_event;
4066 XSETFRAME (bufp->frame_or_window, f);
4067 bufp++;
4068 count++;
4069 numchars--;
4070 }
4071 }
4072 else
4073 goto OTHER;
3afe33e7 4074#endif /* USE_X_TOOLKIT */
7a13e894
RS
4075 }
4076 break;
dc6f92b8 4077
7a13e894
RS
4078 case CirculateNotify:
4079 break;
4080 case CirculateRequest:
4081 break;
dc6f92b8 4082
7a13e894
RS
4083 case MappingNotify:
4084 /* Someone has changed the keyboard mapping - update the
4085 local cache. */
4086 switch (event.xmapping.request)
4087 {
4088 case MappingModifier:
4089 x_find_modifier_meanings (dpyinfo);
4090 /* This is meant to fall through. */
4091 case MappingKeyboard:
4092 XRefreshKeyboardMapping (&event.xmapping);
4093 }
3afe33e7 4094#ifdef USE_X_TOOLKIT
7a13e894 4095 goto OTHER;
3afe33e7 4096#endif /* USE_X_TOOLKIT */
7a13e894 4097 break;
dc6f92b8 4098
7a13e894 4099 default:
3afe33e7 4100#ifdef USE_X_TOOLKIT
7a13e894
RS
4101 OTHER:
4102 BLOCK_INPUT;
4103 XtDispatchEvent (&event);
4104 UNBLOCK_INPUT;
3afe33e7 4105#endif /* USE_X_TOOLKIT */
7a13e894
RS
4106 break;
4107 }
dc6f92b8
JB
4108 }
4109 }
4110
9a5196d0
RS
4111 /* On some systems, an X bug causes Emacs to get no more events
4112 when the window is destroyed. Detect that. (1994.) */
58769bee 4113 if (! event_found)
ef2a22d0 4114 {
ef2a22d0
RS
4115 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4116 One XNOOP in 100 loops will make Emacs terminate.
4117 B. Bretthauer, 1994 */
4118 x_noop_count++;
58769bee 4119 if (x_noop_count >= 100)
ef2a22d0
RS
4120 {
4121 x_noop_count=0;
2224b905
RS
4122
4123 if (next_noop_dpyinfo == 0)
4124 next_noop_dpyinfo = x_display_list;
4125
4126 XNoOp (next_noop_dpyinfo->display);
4127
4128 /* Each time we get here, cycle through the displays now open. */
4129 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
4130 }
4131 }
502add23 4132
0134a210
RS
4133 /* If the focus was just given to an autoraising frame,
4134 raise it now. */
7a13e894 4135 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
4136 if (pending_autoraise_frame)
4137 {
4138 x_raise_frame (pending_autoraise_frame);
4139 pending_autoraise_frame = 0;
4140 }
0134a210 4141
dc6f92b8
JB
4142 UNBLOCK_INPUT;
4143 return count;
4144}
dc6f92b8 4145\f
f451eb13
JB
4146/* Drawing the cursor. */
4147
4148
39d8bb4d
KH
4149/* Draw a hollow box cursor on frame F at X, Y.
4150 Don't change the inside of the box. */
dc6f92b8
JB
4151
4152static void
39d8bb4d 4153x_draw_box (f, x, y)
f676886a 4154 struct frame *f;
39d8bb4d 4155 int x, y;
dc6f92b8 4156{
39d8bb4d
KH
4157 int left = CHAR_TO_PIXEL_COL (f, x);
4158 int top = CHAR_TO_PIXEL_ROW (f, y);
7556890b
RS
4159 int width = FONT_WIDTH (f->output_data.x->font);
4160 int height = f->output_data.x->line_height;
dc6f92b8 4161
334208b7 4162 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 4163 f->output_data.x->cursor_gc,
dc6f92b8 4164 left, top, width - 1, height - 1);
dc6f92b8
JB
4165}
4166
f676886a 4167/* Clear the cursor of frame F to background color,
dc6f92b8
JB
4168 and mark the cursor as not shown.
4169 This is used when the text where the cursor is
4170 is about to be rewritten. */
4171
4172static void
f676886a
JB
4173clear_cursor (f)
4174 struct frame *f;
dc6f92b8
JB
4175{
4176 int mask;
4177
f451eb13 4178 if (! FRAME_VISIBLE_P (f)
f676886a 4179 || f->phys_cursor_x < 0)
dc6f92b8
JB
4180 return;
4181
f676886a 4182 x_display_cursor (f, 0);
f676886a 4183 f->phys_cursor_x = -1;
dc6f92b8
JB
4184}
4185
f676886a 4186/* Redraw the glyph at ROW, COLUMN on frame F, in the style
90e65f07
JB
4187 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4188 glyph drawn. */
dc6f92b8
JB
4189
4190static void
f676886a
JB
4191x_draw_single_glyph (f, row, column, glyph, highlight)
4192 struct frame *f;
dc6f92b8 4193 int row, column;
90e65f07 4194 GLYPH glyph;
dc6f92b8
JB
4195 int highlight;
4196{
f676886a 4197 dumpglyphs (f,
12ba150f
JB
4198 CHAR_TO_PIXEL_COL (f, column),
4199 CHAR_TO_PIXEL_ROW (f, row),
0cdd0c9f 4200 &glyph, 1, highlight, 0);
dc6f92b8
JB
4201}
4202
dc6f92b8 4203static void
39d8bb4d 4204x_display_bar_cursor (f, on, x, y)
f676886a 4205 struct frame *f;
dc6f92b8 4206 int on;
39d8bb4d 4207 int x, y;
dc6f92b8 4208{
f676886a 4209 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
90e65f07 4210
49d838ea
JB
4211 /* This is pointless on invisible frames, and dangerous on garbaged
4212 frames; in the latter case, the frame may be in the midst of
39d8bb4d 4213 changing its size, and x and y may be off the frame. */
49d838ea 4214 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dbc4e1c1
JB
4215 return;
4216
4217 if (! on && f->phys_cursor_x < 0)
4218 return;
4219
dbc4e1c1
JB
4220 /* If there is anything wrong with the current cursor state, remove it. */
4221 if (f->phys_cursor_x >= 0
4222 && (!on
39d8bb4d
KH
4223 || f->phys_cursor_x != x
4224 || f->phys_cursor_y != y
7556890b 4225 || f->output_data.x->current_cursor != bar_cursor))
dbc4e1c1
JB
4226 {
4227 /* Erase the cursor by redrawing the character underneath it. */
4228 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4229 f->phys_cursor_glyph,
4230 current_glyphs->highlight[f->phys_cursor_y]);
4231 f->phys_cursor_x = -1;
4232 }
4233
4234 /* If we now need a cursor in the new place or in the new form, do it so. */
4235 if (on
4236 && (f->phys_cursor_x < 0
7556890b 4237 || (f->output_data.x->current_cursor != bar_cursor)))
dbc4e1c1
JB
4238 {
4239 f->phys_cursor_glyph
39d8bb4d
KH
4240 = ((current_glyphs->enable[y]
4241 && x < current_glyphs->used[y])
4242 ? current_glyphs->glyphs[y][x]
dbc4e1c1 4243 : SPACEGLYPH);
334208b7 4244 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 4245 f->output_data.x->cursor_gc,
39d8bb4d
KH
4246 CHAR_TO_PIXEL_COL (f, x),
4247 CHAR_TO_PIXEL_ROW (f, y),
7556890b
RS
4248 max (f->output_data.x->cursor_width, 1),
4249 f->output_data.x->line_height);
dbc4e1c1 4250
39d8bb4d
KH
4251 f->phys_cursor_x = x;
4252 f->phys_cursor_y = y;
dbc4e1c1 4253
7556890b 4254 f->output_data.x->current_cursor = bar_cursor;
dbc4e1c1
JB
4255 }
4256
4257 if (updating_frame != f)
334208b7 4258 XFlush (FRAME_X_DISPLAY (f));
dbc4e1c1
JB
4259}
4260
4261
4262/* Turn the displayed cursor of frame F on or off according to ON.
39d8bb4d 4263 If ON is nonzero, where to put the cursor is specified by X and Y. */
dbc4e1c1
JB
4264
4265static void
39d8bb4d 4266x_display_box_cursor (f, on, x, y)
dbc4e1c1
JB
4267 struct frame *f;
4268 int on;
39d8bb4d 4269 int x, y;
dbc4e1c1
JB
4270{
4271 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4272
49d838ea
JB
4273 /* This is pointless on invisible frames, and dangerous on garbaged
4274 frames; in the latter case, the frame may be in the midst of
39d8bb4d 4275 changing its size, and x and y may be off the frame. */
49d838ea 4276 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dc6f92b8
JB
4277 return;
4278
4279 /* If cursor is off and we want it off, return quickly. */
f676886a 4280 if (!on && f->phys_cursor_x < 0)
dc6f92b8
JB
4281 return;
4282
4283 /* If cursor is currently being shown and we don't want it to be
4284 or it is in the wrong place,
4285 or we want a hollow box and it's not so, (pout!)
4286 erase it. */
f676886a 4287 if (f->phys_cursor_x >= 0
dc6f92b8 4288 && (!on
39d8bb4d
KH
4289 || f->phys_cursor_x != x
4290 || f->phys_cursor_y != y
7556890b 4291 || (f->output_data.x->current_cursor != hollow_box_cursor
0f941935 4292 && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
dc6f92b8 4293 {
79cf7456 4294 int mouse_face_here = 0;
9f67f20b 4295 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
79cf7456
RS
4296
4297 /* If the cursor is in the mouse face area, redisplay that when
4298 we clear the cursor. */
7a13e894 4299 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
79cf7456 4300 &&
7a13e894
RS
4301 (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4302 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4303 && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
79cf7456 4304 &&
7a13e894
RS
4305 (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4306 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
9f67f20b
RS
4307 && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
4308 /* Don't redraw the cursor's spot in mouse face
4309 if it is at the end of a line (on a newline).
4310 The cursor appears there, but mouse highlighting does not. */
4311 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
79cf7456
RS
4312 mouse_face_here = 1;
4313
0cdd0c9f
RS
4314 /* If the font is not as tall as a whole line,
4315 we must explicitly clear the line's whole height. */
7556890b 4316 if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
334208b7 4317 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
0cdd0c9f
RS
4318 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4319 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
7556890b
RS
4320 FONT_WIDTH (f->output_data.x->font),
4321 f->output_data.x->line_height, False);
dc6f92b8 4322 /* Erase the cursor by redrawing the character underneath it. */
f676886a
JB
4323 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4324 f->phys_cursor_glyph,
79cf7456
RS
4325 (mouse_face_here
4326 ? 3
4327 : current_glyphs->highlight[f->phys_cursor_y]));
f676886a 4328 f->phys_cursor_x = -1;
dc6f92b8
JB
4329 }
4330
4331 /* If we want to show a cursor,
4332 or we want a box cursor and it's not so,
4333 write it in the right place. */
4334 if (on
f676886a 4335 && (f->phys_cursor_x < 0
7556890b 4336 || (f->output_data.x->current_cursor != filled_box_cursor
0f941935 4337 && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
dc6f92b8 4338 {
f676886a 4339 f->phys_cursor_glyph
39d8bb4d
KH
4340 = ((current_glyphs->enable[y]
4341 && x < current_glyphs->used[y])
4342 ? current_glyphs->glyphs[y][x]
90e65f07 4343 : SPACEGLYPH);
0f941935 4344 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
dc6f92b8 4345 {
39d8bb4d 4346 x_draw_box (f, x, y);
7556890b 4347 f->output_data.x->current_cursor = hollow_box_cursor;
dc6f92b8
JB
4348 }
4349 else
4350 {
39d8bb4d 4351 x_draw_single_glyph (f, y, x,
f676886a 4352 f->phys_cursor_glyph, 2);
7556890b 4353 f->output_data.x->current_cursor = filled_box_cursor;
dc6f92b8
JB
4354 }
4355
39d8bb4d
KH
4356 f->phys_cursor_x = x;
4357 f->phys_cursor_y = y;
dc6f92b8
JB
4358 }
4359
f676886a 4360 if (updating_frame != f)
334208b7 4361 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
4362}
4363
5d46f928
RS
4364/* Display the cursor on frame F, or clear it, according to ON.
4365 Use the position specified by curs_x and curs_y
4366 if we are doing an update of frame F now.
4367 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4368 of F. */
4369
f676886a
JB
4370x_display_cursor (f, on)
4371 struct frame *f;
dc6f92b8
JB
4372 int on;
4373{
f94397b5
KH
4374 BLOCK_INPUT;
4375
5d46f928
RS
4376 /* If we're not updating, then don't change the physical cursor
4377 position. Just change (if appropriate) the style of display. */
4378 if (f != updating_frame)
4379 {
4380 curs_x = FRAME_CURSOR_X (f);
4381 curs_y = FRAME_CURSOR_Y (f);
4382 }
4383
4384 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
39d8bb4d 4385 x_display_box_cursor (f, on, curs_x, curs_y);
5d46f928 4386 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
39d8bb4d 4387 x_display_bar_cursor (f, on, curs_x, curs_y);
5d46f928
RS
4388 else
4389 /* Those are the only two we have implemented! */
4390 abort ();
4391
4392 UNBLOCK_INPUT;
4393}
4394
4395/* Display the cursor on frame F, or clear it, according to ON.
4396 Don't change the cursor's position. */
4397
4398x_update_cursor (f, on)
4399 struct frame *f;
4400 int on;
4401{
4402 BLOCK_INPUT;
4403
dbc4e1c1 4404 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
39d8bb4d 4405 x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
dbc4e1c1 4406 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
39d8bb4d 4407 x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
dbc4e1c1
JB
4408 else
4409 /* Those are the only two we have implemented! */
4410 abort ();
f94397b5
KH
4411
4412 UNBLOCK_INPUT;
dc6f92b8
JB
4413}
4414\f
4415/* Icons. */
4416
f676886a 4417/* Refresh bitmap kitchen sink icon for frame F
dc6f92b8
JB
4418 when we get an expose event for it. */
4419
f676886a
JB
4420refreshicon (f)
4421 struct frame *f;
dc6f92b8 4422{
dc6f92b8 4423 /* Normally, the window manager handles this function. */
dc6f92b8
JB
4424}
4425
dbc4e1c1 4426/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
4427
4428int
990ba854 4429x_bitmap_icon (f, file)
f676886a 4430 struct frame *f;
990ba854 4431 Lisp_Object file;
dc6f92b8 4432{
7f2ae036 4433 int mask, bitmap_id;
dc6f92b8
JB
4434 Window icon_window;
4435
c118dd06 4436 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
4437 return 1;
4438
990ba854 4439 /* Free up our existing icon bitmap if any. */
7556890b
RS
4440 if (f->output_data.x->icon_bitmap > 0)
4441 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4442 f->output_data.x->icon_bitmap = 0;
990ba854
RS
4443
4444 if (STRINGP (file))
7f2ae036
RS
4445 bitmap_id = x_create_bitmap_from_file (f, file);
4446 else
4447 {
990ba854 4448 /* Create the GNU bitmap if necessary. */
5bf01b68 4449 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
4450 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
4451 = x_create_bitmap_from_data (f, gnu_bits,
4452 gnu_width, gnu_height);
990ba854
RS
4453
4454 /* The first time we create the GNU bitmap,
4455 this increments the refcount one extra time.
4456 As a result, the GNU bitmap is never freed.
4457 That way, we don't have to worry about allocating it again. */
334208b7 4458 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 4459
334208b7 4460 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
4461 }
4462
4463 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 4464 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
4465
4466 return 0;
4467}
4468
4469
1be2d067
KH
4470/* Make the x-window of frame F use a rectangle with text.
4471 Use ICON_NAME as the text. */
dc6f92b8
JB
4472
4473int
f676886a
JB
4474x_text_icon (f, icon_name)
4475 struct frame *f;
dc6f92b8
JB
4476 char *icon_name;
4477{
c118dd06 4478 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
4479 return 1;
4480
1be2d067
KH
4481#ifdef HAVE_X11R4
4482 {
4483 XTextProperty text;
4484 text.value = (unsigned char *) icon_name;
4485 text.encoding = XA_STRING;
4486 text.format = 8;
4487 text.nitems = strlen (icon_name);
4488#ifdef USE_X_TOOLKIT
7556890b 4489 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
4490 &text);
4491#else /* not USE_X_TOOLKIT */
4492 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
4493#endif /* not USE_X_TOOLKIT */
4494 }
4495#else /* not HAVE_X11R4 */
4496 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
4497#endif /* not HAVE_X11R4 */
58769bee 4498
7556890b
RS
4499 if (f->output_data.x->icon_bitmap > 0)
4500 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4501 f->output_data.x->icon_bitmap = 0;
b1c884c3 4502 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
4503
4504 return 0;
4505}
4506\f
4746118a
JB
4507/* Handling X errors. */
4508
7a13e894 4509/* Handle the loss of connection to display DISPLAY. */
16bd92ea 4510
4746118a 4511static SIGTYPE
7a13e894
RS
4512x_connection_closed (display, error_message)
4513 Display *display;
4514 char *error_message;
4746118a 4515{
7a13e894
RS
4516 struct x_display_info *dpyinfo = x_display_info_for_display (display);
4517 Lisp_Object frame, tail;
4518
07a7096a
KH
4519 /* Whatever we were in the middle of, we are going to throw out of it,
4520 so reassure various things that have error checks about being
4521 called with input blocked. */
4522 TOTALLY_UNBLOCK_INPUT;
4523
4746118a
JB
4524 if (_Xdebug)
4525 abort ();
12ba150f 4526
7a13e894
RS
4527 /* First delete frames whose minibuffers are on frames
4528 that are on the dead display. */
4529 FOR_EACH_FRAME (tail, frame)
4530 {
4531 Lisp_Object minibuf_frame;
4532 minibuf_frame
4533 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
4534 if (FRAME_X_P (XFRAME (frame))
4535 && FRAME_X_P (XFRAME (minibuf_frame))
4536 && ! EQ (frame, minibuf_frame)
4537 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
4538 Fdelete_frame (frame, Qt);
4539 }
4540
4541 /* Now delete all remaining frames on the dead display.
4542 We are now sure none of these is used as the minibuffer
4543 for another frame that we need to delete. */
4544 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
4545 if (FRAME_X_P (XFRAME (frame))
4546 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
4547 {
4548 /* Set this to t so that Fdelete_frame won't get confused
4549 trying to find a replacement. */
4550 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
4551 Fdelete_frame (frame, Qt);
4552 }
7a13e894
RS
4553
4554 x_delete_display (dpyinfo);
4555
4556 if (x_display_list == 0)
4557 {
4558 fprintf (stderr, "%s", error_message);
4559 shut_down_emacs (0, 0, Qnil);
4560 exit (70);
4561 }
12ba150f 4562
7a13e894
RS
4563 /* Ordinary stack unwind doesn't deal with these. */
4564#ifdef SIGIO
4565 sigunblock (sigmask (SIGIO));
4566#endif
4567 sigunblock (sigmask (SIGALRM));
4568 TOTALLY_UNBLOCK_INPUT;
4569
4570 error ("%s", error_message);
4746118a
JB
4571}
4572
7a13e894
RS
4573/* This is the usual handler for X protocol errors.
4574 It kills all frames on the display that we got the error for.
4575 If that was the only one, it prints an error message and kills Emacs. */
4576
c118dd06
JB
4577static int
4578x_error_quitter (display, error)
4579 Display *display;
4580 XErrorEvent *error;
4581{
7a13e894 4582 char buf[256], buf1[356];
dc6f92b8 4583
58769bee 4584 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 4585 original error handler. */
dc6f92b8 4586
c118dd06 4587 XGetErrorText (display, error->error_code, buf, sizeof (buf));
7a13e894 4588 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 4589 buf, error->request_code);
7a13e894 4590 x_connection_closed (display, buf1);
dc6f92b8
JB
4591}
4592
7a13e894
RS
4593/* This is the handler for X IO errors, always.
4594 It kills all frames on the display that we lost touch with.
4595 If that was the only one, it prints an error message and kills Emacs. */
4596
8922af5f
JB
4597static int
4598x_io_error_quitter (display)
4599 Display *display;
4600{
7a13e894 4601 char buf[256];
8922af5f 4602
7a13e894
RS
4603 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
4604 x_connection_closed (display, buf);
8922af5f 4605}
7a13e894 4606\f
f9e24cb9
RS
4607/* Handle SIGPIPE, which can happen when the connection to a server
4608 simply goes away. SIGPIPE is handled by x_connection_signal.
4609 It works by sending a no-op command to each X server connection.
4610 When we try a connection that has closed, we get SIGPIPE again.
4611 But this time, it is handled by x_connection_signal_1.
4612 That function knows which connection we were testing,
4613 so it closes that one.
4614
4615 x_connection_closed never returns,
4616 so if more than one connection was lost at once,
4617 we only find one. But XTread_socket keeps trying them all,
4618 so it will notice the other closed one sooner or later. */
4619
4620
4621static struct x_display_info *x_connection_signal_dpyinfo;
4622
4623static SIGTYPE x_connection_signal ();
4624
4625static SIGTYPE
4626x_connection_signal_1 (signalnum) /* If we don't have an argument, */
4627 int signalnum; /* some compilers complain in signal calls. */
4628{
4629 signal (SIGPIPE, x_connection_signal);
4630 x_connection_closed (x_connection_signal_dpyinfo,
4631 "connection was lost");
4632}
4633
4634static SIGTYPE
4635x_connection_signal (signalnum) /* If we don't have an argument, */
4636 int signalnum; /* some compilers complain in signal calls. */
4637{
4638 x_connection_signal_dpyinfo = x_display_list;
4639
4640 sigunblock (SIGPIPE);
4641
4642 while (x_connection_signal_dpyinfo)
4643 {
4644 signal (SIGPIPE, x_connection_signal_1);
4645
4646 XNoOp (x_connection_signal_dpyinfo->display);
4647 XSync (x_connection_signal_dpyinfo->display, False);
4648
4649 /* Each time we get here, cycle through the displays now open. */
4650 x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
4651 }
4652
4653 /* We should have found some closed connection. */
4654 abort ();
4655}
4656\f
c118dd06 4657/* A buffer for storing X error messages. */
cef13e55
RS
4658static char *x_caught_error_message;
4659#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
c118dd06
JB
4660
4661/* An X error handler which stores the error message in
4662 x_caught_error_message. This is what's installed when
4663 x_catch_errors is in effect. */
7a13e894 4664
c118dd06
JB
4665static int
4666x_error_catcher (display, error)
4667 Display *display;
4668 XErrorEvent *error;
4669{
4670 XGetErrorText (display, error->error_code,
cef13e55 4671 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
c118dd06
JB
4672}
4673
4674
7a13e894
RS
4675/* Begin trapping X errors for display DPY. Actually we trap X errors
4676 for all displays, but DPY should be the display you are actually
4677 operating on.
dc6f92b8 4678
c118dd06
JB
4679 After calling this function, X protocol errors no longer cause
4680 Emacs to exit; instead, they are recorded in x_cfc_error_message.
dc6f92b8 4681
c118dd06
JB
4682 Calling x_check_errors signals an Emacs error if an X error has
4683 occurred since the last call to x_catch_errors or x_check_errors.
4684
4685 Calling x_uncatch_errors resumes the normal error handling. */
4686
bc20ebbf 4687void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
c118dd06
JB
4688
4689void
7a13e894
RS
4690x_catch_errors (dpy)
4691 Display *dpy;
dc6f92b8 4692{
c118dd06 4693 /* Make sure any errors from previous requests have been dealt with. */
7a13e894 4694 XSync (dpy, False);
dc6f92b8 4695
c118dd06 4696 /* Set up the error buffer. */
60f9aad3 4697 x_caught_error_message
cef13e55
RS
4698 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4699 x_caught_error_message[0] = '\0';
16bd92ea 4700
c118dd06 4701 /* Install our little error handler. */
334208b7 4702 XSetErrorHandler (x_error_catcher);
c118dd06 4703}
16bd92ea 4704
c118dd06
JB
4705/* If any X protocol errors have arrived since the last call to
4706 x_catch_errors or x_check_errors, signal an Emacs error using
4707 sprintf (a buffer, FORMAT, the x error message text) as the text. */
812361a1 4708
c118dd06 4709void
7a13e894
RS
4710x_check_errors (dpy, format)
4711 Display *dpy;
c118dd06
JB
4712 char *format;
4713{
4714 /* Make sure to catch any errors incurred so far. */
7a13e894 4715 XSync (dpy, False);
16bd92ea 4716
cef13e55 4717 if (x_caught_error_message[0])
c118dd06 4718 {
cef13e55 4719 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
dc6f92b8 4720
cef13e55 4721 sprintf (buf, format, x_caught_error_message);
7a13e894 4722 x_uncatch_errors (dpy);
c118dd06
JB
4723 error (buf);
4724 }
4725}
4726
b849c413
RS
4727/* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4728
4729int
7a13e894
RS
4730x_had_errors_p (dpy)
4731 Display *dpy;
b849c413
RS
4732{
4733 /* Make sure to catch any errors incurred so far. */
7a13e894 4734 XSync (dpy, False);
b849c413
RS
4735
4736 return x_caught_error_message[0] != 0;
4737}
4738
812361a1
RS
4739/* Stop catching X protocol errors and let them make Emacs die. */
4740
c118dd06 4741void
7a13e894
RS
4742x_uncatch_errors (dpy)
4743 Display *dpy;
c118dd06 4744{
9ac0d9e0 4745 xfree (x_caught_error_message);
cef13e55 4746 x_caught_error_message = 0;
334208b7 4747 XSetErrorHandler (x_error_quitter);
dc6f92b8
JB
4748}
4749
dc6f92b8
JB
4750#if 0
4751static unsigned int x_wire_count;
4752x_trace_wire ()
4753{
4754 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4755}
c118dd06 4756#endif /* ! 0 */
dc6f92b8
JB
4757
4758\f
f451eb13
JB
4759/* Changing the font of the frame. */
4760
76bcdf39
RS
4761/* Give frame F the font named FONTNAME as its default font, and
4762 return the full name of that font. FONTNAME may be a wildcard
4763 pattern; in that case, we choose some font that fits the pattern.
4764 The return value shows which font we chose. */
4765
b5cf7a0e 4766Lisp_Object
f676886a
JB
4767x_new_font (f, fontname)
4768 struct frame *f;
dc6f92b8
JB
4769 register char *fontname;
4770{
dc6f92b8
JB
4771 int already_loaded;
4772 int n_matching_fonts;
4773 XFontStruct *font_info;
4774 char **font_names;
4775
4776 /* Get a list of all the fonts that match this name. Once we
4777 have a list of matching fonts, we compare them against the fonts
4778 we already have by comparing font ids. */
334208b7 4779 font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
2224a5fc 4780 1024, &n_matching_fonts);
0c94f6ee
JB
4781 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4782 find any matches; font_names == 0 is the only clue. */
4783 if (! font_names)
4784 n_matching_fonts = 0;
4785
5835f860
RS
4786 /* Don't just give up if n_matching_fonts is 0.
4787 Apparently there's a bug on Suns: XListFontsWithInfo can
4788 fail to find a font, but XLoadQueryFont may still find it. */
dc6f92b8 4789
90e65f07 4790 /* See if we've already loaded a matching font. */
5835f860
RS
4791 already_loaded = -1;
4792 if (n_matching_fonts != 0)
4793 {
4794 int i, j;
dc6f92b8 4795
7a13e894 4796 for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
5835f860 4797 for (j = 0; j < n_matching_fonts; j++)
7a13e894
RS
4798 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
4799 || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
5835f860
RS
4800 {
4801 already_loaded = i;
7a13e894 4802 fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
5835f860
RS
4803 goto found_font;
4804 }
4805 }
dc6f92b8 4806 found_font:
58769bee 4807
dc6f92b8 4808 /* If we have, just return it from the table. */
2224a5fc 4809 if (already_loaded >= 0)
7556890b 4810 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
dc6f92b8
JB
4811 /* Otherwise, load the font and add it to the table. */
4812 else
4813 {
9696f58b 4814 int i;
76bcdf39 4815 char *full_name;
dc6f92b8 4816 XFontStruct *font;
7a13e894 4817 int n_fonts;
dc6f92b8 4818
9696f58b 4819 /* Try to find a character-cell font in the list. */
58769bee 4820#if 0
f126bd67 4821 /* A laudable goal, but this isn't how to do it. */
9696f58b
JB
4822 for (i = 0; i < n_matching_fonts; i++)
4823 if (! font_info[i].per_char)
4824 break;
f126bd67
JB
4825#else
4826 i = 0;
4827#endif
9696f58b 4828
5835f860
RS
4829 /* See comment above. */
4830 if (n_matching_fonts != 0)
9696f58b
JB
4831 fontname = font_names[i];
4832
334208b7 4833 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
dc6f92b8 4834 if (! font)
5835f860 4835 {
2224a5fc 4836 /* Free the information from XListFonts. */
5835f860 4837 if (n_matching_fonts)
2224a5fc 4838 XFreeFontNames (font_names);
5835f860
RS
4839 return Qnil;
4840 }
dc6f92b8
JB
4841
4842 /* Do we need to create the table? */
7a13e894 4843 if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
dc6f92b8 4844 {
7a13e894
RS
4845 FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
4846 FRAME_X_DISPLAY_INFO (f)->font_table
4847 = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
4848 * sizeof (struct font_info));
dc6f92b8
JB
4849 }
4850 /* Do we need to grow the table? */
7a13e894
RS
4851 else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
4852 >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
dc6f92b8 4853 {
7a13e894
RS
4854 FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
4855 FRAME_X_DISPLAY_INFO (f)->font_table
4856 = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
4857 (FRAME_X_DISPLAY_INFO (f)->font_table_size
4858 * sizeof (struct font_info)));
dc6f92b8
JB
4859 }
4860
76bcdf39
RS
4861 /* Try to get the full name of FONT. Put it in full_name. */
4862 full_name = 0;
4863 for (i = 0; i < font->n_properties; i++)
4864 {
4865 char *atom
334208b7 4866 = XGetAtomName (FRAME_X_DISPLAY (f), font->properties[i].name);
76bcdf39 4867 if (!strcmp (atom, "FONT"))
7965883b 4868 {
334208b7 4869 char *name = XGetAtomName (FRAME_X_DISPLAY (f),
7965883b
RS
4870 (Atom) (font->properties[i].card32));
4871 char *p = name;
4872 int dashes = 0;
4873
4874 /* Count the number of dashes in the "full name".
4875 If it is too few, this isn't really the font's full name,
4876 so don't use it.
4877 In X11R4, the fonts did not come with their canonical names
4878 stored in them. */
4879 while (*p)
4880 {
4881 if (*p == '-')
4882 dashes++;
4883 p++;
4884 }
4885
4886 if (dashes >= 13)
4887 full_name = name;
8ed24d5a
RS
4888
4889 break;
7965883b
RS
4890 }
4891
76bcdf39
RS
4892 XFree (atom);
4893 }
4894
7a13e894
RS
4895 n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
4896 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
4897 bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
76bcdf39 4898 if (full_name != 0)
7a13e894 4899 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
76bcdf39 4900 else
7a13e894 4901 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
7556890b 4902 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
7a13e894 4903 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
76bcdf39 4904
d53067dc
RS
4905 if (full_name)
4906 fontname = full_name;
dc6f92b8 4907 }
2224a5fc 4908
b2cad826
KH
4909 /* Compute the scroll bar width in character columns. */
4910 if (f->scroll_bar_pixel_width > 0)
4911 {
7556890b 4912 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
4913 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
4914 }
4915 else
4916 f->scroll_bar_cols = 2;
4917
f676886a 4918 /* Now make the frame display the given font. */
c118dd06 4919 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 4920 {
7556890b
RS
4921 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
4922 f->output_data.x->font->fid);
4923 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
4924 f->output_data.x->font->fid);
4925 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
4926 f->output_data.x->font->fid);
f676886a 4927
a27f9f86 4928 frame_update_line_height (f);
0134a210 4929 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 4930 }
a27f9f86
RS
4931 else
4932 /* If we are setting a new frame's font for the first time,
4933 there are no faces yet, so this font's height is the line height. */
7556890b 4934 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 4935
b5cf7a0e 4936 {
abdda982 4937 Lisp_Object lispy_name;
b5cf7a0e 4938
abdda982 4939 lispy_name = build_string (fontname);
b5cf7a0e 4940
2224a5fc 4941 /* Free the information from XListFonts. The data
b5cf7a0e 4942 we actually retain comes from XLoadQueryFont. */
2224a5fc 4943 XFreeFontNames (font_names);
b5cf7a0e
JB
4944
4945 return lispy_name;
4946 }
dc6f92b8 4947}
dc6f92b8 4948\f
43bca5d5 4949x_calc_absolute_position (f)
f676886a 4950 struct frame *f;
dc6f92b8 4951{
6dba1858
RS
4952 Window win, child;
4953 int win_x = 0, win_y = 0;
7556890b 4954 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
4955 int this_window;
4956
4957#ifdef USE_X_TOOLKIT
7556890b 4958 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
4959#else
4960 this_window = FRAME_X_WINDOW (f);
4961#endif
6dba1858
RS
4962
4963 /* Find the position of the outside upper-left corner of
4964 the inner window, with respect to the outer window. */
7556890b 4965 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858
RS
4966 {
4967 BLOCK_INPUT;
334208b7 4968 XTranslateCoordinates (FRAME_X_DISPLAY (f),
58769bee 4969
6dba1858 4970 /* From-window, to-window. */
c81412a0 4971 this_window,
7556890b 4972 f->output_data.x->parent_desc,
6dba1858
RS
4973
4974 /* From-position, to-position. */
4975 0, 0, &win_x, &win_y,
4976
4977 /* Child of win. */
4978 &child);
4979 UNBLOCK_INPUT;
4980 }
4981
4982 /* Treat negative positions as relative to the leftmost bottommost
4983 position that fits on the screen. */
20f55f9a 4984 if (flags & XNegative)
7556890b
RS
4985 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
4986 - 2 * f->output_data.x->border_width - win_x
31ea78fd 4987 - PIXEL_WIDTH (f)
7556890b 4988 + f->output_data.x->left_pos);
dc6f92b8 4989
20f55f9a 4990 if (flags & YNegative)
7556890b
RS
4991 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
4992 - 2 * f->output_data.x->border_width - win_y
31ea78fd 4993 - PIXEL_HEIGHT (f)
c81412a0 4994 - (FRAME_EXTERNAL_MENU_BAR (f)
7556890b
RS
4995 ? f->output_data.x->menubar_height : 0)
4996 + f->output_data.x->top_pos);
3a35ab44
RS
4997 /* The left_pos and top_pos
4998 are now relative to the top and left screen edges,
4999 so the flags should correspond. */
7556890b 5000 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
5001}
5002
3a35ab44
RS
5003/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5004 to really change the position, and 0 when calling from
5005 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
5006 position values). It is -1 when calling from x_set_frame_parameters,
5007 which means, do adjust for borders but don't change the gravity. */
3a35ab44 5008
dc05a16b 5009x_set_offset (f, xoff, yoff, change_gravity)
f676886a 5010 struct frame *f;
dc6f92b8 5011 register int xoff, yoff;
dc05a16b 5012 int change_gravity;
dc6f92b8 5013{
4a4cbdd5
KH
5014 int modified_top, modified_left;
5015
aa3ff7c9 5016 if (change_gravity > 0)
3a35ab44 5017 {
7556890b
RS
5018 f->output_data.x->top_pos = yoff;
5019 f->output_data.x->left_pos = xoff;
5020 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 5021 if (xoff < 0)
7556890b 5022 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 5023 if (yoff < 0)
7556890b
RS
5024 f->output_data.x->size_hint_flags |= YNegative;
5025 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 5026 }
43bca5d5 5027 x_calc_absolute_position (f);
dc6f92b8
JB
5028
5029 BLOCK_INPUT;
c32cdd9a 5030 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 5031
4a4cbdd5
KH
5032 /* It is a mystery why we need to add the border_width here
5033 when the frame is already visible, but experiment says we do. */
7556890b
RS
5034 modified_left = f->output_data.x->left_pos;
5035 modified_top = f->output_data.x->top_pos;
aa3ff7c9 5036 if (change_gravity != 0)
4a4cbdd5 5037 {
7556890b
RS
5038 modified_left += f->output_data.x->border_width;
5039 modified_top += f->output_data.x->border_width;
4a4cbdd5
KH
5040 }
5041
3afe33e7 5042#ifdef USE_X_TOOLKIT
7556890b 5043 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 5044 modified_left, modified_top);
3afe33e7 5045#else /* not USE_X_TOOLKIT */
334208b7 5046 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 5047 modified_left, modified_top);
3afe33e7 5048#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5049 UNBLOCK_INPUT;
5050}
5051
bc20ebbf
FP
5052/* Call this to change the size of frame F's x-window.
5053 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5054 for this size change and subsequent size changes.
5055 Otherwise we leave the window gravity unchanged. */
dc6f92b8 5056
bc20ebbf 5057x_set_window_size (f, change_gravity, cols, rows)
f676886a 5058 struct frame *f;
bc20ebbf 5059 int change_gravity;
b1c884c3 5060 int cols, rows;
dc6f92b8
JB
5061{
5062 int pixelwidth, pixelheight;
5063 int mask;
dc6f92b8 5064
80fd1fe2
FP
5065#ifdef USE_X_TOOLKIT
5066 BLOCK_INPUT;
3a20653d
RS
5067 {
5068 /* The x and y position of the widget is clobbered by the
5069 call to XtSetValues within EmacsFrameSetCharSize.
5070 This is a real kludge, but I don't understand Xt so I can't
5071 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
5072 int xpos = f->output_data.x->widget->core.x;
5073 int ypos = f->output_data.x->widget->core.y;
5074 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
5075 f->output_data.x->widget->core.x = xpos;
5076 f->output_data.x->widget->core.y = ypos;
3a20653d 5077 }
80fd1fe2
FP
5078 UNBLOCK_INPUT;
5079
5080#else /* not USE_X_TOOLKIT */
5081
dc6f92b8
JB
5082 BLOCK_INPUT;
5083
b1c884c3 5084 check_frame_size (f, &rows, &cols);
7556890b 5085 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
5086 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5087 ? 0
5088 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 5089 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 5090 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
f451eb13
JB
5091 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5092 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 5093
7556890b 5094 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 5095 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 5096
334208b7
RS
5097 XSync (FRAME_X_DISPLAY (f), False);
5098 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5099 pixelwidth, pixelheight);
b1c884c3
JB
5100
5101 /* Now, strictly speaking, we can't be sure that this is accurate,
5102 but the window manager will get around to dealing with the size
5103 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
5104 ConfigureNotify event gets here.
5105
5106 We could just not bother storing any of this information here,
5107 and let the ConfigureNotify event set everything up, but that
5108 might be kind of confusing to the lisp code, since size changes
5109 wouldn't be reported in the frame parameters until some random
5110 point in the future when the ConfigureNotify event arrives. */
8922af5f 5111 change_frame_size (f, rows, cols, 0, 0);
b1c884c3
JB
5112 PIXEL_WIDTH (f) = pixelwidth;
5113 PIXEL_HEIGHT (f) = pixelheight;
5114
4d73d038
RS
5115 /* If cursor was outside the new size, mark it as off. */
5116 if (f->phys_cursor_y >= rows
5117 || f->phys_cursor_x >= cols)
5118 {
5119 f->phys_cursor_x = -1;
5120 f->phys_cursor_y = -1;
5121 }
5122
dbc4e1c1
JB
5123 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5124 receive in the ConfigureNotify event; if we get what we asked
5125 for, then the event won't cause the screen to become garbaged, so
5126 we have to make sure to do it here. */
5127 SET_FRAME_GARBAGED (f);
5128
334208b7 5129 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 5130 UNBLOCK_INPUT;
80fd1fe2 5131#endif /* not USE_X_TOOLKIT */
dc6f92b8 5132}
dc6f92b8 5133\f
d047c4eb 5134/* Mouse warping. */
dc6f92b8 5135
9b378208 5136void
f676886a
JB
5137x_set_mouse_position (f, x, y)
5138 struct frame *f;
dc6f92b8
JB
5139 int x, y;
5140{
5141 int pix_x, pix_y;
5142
7556890b
RS
5143 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
5144 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
5145
5146 if (pix_x < 0) pix_x = 0;
5147 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5148
5149 if (pix_y < 0) pix_y = 0;
5150 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
5151
5152 BLOCK_INPUT;
dc6f92b8 5153
334208b7
RS
5154 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5155 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
5156 UNBLOCK_INPUT;
5157}
5158
9b378208
RS
5159/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5160
5161void
5162x_set_mouse_pixel_position (f, pix_x, pix_y)
5163 struct frame *f;
5164 int pix_x, pix_y;
5165{
5166 BLOCK_INPUT;
5167
334208b7
RS
5168 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5169 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
5170 UNBLOCK_INPUT;
5171}
d047c4eb
KH
5172\f
5173/* focus shifting, raising and lowering. */
9b378208 5174
f676886a
JB
5175x_focus_on_frame (f)
5176 struct frame *f;
dc6f92b8 5177{
1fb20991 5178#if 0 /* This proves to be unpleasant. */
f676886a 5179 x_raise_frame (f);
1fb20991 5180#endif
6d4238f3
JB
5181#if 0
5182 /* I don't think that the ICCCM allows programs to do things like this
5183 without the interaction of the window manager. Whatever you end up
f676886a 5184 doing with this code, do it to x_unfocus_frame too. */
334208b7 5185 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 5186 RevertToPointerRoot, CurrentTime);
c118dd06 5187#endif /* ! 0 */
dc6f92b8
JB
5188}
5189
f676886a
JB
5190x_unfocus_frame (f)
5191 struct frame *f;
dc6f92b8 5192{
6d4238f3 5193#if 0
f676886a 5194 /* Look at the remarks in x_focus_on_frame. */
0f941935 5195 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 5196 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 5197 RevertToPointerRoot, CurrentTime);
c118dd06 5198#endif /* ! 0 */
dc6f92b8
JB
5199}
5200
f676886a 5201/* Raise frame F. */
dc6f92b8 5202
f676886a
JB
5203x_raise_frame (f)
5204 struct frame *f;
dc6f92b8 5205{
3a88c238 5206 if (f->async_visible)
dc6f92b8
JB
5207 {
5208 BLOCK_INPUT;
3afe33e7 5209#ifdef USE_X_TOOLKIT
7556890b 5210 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 5211#else /* not USE_X_TOOLKIT */
334208b7 5212 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 5213#endif /* not USE_X_TOOLKIT */
334208b7 5214 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
5215 UNBLOCK_INPUT;
5216 }
5217}
5218
f676886a 5219/* Lower frame F. */
dc6f92b8 5220
f676886a
JB
5221x_lower_frame (f)
5222 struct frame *f;
dc6f92b8 5223{
3a88c238 5224 if (f->async_visible)
dc6f92b8
JB
5225 {
5226 BLOCK_INPUT;
3afe33e7 5227#ifdef USE_X_TOOLKIT
7556890b 5228 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 5229#else /* not USE_X_TOOLKIT */
334208b7 5230 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 5231#endif /* not USE_X_TOOLKIT */
334208b7 5232 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
5233 UNBLOCK_INPUT;
5234 }
5235}
5236
dbc4e1c1
JB
5237static void
5238XTframe_raise_lower (f, raise)
5239 FRAME_PTR f;
5240 int raise;
5241{
5242 if (raise)
5243 x_raise_frame (f);
5244 else
5245 x_lower_frame (f);
5246}
d047c4eb
KH
5247\f
5248/* Change of visibility. */
dc6f92b8 5249
9382638d
KH
5250/* This tries to wait until the frame is really visible.
5251 However, if the window manager asks the user where to position
5252 the frame, this will return before the user finishes doing that.
5253 The frame will not actually be visible at that time,
5254 but it will become visible later when the window manager
5255 finishes with it. */
5256
f676886a
JB
5257x_make_frame_visible (f)
5258 struct frame *f;
dc6f92b8
JB
5259{
5260 int mask;
990ba854 5261 Lisp_Object type;
dc6f92b8 5262
dc6f92b8 5263 BLOCK_INPUT;
dc6f92b8 5264
990ba854
RS
5265 type = x_icon_type (f);
5266 if (!NILP (type))
5267 x_bitmap_icon (f, type);
bdcd49ba 5268
f676886a 5269 if (! FRAME_VISIBLE_P (f))
90e65f07 5270 {
9382638d
KH
5271 /* We test FRAME_GARBAGED_P here to make sure we don't
5272 call x_set_offset a second time
5273 if we get to x_make_frame_visible a second time
5274 before the window gets really visible. */
5275 if (! FRAME_ICONIFIED_P (f)
7556890b
RS
5276 && ! f->output_data.x->asked_for_visible)
5277 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
dc05a16b 5278
7556890b 5279 f->output_data.x->asked_for_visible = 1;
9382638d 5280
90e65f07 5281 if (! EQ (Vx_no_window_manager, Qt))
f676886a 5282 x_wm_set_window_state (f, NormalState);
3afe33e7 5283#ifdef USE_X_TOOLKIT
d7a38a2e 5284 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 5285 XtMapWidget (f->output_data.x->widget);
3afe33e7 5286#else /* not USE_X_TOOLKIT */
7f9c7f94 5287 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 5288#endif /* not USE_X_TOOLKIT */
0134a210
RS
5289#if 0 /* This seems to bring back scroll bars in the wrong places
5290 if the window configuration has changed. They seem
5291 to come back ok without this. */
ab648270 5292 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 5293 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 5294#endif
90e65f07 5295 }
dc6f92b8 5296
334208b7 5297 XFlush (FRAME_X_DISPLAY (f));
90e65f07 5298
0dacf791
RS
5299 /* Synchronize to ensure Emacs knows the frame is visible
5300 before we do anything else. We do this loop with input not blocked
5301 so that incoming events are handled. */
5302 {
5303 Lisp_Object frame;
c0a04927
RS
5304 int count = input_signal_count;
5305
5306 /* This must come after we set COUNT. */
5307 UNBLOCK_INPUT;
5308
e0c1aef2 5309 XSETFRAME (frame, f);
c0a04927
RS
5310
5311 while (1)
2a6cf806 5312 {
334208b7 5313 x_sync (f);
c0a04927
RS
5314 /* Once we have handled input events,
5315 we should have received the MapNotify if one is coming.
5316 So if we have not got it yet, stop looping.
5317 Some window managers make their own decisions
5318 about visibility. */
5319 if (input_signal_count != count)
5320 break;
c12a7cbd 5321 /* Machines that do polling rather than SIGIO have been observed
23cf7c60
KH
5322 to go into a busy-wait here. So we'll fake an alarm signal
5323 to let the handler know that there's something to be read.
5324 We used to raise a real alarm, but it seems that the handler
5325 isn't always enabled here. This is probably a bug. */
8b2f8d4e 5326 if (input_polling_used ())
3b2fa4e6
RS
5327 {
5328 /* It could be confusing if a real alarm arrives while processing
5329 the fake one. Turn it off and let the handler reset it. */
5330 alarm (0);
5331 input_poll_signal ();
5332 }
c0a04927
RS
5333 /* Once we have handled input events,
5334 we should have received the MapNotify if one is coming.
5335 So if we have not got it yet, stop looping.
5336 Some window managers make their own decisions
5337 about visibility. */
5338 if (input_signal_count != count)
5339 break;
2a6cf806 5340 }
0dacf791
RS
5341 FRAME_SAMPLE_VISIBILITY (f);
5342 }
dc6f92b8
JB
5343}
5344
5345/* Change from mapped state to withdrawn state. */
5346
d047c4eb
KH
5347/* Make the frame visible (mapped and not iconified). */
5348
f676886a
JB
5349x_make_frame_invisible (f)
5350 struct frame *f;
dc6f92b8
JB
5351{
5352 int mask;
546e6d5b
RS
5353 Window window;
5354
5355#ifdef USE_X_TOOLKIT
5356 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 5357 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
5358#else /* not USE_X_TOOLKIT */
5359 window = FRAME_X_WINDOW (f);
5360#endif /* not USE_X_TOOLKIT */
dc6f92b8 5361
9319ae23 5362 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
5363 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5364 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 5365
5627c40e 5366#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 5367 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 5368 return;
5627c40e 5369#endif
dc6f92b8
JB
5370
5371 BLOCK_INPUT;
c118dd06 5372
af31d76f
RS
5373 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5374 that the current position of the window is user-specified, rather than
5375 program-specified, so that when the window is mapped again, it will be
5376 placed at the same location, without forcing the user to position it
5377 by hand again (they have already done that once for this window.) */
c32cdd9a 5378 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 5379
c118dd06
JB
5380#ifdef HAVE_X11R4
5381
334208b7
RS
5382 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
5383 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
5384 {
5385 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5386 error ("Can't notify window manager of window withdrawal");
c118dd06 5387 }
c118dd06 5388#else /* ! defined (HAVE_X11R4) */
16bd92ea 5389
c118dd06 5390 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
5391 if (! EQ (Vx_no_window_manager, Qt))
5392 {
16bd92ea 5393 XEvent unmap;
dc6f92b8 5394
16bd92ea 5395 unmap.xunmap.type = UnmapNotify;
546e6d5b 5396 unmap.xunmap.window = window;
334208b7 5397 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 5398 unmap.xunmap.from_configure = False;
334208b7
RS
5399 if (! XSendEvent (FRAME_X_DISPLAY (f),
5400 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
5401 False,
5402 SubstructureRedirectMask|SubstructureNotifyMask,
5403 &unmap))
5404 {
5405 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5406 error ("Can't notify window manager of withdrawal");
16bd92ea 5407 }
dc6f92b8
JB
5408 }
5409
16bd92ea 5410 /* Unmap the window ourselves. Cheeky! */
334208b7 5411 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 5412#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 5413
5627c40e
RS
5414 /* We can't distinguish this from iconification
5415 just by the event that we get from the server.
5416 So we can't win using the usual strategy of letting
5417 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5418 and synchronize with the server to make sure we agree. */
5419 f->visible = 0;
5420 FRAME_ICONIFIED_P (f) = 0;
5421 f->async_visible = 0;
5422 f->async_iconified = 0;
5423
334208b7 5424 x_sync (f);
5627c40e 5425
dc6f92b8
JB
5426 UNBLOCK_INPUT;
5427}
5428
dc6f92b8
JB
5429/* Change window state from mapped to iconified. */
5430
f676886a
JB
5431x_iconify_frame (f)
5432 struct frame *f;
dc6f92b8
JB
5433{
5434 int mask;
3afe33e7 5435 int result;
990ba854 5436 Lisp_Object type;
dc6f92b8 5437
9319ae23 5438 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
5439 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5440 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 5441
3a88c238 5442 if (f->async_iconified)
dc6f92b8
JB
5443 return;
5444
3afe33e7 5445 BLOCK_INPUT;
546e6d5b 5446
990ba854
RS
5447 type = x_icon_type (f);
5448 if (!NILP (type))
5449 x_bitmap_icon (f, type);
bdcd49ba
RS
5450
5451#ifdef USE_X_TOOLKIT
5452
546e6d5b
RS
5453 if (! FRAME_VISIBLE_P (f))
5454 {
5455 if (! EQ (Vx_no_window_manager, Qt))
5456 x_wm_set_window_state (f, IconicState);
5457 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 5458 XtMapWidget (f->output_data.x->widget);
546e6d5b
RS
5459 UNBLOCK_INPUT;
5460 return;
5461 }
5462
334208b7 5463 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 5464 XtWindow (f->output_data.x->widget),
334208b7 5465 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
5466 UNBLOCK_INPUT;
5467
5468 if (!result)
546e6d5b 5469 error ("Can't notify window manager of iconification");
3afe33e7
RS
5470
5471 f->async_iconified = 1;
8c002a25
KH
5472
5473 BLOCK_INPUT;
334208b7 5474 XFlush (FRAME_X_DISPLAY (f));
8c002a25 5475 UNBLOCK_INPUT;
3afe33e7
RS
5476#else /* not USE_X_TOOLKIT */
5477
fd13dbb2
RS
5478 /* Make sure the X server knows where the window should be positioned,
5479 in case the user deiconifies with the window manager. */
5480 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 5481 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 5482
16bd92ea
JB
5483 /* Since we don't know which revision of X we're running, we'll use both
5484 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5485
5486 /* X11R4: send a ClientMessage to the window manager using the
5487 WM_CHANGE_STATE type. */
5488 {
5489 XEvent message;
58769bee 5490
c118dd06 5491 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 5492 message.xclient.type = ClientMessage;
334208b7 5493 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
5494 message.xclient.format = 32;
5495 message.xclient.data.l[0] = IconicState;
5496
334208b7
RS
5497 if (! XSendEvent (FRAME_X_DISPLAY (f),
5498 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
5499 False,
5500 SubstructureRedirectMask | SubstructureNotifyMask,
5501 &message))
dc6f92b8
JB
5502 {
5503 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 5504 error ("Can't notify window manager of iconification");
dc6f92b8 5505 }
16bd92ea 5506 }
dc6f92b8 5507
58769bee 5508 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
5509 IconicState. */
5510 x_wm_set_window_state (f, IconicState);
dc6f92b8 5511
a9c00105
RS
5512 if (!FRAME_VISIBLE_P (f))
5513 {
5514 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 5515 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
5516 }
5517
3a88c238 5518 f->async_iconified = 1;
dc6f92b8 5519
334208b7 5520 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 5521 UNBLOCK_INPUT;
8c002a25 5522#endif /* not USE_X_TOOLKIT */
dc6f92b8 5523}
d047c4eb 5524\f
c0ff3fab 5525/* Destroy the X window of frame F. */
dc6f92b8 5526
c0ff3fab 5527x_destroy_window (f)
f676886a 5528 struct frame *f;
dc6f92b8 5529{
7f9c7f94
RS
5530 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5531
dc6f92b8 5532 BLOCK_INPUT;
c0ff3fab 5533
7556890b
RS
5534 if (f->output_data.x->icon_desc != 0)
5535 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
5536 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 5537#ifdef USE_X_TOOLKIT
7556890b 5538 XtDestroyWidget (f->output_data.x->widget);
9d7e2e3e 5539 free_frame_menubar (f);
3afe33e7
RS
5540#endif /* USE_X_TOOLKIT */
5541
07e34cb0 5542 free_frame_faces (f);
334208b7 5543 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 5544
7556890b
RS
5545 xfree (f->output_data.x);
5546 f->output_data.x = 0;
0f941935
KH
5547 if (f == dpyinfo->x_focus_frame)
5548 dpyinfo->x_focus_frame = 0;
5549 if (f == dpyinfo->x_focus_event_frame)
5550 dpyinfo->x_focus_event_frame = 0;
5551 if (f == dpyinfo->x_highlight_frame)
5552 dpyinfo->x_highlight_frame = 0;
c0ff3fab 5553
7f9c7f94
RS
5554 dpyinfo->reference_count--;
5555
5556 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 5557 {
7f9c7f94
RS
5558 dpyinfo->mouse_face_beg_row
5559 = dpyinfo->mouse_face_beg_col = -1;
5560 dpyinfo->mouse_face_end_row
5561 = dpyinfo->mouse_face_end_col = -1;
5562 dpyinfo->mouse_face_window = Qnil;
dc05a16b 5563 }
0134a210 5564
c0ff3fab 5565 UNBLOCK_INPUT;
dc6f92b8
JB
5566}
5567\f
f451eb13
JB
5568/* Setting window manager hints. */
5569
af31d76f
RS
5570/* Set the normal size hints for the window manager, for frame F.
5571 FLAGS is the flags word to use--or 0 meaning preserve the flags
5572 that the window now has.
5573 If USER_POSITION is nonzero, we set the USPosition
5574 flag (this is useful when FLAGS is 0). */
6dba1858 5575
af31d76f 5576x_wm_set_size_hint (f, flags, user_position)
f676886a 5577 struct frame *f;
af31d76f
RS
5578 long flags;
5579 int user_position;
dc6f92b8
JB
5580{
5581 XSizeHints size_hints;
3afe33e7
RS
5582
5583#ifdef USE_X_TOOLKIT
7e4f2521
FP
5584 Arg al[2];
5585 int ac = 0;
5586 Dimension widget_width, widget_height;
7556890b 5587 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 5588#else /* not USE_X_TOOLKIT */
c118dd06 5589 Window window = FRAME_X_WINDOW (f);
3afe33e7 5590#endif /* not USE_X_TOOLKIT */
dc6f92b8 5591
b72a58fd
RS
5592 /* Setting PMaxSize caused various problems. */
5593 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 5594
f676886a
JB
5595 flexlines = f->height;
5596
7556890b
RS
5597 size_hints.x = f->output_data.x->left_pos;
5598 size_hints.y = f->output_data.x->top_pos;
7553a6b7 5599
7e4f2521
FP
5600#ifdef USE_X_TOOLKIT
5601 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5602 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 5603 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
5604 size_hints.height = widget_height;
5605 size_hints.width = widget_width;
5606#else /* not USE_X_TOOLKIT */
f676886a
JB
5607 size_hints.height = PIXEL_HEIGHT (f);
5608 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 5609#endif /* not USE_X_TOOLKIT */
7553a6b7 5610
7556890b
RS
5611 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
5612 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
5613 size_hints.max_width
5614 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
5615 size_hints.max_height
5616 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 5617
d067ea8b
KH
5618 /* Calculate the base and minimum sizes.
5619
5620 (When we use the X toolkit, we don't do it here.
5621 Instead we copy the values that the widgets are using, below.) */
5622#ifndef USE_X_TOOLKIT
b1c884c3 5623 {
b0342f17 5624 int base_width, base_height;
0134a210 5625 int min_rows = 0, min_cols = 0;
b0342f17 5626
f451eb13
JB
5627 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5628 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 5629
0134a210 5630 check_frame_size (f, &min_rows, &min_cols);
b0342f17 5631
0134a210
RS
5632 /* The window manager uses the base width hints to calculate the
5633 current number of rows and columns in the frame while
5634 resizing; min_width and min_height aren't useful for this
5635 purpose, since they might not give the dimensions for a
5636 zero-row, zero-column frame.
58769bee 5637
0134a210
RS
5638 We use the base_width and base_height members if we have
5639 them; otherwise, we set the min_width and min_height members
5640 to the size for a zero x zero frame. */
b0342f17
JB
5641
5642#ifdef HAVE_X11R4
0134a210
RS
5643 size_hints.flags |= PBaseSize;
5644 size_hints.base_width = base_width;
5645 size_hints.base_height = base_height;
5646 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5647 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 5648#else
0134a210
RS
5649 size_hints.min_width = base_width;
5650 size_hints.min_height = base_height;
b0342f17 5651#endif
b1c884c3 5652 }
dc6f92b8 5653
d067ea8b 5654 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 5655 if (flags)
dc6f92b8 5656 {
d067ea8b
KH
5657 size_hints.flags |= flags;
5658 goto no_read;
5659 }
5660#endif /* not USE_X_TOOLKIT */
5661
5662 {
5663 XSizeHints hints; /* Sometimes I hate X Windows... */
5664 long supplied_return;
5665 int value;
af31d76f
RS
5666
5667#ifdef HAVE_X11R4
d067ea8b
KH
5668 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5669 &supplied_return);
af31d76f 5670#else
d067ea8b 5671 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 5672#endif
58769bee 5673
d067ea8b
KH
5674#ifdef USE_X_TOOLKIT
5675 size_hints.base_height = hints.base_height;
5676 size_hints.base_width = hints.base_width;
5677 size_hints.min_height = hints.min_height;
5678 size_hints.min_width = hints.min_width;
5679#endif
5680
5681 if (flags)
5682 size_hints.flags |= flags;
5683 else
5684 {
5685 if (value == 0)
5686 hints.flags = 0;
5687 if (hints.flags & PSize)
5688 size_hints.flags |= PSize;
5689 if (hints.flags & PPosition)
5690 size_hints.flags |= PPosition;
5691 if (hints.flags & USPosition)
5692 size_hints.flags |= USPosition;
5693 if (hints.flags & USSize)
5694 size_hints.flags |= USSize;
5695 }
5696 }
5697
5698 no_read:
0134a210 5699
af31d76f 5700#ifdef PWinGravity
7556890b 5701 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 5702 size_hints.flags |= PWinGravity;
dc05a16b 5703
af31d76f 5704 if (user_position)
6dba1858 5705 {
af31d76f
RS
5706 size_hints.flags &= ~ PPosition;
5707 size_hints.flags |= USPosition;
6dba1858 5708 }
2554751d 5709#endif /* PWinGravity */
6dba1858 5710
b0342f17 5711#ifdef HAVE_X11R4
334208b7 5712 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 5713#else
334208b7 5714 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 5715#endif
dc6f92b8
JB
5716}
5717
5718/* Used for IconicState or NormalState */
f676886a
JB
5719x_wm_set_window_state (f, state)
5720 struct frame *f;
dc6f92b8
JB
5721 int state;
5722{
3afe33e7 5723#ifdef USE_X_TOOLKIT
546e6d5b
RS
5724 Arg al[1];
5725
5726 XtSetArg (al[0], XtNinitialState, state);
7556890b 5727 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 5728#else /* not USE_X_TOOLKIT */
c118dd06 5729 Window window = FRAME_X_WINDOW (f);
dc6f92b8 5730
7556890b
RS
5731 f->output_data.x->wm_hints.flags |= StateHint;
5732 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 5733
7556890b 5734 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 5735#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5736}
5737
7f2ae036 5738x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 5739 struct frame *f;
7f2ae036 5740 int pixmap_id;
dc6f92b8 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
7f2ae036 5748 if (pixmap_id > 0)
dbc4e1c1 5749 {
7a13e894 5750 Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 5751 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
5752 }
5753 else
68568555
RS
5754 {
5755 /* It seems there is no way to turn off use of an icon pixmap.
5756 The following line does it, only if no icon has yet been created,
5757 for some window managers. But with mwm it crashes.
5758 Some people say it should clear the IconPixmapHint bit in this case,
5759 but that doesn't work, and the X consortium said it isn't the
5760 right thing at all. Since there is no way to win,
5761 best to explicitly give up. */
5762#if 0
5763 f->output_data.x->wm_hints.icon_pixmap = None;
5764#else
5765 return;
5766#endif
5767 }
b1c884c3 5768
7556890b
RS
5769 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5770 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
5771}
5772
f676886a
JB
5773x_wm_set_icon_position (f, icon_x, icon_y)
5774 struct frame *f;
dc6f92b8
JB
5775 int icon_x, icon_y;
5776{
75231bad 5777#ifdef USE_X_TOOLKIT
7556890b 5778 Window window = XtWindow (f->output_data.x->widget);
75231bad 5779#else
c118dd06 5780 Window window = FRAME_X_WINDOW (f);
75231bad 5781#endif
dc6f92b8 5782
7556890b
RS
5783 f->output_data.x->wm_hints.flags |= IconPositionHint;
5784 f->output_data.x->wm_hints.icon_x = icon_x;
5785 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 5786
7556890b 5787 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
5788}
5789
5790\f
f451eb13
JB
5791/* Initialization. */
5792
3afe33e7
RS
5793#ifdef USE_X_TOOLKIT
5794static XrmOptionDescRec emacs_options[] = {
5795 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5796 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5797
5798 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5799 XrmoptionSepArg, NULL},
5800 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5801
5802 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5803 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5804 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5805 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5806 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5807 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5808 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5809};
5810#endif /* USE_X_TOOLKIT */
5811
7a13e894
RS
5812static int x_initialized;
5813
29b38361
KH
5814#ifdef MULTI_KBOARD
5815/* Test whether two display-name strings agree up to the dot that separates
5816 the screen number from the server number. */
5817static int
5818same_x_server (name1, name2)
5819 char *name1, *name2;
5820{
5821 int seen_colon = 0;
5822 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
5823 {
5824 if (*name1 == ':')
5825 seen_colon++;
5826 if (seen_colon && *name1 == '.')
5827 return 1;
5828 }
5829 return (seen_colon
5830 && (*name1 == '.' || *name1 == '\0')
5831 && (*name2 == '.' || *name2 == '\0'));
5832}
5833#endif
5834
334208b7 5835struct x_display_info *
1f8255f2 5836x_term_init (display_name, xrm_option, resource_name)
334208b7 5837 Lisp_Object display_name;
1f8255f2
RS
5838 char *xrm_option;
5839 char *resource_name;
dc6f92b8 5840{
f676886a 5841 Lisp_Object frame;
dc6f92b8 5842 char *defaultvalue;
334208b7 5843 int connection;
7a13e894 5844 Display *dpy;
334208b7
RS
5845 struct x_display_info *dpyinfo;
5846 XrmDatabase xrdb;
5847
60439948
KH
5848 BLOCK_INPUT;
5849
7a13e894
RS
5850 if (!x_initialized)
5851 {
5852 x_initialize ();
5853 x_initialized = 1;
5854 }
dc6f92b8 5855
6c183ba5
RS
5856#ifdef HAVE_X_I18N
5857 setlocale (LC_ALL, NULL);
5858#endif
5859
3afe33e7 5860#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
5861 /* weiner@footloose.sps.mot.com reports that this causes
5862 errors with X11R5:
5863 X protocol error: BadAtom (invalid Atom parameter)
5864 on protocol request 18skiloaf.
5865 So let's not use it until R6. */
5866#ifdef HAVE_X11XTR6
bdcd49ba
RS
5867 XtSetLanguageProc (NULL, NULL, NULL);
5868#endif
5869
7f9c7f94
RS
5870 {
5871 int argc = 0;
5872 char *argv[3];
5873
5874 argv[0] = "";
5875 argc = 1;
5876 if (xrm_option)
5877 {
5878 argv[argc++] = "-xrm";
5879 argv[argc++] = xrm_option;
5880 }
5881 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
5882 resource_name, EMACS_CLASS,
5883 emacs_options, XtNumber (emacs_options),
5884 &argc, argv);
39d8bb4d
KH
5885
5886#ifdef HAVE_X11XTR6
5887 setlocale (LC_NUMERIC, "C");
5888 setlocale (LC_TIME, "C");
5889#endif
7f9c7f94 5890 }
3afe33e7
RS
5891
5892#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
5893#ifdef HAVE_X11R5
5894 XSetLocaleModifiers ("");
5895#endif
7a13e894 5896 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 5897#endif /* not USE_X_TOOLKIT */
334208b7 5898
7a13e894
RS
5899 /* Detect failure. */
5900 if (dpy == 0)
60439948
KH
5901 {
5902 UNBLOCK_INPUT;
5903 return 0;
5904 }
7a13e894
RS
5905
5906 /* We have definitely succeeded. Record the new connection. */
5907
5908 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
5909
29b38361
KH
5910#ifdef MULTI_KBOARD
5911 {
5912 struct x_display_info *share;
5913 Lisp_Object tail;
5914
5915 for (share = x_display_list, tail = x_display_name_list; share;
5916 share = share->next, tail = XCONS (tail)->cdr)
5917 if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
5918 XSTRING (display_name)->data))
5919 break;
5920 if (share)
5921 dpyinfo->kboard = share->kboard;
5922 else
5923 {
5924 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
5925 init_kboard (dpyinfo->kboard);
59e755be
KH
5926 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
5927 {
5928 char *vendor = ServerVendor (dpy);
5929 dpyinfo->kboard->Vsystem_key_alist
5930 = call1 (Qvendor_specific_keysyms,
5931 build_string (vendor ? vendor : ""));
5932 }
5933
29b38361
KH
5934 dpyinfo->kboard->next_kboard = all_kboards;
5935 all_kboards = dpyinfo->kboard;
0ad5446c
KH
5936 /* Don't let the initial kboard remain current longer than necessary.
5937 That would cause problems if a file loaded on startup tries to
5938 prompt in the minibuffer. */
5939 if (current_kboard == initial_kboard)
5940 current_kboard = dpyinfo->kboard;
29b38361
KH
5941 }
5942 dpyinfo->kboard->reference_count++;
5943 }
b9737ad3
KH
5944#endif
5945
7a13e894
RS
5946 /* Put this display on the chain. */
5947 dpyinfo->next = x_display_list;
5948 x_display_list = dpyinfo;
5949
5950 /* Put it on x_display_name_list as well, to keep them parallel. */
5951 x_display_name_list = Fcons (Fcons (display_name, Qnil),
5952 x_display_name_list);
5953 dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
5954
5955 dpyinfo->display = dpy;
dc6f92b8 5956
dc6f92b8 5957#if 0
7a13e894 5958 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 5959#endif /* ! 0 */
7a13e894
RS
5960
5961 dpyinfo->x_id_name
5962 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
5963 + XSTRING (Vsystem_name)->size
5964 + 2);
5965 sprintf (dpyinfo->x_id_name, "%s@%s",
5966 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
5967
5968 /* Figure out which modifier bits mean what. */
334208b7 5969 x_find_modifier_meanings (dpyinfo);
f451eb13 5970
ab648270 5971 /* Get the scroll bar cursor. */
7a13e894 5972 dpyinfo->vertical_scroll_bar_cursor
334208b7 5973 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 5974
334208b7
RS
5975 xrdb = x_load_resources (dpyinfo->display, xrm_option,
5976 resource_name, EMACS_CLASS);
5977#ifdef HAVE_XRMSETDATABASE
5978 XrmSetDatabase (dpyinfo->display, xrdb);
5979#else
5980 dpyinfo->display->db = xrdb;
5981#endif
547d9db8 5982 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
5983 all versions. */
5984 dpyinfo->xrdb = xrdb;
334208b7
RS
5985
5986 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
5987 DefaultScreen (dpyinfo->display));
5988 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
5989 &dpyinfo->n_planes);
5990 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
5991 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
5992 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
5993 dpyinfo->grabbed = 0;
5994 dpyinfo->reference_count = 0;
5995 dpyinfo->icon_bitmap_id = -1;
7a13e894
RS
5996 dpyinfo->n_fonts = 0;
5997 dpyinfo->font_table_size = 0;
5998 dpyinfo->bitmaps = 0;
5999 dpyinfo->bitmaps_size = 0;
6000 dpyinfo->bitmaps_last = 0;
6001 dpyinfo->scratch_cursor_gc = 0;
6002 dpyinfo->mouse_face_mouse_frame = 0;
6003 dpyinfo->mouse_face_deferred_gc = 0;
6004 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6005 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6006 dpyinfo->mouse_face_face_id = 0;
6007 dpyinfo->mouse_face_window = Qnil;
6008 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
6009 dpyinfo->mouse_face_defer = 0;
0f941935
KH
6010 dpyinfo->x_focus_frame = 0;
6011 dpyinfo->x_focus_event_frame = 0;
6012 dpyinfo->x_highlight_frame = 0;
334208b7
RS
6013
6014 dpyinfo->Xatom_wm_protocols
6015 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
6016 dpyinfo->Xatom_wm_take_focus
6017 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
6018 dpyinfo->Xatom_wm_save_yourself
6019 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
6020 dpyinfo->Xatom_wm_delete_window
6021 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
6022 dpyinfo->Xatom_wm_change_state
6023 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
6024 dpyinfo->Xatom_wm_configure_denied
6025 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
6026 dpyinfo->Xatom_wm_window_moved
6027 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
6028 dpyinfo->Xatom_editres
6029 = XInternAtom (dpyinfo->display, "Editres", False);
6030 dpyinfo->Xatom_CLIPBOARD
6031 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
6032 dpyinfo->Xatom_TIMESTAMP
6033 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
6034 dpyinfo->Xatom_TEXT
6035 = XInternAtom (dpyinfo->display, "TEXT", False);
6036 dpyinfo->Xatom_DELETE
6037 = XInternAtom (dpyinfo->display, "DELETE", False);
6038 dpyinfo->Xatom_MULTIPLE
6039 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
6040 dpyinfo->Xatom_INCR
6041 = XInternAtom (dpyinfo->display, "INCR", False);
6042 dpyinfo->Xatom_EMACS_TMP
6043 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
6044 dpyinfo->Xatom_TARGETS
6045 = XInternAtom (dpyinfo->display, "TARGETS", False);
6046 dpyinfo->Xatom_NULL
6047 = XInternAtom (dpyinfo->display, "NULL", False);
6048 dpyinfo->Xatom_ATOM_PAIR
6049 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
6050
547d9db8
KH
6051 dpyinfo->cut_buffers_initialized = 0;
6052
334208b7
RS
6053 connection = ConnectionNumber (dpyinfo->display);
6054 dpyinfo->connection = connection;
6055
87485d6f
MW
6056#ifdef subprocesses
6057 /* This is only needed for distinguishing keyboard and process input. */
334208b7 6058 if (connection != 0)
7a13e894 6059 add_keyboard_wait_descriptor (connection);
87485d6f 6060#endif
6d4238f3 6061
041b69ac 6062#ifndef F_SETOWN_BUG
dc6f92b8 6063#ifdef F_SETOWN
dc6f92b8 6064#ifdef F_SETOWN_SOCK_NEG
61c3ce62 6065 /* stdin is a socket here */
334208b7 6066 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 6067#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 6068 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
6069#endif /* ! defined (F_SETOWN_SOCK_NEG) */
6070#endif /* ! defined (F_SETOWN) */
041b69ac 6071#endif /* F_SETOWN_BUG */
dc6f92b8
JB
6072
6073#ifdef SIGIO
eee20f6a
KH
6074 if (interrupt_input)
6075 init_sigio (connection);
c118dd06 6076#endif /* ! defined (SIGIO) */
dc6f92b8 6077
60439948
KH
6078 UNBLOCK_INPUT;
6079
7a13e894
RS
6080 return dpyinfo;
6081}
6082\f
6083/* Get rid of display DPYINFO, assuming all frames are already gone,
6084 and without sending any more commands to the X server. */
dc6f92b8 6085
7a13e894
RS
6086void
6087x_delete_display (dpyinfo)
6088 struct x_display_info *dpyinfo;
6089{
6090 delete_keyboard_wait_descriptor (dpyinfo->connection);
6091
6092 /* Discard this display from x_display_name_list and x_display_list.
6093 We can't use Fdelq because that can quit. */
6094 if (! NILP (x_display_name_list)
6095 && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
6096 x_display_name_list = XCONS (x_display_name_list)->cdr;
6097 else
6098 {
6099 Lisp_Object tail;
6100
6101 tail = x_display_name_list;
6102 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
6103 {
6104 if (EQ (XCONS (XCONS (tail)->cdr)->car,
6105 dpyinfo->name_list_element))
6106 {
6107 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
6108 break;
6109 }
6110 tail = XCONS (tail)->cdr;
6111 }
6112 }
6113
6114 if (x_display_list == dpyinfo)
6115 x_display_list = dpyinfo->next;
7f9c7f94
RS
6116 else
6117 {
6118 struct x_display_info *tail;
7a13e894 6119
7f9c7f94
RS
6120 for (tail = x_display_list; tail; tail = tail->next)
6121 if (tail->next == dpyinfo)
6122 tail->next = tail->next->next;
6123 }
7a13e894 6124
0d777288
RS
6125#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6126#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
6127 XrmDestroyDatabase (dpyinfo->xrdb);
6128#endif
0d777288 6129#endif
29b38361
KH
6130#ifdef MULTI_KBOARD
6131 if (--dpyinfo->kboard->reference_count == 0)
39f79001 6132 delete_kboard (dpyinfo->kboard);
b9737ad3
KH
6133#endif
6134 xfree (dpyinfo->font_table);
6135 xfree (dpyinfo->x_id_name);
6136 xfree (dpyinfo);
7a13e894
RS
6137}
6138\f
6139/* Set up use of X before we make the first connection. */
6140
6141x_initialize ()
6142{
f676886a 6143 clear_frame_hook = XTclear_frame;
dc6f92b8
JB
6144 clear_end_of_line_hook = XTclear_end_of_line;
6145 ins_del_lines_hook = XTins_del_lines;
6146 change_line_highlight_hook = XTchange_line_highlight;
6147 insert_glyphs_hook = XTinsert_glyphs;
6148 write_glyphs_hook = XTwrite_glyphs;
6149 delete_glyphs_hook = XTdelete_glyphs;
6150 ring_bell_hook = XTring_bell;
6151 reset_terminal_modes_hook = XTreset_terminal_modes;
6152 set_terminal_modes_hook = XTset_terminal_modes;
6153 update_begin_hook = XTupdate_begin;
6154 update_end_hook = XTupdate_end;
6155 set_terminal_window_hook = XTset_terminal_window;
6156 read_socket_hook = XTread_socket;
b8009dd1 6157 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8
JB
6158 cursor_to_hook = XTcursor_to;
6159 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 6160 mouse_position_hook = XTmouse_position;
f451eb13 6161 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 6162 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
6163 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6164 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6165 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6166 judge_scroll_bars_hook = XTjudge_scroll_bars;
58769bee 6167
f676886a 6168 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
6169 char_ins_del_ok = 0; /* just as fast to write the line */
6170 line_ins_del_ok = 1; /* we'll just blt 'em */
6171 fast_clear_end_of_line = 1; /* X does this well */
58769bee 6172 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
6173 off the bottom */
6174 baud_rate = 19200;
6175
7a13e894
RS
6176 x_noop_count = 0;
6177
b30b24cb
RS
6178 /* Try to use interrupt input; if we can't, then start polling. */
6179 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6180
7f9c7f94
RS
6181#ifdef USE_X_TOOLKIT
6182 XtToolkitInitialize ();
6183 Xt_app_con = XtCreateApplicationContext ();
665881ad 6184 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
7f9c7f94
RS
6185#endif
6186
58769bee 6187 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 6188 original error handler. */
334208b7
RS
6189 XSetErrorHandler (x_error_quitter);
6190 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8
JB
6191
6192 /* Disable Window Change signals; they are handled by X events. */
6193#ifdef SIGWINCH
6194 signal (SIGWINCH, SIG_DFL);
c118dd06 6195#endif /* ! defined (SIGWINCH) */
dc6f92b8 6196
92e2441b 6197 signal (SIGPIPE, x_connection_signal);
dc6f92b8 6198}
55123275
JB
6199
6200void
6201syms_of_xterm ()
6202{
7a13e894
RS
6203 staticpro (&x_display_name_list);
6204 x_display_name_list = Qnil;
334208b7 6205
ab648270 6206 staticpro (&last_mouse_scroll_bar);
e53cb100 6207 last_mouse_scroll_bar = Qnil;
59e755be
KH
6208
6209 staticpro (&Qvendor_specific_keysyms);
6210 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
55123275 6211}
c118dd06 6212#endif /* ! defined (HAVE_X_WINDOWS) */