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