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