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