comparison src/xterm.c @ 286:8a40ab4a424f

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