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