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