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