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