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