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