*** empty log message ***
[bpt/emacs.git] / 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
34 /* On 4.3 this loses if it comes after xterm.h. */
35 #include <signal.h>
36
37 /* This may include sys/types.h, and that somehow loses
38 if this is not done before the other system files. */
39 #include "xterm.h"
40
41 /* Load sys/types.h if not already loaded.
42 In some systems loading it twice is suicidal. */
43 #ifndef makedev
44 #include <sys/types.h>
45 #endif
46
47 #ifdef BSD
48 #include <sys/ioctl.h>
49 #include <strings.h>
50 #else
51 #include <sys/termio.h>
52 #include <string.h>
53 #endif
54
55 /* Allow m- file to inhibit use of FIONREAD. */
56 #ifdef BROKEN_FIONREAD
57 #undef FIONREAD
58 #endif
59
60 /* We are unable to use interrupts if FIONREAD is not available,
61 so flush SIGIO so we won't try. */
62 #ifndef FIONREAD
63 #ifdef SIGIO
64 #undef SIGIO
65 #endif
66 #endif
67
68 #ifdef NEED_TIME_H
69 #include <time.h>
70 #else /* not NEED_TIME_H */
71 #ifdef HAVE_TIMEVAL
72 #include <sys/time.h>
73 #endif /* HAVE_TIMEVAL */
74 #endif /* not NEED_TIME_H */
75
76 #include <fcntl.h>
77 #include <stdio.h>
78 #include <ctype.h>
79 #include <errno.h>
80 #include <setjmp.h>
81 #include <sys/stat.h>
82 #include <sys/param.h>
83
84 #include "dispextern.h"
85 #include "termhooks.h"
86 #include "termopts.h"
87 #include "termchar.h"
88 #if 0
89 #include "sink.h"
90 #include "sinkmask.h"
91 #endif
92 #include "gnu.h"
93 #include "screen.h"
94 #include "disptab.h"
95 #include "buffer.h"
96
97 #ifdef HAVE_X11
98 #define XMapWindow XMapRaised /* Raise them when mapping. */
99 #else
100 #include <X/Xkeyboard.h>
101 /*#include <X/Xproto.h> */
102 #endif /* HAVE_X11 */
103
104 /* For sending Meta-characters. Do we need this? */
105 #define METABIT 0200
106
107 #define min(a,b) ((a)<(b) ? (a) : (b))
108 #define max(a,b) ((a)>(b) ? (a) : (b))
109
110 /* Nonzero means we must reprint all windows
111 because 1) we received an ExposeWindow event
112 or 2) we received too many ExposeRegion events to record. */
113
114 static int expose_all_windows;
115
116 /* Nonzero means we must reprint all icon windows. */
117
118 static int expose_all_icons;
119
120 #ifndef HAVE_X11
121 /* ExposeRegion events, when received, are copied into this queue
122 for later processing. */
123
124 static struct event_queue x_expose_queue;
125
126 /* ButtonPressed and ButtonReleased events, when received,
127 are copied into this queue for later processing. */
128
129 struct event_queue x_mouse_queue;
130 #endif
131
132 /* Nonzero after BLOCK_INPUT; prevents input events from being
133 processed until later. */
134
135 int x_input_blocked;
136
137 #if defined (SIGIO) && defined (FIONREAD)
138 int BLOCK_INPUT_mask;
139 #endif
140
141 /* Nonzero if input events came in while x_input_blocked was nonzero.
142 UNBLOCK_INPUT checks for this. */
143
144 int x_pending_input;
145
146 /* Nonzero if in redisplay (); prevents us from calling it recursively */
147
148 int in_display;
149
150 /* The id of a bitmap used for icon windows.
151 One such map is shared by all Emacs icon windows.
152 This is zero if we have not yet had a need to create the bitmap. */
153
154 static Bitmap icon_bitmap;
155
156 /* Font used for text icons. */
157
158 static FONT_TYPE *icon_font_info;
159
160 /* Stuff for dealing with the main icon title. */
161
162 extern Lisp_Object Vcommand_line_args;
163 char *hostname, *x_id_name;
164 Lisp_Object 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 Display *XOpenDisplay ();
255 extern Window XCreateWindow ();
256
257 extern Cursor XCreateCursor ();
258 extern FONT_TYPE *XOpenFont ();
259
260 static void flashback ();
261
262 #ifndef HAVE_X11
263 static void dumpqueue ();
264 #endif
265
266 void dumpborder ();
267 static XTcursor_to ();
268 static XTclear_end_of_line ();
269 \f
270 /* These hooks are called by update_screen at the beginning and end
271 of a screen update. We record in `updating_screen' the identity
272 of the screen being updated, so that the XT... functions do not
273 need to take a screen as argument. Most of the XT... functions
274 should never be called except during an update, the only exceptions
275 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
276
277 extern int mouse_track_top, mouse_track_left, mouse_track_width;
278
279 static
280 XTupdate_begin (s)
281 struct screen *s;
282 {
283 int mask;
284
285 if (s == 0)
286 abort ();
287
288 updating_screen = s;
289 flexlines = s->height;
290 highlight = 0;
291
292 BLOCK_INPUT;
293 #ifndef HAVE_X11
294 dumpqueue ();
295 #endif
296 UNBLOCK_INPUT;
297 }
298
299 static void x_do_pending_expose ();
300
301 static
302 XTupdate_end (s)
303 struct screen *s;
304 {
305 int mask;
306
307 if (updating_screen == 0
308 || updating_screen != s)
309 abort ();
310
311 BLOCK_INPUT;
312 #ifndef HAVE_X11
313 dumpqueue ();
314 #endif
315 adjust_scrollbars (s);
316 x_do_pending_expose ();
317
318 x_display_cursor (s, 1);
319
320 updating_screen = 0;
321 XFlushQueue ();
322 UNBLOCK_INPUT;
323 }
324 \f
325 /* External interface to control of standout mode.
326 Call this when about to modify line at position VPOS
327 and not change whether it is highlighted. */
328
329 XTreassert_line_highlight (new, vpos)
330 int new, vpos;
331 {
332 highlight = new;
333 }
334
335 /* Call this when about to modify line at position VPOS
336 and change whether it is highlighted. */
337
338 static
339 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
340 int new_highlight, vpos, first_unused_hpos;
341 {
342 highlight = new_highlight;
343 XTcursor_to (vpos, 0);
344 XTclear_end_of_line (updating_screen->width);
345 }
346
347 /* This is used when starting Emacs and when restarting after suspend.
348 When starting Emacs, no X window is mapped. And nothing must be done
349 to Emacs's own window if it is suspended (though that rarely happens). */
350
351 static
352 XTset_terminal_modes ()
353 {
354 }
355
356 /* This is called when exiting or suspending Emacs.
357 Exiting will make the X-windows go away, and suspending
358 requires no action. */
359
360 static
361 XTreset_terminal_modes ()
362 {
363 /* XTclear_screen (); */
364 }
365 \f
366 /* Set the nominal cursor position of the screen:
367 where display update commands will take effect.
368 This does not affect the place where the cursor-box is displayed. */
369
370 static
371 XTcursor_to (row, col)
372 register int row, col;
373 {
374 int mask;
375 int orow = row;
376
377 curs_x = col;
378 curs_y = row;
379
380 if (updating_screen == 0)
381 {
382 BLOCK_INPUT;
383 x_display_cursor (selected_screen, 1);
384 XFlushQueue ();
385 UNBLOCK_INPUT;
386 }
387 }
388 \f
389 /* Display a sequence of N glyphs found at GP.
390 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
391 HL is 1 if this text is highlighted, 2 if the cursor is on it.
392
393 FONT is the default font to use (for glyphs whose font-code is 0). */
394
395 static void
396 dumpglyphs (s, left, top, gp, n, hl, font)
397 struct screen *s;
398 int left, top;
399 register GLYPH *gp; /* Points to first GLYPH. */
400 register int n; /* Number of glyphs to display. */
401 int hl;
402 FONT_TYPE *font;
403 {
404 register int len;
405 Window window = s->display.x->window_desc;
406 GC drawing_gc = (hl == 2 ? s->display.x->cursor_gc
407 : (hl ? s->display.x->reverse_gc
408 : s->display.x->normal_gc));
409
410 if (sizeof (GLYPH) == sizeof (XChar2b))
411 XDrawImageString16 (x_current_display, window, drawing_gc,
412 left, top + FONT_BASE (font), (XChar2b *) gp, n);
413 else if (sizeof (GLYPH) == sizeof (unsigned char))
414 XDrawImageString (x_current_display, window, drawing_gc,
415 left, top + FONT_BASE (font), (char *) gp, n);
416 else
417 /* What size of glyph ARE you using? And does X have a function to
418 draw them? */
419 abort ();
420 }
421
422 #if 0
423 static void
424 dumpglyphs (s, left, top, gp, n, hl, font)
425 struct screen *s;
426 int left, top;
427 register GLYPH *gp; /* Points to first GLYPH. */
428 register int n; /* Number of glyphs to display. */
429 int hl;
430 FONT_TYPE *font;
431 {
432 char buf[s->width]; /* Holds characters to be displayed. */
433 register char *cp; /* Steps through buf[]. */
434 register int tlen = GLYPH_TABLE_LENGTH;
435 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
436 Window window = s->display.x->window_desc;
437 int cursor_pixel = s->display.x->cursor_pixel;
438 int fg_pixel = s->display.x->foreground_pixel;
439 int bg_pixel = s->display.x->background_pixel;
440 int intborder = s->display.x->internal_border_width;
441
442 while (n)
443 {
444 /* Get the face-code of the next GLYPH. */
445 int cf, len;
446 int g = *gp;
447
448 while (GLYPH_ALIAS_P (tbase, tlen, g))
449 g = GLYPH_ALIAS (tbase, g);
450
451 cf = g >> 8;
452
453 /* Find the run of consecutive glyphs with the same face-code.
454 Extract their character codes into BUF. */
455 cp = buf;
456 while (n > 0)
457 {
458 g = *gp;
459 while (GLYPH_ALIAS_P (tbase, tlen, g))
460 g = GLYPH_ALIAS (tbase, g);
461 if ((g >> 8) != cf)
462 break;
463
464 *cp++ = 0377 & g;
465 --n;
466 ++gp;
467 }
468
469 /* LEN gets the length of the run. */
470 len = cp - buf;
471
472 /* Now output this run of chars, with the font and pixel values
473 determined by the face code CF. */
474 if (cf == 0)
475 {
476 #ifdef HAVE_X11
477 GC GC_cursor = s->display.x->cursor_gc;
478 GC GC_reverse = s->display.x->reverse_gc;
479 GC GC_normal = s->display.x->normal_gc;
480
481 XDrawImageString (x_current_display, window,
482 (hl == 2
483 ? GC_cursor
484 : (hl ? GC_reverse : GC_normal)),
485 left, top + FONT_BASE (font), buf, len);
486 #else
487 XText (window, left, top,
488 buf,
489 len,
490 font->id,
491 (hl == 2
492 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
493 : hl ? bg_pixel : fg_pixel),
494 (hl == 2 ? cursor_pixel
495 : hl ? fg_pixel : bg_pixel));
496 #endif /* HAVE_X11 */
497 }
498 else
499 {
500 #ifdef HAVE_X11
501 if (FACE_IS_FONT (cf))
502 XDrawImageString (x_current_display, s->display.x->window_desc,
503 FACE_GC (cf),
504 left, top + FONT_BASE (FACE_FONT (cf)),
505 buf, len);
506 else if (FACE_IS_IMAGE (cf))
507 XCopyPlane (x_current_display, FACE_IMAGE (cf),
508 s->display.x->window_desc,
509 s->display.x->normal_gc,
510 0, 0,
511 FACE_IMAGE_WIDTH (cf),
512 FACE_IMAGE_HEIGHT (cf), left, top);
513 else
514 abort ();
515 #else
516 register struct face *fp = x_face_table[cf];
517
518 XText (window, left, top,
519 buf,
520 len,
521 fp->font->id,
522 (hl == 2
523 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
524 : hl ? fp->bg : fp->fg),
525 (hl == 2 ? cursor_pixel
526 : hl ? fp->fg : fp->bg));
527 #endif /* HAVE_X11 */
528 }
529 left += len * FONT_WIDTH (font);
530 }
531 }
532 #endif
533 \f
534 /* Output some text at the nominal screen cursor position,
535 advancing the cursor over the text.
536 Output LEN glyphs at START.
537
538 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
539 controls the pixel values used for foreground and background. */
540
541 static
542 XTwrite_glyphs (start, len)
543 register GLYPH *start;
544 int len;
545 {
546 register int temp_length;
547 int mask;
548 struct screen *s;
549
550 BLOCK_INPUT;
551
552 s = updating_screen;
553 if (s == 0)
554 {
555 s = selected_screen;
556 /* If not within an update,
557 output at the screen's visible cursor. */
558 curs_x = s->cursor_x;
559 curs_y = s->cursor_y;
560 }
561
562 dumpglyphs (s,
563 (curs_x * FONT_WIDTH (s->display.x->font)
564 + s->display.x->internal_border_width),
565 (curs_y * FONT_HEIGHT (s->display.x->font)
566 + s->display.x->internal_border_width),
567 start, len, highlight, s->display.x->font);
568
569 /* If we drew on top of the cursor, note that it is turned off. */
570 if (curs_y == s->phys_cursor_y
571 && curs_x <= s->phys_cursor_x
572 && curs_x + len > s->phys_cursor_x)
573 s->phys_cursor_x = -1;
574
575 if (updating_screen == 0)
576 {
577 s->cursor_x += len;
578 x_display_cursor (s, 1);
579 s->cursor_x -= len;
580 }
581 else
582 curs_x += len;
583
584 UNBLOCK_INPUT;
585 }
586 \f
587 /* Erase the current text line from the nominal cursor position (inclusive)
588 to column FIRST_UNUSED (exclusive). The idea is that everything
589 from FIRST_UNUSED onward is already erased. */
590
591 static
592 XTclear_end_of_line (first_unused)
593 register int first_unused;
594 {
595 struct screen *s = updating_screen;
596 int mask;
597
598 if (s == 0)
599 abort ();
600
601 if (curs_y < 0 || curs_y >= s->height)
602 return;
603 if (first_unused <= 0)
604 return;
605
606 if (first_unused >= s->width)
607 first_unused = s->width;
608
609 BLOCK_INPUT;
610
611 /* Notice if the cursor will be cleared by this operation. */
612 if (curs_y == s->phys_cursor_y
613 && curs_x <= s->phys_cursor_x
614 && s->phys_cursor_x < first_unused)
615 s->phys_cursor_x = -1;
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 /* Hide 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 (! SCREEN_IS_X (s))
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 /* Position of the mouse in characters */
1290 unsigned int x_mouse_x, x_mouse_y;
1291
1292 /* Offset in buffer of character under the pointer, or 0. */
1293 extern int mouse_buffer_offset;
1294
1295 extern int buffer_posn_from_coords ();
1296
1297 /* Symbols from xfns.c to denote the different parts of a window. */
1298 extern Lisp_Object Qmodeline_part, Qtext_part;
1299
1300 #if 0
1301 /* Set *RESULT to an emacs input_event corresponding to MOTION_EVENT.
1302 S is the screen in which the event occurred.
1303
1304 WINDOW_TYPE says whether the event happened in a scrollbar window
1305 or a text window, affecting the format of the event created.
1306
1307 PART specifies which part of the scrollbar the event happened in,
1308 if WINDOW_TYPE == scrollbar_window.
1309
1310 If the mouse is over the same character as the last time we checked,
1311 don't return an event; set result->kind to no_event. */
1312
1313 static void
1314 notice_mouse_movement (result, motion_event, s, window_type, part)
1315 struct input_event *result;
1316 XMotionEvent motion_event;
1317 struct screen *s;
1318 int window_type;
1319 Lisp_Object part;
1320 {
1321 int x, y, root_x, root_y, pix_x, pix_y;
1322 unsigned int keys_and_buttons;
1323 Window w, root_window;
1324
1325 /* Unless we decide otherwise below, return a non-event. */
1326 result->kind = no_event;
1327
1328 if (XQueryPointer (x_current_display,
1329 s->display.x->window_desc,
1330 &root_window, &w,
1331 &root_x, &root_y, &pix_x, &pix_y,
1332 &keys_and_buttons)
1333 == False)
1334 return;
1335
1336 #if 0
1337 if (w == None) /* Mouse no longer in window. */
1338 return Qnil;
1339 #endif
1340
1341 pixel_to_glyph_translation (s, pix_x, pix_y, &x, &y);
1342 if (x == x_mouse_x && y == x_mouse_y)
1343 return;
1344
1345 x_mouse_x = x;
1346 x_mouse_y = y;
1347
1348 /* What sort of window are we in now? */
1349 if (window_type == text_window) /* Text part */
1350 {
1351 int modeline_p;
1352
1353 Vmouse_window = window_from_coordinates (s, x, y, &modeline_p);
1354
1355 if (XTYPE (Vmouse_window) == Lisp_Window)
1356 mouse_buffer_offset
1357 = buffer_posn_from_coords (XWINDOW (Vmouse_window), x, y);
1358 else
1359 mouse_buffer_offset = 0;
1360
1361 if (EQ (Vmouse_window, Qnil))
1362 Vmouse_screen_part = Qnil;
1363 else if (modeline_p)
1364 Vmouse_screen_part = Qmodeline_part;
1365 else
1366 Vmouse_screen_part = Qtext_part;
1367
1368 result->kind = window_sys_event;
1369 result->code = Qmouse_moved;
1370
1371 return;
1372 }
1373 else if (window_type == scrollbar_window) /* Scrollbar */
1374 {
1375 Vmouse_window = s->selected_window;
1376 mouse_buffer_offset = 0;
1377 Vmouse_screen_part = part;
1378
1379 result->kind = window_sys_event;
1380 result->code = Qmouse_moved;
1381
1382 return;
1383 }
1384
1385 return;
1386 }
1387 #endif
1388
1389 \f
1390 /* Mouse clicks and mouse movement. Rah. */
1391 #ifdef HAVE_X11
1392
1393 /* Given a pixel position (PIX_X, PIX_Y) on the screen S, return
1394 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1395 that the glyph at X, Y occupies, if BOUNDS != 0. */
1396 static void
1397 pixel_to_glyph_coords (s, pix_x, pix_y, x, y, bounds)
1398 SCREEN_PTR s;
1399 register unsigned int pix_x, pix_y;
1400 register int *x, *y;
1401 XRectangle *bounds;
1402 {
1403 int ibw = s->display.x->internal_border_width;
1404 int width, height;
1405 FONT_TYPE *font = s->display.x->font;
1406
1407 width = FONT_WIDTH (font);
1408 height = FONT_HEIGHT (font);
1409
1410 /* What line is it on? */
1411 if (pix_y < ibw)
1412 *y = 0;
1413 else if (pix_y > s->display.x->pixel_height - ibw)
1414 *y = SCREEN_HEIGHT (s) - 1;
1415 else
1416 *y = (pix_y - ibw) / height;
1417
1418 /* And what column? */
1419 if (pix_x < ibw)
1420 *x = 0;
1421 else if (pix_x > s->display.x->pixel_width - ibw)
1422 *x = SCREEN_WIDTH (s) - 1;
1423 else
1424 *x = (pix_x - ibw) / width;
1425
1426 if (bounds)
1427 {
1428 bounds->width = width;
1429 bounds->height = height;
1430 bounds->x = ibw + (*x * width);
1431 bounds->y = ibw + (*y * height);
1432 }
1433 }
1434
1435 /* Any buttons grabbed. */
1436 unsigned int x_mouse_grabbed;
1437
1438 /* Convert a set of X modifier bits to the proper form for a
1439 struct input_event modifiers value. */
1440
1441 static Lisp_Object
1442 x_convert_modifiers (state)
1443 unsigned int state;
1444 {
1445 return ( ((state & (ShiftMask | LockMask)) ? shift_modifier : 0)
1446 | ((state & ControlMask) ? ctrl_modifier : 0)
1447 | ((state & Mod1Mask) ? meta_modifier : 0));
1448 }
1449
1450 extern struct screen *x_window_to_scrollbar ();
1451 extern Lisp_Object Vmouse_event;
1452
1453 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1454
1455 If the event is a button press, then note that we have grabbed
1456 the mouse.
1457
1458 If PART and PREFIX are 0, then the event occurred in the text part;
1459 otherwise it happened in a scrollbar. */
1460
1461 static Lisp_Object
1462 construct_mouse_click (result, event, s, part, prefix)
1463 struct input_event *result;
1464 XButtonEvent *event;
1465 struct screen *s;
1466 int prefix;
1467 Lisp_Object part;
1468 {
1469 /* Initialize those fields text and scrollbar clicks hold in common.
1470 Make the event type no_event; we'll change that when we decide
1471 otherwise. */
1472 result->kind = no_event;
1473 XSET (result->code, Lisp_Int, event->button);
1474 XSET (result->timestamp, Lisp_Int, event->time);
1475 result->modifiers = (x_convert_modifiers (event->state)
1476 | (event->type == ButtonRelease ? up_modifier : 0));
1477 XSET (result->timestamp, Lisp_Int, (event->time & 0x7fffff));
1478
1479 /* Notice if the mouse is still grabbed. */
1480 if (event->type == ButtonPress)
1481 {
1482 if (! x_mouse_grabbed)
1483 Vmouse_depressed = Qt;
1484 x_mouse_grabbed |= (1 << event->button);
1485 }
1486 else if (event->type == ButtonRelease)
1487 {
1488 x_mouse_grabbed &= ~(1 << event->button);
1489 if (!x_mouse_grabbed)
1490 Vmouse_depressed = Qnil;
1491 }
1492
1493 if (part) /* Scrollbar event */
1494 {
1495 int pos, len;
1496
1497 pos = event->y - (s->display.x->v_scrollbar_width - 2);
1498 XSET (x_mouse_x, Lisp_Int, pos);
1499 len = ((FONT_HEIGHT (s->display.x->font) * s->height)
1500 + s->display.x->internal_border_width
1501 - (2 * (s->display.x->v_scrollbar_width - 2)));
1502 XSET (x_mouse_y, Lisp_Int, len);
1503
1504 result->kind = scrollbar_click;
1505 result->part = part;
1506 XSET (result->x, Lisp_Int, (s->display.x->top_pos - event->y));
1507 XSET (result->y, Lisp_Int, s->display.x->pixel_height);
1508 result->screen = s;
1509 }
1510 else /* Text Window Event */
1511 {
1512 int row, column;
1513
1514 pixel_to_glyph_coords (s, event->x, event->y, &column, &row, NULL);
1515 result->kind = mouse_click;
1516 result->x = column;
1517 result->y = row;
1518 result->screen = s;
1519 }
1520 }
1521
1522
1523 /* Mouse movement. Rah.
1524
1525 In order to avoid asking for motion events and then throwing most
1526 of them away or busy-polling the server for mouse positions, we ask
1527 the server for pointer motion hints. This means that we get only
1528 one event per group of mouse movements. "Groups" are delimited by
1529 other kinds of events (focus changes and button clicks, for
1530 example), or by XQueryPointer calls; when one of these happens, we
1531 get another MotionNotify event the next time the mouse moves. This
1532 is at least as efficient than getting motion events when mouse
1533 tracking is on, and I suspect only negligibly worse when tracking
1534 is off.
1535
1536 The silly O'Reilly & Associates Nutshell guides barely document
1537 pointer motion hints at all (I think you have to infer how they
1538 work from an example), and the description of XQueryPointer doesn't
1539 mention that calling it causes you to get another motion hint from
1540 the server, which is very important. */
1541
1542 /* Where the mouse was last time we reported a mouse event. */
1543 static SCREEN_PTR last_mouse_screen;
1544 static XRectangle last_mouse_glyph;
1545
1546 /* Function to report a mouse movement to the mainstream Emacs code.
1547 The input handler calls this.
1548
1549 We have received a mouse movement event, which is given in *event.
1550 If the mouse is over a different glyph than it was last time, tell
1551 the mainstream emacs code by setting mouse_moved. If not, ask for
1552 another motion event, so we can check again the next time it moves. */
1553 static void
1554 note_mouse_position (screen, event)
1555 SCREEN_PTR screen;
1556 XMotionEvent *event;
1557
1558 {
1559 /* Has the mouse moved off the glyph it was on at the last sighting? */
1560 if (event->x < last_mouse_glyph.x
1561 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1562 || event->y < last_mouse_glyph.y
1563 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1564 mouse_moved = 1;
1565 else
1566 {
1567 /* It's on the same glyph. Call XQueryPointer so we'll get an
1568 event the next time the mouse moves and we can see if it's
1569 *still* on the same glyph. */
1570 int dummy;
1571
1572 XQueryPointer (event->display, event->window,
1573 (Window *) &dummy, (Window *) &dummy,
1574 &dummy, &dummy, &dummy, &dummy,
1575 (unsigned int *) &dummy);
1576 }
1577 }
1578
1579 /* Return the current position of the mouse.
1580
1581 This clears the mouse_moved flag, so we can wait for the next mouse
1582 position. This also calls XQueryPointer, which will cause the
1583 server to give us another MotionNotify when the mouse moves again.
1584 */
1585
1586 static void
1587 XTmouse_position (s, x, y, time)
1588 SCREEN_PTR *s;
1589 Lisp_Object *x, *y;
1590 Lisp_Object *time;
1591 {
1592 int ix, iy, dummy;
1593 Display *d = x_current_display;
1594 Window guess, root, child;
1595
1596 BLOCK_INPUT;
1597
1598 /* I would like to have an X function that just told me the
1599 innermost window containing the mouse.
1600
1601 /* There doesn't seem to be any way to just get the innermost window
1602 containing the pointer, no matter what X screen it's on; you have
1603 to guess a window, and then X will tell you which one of that
1604 window's children it's in. If the pointer isn't in any of that
1605 window's children, it gives you a root window that contains it.
1606
1607 So we start with the selected screen's window and chase down
1608 branches under the guidance of XQueryPointer until we hit a leaf
1609 (all of the Emacs windows we care about are leaf windows). If at
1610 any time XQueryPointer returns false, that means that the current
1611 window does not contain the pointer any more (perhaps it moved),
1612 so we start with the root window XQueryPointer has given us and
1613 start again. */
1614
1615 guess = selected_screen->display.x->window_desc;
1616 for (;;)
1617 if (XQueryPointer (d, guess, &root, &child,
1618 &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
1619 {
1620 if (child == None)
1621 /* Guess is a leaf window, and it contains the pointer. */
1622 break;
1623 else
1624 guess = child;
1625 }
1626 else
1627 /* When XQueryPointer returns False, the pointer isn't in guess
1628 anymore, but root is the root window of the screen we should
1629 try instead. */
1630 guess = root;
1631
1632 *s = last_mouse_screen = x_window_to_screen (guess);
1633 if (! *s)
1634 *x = *y = Qnil;
1635 else
1636 {
1637 pixel_to_glyph_coords (*s, ix, iy, &ix, &iy, &last_mouse_glyph);
1638 XSET (*x, Lisp_Int, ix);
1639 XSET (*y, Lisp_Int, iy);
1640 }
1641
1642 mouse_moved = 0;
1643
1644 /* I don't know how to find the time for the last movement; it seems
1645 like XQueryPointer ought to return it, but it doesn't. */
1646 *time = Qnil;
1647
1648 UNBLOCK_INPUT;
1649 }
1650
1651 \f
1652 static char *events[] =
1653 {
1654 "0: ERROR!",
1655 "1: REPLY",
1656 "KeyPress",
1657 "KeyRelease",
1658 "ButtonPress",
1659 "ButtonRelease",
1660 "MotionNotify",
1661 "EnterNotify",
1662 "LeaveNotify",
1663 "FocusIn",
1664 "FocusOut",
1665 "KeymapNotify",
1666 "Expose",
1667 "GraphicsExpose",
1668 "NoExpose",
1669 "VisibilityNotify",
1670 "CreateNotify",
1671 "DestroyNotify",
1672 "UnmapNotify",
1673 "MapNotify",
1674 "MapRequest",
1675 "ReparentNotify",
1676 "ConfigureNotify",
1677 "ConfigureRequest",
1678 "GravityNotify",
1679 "ResizeRequest",
1680 "CirculateNotify",
1681 "CirculateRequest",
1682 "PropertyNotify",
1683 "SelectionClear",
1684 "SelectionRequest",
1685 "SelectionNotify",
1686 "ColormapNotify",
1687 "ClientMessage",
1688 "MappingNotify",
1689 "LASTEvent"
1690 };
1691 #else /* X10 */
1692 #define XEvent XKeyPressedEvent
1693 #endif /* HAVE_X11 */
1694
1695 /* Timestamp of enter window event. This is only used by XTread_socket,
1696 but we have to put it out here, since static variables within functions
1697 sometimes don't work. */
1698 static Time enter_timestamp;
1699
1700 /* Read events coming from the X server.
1701 This routine is called by the SIGIO handler.
1702 We return as soon as there are no more events to be read.
1703
1704 Events representing keys are stored in buffer BUFP,
1705 which can hold up to NUMCHARS characters.
1706 We return the number of characters stored into the buffer,
1707 thus pretending to be `read'.
1708
1709 WAITP is nonzero if we should block until input arrives.
1710 EXPECTED is nonzero if the caller knows input is available. */
1711
1712 Lisp_Object
1713 XTread_socket (sd, bufp, numchars, waitp, expected)
1714 register int sd;
1715 register struct input_event *bufp;
1716 register int numchars;
1717 int waitp;
1718 int expected;
1719 {
1720 int count = 0;
1721 int nbytes = 0;
1722 int mask;
1723 int items_pending; /* How many items are in the X queue. */
1724 XEvent event;
1725 struct screen *s;
1726 int event_found;
1727 int prefix;
1728 Lisp_Object part;
1729
1730 if (x_input_blocked)
1731 {
1732 x_pending_input = 1;
1733 return -1;
1734 }
1735
1736 x_pending_input = 0;
1737 BLOCK_INPUT;
1738
1739 if (numchars <= 0)
1740 abort (); /* Don't think this happens. */
1741
1742 #ifdef FIOSNBIO
1743 /* If available, Xlib uses FIOSNBIO to make the socket
1744 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
1745 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
1746 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
1747 fcntl (fileno (stdin), F_SETFL, 0);
1748 #endif
1749
1750 #ifndef SIGIO
1751 #ifndef HAVE_SELECT
1752 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
1753 {
1754 extern int read_alarm_should_throw;
1755 read_alarm_should_throw = 1;
1756 XPeekEvent (XDISPLAY &event);
1757 read_alarm_should_throw = 0;
1758 }
1759 #endif
1760 #endif
1761
1762 while (XStuffPending () != 0)
1763 {
1764 XNextEvent (XDISPLAY &event);
1765 event_found = 1;
1766
1767 switch (event.type)
1768 {
1769 #ifdef HAVE_X11
1770
1771 case SelectionClear: /* Someone has grabbed ownership. */
1772 x_disown_selection (event.xselectionclear.window,
1773 event.xselectionclear.selection,
1774 event.xselectionclear.time);
1775 break;
1776
1777 case SelectionRequest: /* Someone wants our selection. */
1778 x_answer_selection_request (event);
1779 break;
1780
1781 case PropertyNotify:
1782 /* If we were to do this synchronously, there'd be no worry
1783 about re-selecting. */
1784 x_send_incremental (event);
1785 break;
1786
1787 case Expose:
1788 s = x_window_to_screen (event.xexpose.window);
1789 if (s)
1790 {
1791 if (s->visible == 0)
1792 {
1793 s->visible = 1;
1794 s->iconified = 0;
1795 SET_SCREEN_GARBAGED (s);
1796 }
1797 else
1798 dumprectangle (x_window_to_screen (event.xexpose.window),
1799 event.xexpose.x, event.xexpose.y,
1800 event.xexpose.width, event.xexpose.height);
1801 }
1802 break;
1803
1804 case GraphicsExpose: /* This occurs when an XCopyArea's
1805 source area was obscured or not
1806 available.*/
1807 dumprectangle (x_window_to_screen (event.xgraphicsexpose.drawable),
1808 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
1809 event.xgraphicsexpose.width,
1810 event.xgraphicsexpose.height);
1811 break;
1812
1813 case NoExpose: /* This occurs when an XCopyArea's
1814 source area was completely
1815 available */
1816 break;
1817 #else /* not HAVE_X11 */
1818 case ExposeWindow:
1819 if (event.subwindow != 0)
1820 break; /* duplicate event */
1821 s = x_window_to_screen (event.window);
1822 if (event.window == s->display.x->icon_desc)
1823 {
1824 refreshicon (s);
1825 s->iconified = 1;
1826 }
1827 if (event.window == s->display.x->window_desc)
1828 {
1829 /* Say must check all windows' needs_exposure flags. */
1830 expose_all_windows = 1;
1831 s->display.x->needs_exposure = 1;
1832 s->visible = 1;
1833 }
1834 break;
1835
1836 case ExposeRegion:
1837 if (event.subwindow != 0)
1838 break; /* duplicate event */
1839 s = x_window_to_screen (event.window);
1840 if (event.window == s->display.x->icon_desc)
1841 {
1842 refreshicon (s);
1843 break;
1844 }
1845 /* If window already needs full redraw, ignore this rectangle. */
1846 if (expose_all_windows && s->display.x->needs_exposure)
1847 break;
1848 /* Put the event on the queue of rectangles to redraw. */
1849 if (enqueue_event (&event, &x_expose_queue))
1850 /* If it is full, we can't record the rectangle,
1851 so redraw this entire window. */
1852 {
1853 /* Say must check all windows' needs_exposure flags. */
1854 expose_all_windows = 1;
1855 s->display.x->needs_exposure = 1;
1856 }
1857 break;
1858
1859 case ExposeCopy:
1860 /* This should happen only when we are expecting it,
1861 in x_read_exposes. */
1862 abort ();
1863 #endif /* not HAVE_X11 */
1864
1865 #ifdef HAVE_X11
1866 case UnmapNotify:
1867 {
1868 XWMHints *hints;
1869
1870 s = x_window_to_screen (event.xunmap.window);
1871 if (s) /* S may no longer exist if
1872 the screen was deleted. */
1873 {
1874 /* While a screen is unmapped, display generation is
1875 disabled; you don't want to spend time updating a
1876 display that won't ever be seen. */
1877 s->visible = 0;
1878 x_mouse_x = x_mouse_y = -1;
1879 }
1880 }
1881 break;
1882
1883 case MapNotify:
1884 s = x_window_to_screen (event.xmap.window);
1885 if (s)
1886 {
1887 s->visible = 1;
1888 s->iconified = 0;
1889
1890 /* wait_reading_process_input will notice this and update
1891 the screen's display structures. */
1892 SET_SCREEN_GARBAGED (s);
1893 }
1894 break;
1895
1896 /* Turn off processing if we become fully obscured. */
1897 case VisibilityNotify:
1898 break;
1899
1900 #else
1901 case UnmapWindow:
1902 s = x_window_to_screen (event.window);
1903 if (event.window == s->display.x->icon_desc)
1904 s->iconified = 0;
1905 if (event.window == s->display.x->window_desc)
1906 s->visible = 0;
1907 break;
1908 #endif /* HAVE_X11 */
1909
1910 #ifdef HAVE_X11
1911 case KeyPress:
1912 s = x_window_to_screen (event.xkey.window);
1913 if (s != 0)
1914 {
1915 KeySym keysym;
1916 XComposeStatus status;
1917 char copy_buffer[80];
1918
1919 /* This will have to go some day... */
1920 nbytes = XLookupString (&event.xkey,
1921 copy_buffer,
1922 80,
1923 &keysym,
1924 &status);
1925
1926 /* Strip off the vendor-specific keysym bit, and take a shot
1927 at recognizing the codes. HP servers have extra keysyms
1928 that fit into the MiscFunctionKey category. */
1929 keysym &= ~(1<<28);
1930
1931 if (numchars > 1)
1932 {
1933 if (IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
1934 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
1935 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
1936 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
1937 {
1938 bufp->kind = non_ascii_keystroke;
1939 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
1940 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
1941 bufp->modifiers = x_convert_modifiers (event.xkey.state);
1942 XSET (bufp->timestamp, Lisp_Int, event.xkey.time);
1943 bufp++;
1944 count++;
1945 numchars--;
1946 }
1947 else if (numchars > nbytes)
1948 {
1949 register int i;
1950
1951 if (nbytes == 1)
1952 {
1953 if (event.xkey.state & Mod1Mask)
1954 *copy_buffer |= METABIT;
1955 bufp->kind = ascii_keystroke;
1956 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
1957 XSET (bufp->code, Lisp_Int, *copy_buffer);
1958 XSET (bufp->timestamp, Lisp_Int, event.xkey.time);
1959 bufp++;
1960 }
1961 else
1962 for (i = nbytes - 1; i > 1; i--)
1963 {
1964 bufp->kind = ascii_keystroke;
1965 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
1966 XSET (bufp->timestamp, Lisp_Int, event.xkey.time);
1967 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
1968 bufp++;
1969 }
1970
1971 count += nbytes;
1972 numchars -= nbytes;
1973 }
1974 }
1975 }
1976 break;
1977 #else
1978 case KeyPressed:
1979 {
1980 register char *where_mapping;
1981
1982 s = x_window_to_screen (event.window);
1983 /* Ignore keys typed on icon windows. */
1984 if (s != 0 && event.window == s->display.x->icon_desc)
1985 break;
1986 where_mapping = XLookupMapping (&event, &nbytes);
1987 /* Nasty fix for arrow keys */
1988 if (!nbytes && IsCursorKey (event.detail & 0xff))
1989 {
1990 switch (event.detail & 0xff)
1991 {
1992 case KC_CURSOR_LEFT:
1993 where_mapping = "\002";
1994 break;
1995 case KC_CURSOR_RIGHT:
1996 where_mapping = "\006";
1997 break;
1998 case KC_CURSOR_UP:
1999 where_mapping = "\020";
2000 break;
2001 case KC_CURSOR_DOWN:
2002 where_mapping = "\016";
2003 break;
2004 }
2005 nbytes = 1;
2006 }
2007 if (numchars - nbytes > 0)
2008 {
2009 register int i;
2010
2011 for (i = 0; i < nbytes; i++)
2012 {
2013 bufp->kind = ascii_keystroke;
2014 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2015 XSET (bufp->time, Lisp_Int, event.xkey.time);
2016 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
2017 bufp++;
2018 }
2019 count += nbytes;
2020 numchars -= nbytes;
2021 }
2022 }
2023 break;
2024 #endif /* HAVE_X11 */
2025
2026 #ifdef HAVE_X11
2027 case EnterNotify:
2028 s = x_window_to_screen (event.xcrossing.window);
2029
2030 if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
2031 ;
2032 else if (event.xcrossing.focus) /* Entered Window */
2033 {
2034 /* If we decide we want to generate an event to be seen
2035 by the rest of Emacs, we put it here. */
2036 struct input_event emacs_event;
2037 emacs_event.kind = no_event;
2038
2039 /* Avoid nasty pop/raise loops. */
2040 if (s && (!(s->auto_raise)
2041 || !(s->auto_lower)
2042 || (event.xcrossing.time - enter_timestamp) > 500))
2043 {
2044 x_new_focus_screen (s);
2045 enter_timestamp = event.xcrossing.time;
2046 }
2047 #if 0
2048 else if ((s = x_window_to_scrollbar (event.xcrossing.window,
2049 &part, &prefix)))
2050 /* Fake a motion event */
2051 notice_mouse_movement (&emacs_event,
2052 event.xmotion, s, scrollbar_window,
2053 part);
2054 #endif
2055
2056 #if 0
2057 if (! EQ (Vx_send_mouse_movement_events, Qnil)
2058 && numchars >= 1
2059 && emacs_event.kind != no_event)
2060 {
2061 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2062 bufp++;
2063 count++;
2064 numchars--;
2065 }
2066 #endif
2067 }
2068 else if (s == x_focus_screen)
2069 x_new_focus_screen (0);
2070 #if 0
2071 else if (s = x_window_to_screen (event.xcrossing.window))
2072 x_mouse_screen = s;
2073 #endif
2074
2075 break;
2076
2077 case FocusIn:
2078 s = x_window_to_screen (event.xfocus.window);
2079 if (s)
2080 x_new_focus_screen (s);
2081 break;
2082
2083 case LeaveNotify:
2084 if (event.xcrossing.detail != NotifyInferior
2085 && event.xcrossing.subwindow == None
2086 && event.xcrossing.mode == NotifyNormal)
2087 {
2088 s = x_window_to_screen (event.xcrossing.window);
2089 if (event.xcrossing.focus)
2090 x_new_focus_screen (s);
2091 else if (s == x_focus_screen)
2092 x_new_focus_screen (0);
2093 }
2094 break;
2095
2096 case FocusOut:
2097 s = x_window_to_screen (event.xfocus.window);
2098 if (s && s == x_focus_screen)
2099 x_new_focus_screen (0);
2100 break;
2101
2102 #else /* not HAVE_X11 */
2103
2104 case EnterWindow:
2105 if ((event.detail & 0xFF) == 1)
2106 break; /* Coming from our own subwindow */
2107 if (event.subwindow != 0)
2108 break; /* Entering our own subwindow. */
2109
2110 {
2111 extern int waiting_for_input;
2112 struct screen *old_s = x_input_screen;
2113
2114 s = x_window_to_screen (event.window);
2115 x_mouse_screen = s;
2116
2117 if (waiting_for_input && x_focus_screen == 0)
2118 x_new_focus_screen (s);
2119 }
2120 break;
2121
2122 case LeaveWindow:
2123 if ((event.detail & 0xFF) == 1)
2124 break; /* Entering our own subwindow */
2125 if (event.subwindow != 0)
2126 break; /* Leaving our own subwindow. */
2127
2128 x_mouse_screen = 0;
2129 if (x_focus_screen == 0
2130 && x_input_screen != 0
2131 && x_input_screen == x_window_to_screen (event.window)
2132 && event.window == x_input_screen->display.x->window_desc)
2133 {
2134 s = x_input_screen;
2135 x_input_screen = 0;
2136 if (s)
2137 screen_unhighlight (s);
2138 }
2139 break;
2140 #endif /* not HAVE_X11 */
2141
2142 #ifdef HAVE_X11
2143 case MotionNotify:
2144 {
2145 s = x_window_to_screen (event.xmotion.window);
2146 if (s)
2147 note_mouse_position (s, &event.xmotion);
2148 #if 0
2149 else if ((s = x_window_to_scrollbar (event.xmotion.window,
2150 &part, &prefix)))
2151 {
2152 What should go here?
2153 }
2154 #endif
2155 }
2156 break;
2157
2158 case ConfigureNotify:
2159 {
2160 int rows, columns;
2161 s = x_window_to_screen (event.xconfigure.window);
2162 if (!s)
2163 break;
2164
2165 columns = ((event.xconfigure.width -
2166 (2 * s->display.x->internal_border_width)
2167 - s->display.x->v_scrollbar_width)
2168 / FONT_WIDTH (s->display.x->font));
2169 rows = ((event.xconfigure.height -
2170 (2 * s->display.x->internal_border_width)
2171 - s->display.x->h_scrollbar_height)
2172 / FONT_HEIGHT (s->display.x->font));
2173
2174 /* Even if the number of character rows and columns has
2175 not changed, the font size may have changed, so we need
2176 to check the pixel dimensions as well. */
2177 if (columns != s->width
2178 || rows != s->height
2179 || event.xconfigure.width != s->display.x->pixel_width
2180 || event.xconfigure.height != s->display.x->pixel_height)
2181 {
2182 change_screen_size (s, rows, columns, 0);
2183 x_resize_scrollbars (s);
2184 SET_SCREEN_GARBAGED (s);
2185 }
2186
2187 s->display.x->pixel_width = event.xconfigure.width;
2188 s->display.x->pixel_height = event.xconfigure.height;
2189 s->display.x->left_pos = event.xconfigure.x;
2190 s->display.x->top_pos = event.xconfigure.y;
2191 break;
2192 }
2193
2194 case ButtonPress:
2195 case ButtonRelease:
2196 {
2197 /* If we decide we want to generate an event to be seen
2198 by the rest of Emacs, we put it here. */
2199 struct input_event emacs_event;
2200 emacs_event.kind = no_event;
2201
2202 s = x_window_to_screen (event.xbutton.window);
2203 if (s)
2204 if (!x_focus_screen || (s == x_focus_screen))
2205 construct_mouse_click (&emacs_event,
2206 &event, s, 0, 0);
2207 else
2208 continue;
2209 else
2210 if ((s = x_window_to_scrollbar (event.xbutton.window,
2211 &part, &prefix)))
2212 {
2213 if (!x_focus_screen || (selected_screen == x_focus_screen))
2214 construct_mouse_click (&emacs_event,
2215 &event, s, part, prefix);
2216 else
2217 continue;
2218 }
2219
2220 if (numchars >= 1 && emacs_event.kind != no_event)
2221 {
2222 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2223 bufp++;
2224 count++;
2225 numchars--;
2226 }
2227 }
2228 break;
2229
2230 #else /* not HAVE_X11 */
2231 case ButtonPressed:
2232 case ButtonReleased:
2233 s = x_window_to_screen (event.window);
2234 if (s)
2235 {
2236 if (event.window == s->display.x->icon_desc)
2237 {
2238 x_make_screen_visible (s);
2239
2240 if (warp_mouse_on_deiconify)
2241 XWarpMouse (s->display.x->window_desc, 10, 10);
2242 break;
2243 }
2244 if (event.window == s->display.x->window_desc)
2245 {
2246 if (s->auto_raise)
2247 x_raise_screen (s);
2248 }
2249 }
2250 enqueue_event (&event, &x_mouse_queue);
2251 if (numchars >= 2)
2252 {
2253 bufp->kind = ascii_keystroke;
2254 bufp->code = (char) 'X' & 037; /* C-x */
2255 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
2256 XSET (bufp->time, Lisp_Int, event.xkey.time);
2257 bufp++;
2258
2259 bufp->kind = ascii_keystroke;
2260 bufp->code = (char) 0; /* C-@ */
2261 bufp->screen = XSCREEN (SCREEN_FOCUS_SCREEN (s));
2262 XSET (bufp->time, Lisp_Int, event.xkey.time);
2263 bufp++;
2264
2265 count += 2;
2266 numchars -= 2;
2267 }
2268 break;
2269 #endif /* not HAVE_X11 */
2270
2271 #ifdef HAVE_X11
2272
2273 case CirculateNotify:
2274 break;
2275 case CirculateRequest:
2276 break;
2277
2278 #endif /* HAVE_X11 */
2279
2280 case MappingNotify:
2281 if (event.xmapping.request == MappingKeyboard)
2282 /* Someone has changed the keyboard mapping - flush the
2283 local cache. */
2284 XRefreshKeyboardMapping (&event.xmapping);
2285 break;
2286
2287 default:
2288 break;
2289 }
2290 }
2291
2292 #if 0
2293 #ifdef HAVE_SELECT
2294 if (expected && ! event_found)
2295 {
2296 /* AOJ 880406: if select returns true but XPending doesn't, it means that
2297 there is an EOF condition; in other words, that X has died.
2298 Act as if there had been a hangup. */
2299
2300 int fd = ConnectionNumber (x_current_display);
2301 int mask = 1 << fd;
2302
2303 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
2304 (struct timeval *) 0)
2305 && !XStuffPending ())
2306 kill (getpid (), SIGHUP);
2307 }
2308 #endif /* HAVE_SELECT */
2309 #endif
2310
2311 if (updating_screen == 0)
2312 x_do_pending_expose ();
2313
2314 UNBLOCK_INPUT;
2315 return count;
2316 }
2317
2318 #ifndef HAVE_X11
2319 /* Read and process only Expose events
2320 until we get an ExposeCopy event; then return.
2321 This is used in insert/delete line.
2322 We assume input is already blocked. */
2323
2324 static void
2325 x_read_exposes ()
2326 {
2327 struct screen *s;
2328 XKeyPressedEvent event;
2329
2330 while (1)
2331 {
2332 /* while there are more events*/
2333 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
2334 switch (event.type)
2335 {
2336 case ExposeWindow:
2337 if (event.subwindow != 0)
2338 break; /* duplicate event */
2339 s = x_window_to_screen (event.window);
2340 if (event.window == s->display.x->icon_desc)
2341 {
2342 refreshicon (s);
2343 break;
2344 }
2345 if (event.window == s->display.x->window_desc)
2346 {
2347 expose_all_windows = 1;
2348 s->display.x->needs_exposure = 1;
2349 break;
2350 }
2351 break;
2352
2353 case ExposeRegion:
2354 if (event.subwindow != 0)
2355 break; /* duplicate event */
2356 s = x_window_to_screen (event.window);
2357 if (event.window == s->display.x->icon_desc)
2358 {
2359 refreshicon (s);
2360 break;
2361 }
2362 /* If window already needs full redraw, ignore this rectangle. */
2363 if (expose_all_windows && s->display.x->needs_exposure)
2364 break;
2365 /* Put the event on the queue of rectangles to redraw. */
2366 if (enqueue_event (&event, &x_expose_queue))
2367 /* If it is full, we can't record the rectangle,
2368 so redraw this entire window. */
2369 {
2370 /* Say must check all windows' needs_exposure flags. */
2371 expose_all_windows = 1;
2372 s->display.x->needs_exposure = 1;
2373 }
2374 break;
2375
2376 case ExposeCopy:
2377 return;
2378 }
2379 }
2380 }
2381 #endif /* HAVE_X11 */
2382
2383 \f
2384 /* Draw a hollow box cursor. Don't change the inside of the box. */
2385
2386 static void
2387 x_draw_box (s)
2388 struct screen *s;
2389 {
2390 int left = s->cursor_x * FONT_WIDTH (s->display.x->font)
2391 + s->display.x->internal_border_width;
2392 int top = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2393 + s->display.x->internal_border_width;
2394 int width = FONT_WIDTH (s->display.x->font);
2395 int height = FONT_HEIGHT (s->display.x->font);
2396
2397 #ifdef HAVE_X11
2398 /* Perhaps we should subtract 1 from width and height... */
2399 XDrawRectangle (x_current_display, s->display.x->window_desc,
2400 s->display.x->cursor_gc,
2401 left, top, width - 1, height - 1);
2402 #else
2403 XPixSet (s->display.x->window_desc,
2404 left, top, width, 1,
2405 s->display.x->cursor_pixel);
2406
2407 XPixSet (s->display.x->window_desc,
2408 left, top, 1, height,
2409 s->display.x->cursor_pixel);
2410
2411 XPixSet (s->display.x->window_desc,
2412 left+width-1, top, 1, height,
2413 s->display.x->cursor_pixel);
2414
2415 XPixSet (s->display.x->window_desc,
2416 left, top+height-1, width, 1,
2417 s->display.x->cursor_pixel);
2418 #endif /* HAVE_X11 */
2419 }
2420
2421 /* Clear the cursor of screen S to background color,
2422 and mark the cursor as not shown.
2423 This is used when the text where the cursor is
2424 is about to be rewritten. */
2425
2426 static void
2427 clear_cursor (s)
2428 struct screen *s;
2429 {
2430 int mask;
2431
2432 if (! s->visible
2433 || s->phys_cursor_x < 0)
2434 return;
2435
2436 #ifdef HAVE_X11
2437 x_display_cursor (s, 0);
2438 #if 0
2439 XClearArea (x_current_display, s->display.x->window_desc,
2440 s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2441 + s->display.x->internal_border_width,
2442 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2443 + s->display.x->internal_border_width,
2444 FONT_WIDTH (s->display.x->font) + 1, FONT_HEIGHT (s->display.x->font) + 1, False);
2445 #endif
2446 #else
2447 XPixSet (s->display.x->window_desc,
2448 s->phys_cursor_x * FONT_WIDTH (s->display.x->font) + s->display.x->internal_border_width,
2449 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font) + s->display.x->internal_border_width,
2450 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font),
2451 s->display.x->background_pixel);
2452 #endif /* HAVE_X11 */
2453 s->phys_cursor_x = -1;
2454 }
2455
2456 static void
2457 x_display_bar_cursor (s, on)
2458 struct screen *s;
2459 int on;
2460 {
2461 register int phys_x = s->phys_cursor_x;
2462 register int phys_y = s->phys_cursor_y;
2463 register int x1;
2464 register int y1;
2465 register int y2;
2466
2467 if (! s->visible || (! on && s->phys_cursor_x < 0))
2468 return;
2469
2470 #ifdef HAVE_X11
2471 if (phys_x >= 0 &&
2472 (!on || phys_x != s->cursor_x || phys_y != s->cursor_y))
2473 {
2474 x1 = phys_x * FONT_WIDTH (s->display.x->font)
2475 + s->display.x->internal_border_width;
2476 y1 = phys_y * FONT_HEIGHT (s->display.x->font)
2477 + s->display.x->internal_border_width - 1;
2478 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2479
2480 XDrawLine (x_current_display, s->display.x->window_desc,
2481 s->display.x->reverse_gc, x1, y1, x1, y2);
2482
2483 s->phys_cursor_x = phys_x = -1;
2484 }
2485
2486 if (on && s == x_highlight_screen)
2487 {
2488 x1 = s->cursor_x * FONT_WIDTH (s->display.x->font)
2489 + s->display.x->internal_border_width;
2490 y1 = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2491 + s->display.x->internal_border_width - 1;
2492 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2493
2494 XDrawLine (x_current_display, s->display.x->window_desc,
2495 s->display.x->cursor_gc, x1, y1, x1, y2);
2496
2497 s->phys_cursor_x = s->cursor_x;
2498 s->phys_cursor_y = s->cursor_y;
2499 }
2500 #else /* X10 */
2501 Give it up, dude.
2502 #endif /* X10 */
2503 }
2504
2505
2506 /* Redraw the glyph at ROW, COLUMN on screen S, in the style
2507 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2508 glyph drawn. */
2509
2510 static void
2511 x_draw_single_glyph (s, row, column, glyph, highlight)
2512 struct screen *s;
2513 int row, column;
2514 GLYPH glyph;
2515 int highlight;
2516 {
2517 dumpglyphs (s,
2518 (column * FONT_WIDTH (s->display.x->font)
2519 + s->display.x->internal_border_width),
2520 (row * FONT_HEIGHT (s->display.x->font)
2521 + s->display.x->internal_border_width),
2522 &glyph, 1, highlight, s->display.x->font);
2523 }
2524
2525 /* Turn the displayed cursor of screen S on or off according to ON.
2526 If ON is nonzero, where to put the cursor is specified
2527 by S->cursor_x and S->cursor_y. */
2528
2529 static void
2530 x_display_box_cursor (s, on)
2531 struct screen *s;
2532 int on;
2533 {
2534 struct screen_glyphs *current_glyphs = SCREEN_CURRENT_GLYPHS (s);
2535
2536 if (! s->visible)
2537 return;
2538
2539 /* If cursor is off and we want it off, return quickly. */
2540 if (!on && s->phys_cursor_x < 0)
2541 return;
2542
2543 /* If cursor is currently being shown and we don't want it to be
2544 or it is in the wrong place,
2545 or we want a hollow box and it's not so, (pout!)
2546 erase it. */
2547 if (s->phys_cursor_x >= 0
2548 && (!on
2549 || s->phys_cursor_x != s->cursor_x
2550 || s->phys_cursor_y != s->cursor_y
2551 || (s->display.x->text_cursor_kind != hollow_box_cursor
2552 && (s != x_highlight_screen))))
2553 {
2554 /* Erase the cursor by redrawing the character underneath it. */
2555 x_draw_single_glyph (s, s->phys_cursor_y, s->phys_cursor_x,
2556 s->phys_cursor_glyph,
2557 current_glyphs->highlight[s->phys_cursor_y]);
2558 s->phys_cursor_x = -1;
2559 }
2560
2561 /* If we want to show a cursor,
2562 or we want a box cursor and it's not so,
2563 write it in the right place. */
2564 if (on
2565 && (s->phys_cursor_x < 0
2566 || (s->display.x->text_cursor_kind != filled_box_cursor
2567 && s == x_highlight_screen)))
2568 {
2569 s->phys_cursor_glyph
2570 = ((current_glyphs->enable[s->cursor_y]
2571 && s->cursor_x < current_glyphs->used[s->cursor_y])
2572 ? current_glyphs->glyphs[s->cursor_y][s->cursor_x]
2573 : SPACEGLYPH);
2574 if (s != x_highlight_screen)
2575 {
2576 x_draw_box (s);
2577 s->display.x->text_cursor_kind = hollow_box_cursor;
2578 }
2579 else
2580 {
2581 x_draw_single_glyph (s, s->cursor_y, s->cursor_x,
2582 s->phys_cursor_glyph, 2);
2583 s->display.x->text_cursor_kind = filled_box_cursor;
2584 }
2585
2586 s->phys_cursor_x = s->cursor_x;
2587 s->phys_cursor_y = s->cursor_y;
2588 }
2589
2590 if (updating_screen != s)
2591 XFlushQueue ();
2592 }
2593
2594 extern Lisp_Object Vbar_cursor;
2595
2596 x_display_cursor (s, on)
2597 struct screen *s;
2598 int on;
2599 {
2600 if (EQ (Vbar_cursor, Qnil))
2601 x_display_box_cursor (s, on);
2602 else
2603 x_display_bar_cursor (s, on);
2604 }
2605 \f
2606 /* Icons. */
2607
2608 /* Refresh bitmap kitchen sink icon for screen S
2609 when we get an expose event for it. */
2610
2611 refreshicon (s)
2612 struct screen *s;
2613 {
2614 #ifdef HAVE_X11
2615 /* Normally, the window manager handles this function. */
2616 #else
2617 int mask;
2618
2619 if (s->display.x->icon_bitmap_flag)
2620 XBitmapBitsPut (s->display.x->icon_desc, 0, 0, sink_width, sink_height,
2621 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
2622 icon_bitmap, GXcopy, AllPlanes);
2623 else
2624 {
2625 extern struct screen *selected_screen;
2626 struct Lisp_String *str;
2627 unsigned char *string;
2628
2629 string
2630 = XSTRING (XBUFFER (XWINDOW (s->selected_window)->buffer)->name)->data;
2631
2632 if (s->display.x->icon_label != string)
2633 {
2634 s->display.x->icon_label = string;
2635 XChangeWindow (s->display.x->icon_desc,
2636 XQueryWidth (string, icon_font_info->id) + 10,
2637 icon_font_info->height + 10);
2638 }
2639
2640 XText (s->display.x->icon_desc, 5, 5, string,
2641 str->size, icon_font_info->id,
2642 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
2643 }
2644 XFlushQueue ();
2645 #endif /* HAVE_X11 */
2646 }
2647
2648 /* Make the x-window of screen S use the kitchen-sink icon
2649 that's a window generated by Emacs. */
2650
2651 int
2652 x_bitmap_icon (s)
2653 struct screen *s;
2654 {
2655 int mask;
2656 Window icon_window;
2657
2658 if (s->display.x->window_desc == 0)
2659 return 1;
2660
2661 #ifdef HAVE_X11
2662 if (icon_bitmap)
2663 XFreePixmap (x_current_display, icon_bitmap);
2664
2665 icon_bitmap =
2666 XCreateBitmapFromData (x_current_display, s->display.x->window_desc,
2667 gnu_bits, gnu_width, gnu_height);
2668 x_wm_set_icon_pixmap (s, icon_bitmap);
2669 s->display.x->icon_bitmap_flag = 1;
2670 #else
2671 if (s->display.x->icon_desc)
2672 {
2673 XClearIconWindow (s->display.x->window_desc);
2674 XDestroyWindow (s->display.x->icon_desc);
2675 }
2676
2677 icon_window = XCreateWindow (s->display.x->parent_desc,
2678 0, 0, sink_width, sink_height,
2679 2, WhitePixmap, (Pixmap) NULL);
2680
2681 if (icon_window == 0)
2682 return 1;
2683
2684 XSetIconWindow (s->display.x->window_desc, icon_window);
2685 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
2686
2687 s->display.x->icon_desc = icon_window;
2688 s->display.x->icon_bitmap_flag = 1;
2689
2690 if (icon_bitmap == 0)
2691 icon_bitmap
2692 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
2693 #endif /* HAVE_X11 */
2694
2695 return 0;
2696 }
2697
2698
2699 /* Make the x-window of screen S use a rectangle with text. */
2700
2701 int
2702 x_text_icon (s, icon_name)
2703 struct screen *s;
2704 char *icon_name;
2705 {
2706 #ifndef HAVE_X11
2707 int mask;
2708 int width;
2709 Window icon_window;
2710 char *X_DefaultValue;
2711 Bitmap b1;
2712
2713 #ifndef WhitePixel
2714 #define WhitePixel 1
2715 #endif
2716
2717 #ifndef BlackPixel
2718 #define BlackPixel 0
2719 #endif
2720 #endif /* not HAVE_X11 */
2721
2722 if (s->display.x->window_desc == 0)
2723 return 1;
2724
2725 if (icon_font_info == 0)
2726 icon_font_info
2727 = XGetFont (XGetDefault (XDISPLAY
2728 (char *) XSTRING (invocation_name)->data,
2729 "BodyFont"));
2730
2731 #ifdef HAVE_X11
2732 if (icon_name)
2733 s->display.x->icon_label = icon_name;
2734 else
2735 if (! s->display.x->icon_label)
2736 s->display.x->icon_label = " *emacs* ";
2737
2738 XSetIconName (x_current_display, s->display.x->window_desc,
2739 (char *) s->display.x->icon_label);
2740
2741 s->display.x->icon_bitmap_flag = 0;
2742 #else
2743 if (s->display.x->icon_desc)
2744 {
2745 XClearIconWindow (XDISPLAY s->display.x->window_desc);
2746 XDestroyWindow (XDISPLAY s->display.x->icon_desc);
2747 }
2748
2749 if (icon_name)
2750 s->display.x->icon_label = (unsigned char *) icon_name;
2751 else
2752 if (! s->display.x->icon_label)
2753 s->display.x->icon_label = XSTRING (s->name)->data;
2754
2755 width = XStringWidth (s->display.x->icon_label, icon_font_info, 0, 0);
2756 icon_window = XCreateWindow (s->display.x->parent_desc,
2757 s->display.x->left_pos,
2758 s->display.x->top_pos,
2759 width + 10, icon_font_info->height + 10,
2760 2, BlackPixmap, WhitePixmap);
2761
2762 if (icon_window == 0)
2763 return 1;
2764
2765 XSetIconWindow (s->display.x->window_desc, icon_window);
2766 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
2767
2768 s->display.x->icon_desc = icon_window;
2769 s->display.x->icon_bitmap_flag = 0;
2770 s->display.x->icon_label = 0;
2771 #endif /* HAVE_X11 */
2772
2773 return 0;
2774 }
2775 \f
2776 static char *x_proto_requests[] =
2777 {
2778 "CreateWindow",
2779 "ChangeWindowAttributes",
2780 "GetWindowAttributes",
2781 "DestroyWindow",
2782 "DestroySubwindows",
2783 "ChangeSaveSet",
2784 "ReparentWindow",
2785 "MapWindow",
2786 "MapSubwindows",
2787 "UnmapWindow",
2788 "UnmapSubwindows",
2789 "ConfigureWindow",
2790 "CirculateWindow",
2791 "GetGeometry",
2792 "QueryTree",
2793 "InternAtom",
2794 "GetAtomName",
2795 "ChangeProperty",
2796 "DeleteProperty",
2797 "GetProperty",
2798 "ListProperties",
2799 "SetSelectionOwner",
2800 "GetSelectionOwner",
2801 "ConvertSelection",
2802 "SendEvent",
2803 "GrabPointer",
2804 "UngrabPointer",
2805 "GrabButton",
2806 "UngrabButton",
2807 "ChangeActivePointerGrab",
2808 "GrabKeyboard",
2809 "UngrabKeyboard",
2810 "GrabKey",
2811 "UngrabKey",
2812 "AllowEvents",
2813 "GrabServer",
2814 "UngrabServer",
2815 "QueryPointer",
2816 "GetMotionEvents",
2817 "TranslateCoords",
2818 "WarpPointer",
2819 "SetInputFocus",
2820 "GetInputFocus",
2821 "QueryKeymap",
2822 "OpenFont",
2823 "CloseFont",
2824 "QueryFont",
2825 "QueryTextExtents",
2826 "ListFonts",
2827 "ListFontsWithInfo",
2828 "SetFontPath",
2829 "GetFontPath",
2830 "CreatePixmap",
2831 "FreePixmap",
2832 "CreateGC",
2833 "ChangeGC",
2834 "CopyGC",
2835 "SetDashes",
2836 "SetClipRectangles",
2837 "FreeGC",
2838 "ClearArea",
2839 "CopyArea",
2840 "CopyPlane",
2841 "PolyPoint",
2842 "PolyLine",
2843 "PolySegment",
2844 "PolyRectangle",
2845 "PolyArc",
2846 "FillPoly",
2847 "PolyFillRectangle",
2848 "PolyFillArc",
2849 "PutImage",
2850 "GetImage",
2851 "PolyText",
2852 "PolyText",
2853 "ImageText",
2854 "ImageText",
2855 "CreateColormap",
2856 "FreeColormap",
2857 "CopyColormapAndFree",
2858 "InstallColormap",
2859 "UninstallColormap",
2860 "ListInstalledColormaps",
2861 "AllocColor",
2862 "AllocNamedColor",
2863 "AllocColorCells",
2864 "AllocColorPlanes",
2865 "FreeColors",
2866 "StoreColors",
2867 "StoreNamedColor",
2868 "QueryColors",
2869 "LookupColor",
2870 "CreateCursor",
2871 "CreateGlyphCursor",
2872 "FreeCursor",
2873 "RecolorCursor",
2874 "QueryBestSize",
2875 "QueryExtension",
2876 "ListExtensions",
2877 "ChangeKeyboardMapping",
2878 "GetKeyboardMapping",
2879 "ChangeKeyboardControl",
2880 "GetKeyboardControl",
2881 "Bell",
2882 "ChangePointerControl",
2883 "GetPointerControl",
2884 "SetScreenSaver",
2885 "GetScreenSaver",
2886 "ChangeHosts",
2887 "ListHosts",
2888 "SetAccessControl",
2889 "SetCloseDownMode",
2890 "KillClient",
2891 "RotateProperties",
2892 "ForceScreenSaver",
2893 "SetPointerMapping",
2894 "GetPointerMapping",
2895 "SetModifierMapping",
2896 "GetModifierMapping",
2897 "NoOperation"
2898 };
2899
2900 #define acceptable_x_error_p(type) ((type) == 94)
2901
2902 x_handle_error_gracefully (event)
2903 XErrorEvent *event;
2904 {
2905 char error_ptr[128];
2906 char *proto_ptr = x_proto_requests[event->request_code];
2907 char str[128];
2908
2909 XGetErrorText (x_current_display, event->error_code, error_ptr, 128);
2910 sprintf (str, "X Protocol Error: %s on request: %s", error_ptr, proto_ptr);
2911 TOTALLY_UNBLOCK_INPUT;
2912 error (str);
2913 }
2914
2915 #if 0
2916 extern int x_selection_alloc_error;
2917 extern int x_converting_selection;
2918 #endif
2919
2920 /* Handle X Errors. If the error is not traumatic,
2921 just call error (). Otherwise print a (hopefully) interesting
2922 message and quit.
2923
2924 The arg to Fkill_emacs is an exit status value
2925 and also prevents any questions. */
2926
2927 x_error_handler (disp, event)
2928 Display *disp;
2929 #ifdef HAVE_X11
2930 XErrorEvent *event;
2931
2932 #define XlibDisplayIOError (1L << 0)
2933
2934 #else
2935 struct _XErrorEvent *event;
2936 #endif
2937 {
2938 /* Here we use the standard X handlers. */
2939
2940 BLOCK_INPUT;
2941 if (event && event->type == 0) /* 0 is the XError Event type. */
2942 {
2943 #if 0
2944 #ifdef HAVE_X11
2945 if (event->request_code == BadAlloc && x_converting_selection)
2946 x_selection_alloc_error = 1;
2947 else
2948 #endif
2949 #endif
2950 if (acceptable_x_error_p (event->request_code))
2951 x_handle_error_gracefully (event);
2952 else
2953 _XDefaultError (disp, event);
2954 }
2955 else
2956 {
2957 disp->flags |= XlibDisplayIOError;
2958 _XDefaultIOError (disp);
2959 }
2960 UNBLOCK_INPUT;
2961
2962 if (_Xdebug)
2963 abort ();
2964 else
2965 Fkill_emacs (make_number (70));
2966 }
2967
2968 /* Initialize communication with the X window server. */
2969
2970 #if 0
2971 static unsigned int x_wire_count;
2972 x_trace_wire ()
2973 {
2974 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
2975 }
2976 #endif
2977
2978 \f
2979 /* Set the font of the x-window specified by screen S
2980 to the font named NEWNAME. This is safe to use
2981 even before S has an actual x-window. */
2982
2983 #ifdef HAVE_X11
2984
2985 /* A table of all the fonts we have already loaded. */
2986 static XFontStruct **x_font_table;
2987
2988 /* The current capacity of x_font_table. */
2989 static int x_font_table_size;
2990
2991 /* The number of fonts actually stored in x_font_table.
2992 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
2993 0 <= n_fonts <= x_font_table_size. */
2994 static int n_fonts;
2995
2996 x_new_font (s, fontname)
2997 struct screen *s;
2998 register char *fontname;
2999 {
3000 XFontStruct *temp;
3001 int already_loaded;
3002 int n_matching_fonts;
3003 XFontStruct *font_info;
3004 char **font_names;
3005
3006 /* Get a list of all the fonts that match this name. Once we
3007 have a list of matching fonts, we compare them against the fonts
3008 we already have by comparing font ids. */
3009 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3010 1024, &n_matching_fonts,
3011 &font_info);
3012 /* If the server couldn't find any fonts whose named matched fontname,
3013 return an error code. */
3014 if (n_matching_fonts == 0)
3015 return 1;
3016
3017 /* See if we've already loaded a matching font. */
3018 {
3019 int i, j;
3020
3021 already_loaded = 0;
3022 for (i = 0; i < n_fonts; i++)
3023 for (j = 0; j < n_matching_fonts; j++)
3024 if (x_font_table[i]->fid == font_info[j].fid)
3025 {
3026 already_loaded = i;
3027 goto found_font;
3028 }
3029 }
3030 found_font:
3031
3032 /* If we have, just return it from the table. */
3033 if (already_loaded)
3034 s->display.x->font = x_font_table[already_loaded];
3035
3036 /* Otherwise, load the font and add it to the table. */
3037 else
3038 {
3039 XFontStruct *font;
3040
3041 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3042 if (! font)
3043 return 1;
3044
3045 /* Do we need to create the table? */
3046 if (x_font_table_size == 0)
3047 {
3048 x_font_table_size = 16;
3049 x_font_table
3050 = (XFontStruct **) xmalloc (x_font_table_size
3051 * sizeof (x_font_table[0]));
3052 }
3053 /* Do we need to grow the table? */
3054 else if (n_fonts >= x_font_table_size)
3055 {
3056 x_font_table_size *= 2;
3057 x_font_table
3058 = (XFontStruct **) xrealloc (x_font_table,
3059 (x_font_table_size
3060 * sizeof (x_font_table[0])));
3061 }
3062
3063 s->display.x->font = x_font_table[n_fonts++] = font;
3064 }
3065
3066 /* Free the information from XListFontsWithInfo. The data
3067 we actually retain comes from XLoadQueryFont. */
3068 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3069
3070 /* Now make the screen display the given font. */
3071 if (s->display.x->window_desc != 0)
3072 {
3073 XSetFont (x_current_display, s->display.x->normal_gc,
3074 s->display.x->font->fid);
3075 XSetFont (x_current_display, s->display.x->reverse_gc,
3076 s->display.x->font->fid);
3077 XSetFont (x_current_display, s->display.x->cursor_gc,
3078 s->display.x->font->fid);
3079
3080 x_set_window_size (s, s->width, s->height);
3081 }
3082
3083 return 0;
3084 }
3085 #else
3086 x_new_font (s, newname)
3087 struct screen *s;
3088 register char *newname;
3089 {
3090 FONT_TYPE *temp;
3091 int mask;
3092
3093 temp = XGetFont (newname);
3094 if (temp == (FONT_TYPE *) 0)
3095 return 1;
3096
3097 if (s->display.x->font)
3098 XLoseFont (s->display.x->font);
3099
3100 s->display.x->font = temp;
3101
3102 if (s->display.x->window_desc != 0)
3103 x_set_window_size (s, s->width, s->height);
3104
3105 return 0;
3106 }
3107 #endif
3108 \f
3109 x_calc_absolute_position (s)
3110 struct screen *s;
3111 {
3112 #ifdef HAVE_X11
3113 if (s->display.x->left_pos < 0)
3114 s->display.x->left_pos
3115 = XINT (x_screen_width) - PIXEL_WIDTH (s) + s->display.x->left_pos;
3116
3117 if (s->display.x->top_pos < 0)
3118 s->display.x->top_pos
3119 = XINT (x_screen_height) - PIXEL_HEIGHT (s) + s->display.x->top_pos;
3120 #else /* X10 */
3121 WINDOWINFO_TYPE parentinfo;
3122
3123 XGetWindowInfo (s->display.x->window_desc, &parentinfo);
3124
3125 if (s->display.x->left_pos < 0)
3126 s->display.x->left_pos = parentinfo.width + (s->display.x->left_pos + 1)
3127 - PIXEL_WIDTH (s) - 2 * s->display.x->internal_border_width;
3128
3129 if (s->display.x->top_pos < 0)
3130 s->display.x->top_pos = parentinfo.height + (s->display.x->top_pos + 1)
3131 - PIXEL_HEIGHT (s) - 2 * s->display.x->internal_border_width;
3132 #endif /* X10 */
3133 }
3134
3135 x_set_offset (s, xoff, yoff)
3136 struct screen *s;
3137 register int xoff, yoff;
3138 {
3139 s->display.x->top_pos = yoff;
3140 s->display.x->left_pos = xoff;
3141 x_calc_absolute_position (s);
3142
3143 BLOCK_INPUT;
3144 XMoveWindow (XDISPLAY s->display.x->window_desc,
3145 s->display.x->left_pos, s->display.x->top_pos);
3146 #ifdef HAVE_X11
3147 x_wm_set_size_hint (s, 0);
3148 #endif
3149 UNBLOCK_INPUT;
3150 }
3151
3152 /* Call this to change the size of screen S's x-window. */
3153
3154 x_set_window_size (s, cols, rows)
3155 struct screen *s;
3156 register int cols, rows;
3157 {
3158 int pixelwidth, pixelheight;
3159 int mask;
3160 int ibw = s->display.x->internal_border_width;
3161
3162 BLOCK_INPUT;
3163
3164 /* ??? Who DOES worry about minimum reasonable sizes? */
3165 pixelwidth = (cols * FONT_WIDTH (s->display.x->font) + 2 * ibw
3166 + s->display.x->v_scrollbar_width);
3167 pixelheight = (rows * FONT_HEIGHT (s->display.x->font) + 2 * ibw
3168 + s->display.x->h_scrollbar_height);
3169
3170 #ifdef HAVE_X11
3171 x_wm_set_size_hint (s, 0);
3172 #endif /* HAVE_X11 */
3173 XChangeWindowSize (s->display.x->window_desc, pixelwidth, pixelheight);
3174 XFlushQueue ();
3175 UNBLOCK_INPUT;
3176 }
3177
3178 #ifndef HAVE_X11
3179 x_set_resize_hint (s)
3180 struct screen *s;
3181 {
3182
3183 XSetResizeHint (s->display.x->window_desc, 2 * s->display.x->internal_border_width,
3184 2 * s->display.x->internal_border_width,
3185 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font));
3186 }
3187 #endif /* not HAVE_X11 */
3188 \f
3189
3190 x_set_mouse_position (s, x, y)
3191 struct screen *s;
3192 int x, y;
3193 {
3194 int pix_x, pix_y;
3195
3196 x_raise_screen (s);
3197
3198 if (x < 0)
3199 pix_x = (SCREEN_WIDTH (s)
3200 * FONT_WIDTH (s->display.x->font)
3201 + 2 * s->display.x->internal_border_width
3202 + s->display.x->v_scrollbar_width) / 2;
3203 else
3204 pix_x = x * FONT_WIDTH (s->display.x->font) + 2; /* add 2 pixels to each
3205 dimension to move the
3206 mouse into the char
3207 cell */
3208
3209 if (y < 0)
3210 pix_y = (SCREEN_HEIGHT (s)
3211 * FONT_HEIGHT (s->display.x->font)
3212 + 2 * s->display.x->internal_border_width
3213 + s->display.x->h_scrollbar_height) / 2;
3214 else
3215 pix_y = y * FONT_HEIGHT (s->display.x->font) + 2;
3216
3217 BLOCK_INPUT;
3218 x_mouse_x = x;
3219 x_mouse_y = y;
3220
3221 XWarpMousePointer (s->display.x->window_desc, pix_x, pix_y);
3222 UNBLOCK_INPUT;
3223 }
3224
3225 #ifdef HAVE_X11
3226 x_focus_on_screen (s)
3227 struct screen *s;
3228 {
3229 x_raise_screen (s);
3230 #if 0
3231 /* I don't think that the ICCCM allows programs to do things like this
3232 without the interaction of the window manager. Whatever you end up
3233 doing with this code, do it to x_unfocus_screen too. */
3234 XSetInputFocus (x_current_display, s->display.x->window_desc,
3235 RevertToPointerRoot, CurrentTime);
3236 #endif
3237 }
3238
3239 x_unfocus_screen (s)
3240 struct screen *s;
3241 {
3242 #if 0
3243 /* Look at the remarks in x_focus_on_screen. */
3244 if (x_focus_screen == s)
3245 XSetInputFocus (x_current_display, PointerRoot,
3246 RevertToPointerRoot, CurrentTime);
3247 #endif
3248 }
3249
3250 #endif
3251
3252 /* Raise screen S. */
3253
3254 x_raise_screen (s)
3255 struct screen *s;
3256 {
3257 if (s->visible)
3258 {
3259 BLOCK_INPUT;
3260 XRaiseWindow (XDISPLAY s->display.x->window_desc);
3261 XFlushQueue ();
3262 UNBLOCK_INPUT;
3263 }
3264 }
3265
3266 /* Lower screen S. */
3267
3268 x_lower_screen (s)
3269 struct screen *s;
3270 {
3271 if (s->visible)
3272 {
3273 BLOCK_INPUT;
3274 XLowerWindow (XDISPLAY s->display.x->window_desc);
3275 XFlushQueue ();
3276 UNBLOCK_INPUT;
3277 }
3278 }
3279
3280 /* Change from withdrawn state to mapped state. */
3281
3282 x_make_screen_visible (s)
3283 struct screen *s;
3284 {
3285 int mask;
3286
3287 BLOCK_INPUT;
3288
3289 if (! SCREEN_VISIBLE_P (s))
3290 {
3291 #ifdef HAVE_X11
3292 if (! EQ (Vx_no_window_manager, Qt))
3293 x_wm_set_window_state (s, NormalState);
3294
3295 XMapWindow (XDISPLAY s->display.x->window_desc);
3296 if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
3297 XMapSubwindows (x_current_display, s->display.x->window_desc);
3298 #else
3299 XMapWindow (XDISPLAY s->display.x->window_desc);
3300 if (s->display.x->icon_desc != 0)
3301 XUnmapWindow (s->display.x->icon_desc);
3302
3303 /* Handled by the MapNotify event for X11 */
3304 s->visible = 1;
3305 s->iconified = 0;
3306
3307 /* NOTE: this may cause problems for the first screen. */
3308 XTcursor_to (0, 0);
3309 #endif /* not HAVE_X11 */
3310 }
3311
3312 XFlushQueue ();
3313
3314 UNBLOCK_INPUT;
3315 }
3316
3317 /* Change from mapped state to withdrawn state. */
3318
3319 x_make_screen_invisible (s)
3320 struct screen *s;
3321 {
3322 int mask;
3323
3324 if (! s->visible)
3325 return;
3326
3327 BLOCK_INPUT;
3328 #ifdef HAVE_X11
3329 #if 0
3330 if (! EQ (Vx_no_window_manager, Qt))
3331 {
3332 XUnmapEvent unmap;
3333
3334 unmap.type = UnmapNotify;
3335 unmap.window = s->display.x->window_desc;
3336 unmap.event = DefaultRootWindow (x_current_display);
3337 unmap.from_configure = False;
3338 XSendEvent (x_current_display, DefaultRootWindow (x_current_display),
3339 False, SubstructureRedirectMask|SubstructureNotifyMask,
3340 &unmap);
3341 }
3342
3343 /* The new function below does the same as the above code, plus unmapping
3344 the window. Sending the event without actually unmapping can make
3345 the window manager start ignoring the window (i.e., no more title bar,
3346 icon manager stuff.) */
3347 #endif
3348
3349 /* New function available with R4 */
3350 if (! XWithdrawWindow (x_current_display, s->display.x->window_desc,
3351 DefaultScreen (x_current_display)))
3352 {
3353 UNBLOCK_INPUT_RESIGNAL;
3354 error ("Can't notify window manager of iconification.");
3355 }
3356
3357 #else
3358 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3359
3360 s->visible = 0; /* Handled by the UnMap event for X11 */
3361 if (s->display.x->icon_desc != 0)
3362 XUnmapWindow (XDISPLAY s->display.x->icon_desc);
3363 #endif /* not HAVE_X11 */
3364
3365 XFlushQueue ();
3366 UNBLOCK_INPUT;
3367 }
3368
3369 /* Window manager communication. Created in Fx_open_connection. */
3370 extern Atom Xatom_wm_change_state;
3371
3372 /* Change window state from mapped to iconified. */
3373
3374 x_iconify_screen (s)
3375 struct screen *s;
3376 {
3377 int mask;
3378
3379 if (s->iconified)
3380 return;
3381
3382 BLOCK_INPUT;
3383
3384 #ifdef HAVE_X11
3385 if (! EQ (Vx_no_window_manager, Qt))
3386 if (! XIconifyWindow (x_current_display, s->display.x->window_desc,
3387 DefaultScreen (x_current_display)))
3388 {
3389 UNBLOCK_INPUT_RESIGNAL;
3390 error ("Can't notify window manager of iconification.");
3391 }
3392
3393 s->iconified = 1;
3394
3395 #if 0
3396 {
3397 XClientMessageEvent message;
3398
3399 message.window = s->display.x->window_desc;
3400 message.type = ClientMessage;
3401 message.message_type = Xatom_wm_change_state;
3402 message.format = 32;
3403 message.data.l[0] = IconicState;
3404
3405 if (! XSendEvent (x_current_display,
3406 DefaultRootWindow (x_current_display),
3407 False,
3408 SubstructureRedirectMask | SubstructureNotifyMask,
3409 &message))
3410 {
3411 UNBLOCK_INPUT_RESIGNAL;
3412 error ("Can't notify window manager of iconification.");
3413 }
3414 }
3415 #endif
3416 #else /* X10 */
3417 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3418
3419 s->visible = 0; /* Handled in the UnMap event for X11. */
3420 if (s->display.x->icon_desc != 0)
3421 {
3422 XMapWindow (XDISPLAY s->display.x->icon_desc);
3423 refreshicon (s);
3424 }
3425 #endif /* X10 */
3426
3427 XFlushQueue ();
3428 UNBLOCK_INPUT;
3429 }
3430
3431 /* Destroy the X window of screen S.
3432 DISPL is the former s->display (since s->display
3433 has already been nulled out). */
3434
3435 x_destroy_window (s, displ)
3436 struct screen *s;
3437 union display displ;
3438 {
3439 int mask;
3440
3441 BLOCK_INPUT;
3442 if (displ.x->icon_desc != 0)
3443 XDestroyWindow (XDISPLAY displ.x->icon_desc);
3444 XDestroyWindow (XDISPLAY displ.x->window_desc);
3445 XFlushQueue ();
3446 UNBLOCK_INPUT;
3447
3448 free (displ.x);
3449 if (s == x_focus_screen)
3450 x_focus_screen = 0;
3451 if (s == x_highlight_screen)
3452 x_highlight_screen = 0;
3453 }
3454 \f
3455 #ifndef HAVE_X11
3456
3457 /* Manage event queues.
3458
3459 This code is only used by the X10 support.
3460
3461 We cannot leave events in the X queue and get them when we are ready
3462 because X does not provide a subroutine to get only a certain kind
3463 of event but not block if there are no queued events of that kind.
3464
3465 Therefore, we must examine events as they come in and copy events
3466 of certain kinds into our private queues.
3467
3468 All ExposeRegion events are put in x_expose_queue.
3469 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
3470
3471
3472 /* Write the event *P_XREP into the event queue *QUEUE.
3473 If the queue is full, do nothing, but return nonzero. */
3474
3475 int
3476 enqueue_event (p_xrep, queue)
3477 register XEvent *p_xrep;
3478 register struct event_queue *queue;
3479 {
3480 int newindex = queue->windex + 1;
3481 if (newindex == EVENT_BUFFER_SIZE)
3482 newindex = 0;
3483 if (newindex == queue->rindex)
3484 return -1;
3485 queue->xrep[queue->windex] = *p_xrep;
3486 queue->windex = newindex;
3487 return 0;
3488 }
3489
3490 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
3491 If *QUEUE is empty, do nothing and return 0. */
3492
3493 int
3494 dequeue_event (p_xrep, queue)
3495 register XEvent *p_xrep;
3496 register struct event_queue *queue;
3497 {
3498 if (queue->windex == queue->rindex)
3499 return 0;
3500 *p_xrep = queue->xrep[queue->rindex++];
3501 if (queue->rindex == EVENT_BUFFER_SIZE)
3502 queue->rindex = 0;
3503 return 1;
3504 }
3505
3506 /* Return the number of events buffered in *QUEUE. */
3507
3508 int
3509 queue_event_count (queue)
3510 register struct event_queue *queue;
3511 {
3512 int tem = queue->windex - queue->rindex;
3513 if (tem >= 0)
3514 return tem;
3515 return EVENT_BUFFER_SIZE + tem;
3516 }
3517
3518 /* Return nonzero if mouse input is pending. */
3519
3520 int
3521 mouse_event_pending_p ()
3522 {
3523 return queue_event_count (&x_mouse_queue);
3524 }
3525 #endif
3526 \f
3527 #ifdef HAVE_X11
3528
3529 x_wm_set_size_hint (s, prompting)
3530 struct screen *s;
3531 long prompting;
3532 {
3533 XSizeHints size_hints;
3534 Window window = s->display.x->window_desc;
3535
3536 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
3537
3538 flexlines = s->height;
3539
3540 size_hints.x = s->display.x->left_pos;
3541 size_hints.y = s->display.x->top_pos;
3542 size_hints.height = PIXEL_HEIGHT (s);
3543 size_hints.width = PIXEL_WIDTH (s);
3544 size_hints.width_inc = FONT_WIDTH (s->display.x->font);
3545 size_hints.height_inc = FONT_HEIGHT (s->display.x->font);
3546 size_hints.base_width = (2 * s->display.x->internal_border_width)
3547 + s->display.x->v_scrollbar_width;
3548 size_hints.base_height = (2 * s->display.x->internal_border_width)
3549 + s->display.x->h_scrollbar_height;
3550 size_hints.min_width = size_hints.base_width + size_hints.width_inc;
3551 size_hints.min_height = size_hints.base_height + size_hints.height_inc;
3552 size_hints.max_width = x_screen_width
3553 - ((2 * s->display.x->internal_border_width)
3554 + s->display.x->v_scrollbar_width);
3555 size_hints.max_height = x_screen_height
3556 - ((2 * s->display.x->internal_border_width)
3557 + s->display.x->h_scrollbar_height);
3558
3559 if (prompting)
3560 size_hints.flags |= prompting;
3561 else
3562 {
3563 XSizeHints hints; /* Sometimes I hate X Windows... */
3564
3565 XGetNormalHints (x_current_display, window, &hints);
3566 if (hints.flags & PSize)
3567 size_hints.flags |= PSize;
3568 if (hints.flags & PPosition)
3569 size_hints.flags |= PPosition;
3570 if (hints.flags & USPosition)
3571 size_hints.flags |= USPosition;
3572 if (hints.flags & USSize)
3573 size_hints.flags |= USSize;
3574 }
3575
3576 #if 0 /* R3 */
3577 XSetNormalHints (x_current_display, window, &size_hints);
3578 #endif
3579 XSetWMNormalHints (x_current_display, window, &size_hints);
3580 }
3581
3582 /* Used for IconicState or NormalState */
3583 x_wm_set_window_state (s, state)
3584 struct screen *s;
3585 int state;
3586 {
3587 XWMHints wm_hints;
3588 Window window = s->display.x->window_desc;
3589
3590 wm_hints.flags = StateHint;
3591 wm_hints.initial_state = state;
3592 XSetWMHints (x_current_display, window, &wm_hints);
3593 }
3594
3595 x_wm_set_icon_pixmap (s, icon_pixmap)
3596 struct screen *s;
3597 Pixmap icon_pixmap;
3598 {
3599 XWMHints wm_hints;
3600 Window window = s->display.x->window_desc;
3601
3602 wm_hints.flags = IconPixmapHint;
3603 wm_hints.icon_pixmap = icon_pixmap;
3604 XSetWMHints (x_current_display, window, &wm_hints);
3605 }
3606
3607 x_wm_set_icon_position (s, icon_x, icon_y)
3608 struct screen *s;
3609 int icon_x, icon_y;
3610 {
3611 XWMHints wm_hints;
3612 Window window = s->display.x->window_desc;
3613
3614 wm_hints.flags = IconPositionHint;
3615 wm_hints.icon_x = icon_x;
3616 wm_hints.icon_y = icon_y;
3617 XSetWMHints (x_current_display, window, &wm_hints);
3618 }
3619
3620 \f
3621 void
3622 x_term_init (display_name)
3623 char *display_name;
3624 {
3625 Lisp_Object screen;
3626 char *defaultvalue;
3627 #ifdef F_SETOWN
3628 extern int old_fcntl_owner;
3629 #endif
3630
3631 x_focus_screen = x_highlight_screen = 0;
3632
3633 x_current_display = XOpenDisplay (display_name);
3634 if (x_current_display == 0)
3635 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
3636 display_name);
3637
3638 #ifdef HAVE_X11
3639 {
3640 int hostname_size = MAXHOSTNAMELEN + 1;
3641
3642 hostname = (char *) xmalloc (hostname_size);
3643
3644 #if 0
3645 XSetAfterFunction (x_current_display, x_trace_wire);
3646 #endif
3647
3648 invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
3649
3650 /* Try to get the host name; if the buffer is too short, try
3651 again. Apparently, the only indication gethostname gives of
3652 whether the buffer was large enough is the presence or absence
3653 of a '\0' in the string. Eech. */
3654 for (;;)
3655 {
3656 gethostname (hostname, hostname_size - 1);
3657 hostname[hostname_size - 1] = '\0';
3658
3659 /* Was the buffer large enough for gethostname to store the '\0'? */
3660 if (strlen (hostname) < hostname_size - 1)
3661 break;
3662
3663 hostname_size <<= 1;
3664 hostname = (char *) xrealloc (hostname, hostname_size);
3665 }
3666 x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
3667 + strlen (hostname)
3668 + 2);
3669 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
3670 }
3671
3672 dup2 (ConnectionNumber (x_current_display), 0);
3673
3674 #ifndef SYSV_STREAMS
3675 /* Streams somehow keeps track of which descriptor number
3676 is being used to talk to X. So it is not safe to substitute
3677 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
3678 close (ConnectionNumber (x_current_display));
3679 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
3680 * check the def of the macro;
3681 * it is a genuine lvalue */
3682 #endif /* not SYSV_STREAMS */
3683
3684 #endif /* HAVE_X11 */
3685
3686 #ifdef F_SETOWN
3687 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
3688 #ifdef F_SETOWN_SOCK_NEG
3689 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
3690 #else
3691 fcntl (0, F_SETOWN, getpid ());
3692 #endif /* F_SETOWN_SOCK_NEG */
3693 #endif /* F_SETOWN */
3694
3695 #ifdef SIGIO
3696 init_sigio ();
3697 #endif
3698
3699 /* Must use interrupt input because we cannot otherwise
3700 arrange for C-g to be noticed immediately.
3701 We cannot connect it to SIGINT. */
3702 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3703
3704 expose_all_windows = 0;
3705
3706 clear_screen_hook = XTclear_screen;
3707 clear_end_of_line_hook = XTclear_end_of_line;
3708 ins_del_lines_hook = XTins_del_lines;
3709 change_line_highlight_hook = XTchange_line_highlight;
3710 insert_glyphs_hook = XTinsert_glyphs;
3711 write_glyphs_hook = XTwrite_glyphs;
3712 delete_glyphs_hook = XTdelete_glyphs;
3713 ring_bell_hook = XTring_bell;
3714 reset_terminal_modes_hook = XTreset_terminal_modes;
3715 set_terminal_modes_hook = XTset_terminal_modes;
3716 update_begin_hook = XTupdate_begin;
3717 update_end_hook = XTupdate_end;
3718 set_terminal_window_hook = XTset_terminal_window;
3719 read_socket_hook = XTread_socket;
3720 cursor_to_hook = XTcursor_to;
3721 reassert_line_highlight_hook = XTreassert_line_highlight;
3722 screen_rehighlight_hook = XTscreen_rehighlight;
3723 mouse_position_hook = XTmouse_position;
3724
3725 scroll_region_ok = 1; /* we'll scroll partial screens */
3726 char_ins_del_ok = 0; /* just as fast to write the line */
3727 line_ins_del_ok = 1; /* we'll just blt 'em */
3728 fast_clear_end_of_line = 1; /* X does this well */
3729 memory_below_screen = 0; /* we don't remember what scrolls
3730 off the bottom */
3731 baud_rate = 19200;
3732
3733 XHandleError (x_error_handler);
3734 XHandleIOError (x_error_handler);
3735
3736 /* Disable Window Change signals; they are handled by X events. */
3737 #ifdef SIGWINCH
3738 signal (SIGWINCH, SIG_DFL);
3739 #endif /* SIGWINCH */
3740
3741 signal (SIGPIPE, x_error_handler);
3742 }
3743
3744 void
3745 syms_of_xterm ()
3746 {
3747 staticpro (&invocation_name);
3748 invocation_name = Qnil;
3749 }
3750 #endif /* HAVE_X11 */
3751 #endif /* HAVE_X_WINDOWS */