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