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