*** 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);
1113d9db 1468 result->timestamp = event->time;
dc6f92b8
JB
1469 result->modifiers = (x_convert_modifiers (event->state)
1470 | (event->type == ButtonRelease ? up_modifier : 0));
dc6f92b8
JB
1471
1472 /* Notice if the mouse is still grabbed. */
1473 if (event->type == ButtonPress)
1474 {
1475 if (! x_mouse_grabbed)
1476 Vmouse_depressed = Qt;
90e65f07 1477 x_mouse_grabbed |= (1 << event->button);
dc6f92b8
JB
1478 }
1479 else if (event->type == ButtonRelease)
1480 {
90e65f07 1481 x_mouse_grabbed &= ~(1 << event->button);
dc6f92b8
JB
1482 if (!x_mouse_grabbed)
1483 Vmouse_depressed = Qnil;
1484 }
1485
1486 if (part) /* Scrollbar event */
1487 {
1488 int pos, len;
1489
1490 pos = event->y - (s->display.x->v_scrollbar_width - 2);
1491 XSET (x_mouse_x, Lisp_Int, pos);
1492 len = ((FONT_HEIGHT (s->display.x->font) * s->height)
1493 + s->display.x->internal_border_width
1494 - (2 * (s->display.x->v_scrollbar_width - 2)));
1495 XSET (x_mouse_y, Lisp_Int, len);
1496
1497 result->kind = scrollbar_click;
1498 result->part = part;
1499 XSET (result->x, Lisp_Int, (s->display.x->top_pos - event->y));
1500 XSET (result->y, Lisp_Int, s->display.x->pixel_height);
1501 result->screen = s;
1502 }
1503 else /* Text Window Event */
1504 {
1505 int row, column;
1506
90e65f07 1507 pixel_to_glyph_coords (s, event->x, event->y, &column, &row, NULL);
dc6f92b8
JB
1508 result->kind = mouse_click;
1509 result->x = column;
1510 result->y = row;
1511 result->screen = s;
1512 }
1513}
1514
1515
90e65f07
JB
1516/* Mouse movement. Rah.
1517
1518 In order to avoid asking for motion events and then throwing most
1519 of them away or busy-polling the server for mouse positions, we ask
1520 the server for pointer motion hints. This means that we get only
1521 one event per group of mouse movements. "Groups" are delimited by
1522 other kinds of events (focus changes and button clicks, for
1523 example), or by XQueryPointer calls; when one of these happens, we
1524 get another MotionNotify event the next time the mouse moves. This
1525 is at least as efficient than getting motion events when mouse
1526 tracking is on, and I suspect only negligibly worse when tracking
1527 is off.
1528
1529 The silly O'Reilly & Associates Nutshell guides barely document
1530 pointer motion hints at all (I think you have to infer how they
1531 work from an example), and the description of XQueryPointer doesn't
1532 mention that calling it causes you to get another motion hint from
1533 the server, which is very important. */
1534
1535/* Where the mouse was last time we reported a mouse event. */
1536static SCREEN_PTR last_mouse_screen;
1537static XRectangle last_mouse_glyph;
1538
1539/* Function to report a mouse movement to the mainstream Emacs code.
1540 The input handler calls this.
1541
1542 We have received a mouse movement event, which is given in *event.
1543 If the mouse is over a different glyph than it was last time, tell
1544 the mainstream emacs code by setting mouse_moved. If not, ask for
1545 another motion event, so we can check again the next time it moves. */
1546static void
1547note_mouse_position (screen, event)
1548 SCREEN_PTR screen;
1549 XMotionEvent *event;
1550
1551{
1552 /* Has the mouse moved off the glyph it was on at the last sighting? */
1553 if (event->x < last_mouse_glyph.x
1554 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1555 || event->y < last_mouse_glyph.y
1556 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1557 mouse_moved = 1;
1558 else
1559 {
1560 /* It's on the same glyph. Call XQueryPointer so we'll get an
1561 event the next time the mouse moves and we can see if it's
1562 *still* on the same glyph. */
1563 int dummy;
1564
1565 XQueryPointer (event->display, event->window,
1566 (Window *) &dummy, (Window *) &dummy,
1567 &dummy, &dummy, &dummy, &dummy,
1568 (unsigned int *) &dummy);
1569 }
1570}
1571
1572/* Return the current position of the mouse.
1573
1574 This clears the mouse_moved flag, so we can wait for the next mouse
1575 position. This also calls XQueryPointer, which will cause the
1576 server to give us another MotionNotify when the mouse moves again.
1577 */
1578
1579static void
1580XTmouse_position (s, x, y, time)
1581 SCREEN_PTR *s;
1582 Lisp_Object *x, *y;
1583 Lisp_Object *time;
1584{
1585 int ix, iy, dummy;
1586 Display *d = x_current_display;
1587 Window guess, root, child;
1588
1589 BLOCK_INPUT;
1590
1591 /* I would like to have an X function that just told me the
1592 innermost window containing the mouse.
1593
1594 /* There doesn't seem to be any way to just get the innermost window
1595 containing the pointer, no matter what X screen it's on; you have
1596 to guess a window, and then X will tell you which one of that
1597 window's children it's in. If the pointer isn't in any of that
1598 window's children, it gives you a root window that contains it.
1599
1600 So we start with the selected screen's window and chase down
1601 branches under the guidance of XQueryPointer until we hit a leaf
1602 (all of the Emacs windows we care about are leaf windows). If at
1603 any time XQueryPointer returns false, that means that the current
1604 window does not contain the pointer any more (perhaps it moved),
1605 so we start with the root window XQueryPointer has given us and
1606 start again. */
1607
1608 guess = selected_screen->display.x->window_desc;
1609 for (;;)
1610 if (XQueryPointer (d, guess, &root, &child,
1611 &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
1612 {
1613 if (child == None)
1614 /* Guess is a leaf window, and it contains the pointer. */
1615 break;
1616 else
1617 guess = child;
1618 }
1619 else
1620 /* When XQueryPointer returns False, the pointer isn't in guess
1621 anymore, but root is the root window of the screen we should
1622 try instead. */
1623 guess = root;
1624
1625 *s = last_mouse_screen = x_window_to_screen (guess);
1626 if (! *s)
1627 *x = *y = Qnil;
1628 else
1629 {
1630 pixel_to_glyph_coords (*s, ix, iy, &ix, &iy, &last_mouse_glyph);
1631 XSET (*x, Lisp_Int, ix);
1632 XSET (*y, Lisp_Int, iy);
1633 }
1634
1635 mouse_moved = 0;
1636
1637 /* I don't know how to find the time for the last movement; it seems
1638 like XQueryPointer ought to return it, but it doesn't. */
1639 *time = Qnil;
1640
1641 UNBLOCK_INPUT;
1642}
1643
1644\f
dc6f92b8
JB
1645static char *events[] =
1646{
1647 "0: ERROR!",
1648 "1: REPLY",
1649 "KeyPress",
55123275
JB
1650 "KeyRelease",
1651 "ButtonPress",
1652 "ButtonRelease",
1653 "MotionNotify",
1654 "EnterNotify",
1655 "LeaveNotify",
1656 "FocusIn",
1657 "FocusOut",
1658 "KeymapNotify",
1659 "Expose",
1660 "GraphicsExpose",
1661 "NoExpose",
1662 "VisibilityNotify",
1663 "CreateNotify",
1664 "DestroyNotify",
1665 "UnmapNotify",
1666 "MapNotify",
1667 "MapRequest",
1668 "ReparentNotify",
1669 "ConfigureNotify",
1670 "ConfigureRequest",
1671 "GravityNotify",
1672 "ResizeRequest",
1673 "CirculateNotify",
1674 "CirculateRequest",
1675 "PropertyNotify",
1676 "SelectionClear",
1677 "SelectionRequest",
1678 "SelectionNotify",
1679 "ColormapNotify",
1680 "ClientMessage",
1681 "MappingNotify",
1682 "LASTEvent"
dc6f92b8
JB
1683};
1684#else /* X10 */
1685#define XEvent XKeyPressedEvent
1686#endif /* HAVE_X11 */
1687
dc6f92b8
JB
1688/* Timestamp of enter window event. This is only used by XTread_socket,
1689 but we have to put it out here, since static variables within functions
1690 sometimes don't work. */
1691static Time enter_timestamp;
1692
c047688c
JA
1693/* Communication with window managers. */
1694Atom Xatom_wm_protocols;
1695
1696/* Kinds of protocol things we may receive. */
1697Atom Xatom_wm_take_focus;
1698Atom Xatom_wm_save_yourself;
1699Atom Xatom_wm_delete_window;
1700
1701/* Other WM communication */
1702Atom Xatom_wm_configure_denied; /* When our config request is denied */
1703Atom Xatom_wm_window_moved; /* When the WM moves us. */
1704
dc6f92b8
JB
1705/* Read events coming from the X server.
1706 This routine is called by the SIGIO handler.
1707 We return as soon as there are no more events to be read.
1708
1709 Events representing keys are stored in buffer BUFP,
1710 which can hold up to NUMCHARS characters.
1711 We return the number of characters stored into the buffer,
1712 thus pretending to be `read'.
1713
1714 WAITP is nonzero if we should block until input arrives.
1715 EXPECTED is nonzero if the caller knows input is available. */
1716
1717Lisp_Object
1718XTread_socket (sd, bufp, numchars, waitp, expected)
1719 register int sd;
1720 register struct input_event *bufp;
1721 register int numchars;
1722 int waitp;
1723 int expected;
1724{
1725 int count = 0;
1726 int nbytes = 0;
1727 int mask;
1728 int items_pending; /* How many items are in the X queue. */
1729 XEvent event;
1730 struct screen *s;
1731 int event_found;
1732 int prefix;
1733 Lisp_Object part;
1734
1735 if (x_input_blocked)
1736 {
1737 x_pending_input = 1;
1738 return -1;
1739 }
1740
1741 x_pending_input = 0;
1742 BLOCK_INPUT;
1743
1744 if (numchars <= 0)
1745 abort (); /* Don't think this happens. */
1746
1747#ifdef FIOSNBIO
1748 /* If available, Xlib uses FIOSNBIO to make the socket
1749 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
1750 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
1751 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
1752 fcntl (fileno (stdin), F_SETFL, 0);
1753#endif
1754
1755#ifndef SIGIO
1756#ifndef HAVE_SELECT
1757 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
1758 {
1759 extern int read_alarm_should_throw;
1760 read_alarm_should_throw = 1;
1761 XPeekEvent (XDISPLAY &event);
1762 read_alarm_should_throw = 0;
1763 }
1764#endif
1765#endif
1766
1767 while (XStuffPending () != 0)
1768 {
1769 XNextEvent (XDISPLAY &event);
1770 event_found = 1;
1771
1772 switch (event.type)
1773 {
1774#ifdef HAVE_X11
c047688c
JA
1775 case ClientMessage:
1776 {
1777 if (event.xclient.message_type == Xatom_wm_protocols
1778 && event.xclient.format == 32)
1779 {
1780 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
1781 {
1782 s = x_window_to_screen (event.xclient.window);
1783 if (s)
1784 x_focus_on_screen (s);
1785 /* Not certain about handling scrollbars here */
1786 }
1787 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
1788 {
1789 /* Save state modify the WM_COMMAND property to
1790 something which can reinstate us. This notifies
1791 the session manager, who's looking for such a
1792 PropertyNotify. Can restart processing when
1793 a keyboard or mouse event arrives. */
1794 if (numchars > 0)
1795 {
1796 }
1797 }
1798 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
1799 {
1800 struct screen *s = x_window_to_screen (event.xclient.window);
1801
1802 if (s)
1803 if (numchars > 0)
1804 {
1805 }
1806 }
1807 }
1808 else if (event.xclient.message_type == Xatom_wm_configure_denied)
1809 {
1810 }
1811 else if (event.xclient.message_type == Xatom_wm_window_moved)
1812 {
1813 int new_x, new_y;
1814
1815 new_x = event.xclient.data.s[0];
1816 new_y = event.xclient.data.s[1];
1817 }
1818 }
1819 break;
dc6f92b8
JB
1820
1821 case SelectionClear: /* Someone has grabbed ownership. */
1822 x_disown_selection (event.xselectionclear.window,
1823 event.xselectionclear.selection,
1824 event.xselectionclear.time);
1825 break;
1826
1827 case SelectionRequest: /* Someone wants our selection. */
1828 x_answer_selection_request (event);
1829 break;
1830
1831 case PropertyNotify:
1832 /* If we were to do this synchronously, there'd be no worry
1833 about re-selecting. */
1834 x_send_incremental (event);
1835 break;
1836
1837 case Expose:
1838 s = x_window_to_screen (event.xexpose.window);
1839 if (s)
1840 {
1841 if (s->visible == 0)
1842 {
1843 s->visible = 1;
1844 s->iconified = 0;
1845 SET_SCREEN_GARBAGED (s);
1846 }
1847 else
1848 dumprectangle (x_window_to_screen (event.xexpose.window),
1849 event.xexpose.x, event.xexpose.y,
1850 event.xexpose.width, event.xexpose.height);
1851 }
1852 break;
1853
1854 case GraphicsExpose: /* This occurs when an XCopyArea's
1855 source area was obscured or not
1856 available.*/
1857 dumprectangle (x_window_to_screen (event.xgraphicsexpose.drawable),
1858 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
1859 event.xgraphicsexpose.width,
1860 event.xgraphicsexpose.height);
1861 break;
1862
1863 case NoExpose: /* This occurs when an XCopyArea's
1864 source area was completely
1865 available */
1866 break;
1867#else /* not HAVE_X11 */
1868 case ExposeWindow:
1869 if (event.subwindow != 0)
1870 break; /* duplicate event */
1871 s = x_window_to_screen (event.window);
1872 if (event.window == s->display.x->icon_desc)
1873 {
1874 refreshicon (s);
1875 s->iconified = 1;
1876 }
1877 if (event.window == s->display.x->window_desc)
1878 {
1879 /* Say must check all windows' needs_exposure flags. */
1880 expose_all_windows = 1;
1881 s->display.x->needs_exposure = 1;
1882 s->visible = 1;
1883 }
1884 break;
1885
1886 case ExposeRegion:
1887 if (event.subwindow != 0)
1888 break; /* duplicate event */
1889 s = x_window_to_screen (event.window);
1890 if (event.window == s->display.x->icon_desc)
1891 {
1892 refreshicon (s);
1893 break;
1894 }
1895 /* If window already needs full redraw, ignore this rectangle. */
1896 if (expose_all_windows && s->display.x->needs_exposure)
1897 break;
1898 /* Put the event on the queue of rectangles to redraw. */
1899 if (enqueue_event (&event, &x_expose_queue))
1900 /* If it is full, we can't record the rectangle,
1901 so redraw this entire window. */
1902 {
1903 /* Say must check all windows' needs_exposure flags. */
1904 expose_all_windows = 1;
1905 s->display.x->needs_exposure = 1;
1906 }
1907 break;
1908
1909 case ExposeCopy:
1910 /* This should happen only when we are expecting it,
1911 in x_read_exposes. */
1912 abort ();
1913#endif /* not HAVE_X11 */
1914
1915#ifdef HAVE_X11
1916 case UnmapNotify:
1917 {
1918 XWMHints *hints;
1919
1920 s = x_window_to_screen (event.xunmap.window);
1921 if (s) /* S may no longer exist if
1922 the screen was deleted. */
1923 {
1924 /* While a screen is unmapped, display generation is
1925 disabled; you don't want to spend time updating a
1926 display that won't ever be seen. */
1927 s->visible = 0;
dc6f92b8
JB
1928 x_mouse_x = x_mouse_y = -1;
1929 }
1930 }
1931 break;
1932
1933 case MapNotify:
1934 s = x_window_to_screen (event.xmap.window);
1935 if (s)
1936 {
1937 s->visible = 1;
1938 s->iconified = 0;
1939
1940 /* wait_reading_process_input will notice this and update
1941 the screen's display structures. */
1942 SET_SCREEN_GARBAGED (s);
1943 }
1944 break;
1945
1946 /* Turn off processing if we become fully obscured. */
1947 case VisibilityNotify:
1948 break;
1949
1950#else
1951 case UnmapWindow:
1952 s = x_window_to_screen (event.window);
1953 if (event.window == s->display.x->icon_desc)
1954 s->iconified = 0;
1955 if (event.window == s->display.x->window_desc)
1956 s->visible = 0;
1957 break;
1958#endif /* HAVE_X11 */
1959
1960#ifdef HAVE_X11
1961 case KeyPress:
1962 s = x_window_to_screen (event.xkey.window);
1963 if (s != 0)
1964 {
1965 KeySym keysym;
1966 XComposeStatus status;
1967 char copy_buffer[80];
3a2712f9
JB
1968 int modifiers = event.xkey.state;
1969
1970 /* Some keyboards generate different characters
1971 depending on the state of the meta key, in an attempt
1972 to support non-English typists. It would be nice to
1973 keep this functionality somehow, but for now, we will
1974 just clear the meta-key flag to get the 'pure' character. */
1975 event.xkey.state &= ~Mod1Mask;
dc6f92b8
JB
1976
1977 /* This will have to go some day... */
1978 nbytes = XLookupString (&event.xkey,
1979 copy_buffer,
1980 80,
1981 &keysym,
1982 &status);
1983
55123275
JB
1984 /* Strip off the vendor-specific keysym bit, and take a shot
1985 at recognizing the codes. HP servers have extra keysyms
1986 that fit into the MiscFunctionKey category. */
1987 keysym &= ~(1<<28);
1988
dc6f92b8
JB
1989 if (numchars > 1)
1990 {
55123275
JB
1991 if (IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
1992 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
1993 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
1994 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
dc6f92b8
JB
1995 {
1996 bufp->kind = non_ascii_keystroke;
90e65f07 1997 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
daa37602 1998 bufp->screen = s;
3a2712f9 1999 bufp->modifiers = x_convert_modifiers (modifiers);
1113d9db 2000 bufp->timestamp = event.xkey.time;
dc6f92b8
JB
2001 bufp++;
2002 count++;
2003 numchars--;
2004 }
2005 else if (numchars > nbytes)
2006 {
2007 register int i;
2008
2009 if (nbytes == 1)
2010 {
3a2712f9 2011 if (modifiers & Mod1Mask)
dc6f92b8
JB
2012 *copy_buffer |= METABIT;
2013 bufp->kind = ascii_keystroke;
2014 XSET (bufp->code, Lisp_Int, *copy_buffer);
daa37602 2015 bufp->screen = s;
1113d9db 2016 bufp->timestamp = event.xkey.time;
dc6f92b8
JB
2017 bufp++;
2018 }
2019 else
2020 for (i = nbytes - 1; i > 1; i--)
2021 {
2022 bufp->kind = ascii_keystroke;
2023 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
daa37602 2024 bufp->screen = s;
1113d9db 2025 bufp->timestamp = event.xkey.time;
dc6f92b8
JB
2026 bufp++;
2027 }
2028
2029 count += nbytes;
2030 numchars -= nbytes;
2031 }
2032 }
2033 }
2034 break;
2035#else
2036 case KeyPressed:
2037 {
2038 register char *where_mapping;
2039
2040 s = x_window_to_screen (event.window);
2041 /* Ignore keys typed on icon windows. */
2042 if (s != 0 && event.window == s->display.x->icon_desc)
2043 break;
2044 where_mapping = XLookupMapping (&event, &nbytes);
2045 /* Nasty fix for arrow keys */
2046 if (!nbytes && IsCursorKey (event.detail & 0xff))
2047 {
2048 switch (event.detail & 0xff)
2049 {
2050 case KC_CURSOR_LEFT:
2051 where_mapping = "\002";
2052 break;
2053 case KC_CURSOR_RIGHT:
2054 where_mapping = "\006";
2055 break;
2056 case KC_CURSOR_UP:
2057 where_mapping = "\020";
2058 break;
2059 case KC_CURSOR_DOWN:
2060 where_mapping = "\016";
2061 break;
2062 }
2063 nbytes = 1;
2064 }
2065 if (numchars - nbytes > 0)
2066 {
2067 register int i;
2068
2069 for (i = 0; i < nbytes; i++)
2070 {
2071 bufp->kind = ascii_keystroke;
2072 XSET (bufp->code, Lisp_Int, where_mapping[i]);
90e65f07 2073 XSET (bufp->time, Lisp_Int, event.xkey.time);
daa37602 2074 bufp->screen = s;
dc6f92b8
JB
2075 bufp++;
2076 }
2077 count += nbytes;
2078 numchars -= nbytes;
2079 }
2080 }
2081 break;
2082#endif /* HAVE_X11 */
2083
2084#ifdef HAVE_X11
2085 case EnterNotify:
6d4238f3
JB
2086 s = x_window_to_screen (event.xcrossing.window);
2087
dc6f92b8
JB
2088 if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
2089 ;
2090 else if (event.xcrossing.focus) /* Entered Window */
2091 {
2092 /* If we decide we want to generate an event to be seen
2093 by the rest of Emacs, we put it here. */
2094 struct input_event emacs_event;
2095 emacs_event.kind = no_event;
2096
dc6f92b8
JB
2097 /* Avoid nasty pop/raise loops. */
2098 if (s && (!(s->auto_raise)
2099 || !(s->auto_lower)
2100 || (event.xcrossing.time - enter_timestamp) > 500))
2101 {
6d4238f3 2102 x_new_focus_screen (s);
dc6f92b8
JB
2103 enter_timestamp = event.xcrossing.time;
2104 }
2105#if 0
2106 else if ((s = x_window_to_scrollbar (event.xcrossing.window,
2107 &part, &prefix)))
2108 /* Fake a motion event */
2109 notice_mouse_movement (&emacs_event,
2110 event.xmotion, s, scrollbar_window,
2111 part);
2112#endif
2113
2114#if 0
2115 if (! EQ (Vx_send_mouse_movement_events, Qnil)
2116 && numchars >= 1
2117 && emacs_event.kind != no_event)
2118 {
2119 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2120 bufp++;
2121 count++;
2122 numchars--;
2123 }
2124#endif
2125 }
6d4238f3
JB
2126 else if (s == x_focus_screen)
2127 x_new_focus_screen (0);
dc6f92b8
JB
2128#if 0
2129 else if (s = x_window_to_screen (event.xcrossing.window))
2130 x_mouse_screen = s;
2131#endif
2132
2133 break;
2134
2135 case FocusIn:
2136 s = x_window_to_screen (event.xfocus.window);
2137 if (s)
6d4238f3 2138 x_new_focus_screen (s);
dc6f92b8
JB
2139 break;
2140
2141 case LeaveNotify:
2142 if (event.xcrossing.detail != NotifyInferior
2143 && event.xcrossing.subwindow == None
2144 && event.xcrossing.mode == NotifyNormal)
2145 {
6d4238f3 2146 s = x_window_to_screen (event.xcrossing.window);
c7004826 2147 if (event.xcrossing.focus)
6d4238f3
JB
2148 x_new_focus_screen (s);
2149 else if (s == x_focus_screen)
2150 x_new_focus_screen (0);
dc6f92b8
JB
2151 }
2152 break;
2153
2154 case FocusOut:
2155 s = x_window_to_screen (event.xfocus.window);
2156 if (s && s == x_focus_screen)
6d4238f3 2157 x_new_focus_screen (0);
dc6f92b8
JB
2158 break;
2159
2160#else /* not HAVE_X11 */
2161
2162 case EnterWindow:
2163 if ((event.detail & 0xFF) == 1)
2164 break; /* Coming from our own subwindow */
2165 if (event.subwindow != 0)
2166 break; /* Entering our own subwindow. */
2167
2168 {
dc6f92b8
JB
2169 struct screen *old_s = x_input_screen;
2170
2171 s = x_window_to_screen (event.window);
2172 x_mouse_screen = s;
2173
1113d9db 2174 x_new_focus_screen (s);
dc6f92b8
JB
2175 }
2176 break;
2177
2178 case LeaveWindow:
2179 if ((event.detail & 0xFF) == 1)
2180 break; /* Entering our own subwindow */
2181 if (event.subwindow != 0)
2182 break; /* Leaving our own subwindow. */
2183
2184 x_mouse_screen = 0;
2185 if (x_focus_screen == 0
2186 && x_input_screen != 0
2187 && x_input_screen == x_window_to_screen (event.window)
2188 && event.window == x_input_screen->display.x->window_desc)
2189 {
2190 s = x_input_screen;
2191 x_input_screen = 0;
2192 if (s)
2193 screen_unhighlight (s);
2194 }
2195 break;
2196#endif /* not HAVE_X11 */
2197
2198#ifdef HAVE_X11
2199 case MotionNotify:
2200 {
2201 s = x_window_to_screen (event.xmotion.window);
2202 if (s)
90e65f07 2203 note_mouse_position (s, &event.xmotion);
dc6f92b8
JB
2204#if 0
2205 else if ((s = x_window_to_scrollbar (event.xmotion.window,
2206 &part, &prefix)))
2207 {
2208 What should go here?
2209 }
2210#endif
2211 }
2212 break;
2213
2214 case ConfigureNotify:
2215 {
2216 int rows, columns;
2217 s = x_window_to_screen (event.xconfigure.window);
2218 if (!s)
2219 break;
2220
2221 columns = ((event.xconfigure.width -
2222 (2 * s->display.x->internal_border_width)
2223 - s->display.x->v_scrollbar_width)
2224 / FONT_WIDTH (s->display.x->font));
2225 rows = ((event.xconfigure.height -
2226 (2 * s->display.x->internal_border_width)
2227 - s->display.x->h_scrollbar_height)
2228 / FONT_HEIGHT (s->display.x->font));
2229
90e65f07
JB
2230 /* Even if the number of character rows and columns has
2231 not changed, the font size may have changed, so we need
2232 to check the pixel dimensions as well. */
2233 if (columns != s->width
2234 || rows != s->height
2235 || event.xconfigure.width != s->display.x->pixel_width
2236 || event.xconfigure.height != s->display.x->pixel_height)
dc6f92b8 2237 {
dc6f92b8
JB
2238 change_screen_size (s, rows, columns, 0);
2239 x_resize_scrollbars (s);
2240 SET_SCREEN_GARBAGED (s);
dc6f92b8
JB
2241 }
2242
dc6f92b8
JB
2243 s->display.x->pixel_width = event.xconfigure.width;
2244 s->display.x->pixel_height = event.xconfigure.height;
90e65f07
JB
2245 s->display.x->left_pos = event.xconfigure.x;
2246 s->display.x->top_pos = event.xconfigure.y;
dc6f92b8
JB
2247 break;
2248 }
2249
2250 case ButtonPress:
2251 case ButtonRelease:
2252 {
2253 /* If we decide we want to generate an event to be seen
2254 by the rest of Emacs, we put it here. */
2255 struct input_event emacs_event;
2256 emacs_event.kind = no_event;
2257
2258 s = x_window_to_screen (event.xbutton.window);
2259 if (s)
2260 if (!x_focus_screen || (s == x_focus_screen))
2261 construct_mouse_click (&emacs_event,
2262 &event, s, 0, 0);
2263 else
2264 continue;
2265 else
2266 if ((s = x_window_to_scrollbar (event.xbutton.window,
2267 &part, &prefix)))
2268 {
2269 if (!x_focus_screen || (selected_screen == x_focus_screen))
2270 construct_mouse_click (&emacs_event,
2271 &event, s, part, prefix);
2272 else
2273 continue;
2274 }
2275
2276 if (numchars >= 1 && emacs_event.kind != no_event)
2277 {
2278 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2279 bufp++;
2280 count++;
2281 numchars--;
2282 }
2283 }
2284 break;
2285
2286#else /* not HAVE_X11 */
2287 case ButtonPressed:
2288 case ButtonReleased:
2289 s = x_window_to_screen (event.window);
2290 if (s)
2291 {
2292 if (event.window == s->display.x->icon_desc)
2293 {
2294 x_make_screen_visible (s);
2295
2296 if (warp_mouse_on_deiconify)
2297 XWarpMouse (s->display.x->window_desc, 10, 10);
2298 break;
2299 }
2300 if (event.window == s->display.x->window_desc)
2301 {
2302 if (s->auto_raise)
2303 x_raise_screen (s);
2304 }
2305 }
2306 enqueue_event (&event, &x_mouse_queue);
2307 if (numchars >= 2)
2308 {
2309 bufp->kind = ascii_keystroke;
2310 bufp->code = (char) 'X' & 037; /* C-x */
daa37602 2311 bufp->screen = s;
90e65f07 2312 XSET (bufp->time, Lisp_Int, event.xkey.time);
dc6f92b8
JB
2313 bufp++;
2314
2315 bufp->kind = ascii_keystroke;
2316 bufp->code = (char) 0; /* C-@ */
daa37602 2317 bufp->screen = s;
90e65f07 2318 XSET (bufp->time, Lisp_Int, event.xkey.time);
dc6f92b8
JB
2319 bufp++;
2320
2321 count += 2;
2322 numchars -= 2;
2323 }
2324 break;
2325#endif /* not HAVE_X11 */
2326
2327#ifdef HAVE_X11
2328
2329 case CirculateNotify:
2330 break;
2331 case CirculateRequest:
2332 break;
2333
2334#endif /* HAVE_X11 */
2335
2336 case MappingNotify:
2337 if (event.xmapping.request == MappingKeyboard)
2338 /* Someone has changed the keyboard mapping - flush the
2339 local cache. */
2340 XRefreshKeyboardMapping (&event.xmapping);
2341 break;
2342
2343 default:
2344 break;
2345 }
2346 }
2347
2348#if 0
2349#ifdef HAVE_SELECT
2350 if (expected && ! event_found)
2351 {
2352 /* AOJ 880406: if select returns true but XPending doesn't, it means that
2353 there is an EOF condition; in other words, that X has died.
2354 Act as if there had been a hangup. */
2355
2356 int fd = ConnectionNumber (x_current_display);
2357 int mask = 1 << fd;
2358
2359 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3a2712f9 2360 (EMACS_TIME) 0)
dc6f92b8
JB
2361 && !XStuffPending ())
2362 kill (getpid (), SIGHUP);
2363 }
2364#endif /* HAVE_SELECT */
2365#endif
2366
2367 if (updating_screen == 0)
2368 x_do_pending_expose ();
2369
2370 UNBLOCK_INPUT;
2371 return count;
2372}
2373
2374#ifndef HAVE_X11
2375/* Read and process only Expose events
2376 until we get an ExposeCopy event; then return.
2377 This is used in insert/delete line.
2378 We assume input is already blocked. */
2379
2380static void
2381x_read_exposes ()
2382{
2383 struct screen *s;
2384 XKeyPressedEvent event;
2385
2386 while (1)
2387 {
2388 /* while there are more events*/
2389 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
2390 switch (event.type)
2391 {
2392 case ExposeWindow:
2393 if (event.subwindow != 0)
2394 break; /* duplicate event */
2395 s = x_window_to_screen (event.window);
2396 if (event.window == s->display.x->icon_desc)
2397 {
2398 refreshicon (s);
2399 break;
2400 }
2401 if (event.window == s->display.x->window_desc)
2402 {
2403 expose_all_windows = 1;
2404 s->display.x->needs_exposure = 1;
2405 break;
2406 }
2407 break;
2408
2409 case ExposeRegion:
2410 if (event.subwindow != 0)
2411 break; /* duplicate event */
2412 s = x_window_to_screen (event.window);
2413 if (event.window == s->display.x->icon_desc)
2414 {
2415 refreshicon (s);
2416 break;
2417 }
2418 /* If window already needs full redraw, ignore this rectangle. */
2419 if (expose_all_windows && s->display.x->needs_exposure)
2420 break;
2421 /* Put the event on the queue of rectangles to redraw. */
2422 if (enqueue_event (&event, &x_expose_queue))
2423 /* If it is full, we can't record the rectangle,
2424 so redraw this entire window. */
2425 {
2426 /* Say must check all windows' needs_exposure flags. */
2427 expose_all_windows = 1;
2428 s->display.x->needs_exposure = 1;
2429 }
2430 break;
2431
2432 case ExposeCopy:
2433 return;
2434 }
2435 }
2436}
2437#endif /* HAVE_X11 */
2438
dc6f92b8
JB
2439\f
2440/* Draw a hollow box cursor. Don't change the inside of the box. */
2441
2442static void
2443x_draw_box (s)
2444 struct screen *s;
2445{
2446 int left = s->cursor_x * FONT_WIDTH (s->display.x->font)
2447 + s->display.x->internal_border_width;
2448 int top = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2449 + s->display.x->internal_border_width;
2450 int width = FONT_WIDTH (s->display.x->font);
2451 int height = FONT_HEIGHT (s->display.x->font);
2452
2453#ifdef HAVE_X11
2454 /* Perhaps we should subtract 1 from width and height... */
2455 XDrawRectangle (x_current_display, s->display.x->window_desc,
2456 s->display.x->cursor_gc,
2457 left, top, width - 1, height - 1);
2458#else
2459 XPixSet (s->display.x->window_desc,
2460 left, top, width, 1,
2461 s->display.x->cursor_pixel);
2462
2463 XPixSet (s->display.x->window_desc,
2464 left, top, 1, height,
2465 s->display.x->cursor_pixel);
2466
2467 XPixSet (s->display.x->window_desc,
2468 left+width-1, top, 1, height,
2469 s->display.x->cursor_pixel);
2470
2471 XPixSet (s->display.x->window_desc,
2472 left, top+height-1, width, 1,
2473 s->display.x->cursor_pixel);
2474#endif /* HAVE_X11 */
2475}
2476
2477/* Clear the cursor of screen S to background color,
2478 and mark the cursor as not shown.
2479 This is used when the text where the cursor is
2480 is about to be rewritten. */
2481
2482static void
2483clear_cursor (s)
2484 struct screen *s;
2485{
2486 int mask;
2487
2488 if (! s->visible
2489 || s->phys_cursor_x < 0)
2490 return;
2491
2492#ifdef HAVE_X11
2493 x_display_cursor (s, 0);
2494#if 0
2495 XClearArea (x_current_display, s->display.x->window_desc,
2496 s->phys_cursor_x * FONT_WIDTH (s->display.x->font)
2497 + s->display.x->internal_border_width,
2498 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font)
2499 + s->display.x->internal_border_width,
2500 FONT_WIDTH (s->display.x->font) + 1, FONT_HEIGHT (s->display.x->font) + 1, False);
2501#endif
2502#else
2503 XPixSet (s->display.x->window_desc,
2504 s->phys_cursor_x * FONT_WIDTH (s->display.x->font) + s->display.x->internal_border_width,
2505 s->phys_cursor_y * FONT_HEIGHT (s->display.x->font) + s->display.x->internal_border_width,
2506 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font),
2507 s->display.x->background_pixel);
2508#endif /* HAVE_X11 */
2509 s->phys_cursor_x = -1;
2510}
2511
90e65f07 2512static void
dc6f92b8
JB
2513x_display_bar_cursor (s, on)
2514 struct screen *s;
2515 int on;
2516{
2517 register int phys_x = s->phys_cursor_x;
2518 register int phys_y = s->phys_cursor_y;
2519 register int x1;
2520 register int y1;
2521 register int y2;
2522
2523 if (! s->visible || (! on && s->phys_cursor_x < 0))
2524 return;
2525
2526#ifdef HAVE_X11
2527 if (phys_x >= 0 &&
2528 (!on || phys_x != s->cursor_x || phys_y != s->cursor_y))
2529 {
2530 x1 = phys_x * FONT_WIDTH (s->display.x->font)
2531 + s->display.x->internal_border_width;
2532 y1 = phys_y * FONT_HEIGHT (s->display.x->font)
2533 + s->display.x->internal_border_width - 1;
2534 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2535
2536 XDrawLine (x_current_display, s->display.x->window_desc,
2537 s->display.x->reverse_gc, x1, y1, x1, y2);
2538
2539 s->phys_cursor_x = phys_x = -1;
2540 }
2541
6d4238f3 2542 if (on && s == x_highlight_screen)
dc6f92b8
JB
2543 {
2544 x1 = s->cursor_x * FONT_WIDTH (s->display.x->font)
2545 + s->display.x->internal_border_width;
2546 y1 = s->cursor_y * FONT_HEIGHT (s->display.x->font)
2547 + s->display.x->internal_border_width - 1;
2548 y2 = y1 + FONT_HEIGHT (s->display.x->font) + 1;
2549
2550 XDrawLine (x_current_display, s->display.x->window_desc,
2551 s->display.x->cursor_gc, x1, y1, x1, y2);
2552
2553 s->phys_cursor_x = s->cursor_x;
2554 s->phys_cursor_y = s->cursor_y;
2555 }
2556#else /* X10 */
2557 Give it up, dude.
2558#endif /* X10 */
2559}
2560
2561
90e65f07
JB
2562/* Redraw the glyph at ROW, COLUMN on screen S, in the style
2563 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2564 glyph drawn. */
dc6f92b8
JB
2565
2566static void
90e65f07 2567x_draw_single_glyph (s, row, column, glyph, highlight)
dc6f92b8
JB
2568 struct screen *s;
2569 int row, column;
90e65f07 2570 GLYPH glyph;
dc6f92b8
JB
2571 int highlight;
2572{
90e65f07
JB
2573 dumpglyphs (s,
2574 (column * FONT_WIDTH (s->display.x->font)
2575 + s->display.x->internal_border_width),
2576 (row * FONT_HEIGHT (s->display.x->font)
2577 + s->display.x->internal_border_width),
2578 &glyph, 1, highlight, s->display.x->font);
dc6f92b8
JB
2579}
2580
2581/* Turn the displayed cursor of screen S on or off according to ON.
2582 If ON is nonzero, where to put the cursor is specified
2583 by S->cursor_x and S->cursor_y. */
2584
2585static void
2586x_display_box_cursor (s, on)
2587 struct screen *s;
2588 int on;
2589{
90e65f07
JB
2590 struct screen_glyphs *current_glyphs = SCREEN_CURRENT_GLYPHS (s);
2591
1113d9db
JB
2592 /* If we're not updating, then we want to use the current screen's
2593 cursor position, not our local idea of where the cursor ought to be. */
2594 if (s != updating_screen)
2595 {
2596 curs_x = SCREEN_CURSOR_X (s);
2597 curs_y = SCREEN_CURSOR_Y (s);
2598 }
2599
dc6f92b8
JB
2600 if (! s->visible)
2601 return;
2602
2603 /* If cursor is off and we want it off, return quickly. */
dc6f92b8
JB
2604 if (!on && s->phys_cursor_x < 0)
2605 return;
2606
2607 /* If cursor is currently being shown and we don't want it to be
2608 or it is in the wrong place,
2609 or we want a hollow box and it's not so, (pout!)
2610 erase it. */
2611 if (s->phys_cursor_x >= 0
2612 && (!on
1113d9db
JB
2613 || s->phys_cursor_x != curs_x
2614 || s->phys_cursor_y != curs_y
dc6f92b8 2615 || (s->display.x->text_cursor_kind != hollow_box_cursor
6d4238f3 2616 && (s != x_highlight_screen))))
dc6f92b8
JB
2617 {
2618 /* Erase the cursor by redrawing the character underneath it. */
2619 x_draw_single_glyph (s, s->phys_cursor_y, s->phys_cursor_x,
90e65f07
JB
2620 s->phys_cursor_glyph,
2621 current_glyphs->highlight[s->phys_cursor_y]);
dc6f92b8
JB
2622 s->phys_cursor_x = -1;
2623 }
2624
2625 /* If we want to show a cursor,
2626 or we want a box cursor and it's not so,
2627 write it in the right place. */
2628 if (on
2629 && (s->phys_cursor_x < 0
2630 || (s->display.x->text_cursor_kind != filled_box_cursor
6d4238f3 2631 && s == x_highlight_screen)))
dc6f92b8 2632 {
90e65f07 2633 s->phys_cursor_glyph
1113d9db
JB
2634 = ((current_glyphs->enable[curs_y]
2635 && curs_x < current_glyphs->used[curs_y])
2636 ? current_glyphs->glyphs[curs_y][curs_x]
90e65f07 2637 : SPACEGLYPH);
6d4238f3 2638 if (s != x_highlight_screen)
dc6f92b8
JB
2639 {
2640 x_draw_box (s);
2641 s->display.x->text_cursor_kind = hollow_box_cursor;
2642 }
2643 else
2644 {
1113d9db 2645 x_draw_single_glyph (s, curs_y, curs_x,
90e65f07 2646 s->phys_cursor_glyph, 2);
dc6f92b8
JB
2647 s->display.x->text_cursor_kind = filled_box_cursor;
2648 }
2649
1113d9db
JB
2650 s->phys_cursor_x = curs_x;
2651 s->phys_cursor_y = curs_y;
dc6f92b8
JB
2652 }
2653
2654 if (updating_screen != s)
2655 XFlushQueue ();
2656}
2657
dc6f92b8
JB
2658extern Lisp_Object Vbar_cursor;
2659
2660x_display_cursor (s, on)
2661 struct screen *s;
2662 int on;
2663{
2664 if (EQ (Vbar_cursor, Qnil))
2665 x_display_box_cursor (s, on);
2666 else
2667 x_display_bar_cursor (s, on);
2668}
2669\f
2670/* Icons. */
2671
2672/* Refresh bitmap kitchen sink icon for screen S
2673 when we get an expose event for it. */
2674
2675refreshicon (s)
2676 struct screen *s;
2677{
2678#ifdef HAVE_X11
2679 /* Normally, the window manager handles this function. */
2680#else
2681 int mask;
2682
2683 if (s->display.x->icon_bitmap_flag)
2684 XBitmapBitsPut (s->display.x->icon_desc, 0, 0, sink_width, sink_height,
2685 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
2686 icon_bitmap, GXcopy, AllPlanes);
2687 else
2688 {
2689 extern struct screen *selected_screen;
2690 struct Lisp_String *str;
2691 unsigned char *string;
2692
2693 string
2694 = XSTRING (XBUFFER (XWINDOW (s->selected_window)->buffer)->name)->data;
2695
2696 if (s->display.x->icon_label != string)
2697 {
2698 s->display.x->icon_label = string;
2699 XChangeWindow (s->display.x->icon_desc,
2700 XQueryWidth (string, icon_font_info->id) + 10,
2701 icon_font_info->height + 10);
2702 }
2703
2704 XText (s->display.x->icon_desc, 5, 5, string,
2705 str->size, icon_font_info->id,
2706 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
2707 }
2708 XFlushQueue ();
2709#endif /* HAVE_X11 */
2710}
2711
2712/* Make the x-window of screen S use the kitchen-sink icon
2713 that's a window generated by Emacs. */
2714
2715int
2716x_bitmap_icon (s)
2717 struct screen *s;
2718{
2719 int mask;
2720 Window icon_window;
2721
2722 if (s->display.x->window_desc == 0)
2723 return 1;
2724
2725#ifdef HAVE_X11
2726 if (icon_bitmap)
2727 XFreePixmap (x_current_display, icon_bitmap);
2728
2729 icon_bitmap =
2730 XCreateBitmapFromData (x_current_display, s->display.x->window_desc,
2731 gnu_bits, gnu_width, gnu_height);
2732 x_wm_set_icon_pixmap (s, icon_bitmap);
2733 s->display.x->icon_bitmap_flag = 1;
2734#else
2735 if (s->display.x->icon_desc)
2736 {
2737 XClearIconWindow (s->display.x->window_desc);
2738 XDestroyWindow (s->display.x->icon_desc);
2739 }
2740
2741 icon_window = XCreateWindow (s->display.x->parent_desc,
2742 0, 0, sink_width, sink_height,
2743 2, WhitePixmap, (Pixmap) NULL);
2744
2745 if (icon_window == 0)
2746 return 1;
2747
2748 XSetIconWindow (s->display.x->window_desc, icon_window);
2749 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
2750
2751 s->display.x->icon_desc = icon_window;
2752 s->display.x->icon_bitmap_flag = 1;
2753
2754 if (icon_bitmap == 0)
2755 icon_bitmap
2756 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
2757#endif /* HAVE_X11 */
2758
2759 return 0;
2760}
2761
2762
2763/* Make the x-window of screen S use a rectangle with text. */
2764
2765int
2766x_text_icon (s, icon_name)
2767 struct screen *s;
2768 char *icon_name;
2769{
2770#ifndef HAVE_X11
2771 int mask;
2772 int width;
2773 Window icon_window;
2774 char *X_DefaultValue;
2775 Bitmap b1;
2776
dc6f92b8
JB
2777#ifndef WhitePixel
2778#define WhitePixel 1
2779#endif
2780
2781#ifndef BlackPixel
2782#define BlackPixel 0
2783#endif
2784#endif /* not HAVE_X11 */
2785
2786 if (s->display.x->window_desc == 0)
2787 return 1;
2788
2789 if (icon_font_info == 0)
2790 icon_font_info
55123275
JB
2791 = XGetFont (XGetDefault (XDISPLAY
2792 (char *) XSTRING (invocation_name)->data,
2793 "BodyFont"));
dc6f92b8
JB
2794
2795#ifdef HAVE_X11
2796 if (icon_name)
2797 s->display.x->icon_label = icon_name;
2798 else
2799 if (! s->display.x->icon_label)
2800 s->display.x->icon_label = " *emacs* ";
2801
2802 XSetIconName (x_current_display, s->display.x->window_desc,
2803 (char *) s->display.x->icon_label);
2804
2805 s->display.x->icon_bitmap_flag = 0;
2806#else
2807 if (s->display.x->icon_desc)
2808 {
2809 XClearIconWindow (XDISPLAY s->display.x->window_desc);
2810 XDestroyWindow (XDISPLAY s->display.x->icon_desc);
2811 }
2812
2813 if (icon_name)
2814 s->display.x->icon_label = (unsigned char *) icon_name;
2815 else
2816 if (! s->display.x->icon_label)
2817 s->display.x->icon_label = XSTRING (s->name)->data;
2818
2819 width = XStringWidth (s->display.x->icon_label, icon_font_info, 0, 0);
2820 icon_window = XCreateWindow (s->display.x->parent_desc,
2821 s->display.x->left_pos,
2822 s->display.x->top_pos,
2823 width + 10, icon_font_info->height + 10,
2824 2, BlackPixmap, WhitePixmap);
2825
2826 if (icon_window == 0)
2827 return 1;
2828
2829 XSetIconWindow (s->display.x->window_desc, icon_window);
2830 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
2831
2832 s->display.x->icon_desc = icon_window;
2833 s->display.x->icon_bitmap_flag = 0;
2834 s->display.x->icon_label = 0;
2835#endif /* HAVE_X11 */
2836
2837 return 0;
2838}
2839\f
4746118a
JB
2840/* Handling X errors. */
2841
2842/* A handler for SIGPIPE, when it occurs on the X server's connection.
2843 This basically does an orderly shutdown of Emacs. */
2844static SIGTYPE
2845x_death_handler ()
2846{
2847 if (_Xdebug)
2848 abort ();
2849 else
2850 Fkill_emacs (make_number (70));
2851}
2852
dc6f92b8
JB
2853static char *x_proto_requests[] =
2854{
2855 "CreateWindow",
2856 "ChangeWindowAttributes",
2857 "GetWindowAttributes",
2858 "DestroyWindow",
2859 "DestroySubwindows",
2860 "ChangeSaveSet",
2861 "ReparentWindow",
2862 "MapWindow",
2863 "MapSubwindows",
2864 "UnmapWindow",
2865 "UnmapSubwindows",
2866 "ConfigureWindow",
2867 "CirculateWindow",
2868 "GetGeometry",
2869 "QueryTree",
2870 "InternAtom",
2871 "GetAtomName",
2872 "ChangeProperty",
2873 "DeleteProperty",
2874 "GetProperty",
2875 "ListProperties",
2876 "SetSelectionOwner",
2877 "GetSelectionOwner",
2878 "ConvertSelection",
2879 "SendEvent",
2880 "GrabPointer",
2881 "UngrabPointer",
2882 "GrabButton",
2883 "UngrabButton",
2884 "ChangeActivePointerGrab",
2885 "GrabKeyboard",
2886 "UngrabKeyboard",
2887 "GrabKey",
2888 "UngrabKey",
2889 "AllowEvents",
2890 "GrabServer",
2891 "UngrabServer",
2892 "QueryPointer",
2893 "GetMotionEvents",
2894 "TranslateCoords",
2895 "WarpPointer",
2896 "SetInputFocus",
2897 "GetInputFocus",
2898 "QueryKeymap",
2899 "OpenFont",
2900 "CloseFont",
2901 "QueryFont",
2902 "QueryTextExtents",
2903 "ListFonts",
2904 "ListFontsWithInfo",
2905 "SetFontPath",
2906 "GetFontPath",
2907 "CreatePixmap",
2908 "FreePixmap",
2909 "CreateGC",
2910 "ChangeGC",
2911 "CopyGC",
2912 "SetDashes",
2913 "SetClipRectangles",
2914 "FreeGC",
2915 "ClearArea",
2916 "CopyArea",
2917 "CopyPlane",
2918 "PolyPoint",
2919 "PolyLine",
2920 "PolySegment",
2921 "PolyRectangle",
2922 "PolyArc",
2923 "FillPoly",
2924 "PolyFillRectangle",
2925 "PolyFillArc",
2926 "PutImage",
2927 "GetImage",
2928 "PolyText",
2929 "PolyText",
2930 "ImageText",
2931 "ImageText",
2932 "CreateColormap",
2933 "FreeColormap",
2934 "CopyColormapAndFree",
2935 "InstallColormap",
2936 "UninstallColormap",
2937 "ListInstalledColormaps",
2938 "AllocColor",
2939 "AllocNamedColor",
2940 "AllocColorCells",
2941 "AllocColorPlanes",
2942 "FreeColors",
2943 "StoreColors",
2944 "StoreNamedColor",
2945 "QueryColors",
2946 "LookupColor",
2947 "CreateCursor",
2948 "CreateGlyphCursor",
2949 "FreeCursor",
2950 "RecolorCursor",
2951 "QueryBestSize",
2952 "QueryExtension",
2953 "ListExtensions",
2954 "ChangeKeyboardMapping",
2955 "GetKeyboardMapping",
2956 "ChangeKeyboardControl",
2957 "GetKeyboardControl",
2958 "Bell",
2959 "ChangePointerControl",
2960 "GetPointerControl",
2961 "SetScreenSaver",
2962 "GetScreenSaver",
2963 "ChangeHosts",
2964 "ListHosts",
2965 "SetAccessControl",
2966 "SetCloseDownMode",
2967 "KillClient",
2968 "RotateProperties",
2969 "ForceScreenSaver",
2970 "SetPointerMapping",
2971 "GetPointerMapping",
2972 "SetModifierMapping",
2973 "GetModifierMapping",
2974 "NoOperation"
2975};
2976
2977#define acceptable_x_error_p(type) ((type) == 94)
2978
2979x_handle_error_gracefully (event)
2980 XErrorEvent *event;
2981{
2982 char error_ptr[128];
2983 char *proto_ptr = x_proto_requests[event->request_code];
2984 char str[128];
2985
2986 XGetErrorText (x_current_display, event->error_code, error_ptr, 128);
2987 sprintf (str, "X Protocol Error: %s on request: %s", error_ptr, proto_ptr);
2988 TOTALLY_UNBLOCK_INPUT;
2989 error (str);
2990}
2991
2992#if 0
2993extern int x_selection_alloc_error;
2994extern int x_converting_selection;
2995#endif
2996
2997/* Handle X Errors. If the error is not traumatic,
2998 just call error (). Otherwise print a (hopefully) interesting
2999 message and quit.
3000
3001 The arg to Fkill_emacs is an exit status value
3002 and also prevents any questions. */
3003
3004x_error_handler (disp, event)
3005 Display *disp;
3006#ifdef HAVE_X11
3007 XErrorEvent *event;
3008
3009#define XlibDisplayIOError (1L << 0)
3010
3011#else
3012 struct _XErrorEvent *event;
3013#endif
3014{
3015 /* Here we use the standard X handlers. */
3016
3017 BLOCK_INPUT;
3018 if (event && event->type == 0) /* 0 is the XError Event type. */
3019 {
3020#if 0
3021#ifdef HAVE_X11
3022 if (event->request_code == BadAlloc && x_converting_selection)
3023 x_selection_alloc_error = 1;
3024 else
3025#endif
3026#endif
3027 if (acceptable_x_error_p (event->request_code))
3028 x_handle_error_gracefully (event);
3029 else
3030 _XDefaultError (disp, event);
3031 }
3032 else
3033 {
3034 disp->flags |= XlibDisplayIOError;
3035 _XDefaultIOError (disp);
3036 }
3037 UNBLOCK_INPUT;
3038
4746118a 3039 x_death_handler ();
dc6f92b8
JB
3040}
3041
dc6f92b8
JB
3042#if 0
3043static unsigned int x_wire_count;
3044x_trace_wire ()
3045{
3046 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3047}
3048#endif
3049
3050\f
3051/* Set the font of the x-window specified by screen S
3052 to the font named NEWNAME. This is safe to use
3053 even before S has an actual x-window. */
3054
3055#ifdef HAVE_X11
3056
3057/* A table of all the fonts we have already loaded. */
3058static XFontStruct **x_font_table;
3059
3060/* The current capacity of x_font_table. */
3061static int x_font_table_size;
3062
3063/* The number of fonts actually stored in x_font_table.
3064 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3065 0 <= n_fonts <= x_font_table_size. */
3066static int n_fonts;
3067
3068x_new_font (s, fontname)
3069 struct screen *s;
3070 register char *fontname;
3071{
3072 XFontStruct *temp;
3073 int already_loaded;
3074 int n_matching_fonts;
3075 XFontStruct *font_info;
3076 char **font_names;
3077
3078 /* Get a list of all the fonts that match this name. Once we
3079 have a list of matching fonts, we compare them against the fonts
3080 we already have by comparing font ids. */
3081 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3082 1024, &n_matching_fonts,
3083 &font_info);
3084 /* If the server couldn't find any fonts whose named matched fontname,
3085 return an error code. */
3086 if (n_matching_fonts == 0)
3087 return 1;
3088
90e65f07 3089 /* See if we've already loaded a matching font. */
dc6f92b8
JB
3090 {
3091 int i, j;
3092
3093 already_loaded = 0;
3094 for (i = 0; i < n_fonts; i++)
3095 for (j = 0; j < n_matching_fonts; j++)
3096 if (x_font_table[i]->fid == font_info[j].fid)
3097 {
3098 already_loaded = i;
3099 goto found_font;
3100 }
3101 }
3102 found_font:
3103
3104 /* If we have, just return it from the table. */
3105 if (already_loaded)
90e65f07
JB
3106 s->display.x->font = x_font_table[already_loaded];
3107
dc6f92b8
JB
3108 /* Otherwise, load the font and add it to the table. */
3109 else
3110 {
3111 XFontStruct *font;
3112
3113 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3114 if (! font)
3115 return 1;
3116
3117 /* Do we need to create the table? */
3118 if (x_font_table_size == 0)
3119 {
3120 x_font_table_size = 16;
3121 x_font_table
3122 = (XFontStruct **) xmalloc (x_font_table_size
3123 * sizeof (x_font_table[0]));
3124 }
3125 /* Do we need to grow the table? */
3126 else if (n_fonts >= x_font_table_size)
3127 {
90e65f07 3128 x_font_table_size *= 2;
dc6f92b8
JB
3129 x_font_table
3130 = (XFontStruct **) xrealloc (x_font_table,
3131 (x_font_table_size
3132 * sizeof (x_font_table[0])));
3133 }
3134
3135 s->display.x->font = x_font_table[n_fonts++] = font;
3136 }
3137
3138 /* Free the information from XListFontsWithInfo. The data
3139 we actually retain comes from XLoadQueryFont. */
3140 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3141
3142 /* Now make the screen display the given font. */
3143 if (s->display.x->window_desc != 0)
3144 {
3145 XSetFont (x_current_display, s->display.x->normal_gc,
3146 s->display.x->font->fid);
3147 XSetFont (x_current_display, s->display.x->reverse_gc,
3148 s->display.x->font->fid);
3149 XSetFont (x_current_display, s->display.x->cursor_gc,
3150 s->display.x->font->fid);
3151
3152 x_set_window_size (s, s->width, s->height);
3153 }
3154
3155 return 0;
3156}
3157#else
3158x_new_font (s, newname)
3159 struct screen *s;
3160 register char *newname;
3161{
3162 FONT_TYPE *temp;
3163 int mask;
3164
3165 temp = XGetFont (newname);
3166 if (temp == (FONT_TYPE *) 0)
3167 return 1;
3168
3169 if (s->display.x->font)
3170 XLoseFont (s->display.x->font);
3171
3172 s->display.x->font = temp;
3173
3174 if (s->display.x->window_desc != 0)
3175 x_set_window_size (s, s->width, s->height);
3176
3177 return 0;
3178}
3179#endif
3180\f
3181x_calc_absolute_position (s)
3182 struct screen *s;
3183{
3184#ifdef HAVE_X11
3185 if (s->display.x->left_pos < 0)
3186 s->display.x->left_pos
3187 = XINT (x_screen_width) - PIXEL_WIDTH (s) + s->display.x->left_pos;
3188
3189 if (s->display.x->top_pos < 0)
3190 s->display.x->top_pos
3191 = XINT (x_screen_height) - PIXEL_HEIGHT (s) + s->display.x->top_pos;
3192#else /* X10 */
3193 WINDOWINFO_TYPE parentinfo;
3194
3195 XGetWindowInfo (s->display.x->window_desc, &parentinfo);
3196
3197 if (s->display.x->left_pos < 0)
3198 s->display.x->left_pos = parentinfo.width + (s->display.x->left_pos + 1)
3199 - PIXEL_WIDTH (s) - 2 * s->display.x->internal_border_width;
3200
3201 if (s->display.x->top_pos < 0)
3202 s->display.x->top_pos = parentinfo.height + (s->display.x->top_pos + 1)
3203 - PIXEL_HEIGHT (s) - 2 * s->display.x->internal_border_width;
3204#endif /* X10 */
3205}
3206
3207x_set_offset (s, xoff, yoff)
3208 struct screen *s;
3209 register int xoff, yoff;
3210{
3211 s->display.x->top_pos = yoff;
3212 s->display.x->left_pos = xoff;
3213 x_calc_absolute_position (s);
3214
3215 BLOCK_INPUT;
3216 XMoveWindow (XDISPLAY s->display.x->window_desc,
3217 s->display.x->left_pos, s->display.x->top_pos);
3218#ifdef HAVE_X11
3219 x_wm_set_size_hint (s, 0);
3220#endif
3221 UNBLOCK_INPUT;
3222}
3223
3224/* Call this to change the size of screen S's x-window. */
3225
3226x_set_window_size (s, cols, rows)
3227 struct screen *s;
3228 register int cols, rows;
3229{
3230 int pixelwidth, pixelheight;
3231 int mask;
3232 int ibw = s->display.x->internal_border_width;
3233
3234 BLOCK_INPUT;
3235
3236 /* ??? Who DOES worry about minimum reasonable sizes? */
3237 pixelwidth = (cols * FONT_WIDTH (s->display.x->font) + 2 * ibw
3238 + s->display.x->v_scrollbar_width);
3239 pixelheight = (rows * FONT_HEIGHT (s->display.x->font) + 2 * ibw
3240 + s->display.x->h_scrollbar_height);
3241
3242#ifdef HAVE_X11
3243 x_wm_set_size_hint (s, 0);
3244#endif /* HAVE_X11 */
3245 XChangeWindowSize (s->display.x->window_desc, pixelwidth, pixelheight);
3246 XFlushQueue ();
3247 UNBLOCK_INPUT;
3248}
3249
3250#ifndef HAVE_X11
3251x_set_resize_hint (s)
3252 struct screen *s;
3253{
3254
3255 XSetResizeHint (s->display.x->window_desc, 2 * s->display.x->internal_border_width,
3256 2 * s->display.x->internal_border_width,
3257 FONT_WIDTH (s->display.x->font), FONT_HEIGHT (s->display.x->font));
3258}
3259#endif /* not HAVE_X11 */
3260\f
3261
3262x_set_mouse_position (s, x, y)
3263 struct screen *s;
3264 int x, y;
3265{
3266 int pix_x, pix_y;
3267
3268 x_raise_screen (s);
3269
3270 if (x < 0)
3271 pix_x = (SCREEN_WIDTH (s)
3272 * FONT_WIDTH (s->display.x->font)
3273 + 2 * s->display.x->internal_border_width
3274 + s->display.x->v_scrollbar_width) / 2;
3275 else
3276 pix_x = x * FONT_WIDTH (s->display.x->font) + 2; /* add 2 pixels to each
3277 dimension to move the
3278 mouse into the char
3279 cell */
3280
3281 if (y < 0)
3282 pix_y = (SCREEN_HEIGHT (s)
3283 * FONT_HEIGHT (s->display.x->font)
3284 + 2 * s->display.x->internal_border_width
3285 + s->display.x->h_scrollbar_height) / 2;
3286 else
3287 pix_y = y * FONT_HEIGHT (s->display.x->font) + 2;
3288
3289 BLOCK_INPUT;
3290 x_mouse_x = x;
3291 x_mouse_y = y;
3292
3293 XWarpMousePointer (s->display.x->window_desc, pix_x, pix_y);
3294 UNBLOCK_INPUT;
3295}
3296
3297#ifdef HAVE_X11
3298x_focus_on_screen (s)
3299 struct screen *s;
3300{
3301 x_raise_screen (s);
6d4238f3
JB
3302#if 0
3303 /* I don't think that the ICCCM allows programs to do things like this
3304 without the interaction of the window manager. Whatever you end up
3305 doing with this code, do it to x_unfocus_screen too. */
dc6f92b8
JB
3306 XSetInputFocus (x_current_display, s->display.x->window_desc,
3307 RevertToPointerRoot, CurrentTime);
6d4238f3 3308#endif
dc6f92b8
JB
3309}
3310
3311x_unfocus_screen (s)
3312 struct screen *s;
3313{
6d4238f3
JB
3314#if 0
3315 /* Look at the remarks in x_focus_on_screen. */
dc6f92b8
JB
3316 if (x_focus_screen == s)
3317 XSetInputFocus (x_current_display, PointerRoot,
3318 RevertToPointerRoot, CurrentTime);
6d4238f3 3319#endif
dc6f92b8
JB
3320}
3321
3322#endif
3323
3324/* Raise screen S. */
3325
3326x_raise_screen (s)
3327 struct screen *s;
3328{
3329 if (s->visible)
3330 {
3331 BLOCK_INPUT;
3332 XRaiseWindow (XDISPLAY s->display.x->window_desc);
3333 XFlushQueue ();
3334 UNBLOCK_INPUT;
3335 }
3336}
3337
3338/* Lower screen S. */
3339
3340x_lower_screen (s)
3341 struct screen *s;
3342{
3343 if (s->visible)
3344 {
3345 BLOCK_INPUT;
3346 XLowerWindow (XDISPLAY s->display.x->window_desc);
3347 XFlushQueue ();
3348 UNBLOCK_INPUT;
3349 }
3350}
3351
3352/* Change from withdrawn state to mapped state. */
3353
3354x_make_screen_visible (s)
3355 struct screen *s;
3356{
3357 int mask;
3358
dc6f92b8 3359 BLOCK_INPUT;
dc6f92b8 3360
90e65f07
JB
3361 if (! SCREEN_VISIBLE_P (s))
3362 {
3363#ifdef HAVE_X11
3364 if (! EQ (Vx_no_window_manager, Qt))
3365 x_wm_set_window_state (s, NormalState);
dc6f92b8 3366
90e65f07
JB
3367 XMapWindow (XDISPLAY s->display.x->window_desc);
3368 if (s->display.x->v_scrollbar != 0 || s->display.x->h_scrollbar != 0)
3369 XMapSubwindows (x_current_display, s->display.x->window_desc);
dc6f92b8 3370#else
90e65f07
JB
3371 XMapWindow (XDISPLAY s->display.x->window_desc);
3372 if (s->display.x->icon_desc != 0)
3373 XUnmapWindow (s->display.x->icon_desc);
dc6f92b8 3374
90e65f07
JB
3375 /* Handled by the MapNotify event for X11 */
3376 s->visible = 1;
3377 s->iconified = 0;
dc6f92b8 3378
90e65f07
JB
3379 /* NOTE: this may cause problems for the first screen. */
3380 XTcursor_to (0, 0);
3381#endif /* not HAVE_X11 */
3382 }
dc6f92b8 3383
dc6f92b8 3384 XFlushQueue ();
90e65f07 3385
dc6f92b8
JB
3386 UNBLOCK_INPUT;
3387}
3388
3389/* Change from mapped state to withdrawn state. */
3390
3391x_make_screen_invisible (s)
3392 struct screen *s;
3393{
3394 int mask;
3395
3396 if (! s->visible)
3397 return;
3398
3399 BLOCK_INPUT;
3400#ifdef HAVE_X11
3401#if 0
3402 if (! EQ (Vx_no_window_manager, Qt))
3403 {
3404 XUnmapEvent unmap;
3405
3406 unmap.type = UnmapNotify;
3407 unmap.window = s->display.x->window_desc;
3408 unmap.event = DefaultRootWindow (x_current_display);
3409 unmap.from_configure = False;
3410 XSendEvent (x_current_display, DefaultRootWindow (x_current_display),
3411 False, SubstructureRedirectMask|SubstructureNotifyMask,
3412 &unmap);
3413 }
3414
3415 /* The new function below does the same as the above code, plus unmapping
3416 the window. Sending the event without actually unmapping can make
3417 the window manager start ignoring the window (i.e., no more title bar,
3418 icon manager stuff.) */
3419#endif
3420
3421 /* New function available with R4 */
3422 if (! XWithdrawWindow (x_current_display, s->display.x->window_desc,
3423 DefaultScreen (x_current_display)))
3424 {
3425 UNBLOCK_INPUT_RESIGNAL;
3426 error ("Can't notify window manager of iconification.");
3427 }
3428
3429#else
3430 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3431
3432 s->visible = 0; /* Handled by the UnMap event for X11 */
3433 if (s->display.x->icon_desc != 0)
3434 XUnmapWindow (XDISPLAY s->display.x->icon_desc);
3435#endif /* not HAVE_X11 */
3436
3437 XFlushQueue ();
3438 UNBLOCK_INPUT;
3439}
3440
3441 /* Window manager communication. Created in Fx_open_connection. */
3442extern Atom Xatom_wm_change_state;
3443
3444/* Change window state from mapped to iconified. */
3445
3446x_iconify_screen (s)
3447 struct screen *s;
3448{
3449 int mask;
3450
3451 if (s->iconified)
3452 return;
3453
3454 BLOCK_INPUT;
3455
3456#ifdef HAVE_X11
3457 if (! EQ (Vx_no_window_manager, Qt))
3458 if (! XIconifyWindow (x_current_display, s->display.x->window_desc,
3459 DefaultScreen (x_current_display)))
3460 {
3461 UNBLOCK_INPUT_RESIGNAL;
3462 error ("Can't notify window manager of iconification.");
3463 }
3464
3465 s->iconified = 1;
3466
3467#if 0
3468 {
3469 XClientMessageEvent message;
3470
3471 message.window = s->display.x->window_desc;
3472 message.type = ClientMessage;
3473 message.message_type = Xatom_wm_change_state;
3474 message.format = 32;
3475 message.data.l[0] = IconicState;
3476
3477 if (! XSendEvent (x_current_display,
3478 DefaultRootWindow (x_current_display),
3479 False,
3480 SubstructureRedirectMask | SubstructureNotifyMask,
3481 &message))
3482 {
3483 UNBLOCK_INPUT_RESIGNAL;
3484 error ("Can't notify window manager of iconification.");
3485 }
3486 }
3487#endif
3488#else /* X10 */
3489 XUnmapWindow (XDISPLAY s->display.x->window_desc);
3490
3491 s->visible = 0; /* Handled in the UnMap event for X11. */
3492 if (s->display.x->icon_desc != 0)
3493 {
3494 XMapWindow (XDISPLAY s->display.x->icon_desc);
3495 refreshicon (s);
3496 }
3497#endif /* X10 */
3498
3499 XFlushQueue ();
3500 UNBLOCK_INPUT;
3501}
3502
3503/* Destroy the X window of screen S.
3504 DISPL is the former s->display (since s->display
3505 has already been nulled out). */
3506
3507x_destroy_window (s, displ)
3508 struct screen *s;
3509 union display displ;
3510{
3511 int mask;
3512
3513 BLOCK_INPUT;
3514 if (displ.x->icon_desc != 0)
3515 XDestroyWindow (XDISPLAY displ.x->icon_desc);
3516 XDestroyWindow (XDISPLAY displ.x->window_desc);
3517 XFlushQueue ();
3518 UNBLOCK_INPUT;
3519
3520 free (displ.x);
3521 if (s == x_focus_screen)
3522 x_focus_screen = 0;
6d4238f3
JB
3523 if (s == x_highlight_screen)
3524 x_highlight_screen = 0;
dc6f92b8
JB
3525}
3526\f
3527#ifndef HAVE_X11
3528
3529/* Manage event queues.
3530
3531 This code is only used by the X10 support.
3532
3533 We cannot leave events in the X queue and get them when we are ready
3534 because X does not provide a subroutine to get only a certain kind
3535 of event but not block if there are no queued events of that kind.
3536
3537 Therefore, we must examine events as they come in and copy events
3538 of certain kinds into our private queues.
3539
3540 All ExposeRegion events are put in x_expose_queue.
3541 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
3542
3543
3544/* Write the event *P_XREP into the event queue *QUEUE.
3545 If the queue is full, do nothing, but return nonzero. */
3546
3547int
3548enqueue_event (p_xrep, queue)
3549 register XEvent *p_xrep;
3550 register struct event_queue *queue;
3551{
3552 int newindex = queue->windex + 1;
3553 if (newindex == EVENT_BUFFER_SIZE)
3554 newindex = 0;
3555 if (newindex == queue->rindex)
3556 return -1;
3557 queue->xrep[queue->windex] = *p_xrep;
3558 queue->windex = newindex;
3559 return 0;
3560}
3561
3562/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
3563 If *QUEUE is empty, do nothing and return 0. */
3564
3565int
3566dequeue_event (p_xrep, queue)
3567 register XEvent *p_xrep;
3568 register struct event_queue *queue;
3569{
3570 if (queue->windex == queue->rindex)
3571 return 0;
3572 *p_xrep = queue->xrep[queue->rindex++];
3573 if (queue->rindex == EVENT_BUFFER_SIZE)
3574 queue->rindex = 0;
3575 return 1;
3576}
3577
3578/* Return the number of events buffered in *QUEUE. */
3579
3580int
3581queue_event_count (queue)
3582 register struct event_queue *queue;
3583{
3584 int tem = queue->windex - queue->rindex;
3585 if (tem >= 0)
3586 return tem;
3587 return EVENT_BUFFER_SIZE + tem;
3588}
3589
3590/* Return nonzero if mouse input is pending. */
3591
3592int
3593mouse_event_pending_p ()
3594{
3595 return queue_event_count (&x_mouse_queue);
3596}
3597#endif
3598\f
3599#ifdef HAVE_X11
3600
3601x_wm_set_size_hint (s, prompting)
3602 struct screen *s;
3603 long prompting;
3604{
3605 XSizeHints size_hints;
3606 Window window = s->display.x->window_desc;
3607
3608 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
daa37602
JB
3609#ifdef PBaseSize
3610 size_hints.flags |= PBaseSize;
3611#endif
dc6f92b8
JB
3612
3613 flexlines = s->height;
3614
3615 size_hints.x = s->display.x->left_pos;
3616 size_hints.y = s->display.x->top_pos;
3617 size_hints.height = PIXEL_HEIGHT (s);
3618 size_hints.width = PIXEL_WIDTH (s);
3619 size_hints.width_inc = FONT_WIDTH (s->display.x->font);
3620 size_hints.height_inc = FONT_HEIGHT (s->display.x->font);
3621 size_hints.base_width = (2 * s->display.x->internal_border_width)
3622 + s->display.x->v_scrollbar_width;
3623 size_hints.base_height = (2 * s->display.x->internal_border_width)
3624 + s->display.x->h_scrollbar_height;
3625 size_hints.min_width = size_hints.base_width + size_hints.width_inc;
3626 size_hints.min_height = size_hints.base_height + size_hints.height_inc;
3627 size_hints.max_width = x_screen_width
3628 - ((2 * s->display.x->internal_border_width)
3629 + s->display.x->v_scrollbar_width);
3630 size_hints.max_height = x_screen_height
3631 - ((2 * s->display.x->internal_border_width)
3632 + s->display.x->h_scrollbar_height);
3633
3634 if (prompting)
3635 size_hints.flags |= prompting;
3636 else
3637 {
3638 XSizeHints hints; /* Sometimes I hate X Windows... */
3639
3640 XGetNormalHints (x_current_display, window, &hints);
3641 if (hints.flags & PSize)
3642 size_hints.flags |= PSize;
3643 if (hints.flags & PPosition)
3644 size_hints.flags |= PPosition;
3645 if (hints.flags & USPosition)
3646 size_hints.flags |= USPosition;
3647 if (hints.flags & USSize)
3648 size_hints.flags |= USSize;
3649 }
3650
3651#if 0 /* R3 */
3652 XSetNormalHints (x_current_display, window, &size_hints);
3653#endif
3654 XSetWMNormalHints (x_current_display, window, &size_hints);
3655}
3656
3657/* Used for IconicState or NormalState */
3658x_wm_set_window_state (s, state)
3659 struct screen *s;
3660 int state;
3661{
3662 XWMHints wm_hints;
3663 Window window = s->display.x->window_desc;
3664
3665 wm_hints.flags = StateHint;
3666 wm_hints.initial_state = state;
3667 XSetWMHints (x_current_display, window, &wm_hints);
3668}
3669
3670x_wm_set_icon_pixmap (s, icon_pixmap)
3671 struct screen *s;
3672 Pixmap icon_pixmap;
3673{
3674 XWMHints wm_hints;
3675 Window window = s->display.x->window_desc;
3676
3677 wm_hints.flags = IconPixmapHint;
3678 wm_hints.icon_pixmap = icon_pixmap;
3679 XSetWMHints (x_current_display, window, &wm_hints);
3680}
3681
3682x_wm_set_icon_position (s, icon_x, icon_y)
3683 struct screen *s;
3684 int icon_x, icon_y;
3685{
3686 XWMHints wm_hints;
3687 Window window = s->display.x->window_desc;
3688
3689 wm_hints.flags = IconPositionHint;
3690 wm_hints.icon_x = icon_x;
3691 wm_hints.icon_y = icon_y;
3692 XSetWMHints (x_current_display, window, &wm_hints);
3693}
3694
3695\f
dc6f92b8
JB
3696void
3697x_term_init (display_name)
3698 char *display_name;
3699{
3700 Lisp_Object screen;
3701 char *defaultvalue;
3702#ifdef F_SETOWN
3703 extern int old_fcntl_owner;
3704#endif
6d4238f3
JB
3705
3706 x_focus_screen = x_highlight_screen = 0;
dc6f92b8
JB
3707
3708 x_current_display = XOpenDisplay (display_name);
3709 if (x_current_display == 0)
3710 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
3711 display_name);
3712
3713#ifdef HAVE_X11
3714 {
60fb3ee1
JB
3715 int hostname_size = MAXHOSTNAMELEN + 1;
3716
3717 hostname = (char *) xmalloc (hostname_size);
3718
dc6f92b8
JB
3719#if 0
3720 XSetAfterFunction (x_current_display, x_trace_wire);
3721#endif
3722
55123275 3723 invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
60fb3ee1
JB
3724
3725 /* Try to get the host name; if the buffer is too short, try
3726 again. Apparently, the only indication gethostname gives of
3727 whether the buffer was large enough is the presence or absence
3728 of a '\0' in the string. Eech. */
3729 for (;;)
3730 {
3731 gethostname (hostname, hostname_size - 1);
3732 hostname[hostname_size - 1] = '\0';
3733
3734 /* Was the buffer large enough for gethostname to store the '\0'? */
3735 if (strlen (hostname) < hostname_size - 1)
3736 break;
3737
3738 hostname_size <<= 1;
3739 hostname = (char *) xrealloc (hostname, hostname_size);
3740 }
3741 x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
3742 + strlen (hostname)
3743 + 2);
3744 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
dc6f92b8
JB
3745 }
3746
3747 dup2 (ConnectionNumber (x_current_display), 0);
6d4238f3
JB
3748
3749#ifndef SYSV_STREAMS
3750 /* Streams somehow keeps track of which descriptor number
3751 is being used to talk to X. So it is not safe to substitute
3752 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
dc6f92b8 3753 close (ConnectionNumber (x_current_display));
6d4238f3
JB
3754 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
3755 * check the def of the macro;
3756 * it is a genuine lvalue */
3757#endif /* not SYSV_STREAMS */
3758
dc6f92b8
JB
3759#endif /* HAVE_X11 */
3760
3761#ifdef F_SETOWN
3762 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
3763#ifdef F_SETOWN_SOCK_NEG
3764 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
3765#else
3766 fcntl (0, F_SETOWN, getpid ());
3767#endif /* F_SETOWN_SOCK_NEG */
3768#endif /* F_SETOWN */
3769
3770#ifdef SIGIO
3771 init_sigio ();
3772#endif
3773
3774 /* Must use interrupt input because we cannot otherwise
3775 arrange for C-g to be noticed immediately.
3776 We cannot connect it to SIGINT. */
3777 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3778
3779 expose_all_windows = 0;
3780
3781 clear_screen_hook = XTclear_screen;
3782 clear_end_of_line_hook = XTclear_end_of_line;
3783 ins_del_lines_hook = XTins_del_lines;
3784 change_line_highlight_hook = XTchange_line_highlight;
3785 insert_glyphs_hook = XTinsert_glyphs;
3786 write_glyphs_hook = XTwrite_glyphs;
3787 delete_glyphs_hook = XTdelete_glyphs;
3788 ring_bell_hook = XTring_bell;
3789 reset_terminal_modes_hook = XTreset_terminal_modes;
3790 set_terminal_modes_hook = XTset_terminal_modes;
3791 update_begin_hook = XTupdate_begin;
3792 update_end_hook = XTupdate_end;
3793 set_terminal_window_hook = XTset_terminal_window;
3794 read_socket_hook = XTread_socket;
3795 cursor_to_hook = XTcursor_to;
3796 reassert_line_highlight_hook = XTreassert_line_highlight;
6d4238f3 3797 screen_rehighlight_hook = XTscreen_rehighlight;
90e65f07 3798 mouse_position_hook = XTmouse_position;
dc6f92b8
JB
3799
3800 scroll_region_ok = 1; /* we'll scroll partial screens */
3801 char_ins_del_ok = 0; /* just as fast to write the line */
3802 line_ins_del_ok = 1; /* we'll just blt 'em */
3803 fast_clear_end_of_line = 1; /* X does this well */
3804 memory_below_screen = 0; /* we don't remember what scrolls
3805 off the bottom */
3806 baud_rate = 19200;
3807
dc6f92b8
JB
3808 XHandleError (x_error_handler);
3809 XHandleIOError (x_error_handler);
3810
3811 /* Disable Window Change signals; they are handled by X events. */
3812#ifdef SIGWINCH
3813 signal (SIGWINCH, SIG_DFL);
3814#endif /* SIGWINCH */
3815
4746118a 3816 signal (SIGPIPE, x_death_handler);
dc6f92b8 3817}
55123275
JB
3818
3819void
3820syms_of_xterm ()
3821{
3822 staticpro (&invocation_name);
3823 invocation_name = Qnil;
55123275 3824}
dc6f92b8
JB
3825#endif /* HAVE_X11 */
3826#endif /* HAVE_X_WINDOWS */