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