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