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