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