* xfns.c: Clear out the old face stuff.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
5116f055 2 Copyright (C) 1989, 1993 Free Software Foundation, Inc.
dc6f92b8
JB
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
4746118a 8the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20/* Serious problems:
21
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
25
26*/
27
d56a553a
RS
28#define NEW_SELECTIONS
29
039440c4
RS
30/* On 4.3 these lose if they come after xterm.h. */
31/* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32/* Putting these at the beginning seems to be standard for other .c files. */
33#include <stdio.h>
34#include <signal.h>
35
dc6f92b8
JB
36#include "config.h"
37
38#ifdef HAVE_X_WINDOWS
39
40#include "lisp.h"
9ac0d9e0 41#include "blockinput.h"
dc6f92b8 42
dc6f92b8
JB
43/* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
45#include "xterm.h"
f451eb13 46#include <X11/cursorfont.h>
dc6f92b8 47
16bd92ea 48#ifndef USG
dc6f92b8
JB
49/* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
51#ifndef makedev
52#include <sys/types.h>
c118dd06
JB
53#endif /* makedev */
54#endif /* USG */
dc6f92b8
JB
55
56#ifdef BSD
57#include <sys/ioctl.h>
58#include <strings.h>
c118dd06 59#else /* ! defined (BSD) */
febf25d5 60#ifndef VMS
dc6f92b8
JB
61#include <sys/termio.h>
62#include <string.h>
febf25d5 63#endif
c118dd06 64#endif /* ! defined (BSD) */
dc6f92b8
JB
65
66/* Allow m- file to inhibit use of FIONREAD. */
67#ifdef BROKEN_FIONREAD
68#undef FIONREAD
c118dd06 69#endif /* ! defined (BROKEN_FIONREAD) */
dc6f92b8
JB
70
71/* We are unable to use interrupts if FIONREAD is not available,
72 so flush SIGIO so we won't try. */
73#ifndef FIONREAD
74#ifdef SIGIO
75#undef SIGIO
c118dd06
JB
76#endif /* ! defined (SIGIO) */
77#endif /* FIONREAD */
dc6f92b8 78
3a2712f9 79#include "systime.h"
dc6f92b8
JB
80
81#include <fcntl.h>
dc6f92b8
JB
82#include <ctype.h>
83#include <errno.h>
84#include <setjmp.h>
85#include <sys/stat.h>
86#include <sys/param.h>
87
88#include "dispextern.h"
89#include "termhooks.h"
90#include "termopts.h"
91#include "termchar.h"
92#if 0
93#include "sink.h"
94#include "sinkmask.h"
c118dd06 95#endif /* ! 0 */
dc6f92b8 96#include "gnu.h"
f676886a 97#include "frame.h"
dc6f92b8 98#include "disptab.h"
dc6f92b8 99#include "buffer.h"
f451eb13 100#include "window.h"
dc6f92b8
JB
101
102#ifdef HAVE_X11
103#define XMapWindow XMapRaised /* Raise them when mapping. */
c118dd06 104#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
105#include <X/Xkeyboard.h>
106/*#include <X/Xproto.h> */
c118dd06 107#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
108
109/* For sending Meta-characters. Do we need this? */
110#define METABIT 0200
111
112#define min(a,b) ((a)<(b) ? (a) : (b))
113#define max(a,b) ((a)>(b) ? (a) : (b))
114
115/* Nonzero means we must reprint all windows
116 because 1) we received an ExposeWindow event
f451eb13 117 or 2) we received too many ExposeRegion events to record.
dc6f92b8 118
f451eb13 119 This is never needed under X11. */
dc6f92b8
JB
120static int expose_all_windows;
121
122/* Nonzero means we must reprint all icon windows. */
123
124static int expose_all_icons;
125
126#ifndef HAVE_X11
127/* ExposeRegion events, when received, are copied into this queue
128 for later processing. */
129
130static struct event_queue x_expose_queue;
131
132/* ButtonPressed and ButtonReleased events, when received,
133 are copied into this queue for later processing. */
134
135struct event_queue x_mouse_queue;
c118dd06 136#endif /* HAVE_X11 */
dc6f92b8 137
dc6f92b8
JB
138#if defined (SIGIO) && defined (FIONREAD)
139int BLOCK_INPUT_mask;
c118dd06 140#endif /* ! defined (SIGIO) && defined (FIONREAD) */
dc6f92b8 141
dc6f92b8
JB
142/* The id of a bitmap used for icon windows.
143 One such map is shared by all Emacs icon windows.
144 This is zero if we have not yet had a need to create the bitmap. */
145
146static Bitmap icon_bitmap;
147
148/* Font used for text icons. */
149
150static FONT_TYPE *icon_font_info;
151
152/* Stuff for dealing with the main icon title. */
153
154extern Lisp_Object Vcommand_line_args;
60fb3ee1 155char *hostname, *x_id_name;
dc6f92b8
JB
156
157/* This is the X connection that we are using. */
158
159Display *x_current_display;
160
ab648270
JB
161/* The cursor to use for vertical scroll bars on x_current_display. */
162static Cursor x_vertical_scroll_bar_cursor;
f451eb13 163
987d2ad1 164/* Frame being updated by update_frame. This is declared in term.c.
d0386f2a 165 This is set by update_begin and looked at by all the
dc6f92b8 166 XT functions. It is zero while not inside an update.
f676886a
JB
167 In that case, the XT functions assume that `selected_frame'
168 is the frame to apply to. */
d0386f2a 169extern struct frame *updating_frame;
dc6f92b8 170
f676886a 171/* The frame (if any) which has the X window that has keyboard focus.
f451eb13
JB
172 Zero if none. This is examined by Ffocus_frame in frame.c. Note
173 that a mere EnterNotify event can set this; if you need to know the
174 last frame specified in a FocusIn or FocusOut event, use
175 x_focus_event_frame. */
f676886a 176struct frame *x_focus_frame;
dc6f92b8 177
f451eb13
JB
178/* The last frame mentioned in a FocusIn or FocusOut event. This is
179 separate from x_focus_frame, because whether or not LeaveNotify
180 events cause us to lose focus depends on whether or not we have
181 received a FocusIn event for it. */
182struct frame *x_focus_event_frame;
183
f676886a
JB
184/* The frame which currently has the visual highlight, and should get
185 keyboard input (other sorts of input have the frame encoded in the
186 event). It points to the X focus frame's selected window's
187 frame. It differs from x_focus_frame when we're using a global
6d4238f3 188 minibuffer. */
f676886a 189static struct frame *x_highlight_frame;
6d4238f3 190
dc6f92b8 191/* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
f676886a 192 mouse is moved to inside of frame when frame is de-iconified. */
dc6f92b8
JB
193
194static int warp_mouse_on_deiconify;
195
196/* During an update, maximum vpos for ins/del line operations to affect. */
197
198static int flexlines;
199
200/* During an update, nonzero if chars output now should be highlighted. */
201
202static int highlight;
203
204/* Nominal cursor position -- where to draw output.
205 During an update, these are different from the cursor-box position. */
206
207static int curs_x;
208static int curs_y;
209
210#ifdef HAVE_X11
211/* `t' if a mouse button is depressed. */
212
213extern Lisp_Object Vmouse_depressed;
214
215/* Tells if a window manager is present or not. */
216
217extern Lisp_Object Vx_no_window_manager;
218
219/* Timestamp that we requested selection data was made. */
220extern Time requestor_time;
221
222/* ID of the window requesting selection data. */
223extern Window requestor_window;
224
225/* Nonzero enables some debugging for the X interface code. */
226extern int _Xdebug;
227
c118dd06 228#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
229
230/* Bit patterns for the mouse cursor. */
231
232short MouseCursor[] = {
233 0x0000, 0x0008, 0x0018, 0x0038,
234 0x0078, 0x00f8, 0x01f8, 0x03f8,
235 0x07f8, 0x00f8, 0x00d8, 0x0188,
236 0x0180, 0x0300, 0x0300, 0x0000};
237
238short MouseMask[] = {
239 0x000c, 0x001c, 0x003c, 0x007c,
240 0x00fc, 0x01fc, 0x03fc, 0x07fc,
241 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
242 0x03cc, 0x0780, 0x0780, 0x0300};
243
244static short grey_bits[] = {
245 0x0005, 0x000a, 0x0005, 0x000a};
246
247static Pixmap GreyPixmap = 0;
c118dd06 248#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
249
250/* From time to time we get info on an Emacs window, here. */
251
252static WINDOWINFO_TYPE windowinfo;
253
254extern int errno;
255
dfeccd2d 256/* A mask of extra modifier bits to put into every keyboard char. */
64bb1782
RS
257extern int extra_keyboard_modifiers;
258
dc6f92b8
JB
259extern Display *XOpenDisplay ();
260extern Window XCreateWindow ();
261
262extern Cursor XCreateCursor ();
263extern FONT_TYPE *XOpenFont ();
264
265static void flashback ();
266
267#ifndef HAVE_X11
268static void dumpqueue ();
c118dd06 269#endif /* HAVE_X11 */
dc6f92b8
JB
270
271void dumpborder ();
4746118a
JB
272static int XTcursor_to ();
273static int XTclear_end_of_line ();
16bd92ea
JB
274
275\f
f451eb13
JB
276/* Starting and ending updates.
277
278 These hooks are called by update_frame at the beginning and end
f676886a
JB
279 of a frame update. We record in `updating_frame' the identity
280 of the frame being updated, so that the XT... functions do not
281 need to take a frame as argument. Most of the XT... functions
dc6f92b8
JB
282 should never be called except during an update, the only exceptions
283 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
284
285extern int mouse_track_top, mouse_track_left, mouse_track_width;
286
287static
f676886a
JB
288XTupdate_begin (f)
289 struct frame *f;
dc6f92b8
JB
290{
291 int mask;
292
f676886a 293 if (f == 0)
dc6f92b8
JB
294 abort ();
295
f676886a 296 flexlines = f->height;
dc6f92b8
JB
297 highlight = 0;
298
dc6f92b8
JB
299 BLOCK_INPUT;
300#ifndef HAVE_X11
301 dumpqueue ();
c118dd06 302#endif /* HAVE_X11 */
dc6f92b8
JB
303 UNBLOCK_INPUT;
304}
305
f451eb13 306#ifndef HAVE_X11
dc6f92b8 307static void x_do_pending_expose ();
f451eb13 308#endif
dc6f92b8
JB
309
310static
f676886a
JB
311XTupdate_end (f)
312 struct frame *f;
dc6f92b8
JB
313{
314 int mask;
315
f676886a
JB
316 if (updating_frame == 0
317 || updating_frame != f)
dc6f92b8
JB
318 abort ();
319
320 BLOCK_INPUT;
321#ifndef HAVE_X11
322 dumpqueue ();
dc6f92b8 323 x_do_pending_expose ();
f451eb13 324#endif /* HAVE_X11 */
dc6f92b8 325
f676886a 326 x_display_cursor (f, 1);
dc6f92b8 327
dc6f92b8
JB
328 XFlushQueue ();
329 UNBLOCK_INPUT;
330}
331\f
332/* External interface to control of standout mode.
333 Call this when about to modify line at position VPOS
334 and not change whether it is highlighted. */
335
336XTreassert_line_highlight (new, vpos)
337 int new, vpos;
338{
339 highlight = new;
340}
341
342/* Call this when about to modify line at position VPOS
343 and change whether it is highlighted. */
344
345static
346XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
347 int new_highlight, vpos, first_unused_hpos;
348{
349 highlight = new_highlight;
350 XTcursor_to (vpos, 0);
f676886a 351 XTclear_end_of_line (updating_frame->width);
dc6f92b8
JB
352}
353
354/* This is used when starting Emacs and when restarting after suspend.
355 When starting Emacs, no X window is mapped. And nothing must be done
356 to Emacs's own window if it is suspended (though that rarely happens). */
357
358static
359XTset_terminal_modes ()
360{
361}
362
363/* This is called when exiting or suspending Emacs.
364 Exiting will make the X-windows go away, and suspending
365 requires no action. */
366
367static
368XTreset_terminal_modes ()
369{
f676886a 370/* XTclear_frame (); */
dc6f92b8
JB
371}
372\f
f451eb13
JB
373/* Set the nominal cursor position of the frame.
374 This is where display update commands will take effect.
dc6f92b8
JB
375 This does not affect the place where the cursor-box is displayed. */
376
4746118a 377static int
dc6f92b8
JB
378XTcursor_to (row, col)
379 register int row, col;
380{
381 int mask;
382 int orow = row;
383
384 curs_x = col;
385 curs_y = row;
386
f676886a 387 if (updating_frame == 0)
dc6f92b8
JB
388 {
389 BLOCK_INPUT;
f676886a 390 x_display_cursor (selected_frame, 1);
dc6f92b8
JB
391 XFlushQueue ();
392 UNBLOCK_INPUT;
393 }
394}
395\f
396/* Display a sequence of N glyphs found at GP.
397 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
398 HL is 1 if this text is highlighted, 2 if the cursor is on it.
399
07e34cb0 400 FONT is the default font to use (for glyphs whose font-code is 0).
dc6f92b8 401
07e34cb0
JB
402 Since the display generation code is responsible for calling
403 compute_char_face and compute_glyph_face on everything it puts in
404 the display structure, we can assume that the face code on each
405 glyph is a valid index into FRAME_FACES (f), and the one to which
406 we can actually apply intern_face. */
dc6f92b8 407
07e34cb0
JB
408#if 1
409/* This is the multi-face code. */
dc6f92b8 410
dc6f92b8 411static void
07e34cb0 412dumpglyphs (f, left, top, gp, n, hl)
f676886a 413 struct frame *f;
dc6f92b8
JB
414 int left, top;
415 register GLYPH *gp; /* Points to first GLYPH. */
416 register int n; /* Number of glyphs to display. */
417 int hl;
dc6f92b8 418{
07e34cb0
JB
419 /* Holds characters to be displayed. */
420 char *buf = (char *) alloca (f->width * sizeof (*buf));
dc6f92b8
JB
421 register char *cp; /* Steps through buf[]. */
422 register int tlen = GLYPH_TABLE_LENGTH;
423 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
c118dd06 424 Window window = FRAME_X_WINDOW (f);
dc6f92b8 425
07e34cb0
JB
426 extern struct face *intern_face (/* FRAME_PTR, struct face * */);
427
428 while (n > 0)
dc6f92b8
JB
429 {
430 /* Get the face-code of the next GLYPH. */
431 int cf, len;
432 int g = *gp;
433
07e34cb0
JB
434 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
435 cf = GLYPH_FACE (g);
dc6f92b8
JB
436
437 /* Find the run of consecutive glyphs with the same face-code.
438 Extract their character codes into BUF. */
439 cp = buf;
440 while (n > 0)
441 {
442 g = *gp;
07e34cb0
JB
443 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
444 if (GLYPH_FACE (g) != cf)
dc6f92b8
JB
445 break;
446
07e34cb0 447 *cp++ = GLYPH_CHAR (g);
dc6f92b8
JB
448 --n;
449 ++gp;
450 }
451
452 /* LEN gets the length of the run. */
453 len = cp - buf;
454
455 /* Now output this run of chars, with the font and pixel values
456 determined by the face code CF. */
07e34cb0
JB
457 {
458 struct face *face = FRAME_DEFAULT_FACE (f);
459 FONT_TYPE *font = FACE_FONT (face);
460 GC gc = FACE_GC (face);
b73b6aaf
RS
461 int defaulted = 1;
462 int gc_temporary = 0;
07e34cb0 463
b73b6aaf
RS
464 /* First look at the face of the text itself. */
465 if (cf != 0)
07e34cb0
JB
466 {
467 /* The face codes on the glyphs must be valid indices into the
468 frame's face table. */
469 if (cf < 0 || cf >= FRAME_N_FACES (f))
470 abort ();
471
472 if (cf == 1)
473 face = FRAME_MODE_LINE_FACE (f);
474 else
4a4dc352 475 face = intern_face (f, FRAME_FACES (f) [cf]);
07e34cb0
JB
476 font = FACE_FONT (face);
477 gc = FACE_GC (face);
b73b6aaf 478 defaulted = 0;
07e34cb0 479 }
4a4dc352
JB
480
481 /* Then comes the distinction between modeline and normal text. */
07e34cb0
JB
482 else if (hl == 0)
483 ;
484 else if (hl == 1)
485 {
486 face = FRAME_MODE_LINE_FACE (f);
487 font = FACE_FONT (face);
488 gc = FACE_GC (face);
b73b6aaf
RS
489 defaulted = 0;
490 }
491
492#define FACE_DEFAULT (~0)
493
494 /* Now override that if the cursor's on this character. */
495 if (hl == 2 && (defaulted
496 || !(face->font && (int) face->font != FACE_DEFAULT)))
497 {
498 gc = f->display.x->cursor_gc;
499 }
500 /* Cursor on non-default face: must merge. */
501 else if (hl == 2)
502 {
503 XGCValues xgcv;
504 unsigned long mask;
505
506 xgcv.background = f->display.x->cursor_pixel;
507 xgcv.foreground = f->display.x->cursor_foreground_pixel;
508 xgcv.font = face->font->fid;
509 xgcv.graphics_exposures = 0;
510 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
511 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
512 mask, &xgcv);
513#if 0
514 if (face->stipple && face->stipple != FACE_DEFAULT)
515 XSetStipple (x_current_display, gc, face->stipple);
516#endif
517 gc_temporary = 1;
07e34cb0 518 }
07e34cb0
JB
519
520 XDrawImageString (x_current_display, window, gc,
521 left, top + FONT_BASE (font), buf, len);
07e34cb0 522
b73b6aaf
RS
523 if (gc_temporary)
524 XFreeGC (x_current_display, gc);
525
07e34cb0
JB
526 /* We should probably check for XA_UNDERLINE_POSITION and
527 XA_UNDERLINE_THICKNESS properties on the font, but let's
528 just get the thing working, and come back to that. */
dc6f92b8 529 {
4a4dc352 530 int underline_position = 1;
07e34cb0 531
4a4dc352
JB
532 if (font->descent <= underline_position)
533 underline_position = font->descent - 1;
07e34cb0
JB
534
535 if (face->underline)
536 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
537 FACE_GC (face),
538 left, (top
539 + FONT_BASE (font)
540 + underline_position),
541 len * FONT_WIDTH (font), 1);
dc6f92b8 542 }
07e34cb0
JB
543
544 left += len * FONT_WIDTH (font);
545 }
dc6f92b8
JB
546 }
547}
07e34cb0
JB
548#endif /* 1 */
549
550#if 0
551/* This is the old single-face code. */
552
553static void
554dumpglyphs (f, left, top, gp, n, hl, font)
555 struct frame *f;
556 int left, top;
557 register GLYPH *gp; /* Points to first GLYPH. */
558 register int n; /* Number of glyphs to display. */
559 int hl;
560 FONT_TYPE *font;
561{
562 register int len;
563 Window window = FRAME_X_WINDOW (f);
564 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
565 : (hl ? f->display.x->reverse_gc
566 : f->display.x->normal_gc));
567
568 if (sizeof (GLYPH) == sizeof (XChar2b))
569 XDrawImageString16 (x_current_display, window, drawing_gc,
570 left, top + FONT_BASE (font), (XChar2b *) gp, n);
571 else if (sizeof (GLYPH) == sizeof (unsigned char))
572 XDrawImageString (x_current_display, window, drawing_gc,
573 left, top + FONT_BASE (font), (char *) gp, n);
574 else
575 /* What size of glyph ARE you using? And does X have a function to
576 draw them? */
577 abort ();
578}
579#endif
dc6f92b8 580\f
f451eb13
JB
581/* Output some text at the nominal frame cursor position.
582 Advance the cursor over the text.
dc6f92b8
JB
583 Output LEN glyphs at START.
584
585 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
586 controls the pixel values used for foreground and background. */
587
588static
589XTwrite_glyphs (start, len)
590 register GLYPH *start;
591 int len;
592{
593 register int temp_length;
594 int mask;
f676886a 595 struct frame *f;
dc6f92b8
JB
596
597 BLOCK_INPUT;
598
f676886a
JB
599 f = updating_frame;
600 if (f == 0)
dc6f92b8 601 {
f676886a 602 f = selected_frame;
dc6f92b8 603 /* If not within an update,
f676886a
JB
604 output at the frame's visible cursor. */
605 curs_x = f->cursor_x;
606 curs_y = f->cursor_y;
dc6f92b8
JB
607 }
608
f676886a 609 dumpglyphs (f,
12ba150f
JB
610 CHAR_TO_PIXEL_COL (f, curs_x),
611 CHAR_TO_PIXEL_ROW (f, curs_y),
07e34cb0 612 start, len, highlight);
90e65f07
JB
613
614 /* If we drew on top of the cursor, note that it is turned off. */
f676886a
JB
615 if (curs_y == f->phys_cursor_y
616 && curs_x <= f->phys_cursor_x
617 && curs_x + len > f->phys_cursor_x)
618 f->phys_cursor_x = -1;
dc6f92b8 619
f676886a 620 if (updating_frame == 0)
dc6f92b8 621 {
f676886a
JB
622 f->cursor_x += len;
623 x_display_cursor (f, 1);
624 f->cursor_x -= len;
dc6f92b8
JB
625 }
626 else
627 curs_x += len;
628
629 UNBLOCK_INPUT;
630}
631\f
f451eb13
JB
632/* Clear to the end of the line.
633 Erase the current text line from the nominal cursor position (inclusive)
dc6f92b8
JB
634 to column FIRST_UNUSED (exclusive). The idea is that everything
635 from FIRST_UNUSED onward is already erased. */
636
4746118a 637static int
dc6f92b8
JB
638XTclear_end_of_line (first_unused)
639 register int first_unused;
640{
f676886a 641 struct frame *f = updating_frame;
dc6f92b8
JB
642 int mask;
643
f676886a 644 if (f == 0)
dc6f92b8
JB
645 abort ();
646
f676886a 647 if (curs_y < 0 || curs_y >= f->height)
dc6f92b8
JB
648 return;
649 if (first_unused <= 0)
650 return;
651
f676886a
JB
652 if (first_unused >= f->width)
653 first_unused = f->width;
dc6f92b8
JB
654
655 BLOCK_INPUT;
656
90e65f07 657 /* Notice if the cursor will be cleared by this operation. */
f676886a
JB
658 if (curs_y == f->phys_cursor_y
659 && curs_x <= f->phys_cursor_x
660 && f->phys_cursor_x < first_unused)
661 f->phys_cursor_x = -1;
dc6f92b8
JB
662
663#ifdef HAVE_X11
c118dd06 664 XClearArea (x_current_display, FRAME_X_WINDOW (f),
12ba150f
JB
665 CHAR_TO_PIXEL_COL (f, curs_x),
666 CHAR_TO_PIXEL_ROW (f, curs_y),
f676886a
JB
667 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
668 FONT_HEIGHT (f->display.x->font), False);
dc6f92b8 669
c118dd06
JB
670#else /* ! defined (HAVE_X11) */
671 XPixSet (FRAME_X_WINDOW (f),
12ba150f
JB
672 CHAR_TO_PIXEL_COL (f, curs_x),
673 CHAR_TO_PIXEL_ROW (f, curs_y),
f676886a
JB
674 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
675 FONT_HEIGHT (f->display.x->font),
676 f->display.x->background_pixel);
c118dd06 677#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
678
679 UNBLOCK_INPUT;
680}
681
682static
f676886a 683XTclear_frame ()
dc6f92b8
JB
684{
685 int mask;
f676886a 686 struct frame *f = updating_frame;
dc6f92b8 687
f676886a
JB
688 if (f == 0)
689 f = selected_frame;
dc6f92b8 690
f676886a 691 f->phys_cursor_x = -1; /* Cursor not visible. */
dc6f92b8
JB
692 curs_x = 0; /* Nominal cursor position is top left. */
693 curs_y = 0;
694
695 BLOCK_INPUT;
dbc4e1c1 696
c118dd06 697 XClear (FRAME_X_WINDOW (f));
dbc4e1c1 698
ab648270 699 /* We have to clear the scroll bars, too. If we have changed
dbc4e1c1 700 colors or something like that, then they should be notified. */
ab648270 701 x_scroll_bar_clear (f);
dbc4e1c1 702
dc6f92b8 703#ifndef HAVE_X11
f676886a 704 dumpborder (f, 0);
c118dd06 705#endif /* HAVE_X11 */
dbc4e1c1 706
dc6f92b8
JB
707 XFlushQueue ();
708 UNBLOCK_INPUT;
709}
710\f
dbc4e1c1
JB
711/* Invert the middle quarter of the frame for .15 sec. */
712
713/* We use the select system call to do the waiting, so we have to make sure
714 it's avaliable. If it isn't, we just won't do visual bells. */
715#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
716
717/* Subtract the `struct timeval' values X and Y,
718 storing the result in RESULT.
719 Return 1 if the difference is negative, otherwise 0. */
720
721static int
722timeval_subtract (result, x, y)
723 struct timeval *result, x, y;
724{
725 /* Perform the carry for the later subtraction by updating y.
726 This is safer because on some systems
727 the tv_sec member is unsigned. */
728 if (x.tv_usec < y.tv_usec)
729 {
730 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
731 y.tv_usec -= 1000000 * nsec;
732 y.tv_sec += nsec;
733 }
734 if (x.tv_usec - y.tv_usec > 1000000)
735 {
736 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
737 y.tv_usec += 1000000 * nsec;
738 y.tv_sec -= nsec;
739 }
740
741 /* Compute the time remaining to wait. tv_usec is certainly positive. */
742 result->tv_sec = x.tv_sec - y.tv_sec;
743 result->tv_usec = x.tv_usec - y.tv_usec;
744
745 /* Return indication of whether the result should be considered negative. */
746 return x.tv_sec < y.tv_sec;
747}
dc6f92b8 748
f676886a
JB
749XTflash (f)
750 struct frame *f;
dc6f92b8 751{
dbc4e1c1 752 BLOCK_INPUT;
dc6f92b8 753
dbc4e1c1
JB
754 {
755 GC gc;
dc6f92b8 756
dbc4e1c1
JB
757 /* Create a GC that will use the GXxor function to flip foreground pixels
758 into background pixels. */
759 {
760 XGCValues values;
dc6f92b8 761
dbc4e1c1
JB
762 values.function = GXxor;
763 values.foreground = (f->display.x->foreground_pixel
764 ^ f->display.x->background_pixel);
765
766 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
767 GCFunction | GCForeground, &values);
768 }
dc6f92b8 769
dbc4e1c1
JB
770 {
771 int width = PIXEL_WIDTH (f);
772 int height = PIXEL_HEIGHT (f);
dc6f92b8 773
dbc4e1c1
JB
774 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
775 width/4, height/4, width/2, height/2);
776 XFlush (x_current_display);
dc6f92b8 777
dbc4e1c1
JB
778 {
779 struct timeval wakeup, now;
dc6f92b8 780
dbc4e1c1 781 gettimeofday (&wakeup, (struct timezone *) 0);
dc6f92b8 782
dbc4e1c1
JB
783 /* Compute time to wait until, propagating carry from usecs. */
784 wakeup.tv_usec += 150000;
785 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
786 wakeup.tv_usec %= 1000000;
787
788 /* Keep waiting until past the time wakeup. */
789 while (1)
790 {
791 struct timeval timeout;
792
793 gettimeofday (&timeout, (struct timezone *)0);
794
795 /* In effect, timeout = wakeup - timeout.
796 Break if result would be negative. */
797 if (timeval_subtract (&timeout, wakeup, timeout))
798 break;
799
800 /* Try to wait that long--but we might wake up sooner. */
801 select (0, 0, 0, 0, &timeout);
802 }
803 }
804
805 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
806 width/4, height/4, width/2, height/2);
807 XFreeGC (x_current_display, gc);
808 XFlush (x_current_display);
dc6f92b8 809 }
dbc4e1c1
JB
810 }
811
812 UNBLOCK_INPUT;
dc6f92b8
JB
813}
814
dbc4e1c1
JB
815#endif
816
817
dc6f92b8
JB
818/* Make audible bell. */
819
820#ifdef HAVE_X11
821#define XRINGBELL XBell(x_current_display, 0)
c118dd06 822#else /* ! defined (HAVE_X11) */
dc6f92b8 823#define XRINGBELL XFeep(0);
c118dd06 824#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
825
826XTring_bell ()
827{
dbc4e1c1 828#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
dc6f92b8 829 if (visible_bell)
f676886a 830 XTflash (selected_frame);
dc6f92b8 831 else
dbc4e1c1 832#endif
dc6f92b8
JB
833 {
834 BLOCK_INPUT;
835 XRINGBELL;
836 XFlushQueue ();
837 UNBLOCK_INPUT;
838 }
839}
840\f
f451eb13
JB
841/* Insert and delete character.
842 These are not supposed to be used because we are supposed to turn
843 off the feature of using them. */
dc6f92b8
JB
844
845static
846XTinsert_glyphs (start, len)
847 register char *start;
848 register int len;
849{
850 abort ();
851}
852
853static
854XTdelete_glyphs (n)
855 register int n;
856{
857 abort ();
858}
859\f
860/* Specify how many text lines, from the top of the window,
861 should be affected by insert-lines and delete-lines operations.
862 This, and those operations, are used only within an update
863 that is bounded by calls to XTupdate_begin and XTupdate_end. */
864
865static
866XTset_terminal_window (n)
867 register int n;
868{
f676886a 869 if (updating_frame == 0)
dc6f92b8
JB
870 abort ();
871
f676886a
JB
872 if ((n <= 0) || (n > updating_frame->height))
873 flexlines = updating_frame->height;
dc6f92b8
JB
874 else
875 flexlines = n;
876}
877\f
f451eb13
JB
878/* Perform an insert-lines operation.
879 Insert N lines at a vertical position curs_y. */
dc6f92b8
JB
880
881static void
882stufflines (n)
883 register int n;
884{
885 register int topregion, bottomregion;
886 register int length, newtop, mask;
f676886a
JB
887 register struct frame *f = updating_frame;
888 int intborder = f->display.x->internal_border_width;
dc6f92b8
JB
889
890 if (curs_y >= flexlines)
891 return;
892
893 topregion = curs_y;
894 bottomregion = flexlines - (n + 1);
895 newtop = topregion + n;
896 length = (bottomregion - topregion) + 1;
897
898#ifndef HAVE_X11
899 dumpqueue ();
c118dd06 900#endif /* HAVE_X11 */
dc6f92b8
JB
901
902 if ((length > 0) && (newtop <= flexlines))
903 {
904#ifdef HAVE_X11
c118dd06
JB
905 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
906 FRAME_X_WINDOW (f), f->display.x->normal_gc,
12ba150f 907 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
f676886a
JB
908 f->width * FONT_WIDTH (f->display.x->font),
909 length * FONT_HEIGHT (f->display.x->font), intborder,
12ba150f 910 CHAR_TO_PIXEL_ROW (f, newtop));
c118dd06
JB
911#else /* ! defined (HAVE_X11) */
912 XMoveArea (FRAME_X_WINDOW (f),
12ba150f
JB
913 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
914 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
f676886a
JB
915 f->width * FONT_WIDTH (f->display.x->font),
916 length * FONT_HEIGHT (f->display.x->font));
dc6f92b8
JB
917 /* Now we must process any ExposeRegion events that occur
918 if the area being copied from is obscured.
919 We can't let it wait because further i/d operations
920 may want to copy this area to another area. */
921 x_read_exposes ();
c118dd06 922#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
923 }
924
925 newtop = min (newtop, (flexlines - 1));
926 length = newtop - topregion;
927 if (length > 0)
928 {
929#ifdef HAVE_X11
c118dd06 930 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
12ba150f 931 CHAR_TO_PIXEL_ROW (f, topregion),
f676886a
JB
932 f->width * FONT_WIDTH (f->display.x->font),
933 n * FONT_HEIGHT (f->display.x->font), False);
c118dd06
JB
934#else /* ! defined (HAVE_X11) */
935 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 936 intborder,
12ba150f 937 CHAR_TO_PIXEL_ROW (f, topregion),
f676886a
JB
938 f->width * FONT_WIDTH (f->display.x->font),
939 n * FONT_HEIGHT (f->display.x->font),
940 f->display.x->background_pixel);
c118dd06 941#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
942 }
943}
944
945/* Perform a delete-lines operation, deleting N lines
946 at a vertical position curs_y. */
947
948static void
949scraplines (n)
950 register int n;
951{
952 int mask;
f676886a
JB
953 register struct frame *f = updating_frame;
954 int intborder = f->display.x->internal_border_width;
dc6f92b8
JB
955
956 if (curs_y >= flexlines)
957 return;
958
959#ifndef HAVE_X11
960 dumpqueue ();
c118dd06 961#endif /* HAVE_X11 */
dc6f92b8
JB
962
963 if ((curs_y + n) >= flexlines)
964 {
965 if (flexlines >= (curs_y + 1))
966 {
967#ifdef HAVE_X11
c118dd06 968 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
12ba150f 969 CHAR_TO_PIXEL_ROW (f, curs_y),
f676886a
JB
970 f->width * FONT_WIDTH (f->display.x->font),
971 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
c118dd06
JB
972#else /* ! defined (HAVE_X11) */
973 XPixSet (FRAME_X_WINDOW (f),
12ba150f 974 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
f676886a
JB
975 f->width * FONT_WIDTH (f->display.x->font),
976 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
977 f->display.x->background_pixel);
c118dd06 978#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
979 }
980 }
981 else
982 {
983#ifdef HAVE_X11
c118dd06
JB
984 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
985 FRAME_X_WINDOW (f), f->display.x->normal_gc,
dc6f92b8 986 intborder,
12ba150f 987 CHAR_TO_PIXEL_ROW (f, curs_y + n),
f676886a
JB
988 f->width * FONT_WIDTH (f->display.x->font),
989 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
12ba150f 990 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
c118dd06 991 XClearArea (x_current_display, FRAME_X_WINDOW (f),
dc6f92b8 992 intborder,
12ba150f 993 CHAR_TO_PIXEL_ROW (f, flexlines - n),
f676886a
JB
994 f->width * FONT_WIDTH (f->display.x->font),
995 n * FONT_HEIGHT (f->display.x->font), False);
c118dd06
JB
996#else /* ! defined (HAVE_X11) */
997 XMoveArea (FRAME_X_WINDOW (f),
dc6f92b8 998 intborder,
12ba150f
JB
999 CHAR_TO_PIXEL_ROW (f, curs_y + n),
1000 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
f676886a
JB
1001 f->width * FONT_WIDTH (f->display.x->font),
1002 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
dc6f92b8
JB
1003 /* Now we must process any ExposeRegion events that occur
1004 if the area being copied from is obscured.
1005 We can't let it wait because further i/d operations
1006 may want to copy this area to another area. */
1007 x_read_exposes ();
c118dd06 1008 XPixSet (FRAME_X_WINDOW (f), intborder,
12ba150f 1009 CHAR_TO_PIXEL_ROW (f, flexlines - n),
f676886a
JB
1010 f->width * FONT_WIDTH (f->display.x->font),
1011 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
c118dd06 1012#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
1013 }
1014}
1015
1016/* Perform an insert-lines or delete-lines operation,
1017 inserting N lines or deleting -N lines at vertical position VPOS. */
1018
1019XTins_del_lines (vpos, n)
1020 int vpos, n;
1021{
f676886a 1022 if (updating_frame == 0)
dc6f92b8
JB
1023 abort ();
1024
90e65f07 1025 /* Hide the cursor. */
f676886a 1026 x_display_cursor (updating_frame, 0);
dc6f92b8
JB
1027
1028 XTcursor_to (vpos, 0);
1029
1030 BLOCK_INPUT;
1031 if (n >= 0)
1032 stufflines (n);
1033 else
1034 scraplines (-n);
1035 XFlushQueue ();
1036 UNBLOCK_INPUT;
1037}
1038\f
f451eb13 1039/* Support routines for exposure events. */
dc6f92b8
JB
1040static void clear_cursor ();
1041
f676886a
JB
1042/* Output into a rectangle of an X-window (for frame F)
1043 the characters in f->phys_lines that overlap that rectangle.
dc6f92b8
JB
1044 TOP and LEFT are the position of the upper left corner of the rectangle.
1045 ROWS and COLS are the size of the rectangle. */
1046
1047static void
f676886a
JB
1048dumprectangle (f, left, top, cols, rows)
1049 struct frame *f;
dc6f92b8
JB
1050 register int left, top, cols, rows;
1051{
f676886a 1052 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
dc6f92b8
JB
1053 int cursor_cleared = 0;
1054 int bottom, right;
1055 register int y;
1056
f676886a 1057 if (FRAME_GARBAGED_P (f))
dc6f92b8
JB
1058 return;
1059
dc6f92b8
JB
1060 /* Express rectangle as four edges, instead of position-and-size. */
1061 bottom = top + rows;
1062 right = left + cols;
1063
1064#ifndef HAVE_X11 /* Window manger does this for X11. */
12ba150f
JB
1065 {
1066 int intborder = f->display.x->internal_border_width;
1067
1068 /* If the rectangle includes any of the internal border area,
1069 redisplay the border emphasis. */
1070 if (top < intborder || left < intborder
1071 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1072 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1073 dumpborder (f, 0);
1074 }
c118dd06 1075#endif /* HAVE_X11 /* Window manger does this for X11. */ */
dc6f92b8
JB
1076
1077 /* Convert rectangle edges in pixels to edges in chars.
1078 Round down for left and top, up for right and bottom. */
12ba150f
JB
1079 top = PIXEL_TO_CHAR_ROW (f, top);
1080 left = PIXEL_TO_CHAR_COL (f, left);
f676886a
JB
1081 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1082 right += (FONT_WIDTH (f->display.x->font) - 1);
12ba150f
JB
1083 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1084 right = PIXEL_TO_CHAR_COL (f, right);
dc6f92b8
JB
1085
1086 /* Clip the rectangle to what can be visible. */
1087 if (left < 0)
1088 left = 0;
1089 if (top < 0)
1090 top = 0;
f676886a
JB
1091 if (right > f->width)
1092 right = f->width;
1093 if (bottom > f->height)
1094 bottom = f->height;
dc6f92b8
JB
1095
1096 /* Get size in chars of the rectangle. */
1097 cols = right - left;
1098 rows = bottom - top;
1099
1100 /* If rectangle has zero area, return. */
1101 if (rows <= 0) return;
1102 if (cols <= 0) return;
1103
1104 /* Turn off the cursor if it is in the rectangle.
1105 We will turn it back on afterward. */
f676886a
JB
1106 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1107 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
dc6f92b8 1108 {
f676886a 1109 clear_cursor (f);
dc6f92b8
JB
1110 cursor_cleared = 1;
1111 }
1112
1113 /* Display the text in the rectangle, one text line at a time. */
1114
1115 for (y = top; y < bottom; y++)
1116 {
f676886a 1117 GLYPH *line = &active_frame->glyphs[y][left];
dc6f92b8 1118
f676886a 1119 if (! active_frame->enable[y] || left > active_frame->used[y])
dc6f92b8
JB
1120 continue;
1121
f676886a 1122 dumpglyphs (f,
12ba150f
JB
1123 CHAR_TO_PIXEL_COL (f, left),
1124 CHAR_TO_PIXEL_ROW (f, y),
1125 line, min (cols, active_frame->used[y] - left),
07e34cb0 1126 active_frame->highlight[y]);
dc6f92b8
JB
1127 }
1128
1129 /* Turn the cursor on if we turned it off. */
1130
1131 if (cursor_cleared)
f676886a 1132 x_display_cursor (f, 1);
dc6f92b8
JB
1133}
1134
1135#ifndef HAVE_X11
1136/* Process all queued ExposeRegion events. */
1137
1138static void
1139dumpqueue ()
1140{
1141 register int i;
1142 XExposeRegionEvent r;
1143
1144 while (dequeue_event (&r, &x_expose_queue))
1145 {
f676886a
JB
1146 struct frame *f = x_window_to_frame (r.window);
1147 if (f->display.x->icon_desc == r.window)
1148 refreshicon (f);
dc6f92b8 1149 else
f676886a 1150 dumprectangle (f, r.x, r.y, r.width, r.height);
dc6f92b8
JB
1151 }
1152 XFlushQueue ();
1153}
c118dd06 1154#endif /* HAVE_X11 */
dc6f92b8 1155\f
f451eb13 1156/* Process all expose events that are pending, for X10.
f676886a
JB
1157 Redraws the cursor if necessary on any frame that
1158 is not in the process of being updated with update_frame. */
dc6f92b8 1159
f451eb13 1160#ifndef HAVE_X11
dc6f92b8
JB
1161static void
1162x_do_pending_expose ()
1163{
1164 int mask;
f676886a
JB
1165 struct frame *f;
1166 Lisp_Object tail, frame;
dc6f92b8
JB
1167
1168 if (expose_all_windows)
1169 {
1170 expose_all_windows = 0;
f676886a 1171 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
dc6f92b8
JB
1172 {
1173 register int temp_width, temp_height;
1174 int intborder;
1175
f676886a 1176 frame = XCONS (tail)->car;
ab648270 1177 if (XGCTYPE (frame) != Lisp_Frame)
dc6f92b8 1178 continue;
f676886a 1179 f = XFRAME (frame);
b1c884c3 1180 if (! FRAME_X_P (f))
dc6f92b8 1181 continue;
3a88c238 1182 if (!f->async_visible)
dc6f92b8 1183 continue;
f676886a 1184 if (!f->display.x->needs_exposure)
dc6f92b8
JB
1185 continue;
1186
f676886a 1187 intborder = f->display.x->internal_border_width;
dc6f92b8 1188
f676886a 1189 clear_cursor (f);
c118dd06 1190 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
dc6f92b8 1191 temp_width = ((windowinfo.width - 2 * intborder
ab648270 1192 - f->display.x->v_scroll_bar_width)
f676886a 1193 / FONT_WIDTH (f->display.x->font));
dc6f92b8 1194 temp_height = ((windowinfo.height- 2 * intborder
ab648270 1195 - f->display.x->h_scroll_bar_height)
f676886a
JB
1196 / FONT_HEIGHT (f->display.x->font));
1197 if (temp_width != f->width || temp_height != f->height)
dc6f92b8 1198 {
f676886a 1199 change_frame_size (f, max (1, temp_height),
b1c884c3 1200 max (1, temp_width), 0, 1);
ab648270 1201 x_resize_scroll_bars (f);
dc6f92b8 1202 }
f676886a
JB
1203 f->display.x->left_pos = windowinfo.x;
1204 f->display.x->top_pos = windowinfo.y;
1205 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
dc6f92b8 1206#if 0
f676886a 1207 dumpborder (f, 0);
c118dd06 1208#endif /* ! 0 */
f676886a
JB
1209 f->display.x->needs_exposure = 0;
1210 if (updating_frame != f)
1211 x_display_cursor (f, 1);
dc6f92b8
JB
1212 XFlushQueue ();
1213 }
1214 }
1215 else
1216 /* Handle any individual-rectangle expose events queued
1217 for various windows. */
1218#ifdef HAVE_X11
1219 ;
c118dd06 1220#else /* ! defined (HAVE_X11) */
dc6f92b8 1221 dumpqueue ();
c118dd06 1222#endif /* ! defined (HAVE_X11) */
dc6f92b8 1223}
f451eb13 1224#endif
dc6f92b8
JB
1225
1226#ifdef HAVE_X11
1227static void
f676886a
JB
1228frame_highlight (frame)
1229 struct frame *frame;
dc6f92b8
JB
1230{
1231 if (! EQ (Vx_no_window_manager, Qnil))
c118dd06 1232 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
f676886a
JB
1233 frame->display.x->border_pixel);
1234 x_display_cursor (frame, 1);
dc6f92b8
JB
1235}
1236
1237static void
f676886a
JB
1238frame_unhighlight (frame)
1239 struct frame *frame;
dc6f92b8
JB
1240{
1241 if (! EQ (Vx_no_window_manager, Qnil))
c118dd06 1242 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
f676886a
JB
1243 frame->display.x->border_tile);
1244 x_display_cursor (frame, 1);
dc6f92b8 1245}
c118dd06 1246#else /* ! defined (HAVE_X11) */
f676886a
JB
1247/* Dump the border-emphasis of frame F.
1248 If F is selected, this is a lining of the same color as the border,
dc6f92b8 1249 just within the border, occupying a portion of the internal border.
f676886a 1250 If F is not selected, it is background in the same place.
dc6f92b8
JB
1251 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1252
f676886a 1253 ALWAYS = 1 is used when a frame becomes selected or deselected.
dc6f92b8
JB
1254 In that case, we also turn the cursor off and on again
1255 so it will appear in the proper shape (solid if selected; else hollow.) */
1256
1257static void
f676886a
JB
1258dumpborder (f, always)
1259 struct frame *f;
dc6f92b8
JB
1260 int always;
1261{
f676886a
JB
1262 int thickness = f->display.x->internal_border_width / 2;
1263 int width = PIXEL_WIDTH (f);
1264 int height = PIXEL_HEIGHT (f);
dc6f92b8
JB
1265 int pixel;
1266
f676886a 1267 if (f != selected_frame)
dc6f92b8
JB
1268 {
1269 if (!always)
1270 return;
1271
f676886a 1272 pixel = f->display.x->background_pixel;
dc6f92b8
JB
1273 }
1274 else
1275 {
f676886a 1276 pixel = f->display.x->border_pixel;
dc6f92b8
JB
1277 }
1278
c118dd06
JB
1279 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1280 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1281 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
dc6f92b8 1282 thickness, pixel);
c118dd06 1283 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
dc6f92b8
JB
1284 height, pixel);
1285
1286 if (always)
f676886a 1287 x_display_cursor (f, 1);
dc6f92b8 1288}
c118dd06 1289#endif /* ! defined (HAVE_X11) */
dc6f92b8 1290
f676886a 1291static void XTframe_rehighlight ();
6d4238f3 1292
f676886a
JB
1293/* The focus has changed. Update the frames as necessary to reflect
1294 the new situation. Note that we can't change the selected frame
dc6f92b8 1295 here, because the lisp code we are interrupting might become confused.
f676886a 1296 Each event gets marked with the frame in which it occured, so the
6d4238f3 1297 lisp code can tell when the switch took place by examining the events. */
dc6f92b8 1298
6d4238f3 1299static void
f676886a
JB
1300x_new_focus_frame (frame)
1301 struct frame *frame;
dc6f92b8 1302{
f676886a 1303 struct frame *old_focus = x_focus_frame;
dc6f92b8
JB
1304 int events_enqueued = 0;
1305
f676886a 1306 if (frame != x_focus_frame)
dc6f92b8 1307 {
6d4238f3 1308 /* Set this before calling other routines, so that they see
f676886a
JB
1309 the correct value of x_focus_frame. */
1310 x_focus_frame = frame;
6d4238f3
JB
1311
1312 if (old_focus && old_focus->auto_lower)
f676886a 1313 x_lower_frame (old_focus);
dc6f92b8
JB
1314
1315#if 0
f676886a
JB
1316 selected_frame = frame;
1317 XSET (XWINDOW (selected_frame->selected_window)->frame,
1318 Lisp_Frame, selected_frame);
1319 Fselect_window (selected_frame->selected_window);
1320 choose_minibuf_frame ();
c118dd06 1321#endif /* ! 0 */
dc6f92b8 1322
f676886a
JB
1323 if (x_focus_frame && x_focus_frame->auto_raise)
1324 x_raise_frame (x_focus_frame);
6d4238f3 1325 }
dc6f92b8 1326
f676886a 1327 XTframe_rehighlight ();
6d4238f3
JB
1328}
1329
1330
f451eb13
JB
1331/* The focus has changed, or we have redirected a frame's focus to
1332 another frame (this happens when a frame uses a surrogate
1333 minibuffer frame). Shift the highlight as appropriate. */
6d4238f3 1334static void
f676886a 1335XTframe_rehighlight ()
6d4238f3 1336{
f676886a 1337 struct frame *old_highlight = x_highlight_frame;
6d4238f3 1338
f676886a 1339 if (x_focus_frame)
6d4238f3 1340 {
f451eb13 1341 x_highlight_frame =
ab648270 1342 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
f451eb13
JB
1343 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1344 : x_focus_frame);
1345 if (! FRAME_LIVE_P (x_highlight_frame))
1346 {
1347 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1348 x_highlight_frame = x_focus_frame;
1349 }
dc6f92b8 1350 }
6d4238f3 1351 else
f676886a 1352 x_highlight_frame = 0;
dc6f92b8 1353
f676886a 1354 if (x_highlight_frame != old_highlight)
6d4238f3
JB
1355 {
1356 if (old_highlight)
f676886a
JB
1357 frame_unhighlight (old_highlight);
1358 if (x_highlight_frame)
1359 frame_highlight (x_highlight_frame);
6d4238f3 1360 }
dc6f92b8
JB
1361}
1362\f
90e65f07
JB
1363/* Mouse clicks and mouse movement. Rah. */
1364#ifdef HAVE_X11
1365
f676886a 1366/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
90e65f07
JB
1367 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1368 that the glyph at X, Y occupies, if BOUNDS != 0. */
1369static void
f676886a
JB
1370pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1371 FRAME_PTR f;
dc6f92b8
JB
1372 register unsigned int pix_x, pix_y;
1373 register int *x, *y;
90e65f07 1374 XRectangle *bounds;
dc6f92b8 1375{
12ba150f
JB
1376 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1377 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
90e65f07
JB
1378
1379 if (bounds)
1380 {
12ba150f
JB
1381 bounds->width = FONT_WIDTH (f->display.x->font);
1382 bounds->height = FONT_HEIGHT (f->display.x->font);
1383 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1384 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
90e65f07 1385 }
12ba150f
JB
1386
1387 if (pix_x < 0) pix_x = 0;
1388 else if (pix_x > f->width) pix_x = f->width;
1389
1390 if (pix_y < 0) pix_y = 0;
1391 else if (pix_y > f->height) pix_y = f->height;
1392
1393 *x = pix_x;
1394 *y = pix_y;
dc6f92b8 1395}
dc6f92b8
JB
1396
1397/* Any buttons grabbed. */
1398unsigned int x_mouse_grabbed;
1399
28430d3c
JB
1400/* Which modifier keys are on which modifier bits?
1401
1402 With each keystroke, X returns eight bits indicating which modifier
11edeb03
JB
1403 keys were held down when the key was pressed. The interpretation
1404 of the top five modifier bits depends on what keys are attached
28430d3c
JB
1405 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1406 is the meta bit.
1407
1408 x_meta_mod_mask is a mask containing the bits used for the meta key.
1409 It may have more than one bit set, if more than one modifier bit
1410 has meta keys on it. Basically, if EVENT is a KeyPress event,
11edeb03
JB
1411 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1412
1413 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1414 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1415 only be affected by the lock modifier bit if XK_Shift_Lock is in
1416 use; XK_Caps_Lock should only affect alphabetic keys. With this
1417 arrangement, the lock modifier should shift the character if
1418 (EVENT.state & x_shift_lock_mask) != 0. */
1419static int x_meta_mod_mask, x_shift_lock_mask;
28430d3c 1420
a3c44b14
RS
1421/* These are like x_meta_mod_mask, but for different modifiers. */
1422static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1423
28430d3c
JB
1424/* Initialize mode_switch_bit and modifier_meaning. */
1425static void
1426x_find_modifier_meanings ()
1427{
f689eb05 1428 int min_code, max_code;
28430d3c
JB
1429 KeySym *syms;
1430 int syms_per_code;
1431 XModifierKeymap *mods;
1432
1433 x_meta_mod_mask = 0;
11edeb03 1434 x_shift_lock_mask = 0;
a3c44b14
RS
1435 x_alt_mod_mask = 0;
1436 x_super_mod_mask = 0;
1437 x_hyper_mod_mask = 0;
28430d3c 1438
9658a521 1439#ifdef HAVE_X11R4
28430d3c 1440 XDisplayKeycodes (x_current_display, &min_code, &max_code);
9658a521
JB
1441#else
1442 min_code = x_current_display->min_keycode;
1443 max_code = x_current_display->max_keycode;
1444#endif
1445
28430d3c
JB
1446 syms = XGetKeyboardMapping (x_current_display,
1447 min_code, max_code - min_code + 1,
1448 &syms_per_code);
1449 mods = XGetModifierMapping (x_current_display);
1450
11edeb03
JB
1451 /* Scan the modifier table to see which modifier bits the Meta and
1452 Alt keysyms are on. */
28430d3c
JB
1453 {
1454 int row, col; /* The row and column in the modifier table. */
1455
1456 for (row = 3; row < 8; row++)
1457 for (col = 0; col < mods->max_keypermod; col++)
1458 {
1459 KeyCode code =
1460 mods->modifiermap[(row * mods->max_keypermod) + col];
1461
1462 /* Are any of this keycode's keysyms a meta key? */
1463 {
1464 int code_col;
1465
1466 for (code_col = 0; code_col < syms_per_code; code_col++)
1467 {
f689eb05 1468 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 1469
f689eb05 1470 switch (sym)
28430d3c 1471 {
f689eb05
JB
1472 case XK_Meta_L:
1473 case XK_Meta_R:
28430d3c
JB
1474 x_meta_mod_mask |= (1 << row);
1475 break;
f689eb05
JB
1476
1477 case XK_Alt_L:
1478 case XK_Alt_R:
a3c44b14
RS
1479 x_alt_mod_mask |= (1 << row);
1480 break;
1481
1482 case XK_Hyper_L:
1483 case XK_Hyper_R:
1484 x_hyper_mod_mask |= (1 << row);
1485 break;
1486
1487 case XK_Super_L:
1488 case XK_Super_R:
1489 x_super_mod_mask |= (1 << row);
f689eb05 1490 break;
11edeb03
JB
1491
1492 case XK_Shift_Lock:
1493 /* Ignore this if it's not on the lock modifier. */
1494 if ((1 << row) == LockMask)
1495 x_shift_lock_mask = LockMask;
1496 break;
28430d3c
JB
1497 }
1498 }
1499 }
1500 }
1501 }
1502
f689eb05
JB
1503 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1504 if (! x_meta_mod_mask)
a3c44b14
RS
1505 {
1506 x_meta_mod_mask = x_alt_mod_mask;
1507 x_alt_mod_mask = 0;
1508 }
f689eb05 1509
148c4b70
RS
1510 /* If some keys are both alt and meta,
1511 make them just meta, not alt. */
1512 if (x_alt_mod_mask & x_meta_mod_mask)
1513 {
1514 x_alt_mod_mask &= ~x_meta_mod_mask;
1515 }
1516
28430d3c 1517 XFree ((char *) syms);
f689eb05 1518 XFreeModifiermap (mods);
28430d3c
JB
1519}
1520
1521
dfeccd2d
JB
1522/* Convert between the modifier bits X uses and the modifier bits
1523 Emacs uses. */
7c5283e4 1524static unsigned int
dfeccd2d 1525x_x_to_emacs_modifiers (state)
dc6f92b8
JB
1526 unsigned int state;
1527{
11edeb03
JB
1528 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1529 | ((state & ControlMask) ? ctrl_modifier : 0)
a3c44b14
RS
1530 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1531 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1532 | ((state & x_super_mod_mask) ? super_modifier : 0)
1533 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
1534}
1535
dfeccd2d
JB
1536static unsigned int
1537x_emacs_to_x_modifiers (state)
1538 unsigned int state;
1539{
1540 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1541 | ((state & super_modifier) ? x_super_mod_mask : 0)
1542 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1543 | ((state & shift_modifier) ? ShiftMask : 0)
1544 | ((state & ctrl_modifier) ? ControlMask : 0)
1545 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1546}
1547
dc6f92b8
JB
1548/* Prepare a mouse-event in *RESULT for placement in the input queue.
1549
1550 If the event is a button press, then note that we have grabbed
f451eb13 1551 the mouse. */
dc6f92b8
JB
1552
1553static Lisp_Object
f451eb13 1554construct_mouse_click (result, event, f)
dc6f92b8
JB
1555 struct input_event *result;
1556 XButtonEvent *event;
f676886a 1557 struct frame *f;
dc6f92b8 1558{
f451eb13 1559 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 1560 otherwise. */
f451eb13
JB
1561 result->kind = mouse_click;
1562 XSET (result->code, Lisp_Int, event->button - Button1);
1113d9db 1563 result->timestamp = event->time;
dfeccd2d 1564 result->modifiers = (x_x_to_emacs_modifiers (event->state)
f689eb05
JB
1565 | (event->type == ButtonRelease
1566 ? up_modifier
1567 : down_modifier));
dc6f92b8
JB
1568
1569 /* Notice if the mouse is still grabbed. */
1570 if (event->type == ButtonPress)
1571 {
1572 if (! x_mouse_grabbed)
1573 Vmouse_depressed = Qt;
90e65f07 1574 x_mouse_grabbed |= (1 << event->button);
dc6f92b8
JB
1575 }
1576 else if (event->type == ButtonRelease)
1577 {
90e65f07 1578 x_mouse_grabbed &= ~(1 << event->button);
dc6f92b8
JB
1579 if (!x_mouse_grabbed)
1580 Vmouse_depressed = Qnil;
1581 }
1582
f451eb13
JB
1583 {
1584 int row, column;
dc6f92b8 1585
f451eb13
JB
1586 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1587 XFASTINT (result->x) = column;
1588 XFASTINT (result->y) = row;
12ba150f 1589 XSET (result->frame_or_window, Lisp_Frame, f);
f451eb13 1590 }
dc6f92b8
JB
1591}
1592
1593
90e65f07
JB
1594/* Mouse movement. Rah.
1595
1596 In order to avoid asking for motion events and then throwing most
1597 of them away or busy-polling the server for mouse positions, we ask
1598 the server for pointer motion hints. This means that we get only
1599 one event per group of mouse movements. "Groups" are delimited by
1600 other kinds of events (focus changes and button clicks, for
1601 example), or by XQueryPointer calls; when one of these happens, we
1602 get another MotionNotify event the next time the mouse moves. This
e5d77022 1603 is at least as efficient as getting motion events when mouse
90e65f07
JB
1604 tracking is on, and I suspect only negligibly worse when tracking
1605 is off.
1606
1607 The silly O'Reilly & Associates Nutshell guides barely document
1608 pointer motion hints at all (I think you have to infer how they
1609 work from an example), and the description of XQueryPointer doesn't
1610 mention that calling it causes you to get another motion hint from
1611 the server, which is very important. */
1612
1613/* Where the mouse was last time we reported a mouse event. */
f676886a 1614static FRAME_PTR last_mouse_frame;
90e65f07
JB
1615static XRectangle last_mouse_glyph;
1616
ab648270 1617/* The scroll bar in which the last X motion event occurred.
12ba150f 1618
ab648270
JB
1619 If the last X motion event occured in a scroll bar, we set this
1620 so XTmouse_position can know whether to report a scroll bar motion or
12ba150f
JB
1621 an ordinary motion.
1622
ab648270 1623 If the last X motion event didn't occur in a scroll bar, we set this
12ba150f 1624 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
ab648270 1625static Lisp_Object last_mouse_scroll_bar;
f451eb13 1626
e5d77022
JB
1627/* This is a hack. We would really prefer that XTmouse_position would
1628 return the time associated with the position it returns, but there
1629 doesn't seem to be any way to wrest the timestamp from the server
1630 along with the position query. So, we just keep track of the time
1631 of the last movement we received, and return that in hopes that
1632 it's somewhat accurate. */
1633static Time last_mouse_movement_time;
1634
90e65f07
JB
1635/* Function to report a mouse movement to the mainstream Emacs code.
1636 The input handler calls this.
1637
1638 We have received a mouse movement event, which is given in *event.
1639 If the mouse is over a different glyph than it was last time, tell
1640 the mainstream emacs code by setting mouse_moved. If not, ask for
1641 another motion event, so we can check again the next time it moves. */
1642static void
12ba150f 1643note_mouse_movement (frame, event)
f676886a 1644 FRAME_PTR frame;
90e65f07
JB
1645 XMotionEvent *event;
1646
1647{
e5d77022
JB
1648 last_mouse_movement_time = event->time;
1649
90e65f07
JB
1650 /* Has the mouse moved off the glyph it was on at the last sighting? */
1651 if (event->x < last_mouse_glyph.x
1652 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1653 || event->y < last_mouse_glyph.y
1654 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f
JB
1655 {
1656 mouse_moved = 1;
ab648270 1657 last_mouse_scroll_bar = Qnil;
12ba150f 1658 }
90e65f07
JB
1659 else
1660 {
1661 /* It's on the same glyph. Call XQueryPointer so we'll get an
1662 event the next time the mouse moves and we can see if it's
1663 *still* on the same glyph. */
1664 int dummy;
1665
1666 XQueryPointer (event->display, event->window,
1667 (Window *) &dummy, (Window *) &dummy,
1668 &dummy, &dummy, &dummy, &dummy,
1669 (unsigned int *) &dummy);
1670 }
1671}
1672
ab648270
JB
1673static struct scroll_bar *x_window_to_scroll_bar ();
1674static void x_scroll_bar_report_motion ();
12ba150f 1675
90e65f07
JB
1676/* Return the current position of the mouse.
1677
ab648270
JB
1678 If the mouse movement started in a scroll bar, set *f, *bar_window,
1679 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 1680 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 1681 position on the scroll bar.
12ba150f
JB
1682
1683 If the mouse movement started elsewhere, set *f to the frame the
1684 mouse is on, *bar_window to nil, and *x and *y to the character cell
1685 the mouse is over.
1686
1687 Set *time to the server timestamp for the time at which the mouse
1688 was at this position.
1689
90e65f07 1690 This clears the mouse_moved flag, so we can wait for the next mouse
12ba150f
JB
1691 movement. This also calls XQueryPointer, which will cause the
1692 server to give us another MotionNotify when the mouse moves
1693 again. */
90e65f07
JB
1694
1695static void
12ba150f 1696XTmouse_position (f, bar_window, part, x, y, time)
f676886a 1697 FRAME_PTR *f;
12ba150f 1698 Lisp_Object *bar_window;
ab648270 1699 enum scroll_bar_part *part;
90e65f07 1700 Lisp_Object *x, *y;
e5d77022 1701 unsigned long *time;
90e65f07 1702{
90e65f07
JB
1703 BLOCK_INPUT;
1704
ab648270
JB
1705 if (! NILP (last_mouse_scroll_bar))
1706 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
90e65f07
JB
1707 else
1708 {
12ba150f
JB
1709 Window root;
1710 int root_x, root_y;
90e65f07 1711
12ba150f
JB
1712 Window dummy_window;
1713 int dummy;
1714
1715 mouse_moved = 0;
ab648270 1716 last_mouse_scroll_bar = Qnil;
12ba150f
JB
1717
1718 /* Figure out which root window we're on. */
1719 XQueryPointer (x_current_display,
1720 DefaultRootWindow (x_current_display),
1721
1722 /* The root window which contains the pointer. */
1723 &root,
1724
1725 /* Trash which we can't trust if the pointer is on
1726 a different screen. */
1727 &dummy_window,
1728
1729 /* The position on that root window. */
1730 &root_x, &root_y,
1731
1732 /* More trash we can't trust. */
1733 &dummy, &dummy,
1734
1735 /* Modifier keys and pointer buttons, about which
1736 we don't care. */
1737 (unsigned int *) &dummy);
1738
1739 /* Now we have a position on the root; find the innermost window
1740 containing the pointer. */
1741 {
1742 Window win, child;
1743 int win_x, win_y;
1744 int parent_x, parent_y;
1745
1746 win = root;
1747 for (;;)
1748 {
1749 XTranslateCoordinates (x_current_display,
1750
1751 /* From-window, to-window. */
1752 root, win,
1753
1754 /* From-position, to-position. */
1755 root_x, root_y, &win_x, &win_y,
1756
1757 /* Child of win. */
1758 &child);
1759
1760 if (child == None)
1761 break;
1762
1763 win = child;
1764 parent_x = win_x;
1765 parent_y = win_y;
1766 }
1767
1768 /* Now we know that:
1769 win is the innermost window containing the pointer
1770 (XTC says it has no child containing the pointer),
1771 win_x and win_y are the pointer's position in it
1772 (XTC did this the last time through), and
1773 parent_x and parent_y are the pointer's position in win's parent.
1774 (They are what win_x and win_y were when win was child.
1775 If win is the root window, it has no parent, and
1776 parent_{x,y} are invalid, but that's okay, because we'll
1777 never use them in that case.) */
1778
1779 /* Is win one of our frames? */
1780 *f = x_window_to_frame (win);
1781
ab648270 1782 /* If not, is it one of our scroll bars? */
12ba150f
JB
1783 if (! *f)
1784 {
ab648270 1785 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
1786
1787 if (bar)
1788 {
1789 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1790 win_x = parent_x;
1791 win_y = parent_y;
1792 }
1793 }
90e65f07 1794
12ba150f
JB
1795 if (*f)
1796 {
1797 pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y,
1798 &last_mouse_glyph);
1799
1800 *bar_window = Qnil;
1801 *part = 0;
1802 XSET (*x, Lisp_Int, win_x);
1803 XSET (*y, Lisp_Int, win_y);
1804 *time = last_mouse_movement_time;
1805 }
1806 }
1807 }
90e65f07
JB
1808
1809 UNBLOCK_INPUT;
1810}
1811
c118dd06 1812#else /* ! defined (HAVE_X11) */
dc6f92b8 1813#define XEvent XKeyPressedEvent
c118dd06
JB
1814#endif /* ! defined (HAVE_X11) */
1815\f
ab648270 1816/* Scroll bar support. */
f451eb13 1817
ab648270
JB
1818/* Given an X window ID, find the struct scroll_bar which manages it.
1819 This can be called in GC, so we have to make sure to strip off mark
1820 bits. */
1821static struct scroll_bar *
1822x_window_to_scroll_bar (window_id)
f451eb13
JB
1823 Window window_id;
1824{
1825 Lisp_Object tail, frame;
f451eb13 1826
ab648270
JB
1827 for (tail = Vframe_list;
1828 XGCTYPE (tail) == Lisp_Cons;
1829 tail = XCONS (tail)->cdr)
f451eb13 1830 {
f451eb13 1831 Lisp_Object frame = XCONS (tail)->car;
cf7cb199 1832 Lisp_Object bar, condemned;
f451eb13
JB
1833
1834 /* All elements of Vframe_list should be frames. */
ab648270 1835 if (XGCTYPE (frame) != Lisp_Frame)
f451eb13
JB
1836 abort ();
1837
ab648270 1838 /* Scan this frame's scroll bar list for a scroll bar with the
f451eb13 1839 right window ID. */
ab648270
JB
1840 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1841 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
cf7cb199 1842 /* This trick allows us to search both the ordinary and
ab648270
JB
1843 condemned scroll bar lists with one loop. */
1844 ! GC_NILP (bar) || (bar = condemned,
1845 condemned = Qnil,
1846 ! GC_NILP (bar));
1847 bar = XSCROLL_BAR(bar)->next)
1848 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1849 return XSCROLL_BAR (bar);
f451eb13
JB
1850 }
1851
1852 return 0;
1853}
1854
ab648270
JB
1855/* Open a new X window to serve as a scroll bar, and return the
1856 scroll bar vector for it. */
1857static struct scroll_bar *
1858x_scroll_bar_create (window, top, left, width, height)
12ba150f 1859 struct window *window;
f451eb13
JB
1860 int top, left, width, height;
1861{
12ba150f 1862 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
ab648270
JB
1863 struct scroll_bar *bar =
1864 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
1865
1866 BLOCK_INPUT;
1867
1868 {
1869 XSetWindowAttributes a;
1870 unsigned long mask;
1871
12ba150f
JB
1872 a.background_pixel = frame->display.x->background_pixel;
1873 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 1874 | ButtonMotionMask | PointerMotionHintMask
12ba150f 1875 | ExposureMask);
ab648270 1876 a.cursor = x_vertical_scroll_bar_cursor;
f451eb13 1877
dbc4e1c1 1878 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 1879
ab648270 1880 SET_SCROLL_BAR_X_WINDOW
12ba150f
JB
1881 (bar,
1882 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
f451eb13 1883
ab648270 1884 /* Position and size of scroll bar. */
12ba150f 1885 left, top, width, height,
f451eb13 1886
12ba150f
JB
1887 /* Border width, depth, class, and visual. */
1888 0, CopyFromParent, CopyFromParent, CopyFromParent,
f451eb13 1889
12ba150f
JB
1890 /* Attributes. */
1891 mask, &a));
f451eb13
JB
1892 }
1893
12ba150f
JB
1894 XSET (bar->window, Lisp_Window, window);
1895 XSET (bar->top, Lisp_Int, top);
1896 XSET (bar->left, Lisp_Int, left);
1897 XSET (bar->width, Lisp_Int, width);
1898 XSET (bar->height, Lisp_Int, height);
1899 XSET (bar->start, Lisp_Int, 0);
1900 XSET (bar->end, Lisp_Int, 0);
1901 bar->dragging = Qnil;
f451eb13
JB
1902
1903 /* Add bar to its frame's list of scroll bars. */
ab648270 1904 bar->next = FRAME_SCROLL_BARS (frame);
12ba150f 1905 bar->prev = Qnil;
ab648270 1906 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
12ba150f 1907 if (! NILP (bar->next))
ab648270 1908 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
f451eb13 1909
ab648270 1910 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
f451eb13
JB
1911
1912 UNBLOCK_INPUT;
12ba150f
JB
1913
1914 return bar;
f451eb13
JB
1915}
1916
12ba150f
JB
1917/* Draw BAR's handle in the proper position.
1918 If the handle is already drawn from START to END, don't bother
1919 redrawing it, unless REBUILD is non-zero; in that case, always
1920 redraw it. (REBUILD is handy for drawing the handle after expose
1921 events.)
1922
1923 Normally, we want to constrain the start and end of the handle to
ab648270 1924 fit inside its rectangle, but if the user is dragging the scroll bar
12ba150f
JB
1925 handle, we want to let them drag it down all the way, so that the
1926 bar's top is as far down as it goes; otherwise, there's no way to
1927 move to the very end of the buffer. */
f451eb13 1928static void
ab648270
JB
1929x_scroll_bar_set_handle (bar, start, end, rebuild)
1930 struct scroll_bar *bar;
f451eb13 1931 int start, end;
12ba150f 1932 int rebuild;
f451eb13 1933{
12ba150f 1934 int dragging = ! NILP (bar->dragging);
ab648270 1935 Window w = SCROLL_BAR_X_WINDOW (bar);
12ba150f
JB
1936 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1937
1938 /* If the display is already accurate, do nothing. */
1939 if (! rebuild
1940 && start == XINT (bar->start)
1941 && end == XINT (bar->end))
1942 return;
1943
f451eb13
JB
1944 BLOCK_INPUT;
1945
1946 {
ab648270
JB
1947 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1948 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1949 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
f451eb13
JB
1950
1951 /* Make sure the values are reasonable, and try to preserve
1952 the distance between start and end. */
12ba150f
JB
1953 {
1954 int length = end - start;
1955
1956 if (start < 0)
1957 start = 0;
1958 else if (start > top_range)
1959 start = top_range;
1960 end = start + length;
1961
1962 if (end < start)
1963 end = start;
1964 else if (end > top_range && ! dragging)
1965 end = top_range;
1966 }
f451eb13 1967
ab648270 1968 /* Store the adjusted setting in the scroll bar. */
12ba150f
JB
1969 XSET (bar->start, Lisp_Int, start);
1970 XSET (bar->end, Lisp_Int, end);
f451eb13 1971
12ba150f
JB
1972 /* Clip the end position, just for display. */
1973 if (end > top_range)
1974 end = top_range;
f451eb13 1975
ab648270 1976 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
1977 below top positions, to make sure the handle is always at least
1978 that many pixels tall. */
ab648270 1979 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 1980
12ba150f
JB
1981 /* Draw the empty space above the handle. Note that we can't clear
1982 zero-height areas; that means "clear to end of window." */
1983 if (0 < start)
1984 XClearArea (x_current_display, w,
f451eb13 1985
12ba150f 1986 /* x, y, width, height, and exposures. */
ab648270
JB
1987 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1988 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
1989 inside_width, start,
1990 False);
f451eb13 1991
12ba150f
JB
1992 /* Draw the handle itself. */
1993 XFillRectangle (x_current_display, w, gc,
f451eb13 1994
12ba150f 1995 /* x, y, width, height */
ab648270
JB
1996 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1997 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 1998 inside_width, end - start);
f451eb13 1999
f451eb13 2000
12ba150f
JB
2001 /* Draw the empty space below the handle. Note that we can't
2002 clear zero-height areas; that means "clear to end of window." */
2003 if (end < inside_height)
2004 XClearArea (x_current_display, w,
f451eb13 2005
12ba150f 2006 /* x, y, width, height, and exposures. */
ab648270
JB
2007 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2008 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
2009 inside_width, inside_height - end,
2010 False);
f451eb13 2011
f451eb13
JB
2012 }
2013
f451eb13
JB
2014 UNBLOCK_INPUT;
2015}
2016
ab648270 2017/* Move a scroll bar around on the screen, to accomodate changing
12ba150f 2018 window configurations. */
f451eb13 2019static void
ab648270
JB
2020x_scroll_bar_move (bar, top, left, width, height)
2021 struct scroll_bar *bar;
f451eb13
JB
2022 int top, left, width, height;
2023{
2024 BLOCK_INPUT;
2025
2026 {
2027 XWindowChanges wc;
2028 unsigned int mask = 0;
2029
2030 wc.x = left;
2031 wc.y = top;
2032 wc.width = width;
2033 wc.height = height;
2034
12ba150f
JB
2035 if (left != XINT (bar->left)) mask |= CWX;
2036 if (top != XINT (bar->top)) mask |= CWY;
2037 if (width != XINT (bar->width)) mask |= CWWidth;
2038 if (height != XINT (bar->height)) mask |= CWHeight;
2039
2040 if (mask)
ab648270 2041 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
12ba150f 2042 mask, &wc);
f451eb13
JB
2043 }
2044
12ba150f
JB
2045 XSET (bar->left, Lisp_Int, left);
2046 XSET (bar->top, Lisp_Int, top);
2047 XSET (bar->width, Lisp_Int, width);
2048 XSET (bar->height, Lisp_Int, height);
2049
f451eb13
JB
2050 UNBLOCK_INPUT;
2051}
2052
ab648270 2053/* Destroy the X window for BAR, and set its Emacs window's scroll bar
12ba150f
JB
2054 to nil. */
2055static void
ab648270
JB
2056x_scroll_bar_remove (bar)
2057 struct scroll_bar *bar;
12ba150f
JB
2058{
2059 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2060
2061 BLOCK_INPUT;
2062
2063 /* Destroy the window. */
ab648270 2064 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
12ba150f 2065
ab648270
JB
2066 /* Disassociate this scroll bar from its window. */
2067 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
2068
2069 UNBLOCK_INPUT;
2070}
2071
2072/* Set the handle of the vertical scroll bar for WINDOW to indicate
2073 that we are displaying PORTION characters out of a total of WHOLE
ab648270 2074 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f
JB
2075 create one. */
2076static void
ab648270 2077XTset_vertical_scroll_bar (window, portion, whole, position)
f451eb13
JB
2078 struct window *window;
2079 int portion, whole, position;
2080{
2081 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
f451eb13 2082 int top = XINT (window->top);
ab648270
JB
2083 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2084 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
f451eb13 2085
ab648270 2086 /* Where should this scroll bar be, pixelwise? */
12ba150f
JB
2087 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2088 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
ab648270
JB
2089 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2090 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
f451eb13 2091
ab648270 2092 struct scroll_bar *bar;
12ba150f 2093
ab648270
JB
2094 /* Does the scroll bar exist yet? */
2095 if (NILP (window->vertical_scroll_bar))
2096 bar = x_scroll_bar_create (window,
f451eb13
JB
2097 pixel_top, pixel_left,
2098 pixel_width, pixel_height);
2099 else
12ba150f
JB
2100 {
2101 /* It may just need to be moved and resized. */
ab648270
JB
2102 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2103 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
12ba150f 2104 }
f451eb13 2105
ab648270 2106 /* Set the scroll bar's current state, unless we're currently being
f451eb13 2107 dragged. */
12ba150f 2108 if (NILP (bar->dragging))
f451eb13 2109 {
12ba150f 2110 int top_range =
ab648270 2111 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
f451eb13 2112
12ba150f 2113 if (whole == 0)
ab648270 2114 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
2115 else
2116 {
2117 int start = (position * top_range) / whole;
2118 int end = ((position + portion) * top_range) / whole;
2119
ab648270 2120 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 2121 }
f451eb13
JB
2122 }
2123
ab648270 2124 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
f451eb13
JB
2125}
2126
12ba150f 2127
f451eb13 2128/* The following three hooks are used when we're doing a thorough
ab648270 2129 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 2130 are going to be deleted, because keeping track of when windows go
12ba150f
JB
2131 away is a real pain - "Can you say set-window-configuration, boys
2132 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 2133 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 2134 from the fiery pit when we actually redisplay its window. */
f451eb13 2135
ab648270
JB
2136/* Arrange for all scroll bars on FRAME to be removed at the next call
2137 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2138 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
f451eb13 2139static void
ab648270 2140XTcondemn_scroll_bars (frame)
f451eb13
JB
2141 FRAME_PTR frame;
2142{
12ba150f
JB
2143 /* The condemned list should be empty at this point; if it's not,
2144 then the rest of Emacs isn't using the condemn/redeem/judge
2145 protocol correctly. */
ab648270 2146 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
12ba150f
JB
2147 abort ();
2148
2149 /* Move them all to the "condemned" list. */
ab648270
JB
2150 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2151 FRAME_SCROLL_BARS (frame) = Qnil;
f451eb13
JB
2152}
2153
ab648270 2154/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
12ba150f 2155 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 2156static void
ab648270 2157XTredeem_scroll_bar (window)
12ba150f 2158 struct window *window;
f451eb13 2159{
ab648270 2160 struct scroll_bar *bar;
12ba150f 2161
ab648270
JB
2162 /* We can't redeem this window's scroll bar if it doesn't have one. */
2163 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
2164 abort ();
2165
ab648270 2166 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
2167
2168 /* Unlink it from the condemned list. */
2169 {
2170 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2171
2172 if (NILP (bar->prev))
2173 {
2174 /* If the prev pointer is nil, it must be the first in one of
2175 the lists. */
ab648270 2176 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
2177 /* It's not condemned. Everything's fine. */
2178 return;
ab648270
JB
2179 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2180 window->vertical_scroll_bar))
2181 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
2182 else
2183 /* If its prev pointer is nil, it must be at the front of
2184 one or the other! */
2185 abort ();
2186 }
2187 else
ab648270 2188 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
2189
2190 if (! NILP (bar->next))
ab648270 2191 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 2192
ab648270 2193 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 2194 bar->prev = Qnil;
ab648270 2195 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
12ba150f 2196 if (! NILP (bar->next))
ab648270 2197 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
12ba150f 2198 }
f451eb13
JB
2199}
2200
ab648270
JB
2201/* Remove all scroll bars on FRAME that haven't been saved since the
2202 last call to `*condemn_scroll_bars_hook'. */
f451eb13 2203static void
ab648270 2204XTjudge_scroll_bars (f)
12ba150f 2205 FRAME_PTR f;
f451eb13 2206{
12ba150f 2207 Lisp_Object bar, next;
f451eb13 2208
ab648270 2209 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
2210
2211 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
2212 more events on the hapless scroll bars. */
2213 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
2214
2215 for (; ! NILP (bar); bar = next)
f451eb13 2216 {
ab648270 2217 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 2218
ab648270 2219 x_scroll_bar_remove (b);
12ba150f
JB
2220
2221 next = b->next;
2222 b->next = b->prev = Qnil;
f451eb13 2223 }
12ba150f 2224
ab648270 2225 /* Now there should be no references to the condemned scroll bars,
12ba150f 2226 and they should get garbage-collected. */
f451eb13
JB
2227}
2228
2229
ab648270
JB
2230/* Handle an Expose or GraphicsExpose event on a scroll bar.
2231
2232 This may be called from a signal handler, so we have to ignore GC
2233 mark bits. */
f451eb13 2234static void
ab648270
JB
2235x_scroll_bar_expose (bar, event)
2236 struct scroll_bar *bar;
f451eb13
JB
2237 XEvent *event;
2238{
ab648270 2239 Window w = SCROLL_BAR_X_WINDOW (bar);
12ba150f
JB
2240 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2241
f451eb13
JB
2242 BLOCK_INPUT;
2243
ab648270 2244 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 2245
ab648270 2246 /* Draw a one-pixel border just inside the edges of the scroll bar. */
12ba150f 2247 XDrawRectangle (x_current_display, w, gc,
f451eb13
JB
2248
2249 /* x, y, width, height */
12ba150f 2250 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
f451eb13 2251
12ba150f
JB
2252 /* Draw another line to make the extra-thick border on the right. */
2253 XFillRectangle (x_current_display, w, gc,
f451eb13 2254
12ba150f
JB
2255 /* x, y, width, height */
2256 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
f451eb13
JB
2257
2258 UNBLOCK_INPUT;
2259}
2260
ab648270
JB
2261/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2262 is set to something other than no_event, it is enqueued.
2263
2264 This may be called from a signal handler, so we have to ignore GC
2265 mark bits. */
f451eb13 2266static void
ab648270
JB
2267x_scroll_bar_handle_click (bar, event, emacs_event)
2268 struct scroll_bar *bar;
f451eb13
JB
2269 XEvent *event;
2270 struct input_event *emacs_event;
2271{
ab648270 2272 if (XGCTYPE (bar->window) != Lisp_Window)
12ba150f
JB
2273 abort ();
2274
ab648270 2275 emacs_event->kind = scroll_bar_click;
12ba150f 2276 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
f451eb13 2277 emacs_event->modifiers =
dfeccd2d 2278 (x_x_to_emacs_modifiers (event->xbutton.state)
f451eb13
JB
2279 | (event->type == ButtonRelease
2280 ? up_modifier
2281 : down_modifier));
12ba150f 2282 emacs_event->frame_or_window = bar->window;
f451eb13 2283 emacs_event->timestamp = event->xbutton.time;
12ba150f
JB
2284 {
2285 int internal_height =
ab648270 2286 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
12ba150f 2287 int top_range =
ab648270
JB
2288 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2289 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
2290
2291 if (y < 0) y = 0;
2292 if (y > top_range) y = top_range;
2293
2294 if (y < XINT (bar->start))
ab648270
JB
2295 emacs_event->part = scroll_bar_above_handle;
2296 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2297 emacs_event->part = scroll_bar_handle;
12ba150f 2298 else
ab648270 2299 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
2300
2301 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
2302 they want to drag it. Lisp code needs to be able to decide
2303 whether or not we're dragging. */
929787e1 2304#if 0
12ba150f
JB
2305 /* If the user has just clicked on the handle, record where they're
2306 holding it. */
2307 if (event->type == ButtonPress
ab648270 2308 && emacs_event->part == scroll_bar_handle)
12ba150f 2309 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
929787e1 2310#endif
12ba150f
JB
2311
2312 /* If the user has released the handle, set it to its final position. */
2313 if (event->type == ButtonRelease
2314 && ! NILP (bar->dragging))
2315 {
2316 int new_start = y - XINT (bar->dragging);
2317 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 2318
ab648270 2319 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
2320 bar->dragging = Qnil;
2321 }
f451eb13 2322
5116f055
JB
2323 /* Same deal here as the other #if 0. */
2324#if 0
12ba150f
JB
2325 /* Clicks on the handle are always reported as occuring at the top of
2326 the handle. */
ab648270 2327 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
2328 emacs_event->x = bar->start;
2329 else
2330 XSET (emacs_event->x, Lisp_Int, y);
5116f055
JB
2331#else
2332 XSET (emacs_event->x, Lisp_Int, y);
2333#endif
f451eb13 2334
12ba150f
JB
2335 XSET (emacs_event->y, Lisp_Int, top_range);
2336 }
2337}
f451eb13 2338
ab648270
JB
2339/* Handle some mouse motion while someone is dragging the scroll bar.
2340
2341 This may be called from a signal handler, so we have to ignore GC
2342 mark bits. */
f451eb13 2343static void
ab648270
JB
2344x_scroll_bar_note_movement (bar, event)
2345 struct scroll_bar *bar;
f451eb13
JB
2346 XEvent *event;
2347{
2348 last_mouse_movement_time = event->xmotion.time;
2349
2350 mouse_moved = 1;
ab648270 2351 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
f451eb13
JB
2352
2353 /* If we're dragging the bar, display it. */
ab648270 2354 if (! GC_NILP (bar->dragging))
f451eb13
JB
2355 {
2356 /* Where should the handle be now? */
12ba150f 2357 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 2358
12ba150f 2359 if (new_start != XINT (bar->start))
f451eb13 2360 {
12ba150f 2361 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 2362
ab648270 2363 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
2364 }
2365 }
2366
2367 /* Call XQueryPointer so we'll get an event the next time the mouse
2368 moves and we can see *still* on the same position. */
2369 {
2370 int dummy;
2371
2372 XQueryPointer (event->xmotion.display, event->xmotion.window,
2373 (Window *) &dummy, (Window *) &dummy,
2374 &dummy, &dummy, &dummy, &dummy,
2375 (unsigned int *) &dummy);
2376 }
2377}
2378
12ba150f 2379/* Return information to the user about the current position of the mouse
ab648270 2380 on the scroll bar. */
12ba150f 2381static void
ab648270 2382x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
12ba150f
JB
2383 FRAME_PTR *f;
2384 Lisp_Object *bar_window;
ab648270 2385 enum scroll_bar_part *part;
12ba150f
JB
2386 Lisp_Object *x, *y;
2387 unsigned long *time;
2388{
ab648270 2389 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
12ba150f 2390 int win_x, win_y;
559cb2fb
JB
2391 Window dummy_window;
2392 int dummy_coord;
2393 unsigned int dummy_mask;
12ba150f 2394
cf7cb199
JB
2395 BLOCK_INPUT;
2396
ab648270 2397 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 2398 report that. */
559cb2fb
JB
2399 if (! XQueryPointer (x_current_display,
2400 SCROLL_BAR_X_WINDOW (bar),
12ba150f 2401
559cb2fb
JB
2402 /* Root, child, root x and root y. */
2403 &dummy_window, &dummy_window,
2404 &dummy_coord, &dummy_coord,
12ba150f 2405
559cb2fb
JB
2406 /* Position relative to scroll bar. */
2407 &win_x, &win_y,
12ba150f 2408
559cb2fb
JB
2409 /* Mouse buttons and modifier keys. */
2410 &dummy_mask))
2411 *f = 0;
2412 else
2413 {
2414 int inside_height
2415 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2416 int top_range
2417 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2418
2419 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2420
2421 if (! NILP (bar->dragging))
2422 win_y -= XINT (bar->dragging);
2423
2424 if (win_y < 0)
2425 win_y = 0;
2426 if (win_y > top_range)
2427 win_y = top_range;
2428
2429 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2430 *bar_window = bar->window;
2431
2432 if (! NILP (bar->dragging))
2433 *part = scroll_bar_handle;
2434 else if (win_y < XINT (bar->start))
2435 *part = scroll_bar_above_handle;
2436 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2437 *part = scroll_bar_handle;
2438 else
2439 *part = scroll_bar_below_handle;
12ba150f 2440
559cb2fb
JB
2441 XSET (*x, Lisp_Int, win_y);
2442 XSET (*y, Lisp_Int, top_range);
12ba150f 2443
559cb2fb
JB
2444 mouse_moved = 0;
2445 last_mouse_scroll_bar = Qnil;
2446 }
12ba150f 2447
559cb2fb 2448 *time = last_mouse_movement_time;
cf7cb199 2449
cf7cb199 2450 UNBLOCK_INPUT;
12ba150f
JB
2451}
2452
f451eb13 2453
dbc4e1c1 2454/* The screen has been cleared so we may have changed foreground or
ab648270
JB
2455 background colors, and the scroll bars may need to be redrawn.
2456 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
2457 redraw them. */
2458
ab648270 2459x_scroll_bar_clear (f)
dbc4e1c1
JB
2460 FRAME_PTR f;
2461{
2462 Lisp_Object bar;
2463
ab648270 2464 for (bar = FRAME_SCROLL_BARS (f);
dbc4e1c1 2465 XTYPE (bar) == Lisp_Vector;
ab648270
JB
2466 bar = XSCROLL_BAR (bar)->next)
2467 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
dbc4e1c1
JB
2468 0, 0, 0, 0, True);
2469}
2470
2471
f451eb13
JB
2472\f
2473/* The main X event-reading loop - XTread_socket. */
dc6f92b8 2474
dc6f92b8
JB
2475/* Timestamp of enter window event. This is only used by XTread_socket,
2476 but we have to put it out here, since static variables within functions
2477 sometimes don't work. */
2478static Time enter_timestamp;
2479
11edeb03
JB
2480/* This holds the state XLookupString needs to implement dead keys
2481 and other tricks known as "compose processing". _X Window System_
2482 says that a portable program can't use this, but Stephen Gildea assures
2483 me that letting the compiler initialize it to zeros will work okay.
2484
2485 This must be defined outside of XTread_socket, for the same reasons
2486 given for enter_timestamp, above. */
2487static XComposeStatus compose_status;
2488
c047688c
JA
2489/* Communication with window managers. */
2490Atom Xatom_wm_protocols;
2491
2492/* Kinds of protocol things we may receive. */
2493Atom Xatom_wm_take_focus;
2494Atom Xatom_wm_save_yourself;
2495Atom Xatom_wm_delete_window;
2496
2497/* Other WM communication */
2498Atom Xatom_wm_configure_denied; /* When our config request is denied */
2499Atom Xatom_wm_window_moved; /* When the WM moves us. */
2500
d56a553a
RS
2501/* Window manager communication. */
2502Atom Xatom_wm_change_state;
2503
10e6549c
RS
2504/* Record the last 100 characters stored
2505 to help debug the loss-of-chars-during-GC problem. */
2506int temp_index;
2507short temp_buffer[100];
2508
dc6f92b8
JB
2509/* Read events coming from the X server.
2510 This routine is called by the SIGIO handler.
2511 We return as soon as there are no more events to be read.
2512
2513 Events representing keys are stored in buffer BUFP,
2514 which can hold up to NUMCHARS characters.
2515 We return the number of characters stored into the buffer,
2516 thus pretending to be `read'.
2517
2518 WAITP is nonzero if we should block until input arrives.
2519 EXPECTED is nonzero if the caller knows input is available. */
2520
7c5283e4 2521int
dc6f92b8
JB
2522XTread_socket (sd, bufp, numchars, waitp, expected)
2523 register int sd;
2524 register struct input_event *bufp;
2525 register int numchars;
2526 int waitp;
2527 int expected;
2528{
2529 int count = 0;
2530 int nbytes = 0;
2531 int mask;
2532 int items_pending; /* How many items are in the X queue. */
2533 XEvent event;
f676886a 2534 struct frame *f;
dc6f92b8
JB
2535 int event_found;
2536 int prefix;
2537 Lisp_Object part;
2538
9ac0d9e0 2539 if (interrupt_input_blocked)
dc6f92b8 2540 {
9ac0d9e0 2541 interrupt_input_pending = 1;
dc6f92b8
JB
2542 return -1;
2543 }
2544
9ac0d9e0 2545 interrupt_input_pending = 0;
dc6f92b8
JB
2546 BLOCK_INPUT;
2547
2548 if (numchars <= 0)
2549 abort (); /* Don't think this happens. */
2550
2551#ifdef FIOSNBIO
2552 /* If available, Xlib uses FIOSNBIO to make the socket
2553 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2554 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2555 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2556 fcntl (fileno (stdin), F_SETFL, 0);
c118dd06 2557#endif /* ! defined (FIOSNBIO) */
dc6f92b8
JB
2558
2559#ifndef SIGIO
2560#ifndef HAVE_SELECT
2561 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2562 {
2563 extern int read_alarm_should_throw;
2564 read_alarm_should_throw = 1;
2565 XPeekEvent (XDISPLAY &event);
2566 read_alarm_should_throw = 0;
2567 }
c118dd06
JB
2568#endif /* HAVE_SELECT */
2569#endif /* SIGIO */
dc6f92b8
JB
2570
2571 while (XStuffPending () != 0)
2572 {
2573 XNextEvent (XDISPLAY &event);
2574 event_found = 1;
2575
2576 switch (event.type)
2577 {
2578#ifdef HAVE_X11
c047688c
JA
2579 case ClientMessage:
2580 {
2581 if (event.xclient.message_type == Xatom_wm_protocols
2582 && event.xclient.format == 32)
2583 {
2584 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2585 {
f676886a
JB
2586 f = x_window_to_frame (event.xclient.window);
2587 if (f)
2588 x_focus_on_frame (f);
ab648270 2589 /* Not certain about handling scroll bars here */
c047688c
JA
2590 }
2591 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2592 {
2593 /* Save state modify the WM_COMMAND property to
2594 something which can reinstate us. This notifies
2595 the session manager, who's looking for such a
2596 PropertyNotify. Can restart processing when
2597 a keyboard or mouse event arrives. */
2598 if (numchars > 0)
2599 {
2600 }
2601 }
2602 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2603 {
f676886a 2604 struct frame *f = x_window_to_frame (event.xclient.window);
c047688c 2605
f676886a 2606 if (f)
c047688c
JA
2607 if (numchars > 0)
2608 {
2609 }
2610 }
2611 }
2612 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2613 {
2614 }
2615 else if (event.xclient.message_type == Xatom_wm_window_moved)
2616 {
2617 int new_x, new_y;
2618
4357eba7
JB
2619 new_x = event.xclient.data.s[0];
2620 new_y = event.xclient.data.s[1];
c047688c
JA
2621 }
2622 }
2623 break;
dc6f92b8 2624
d56a553a
RS
2625#ifdef NEW_SELECTIONS
2626 case SelectionNotify:
2627 x_handle_selection_notify (&event);
2628 break;
2629#endif
2630
dc6f92b8 2631 case SelectionClear: /* Someone has grabbed ownership. */
d56a553a
RS
2632#ifdef NEW_SELECTIONS
2633 {
2634 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2635
2636 if (numchars == 0)
2637 abort ();
2638
2639 bufp->kind = selection_clear_event;
2640 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2641 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2642 SELECTION_EVENT_TIME (bufp) = eventp->time;
2643 bufp++;
2644
2645 count += 1;
2646 numchars -= 1;
2647 }
2648#else
dc6f92b8
JB
2649 x_disown_selection (event.xselectionclear.window,
2650 event.xselectionclear.selection,
2651 event.xselectionclear.time);
d56a553a 2652#endif
dc6f92b8
JB
2653 break;
2654
2655 case SelectionRequest: /* Someone wants our selection. */
d56a553a
RS
2656#ifdef NEW_SELECTIONS
2657 {
2658 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2659
2660 if (numchars == 0)
2661 abort ();
2662
2663 bufp->kind = selection_request_event;
2664 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2665 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2666 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2667 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2668 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2669 SELECTION_EVENT_TIME (bufp) = eventp->time;
2670 bufp++;
2671
2672 count += 1;
2673 numchars -= 1;
2674 }
2675#else
dc6f92b8 2676 x_answer_selection_request (event);
d56a553a 2677#endif
dc6f92b8
JB
2678 break;
2679
2680 case PropertyNotify:
d56a553a
RS
2681#ifdef NEW_SELECTIONS
2682 x_handle_property_notify (&event);
2683#else
28430d3c
JB
2684 /* If we're being told about a root window property, then it's
2685 a cut buffer change. */
2686 if (event.xproperty.window == ROOT_WINDOW)
2687 x_invalidate_cut_buffer_cache (&event.xproperty);
2688
2689 /* Otherwise, we're probably handling an incremental
2690 selection transmission. */
2691 else
2692 {
2693 /* If we were to do this synchronously, there'd be no worry
2694 about re-selecting. */
2695 x_send_incremental (event);
2696 }
d56a553a 2697#endif
dc6f92b8
JB
2698 break;
2699
3bd330d4
RS
2700 case ReparentNotify:
2701 f = x_window_to_frame (event.xreparent.window);
2702 if (f)
2703 f->display.x->parent_desc = event.xreparent.parent;
2704 break;
2705
dc6f92b8 2706 case Expose:
f676886a
JB
2707 f = x_window_to_frame (event.xexpose.window);
2708 if (f)
dc6f92b8 2709 {
3a88c238 2710 if (f->async_visible == 0)
dc6f92b8 2711 {
3a88c238
JB
2712 f->async_visible = 1;
2713 f->async_iconified = 0;
f676886a 2714 SET_FRAME_GARBAGED (f);
dc6f92b8
JB
2715 }
2716 else
f451eb13
JB
2717 {
2718 dumprectangle (x_window_to_frame (event.xexpose.window),
2719 event.xexpose.x, event.xexpose.y,
2720 event.xexpose.width, event.xexpose.height);
f451eb13
JB
2721 }
2722 }
2723 else
2724 {
ab648270
JB
2725 struct scroll_bar *bar
2726 = x_window_to_scroll_bar (event.xexpose.window);
f451eb13
JB
2727
2728 if (bar)
ab648270 2729 x_scroll_bar_expose (bar, &event);
dc6f92b8
JB
2730 }
2731 break;
2732
2733 case GraphicsExpose: /* This occurs when an XCopyArea's
2734 source area was obscured or not
2735 available.*/
f451eb13
JB
2736 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2737 if (f)
2738 {
2739 dumprectangle (f,
2740 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2741 event.xgraphicsexpose.width,
2742 event.xgraphicsexpose.height);
f451eb13 2743 }
dc6f92b8
JB
2744 break;
2745
2746 case NoExpose: /* This occurs when an XCopyArea's
2747 source area was completely
2748 available */
2749 break;
c118dd06 2750#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
2751 case ExposeWindow:
2752 if (event.subwindow != 0)
2753 break; /* duplicate event */
f676886a
JB
2754 f = x_window_to_frame (event.window);
2755 if (event.window == f->display.x->icon_desc)
dc6f92b8 2756 {
f676886a 2757 refreshicon (f);
3a88c238 2758 f->async_iconified = 1;
dc6f92b8 2759 }
c118dd06 2760 if (event.window == FRAME_X_WINDOW (f))
dc6f92b8
JB
2761 {
2762 /* Say must check all windows' needs_exposure flags. */
2763 expose_all_windows = 1;
f676886a 2764 f->display.x->needs_exposure = 1;
3a88c238 2765 f->async_visible = 1;
dc6f92b8
JB
2766 }
2767 break;
2768
2769 case ExposeRegion:
2770 if (event.subwindow != 0)
2771 break; /* duplicate event */
f676886a
JB
2772 f = x_window_to_frame (event.window);
2773 if (event.window == f->display.x->icon_desc)
dc6f92b8 2774 {
f676886a 2775 refreshicon (f);
dc6f92b8
JB
2776 break;
2777 }
2778 /* If window already needs full redraw, ignore this rectangle. */
f676886a 2779 if (expose_all_windows && f->display.x->needs_exposure)
dc6f92b8
JB
2780 break;
2781 /* Put the event on the queue of rectangles to redraw. */
2782 if (enqueue_event (&event, &x_expose_queue))
2783 /* If it is full, we can't record the rectangle,
2784 so redraw this entire window. */
2785 {
2786 /* Say must check all windows' needs_exposure flags. */
2787 expose_all_windows = 1;
f676886a 2788 f->display.x->needs_exposure = 1;
dc6f92b8
JB
2789 }
2790 break;
2791
2792 case ExposeCopy:
2793 /* This should happen only when we are expecting it,
2794 in x_read_exposes. */
2795 abort ();
c118dd06 2796#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
2797
2798#ifdef HAVE_X11
2799 case UnmapNotify:
f451eb13
JB
2800 f = x_window_to_frame (event.xunmap.window);
2801 if (f) /* F may no longer exist if
f676886a 2802 the frame was deleted. */
f451eb13
JB
2803 {
2804 /* While a frame is unmapped, display generation is
2805 disabled; you don't want to spend time updating a
2806 display that won't ever be seen. */
2807 f->async_visible = 0;
2808 }
dc6f92b8
JB
2809 break;
2810
2811 case MapNotify:
f676886a
JB
2812 f = x_window_to_frame (event.xmap.window);
2813 if (f)
dc6f92b8 2814 {
3a88c238
JB
2815 f->async_visible = 1;
2816 f->async_iconified = 0;
dc6f92b8
JB
2817
2818 /* wait_reading_process_input will notice this and update
f676886a
JB
2819 the frame's display structures. */
2820 SET_FRAME_GARBAGED (f);
dc6f92b8
JB
2821 }
2822 break;
2823
2824 /* Turn off processing if we become fully obscured. */
2825 case VisibilityNotify:
2826 break;
2827
c118dd06 2828#else /* ! defined (HAVE_X11) */
dc6f92b8 2829 case UnmapWindow:
f676886a
JB
2830 f = x_window_to_frame (event.window);
2831 if (event.window == f->display.x->icon_desc)
3a88c238 2832 f->async_iconified = 0;
c118dd06 2833 if (event.window == FRAME_X_WINDOW (f))
3a88c238 2834 f->async_visible = 0;
dc6f92b8 2835 break;
c118dd06 2836#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
2837
2838#ifdef HAVE_X11
2839 case KeyPress:
f676886a 2840 f = x_window_to_frame (event.xkey.window);
f451eb13 2841
f676886a 2842 if (f != 0)
dc6f92b8
JB
2843 {
2844 KeySym keysym;
dc6f92b8 2845 char copy_buffer[80];
64bb1782
RS
2846 int modifiers;
2847
dfeccd2d
JB
2848 event.xkey.state
2849 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
64bb1782 2850 modifiers = event.xkey.state;
3a2712f9 2851
11edeb03 2852 /* This will have to go some day... */
752a043f
JB
2853
2854 /* make_lispy_event turns chars into control chars.
2855 Don't do it here because XLookupString is too eager. */
2856 event.xkey.state &= ~ControlMask;
11edeb03
JB
2857 nbytes =
2858 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2859 &compose_status);
dc6f92b8 2860
55123275
JB
2861 /* Strip off the vendor-specific keysym bit, and take a shot
2862 at recognizing the codes. HP servers have extra keysyms
2863 that fit into the MiscFunctionKey category. */
2864 keysym &= ~(1<<28);
2865
dc6f92b8
JB
2866 if (numchars > 1)
2867 {
a3c44b14
RS
2868 if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
2869 || keysym == XK_Delete
2870 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
55123275
JB
2871 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
2872 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2873 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
dc6f92b8 2874 {
10e6549c
RS
2875 if (temp_index == sizeof temp_buffer / sizeof (short))
2876 temp_index = 0;
2877 temp_buffer[temp_index++] = keysym;
dc6f92b8 2878 bufp->kind = non_ascii_keystroke;
a3c44b14 2879 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
12ba150f 2880 XSET (bufp->frame_or_window, Lisp_Frame, f);
dfeccd2d 2881 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
1113d9db 2882 bufp->timestamp = event.xkey.time;
dc6f92b8
JB
2883 bufp++;
2884 count++;
2885 numchars--;
2886 }
2887 else if (numchars > nbytes)
2888 {
2889 register int i;
2890
10e6549c 2891 for (i = 0; i < nbytes; i++)
dc6f92b8 2892 {
10e6549c
RS
2893 if (temp_index == sizeof temp_buffer / sizeof (short))
2894 temp_index = 0;
2895 temp_buffer[temp_index++] = copy_buffer[i];
dc6f92b8 2896 bufp->kind = ascii_keystroke;
10e6549c 2897 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
12ba150f 2898 XSET (bufp->frame_or_window, Lisp_Frame, f);
dfeccd2d 2899 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
1113d9db 2900 bufp->timestamp = event.xkey.time;
dc6f92b8
JB
2901 bufp++;
2902 }
dc6f92b8
JB
2903
2904 count += nbytes;
2905 numchars -= nbytes;
2906 }
10e6549c
RS
2907 else
2908 abort ();
dc6f92b8 2909 }
10e6549c
RS
2910 else
2911 abort ();
dc6f92b8
JB
2912 }
2913 break;
c118dd06 2914#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
2915 case KeyPressed:
2916 {
2917 register char *where_mapping;
2918
f676886a 2919 f = x_window_to_frame (event.window);
dc6f92b8 2920 /* Ignore keys typed on icon windows. */
f676886a 2921 if (f != 0 && event.window == f->display.x->icon_desc)
dc6f92b8
JB
2922 break;
2923 where_mapping = XLookupMapping (&event, &nbytes);
2924 /* Nasty fix for arrow keys */
2925 if (!nbytes && IsCursorKey (event.detail & 0xff))
2926 {
2927 switch (event.detail & 0xff)
2928 {
2929 case KC_CURSOR_LEFT:
2930 where_mapping = "\002";
2931 break;
2932 case KC_CURSOR_RIGHT:
2933 where_mapping = "\006";
2934 break;
2935 case KC_CURSOR_UP:
2936 where_mapping = "\020";
2937 break;
2938 case KC_CURSOR_DOWN:
2939 where_mapping = "\016";
2940 break;
2941 }
2942 nbytes = 1;
2943 }
2944 if (numchars - nbytes > 0)
2945 {
2946 register int i;
2947
2948 for (i = 0; i < nbytes; i++)
2949 {
2950 bufp->kind = ascii_keystroke;
2951 XSET (bufp->code, Lisp_Int, where_mapping[i]);
90e65f07 2952 XSET (bufp->time, Lisp_Int, event.xkey.time);
12ba150f 2953 XSET (bufp->frame_or_window, Lisp_Frame, f);
dc6f92b8
JB
2954 bufp++;
2955 }
2956 count += nbytes;
2957 numchars -= nbytes;
2958 }
2959 }
2960 break;
c118dd06 2961#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
2962
2963#ifdef HAVE_X11
f451eb13
JB
2964
2965 /* Here's a possible interpretation of the whole
2966 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2967 FocusIn event, you have to get a FocusOut event before you
2968 relinquish the focus. If you haven't received a FocusIn event,
2969 then a mere LeaveNotify is enough to free you. */
2970
dc6f92b8 2971 case EnterNotify:
f676886a 2972 f = x_window_to_frame (event.xcrossing.window);
6d4238f3 2973
f451eb13 2974 if (event.xcrossing.focus) /* Entered Window */
dc6f92b8 2975 {
dc6f92b8 2976 /* Avoid nasty pop/raise loops. */
f676886a
JB
2977 if (f && (!(f->auto_raise)
2978 || !(f->auto_lower)
dc6f92b8
JB
2979 || (event.xcrossing.time - enter_timestamp) > 500))
2980 {
f676886a 2981 x_new_focus_frame (f);
dc6f92b8
JB
2982 enter_timestamp = event.xcrossing.time;
2983 }
dc6f92b8 2984 }
f676886a
JB
2985 else if (f == x_focus_frame)
2986 x_new_focus_frame (0);
dc6f92b8
JB
2987
2988 break;
2989
2990 case FocusIn:
f676886a 2991 f = x_window_to_frame (event.xfocus.window);
f451eb13
JB
2992 if (event.xfocus.detail != NotifyPointer)
2993 x_focus_event_frame = f;
f676886a
JB
2994 if (f)
2995 x_new_focus_frame (f);
dc6f92b8
JB
2996 break;
2997
f451eb13 2998
dc6f92b8 2999 case LeaveNotify:
f451eb13 3000 f = x_window_to_frame (event.xcrossing.window);
b1c884c3 3001
f451eb13
JB
3002 if (event.xcrossing.focus)
3003 {
3004 if (! x_focus_event_frame)
3005 x_new_focus_frame (0);
3006 else
f676886a 3007 x_new_focus_frame (f);
f451eb13
JB
3008 }
3009 else
3010 {
3011 if (f == x_focus_event_frame)
3012 x_focus_event_frame = 0;
3013 if (f == x_focus_frame)
f676886a 3014 x_new_focus_frame (0);
dc6f92b8
JB
3015 }
3016 break;
3017
3018 case FocusOut:
f676886a 3019 f = x_window_to_frame (event.xfocus.window);
f451eb13
JB
3020 if (event.xfocus.detail != NotifyPointer
3021 && f == x_focus_event_frame)
3022 x_focus_event_frame = 0;
f676886a
JB
3023 if (f && f == x_focus_frame)
3024 x_new_focus_frame (0);
dc6f92b8
JB
3025 break;
3026
c118dd06 3027#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
3028
3029 case EnterWindow:
3030 if ((event.detail & 0xFF) == 1)
3031 break; /* Coming from our own subwindow */
3032 if (event.subwindow != 0)
3033 break; /* Entering our own subwindow. */
3034
3035 {
f676886a
JB
3036 f = x_window_to_frame (event.window);
3037 x_mouse_frame = f;
dc6f92b8 3038
f676886a 3039 x_new_focus_frame (f);
dc6f92b8
JB
3040 }
3041 break;
3042
3043 case LeaveWindow:
3044 if ((event.detail & 0xFF) == 1)
3045 break; /* Entering our own subwindow */
3046 if (event.subwindow != 0)
3047 break; /* Leaving our own subwindow. */
3048
f676886a
JB
3049 x_mouse_frame = 0;
3050 if (x_focus_frame == 0
3051 && x_input_frame != 0
3052 && x_input_frame == x_window_to_frame (event.window)
c118dd06 3053 && event.window == FRAME_X_WINDOW (x_input_frame))
dc6f92b8 3054 {
f676886a
JB
3055 f = x_input_frame;
3056 x_input_frame = 0;
3057 if (f)
3058 frame_unhighlight (f);
dc6f92b8
JB
3059 }
3060 break;
c118dd06 3061#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3062
3063#ifdef HAVE_X11
3064 case MotionNotify:
3065 {
f676886a
JB
3066 f = x_window_to_frame (event.xmotion.window);
3067 if (f)
12ba150f 3068 note_mouse_movement (f, &event.xmotion);
f451eb13 3069 else
dc6f92b8 3070 {
ab648270
JB
3071 struct scroll_bar *bar =
3072 x_window_to_scroll_bar (event.xmotion.window);
f451eb13
JB
3073
3074 if (bar)
ab648270 3075 x_scroll_bar_note_movement (bar, &event);
dc6f92b8 3076 }
dc6f92b8
JB
3077 }
3078 break;
3079
3080 case ConfigureNotify:
dbc4e1c1
JB
3081 f = x_window_to_frame (event.xconfigure.window);
3082 if (f)
3083 {
3084 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3085 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3086
3087 /* Even if the number of character rows and columns has
3088 not changed, the font size may have changed, so we need
3089 to check the pixel dimensions as well. */
3090 if (columns != f->width
3091 || rows != f->height
3092 || event.xconfigure.width != f->display.x->pixel_width
3093 || event.xconfigure.height != f->display.x->pixel_height)
3094 {
3095 change_frame_size (f, rows, columns, 0, 1);
3096 SET_FRAME_GARBAGED (f);
3097 }
dc6f92b8 3098
3bd330d4 3099 if (! event.xconfigure.send_event)
af395ec1
RS
3100 {
3101 Window win, child;
3102 int win_x, win_y;
3103
3bd330d4
RS
3104 /* Coords are relative to the parent.
3105 Convert them to root-relative. */
af395ec1
RS
3106 XTranslateCoordinates (x_current_display,
3107
3108 /* From-window, to-window. */
3bd330d4
RS
3109 f->display.x->parent_desc,
3110 ROOT_WINDOW,
af395ec1
RS
3111
3112 /* From-position, to-position. */
3113 event.xconfigure.x,
3114 event.xconfigure.y,
3115 &win_x, &win_y,
3116
3117 /* Child of win. */
3118 &child);
3119 event.xconfigure.x = win_x;
3120 event.xconfigure.y = win_y;
3121 }
3122
dbc4e1c1
JB
3123 f->display.x->pixel_width = event.xconfigure.width;
3124 f->display.x->pixel_height = event.xconfigure.height;
3125 f->display.x->left_pos = event.xconfigure.x;
3126 f->display.x->top_pos = event.xconfigure.y;
3127 }
3128 break;
dc6f92b8
JB
3129
3130 case ButtonPress:
3131 case ButtonRelease:
3132 {
3133 /* If we decide we want to generate an event to be seen
3134 by the rest of Emacs, we put it here. */
3135 struct input_event emacs_event;
3136 emacs_event.kind = no_event;
3137
f676886a
JB
3138 f = x_window_to_frame (event.xbutton.window);
3139 if (f)
f451eb13
JB
3140 {
3141 if (!x_focus_frame || (f == x_focus_frame))
3142 construct_mouse_click (&emacs_event,
b10fd412 3143 &event, f);
f451eb13 3144 }
dc6f92b8 3145 else
f451eb13 3146 {
ab648270
JB
3147 struct scroll_bar *bar =
3148 x_window_to_scroll_bar (event.xbutton.window);
f451eb13
JB
3149
3150 if (bar)
ab648270 3151 x_scroll_bar_handle_click (bar, &event, &emacs_event);
f451eb13 3152 }
dc6f92b8
JB
3153
3154 if (numchars >= 1 && emacs_event.kind != no_event)
3155 {
3156 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3157 bufp++;
3158 count++;
3159 numchars--;
3160 }
3161 }
3162 break;
3163
c118dd06 3164#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
3165 case ButtonPressed:
3166 case ButtonReleased:
f676886a
JB
3167 f = x_window_to_frame (event.window);
3168 if (f)
dc6f92b8 3169 {
f676886a 3170 if (event.window == f->display.x->icon_desc)
dc6f92b8 3171 {
f676886a 3172 x_make_frame_visible (f);
dc6f92b8
JB
3173
3174 if (warp_mouse_on_deiconify)
c118dd06 3175 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
dc6f92b8
JB
3176 break;
3177 }
c118dd06 3178 if (event.window == FRAME_X_WINDOW (f))
dc6f92b8 3179 {
f676886a
JB
3180 if (f->auto_raise)
3181 x_raise_frame (f);
dc6f92b8
JB
3182 }
3183 }
3184 enqueue_event (&event, &x_mouse_queue);
3185 if (numchars >= 2)
3186 {
3187 bufp->kind = ascii_keystroke;
3188 bufp->code = (char) 'X' & 037; /* C-x */
12ba150f 3189 XSET (bufp->frame_or_window, Lisp_Frame, f);
90e65f07 3190 XSET (bufp->time, Lisp_Int, event.xkey.time);
dc6f92b8
JB
3191 bufp++;
3192
3193 bufp->kind = ascii_keystroke;
3194 bufp->code = (char) 0; /* C-@ */
12ba150f 3195 XSET (bufp->frame_or_window, Lisp_Frame, f);
90e65f07 3196 XSET (bufp->time, Lisp_Int, event.xkey.time);
dc6f92b8
JB
3197 bufp++;
3198
3199 count += 2;
3200 numchars -= 2;
3201 }
3202 break;
c118dd06 3203#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3204
3205#ifdef HAVE_X11
3206
3207 case CirculateNotify:
3208 break;
3209 case CirculateRequest:
3210 break;
3211
c118dd06 3212#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3213
3214 case MappingNotify:
11edeb03
JB
3215 /* Someone has changed the keyboard mapping - update the
3216 local cache. */
3217 switch (event.xmapping.request)
3218 {
3219 case MappingModifier:
3220 x_find_modifier_meanings ();
3221 /* This is meant to fall through. */
3222 case MappingKeyboard:
3223 XRefreshKeyboardMapping (&event.xmapping);
3224 }
dc6f92b8
JB
3225 break;
3226
3227 default:
3228 break;
3229 }
3230 }
3231
3232#if 0
3233#ifdef HAVE_SELECT
3234 if (expected && ! event_found)
3235 {
3236 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3237 there is an EOF condition; in other words, that X has died.
3238 Act as if there had been a hangup. */
3239
3240 int fd = ConnectionNumber (x_current_display);
3241 int mask = 1 << fd;
3242
3243 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3a2712f9 3244 (EMACS_TIME) 0)
dc6f92b8
JB
3245 && !XStuffPending ())
3246 kill (getpid (), SIGHUP);
3247 }
c118dd06
JB
3248#endif /* ! defined (HAVE_SELECT) */
3249#endif /* ! 0 */
dc6f92b8 3250
f451eb13 3251#ifndef HAVE_X11
f676886a 3252 if (updating_frame == 0)
dc6f92b8 3253 x_do_pending_expose ();
f451eb13 3254#endif
dc6f92b8
JB
3255
3256 UNBLOCK_INPUT;
3257 return count;
3258}
3259
3260#ifndef HAVE_X11
3261/* Read and process only Expose events
3262 until we get an ExposeCopy event; then return.
3263 This is used in insert/delete line.
3264 We assume input is already blocked. */
3265
3266static void
3267x_read_exposes ()
3268{
f676886a 3269 struct frame *f;
dc6f92b8
JB
3270 XKeyPressedEvent event;
3271
3272 while (1)
3273 {
3274 /* while there are more events*/
3275 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3276 switch (event.type)
3277 {
3278 case ExposeWindow:
3279 if (event.subwindow != 0)
3280 break; /* duplicate event */
f676886a
JB
3281 f = x_window_to_frame (event.window);
3282 if (event.window == f->display.x->icon_desc)
dc6f92b8 3283 {
f676886a 3284 refreshicon (f);
dc6f92b8
JB
3285 break;
3286 }
c118dd06 3287 if (event.window == FRAME_X_WINDOW (f))
dc6f92b8
JB
3288 {
3289 expose_all_windows = 1;
f676886a 3290 f->display.x->needs_exposure = 1;
dc6f92b8
JB
3291 break;
3292 }
3293 break;
3294
3295 case ExposeRegion:
3296 if (event.subwindow != 0)
3297 break; /* duplicate event */
f676886a
JB
3298 f = x_window_to_frame (event.window);
3299 if (event.window == f->display.x->icon_desc)
dc6f92b8 3300 {
f676886a 3301 refreshicon (f);
dc6f92b8
JB
3302 break;
3303 }
3304 /* If window already needs full redraw, ignore this rectangle. */
f676886a 3305 if (expose_all_windows && f->display.x->needs_exposure)
dc6f92b8
JB
3306 break;
3307 /* Put the event on the queue of rectangles to redraw. */
3308 if (enqueue_event (&event, &x_expose_queue))
3309 /* If it is full, we can't record the rectangle,
3310 so redraw this entire window. */
3311 {
3312 /* Say must check all windows' needs_exposure flags. */
3313 expose_all_windows = 1;
f676886a 3314 f->display.x->needs_exposure = 1;
dc6f92b8
JB
3315 }
3316 break;
3317
3318 case ExposeCopy:
3319 return;
3320 }
3321 }
3322}
3323#endif /* HAVE_X11 */
3324
dc6f92b8 3325\f
f451eb13
JB
3326/* Drawing the cursor. */
3327
3328
dc6f92b8
JB
3329/* Draw a hollow box cursor. Don't change the inside of the box. */
3330
3331static void
f676886a
JB
3332x_draw_box (f)
3333 struct frame *f;
dc6f92b8 3334{
12ba150f
JB
3335 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3336 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
f676886a
JB
3337 int width = FONT_WIDTH (f->display.x->font);
3338 int height = FONT_HEIGHT (f->display.x->font);
dc6f92b8
JB
3339
3340#ifdef HAVE_X11
c118dd06 3341 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
f676886a 3342 f->display.x->cursor_gc,
dc6f92b8 3343 left, top, width - 1, height - 1);
c118dd06
JB
3344#else /* ! defined (HAVE_X11) */
3345 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3346 left, top, width, 1,
f676886a 3347 f->display.x->cursor_pixel);
dc6f92b8 3348
c118dd06 3349 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3350 left, top, 1, height,
f676886a 3351 f->display.x->cursor_pixel);
dc6f92b8 3352
c118dd06 3353 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3354 left+width-1, top, 1, height,
f676886a 3355 f->display.x->cursor_pixel);
dc6f92b8 3356
c118dd06 3357 XPixSet (FRAME_X_WINDOW (f),
dc6f92b8 3358 left, top+height-1, width, 1,
f676886a 3359 f->display.x->cursor_pixel);
c118dd06 3360#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3361}
3362
f676886a 3363/* Clear the cursor of frame F to background color,
dc6f92b8
JB
3364 and mark the cursor as not shown.
3365 This is used when the text where the cursor is
3366 is about to be rewritten. */
3367
3368static void
f676886a
JB
3369clear_cursor (f)
3370 struct frame *f;
dc6f92b8
JB
3371{
3372 int mask;
3373
f451eb13 3374 if (! FRAME_VISIBLE_P (f)
f676886a 3375 || f->phys_cursor_x < 0)
dc6f92b8
JB
3376 return;
3377
3378#ifdef HAVE_X11
f676886a 3379 x_display_cursor (f, 0);
c118dd06
JB
3380#else /* ! defined (HAVE_X11) */
3381 XPixSet (FRAME_X_WINDOW (f),
12ba150f
JB
3382 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3383 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
f676886a
JB
3384 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3385 f->display.x->background_pixel);
c118dd06 3386#endif /* ! defined (HAVE_X11) */
f676886a 3387 f->phys_cursor_x = -1;
dc6f92b8
JB
3388}
3389
f676886a 3390/* Redraw the glyph at ROW, COLUMN on frame F, in the style
90e65f07
JB
3391 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3392 glyph drawn. */
dc6f92b8
JB
3393
3394static void
f676886a
JB
3395x_draw_single_glyph (f, row, column, glyph, highlight)
3396 struct frame *f;
dc6f92b8 3397 int row, column;
90e65f07 3398 GLYPH glyph;
dc6f92b8
JB
3399 int highlight;
3400{
f676886a 3401 dumpglyphs (f,
12ba150f
JB
3402 CHAR_TO_PIXEL_COL (f, column),
3403 CHAR_TO_PIXEL_ROW (f, row),
07e34cb0 3404 &glyph, 1, highlight);
dc6f92b8
JB
3405}
3406
dc6f92b8 3407static void
dbc4e1c1 3408x_display_bar_cursor (f, on)
f676886a 3409 struct frame *f;
dc6f92b8
JB
3410 int on;
3411{
f676886a 3412 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
90e65f07 3413
49d838ea
JB
3414 /* This is pointless on invisible frames, and dangerous on garbaged
3415 frames; in the latter case, the frame may be in the midst of
3416 changing its size, and curs_x and curs_y may be off the frame. */
3417 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dbc4e1c1
JB
3418 return;
3419
3420 if (! on && f->phys_cursor_x < 0)
3421 return;
3422
f676886a 3423 /* If we're not updating, then we want to use the current frame's
1113d9db 3424 cursor position, not our local idea of where the cursor ought to be. */
f676886a 3425 if (f != updating_frame)
1113d9db 3426 {
f676886a
JB
3427 curs_x = FRAME_CURSOR_X (f);
3428 curs_y = FRAME_CURSOR_Y (f);
1113d9db
JB
3429 }
3430
dbc4e1c1
JB
3431 /* If there is anything wrong with the current cursor state, remove it. */
3432 if (f->phys_cursor_x >= 0
3433 && (!on
3434 || f->phys_cursor_x != curs_x
3435 || f->phys_cursor_y != curs_y
3436 || f->display.x->current_cursor != bar_cursor))
3437 {
3438 /* Erase the cursor by redrawing the character underneath it. */
3439 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3440 f->phys_cursor_glyph,
3441 current_glyphs->highlight[f->phys_cursor_y]);
3442 f->phys_cursor_x = -1;
3443 }
3444
3445 /* If we now need a cursor in the new place or in the new form, do it so. */
3446 if (on
3447 && (f->phys_cursor_x < 0
3448 || (f->display.x->current_cursor != bar_cursor)))
3449 {
3450 f->phys_cursor_glyph
3451 = ((current_glyphs->enable[curs_y]
3452 && curs_x < current_glyphs->used[curs_y])
3453 ? current_glyphs->glyphs[curs_y][curs_x]
3454 : SPACEGLYPH);
3455 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3456 f->display.x->cursor_gc,
3457 CHAR_TO_PIXEL_COL (f, curs_x),
3458 CHAR_TO_PIXEL_ROW (f, curs_y),
3459 1, FONT_HEIGHT (f->display.x->font));
3460
3461 f->phys_cursor_x = curs_x;
3462 f->phys_cursor_y = curs_y;
3463
3464 f->display.x->current_cursor = bar_cursor;
3465 }
3466
3467 if (updating_frame != f)
3468 XFlushQueue ();
3469}
3470
3471
3472/* Turn the displayed cursor of frame F on or off according to ON.
3473 If ON is nonzero, where to put the cursor is specified
3474 by F->cursor_x and F->cursor_y. */
3475
3476static void
3477x_display_box_cursor (f, on)
3478 struct frame *f;
3479 int on;
3480{
3481 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3482
49d838ea
JB
3483 /* This is pointless on invisible frames, and dangerous on garbaged
3484 frames; in the latter case, the frame may be in the midst of
3485 changing its size, and curs_x and curs_y may be off the frame. */
3486 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
dc6f92b8
JB
3487 return;
3488
3489 /* If cursor is off and we want it off, return quickly. */
f676886a 3490 if (!on && f->phys_cursor_x < 0)
dc6f92b8
JB
3491 return;
3492
dbc4e1c1
JB
3493 /* If we're not updating, then we want to use the current frame's
3494 cursor position, not our local idea of where the cursor ought to be. */
3495 if (f != updating_frame)
3496 {
3497 curs_x = FRAME_CURSOR_X (f);
3498 curs_y = FRAME_CURSOR_Y (f);
3499 }
3500
dc6f92b8
JB
3501 /* If cursor is currently being shown and we don't want it to be
3502 or it is in the wrong place,
3503 or we want a hollow box and it's not so, (pout!)
3504 erase it. */
f676886a 3505 if (f->phys_cursor_x >= 0
dc6f92b8 3506 && (!on
f676886a
JB
3507 || f->phys_cursor_x != curs_x
3508 || f->phys_cursor_y != curs_y
dbc4e1c1 3509 || (f->display.x->current_cursor != hollow_box_cursor
f676886a 3510 && (f != x_highlight_frame))))
dc6f92b8
JB
3511 {
3512 /* Erase the cursor by redrawing the character underneath it. */
f676886a
JB
3513 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3514 f->phys_cursor_glyph,
3515 current_glyphs->highlight[f->phys_cursor_y]);
3516 f->phys_cursor_x = -1;
dc6f92b8
JB
3517 }
3518
3519 /* If we want to show a cursor,
3520 or we want a box cursor and it's not so,
3521 write it in the right place. */
3522 if (on
f676886a 3523 && (f->phys_cursor_x < 0
dbc4e1c1 3524 || (f->display.x->current_cursor != filled_box_cursor
f676886a 3525 && f == x_highlight_frame)))
dc6f92b8 3526 {
f676886a 3527 f->phys_cursor_glyph
1113d9db
JB
3528 = ((current_glyphs->enable[curs_y]
3529 && curs_x < current_glyphs->used[curs_y])
3530 ? current_glyphs->glyphs[curs_y][curs_x]
90e65f07 3531 : SPACEGLYPH);
f676886a 3532 if (f != x_highlight_frame)
dc6f92b8 3533 {
f676886a 3534 x_draw_box (f);
dbc4e1c1 3535 f->display.x->current_cursor = hollow_box_cursor;
dc6f92b8
JB
3536 }
3537 else
3538 {
f676886a
JB
3539 x_draw_single_glyph (f, curs_y, curs_x,
3540 f->phys_cursor_glyph, 2);
dbc4e1c1 3541 f->display.x->current_cursor = filled_box_cursor;
dc6f92b8
JB
3542 }
3543
f676886a
JB
3544 f->phys_cursor_x = curs_x;
3545 f->phys_cursor_y = curs_y;
dc6f92b8
JB
3546 }
3547
f676886a 3548 if (updating_frame != f)
dc6f92b8
JB
3549 XFlushQueue ();
3550}
3551
f676886a
JB
3552x_display_cursor (f, on)
3553 struct frame *f;
dc6f92b8
JB
3554 int on;
3555{
dbc4e1c1 3556 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
f676886a 3557 x_display_box_cursor (f, on);
dbc4e1c1 3558 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
f676886a 3559 x_display_bar_cursor (f, on);
dbc4e1c1
JB
3560 else
3561 /* Those are the only two we have implemented! */
3562 abort ();
dc6f92b8
JB
3563}
3564\f
3565/* Icons. */
3566
f676886a 3567/* Refresh bitmap kitchen sink icon for frame F
dc6f92b8
JB
3568 when we get an expose event for it. */
3569
f676886a
JB
3570refreshicon (f)
3571 struct frame *f;
dc6f92b8
JB
3572{
3573#ifdef HAVE_X11
3574 /* Normally, the window manager handles this function. */
c118dd06 3575#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
3576 int mask;
3577
f676886a
JB
3578 if (f->display.x->icon_bitmap_flag)
3579 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
dc6f92b8
JB
3580 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3581 icon_bitmap, GXcopy, AllPlanes);
3582 else
3583 {
f676886a 3584 extern struct frame *selected_frame;
dc6f92b8
JB
3585 struct Lisp_String *str;
3586 unsigned char *string;
3587
3588 string
f676886a 3589 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
dc6f92b8 3590
f676886a 3591 if (f->display.x->icon_label != string)
dc6f92b8 3592 {
f676886a
JB
3593 f->display.x->icon_label = string;
3594 XChangeWindow (f->display.x->icon_desc,
dc6f92b8
JB
3595 XQueryWidth (string, icon_font_info->id) + 10,
3596 icon_font_info->height + 10);
3597 }
3598
f676886a 3599 XText (f->display.x->icon_desc, 5, 5, string,
dc6f92b8
JB
3600 str->size, icon_font_info->id,
3601 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3602 }
3603 XFlushQueue ();
c118dd06 3604#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3605}
3606
dbc4e1c1 3607/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
3608
3609int
f676886a
JB
3610x_bitmap_icon (f)
3611 struct frame *f;
dc6f92b8
JB
3612{
3613 int mask;
3614 Window icon_window;
3615
c118dd06 3616 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
3617 return 1;
3618
3619#ifdef HAVE_X11
3620 if (icon_bitmap)
3621 XFreePixmap (x_current_display, icon_bitmap);
3622
3623 icon_bitmap =
c118dd06 3624 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
dc6f92b8 3625 gnu_bits, gnu_width, gnu_height);
f676886a
JB
3626 x_wm_set_icon_pixmap (f, icon_bitmap);
3627 f->display.x->icon_bitmap_flag = 1;
c118dd06 3628#else /* ! defined (HAVE_X11) */
f676886a 3629 if (f->display.x->icon_desc)
dc6f92b8 3630 {
c118dd06 3631 XClearIconWindow (FRAME_X_WINDOW (f));
f676886a 3632 XDestroyWindow (f->display.x->icon_desc);
dc6f92b8
JB
3633 }
3634
f676886a 3635 icon_window = XCreateWindow (f->display.x->parent_desc,
dc6f92b8
JB
3636 0, 0, sink_width, sink_height,
3637 2, WhitePixmap, (Pixmap) NULL);
3638
3639 if (icon_window == 0)
3640 return 1;
3641
c118dd06 3642 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
dc6f92b8
JB
3643 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3644
f676886a
JB
3645 f->display.x->icon_desc = icon_window;
3646 f->display.x->icon_bitmap_flag = 1;
dc6f92b8
JB
3647
3648 if (icon_bitmap == 0)
3649 icon_bitmap
3650 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
c118dd06 3651#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3652
3653 return 0;
3654}
3655
3656
f676886a 3657/* Make the x-window of frame F use a rectangle with text. */
dc6f92b8
JB
3658
3659int
f676886a
JB
3660x_text_icon (f, icon_name)
3661 struct frame *f;
dc6f92b8
JB
3662 char *icon_name;
3663{
3664#ifndef HAVE_X11
3665 int mask;
3666 int width;
3667 Window icon_window;
3668 char *X_DefaultValue;
3669 Bitmap b1;
3670
dc6f92b8
JB
3671#ifndef WhitePixel
3672#define WhitePixel 1
c118dd06 3673#endif /* WhitePixel */
dc6f92b8
JB
3674
3675#ifndef BlackPixel
3676#define BlackPixel 0
c118dd06
JB
3677#endif /* BlackPixel */
3678#endif /* HAVE_X11 */
dc6f92b8 3679
c118dd06 3680 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
3681 return 1;
3682
dc6f92b8
JB
3683#ifdef HAVE_X11
3684 if (icon_name)
f676886a 3685 f->display.x->icon_label = icon_name;
dc6f92b8 3686 else
f676886a
JB
3687 if (! f->display.x->icon_label)
3688 f->display.x->icon_label = " *emacs* ";
dc6f92b8 3689
dfeccd2d 3690#if 0
c118dd06 3691 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
f676886a 3692 (char *) f->display.x->icon_label);
dfeccd2d 3693#endif
dc6f92b8 3694
f676886a 3695 f->display.x->icon_bitmap_flag = 0;
b1c884c3 3696 x_wm_set_icon_pixmap (f, 0);
c118dd06 3697#else /* ! defined (HAVE_X11) */
dbc4e1c1
JB
3698 if (icon_font_info == 0)
3699 icon_font_info
3700 = XGetFont (XGetDefault (XDISPLAY
59653951 3701 (char *) XSTRING (Vinvocation_name)->data,
dbc4e1c1
JB
3702 "BodyFont"));
3703
f676886a 3704 if (f->display.x->icon_desc)
dc6f92b8 3705 {
c118dd06 3706 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
f676886a 3707 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
dc6f92b8
JB
3708 }
3709
3710 if (icon_name)
f676886a 3711 f->display.x->icon_label = (unsigned char *) icon_name;
dc6f92b8 3712 else
f676886a
JB
3713 if (! f->display.x->icon_label)
3714 f->display.x->icon_label = XSTRING (f->name)->data;
dc6f92b8 3715
f676886a
JB
3716 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3717 icon_window = XCreateWindow (f->display.x->parent_desc,
3718 f->display.x->left_pos,
3719 f->display.x->top_pos,
dc6f92b8
JB
3720 width + 10, icon_font_info->height + 10,
3721 2, BlackPixmap, WhitePixmap);
3722
3723 if (icon_window == 0)
3724 return 1;
3725
c118dd06 3726 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
dc6f92b8
JB
3727 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3728
f676886a
JB
3729 f->display.x->icon_desc = icon_window;
3730 f->display.x->icon_bitmap_flag = 0;
3731 f->display.x->icon_label = 0;
c118dd06 3732#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
3733
3734 return 0;
3735}
3736\f
4746118a
JB
3737/* Handling X errors. */
3738
12ba150f
JB
3739/* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3740 X server's connection, or an error reported via the X protocol. */
16bd92ea 3741
4746118a 3742static SIGTYPE
c118dd06 3743x_connection_closed ()
4746118a
JB
3744{
3745 if (_Xdebug)
3746 abort ();
12ba150f
JB
3747
3748 shut_down_emacs (0);
3749
3750 exit (70);
4746118a
JB
3751}
3752
8922af5f
JB
3753/* An X error handler which prints an error message and then kills
3754 Emacs. This is what's normally installed as Xlib's handler for
3755 protocol errors. */
c118dd06
JB
3756static int
3757x_error_quitter (display, error)
3758 Display *display;
3759 XErrorEvent *error;
3760{
3761 char buf[256];
dc6f92b8 3762
c118dd06
JB
3763 /* Note that there is no real way portable across R3/R4 to get the
3764 original error handler. */
dc6f92b8 3765
c118dd06
JB
3766 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3767 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3768 buf, error->request_code);
dc6f92b8 3769
12ba150f
JB
3770 /* While we're testing Emacs 19, we'll just dump core whenever we
3771 get an X error, so we can figure out why it happened. */
3772 abort ();
3773
c118dd06 3774 x_connection_closed ();
dc6f92b8
JB
3775}
3776
8922af5f
JB
3777/* A handler for X IO errors which prints an error message and then
3778 kills Emacs. This is what is always installed as Xlib's handler
3779 for I/O errors. */
3780static int
3781x_io_error_quitter (display)
3782 Display *display;
3783{
3784 fprintf (stderr, "Connection to X server %s lost.\n",
3785 XDisplayName (DisplayString (display)));
3786
3787 /* While we're testing Emacs 19, we'll just dump core whenever we
3788 get an X error, so we can figure out why it happened. */
3789 abort ();
3790
3791 x_connection_closed ();
3792}
3793
c118dd06
JB
3794/* A buffer for storing X error messages. */
3795static char (*x_caught_error_message)[200];
3796
3797/* An X error handler which stores the error message in
3798 x_caught_error_message. This is what's installed when
3799 x_catch_errors is in effect. */
3800static int
3801x_error_catcher (display, error)
3802 Display *display;
3803 XErrorEvent *error;
3804{
3805 XGetErrorText (display, error->error_code,
3806 *x_caught_error_message, sizeof (*x_caught_error_message));
3807}
3808
3809
3810/* Begin trapping X errors.
dc6f92b8 3811
c118dd06
JB
3812 After calling this function, X protocol errors no longer cause
3813 Emacs to exit; instead, they are recorded in x_cfc_error_message.
dc6f92b8 3814
c118dd06
JB
3815 Calling x_check_errors signals an Emacs error if an X error has
3816 occurred since the last call to x_catch_errors or x_check_errors.
3817
3818 Calling x_uncatch_errors resumes the normal error handling. */
3819
3820void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3821
3822void
3823x_catch_errors ()
dc6f92b8 3824{
c118dd06
JB
3825 /* Make sure any errors from previous requests have been dealt with. */
3826 XSync (x_current_display, False);
dc6f92b8 3827
c118dd06
JB
3828 /* Set up the error buffer. */
3829 x_caught_error_message =
3830 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
d872b748 3831 (*x_caught_error_message)[0] = '\0';
16bd92ea 3832
c118dd06
JB
3833 /* Install our little error handler. */
3834 XHandleError (x_error_catcher);
3835}
16bd92ea 3836
c118dd06
JB
3837/* If any X protocol errors have arrived since the last call to
3838 x_catch_errors or x_check_errors, signal an Emacs error using
3839 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3840void
3841x_check_errors (format)
3842 char *format;
3843{
3844 /* Make sure to catch any errors incurred so far. */
3845 XSync (x_current_display, False);
16bd92ea 3846
c118dd06
JB
3847 if ((*x_caught_error_message)[0])
3848 {
3849 char buf[256];
3850
3851 sprintf (buf, format, *x_caught_error_message);
9ac0d9e0 3852 xfree (x_caught_error_message);
dc6f92b8 3853
c118dd06
JB
3854 x_uncatch_errors ();
3855 error (buf);
3856 }
3857}
3858
3859void
3860x_uncatch_errors ()
3861{
9ac0d9e0 3862 xfree (x_caught_error_message);
c118dd06 3863 XHandleError (x_error_quitter);
dc6f92b8
JB
3864}
3865
dc6f92b8
JB
3866#if 0
3867static unsigned int x_wire_count;
3868x_trace_wire ()
3869{
3870 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3871}
c118dd06 3872#endif /* ! 0 */
dc6f92b8
JB
3873
3874\f
f451eb13
JB
3875/* Changing the font of the frame. */
3876
f676886a 3877/* Set the font of the x-window specified by frame F
dc6f92b8 3878 to the font named NEWNAME. This is safe to use
f676886a 3879 even before F has an actual x-window. */
dc6f92b8
JB
3880
3881#ifdef HAVE_X11
3882
3883/* A table of all the fonts we have already loaded. */
3884static XFontStruct **x_font_table;
3885
3886/* The current capacity of x_font_table. */
3887static int x_font_table_size;
3888
3889/* The number of fonts actually stored in x_font_table.
3890 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3891 0 <= n_fonts <= x_font_table_size. */
3892static int n_fonts;
3893
f676886a
JB
3894x_new_font (f, fontname)
3895 struct frame *f;
dc6f92b8
JB
3896 register char *fontname;
3897{
3898 XFontStruct *temp;
3899 int already_loaded;
3900 int n_matching_fonts;
3901 XFontStruct *font_info;
3902 char **font_names;
3903
3904 /* Get a list of all the fonts that match this name. Once we
3905 have a list of matching fonts, we compare them against the fonts
3906 we already have by comparing font ids. */
3907 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3908 1024, &n_matching_fonts,
3909 &font_info);
9696f58b 3910
dc6f92b8
JB
3911 /* If the server couldn't find any fonts whose named matched fontname,
3912 return an error code. */
3913 if (n_matching_fonts == 0)
3914 return 1;
3915
90e65f07 3916 /* See if we've already loaded a matching font. */
dc6f92b8
JB
3917 {
3918 int i, j;
3919
3920 already_loaded = 0;
3921 for (i = 0; i < n_fonts; i++)
3922 for (j = 0; j < n_matching_fonts; j++)
3923 if (x_font_table[i]->fid == font_info[j].fid)
3924 {
3925 already_loaded = i;
3926 goto found_font;
3927 }
3928 }
3929 found_font:
3930
3931 /* If we have, just return it from the table. */
3932 if (already_loaded)
f676886a 3933 f->display.x->font = x_font_table[already_loaded];
90e65f07 3934
dc6f92b8
JB
3935 /* Otherwise, load the font and add it to the table. */
3936 else
3937 {
9696f58b 3938 int i;
dc6f92b8
JB
3939 XFontStruct *font;
3940
9696f58b 3941 /* Try to find a character-cell font in the list. */
f126bd67
JB
3942#if 0
3943 /* A laudable goal, but this isn't how to do it. */
9696f58b
JB
3944 for (i = 0; i < n_matching_fonts; i++)
3945 if (! font_info[i].per_char)
3946 break;
f126bd67
JB
3947#else
3948 i = 0;
3949#endif
9696f58b
JB
3950
3951 if (i >= n_matching_fonts)
3952 return 2;
3953 else
3954 fontname = font_names[i];
3955
dc6f92b8
JB
3956 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3957 if (! font)
3958 return 1;
3959
3960 /* Do we need to create the table? */
3961 if (x_font_table_size == 0)
3962 {
3963 x_font_table_size = 16;
3964 x_font_table
3965 = (XFontStruct **) xmalloc (x_font_table_size
3966 * sizeof (x_font_table[0]));
3967 }
3968 /* Do we need to grow the table? */
3969 else if (n_fonts >= x_font_table_size)
3970 {
90e65f07 3971 x_font_table_size *= 2;
dc6f92b8
JB
3972 x_font_table
3973 = (XFontStruct **) xrealloc (x_font_table,
3974 (x_font_table_size
3975 * sizeof (x_font_table[0])));
3976 }
3977
f676886a 3978 f->display.x->font = x_font_table[n_fonts++] = font;
dc6f92b8
JB
3979 }
3980
3981 /* Free the information from XListFontsWithInfo. The data
3982 we actually retain comes from XLoadQueryFont. */
3983 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3984
f676886a 3985 /* Now make the frame display the given font. */
c118dd06 3986 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 3987 {
f676886a
JB
3988 XSetFont (x_current_display, f->display.x->normal_gc,
3989 f->display.x->font->fid);
3990 XSetFont (x_current_display, f->display.x->reverse_gc,
3991 f->display.x->font->fid);
3992 XSetFont (x_current_display, f->display.x->cursor_gc,
3993 f->display.x->font->fid);
decb54c6 3994 init_frame_faces (f);
f676886a
JB
3995
3996 x_set_window_size (f, f->width, f->height);
dc6f92b8
JB
3997 }
3998
3999 return 0;
4000}
c118dd06 4001#else /* ! defined (HAVE_X11) */
f676886a
JB
4002x_new_font (f, newname)
4003 struct frame *f;
dc6f92b8
JB
4004 register char *newname;
4005{
4006 FONT_TYPE *temp;
4007 int mask;
4008
4009 temp = XGetFont (newname);
4010 if (temp == (FONT_TYPE *) 0)
4011 return 1;
4012
f676886a
JB
4013 if (f->display.x->font)
4014 XLoseFont (f->display.x->font);
dc6f92b8 4015
f676886a 4016 f->display.x->font = temp;
dc6f92b8 4017
c118dd06 4018 if (FRAME_X_WINDOW (f) != 0)
f676886a 4019 x_set_window_size (f, f->width, f->height);
dc6f92b8
JB
4020
4021 return 0;
4022}
c118dd06 4023#endif /* ! defined (HAVE_X11) */
dc6f92b8 4024\f
f451eb13
JB
4025/* X Window sizes and positions. */
4026
f676886a
JB
4027x_calc_absolute_position (f)
4028 struct frame *f;
dc6f92b8
JB
4029{
4030#ifdef HAVE_X11
f676886a
JB
4031 if (f->display.x->left_pos < 0)
4032 f->display.x->left_pos
7c5283e4 4033 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
dc6f92b8 4034
f676886a
JB
4035 if (f->display.x->top_pos < 0)
4036 f->display.x->top_pos
7c5283e4 4037 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
c118dd06 4038#else /* ! defined (HAVE_X11) */
dc6f92b8
JB
4039 WINDOWINFO_TYPE parentinfo;
4040
c118dd06 4041 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
dc6f92b8 4042
f676886a
JB
4043 if (f->display.x->left_pos < 0)
4044 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4045 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
dc6f92b8 4046
f676886a
JB
4047 if (f->display.x->top_pos < 0)
4048 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4049 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
c118dd06 4050#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4051}
4052
f676886a
JB
4053x_set_offset (f, xoff, yoff)
4054 struct frame *f;
dc6f92b8
JB
4055 register int xoff, yoff;
4056{
f676886a
JB
4057 f->display.x->top_pos = yoff;
4058 f->display.x->left_pos = xoff;
4059 x_calc_absolute_position (f);
dc6f92b8
JB
4060
4061 BLOCK_INPUT;
c118dd06 4062 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
f676886a 4063 f->display.x->left_pos, f->display.x->top_pos);
dc6f92b8 4064#ifdef HAVE_X11
f676886a 4065 x_wm_set_size_hint (f, 0);
c118dd06 4066#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4067 UNBLOCK_INPUT;
4068}
4069
f676886a 4070/* Call this to change the size of frame F's x-window. */
dc6f92b8 4071
f676886a
JB
4072x_set_window_size (f, cols, rows)
4073 struct frame *f;
b1c884c3 4074 int cols, rows;
dc6f92b8
JB
4075{
4076 int pixelwidth, pixelheight;
4077 int mask;
dc6f92b8
JB
4078
4079 BLOCK_INPUT;
4080
b1c884c3 4081 check_frame_size (f, &rows, &cols);
ab648270
JB
4082 f->display.x->vertical_scroll_bar_extra =
4083 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4084 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
f451eb13
JB
4085 : 0);
4086 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4087 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8
JB
4088
4089#ifdef HAVE_X11
f676886a 4090 x_wm_set_size_hint (f, 0);
c118dd06
JB
4091#endif /* ! defined (HAVE_X11) */
4092 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
b1c884c3
JB
4093
4094 /* Now, strictly speaking, we can't be sure that this is accurate,
4095 but the window manager will get around to dealing with the size
4096 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
4097 ConfigureNotify event gets here.
4098
4099 We could just not bother storing any of this information here,
4100 and let the ConfigureNotify event set everything up, but that
4101 might be kind of confusing to the lisp code, since size changes
4102 wouldn't be reported in the frame parameters until some random
4103 point in the future when the ConfigureNotify event arrives. */
8922af5f 4104 change_frame_size (f, rows, cols, 0, 0);
b1c884c3
JB
4105 PIXEL_WIDTH (f) = pixelwidth;
4106 PIXEL_HEIGHT (f) = pixelheight;
4107
dbc4e1c1
JB
4108 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4109 receive in the ConfigureNotify event; if we get what we asked
4110 for, then the event won't cause the screen to become garbaged, so
4111 we have to make sure to do it here. */
4112 SET_FRAME_GARBAGED (f);
4113
dc6f92b8
JB
4114 XFlushQueue ();
4115 UNBLOCK_INPUT;
4116}
4117
4118#ifndef HAVE_X11
f676886a
JB
4119x_set_resize_hint (f)
4120 struct frame *f;
dc6f92b8 4121{
12ba150f
JB
4122 XSetResizeHint (FRAME_X_WINDOW (f),
4123 2 * f->display.x->internal_border_width,
f676886a 4124 2 * f->display.x->internal_border_width,
12ba150f
JB
4125 FONT_WIDTH (f->display.x->font),
4126 FONT_HEIGHT (f->display.x->font));
dc6f92b8 4127}
c118dd06 4128#endif /* HAVE_X11 */
dc6f92b8 4129\f
f451eb13 4130/* Mouse warping, focus shifting, raising and lowering. */
dc6f92b8 4131
f676886a
JB
4132x_set_mouse_position (f, x, y)
4133 struct frame *f;
dc6f92b8
JB
4134 int x, y;
4135{
4136 int pix_x, pix_y;
4137
f676886a 4138 x_raise_frame (f);
dc6f92b8 4139
12ba150f
JB
4140 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4141 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
f451eb13
JB
4142
4143 if (pix_x < 0) pix_x = 0;
4144 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4145
4146 if (pix_y < 0) pix_y = 0;
4147 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
4148
4149 BLOCK_INPUT;
dc6f92b8 4150
c118dd06 4151 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
dc6f92b8
JB
4152 UNBLOCK_INPUT;
4153}
4154
4155#ifdef HAVE_X11
f676886a
JB
4156x_focus_on_frame (f)
4157 struct frame *f;
dc6f92b8 4158{
f676886a 4159 x_raise_frame (f);
6d4238f3
JB
4160#if 0
4161 /* I don't think that the ICCCM allows programs to do things like this
4162 without the interaction of the window manager. Whatever you end up
f676886a 4163 doing with this code, do it to x_unfocus_frame too. */
c118dd06 4164 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
dc6f92b8 4165 RevertToPointerRoot, CurrentTime);
c118dd06 4166#endif /* ! 0 */
dc6f92b8
JB
4167}
4168
f676886a
JB
4169x_unfocus_frame (f)
4170 struct frame *f;
dc6f92b8 4171{
6d4238f3 4172#if 0
f676886a
JB
4173 /* Look at the remarks in x_focus_on_frame. */
4174 if (x_focus_frame == f)
dc6f92b8
JB
4175 XSetInputFocus (x_current_display, PointerRoot,
4176 RevertToPointerRoot, CurrentTime);
c118dd06 4177#endif /* ! 0 */
dc6f92b8
JB
4178}
4179
c118dd06 4180#endif /* ! defined (HAVE_X11) */
dc6f92b8 4181
f676886a 4182/* Raise frame F. */
dc6f92b8 4183
f676886a
JB
4184x_raise_frame (f)
4185 struct frame *f;
dc6f92b8 4186{
3a88c238 4187 if (f->async_visible)
dc6f92b8
JB
4188 {
4189 BLOCK_INPUT;
c118dd06 4190 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
dc6f92b8
JB
4191 XFlushQueue ();
4192 UNBLOCK_INPUT;
4193 }
4194}
4195
f676886a 4196/* Lower frame F. */
dc6f92b8 4197
f676886a
JB
4198x_lower_frame (f)
4199 struct frame *f;
dc6f92b8 4200{
3a88c238 4201 if (f->async_visible)
dc6f92b8
JB
4202 {
4203 BLOCK_INPUT;
c118dd06 4204 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
dc6f92b8
JB
4205 XFlushQueue ();
4206 UNBLOCK_INPUT;
4207 }
4208}
4209
dbc4e1c1
JB
4210static void
4211XTframe_raise_lower (f, raise)
4212 FRAME_PTR f;
4213 int raise;
4214{
4215 if (raise)
4216 x_raise_frame (f);
4217 else
4218 x_lower_frame (f);
4219}
4220
4221
dc6f92b8
JB
4222/* Change from withdrawn state to mapped state. */
4223
f676886a
JB
4224x_make_frame_visible (f)
4225 struct frame *f;
dc6f92b8
JB
4226{
4227 int mask;
4228
dc6f92b8 4229 BLOCK_INPUT;
dc6f92b8 4230
f676886a 4231 if (! FRAME_VISIBLE_P (f))
90e65f07
JB
4232 {
4233#ifdef HAVE_X11
4234 if (! EQ (Vx_no_window_manager, Qt))
f676886a 4235 x_wm_set_window_state (f, NormalState);
dc6f92b8 4236
c118dd06 4237 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
ab648270 4238 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
c118dd06
JB
4239 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4240#else /* ! defined (HAVE_X11) */
4241 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
f676886a
JB
4242 if (f->display.x->icon_desc != 0)
4243 XUnmapWindow (f->display.x->icon_desc);
dc6f92b8 4244
90e65f07 4245 /* Handled by the MapNotify event for X11 */
3a88c238
JB
4246 f->async_visible = 1;
4247 f->async_iconified = 0;
dc6f92b8 4248
f676886a 4249 /* NOTE: this may cause problems for the first frame. */
90e65f07 4250 XTcursor_to (0, 0);
c118dd06 4251#endif /* ! defined (HAVE_X11) */
90e65f07 4252 }
dc6f92b8 4253
dc6f92b8 4254 XFlushQueue ();
90e65f07 4255
dc6f92b8
JB
4256 UNBLOCK_INPUT;
4257}
4258
4259/* Change from mapped state to withdrawn state. */
4260
f676886a
JB
4261x_make_frame_invisible (f)
4262 struct frame *f;
dc6f92b8
JB
4263{
4264 int mask;
4265
3a88c238 4266 if (! f->async_visible)
dc6f92b8
JB
4267 return;
4268
4269 BLOCK_INPUT;
c118dd06
JB
4270
4271#ifdef HAVE_X11R4
4272
4273 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4274 DefaultScreen (x_current_display)))
4275 {
4276 UNBLOCK_INPUT_RESIGNAL;
4277 error ("can't notify window manager of window withdrawl");
4278 }
4279
4280#else /* ! defined (HAVE_X11R4) */
dc6f92b8 4281#ifdef HAVE_X11
16bd92ea 4282
c118dd06 4283 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
4284 if (! EQ (Vx_no_window_manager, Qt))
4285 {
16bd92ea 4286 XEvent unmap;
dc6f92b8 4287
16bd92ea 4288 unmap.xunmap.type = UnmapNotify;
c118dd06 4289 unmap.xunmap.window = FRAME_X_WINDOW (f);
16bd92ea
JB
4290 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4291 unmap.xunmap.from_configure = False;
4292 if (! XSendEvent (x_current_display,
4293 DefaultRootWindow (x_current_display),
4294 False,
4295 SubstructureRedirectMask|SubstructureNotifyMask,
4296 &unmap))
4297 {
4298 UNBLOCK_INPUT_RESIGNAL;
4299 error ("can't notify window manager of withdrawal");
4300 }
dc6f92b8
JB
4301 }
4302
16bd92ea 4303 /* Unmap the window ourselves. Cheeky! */
c118dd06
JB
4304 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4305
4306#else /* ! defined (HAVE_X11) */
dc6f92b8 4307
c118dd06 4308 XUnmapWindow (FRAME_X_WINDOW (f));
3a88c238 4309 f->async_visible = 0; /* Handled by the UnMap event for X11 */
f676886a 4310 if (f->display.x->icon_desc != 0)
c118dd06
JB
4311 XUnmapWindow (f->display.x->icon_desc);
4312
4313#endif /* ! defined (HAVE_X11) */
4314#endif /* ! defined (HAVE_X11R4) */
dc6f92b8
JB
4315
4316 XFlushQueue ();
4317 UNBLOCK_INPUT;
4318}
4319
dc6f92b8
JB
4320/* Change window state from mapped to iconified. */
4321
f676886a
JB
4322x_iconify_frame (f)
4323 struct frame *f;
dc6f92b8
JB
4324{
4325 int mask;
4326
3a88c238 4327 if (f->async_iconified)
dc6f92b8
JB
4328 return;
4329
4330 BLOCK_INPUT;
4331
4332#ifdef HAVE_X11
16bd92ea
JB
4333 /* Since we don't know which revision of X we're running, we'll use both
4334 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4335
4336 /* X11R4: send a ClientMessage to the window manager using the
4337 WM_CHANGE_STATE type. */
4338 {
4339 XEvent message;
4340
c118dd06 4341 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea
JB
4342 message.xclient.type = ClientMessage;
4343 message.xclient.message_type = Xatom_wm_change_state;
4344 message.xclient.format = 32;
4345 message.xclient.data.l[0] = IconicState;
4346
4347 if (! XSendEvent (x_current_display,
4348 DefaultRootWindow (x_current_display),
4349 False,
4350 SubstructureRedirectMask | SubstructureNotifyMask,
4351 &message))
dc6f92b8
JB
4352 {
4353 UNBLOCK_INPUT_RESIGNAL;
4354 error ("Can't notify window manager of iconification.");
4355 }
16bd92ea 4356 }
dc6f92b8 4357
16bd92ea
JB
4358 /* X11R3: set the initial_state field of the window manager hints to
4359 IconicState. */
4360 x_wm_set_window_state (f, IconicState);
dc6f92b8 4361
3a88c238 4362 f->async_iconified = 1;
c118dd06
JB
4363#else /* ! defined (HAVE_X11) */
4364 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
dc6f92b8 4365
3a88c238 4366 f->async_visible = 0; /* Handled in the UnMap event for X11. */
f676886a 4367 if (f->display.x->icon_desc != 0)
dc6f92b8 4368 {
f676886a
JB
4369 XMapWindow (XDISPLAY f->display.x->icon_desc);
4370 refreshicon (f);
dc6f92b8 4371 }
c118dd06 4372#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4373
4374 XFlushQueue ();
4375 UNBLOCK_INPUT;
4376}
4377
c0ff3fab 4378/* Destroy the X window of frame F. */
dc6f92b8 4379
c0ff3fab 4380x_destroy_window (f)
f676886a 4381 struct frame *f;
dc6f92b8 4382{
dc6f92b8 4383 BLOCK_INPUT;
c0ff3fab
JB
4384
4385 if (f->display.x->icon_desc != 0)
4386 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4387 XDestroyWindow (XDISPLAY f->display.x->window_desc);
07e34cb0 4388 free_frame_faces (f);
dc6f92b8 4389 XFlushQueue ();
dc6f92b8 4390
9ac0d9e0 4391 xfree (f->display.x);
c0ff3fab 4392 f->display.x = 0;
f676886a
JB
4393 if (f == x_focus_frame)
4394 x_focus_frame = 0;
4395 if (f == x_highlight_frame)
4396 x_highlight_frame = 0;
c0ff3fab
JB
4397
4398 UNBLOCK_INPUT;
dc6f92b8
JB
4399}
4400\f
f451eb13
JB
4401/* Manage event queues for X10. */
4402
dc6f92b8
JB
4403#ifndef HAVE_X11
4404
4405/* Manage event queues.
4406
4407 This code is only used by the X10 support.
4408
4409 We cannot leave events in the X queue and get them when we are ready
4410 because X does not provide a subroutine to get only a certain kind
4411 of event but not block if there are no queued events of that kind.
4412
4413 Therefore, we must examine events as they come in and copy events
4414 of certain kinds into our private queues.
4415
4416 All ExposeRegion events are put in x_expose_queue.
4417 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4418
4419
4420/* Write the event *P_XREP into the event queue *QUEUE.
4421 If the queue is full, do nothing, but return nonzero. */
4422
4423int
4424enqueue_event (p_xrep, queue)
4425 register XEvent *p_xrep;
4426 register struct event_queue *queue;
4427{
4428 int newindex = queue->windex + 1;
4429 if (newindex == EVENT_BUFFER_SIZE)
4430 newindex = 0;
4431 if (newindex == queue->rindex)
4432 return -1;
4433 queue->xrep[queue->windex] = *p_xrep;
4434 queue->windex = newindex;
4435 return 0;
4436}
4437
4438/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4439 If *QUEUE is empty, do nothing and return 0. */
4440
4441int
4442dequeue_event (p_xrep, queue)
4443 register XEvent *p_xrep;
4444 register struct event_queue *queue;
4445{
4446 if (queue->windex == queue->rindex)
4447 return 0;
4448 *p_xrep = queue->xrep[queue->rindex++];
4449 if (queue->rindex == EVENT_BUFFER_SIZE)
4450 queue->rindex = 0;
4451 return 1;
4452}
4453
4454/* Return the number of events buffered in *QUEUE. */
4455
4456int
4457queue_event_count (queue)
4458 register struct event_queue *queue;
4459{
4460 int tem = queue->windex - queue->rindex;
4461 if (tem >= 0)
4462 return tem;
4463 return EVENT_BUFFER_SIZE + tem;
4464}
4465
4466/* Return nonzero if mouse input is pending. */
4467
4468int
4469mouse_event_pending_p ()
4470{
4471 return queue_event_count (&x_mouse_queue);
4472}
c118dd06 4473#endif /* HAVE_X11 */
dc6f92b8 4474\f
f451eb13
JB
4475/* Setting window manager hints. */
4476
dc6f92b8
JB
4477#ifdef HAVE_X11
4478
f676886a
JB
4479x_wm_set_size_hint (f, prompting)
4480 struct frame *f;
dc6f92b8
JB
4481 long prompting;
4482{
4483 XSizeHints size_hints;
c118dd06 4484 Window window = FRAME_X_WINDOW (f);
dc6f92b8
JB
4485
4486 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
4487
f676886a
JB
4488 flexlines = f->height;
4489
4490 size_hints.x = f->display.x->left_pos;
4491 size_hints.y = f->display.x->top_pos;
4492 size_hints.height = PIXEL_HEIGHT (f);
4493 size_hints.width = PIXEL_WIDTH (f);
4494 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4495 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
12ba150f
JB
4496 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4497 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
f451eb13 4498
b1c884c3 4499 {
b0342f17
JB
4500 int base_width, base_height;
4501
f451eb13
JB
4502 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4503 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17
JB
4504
4505 {
4506 int min_rows = 0, min_cols = 0;
4507 check_frame_size (f, &min_rows, &min_cols);
4508
4509 /* The window manager uses the base width hints to calculate the
4510 current number of rows and columns in the frame while
4511 resizing; min_width and min_height aren't useful for this
4512 purpose, since they might not give the dimensions for a
4513 zero-row, zero-column frame.
4514
4515 We use the base_width and base_height members if we have
4516 them; otherwise, we set the min_width and min_height members
4517 to the size for a zero x zero frame. */
4518
4519#ifdef HAVE_X11R4
4520 size_hints.flags |= PBaseSize;
4521 size_hints.base_width = base_width;
4522 size_hints.base_height = base_height;
4523 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4524 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4525#else
4526 size_hints.min_width = base_width;
4527 size_hints.min_height = base_height;
4528#endif
4529 }
b1c884c3 4530
b1c884c3 4531 }
dc6f92b8
JB
4532
4533 if (prompting)
4534 size_hints.flags |= prompting;
4535 else
4536 {
4537 XSizeHints hints; /* Sometimes I hate X Windows... */
4538
4539 XGetNormalHints (x_current_display, window, &hints);
4540 if (hints.flags & PSize)
4541 size_hints.flags |= PSize;
4542 if (hints.flags & PPosition)
4543 size_hints.flags |= PPosition;
4544 if (hints.flags & USPosition)
4545 size_hints.flags |= USPosition;
4546 if (hints.flags & USSize)
4547 size_hints.flags |= USSize;
4548 }
16bd92ea 4549
b0342f17
JB
4550#ifdef HAVE_X11R4
4551 XSetWMNormalHints (x_current_display, window, &size_hints);
4552#else
dc6f92b8 4553 XSetNormalHints (x_current_display, window, &size_hints);
b0342f17 4554#endif
dc6f92b8
JB
4555}
4556
4557/* Used for IconicState or NormalState */
f676886a
JB
4558x_wm_set_window_state (f, state)
4559 struct frame *f;
dc6f92b8
JB
4560 int state;
4561{
c118dd06 4562 Window window = FRAME_X_WINDOW (f);
dc6f92b8 4563
16bd92ea
JB
4564 f->display.x->wm_hints.flags |= StateHint;
4565 f->display.x->wm_hints.initial_state = state;
b1c884c3 4566
16bd92ea 4567 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
4568}
4569
f676886a
JB
4570x_wm_set_icon_pixmap (f, icon_pixmap)
4571 struct frame *f;
dc6f92b8
JB
4572 Pixmap icon_pixmap;
4573{
c118dd06 4574 Window window = FRAME_X_WINDOW (f);
dc6f92b8 4575
dbc4e1c1
JB
4576 if (icon_pixmap)
4577 {
4578 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4579 f->display.x->wm_hints.flags |= IconPixmapHint;
4580 }
4581 else
4582 f->display.x->wm_hints.flags &= ~IconPixmapHint;
b1c884c3 4583
16bd92ea 4584 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
4585}
4586
f676886a
JB
4587x_wm_set_icon_position (f, icon_x, icon_y)
4588 struct frame *f;
dc6f92b8
JB
4589 int icon_x, icon_y;
4590{
c118dd06 4591 Window window = FRAME_X_WINDOW (f);
dc6f92b8 4592
16bd92ea
JB
4593 f->display.x->wm_hints.flags |= IconPositionHint;
4594 f->display.x->wm_hints.icon_x = icon_x;
4595 f->display.x->wm_hints.icon_y = icon_y;
b1c884c3 4596
16bd92ea 4597 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
dc6f92b8
JB
4598}
4599
4600\f
f451eb13
JB
4601/* Initialization. */
4602
dc6f92b8
JB
4603void
4604x_term_init (display_name)
4605 char *display_name;
4606{
f676886a 4607 Lisp_Object frame;
dc6f92b8
JB
4608 char *defaultvalue;
4609#ifdef F_SETOWN
4610 extern int old_fcntl_owner;
c118dd06 4611#endif /* ! defined (F_SETOWN) */
6d4238f3 4612
f676886a 4613 x_focus_frame = x_highlight_frame = 0;
dc6f92b8
JB
4614
4615 x_current_display = XOpenDisplay (display_name);
4616 if (x_current_display == 0)
4617 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4618 display_name);
4619
4620#ifdef HAVE_X11
4621 {
16bd92ea 4622 int hostname_size = 256;
60fb3ee1
JB
4623
4624 hostname = (char *) xmalloc (hostname_size);
4625
dc6f92b8
JB
4626#if 0
4627 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 4628#endif /* ! 0 */
dc6f92b8 4629
60fb3ee1
JB
4630 /* Try to get the host name; if the buffer is too short, try
4631 again. Apparently, the only indication gethostname gives of
4632 whether the buffer was large enough is the presence or absence
4633 of a '\0' in the string. Eech. */
4634 for (;;)
4635 {
4636 gethostname (hostname, hostname_size - 1);
4637 hostname[hostname_size - 1] = '\0';
4638
4639 /* Was the buffer large enough for gethostname to store the '\0'? */
4640 if (strlen (hostname) < hostname_size - 1)
4641 break;
4642
4643 hostname_size <<= 1;
4644 hostname = (char *) xrealloc (hostname, hostname_size);
4645 }
59653951 4646 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
60fb3ee1
JB
4647 + strlen (hostname)
4648 + 2);
59653951 4649 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
dc6f92b8 4650 }
28430d3c
JB
4651
4652 /* Figure out which modifier bits mean what. */
4653 x_find_modifier_meanings ();
f451eb13 4654
ab648270 4655 /* Get the scroll bar cursor. */
d56a553a
RS
4656 x_vertical_scroll_bar_cursor
4657 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
f451eb13 4658
d56a553a 4659#if 0
28430d3c
JB
4660 /* Watch for PropertyNotify events on the root window; we use them
4661 to figure out when to invalidate our cache of the cut buffers. */
4662 x_watch_cut_buffer_cache ();
d56a553a 4663#endif
28430d3c 4664
a4fc7360
JB
4665 if (ConnectionNumber (x_current_display) != 0)
4666 {
4667 dup2 (ConnectionNumber (x_current_display), 0);
6d4238f3
JB
4668
4669#ifndef SYSV_STREAMS
a4fc7360
JB
4670 /* Streams somehow keeps track of which descriptor number
4671 is being used to talk to X. So it is not safe to substitute
4672 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4673 close (ConnectionNumber (x_current_display));
4674 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
6d4238f3
JB
4675 * check the def of the macro;
4676 * it is a genuine lvalue */
c118dd06 4677#endif /* SYSV_STREAMS */
a4fc7360 4678 }
6d4238f3 4679
c118dd06 4680#endif /* ! defined (HAVE_X11) */
dc6f92b8
JB
4681
4682#ifdef F_SETOWN
4683 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4684#ifdef F_SETOWN_SOCK_NEG
4685 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
c118dd06 4686#else /* ! defined (F_SETOWN_SOCK_NEG) */
dc6f92b8 4687 fcntl (0, F_SETOWN, getpid ());
c118dd06
JB
4688#endif /* ! defined (F_SETOWN_SOCK_NEG) */
4689#endif /* ! defined (F_SETOWN) */
dc6f92b8
JB
4690
4691#ifdef SIGIO
4692 init_sigio ();
c118dd06 4693#endif /* ! defined (SIGIO) */
dc6f92b8
JB
4694
4695 /* Must use interrupt input because we cannot otherwise
4696 arrange for C-g to be noticed immediately.
4697 We cannot connect it to SIGINT. */
4698 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4699
4700 expose_all_windows = 0;
4701
f676886a 4702 clear_frame_hook = XTclear_frame;
dc6f92b8
JB
4703 clear_end_of_line_hook = XTclear_end_of_line;
4704 ins_del_lines_hook = XTins_del_lines;
4705 change_line_highlight_hook = XTchange_line_highlight;
4706 insert_glyphs_hook = XTinsert_glyphs;
4707 write_glyphs_hook = XTwrite_glyphs;
4708 delete_glyphs_hook = XTdelete_glyphs;
4709 ring_bell_hook = XTring_bell;
4710 reset_terminal_modes_hook = XTreset_terminal_modes;
4711 set_terminal_modes_hook = XTset_terminal_modes;
4712 update_begin_hook = XTupdate_begin;
4713 update_end_hook = XTupdate_end;
4714 set_terminal_window_hook = XTset_terminal_window;
4715 read_socket_hook = XTread_socket;
4716 cursor_to_hook = XTcursor_to;
4717 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 4718 mouse_position_hook = XTmouse_position;
f451eb13 4719 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 4720 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
4721 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4722 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4723 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4724 judge_scroll_bars_hook = XTjudge_scroll_bars;
dc6f92b8 4725
f676886a 4726 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
4727 char_ins_del_ok = 0; /* just as fast to write the line */
4728 line_ins_del_ok = 1; /* we'll just blt 'em */
4729 fast_clear_end_of_line = 1; /* X does this well */
f676886a 4730 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
4731 off the bottom */
4732 baud_rate = 19200;
4733
c118dd06
JB
4734 /* Note that there is no real way portable across R3/R4 to get the
4735 original error handler. */
4736 XHandleError (x_error_quitter);
8922af5f 4737 XHandleIOError (x_io_error_quitter);
dc6f92b8
JB
4738
4739 /* Disable Window Change signals; they are handled by X events. */
4740#ifdef SIGWINCH
4741 signal (SIGWINCH, SIG_DFL);
c118dd06 4742#endif /* ! defined (SIGWINCH) */
dc6f92b8 4743
c118dd06 4744 signal (SIGPIPE, x_connection_closed);
dc6f92b8 4745}
55123275
JB
4746
4747void
4748syms_of_xterm ()
4749{
ab648270 4750 staticpro (&last_mouse_scroll_bar);
55123275 4751}
c118dd06
JB
4752#endif /* ! defined (HAVE_X11) */
4753#endif /* ! defined (HAVE_X_WINDOWS) */