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