(Fdelete_window): Handle deleting a parent of the selected window.
[bpt/emacs.git] / src / xterm.c
... / ...
CommitLineData
1/* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 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 2, 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#define NEW_SELECTIONS
29
30/* On 4.3 these lose if they come after xterm.h. */
31/* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32/* Putting these at the beginning seems to be standard for other .c files. */
33#include <stdio.h>
34#include <signal.h>
35
36#include "config.h"
37
38#ifdef HAVE_X_WINDOWS
39
40#include "lisp.h"
41#include "blockinput.h"
42
43/* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
45#include "xterm.h"
46#include <X11/cursorfont.h>
47
48#ifndef USG
49/* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
51#ifndef makedev
52#include <sys/types.h>
53#endif /* makedev */
54#endif /* USG */
55
56#ifdef BSD
57#include <sys/ioctl.h>
58#include <strings.h>
59#else /* ! defined (BSD) */
60#ifndef VMS
61#include <string.h>
62#endif
63#endif /* ! defined (BSD) */
64
65#include "systty.h"
66#include "systime.h"
67
68#include <fcntl.h>
69#include <ctype.h>
70#include <errno.h>
71#include <setjmp.h>
72#include <sys/stat.h>
73#include <sys/param.h>
74
75#include "dispextern.h"
76#include "termhooks.h"
77#include "termopts.h"
78#include "termchar.h"
79#if 0
80#include "sink.h"
81#include "sinkmask.h"
82#endif /* ! 0 */
83#include "gnu.h"
84#include "frame.h"
85#include "disptab.h"
86#include "buffer.h"
87#include "window.h"
88
89#ifdef HAVE_X11
90#define XMapWindow XMapRaised /* Raise them when mapping. */
91#else /* ! defined (HAVE_X11) */
92#include <X/Xkeyboard.h>
93/*#include <X/Xproto.h> */
94#endif /* ! defined (HAVE_X11) */
95
96/* For sending Meta-characters. Do we need this? */
97#define METABIT 0200
98
99#define min(a,b) ((a)<(b) ? (a) : (b))
100#define max(a,b) ((a)>(b) ? (a) : (b))
101
102/* Nonzero means we must reprint all windows
103 because 1) we received an ExposeWindow event
104 or 2) we received too many ExposeRegion events to record.
105
106 This is never needed under X11. */
107static int expose_all_windows;
108
109/* Nonzero means we must reprint all icon windows. */
110
111static int expose_all_icons;
112
113#ifndef HAVE_X11
114/* ExposeRegion events, when received, are copied into this queue
115 for later processing. */
116
117static struct event_queue x_expose_queue;
118
119/* ButtonPressed and ButtonReleased events, when received,
120 are copied into this queue for later processing. */
121
122struct event_queue x_mouse_queue;
123#endif /* HAVE_X11 */
124
125#if defined (SIGIO) && defined (FIONREAD)
126int BLOCK_INPUT_mask;
127#endif /* ! defined (SIGIO) && defined (FIONREAD) */
128
129/* The id of a bitmap used for icon windows.
130 One such map is shared by all Emacs icon windows.
131 This is zero if we have not yet had a need to create the bitmap. */
132
133static Bitmap icon_bitmap;
134
135/* Font used for text icons. */
136
137static FONT_TYPE *icon_font_info;
138
139/* Stuff for dealing with the main icon title. */
140
141extern Lisp_Object Vcommand_line_args;
142char *hostname, *x_id_name;
143
144/* This is the X connection that we are using. */
145
146Display *x_current_display;
147
148/* The cursor to use for vertical scroll bars on x_current_display. */
149static Cursor x_vertical_scroll_bar_cursor;
150
151/* Frame being updated by update_frame. This is declared in term.c.
152 This is set by update_begin and looked at by all the
153 XT functions. It is zero while not inside an update.
154 In that case, the XT functions assume that `selected_frame'
155 is the frame to apply to. */
156extern struct frame *updating_frame;
157
158/* The frame (if any) which has the X window that has keyboard focus.
159 Zero if none. This is examined by Ffocus_frame in frame.c. Note
160 that a mere EnterNotify event can set this; if you need to know the
161 last frame specified in a FocusIn or FocusOut event, use
162 x_focus_event_frame. */
163struct frame *x_focus_frame;
164
165/* The last frame mentioned in a FocusIn or FocusOut event. This is
166 separate from x_focus_frame, because whether or not LeaveNotify
167 events cause us to lose focus depends on whether or not we have
168 received a FocusIn event for it. */
169struct frame *x_focus_event_frame;
170
171/* The frame which currently has the visual highlight, and should get
172 keyboard input (other sorts of input have the frame encoded in the
173 event). It points to the X focus frame's selected window's
174 frame. It differs from x_focus_frame when we're using a global
175 minibuffer. */
176static struct frame *x_highlight_frame;
177
178/* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
179 mouse is moved to inside of frame when frame is de-iconified. */
180
181static int warp_mouse_on_deiconify;
182
183/* During an update, maximum vpos for ins/del line operations to affect. */
184
185static int flexlines;
186
187/* During an update, nonzero if chars output now should be highlighted. */
188
189static int highlight;
190
191/* Nominal cursor position -- where to draw output.
192 During an update, these are different from the cursor-box position. */
193
194static int curs_x;
195static int curs_y;
196
197#ifdef HAVE_X11
198/* `t' if a mouse button is depressed. */
199
200extern Lisp_Object Vmouse_depressed;
201
202/* Tells if a window manager is present or not. */
203
204extern Lisp_Object Vx_no_window_manager;
205
206/* Timestamp that we requested selection data was made. */
207extern Time requestor_time;
208
209/* ID of the window requesting selection data. */
210extern Window requestor_window;
211
212/* Nonzero enables some debugging for the X interface code. */
213extern int _Xdebug;
214
215#else /* ! defined (HAVE_X11) */
216
217/* Bit patterns for the mouse cursor. */
218
219short MouseCursor[] = {
220 0x0000, 0x0008, 0x0018, 0x0038,
221 0x0078, 0x00f8, 0x01f8, 0x03f8,
222 0x07f8, 0x00f8, 0x00d8, 0x0188,
223 0x0180, 0x0300, 0x0300, 0x0000};
224
225short MouseMask[] = {
226 0x000c, 0x001c, 0x003c, 0x007c,
227 0x00fc, 0x01fc, 0x03fc, 0x07fc,
228 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
229 0x03cc, 0x0780, 0x0780, 0x0300};
230
231static short grey_bits[] = {
232 0x0005, 0x000a, 0x0005, 0x000a};
233
234static Pixmap GreyPixmap = 0;
235#endif /* ! defined (HAVE_X11) */
236
237/* From time to time we get info on an Emacs window, here. */
238
239static WINDOWINFO_TYPE windowinfo;
240
241extern int errno;
242
243/* A mask of extra modifier bits to put into every keyboard char. */
244extern int extra_keyboard_modifiers;
245
246extern Display *XOpenDisplay ();
247extern Window XCreateWindow ();
248
249extern Cursor XCreateCursor ();
250extern FONT_TYPE *XOpenFont ();
251
252static void flashback ();
253
254#ifndef HAVE_X11
255static void dumpqueue ();
256#endif /* HAVE_X11 */
257
258void dumpborder ();
259static int XTcursor_to ();
260static int XTclear_end_of_line ();
261
262\f
263/* Starting and ending updates.
264
265 These hooks are called by update_frame at the beginning and end
266 of a frame update. We record in `updating_frame' the identity
267 of the frame being updated, so that the XT... functions do not
268 need to take a frame as argument. Most of the XT... functions
269 should never be called except during an update, the only exceptions
270 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
271
272extern int mouse_track_top, mouse_track_left, mouse_track_width;
273
274static
275XTupdate_begin (f)
276 struct frame *f;
277{
278 int mask;
279
280 if (f == 0)
281 abort ();
282
283 flexlines = f->height;
284 highlight = 0;
285
286 BLOCK_INPUT;
287#ifndef HAVE_X11
288 dumpqueue ();
289#endif /* HAVE_X11 */
290 UNBLOCK_INPUT;
291}
292
293#ifndef HAVE_X11
294static void x_do_pending_expose ();
295#endif
296
297static
298XTupdate_end (f)
299 struct frame *f;
300{
301 int mask;
302
303 if (updating_frame == 0
304 || updating_frame != f)
305 abort ();
306
307 BLOCK_INPUT;
308#ifndef HAVE_X11
309 dumpqueue ();
310 x_do_pending_expose ();
311#endif /* HAVE_X11 */
312
313 x_display_cursor (f, 1);
314
315 XFlushQueue ();
316 UNBLOCK_INPUT;
317}
318\f
319/* External interface to control of standout mode.
320 Call this when about to modify line at position VPOS
321 and not change whether it is highlighted. */
322
323XTreassert_line_highlight (new, vpos)
324 int new, vpos;
325{
326 highlight = new;
327}
328
329/* Call this when about to modify line at position VPOS
330 and change whether it is highlighted. */
331
332static
333XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
334 int new_highlight, vpos, first_unused_hpos;
335{
336 highlight = new_highlight;
337 XTcursor_to (vpos, 0);
338 XTclear_end_of_line (updating_frame->width);
339}
340
341/* This is used when starting Emacs and when restarting after suspend.
342 When starting Emacs, no X window is mapped. And nothing must be done
343 to Emacs's own window if it is suspended (though that rarely happens). */
344
345static
346XTset_terminal_modes ()
347{
348}
349
350/* This is called when exiting or suspending Emacs.
351 Exiting will make the X-windows go away, and suspending
352 requires no action. */
353
354static
355XTreset_terminal_modes ()
356{
357/* XTclear_frame (); */
358}
359\f
360/* Set the nominal cursor position of the frame.
361 This is where display update commands will take effect.
362 This does not affect the place where the cursor-box is displayed. */
363
364static int
365XTcursor_to (row, col)
366 register int row, col;
367{
368 int mask;
369 int orow = row;
370
371 curs_x = col;
372 curs_y = row;
373
374 if (updating_frame == 0)
375 {
376 BLOCK_INPUT;
377 x_display_cursor (selected_frame, 1);
378 XFlushQueue ();
379 UNBLOCK_INPUT;
380 }
381}
382\f
383/* Display a sequence of N glyphs found at GP.
384 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
385 HL is 1 if this text is highlighted, 2 if the cursor is on it.
386
387 FONT is the default font to use (for glyphs whose font-code is 0).
388
389 Since the display generation code is responsible for calling
390 compute_char_face and compute_glyph_face on everything it puts in
391 the display structure, we can assume that the face code on each
392 glyph is a valid index into FRAME_FACES (f), and the one to which
393 we can actually apply intern_face. */
394
395#if 1
396/* This is the multi-face code. */
397
398static void
399dumpglyphs (f, left, top, gp, n, hl)
400 struct frame *f;
401 int left, top;
402 register GLYPH *gp; /* Points to first GLYPH. */
403 register int n; /* Number of glyphs to display. */
404 int hl;
405{
406 /* Holds characters to be displayed. */
407 char *buf = (char *) alloca (f->width * sizeof (*buf));
408 register char *cp; /* Steps through buf[]. */
409 register int tlen = GLYPH_TABLE_LENGTH;
410 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
411 Window window = FRAME_X_WINDOW (f);
412
413 while (n > 0)
414 {
415 /* Get the face-code of the next GLYPH. */
416 int cf, len;
417 int g = *gp;
418
419 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
420 cf = GLYPH_FACE (g);
421
422 /* Find the run of consecutive glyphs with the same face-code.
423 Extract their character codes into BUF. */
424 cp = buf;
425 while (n > 0)
426 {
427 g = *gp;
428 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
429 if (GLYPH_FACE (g) != cf)
430 break;
431
432 *cp++ = GLYPH_CHAR (g);
433 --n;
434 ++gp;
435 }
436
437 /* LEN gets the length of the run. */
438 len = cp - buf;
439
440 /* Now output this run of chars, with the font and pixel values
441 determined by the face code CF. */
442 {
443 struct face *face = FRAME_DEFAULT_FACE (f);
444 FONT_TYPE *font = FACE_FONT (face);
445 GC gc = FACE_GC (face);
446 int defaulted = 1;
447 int gc_temporary = 0;
448
449 /* First look at the face of the text itself. */
450 if (cf != 0)
451 {
452 /* The face codes on the glyphs must be valid indices into the
453 frame's face table. */
454 if (cf < 0 || cf >= FRAME_N_FACES (f))
455 abort ();
456
457 if (cf == 1)
458 face = FRAME_MODE_LINE_FACE (f);
459 else
460 face = intern_face (f, FRAME_FACES (f) [cf]);
461 font = FACE_FONT (face);
462 gc = FACE_GC (face);
463 defaulted = 0;
464 }
465
466 /* Then comes the distinction between modeline and normal text. */
467 else if (hl == 0)
468 ;
469 else if (hl == 1)
470 {
471 face = FRAME_MODE_LINE_FACE (f);
472 font = FACE_FONT (face);
473 gc = FACE_GC (face);
474 defaulted = 0;
475 }
476
477#define FACE_DEFAULT (~0)
478
479 /* Now override that if the cursor's on this character. */
480 if (hl == 2)
481 {
482 if (defaulted
483 || !face->font
484 || (int) face->font == FACE_DEFAULT)
485 {
486 gc = f->display.x->cursor_gc;
487 }
488 /* Cursor on non-default face: must merge. */
489 else
490 {
491 XGCValues xgcv;
492 unsigned long mask;
493
494 xgcv.background = f->display.x->cursor_pixel;
495 xgcv.foreground = f->display.x->cursor_foreground_pixel;
496 xgcv.font = face->font->fid;
497 xgcv.graphics_exposures = 0;
498 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
499 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
500 mask, &xgcv);
501#if 0
502 if (face->stipple && face->stipple != FACE_DEFAULT)
503 XSetStipple (x_current_display, gc, face->stipple);
504#endif
505 gc_temporary = 1;
506 }
507 }
508
509 if ((int) font == FACE_DEFAULT)
510 font = f->display.x->font;
511
512 XDrawImageString (x_current_display, window, gc,
513 left, top + FONT_BASE (font), buf, len);
514
515 if (gc_temporary)
516 XFreeGC (x_current_display, gc);
517
518 /* We should probably check for XA_UNDERLINE_POSITION and
519 XA_UNDERLINE_THICKNESS properties on the font, but let's
520 just get the thing working, and come back to that. */
521 {
522 int underline_position = 1;
523
524 if (font->descent <= underline_position)
525 underline_position = font->descent - 1;
526
527 if (face->underline)
528 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
529 FACE_GC (face),
530 left, (top
531 + FONT_BASE (font)
532 + underline_position),
533 len * FONT_WIDTH (font), 1);
534 }
535
536 left += len * FONT_WIDTH (font);
537 }
538 }
539}
540#endif /* 1 */
541
542#if 0
543/* This is the old single-face code. */
544
545static void
546dumpglyphs (f, left, top, gp, n, hl, font)
547 struct frame *f;
548 int left, top;
549 register GLYPH *gp; /* Points to first GLYPH. */
550 register int n; /* Number of glyphs to display. */
551 int hl;
552 FONT_TYPE *font;
553{
554 register int len;
555 Window window = FRAME_X_WINDOW (f);
556 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
557 : (hl ? f->display.x->reverse_gc
558 : f->display.x->normal_gc));
559
560 if (sizeof (GLYPH) == sizeof (XChar2b))
561 XDrawImageString16 (x_current_display, window, drawing_gc,
562 left, top + FONT_BASE (font), (XChar2b *) gp, n);
563 else if (sizeof (GLYPH) == sizeof (unsigned char))
564 XDrawImageString (x_current_display, window, drawing_gc,
565 left, top + FONT_BASE (font), (char *) gp, n);
566 else
567 /* What size of glyph ARE you using? And does X have a function to
568 draw them? */
569 abort ();
570}
571#endif
572\f
573/* Output some text at the nominal frame cursor position.
574 Advance the cursor over the text.
575 Output LEN glyphs at START.
576
577 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
578 controls the pixel values used for foreground and background. */
579
580static
581XTwrite_glyphs (start, len)
582 register GLYPH *start;
583 int len;
584{
585 register int temp_length;
586 int mask;
587 struct frame *f;
588
589 BLOCK_INPUT;
590
591 f = updating_frame;
592 if (f == 0)
593 {
594 f = selected_frame;
595 /* If not within an update,
596 output at the frame's visible cursor. */
597 curs_x = f->cursor_x;
598 curs_y = f->cursor_y;
599 }
600
601 dumpglyphs (f,
602 CHAR_TO_PIXEL_COL (f, curs_x),
603 CHAR_TO_PIXEL_ROW (f, curs_y),
604 start, len, highlight);
605
606 /* If we drew on top of the cursor, note that it is turned off. */
607 if (curs_y == f->phys_cursor_y
608 && curs_x <= f->phys_cursor_x
609 && curs_x + len > f->phys_cursor_x)
610 f->phys_cursor_x = -1;
611
612 if (updating_frame == 0)
613 {
614 f->cursor_x += len;
615 x_display_cursor (f, 1);
616 f->cursor_x -= len;
617 }
618 else
619 curs_x += len;
620
621 UNBLOCK_INPUT;
622}
623\f
624/* Clear to the end of the line.
625 Erase the current text line from the nominal cursor position (inclusive)
626 to column FIRST_UNUSED (exclusive). The idea is that everything
627 from FIRST_UNUSED onward is already erased. */
628
629static int
630XTclear_end_of_line (first_unused)
631 register int first_unused;
632{
633 struct frame *f = updating_frame;
634 int mask;
635
636 if (f == 0)
637 abort ();
638
639 if (curs_y < 0 || curs_y >= f->height)
640 return;
641 if (first_unused <= 0)
642 return;
643
644 if (first_unused >= f->width)
645 first_unused = f->width;
646
647 BLOCK_INPUT;
648
649 /* Notice if the cursor will be cleared by this operation. */
650 if (curs_y == f->phys_cursor_y
651 && curs_x <= f->phys_cursor_x
652 && f->phys_cursor_x < first_unused)
653 f->phys_cursor_x = -1;
654
655#ifdef HAVE_X11
656 XClearArea (x_current_display, FRAME_X_WINDOW (f),
657 CHAR_TO_PIXEL_COL (f, curs_x),
658 CHAR_TO_PIXEL_ROW (f, curs_y),
659 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
660 FONT_HEIGHT (f->display.x->font), False);
661
662#else /* ! defined (HAVE_X11) */
663 XPixSet (FRAME_X_WINDOW (f),
664 CHAR_TO_PIXEL_COL (f, curs_x),
665 CHAR_TO_PIXEL_ROW (f, curs_y),
666 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
667 FONT_HEIGHT (f->display.x->font),
668 f->display.x->background_pixel);
669#endif /* ! defined (HAVE_X11) */
670
671 UNBLOCK_INPUT;
672}
673
674static
675XTclear_frame ()
676{
677 int mask;
678 struct frame *f = updating_frame;
679
680 if (f == 0)
681 f = selected_frame;
682
683 f->phys_cursor_x = -1; /* Cursor not visible. */
684 curs_x = 0; /* Nominal cursor position is top left. */
685 curs_y = 0;
686
687 BLOCK_INPUT;
688
689 XClear (FRAME_X_WINDOW (f));
690
691 /* We have to clear the scroll bars, too. If we have changed
692 colors or something like that, then they should be notified. */
693 x_scroll_bar_clear (f);
694
695#ifndef HAVE_X11
696 dumpborder (f, 0);
697#endif /* HAVE_X11 */
698
699 XFlushQueue ();
700 UNBLOCK_INPUT;
701}
702\f
703/* Invert the middle quarter of the frame for .15 sec. */
704
705/* We use the select system call to do the waiting, so we have to make sure
706 it's available. If it isn't, we just won't do visual bells. */
707#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
708
709/* Subtract the `struct timeval' values X and Y,
710 storing the result in RESULT.
711 Return 1 if the difference is negative, otherwise 0. */
712
713static int
714timeval_subtract (result, x, y)
715 struct timeval *result, x, y;
716{
717 /* Perform the carry for the later subtraction by updating y.
718 This is safer because on some systems
719 the tv_sec member is unsigned. */
720 if (x.tv_usec < y.tv_usec)
721 {
722 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
723 y.tv_usec -= 1000000 * nsec;
724 y.tv_sec += nsec;
725 }
726 if (x.tv_usec - y.tv_usec > 1000000)
727 {
728 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
729 y.tv_usec += 1000000 * nsec;
730 y.tv_sec -= nsec;
731 }
732
733 /* Compute the time remaining to wait. tv_usec is certainly positive. */
734 result->tv_sec = x.tv_sec - y.tv_sec;
735 result->tv_usec = x.tv_usec - y.tv_usec;
736
737 /* Return indication of whether the result should be considered negative. */
738 return x.tv_sec < y.tv_sec;
739}
740
741XTflash (f)
742 struct frame *f;
743{
744 BLOCK_INPUT;
745
746 {
747 GC gc;
748
749 /* Create a GC that will use the GXxor function to flip foreground pixels
750 into background pixels. */
751 {
752 XGCValues values;
753
754 values.function = GXxor;
755 values.foreground = (f->display.x->foreground_pixel
756 ^ f->display.x->background_pixel);
757
758 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
759 GCFunction | GCForeground, &values);
760 }
761
762 {
763 int width = PIXEL_WIDTH (f);
764 int height = PIXEL_HEIGHT (f);
765
766 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
767 width/4, height/4, width/2, height/2);
768 XFlush (x_current_display);
769
770 {
771 struct timeval wakeup, now;
772
773 gettimeofday (&wakeup, (struct timezone *) 0);
774
775 /* Compute time to wait until, propagating carry from usecs. */
776 wakeup.tv_usec += 150000;
777 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
778 wakeup.tv_usec %= 1000000;
779
780 /* Keep waiting until past the time wakeup. */
781 while (1)
782 {
783 struct timeval timeout;
784
785 gettimeofday (&timeout, (struct timezone *)0);
786
787 /* In effect, timeout = wakeup - timeout.
788 Break if result would be negative. */
789 if (timeval_subtract (&timeout, wakeup, timeout))
790 break;
791
792 /* Try to wait that long--but we might wake up sooner. */
793 select (0, 0, 0, 0, &timeout);
794 }
795 }
796
797 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
798 width/4, height/4, width/2, height/2);
799 XFreeGC (x_current_display, gc);
800 XFlush (x_current_display);
801 }
802 }
803
804 UNBLOCK_INPUT;
805}
806
807#endif
808
809
810/* Make audible bell. */
811
812#ifdef HAVE_X11
813#define XRINGBELL XBell(x_current_display, 0)
814#else /* ! defined (HAVE_X11) */
815#define XRINGBELL XFeep(0);
816#endif /* ! defined (HAVE_X11) */
817
818XTring_bell ()
819{
820 if (x_current_display == 0)
821 return;
822
823#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
824 if (visible_bell)
825 XTflash (selected_frame);
826 else
827#endif
828 {
829 BLOCK_INPUT;
830 XRINGBELL;
831 XFlushQueue ();
832 UNBLOCK_INPUT;
833 }
834}
835\f
836/* Insert and delete character.
837 These are not supposed to be used because we are supposed to turn
838 off the feature of using them. */
839
840static
841XTinsert_glyphs (start, len)
842 register char *start;
843 register int len;
844{
845 abort ();
846}
847
848static
849XTdelete_glyphs (n)
850 register int n;
851{
852 abort ();
853}
854\f
855/* Specify how many text lines, from the top of the window,
856 should be affected by insert-lines and delete-lines operations.
857 This, and those operations, are used only within an update
858 that is bounded by calls to XTupdate_begin and XTupdate_end. */
859
860static
861XTset_terminal_window (n)
862 register int n;
863{
864 if (updating_frame == 0)
865 abort ();
866
867 if ((n <= 0) || (n > updating_frame->height))
868 flexlines = updating_frame->height;
869 else
870 flexlines = n;
871}
872\f
873/* Perform an insert-lines operation.
874 Insert N lines at a vertical position curs_y. */
875
876static void
877stufflines (n)
878 register int n;
879{
880 register int topregion, bottomregion;
881 register int length, newtop, mask;
882 register struct frame *f = updating_frame;
883 int intborder = f->display.x->internal_border_width;
884
885 if (curs_y >= flexlines)
886 return;
887
888 topregion = curs_y;
889 bottomregion = flexlines - (n + 1);
890 newtop = topregion + n;
891 length = (bottomregion - topregion) + 1;
892
893#ifndef HAVE_X11
894 dumpqueue ();
895#endif /* HAVE_X11 */
896
897 if ((length > 0) && (newtop <= flexlines))
898 {
899#ifdef HAVE_X11
900 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
901 FRAME_X_WINDOW (f), f->display.x->normal_gc,
902 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
903 f->width * FONT_WIDTH (f->display.x->font),
904 length * FONT_HEIGHT (f->display.x->font), intborder,
905 CHAR_TO_PIXEL_ROW (f, newtop));
906#else /* ! defined (HAVE_X11) */
907 XMoveArea (FRAME_X_WINDOW (f),
908 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
909 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
910 f->width * FONT_WIDTH (f->display.x->font),
911 length * FONT_HEIGHT (f->display.x->font));
912 /* Now we must process any ExposeRegion events that occur
913 if the area being copied from is obscured.
914 We can't let it wait because further i/d operations
915 may want to copy this area to another area. */
916 x_read_exposes ();
917#endif /* ! defined (HAVE_X11) */
918 }
919
920 newtop = min (newtop, (flexlines - 1));
921 length = newtop - topregion;
922 if (length > 0)
923 {
924#ifdef HAVE_X11
925 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
926 CHAR_TO_PIXEL_ROW (f, topregion),
927 f->width * FONT_WIDTH (f->display.x->font),
928 n * FONT_HEIGHT (f->display.x->font), False);
929#else /* ! defined (HAVE_X11) */
930 XPixSet (FRAME_X_WINDOW (f),
931 intborder,
932 CHAR_TO_PIXEL_ROW (f, topregion),
933 f->width * FONT_WIDTH (f->display.x->font),
934 n * FONT_HEIGHT (f->display.x->font),
935 f->display.x->background_pixel);
936#endif /* ! defined (HAVE_X11) */
937 }
938}
939
940/* Perform a delete-lines operation, deleting N lines
941 at a vertical position curs_y. */
942
943static void
944scraplines (n)
945 register int n;
946{
947 int mask;
948 register struct frame *f = updating_frame;
949 int intborder = f->display.x->internal_border_width;
950
951 if (curs_y >= flexlines)
952 return;
953
954#ifndef HAVE_X11
955 dumpqueue ();
956#endif /* HAVE_X11 */
957
958 if ((curs_y + n) >= flexlines)
959 {
960 if (flexlines >= (curs_y + 1))
961 {
962#ifdef HAVE_X11
963 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
964 CHAR_TO_PIXEL_ROW (f, curs_y),
965 f->width * FONT_WIDTH (f->display.x->font),
966 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
967#else /* ! defined (HAVE_X11) */
968 XPixSet (FRAME_X_WINDOW (f),
969 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
970 f->width * FONT_WIDTH (f->display.x->font),
971 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
972 f->display.x->background_pixel);
973#endif /* ! defined (HAVE_X11) */
974 }
975 }
976 else
977 {
978#ifdef HAVE_X11
979 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
980 FRAME_X_WINDOW (f), f->display.x->normal_gc,
981 intborder,
982 CHAR_TO_PIXEL_ROW (f, curs_y + n),
983 f->width * FONT_WIDTH (f->display.x->font),
984 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
985 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
986 XClearArea (x_current_display, FRAME_X_WINDOW (f),
987 intborder,
988 CHAR_TO_PIXEL_ROW (f, flexlines - n),
989 f->width * FONT_WIDTH (f->display.x->font),
990 n * FONT_HEIGHT (f->display.x->font), False);
991#else /* ! defined (HAVE_X11) */
992 XMoveArea (FRAME_X_WINDOW (f),
993 intborder,
994 CHAR_TO_PIXEL_ROW (f, curs_y + n),
995 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
996 f->width * FONT_WIDTH (f->display.x->font),
997 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
998 /* Now we must process any ExposeRegion events that occur
999 if the area being copied from is obscured.
1000 We can't let it wait because further i/d operations
1001 may want to copy this area to another area. */
1002 x_read_exposes ();
1003 XPixSet (FRAME_X_WINDOW (f), intborder,
1004 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1005 f->width * FONT_WIDTH (f->display.x->font),
1006 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
1007#endif /* ! defined (HAVE_X11) */
1008 }
1009}
1010
1011/* Perform an insert-lines or delete-lines operation,
1012 inserting N lines or deleting -N lines at vertical position VPOS. */
1013
1014XTins_del_lines (vpos, n)
1015 int vpos, n;
1016{
1017 if (updating_frame == 0)
1018 abort ();
1019
1020 /* Hide the cursor. */
1021 x_display_cursor (updating_frame, 0);
1022
1023 XTcursor_to (vpos, 0);
1024
1025 BLOCK_INPUT;
1026 if (n >= 0)
1027 stufflines (n);
1028 else
1029 scraplines (-n);
1030 XFlushQueue ();
1031 UNBLOCK_INPUT;
1032}
1033\f
1034/* Support routines for exposure events. */
1035static void clear_cursor ();
1036
1037/* Output into a rectangle of an X-window (for frame F)
1038 the characters in f->phys_lines that overlap that rectangle.
1039 TOP and LEFT are the position of the upper left corner of the rectangle.
1040 ROWS and COLS are the size of the rectangle. */
1041
1042static void
1043dumprectangle (f, left, top, cols, rows)
1044 struct frame *f;
1045 register int left, top, cols, rows;
1046{
1047 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1048 int cursor_cleared = 0;
1049 int bottom, right;
1050 register int y;
1051
1052 if (FRAME_GARBAGED_P (f))
1053 return;
1054
1055 /* Express rectangle as four edges, instead of position-and-size. */
1056 bottom = top + rows;
1057 right = left + cols;
1058
1059#ifndef HAVE_X11 /* Window manger does this for X11. */
1060 {
1061 int intborder = f->display.x->internal_border_width;
1062
1063 /* If the rectangle includes any of the internal border area,
1064 redisplay the border emphasis. */
1065 if (top < intborder || left < intborder
1066 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1067 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1068 dumpborder (f, 0);
1069 }
1070#endif /* HAVE_X11 Window manger does this for X11. */
1071
1072 /* Convert rectangle edges in pixels to edges in chars.
1073 Round down for left and top, up for right and bottom. */
1074 top = PIXEL_TO_CHAR_ROW (f, top);
1075 left = PIXEL_TO_CHAR_COL (f, left);
1076 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1077 right += (FONT_WIDTH (f->display.x->font) - 1);
1078 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1079 right = PIXEL_TO_CHAR_COL (f, right);
1080
1081 /* Clip the rectangle to what can be visible. */
1082 if (left < 0)
1083 left = 0;
1084 if (top < 0)
1085 top = 0;
1086 if (right > f->width)
1087 right = f->width;
1088 if (bottom > f->height)
1089 bottom = f->height;
1090
1091 /* Get size in chars of the rectangle. */
1092 cols = right - left;
1093 rows = bottom - top;
1094
1095 /* If rectangle has zero area, return. */
1096 if (rows <= 0) return;
1097 if (cols <= 0) return;
1098
1099 /* Turn off the cursor if it is in the rectangle.
1100 We will turn it back on afterward. */
1101 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1102 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1103 {
1104 clear_cursor (f);
1105 cursor_cleared = 1;
1106 }
1107
1108 /* Display the text in the rectangle, one text line at a time. */
1109
1110 for (y = top; y < bottom; y++)
1111 {
1112 GLYPH *line = &active_frame->glyphs[y][left];
1113
1114 if (! active_frame->enable[y] || left > active_frame->used[y])
1115 continue;
1116
1117 dumpglyphs (f,
1118 CHAR_TO_PIXEL_COL (f, left),
1119 CHAR_TO_PIXEL_ROW (f, y),
1120 line, min (cols, active_frame->used[y] - left),
1121 active_frame->highlight[y]);
1122 }
1123
1124 /* Turn the cursor on if we turned it off. */
1125
1126 if (cursor_cleared)
1127 x_display_cursor (f, 1);
1128}
1129
1130#ifndef HAVE_X11
1131/* Process all queued ExposeRegion events. */
1132
1133static void
1134dumpqueue ()
1135{
1136 register int i;
1137 XExposeRegionEvent r;
1138
1139 while (dequeue_event (&r, &x_expose_queue))
1140 {
1141 struct frame *f = x_window_to_frame (r.window);
1142 if (f->display.x->icon_desc == r.window)
1143 refreshicon (f);
1144 else
1145 dumprectangle (f, r.x, r.y, r.width, r.height);
1146 }
1147 XFlushQueue ();
1148}
1149#endif /* HAVE_X11 */
1150\f
1151/* Process all expose events that are pending, for X10.
1152 Redraws the cursor if necessary on any frame that
1153 is not in the process of being updated with update_frame. */
1154
1155#ifndef HAVE_X11
1156static void
1157x_do_pending_expose ()
1158{
1159 int mask;
1160 struct frame *f;
1161 Lisp_Object tail, frame;
1162
1163 if (expose_all_windows)
1164 {
1165 expose_all_windows = 0;
1166 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1167 {
1168 register int temp_width, temp_height;
1169 int intborder;
1170
1171 frame = XCONS (tail)->car;
1172 if (XGCTYPE (frame) != Lisp_Frame)
1173 continue;
1174 f = XFRAME (frame);
1175 if (! FRAME_X_P (f))
1176 continue;
1177 if (!f->async_visible)
1178 continue;
1179 if (!f->display.x->needs_exposure)
1180 continue;
1181
1182 intborder = f->display.x->internal_border_width;
1183
1184 clear_cursor (f);
1185 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1186 temp_width = ((windowinfo.width - 2 * intborder
1187 - f->display.x->v_scroll_bar_width)
1188 / FONT_WIDTH (f->display.x->font));
1189 temp_height = ((windowinfo.height- 2 * intborder
1190 - f->display.x->h_scroll_bar_height)
1191 / FONT_HEIGHT (f->display.x->font));
1192 if (temp_width != f->width || temp_height != f->height)
1193 {
1194 change_frame_size (f, max (1, temp_height),
1195 max (1, temp_width), 0, 1);
1196 x_resize_scroll_bars (f);
1197 }
1198 f->display.x->left_pos = windowinfo.x;
1199 f->display.x->top_pos = windowinfo.y;
1200 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1201#if 0
1202 dumpborder (f, 0);
1203#endif /* ! 0 */
1204 f->display.x->needs_exposure = 0;
1205 if (updating_frame != f)
1206 x_display_cursor (f, 1);
1207 XFlushQueue ();
1208 }
1209 }
1210 else
1211 /* Handle any individual-rectangle expose events queued
1212 for various windows. */
1213#ifdef HAVE_X11
1214 ;
1215#else /* ! defined (HAVE_X11) */
1216 dumpqueue ();
1217#endif /* ! defined (HAVE_X11) */
1218}
1219#endif
1220
1221#ifdef HAVE_X11
1222static void
1223frame_highlight (frame)
1224 struct frame *frame;
1225{
1226 if (! EQ (Vx_no_window_manager, Qnil))
1227 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1228 frame->display.x->border_pixel);
1229 x_display_cursor (frame, 1);
1230}
1231
1232static void
1233frame_unhighlight (frame)
1234 struct frame *frame;
1235{
1236 if (! EQ (Vx_no_window_manager, Qnil))
1237 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1238 frame->display.x->border_tile);
1239 x_display_cursor (frame, 1);
1240}
1241#else /* ! defined (HAVE_X11) */
1242/* Dump the border-emphasis of frame F.
1243 If F is selected, this is a lining of the same color as the border,
1244 just within the border, occupying a portion of the internal border.
1245 If F is not selected, it is background in the same place.
1246 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1247
1248 ALWAYS = 1 is used when a frame becomes selected or deselected.
1249 In that case, we also turn the cursor off and on again
1250 so it will appear in the proper shape (solid if selected; else hollow.) */
1251
1252static void
1253dumpborder (f, always)
1254 struct frame *f;
1255 int always;
1256{
1257 int thickness = f->display.x->internal_border_width / 2;
1258 int width = PIXEL_WIDTH (f);
1259 int height = PIXEL_HEIGHT (f);
1260 int pixel;
1261
1262 if (f != selected_frame)
1263 {
1264 if (!always)
1265 return;
1266
1267 pixel = f->display.x->background_pixel;
1268 }
1269 else
1270 {
1271 pixel = f->display.x->border_pixel;
1272 }
1273
1274 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1275 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1276 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1277 thickness, pixel);
1278 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1279 height, pixel);
1280
1281 if (always)
1282 x_display_cursor (f, 1);
1283}
1284#endif /* ! defined (HAVE_X11) */
1285
1286static void XTframe_rehighlight ();
1287
1288/* The focus has changed. Update the frames as necessary to reflect
1289 the new situation. Note that we can't change the selected frame
1290 here, because the lisp code we are interrupting might become confused.
1291 Each event gets marked with the frame in which it occurred, so the
1292 lisp code can tell when the switch took place by examining the events. */
1293
1294static void
1295x_new_focus_frame (frame)
1296 struct frame *frame;
1297{
1298 struct frame *old_focus = x_focus_frame;
1299 int events_enqueued = 0;
1300
1301 if (frame != x_focus_frame)
1302 {
1303 /* Set this before calling other routines, so that they see
1304 the correct value of x_focus_frame. */
1305 x_focus_frame = frame;
1306
1307 if (old_focus && old_focus->auto_lower)
1308 x_lower_frame (old_focus);
1309
1310#if 0
1311 selected_frame = frame;
1312 XSET (XWINDOW (selected_frame->selected_window)->frame,
1313 Lisp_Frame, selected_frame);
1314 Fselect_window (selected_frame->selected_window);
1315 choose_minibuf_frame ();
1316#endif /* ! 0 */
1317
1318 if (x_focus_frame && x_focus_frame->auto_raise)
1319 x_raise_frame (x_focus_frame);
1320 }
1321
1322 XTframe_rehighlight ();
1323}
1324
1325
1326/* The focus has changed, or we have redirected a frame's focus to
1327 another frame (this happens when a frame uses a surrogate
1328 minibuffer frame). Shift the highlight as appropriate. */
1329static void
1330XTframe_rehighlight ()
1331{
1332 struct frame *old_highlight = x_highlight_frame;
1333
1334 if (x_focus_frame)
1335 {
1336 x_highlight_frame =
1337 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1338 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1339 : x_focus_frame);
1340 if (! FRAME_LIVE_P (x_highlight_frame))
1341 {
1342 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1343 x_highlight_frame = x_focus_frame;
1344 }
1345 }
1346 else
1347 x_highlight_frame = 0;
1348
1349 if (x_highlight_frame != old_highlight)
1350 {
1351 if (old_highlight)
1352 frame_unhighlight (old_highlight);
1353 if (x_highlight_frame)
1354 frame_highlight (x_highlight_frame);
1355 }
1356}
1357\f
1358/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1359
1360/* Which modifier keys are on which modifier bits?
1361
1362 With each keystroke, X returns eight bits indicating which modifier
1363 keys were held down when the key was pressed. The interpretation
1364 of the top five modifier bits depends on what keys are attached
1365 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1366 is the meta bit.
1367
1368 x_meta_mod_mask is a mask containing the bits used for the meta key.
1369 It may have more than one bit set, if more than one modifier bit
1370 has meta keys on it. Basically, if EVENT is a KeyPress event,
1371 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1372
1373 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1374 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1375 only be affected by the lock modifier bit if XK_Shift_Lock is in
1376 use; XK_Caps_Lock should only affect alphabetic keys. With this
1377 arrangement, the lock modifier should shift the character if
1378 (EVENT.state & x_shift_lock_mask) != 0. */
1379static int x_meta_mod_mask, x_shift_lock_mask;
1380
1381/* These are like x_meta_mod_mask, but for different modifiers. */
1382static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1383
1384/* Initialize mode_switch_bit and modifier_meaning. */
1385static void
1386x_find_modifier_meanings ()
1387{
1388 int min_code, max_code;
1389 KeySym *syms;
1390 int syms_per_code;
1391 XModifierKeymap *mods;
1392
1393 x_meta_mod_mask = 0;
1394 x_shift_lock_mask = 0;
1395 x_alt_mod_mask = 0;
1396 x_super_mod_mask = 0;
1397 x_hyper_mod_mask = 0;
1398
1399#ifdef HAVE_X11R4
1400 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1401#else
1402 min_code = x_current_display->min_keycode;
1403 max_code = x_current_display->max_keycode;
1404#endif
1405
1406 syms = XGetKeyboardMapping (x_current_display,
1407 min_code, max_code - min_code + 1,
1408 &syms_per_code);
1409 mods = XGetModifierMapping (x_current_display);
1410
1411 /* Scan the modifier table to see which modifier bits the Meta and
1412 Alt keysyms are on. */
1413 {
1414 int row, col; /* The row and column in the modifier table. */
1415
1416 for (row = 3; row < 8; row++)
1417 for (col = 0; col < mods->max_keypermod; col++)
1418 {
1419 KeyCode code =
1420 mods->modifiermap[(row * mods->max_keypermod) + col];
1421
1422 /* Are any of this keycode's keysyms a meta key? */
1423 {
1424 int code_col;
1425
1426 for (code_col = 0; code_col < syms_per_code; code_col++)
1427 {
1428 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1429
1430 switch (sym)
1431 {
1432 case XK_Meta_L:
1433 case XK_Meta_R:
1434 x_meta_mod_mask |= (1 << row);
1435 break;
1436
1437 case XK_Alt_L:
1438 case XK_Alt_R:
1439 x_alt_mod_mask |= (1 << row);
1440 break;
1441
1442 case XK_Hyper_L:
1443 case XK_Hyper_R:
1444 x_hyper_mod_mask |= (1 << row);
1445 break;
1446
1447 case XK_Super_L:
1448 case XK_Super_R:
1449 x_super_mod_mask |= (1 << row);
1450 break;
1451
1452 case XK_Shift_Lock:
1453 /* Ignore this if it's not on the lock modifier. */
1454 if ((1 << row) == LockMask)
1455 x_shift_lock_mask = LockMask;
1456 break;
1457 }
1458 }
1459 }
1460 }
1461 }
1462
1463 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1464 if (! x_meta_mod_mask)
1465 {
1466 x_meta_mod_mask = x_alt_mod_mask;
1467 x_alt_mod_mask = 0;
1468 }
1469
1470 /* If some keys are both alt and meta,
1471 make them just meta, not alt. */
1472 if (x_alt_mod_mask & x_meta_mod_mask)
1473 {
1474 x_alt_mod_mask &= ~x_meta_mod_mask;
1475 }
1476
1477 XFree ((char *) syms);
1478 XFreeModifiermap (mods);
1479}
1480
1481
1482/* Convert between the modifier bits X uses and the modifier bits
1483 Emacs uses. */
1484static unsigned int
1485x_x_to_emacs_modifiers (state)
1486 unsigned int state;
1487{
1488 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1489 | ((state & ControlMask) ? ctrl_modifier : 0)
1490 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1491 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1492 | ((state & x_super_mod_mask) ? super_modifier : 0)
1493 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1494}
1495
1496static unsigned int
1497x_emacs_to_x_modifiers (state)
1498 unsigned int state;
1499{
1500 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1501 | ((state & super_modifier) ? x_super_mod_mask : 0)
1502 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1503 | ((state & shift_modifier) ? ShiftMask : 0)
1504 | ((state & ctrl_modifier) ? ControlMask : 0)
1505 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1506}
1507
1508/* Return true iff KEYSYM is a vendor-specific keysym that we should
1509 return as a function key. If you add a keysym to this, you should
1510 make sure that the tables make_lispy_event uses contain a suitable
1511 name for it. */
1512static int
1513x_is_vendor_fkey (sym)
1514 KeySym sym;
1515{
1516 return 0
1517#ifdef DXK_Remove
1518 || (sym == DXK_Remove)
1519#endif
1520 ;
1521}
1522
1523\f
1524/* Mouse clicks and mouse movement. Rah. */
1525#ifdef HAVE_X11
1526
1527/* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1528 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1529 that the glyph at X, Y occupies, if BOUNDS != 0. */
1530static void
1531pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1532 FRAME_PTR f;
1533 register unsigned int pix_x, pix_y;
1534 register int *x, *y;
1535 XRectangle *bounds;
1536{
1537 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1538 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1539
1540 if (bounds)
1541 {
1542 bounds->width = FONT_WIDTH (f->display.x->font);
1543 bounds->height = FONT_HEIGHT (f->display.x->font);
1544 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1545 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1546 }
1547
1548 if (pix_x < 0) pix_x = 0;
1549 else if (pix_x > f->width) pix_x = f->width;
1550
1551 if (pix_y < 0) pix_y = 0;
1552 else if (pix_y > f->height) pix_y = f->height;
1553
1554 *x = pix_x;
1555 *y = pix_y;
1556}
1557
1558/* Any buttons grabbed. */
1559unsigned int x_mouse_grabbed;
1560
1561/* Prepare a mouse-event in *RESULT for placement in the input queue.
1562
1563 If the event is a button press, then note that we have grabbed
1564 the mouse. */
1565
1566static Lisp_Object
1567construct_mouse_click (result, event, f)
1568 struct input_event *result;
1569 XButtonEvent *event;
1570 struct frame *f;
1571{
1572 /* Make the event type no_event; we'll change that when we decide
1573 otherwise. */
1574 result->kind = mouse_click;
1575 XSET (result->code, Lisp_Int, event->button - Button1);
1576 result->timestamp = event->time;
1577 result->modifiers = (x_x_to_emacs_modifiers (event->state)
1578 | (event->type == ButtonRelease
1579 ? up_modifier
1580 : down_modifier));
1581
1582 /* Notice if the mouse is still grabbed. */
1583 if (event->type == ButtonPress)
1584 {
1585 if (! x_mouse_grabbed)
1586 Vmouse_depressed = Qt;
1587 x_mouse_grabbed |= (1 << event->button);
1588 }
1589 else if (event->type == ButtonRelease)
1590 {
1591 x_mouse_grabbed &= ~(1 << event->button);
1592 if (!x_mouse_grabbed)
1593 Vmouse_depressed = Qnil;
1594 }
1595
1596 {
1597 int row, column;
1598
1599 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1600 XFASTINT (result->x) = column;
1601 XFASTINT (result->y) = row;
1602 XSET (result->frame_or_window, Lisp_Frame, f);
1603 }
1604}
1605
1606
1607/* Mouse movement. Rah.
1608
1609 In order to avoid asking for motion events and then throwing most
1610 of them away or busy-polling the server for mouse positions, we ask
1611 the server for pointer motion hints. This means that we get only
1612 one event per group of mouse movements. "Groups" are delimited by
1613 other kinds of events (focus changes and button clicks, for
1614 example), or by XQueryPointer calls; when one of these happens, we
1615 get another MotionNotify event the next time the mouse moves. This
1616 is at least as efficient as getting motion events when mouse
1617 tracking is on, and I suspect only negligibly worse when tracking
1618 is off.
1619
1620 The silly O'Reilly & Associates Nutshell guides barely document
1621 pointer motion hints at all (I think you have to infer how they
1622 work from an example), and the description of XQueryPointer doesn't
1623 mention that calling it causes you to get another motion hint from
1624 the server, which is very important. */
1625
1626/* Where the mouse was last time we reported a mouse event. */
1627static FRAME_PTR last_mouse_frame;
1628static XRectangle last_mouse_glyph;
1629
1630/* The scroll bar in which the last X motion event occurred.
1631
1632 If the last X motion event occurred in a scroll bar, we set this
1633 so XTmouse_position can know whether to report a scroll bar motion or
1634 an ordinary motion.
1635
1636 If the last X motion event didn't occur in a scroll bar, we set this
1637 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1638static Lisp_Object last_mouse_scroll_bar;
1639
1640/* This is a hack. We would really prefer that XTmouse_position would
1641 return the time associated with the position it returns, but there
1642 doesn't seem to be any way to wrest the timestamp from the server
1643 along with the position query. So, we just keep track of the time
1644 of the last movement we received, and return that in hopes that
1645 it's somewhat accurate. */
1646static Time last_mouse_movement_time;
1647
1648/* Function to report a mouse movement to the mainstream Emacs code.
1649 The input handler calls this.
1650
1651 We have received a mouse movement event, which is given in *event.
1652 If the mouse is over a different glyph than it was last time, tell
1653 the mainstream emacs code by setting mouse_moved. If not, ask for
1654 another motion event, so we can check again the next time it moves. */
1655static void
1656note_mouse_movement (frame, event)
1657 FRAME_PTR frame;
1658 XMotionEvent *event;
1659
1660{
1661 last_mouse_movement_time = event->time;
1662
1663 /* Has the mouse moved off the glyph it was on at the last sighting? */
1664 if (event->x < last_mouse_glyph.x
1665 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1666 || event->y < last_mouse_glyph.y
1667 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1668 {
1669 mouse_moved = 1;
1670 last_mouse_scroll_bar = Qnil;
1671 }
1672 else
1673 {
1674 /* It's on the same glyph. Call XQueryPointer so we'll get an
1675 event the next time the mouse moves and we can see if it's
1676 *still* on the same glyph. */
1677 int dummy;
1678
1679 XQueryPointer (event->display, event->window,
1680 (Window *) &dummy, (Window *) &dummy,
1681 &dummy, &dummy, &dummy, &dummy,
1682 (unsigned int *) &dummy);
1683 }
1684}
1685
1686static struct scroll_bar *x_window_to_scroll_bar ();
1687static void x_scroll_bar_report_motion ();
1688
1689/* Return the current position of the mouse.
1690
1691 If the mouse movement started in a scroll bar, set *f, *bar_window,
1692 and *part to the frame, window, and scroll bar part that the mouse
1693 is over. Set *x and *y to the portion and whole of the mouse's
1694 position on the scroll bar.
1695
1696 If the mouse movement started elsewhere, set *f to the frame the
1697 mouse is on, *bar_window to nil, and *x and *y to the character cell
1698 the mouse is over.
1699
1700 Set *time to the server timestamp for the time at which the mouse
1701 was at this position.
1702
1703 Don't store anything if we don't have a valid set of values to report.
1704
1705 This clears the mouse_moved flag, so we can wait for the next mouse
1706 movement. This also calls XQueryPointer, which will cause the
1707 server to give us another MotionNotify when the mouse moves
1708 again. */
1709
1710static void
1711XTmouse_position (f, bar_window, part, x, y, time)
1712 FRAME_PTR *f;
1713 Lisp_Object *bar_window;
1714 enum scroll_bar_part *part;
1715 Lisp_Object *x, *y;
1716 unsigned long *time;
1717{
1718 FRAME_PTR f1;
1719
1720 BLOCK_INPUT;
1721
1722 if (! NILP (last_mouse_scroll_bar))
1723 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1724 else
1725 {
1726 Window root;
1727 int root_x, root_y;
1728
1729 Window dummy_window;
1730 int dummy;
1731
1732 mouse_moved = 0;
1733 last_mouse_scroll_bar = Qnil;
1734
1735 /* Figure out which root window we're on. */
1736 XQueryPointer (x_current_display,
1737 DefaultRootWindow (x_current_display),
1738
1739 /* The root window which contains the pointer. */
1740 &root,
1741
1742 /* Trash which we can't trust if the pointer is on
1743 a different screen. */
1744 &dummy_window,
1745
1746 /* The position on that root window. */
1747 &root_x, &root_y,
1748
1749 /* More trash we can't trust. */
1750 &dummy, &dummy,
1751
1752 /* Modifier keys and pointer buttons, about which
1753 we don't care. */
1754 (unsigned int *) &dummy);
1755
1756 /* Now we have a position on the root; find the innermost window
1757 containing the pointer. */
1758 {
1759 Window win, child;
1760 int win_x, win_y;
1761 int parent_x, parent_y;
1762
1763 win = root;
1764 for (;;)
1765 {
1766 XTranslateCoordinates (x_current_display,
1767
1768 /* From-window, to-window. */
1769 root, win,
1770
1771 /* From-position, to-position. */
1772 root_x, root_y, &win_x, &win_y,
1773
1774 /* Child of win. */
1775 &child);
1776
1777 if (child == None)
1778 break;
1779
1780 win = child;
1781 parent_x = win_x;
1782 parent_y = win_y;
1783 }
1784
1785 /* Now we know that:
1786 win is the innermost window containing the pointer
1787 (XTC says it has no child containing the pointer),
1788 win_x and win_y are the pointer's position in it
1789 (XTC did this the last time through), and
1790 parent_x and parent_y are the pointer's position in win's parent.
1791 (They are what win_x and win_y were when win was child.
1792 If win is the root window, it has no parent, and
1793 parent_{x,y} are invalid, but that's okay, because we'll
1794 never use them in that case.) */
1795
1796 /* Is win one of our frames? */
1797 f1 = x_window_to_frame (win);
1798
1799 /* If not, is it one of our scroll bars? */
1800 if (! f1)
1801 {
1802 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1803
1804 if (bar)
1805 {
1806 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1807 win_x = parent_x;
1808 win_y = parent_y;
1809 }
1810 }
1811
1812 if (f1)
1813 {
1814 /* Ok, we found a frame. Convert from pixels to characters
1815 and store all the values. */
1816
1817 pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y,
1818 &last_mouse_glyph);
1819
1820 *bar_window = Qnil;
1821 *part = 0;
1822 *f = f1;
1823 XSET (*x, Lisp_Int, win_x);
1824 XSET (*y, Lisp_Int, win_y);
1825 *time = last_mouse_movement_time;
1826 }
1827 }
1828 }
1829
1830 UNBLOCK_INPUT;
1831}
1832
1833#else /* ! defined (HAVE_X11) */
1834#define XEvent XKeyPressedEvent
1835#endif /* ! defined (HAVE_X11) */
1836\f
1837/* Scroll bar support. */
1838
1839/* Given an X window ID, find the struct scroll_bar which manages it.
1840 This can be called in GC, so we have to make sure to strip off mark
1841 bits. */
1842static struct scroll_bar *
1843x_window_to_scroll_bar (window_id)
1844 Window window_id;
1845{
1846 Lisp_Object tail, frame;
1847
1848 for (tail = Vframe_list;
1849 XGCTYPE (tail) == Lisp_Cons;
1850 tail = XCONS (tail)->cdr)
1851 {
1852 Lisp_Object frame = XCONS (tail)->car;
1853 Lisp_Object bar, condemned;
1854
1855 /* All elements of Vframe_list should be frames. */
1856 if (XGCTYPE (frame) != Lisp_Frame)
1857 abort ();
1858
1859 /* Scan this frame's scroll bar list for a scroll bar with the
1860 right window ID. */
1861 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1862 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1863 /* This trick allows us to search both the ordinary and
1864 condemned scroll bar lists with one loop. */
1865 ! GC_NILP (bar) || (bar = condemned,
1866 condemned = Qnil,
1867 ! GC_NILP (bar));
1868 bar = XSCROLL_BAR(bar)->next)
1869 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1870 return XSCROLL_BAR (bar);
1871 }
1872
1873 return 0;
1874}
1875
1876/* Open a new X window to serve as a scroll bar, and return the
1877 scroll bar vector for it. */
1878static struct scroll_bar *
1879x_scroll_bar_create (window, top, left, width, height)
1880 struct window *window;
1881 int top, left, width, height;
1882{
1883 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1884 struct scroll_bar *bar =
1885 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1886
1887 BLOCK_INPUT;
1888
1889 {
1890 XSetWindowAttributes a;
1891 unsigned long mask;
1892
1893 a.background_pixel = frame->display.x->background_pixel;
1894 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1895 | ButtonMotionMask | PointerMotionHintMask
1896 | ExposureMask);
1897 a.cursor = x_vertical_scroll_bar_cursor;
1898
1899 mask = (CWBackPixel | CWEventMask | CWCursor);
1900
1901 SET_SCROLL_BAR_X_WINDOW
1902 (bar,
1903 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1904
1905 /* Position and size of scroll bar. */
1906 left, top, width, height,
1907
1908 /* Border width, depth, class, and visual. */
1909 0, CopyFromParent, CopyFromParent, CopyFromParent,
1910
1911 /* Attributes. */
1912 mask, &a));
1913 }
1914
1915 XSET (bar->window, Lisp_Window, window);
1916 XSET (bar->top, Lisp_Int, top);
1917 XSET (bar->left, Lisp_Int, left);
1918 XSET (bar->width, Lisp_Int, width);
1919 XSET (bar->height, Lisp_Int, height);
1920 XSET (bar->start, Lisp_Int, 0);
1921 XSET (bar->end, Lisp_Int, 0);
1922 bar->dragging = Qnil;
1923
1924 /* Add bar to its frame's list of scroll bars. */
1925 bar->next = FRAME_SCROLL_BARS (frame);
1926 bar->prev = Qnil;
1927 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1928 if (! NILP (bar->next))
1929 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1930
1931 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1932
1933 UNBLOCK_INPUT;
1934
1935 return bar;
1936}
1937
1938/* Draw BAR's handle in the proper position.
1939 If the handle is already drawn from START to END, don't bother
1940 redrawing it, unless REBUILD is non-zero; in that case, always
1941 redraw it. (REBUILD is handy for drawing the handle after expose
1942 events.)
1943
1944 Normally, we want to constrain the start and end of the handle to
1945 fit inside its rectangle, but if the user is dragging the scroll bar
1946 handle, we want to let them drag it down all the way, so that the
1947 bar's top is as far down as it goes; otherwise, there's no way to
1948 move to the very end of the buffer. */
1949static void
1950x_scroll_bar_set_handle (bar, start, end, rebuild)
1951 struct scroll_bar *bar;
1952 int start, end;
1953 int rebuild;
1954{
1955 int dragging = ! NILP (bar->dragging);
1956 Window w = SCROLL_BAR_X_WINDOW (bar);
1957 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1958
1959 /* If the display is already accurate, do nothing. */
1960 if (! rebuild
1961 && start == XINT (bar->start)
1962 && end == XINT (bar->end))
1963 return;
1964
1965 BLOCK_INPUT;
1966
1967 {
1968 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1969 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1970 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
1971
1972 /* Make sure the values are reasonable, and try to preserve
1973 the distance between start and end. */
1974 {
1975 int length = end - start;
1976
1977 if (start < 0)
1978 start = 0;
1979 else if (start > top_range)
1980 start = top_range;
1981 end = start + length;
1982
1983 if (end < start)
1984 end = start;
1985 else if (end > top_range && ! dragging)
1986 end = top_range;
1987 }
1988
1989 /* Store the adjusted setting in the scroll bar. */
1990 XSET (bar->start, Lisp_Int, start);
1991 XSET (bar->end, Lisp_Int, end);
1992
1993 /* Clip the end position, just for display. */
1994 if (end > top_range)
1995 end = top_range;
1996
1997 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1998 below top positions, to make sure the handle is always at least
1999 that many pixels tall. */
2000 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2001
2002 /* Draw the empty space above the handle. Note that we can't clear
2003 zero-height areas; that means "clear to end of window." */
2004 if (0 < start)
2005 XClearArea (x_current_display, w,
2006
2007 /* x, y, width, height, and exposures. */
2008 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2009 VERTICAL_SCROLL_BAR_TOP_BORDER,
2010 inside_width, start,
2011 False);
2012
2013 /* Draw the handle itself. */
2014 XFillRectangle (x_current_display, w, gc,
2015
2016 /* x, y, width, height */
2017 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2018 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2019 inside_width, end - start);
2020
2021
2022 /* Draw the empty space below the handle. Note that we can't
2023 clear zero-height areas; that means "clear to end of window." */
2024 if (end < inside_height)
2025 XClearArea (x_current_display, w,
2026
2027 /* x, y, width, height, and exposures. */
2028 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2029 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2030 inside_width, inside_height - end,
2031 False);
2032
2033 }
2034
2035 UNBLOCK_INPUT;
2036}
2037
2038/* Move a scroll bar around on the screen, to accommodate changing
2039 window configurations. */
2040static void
2041x_scroll_bar_move (bar, top, left, width, height)
2042 struct scroll_bar *bar;
2043 int top, left, width, height;
2044{
2045 BLOCK_INPUT;
2046
2047 {
2048 XWindowChanges wc;
2049 unsigned int mask = 0;
2050
2051 wc.x = left;
2052 wc.y = top;
2053 wc.width = width;
2054 wc.height = height;
2055
2056 if (left != XINT (bar->left)) mask |= CWX;
2057 if (top != XINT (bar->top)) mask |= CWY;
2058 if (width != XINT (bar->width)) mask |= CWWidth;
2059 if (height != XINT (bar->height)) mask |= CWHeight;
2060
2061 if (mask)
2062 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
2063 mask, &wc);
2064 }
2065
2066 XSET (bar->left, Lisp_Int, left);
2067 XSET (bar->top, Lisp_Int, top);
2068 XSET (bar->width, Lisp_Int, width);
2069 XSET (bar->height, Lisp_Int, height);
2070
2071 UNBLOCK_INPUT;
2072}
2073
2074/* Destroy the X window for BAR, and set its Emacs window's scroll bar
2075 to nil. */
2076static void
2077x_scroll_bar_remove (bar)
2078 struct scroll_bar *bar;
2079{
2080 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2081
2082 BLOCK_INPUT;
2083
2084 /* Destroy the window. */
2085 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2086
2087 /* Disassociate this scroll bar from its window. */
2088 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2089
2090 UNBLOCK_INPUT;
2091}
2092
2093/* Set the handle of the vertical scroll bar for WINDOW to indicate
2094 that we are displaying PORTION characters out of a total of WHOLE
2095 characters, starting at POSITION. If WINDOW has no scroll bar,
2096 create one. */
2097static void
2098XTset_vertical_scroll_bar (window, portion, whole, position)
2099 struct window *window;
2100 int portion, whole, position;
2101{
2102 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2103 int top = XINT (window->top);
2104 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2105 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2106
2107 /* Where should this scroll bar be, pixelwise? */
2108 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2109 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2110 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2111 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2112
2113 struct scroll_bar *bar;
2114
2115 /* Does the scroll bar exist yet? */
2116 if (NILP (window->vertical_scroll_bar))
2117 bar = x_scroll_bar_create (window,
2118 pixel_top, pixel_left,
2119 pixel_width, pixel_height);
2120 else
2121 {
2122 /* It may just need to be moved and resized. */
2123 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2124 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2125 }
2126
2127 /* Set the scroll bar's current state, unless we're currently being
2128 dragged. */
2129 if (NILP (bar->dragging))
2130 {
2131 int top_range =
2132 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2133
2134 if (whole == 0)
2135 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2136 else
2137 {
2138 int start = ((double) position * top_range) / whole;
2139 int end = ((double) (position + portion) * top_range) / whole;
2140
2141 x_scroll_bar_set_handle (bar, start, end, 0);
2142 }
2143 }
2144
2145 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2146}
2147
2148
2149/* The following three hooks are used when we're doing a thorough
2150 redisplay of the frame. We don't explicitly know which scroll bars
2151 are going to be deleted, because keeping track of when windows go
2152 away is a real pain - "Can you say set-window-configuration, boys
2153 and girls?" Instead, we just assert at the beginning of redisplay
2154 that *all* scroll bars are to be removed, and then save a scroll bar
2155 from the fiery pit when we actually redisplay its window. */
2156
2157/* Arrange for all scroll bars on FRAME to be removed at the next call
2158 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2159 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2160static void
2161XTcondemn_scroll_bars (frame)
2162 FRAME_PTR frame;
2163{
2164 /* The condemned list should be empty at this point; if it's not,
2165 then the rest of Emacs isn't using the condemn/redeem/judge
2166 protocol correctly. */
2167 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2168 abort ();
2169
2170 /* Move them all to the "condemned" list. */
2171 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2172 FRAME_SCROLL_BARS (frame) = Qnil;
2173}
2174
2175/* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2176 Note that WINDOW isn't necessarily condemned at all. */
2177static void
2178XTredeem_scroll_bar (window)
2179 struct window *window;
2180{
2181 struct scroll_bar *bar;
2182
2183 /* We can't redeem this window's scroll bar if it doesn't have one. */
2184 if (NILP (window->vertical_scroll_bar))
2185 abort ();
2186
2187 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2188
2189 /* Unlink it from the condemned list. */
2190 {
2191 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2192
2193 if (NILP (bar->prev))
2194 {
2195 /* If the prev pointer is nil, it must be the first in one of
2196 the lists. */
2197 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2198 /* It's not condemned. Everything's fine. */
2199 return;
2200 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2201 window->vertical_scroll_bar))
2202 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2203 else
2204 /* If its prev pointer is nil, it must be at the front of
2205 one or the other! */
2206 abort ();
2207 }
2208 else
2209 XSCROLL_BAR (bar->prev)->next = bar->next;
2210
2211 if (! NILP (bar->next))
2212 XSCROLL_BAR (bar->next)->prev = bar->prev;
2213
2214 bar->next = FRAME_SCROLL_BARS (f);
2215 bar->prev = Qnil;
2216 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2217 if (! NILP (bar->next))
2218 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2219 }
2220}
2221
2222/* Remove all scroll bars on FRAME that haven't been saved since the
2223 last call to `*condemn_scroll_bars_hook'. */
2224static void
2225XTjudge_scroll_bars (f)
2226 FRAME_PTR f;
2227{
2228 Lisp_Object bar, next;
2229
2230 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2231
2232 /* Clear out the condemned list now so we won't try to process any
2233 more events on the hapless scroll bars. */
2234 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2235
2236 for (; ! NILP (bar); bar = next)
2237 {
2238 struct scroll_bar *b = XSCROLL_BAR (bar);
2239
2240 x_scroll_bar_remove (b);
2241
2242 next = b->next;
2243 b->next = b->prev = Qnil;
2244 }
2245
2246 /* Now there should be no references to the condemned scroll bars,
2247 and they should get garbage-collected. */
2248}
2249
2250
2251/* Handle an Expose or GraphicsExpose event on a scroll bar.
2252
2253 This may be called from a signal handler, so we have to ignore GC
2254 mark bits. */
2255static void
2256x_scroll_bar_expose (bar, event)
2257 struct scroll_bar *bar;
2258 XEvent *event;
2259{
2260 Window w = SCROLL_BAR_X_WINDOW (bar);
2261 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2262
2263 BLOCK_INPUT;
2264
2265 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2266
2267 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2268 XDrawRectangle (x_current_display, w, gc,
2269
2270 /* x, y, width, height */
2271 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2272
2273 /* Draw another line to make the extra-thick border on the right. */
2274 XFillRectangle (x_current_display, w, gc,
2275
2276 /* x, y, width, height */
2277 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2278
2279 UNBLOCK_INPUT;
2280}
2281
2282/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2283 is set to something other than no_event, it is enqueued.
2284
2285 This may be called from a signal handler, so we have to ignore GC
2286 mark bits. */
2287static void
2288x_scroll_bar_handle_click (bar, event, emacs_event)
2289 struct scroll_bar *bar;
2290 XEvent *event;
2291 struct input_event *emacs_event;
2292{
2293 if (XGCTYPE (bar->window) != Lisp_Window)
2294 abort ();
2295
2296 emacs_event->kind = scroll_bar_click;
2297 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2298 emacs_event->modifiers =
2299 (x_x_to_emacs_modifiers (event->xbutton.state)
2300 | (event->type == ButtonRelease
2301 ? up_modifier
2302 : down_modifier));
2303 emacs_event->frame_or_window = bar->window;
2304 emacs_event->timestamp = event->xbutton.time;
2305 {
2306 int internal_height =
2307 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2308 int top_range =
2309 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2310 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2311
2312 if (y < 0) y = 0;
2313 if (y > top_range) y = top_range;
2314
2315 if (y < XINT (bar->start))
2316 emacs_event->part = scroll_bar_above_handle;
2317 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2318 emacs_event->part = scroll_bar_handle;
2319 else
2320 emacs_event->part = scroll_bar_below_handle;
2321
2322 /* Just because the user has clicked on the handle doesn't mean
2323 they want to drag it. Lisp code needs to be able to decide
2324 whether or not we're dragging. */
2325#if 0
2326 /* If the user has just clicked on the handle, record where they're
2327 holding it. */
2328 if (event->type == ButtonPress
2329 && emacs_event->part == scroll_bar_handle)
2330 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2331#endif
2332
2333 /* If the user has released the handle, set it to its final position. */
2334 if (event->type == ButtonRelease
2335 && ! NILP (bar->dragging))
2336 {
2337 int new_start = y - XINT (bar->dragging);
2338 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2339
2340 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2341 bar->dragging = Qnil;
2342 }
2343
2344 /* Same deal here as the other #if 0. */
2345#if 0
2346 /* Clicks on the handle are always reported as occurring at the top of
2347 the handle. */
2348 if (emacs_event->part == scroll_bar_handle)
2349 emacs_event->x = bar->start;
2350 else
2351 XSET (emacs_event->x, Lisp_Int, y);
2352#else
2353 XSET (emacs_event->x, Lisp_Int, y);
2354#endif
2355
2356 XSET (emacs_event->y, Lisp_Int, top_range);
2357 }
2358}
2359
2360/* Handle some mouse motion while someone is dragging the scroll bar.
2361
2362 This may be called from a signal handler, so we have to ignore GC
2363 mark bits. */
2364static void
2365x_scroll_bar_note_movement (bar, event)
2366 struct scroll_bar *bar;
2367 XEvent *event;
2368{
2369 last_mouse_movement_time = event->xmotion.time;
2370
2371 mouse_moved = 1;
2372 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2373
2374 /* If we're dragging the bar, display it. */
2375 if (! GC_NILP (bar->dragging))
2376 {
2377 /* Where should the handle be now? */
2378 int new_start = event->xmotion.y - XINT (bar->dragging);
2379
2380 if (new_start != XINT (bar->start))
2381 {
2382 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2383
2384 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2385 }
2386 }
2387
2388 /* Call XQueryPointer so we'll get an event the next time the mouse
2389 moves and we can see *still* on the same position. */
2390 {
2391 int dummy;
2392
2393 XQueryPointer (event->xmotion.display, event->xmotion.window,
2394 (Window *) &dummy, (Window *) &dummy,
2395 &dummy, &dummy, &dummy, &dummy,
2396 (unsigned int *) &dummy);
2397 }
2398}
2399
2400/* Return information to the user about the current position of the mouse
2401 on the scroll bar. */
2402static void
2403x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2404 FRAME_PTR *f;
2405 Lisp_Object *bar_window;
2406 enum scroll_bar_part *part;
2407 Lisp_Object *x, *y;
2408 unsigned long *time;
2409{
2410 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2411 int win_x, win_y;
2412 Window dummy_window;
2413 int dummy_coord;
2414 unsigned int dummy_mask;
2415
2416 BLOCK_INPUT;
2417
2418 /* Get the mouse's position relative to the scroll bar window, and
2419 report that. */
2420 if (! XQueryPointer (x_current_display,
2421 SCROLL_BAR_X_WINDOW (bar),
2422
2423 /* Root, child, root x and root y. */
2424 &dummy_window, &dummy_window,
2425 &dummy_coord, &dummy_coord,
2426
2427 /* Position relative to scroll bar. */
2428 &win_x, &win_y,
2429
2430 /* Mouse buttons and modifier keys. */
2431 &dummy_mask))
2432 *f = 0;
2433 else
2434 {
2435 int inside_height
2436 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2437 int top_range
2438 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2439
2440 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2441
2442 if (! NILP (bar->dragging))
2443 win_y -= XINT (bar->dragging);
2444
2445 if (win_y < 0)
2446 win_y = 0;
2447 if (win_y > top_range)
2448 win_y = top_range;
2449
2450 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2451 *bar_window = bar->window;
2452
2453 if (! NILP (bar->dragging))
2454 *part = scroll_bar_handle;
2455 else if (win_y < XINT (bar->start))
2456 *part = scroll_bar_above_handle;
2457 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2458 *part = scroll_bar_handle;
2459 else
2460 *part = scroll_bar_below_handle;
2461
2462 XSET (*x, Lisp_Int, win_y);
2463 XSET (*y, Lisp_Int, top_range);
2464
2465 mouse_moved = 0;
2466 last_mouse_scroll_bar = Qnil;
2467 }
2468
2469 *time = last_mouse_movement_time;
2470
2471 UNBLOCK_INPUT;
2472}
2473
2474
2475/* The screen has been cleared so we may have changed foreground or
2476 background colors, and the scroll bars may need to be redrawn.
2477 Clear out the scroll bars, and ask for expose events, so we can
2478 redraw them. */
2479
2480x_scroll_bar_clear (f)
2481 FRAME_PTR f;
2482{
2483 Lisp_Object bar;
2484
2485 for (bar = FRAME_SCROLL_BARS (f);
2486 XTYPE (bar) == Lisp_Vector;
2487 bar = XSCROLL_BAR (bar)->next)
2488 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2489 0, 0, 0, 0, True);
2490}
2491
2492
2493\f
2494/* The main X event-reading loop - XTread_socket. */
2495
2496/* Timestamp of enter window event. This is only used by XTread_socket,
2497 but we have to put it out here, since static variables within functions
2498 sometimes don't work. */
2499static Time enter_timestamp;
2500
2501/* This holds the state XLookupString needs to implement dead keys
2502 and other tricks known as "compose processing". _X Window System_
2503 says that a portable program can't use this, but Stephen Gildea assures
2504 me that letting the compiler initialize it to zeros will work okay.
2505
2506 This must be defined outside of XTread_socket, for the same reasons
2507 given for enter_timestamp, above. */
2508static XComposeStatus compose_status;
2509
2510/* Communication with window managers. */
2511Atom Xatom_wm_protocols;
2512
2513/* Kinds of protocol things we may receive. */
2514Atom Xatom_wm_take_focus;
2515Atom Xatom_wm_save_yourself;
2516Atom Xatom_wm_delete_window;
2517
2518/* Other WM communication */
2519Atom Xatom_wm_configure_denied; /* When our config request is denied */
2520Atom Xatom_wm_window_moved; /* When the WM moves us. */
2521
2522/* Window manager communication. */
2523Atom Xatom_wm_change_state;
2524
2525/* Record the last 100 characters stored
2526 to help debug the loss-of-chars-during-GC problem. */
2527int temp_index;
2528short temp_buffer[100];
2529
2530/* Read events coming from the X server.
2531 This routine is called by the SIGIO handler.
2532 We return as soon as there are no more events to be read.
2533
2534 Events representing keys are stored in buffer BUFP,
2535 which can hold up to NUMCHARS characters.
2536 We return the number of characters stored into the buffer,
2537 thus pretending to be `read'.
2538
2539 WAITP is nonzero if we should block until input arrives.
2540 EXPECTED is nonzero if the caller knows input is available. */
2541
2542int
2543XTread_socket (sd, bufp, numchars, waitp, expected)
2544 register int sd;
2545 register struct input_event *bufp;
2546 register int numchars;
2547 int waitp;
2548 int expected;
2549{
2550 int count = 0;
2551 int nbytes = 0;
2552 int mask;
2553 int items_pending; /* How many items are in the X queue. */
2554 XEvent event;
2555 struct frame *f;
2556 int event_found;
2557 int prefix;
2558 Lisp_Object part;
2559
2560 if (interrupt_input_blocked)
2561 {
2562 interrupt_input_pending = 1;
2563 return -1;
2564 }
2565
2566 interrupt_input_pending = 0;
2567 BLOCK_INPUT;
2568
2569 if (numchars <= 0)
2570 abort (); /* Don't think this happens. */
2571
2572#ifdef FIOSNBIO
2573 /* If available, Xlib uses FIOSNBIO to make the socket
2574 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2575 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2576 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2577 fcntl (fileno (stdin), F_SETFL, 0);
2578#endif /* ! defined (FIOSNBIO) */
2579
2580#ifndef SIGIO
2581#ifndef HAVE_SELECT
2582 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2583 {
2584 extern int read_alarm_should_throw;
2585 read_alarm_should_throw = 1;
2586 XPeekEvent (XDISPLAY &event);
2587 read_alarm_should_throw = 0;
2588 }
2589#endif /* HAVE_SELECT */
2590#endif /* SIGIO */
2591
2592 while (XStuffPending () != 0)
2593 {
2594 XNextEvent (XDISPLAY &event);
2595 event_found = 1;
2596
2597 switch (event.type)
2598 {
2599#ifdef HAVE_X11
2600 case ClientMessage:
2601 {
2602 if (event.xclient.message_type == Xatom_wm_protocols
2603 && event.xclient.format == 32)
2604 {
2605 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2606 {
2607 f = x_window_to_frame (event.xclient.window);
2608 if (f)
2609 x_focus_on_frame (f);
2610 /* Not certain about handling scroll bars here */
2611 }
2612 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2613 {
2614 /* Save state modify the WM_COMMAND property to
2615 something which can reinstate us. This notifies
2616 the session manager, who's looking for such a
2617 PropertyNotify. Can restart processing when
2618 a keyboard or mouse event arrives. */
2619 if (numchars > 0)
2620 {
2621 }
2622 }
2623 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2624 {
2625 struct frame *f = x_window_to_frame (event.xclient.window);
2626
2627 if (f)
2628 if (numchars > 0)
2629 {
2630 }
2631 }
2632 }
2633 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2634 {
2635 }
2636 else if (event.xclient.message_type == Xatom_wm_window_moved)
2637 {
2638 int new_x, new_y;
2639
2640 new_x = event.xclient.data.s[0];
2641 new_y = event.xclient.data.s[1];
2642 }
2643 }
2644 break;
2645
2646#ifdef NEW_SELECTIONS
2647 case SelectionNotify:
2648 x_handle_selection_notify (&event);
2649 break;
2650#endif
2651
2652 case SelectionClear: /* Someone has grabbed ownership. */
2653#ifdef NEW_SELECTIONS
2654 {
2655 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2656
2657 if (numchars == 0)
2658 abort ();
2659
2660 bufp->kind = selection_clear_event;
2661 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2662 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2663 SELECTION_EVENT_TIME (bufp) = eventp->time;
2664 bufp++;
2665
2666 count += 1;
2667 numchars -= 1;
2668 }
2669#else
2670 x_disown_selection (event.xselectionclear.window,
2671 event.xselectionclear.selection,
2672 event.xselectionclear.time);
2673#endif
2674 break;
2675
2676 case SelectionRequest: /* Someone wants our selection. */
2677#ifdef NEW_SELECTIONS
2678 {
2679 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2680
2681 if (numchars == 0)
2682 abort ();
2683
2684 bufp->kind = selection_request_event;
2685 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2686 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2687 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2688 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2689 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2690 SELECTION_EVENT_TIME (bufp) = eventp->time;
2691 bufp++;
2692
2693 count += 1;
2694 numchars -= 1;
2695 }
2696#else
2697 x_answer_selection_request (event);
2698#endif
2699 break;
2700
2701 case PropertyNotify:
2702#ifdef NEW_SELECTIONS
2703 x_handle_property_notify (&event);
2704#else
2705 /* If we're being told about a root window property, then it's
2706 a cut buffer change. */
2707 if (event.xproperty.window == ROOT_WINDOW)
2708 x_invalidate_cut_buffer_cache (&event.xproperty);
2709
2710 /* Otherwise, we're probably handling an incremental
2711 selection transmission. */
2712 else
2713 {
2714 /* If we were to do this synchronously, there'd be no worry
2715 about re-selecting. */
2716 x_send_incremental (event);
2717 }
2718#endif
2719 break;
2720
2721 case ReparentNotify:
2722 f = x_window_to_frame (event.xreparent.window);
2723 if (f)
2724 f->display.x->parent_desc = event.xreparent.parent;
2725 break;
2726
2727 case Expose:
2728 f = x_window_to_frame (event.xexpose.window);
2729 if (f)
2730 {
2731 if (f->async_visible == 0)
2732 {
2733 f->async_visible = 1;
2734 f->async_iconified = 0;
2735 SET_FRAME_GARBAGED (f);
2736 }
2737 else
2738 {
2739 dumprectangle (x_window_to_frame (event.xexpose.window),
2740 event.xexpose.x, event.xexpose.y,
2741 event.xexpose.width, event.xexpose.height);
2742 }
2743 }
2744 else
2745 {
2746 struct scroll_bar *bar
2747 = x_window_to_scroll_bar (event.xexpose.window);
2748
2749 if (bar)
2750 x_scroll_bar_expose (bar, &event);
2751 }
2752 break;
2753
2754 case GraphicsExpose: /* This occurs when an XCopyArea's
2755 source area was obscured or not
2756 available.*/
2757 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2758 if (f)
2759 {
2760 dumprectangle (f,
2761 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2762 event.xgraphicsexpose.width,
2763 event.xgraphicsexpose.height);
2764 }
2765 break;
2766
2767 case NoExpose: /* This occurs when an XCopyArea's
2768 source area was completely
2769 available */
2770 break;
2771#else /* ! defined (HAVE_X11) */
2772 case ExposeWindow:
2773 if (event.subwindow != 0)
2774 break; /* duplicate event */
2775 f = x_window_to_frame (event.window);
2776 if (event.window == f->display.x->icon_desc)
2777 {
2778 refreshicon (f);
2779 f->async_iconified = 1;
2780 }
2781 if (event.window == FRAME_X_WINDOW (f))
2782 {
2783 /* Say must check all windows' needs_exposure flags. */
2784 expose_all_windows = 1;
2785 f->display.x->needs_exposure = 1;
2786 f->async_visible = 1;
2787 }
2788 break;
2789
2790 case ExposeRegion:
2791 if (event.subwindow != 0)
2792 break; /* duplicate event */
2793 f = x_window_to_frame (event.window);
2794 if (event.window == f->display.x->icon_desc)
2795 {
2796 refreshicon (f);
2797 break;
2798 }
2799 /* If window already needs full redraw, ignore this rectangle. */
2800 if (expose_all_windows && f->display.x->needs_exposure)
2801 break;
2802 /* Put the event on the queue of rectangles to redraw. */
2803 if (enqueue_event (&event, &x_expose_queue))
2804 /* If it is full, we can't record the rectangle,
2805 so redraw this entire window. */
2806 {
2807 /* Say must check all windows' needs_exposure flags. */
2808 expose_all_windows = 1;
2809 f->display.x->needs_exposure = 1;
2810 }
2811 break;
2812
2813 case ExposeCopy:
2814 /* This should happen only when we are expecting it,
2815 in x_read_exposes. */
2816 abort ();
2817#endif /* ! defined (HAVE_X11) */
2818
2819#ifdef HAVE_X11
2820 case UnmapNotify:
2821 f = x_window_to_frame (event.xunmap.window);
2822 if (f) /* F may no longer exist if
2823 the frame was deleted. */
2824 {
2825 /* While a frame is unmapped, display generation is
2826 disabled; you don't want to spend time updating a
2827 display that won't ever be seen. */
2828 f->async_visible = 0;
2829 /* The window manager never makes a window invisible
2830 ("withdrawn"); all it does is switch between visible
2831 and iconified. Frames get into the invisible state
2832 only through x_make_frame_invisible.
2833 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2834 f->async_iconified = 1;
2835 }
2836 break;
2837
2838 case MapNotify:
2839 f = x_window_to_frame (event.xmap.window);
2840 if (f)
2841 {
2842 f->async_visible = 1;
2843 f->async_iconified = 0;
2844
2845 /* wait_reading_process_input will notice this and update
2846 the frame's display structures. */
2847 SET_FRAME_GARBAGED (f);
2848 }
2849 break;
2850
2851 /* Turn off processing if we become fully obscured. */
2852 case VisibilityNotify:
2853 break;
2854
2855#else /* ! defined (HAVE_X11) */
2856 case UnmapWindow:
2857 f = x_window_to_frame (event.window);
2858 if (event.window == f->display.x->icon_desc)
2859 f->async_iconified = 0;
2860 if (event.window == FRAME_X_WINDOW (f))
2861 f->async_visible = 0;
2862 break;
2863#endif /* ! defined (HAVE_X11) */
2864
2865#ifdef HAVE_X11
2866 case KeyPress:
2867 f = x_window_to_frame (event.xkey.window);
2868
2869 if (f != 0)
2870 {
2871 KeySym keysym, orig_keysym;
2872 char copy_buffer[80];
2873 int modifiers;
2874
2875 event.xkey.state
2876 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
2877 modifiers = event.xkey.state;
2878
2879 /* This will have to go some day... */
2880
2881 /* make_lispy_event turns chars into control chars.
2882 Don't do it here because XLookupString is too eager. */
2883 event.xkey.state &= ~ControlMask;
2884 nbytes =
2885 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2886 &compose_status);
2887
2888 /* Strip off the vendor-specific keysym bit, and take a shot
2889 at recognizing the codes. HP servers have extra keysyms
2890 that fit into the MiscFunctionKey category. */
2891 orig_keysym = keysym;
2892 keysym &= ~(1<<28);
2893
2894 if (numchars > 1)
2895 {
2896 if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
2897 || keysym == XK_Delete
2898 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2899 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
2900#ifdef HPUX
2901 /* This recognizes the "extended function keys".
2902 It seems there's no cleaner way.
2903 Test IsModifierKey to avoid handling mode_switch
2904 incorrectly. */
2905 || (!IsModifierKey (orig_keysym)
2906 && (unsigned) (keysym) >= XK_Select
2907 && (unsigned)(keysym) < XK_KP_Space)
2908#endif
2909 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2910 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
2911 || x_is_vendor_fkey (orig_keysym)) /* wherever */
2912 {
2913 if (temp_index == sizeof temp_buffer / sizeof (short))
2914 temp_index = 0;
2915 temp_buffer[temp_index++] = keysym;
2916 bufp->kind = non_ascii_keystroke;
2917 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2918 XSET (bufp->frame_or_window, Lisp_Frame, f);
2919 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2920 bufp->timestamp = event.xkey.time;
2921 bufp++;
2922 count++;
2923 numchars--;
2924 }
2925 else if (numchars > nbytes)
2926 {
2927 register int i;
2928
2929 for (i = 0; i < nbytes; i++)
2930 {
2931 if (temp_index == sizeof temp_buffer / sizeof (short))
2932 temp_index = 0;
2933 temp_buffer[temp_index++] = copy_buffer[i];
2934 bufp->kind = ascii_keystroke;
2935 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2936 XSET (bufp->frame_or_window, Lisp_Frame, f);
2937 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2938 bufp->timestamp = event.xkey.time;
2939 bufp++;
2940 }
2941
2942 count += nbytes;
2943 numchars -= nbytes;
2944 }
2945 else
2946 abort ();
2947 }
2948 else
2949 abort ();
2950 }
2951 break;
2952#else /* ! defined (HAVE_X11) */
2953 case KeyPressed:
2954 {
2955 register char *where_mapping;
2956
2957 f = x_window_to_frame (event.window);
2958 /* Ignore keys typed on icon windows. */
2959 if (f != 0 && event.window == f->display.x->icon_desc)
2960 break;
2961 where_mapping = XLookupMapping (&event, &nbytes);
2962 /* Nasty fix for arrow keys */
2963 if (!nbytes && IsCursorKey (event.detail & 0xff))
2964 {
2965 switch (event.detail & 0xff)
2966 {
2967 case KC_CURSOR_LEFT:
2968 where_mapping = "\002";
2969 break;
2970 case KC_CURSOR_RIGHT:
2971 where_mapping = "\006";
2972 break;
2973 case KC_CURSOR_UP:
2974 where_mapping = "\020";
2975 break;
2976 case KC_CURSOR_DOWN:
2977 where_mapping = "\016";
2978 break;
2979 }
2980 nbytes = 1;
2981 }
2982 if (numchars - nbytes > 0)
2983 {
2984 register int i;
2985
2986 for (i = 0; i < nbytes; i++)
2987 {
2988 bufp->kind = ascii_keystroke;
2989 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2990 XSET (bufp->time, Lisp_Int, event.xkey.time);
2991 XSET (bufp->frame_or_window, Lisp_Frame, f);
2992 bufp++;
2993 }
2994 count += nbytes;
2995 numchars -= nbytes;
2996 }
2997 }
2998 break;
2999#endif /* ! defined (HAVE_X11) */
3000
3001#ifdef HAVE_X11
3002
3003 /* Here's a possible interpretation of the whole
3004 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3005 FocusIn event, you have to get a FocusOut event before you
3006 relinquish the focus. If you haven't received a FocusIn event,
3007 then a mere LeaveNotify is enough to free you. */
3008
3009 case EnterNotify:
3010 f = x_window_to_frame (event.xcrossing.window);
3011
3012 if (event.xcrossing.focus) /* Entered Window */
3013 {
3014 /* Avoid nasty pop/raise loops. */
3015 if (f && (!(f->auto_raise)
3016 || !(f->auto_lower)
3017 || (event.xcrossing.time - enter_timestamp) > 500))
3018 {
3019 x_new_focus_frame (f);
3020 enter_timestamp = event.xcrossing.time;
3021 }
3022 }
3023 else if (f == x_focus_frame)
3024 x_new_focus_frame (0);
3025
3026 break;
3027
3028 case FocusIn:
3029 f = x_window_to_frame (event.xfocus.window);
3030 if (event.xfocus.detail != NotifyPointer)
3031 x_focus_event_frame = f;
3032 if (f)
3033 x_new_focus_frame (f);
3034 break;
3035
3036
3037 case LeaveNotify:
3038 f = x_window_to_frame (event.xcrossing.window);
3039
3040 if (event.xcrossing.focus)
3041 {
3042 if (! x_focus_event_frame)
3043 x_new_focus_frame (0);
3044 else
3045 x_new_focus_frame (f);
3046 }
3047 else
3048 {
3049 if (f == x_focus_event_frame)
3050 x_focus_event_frame = 0;
3051 if (f == x_focus_frame)
3052 x_new_focus_frame (0);
3053 }
3054 break;
3055
3056 case FocusOut:
3057 f = x_window_to_frame (event.xfocus.window);
3058 if (event.xfocus.detail != NotifyPointer
3059 && f == x_focus_event_frame)
3060 x_focus_event_frame = 0;
3061 if (f && f == x_focus_frame)
3062 x_new_focus_frame (0);
3063 break;
3064
3065#else /* ! defined (HAVE_X11) */
3066
3067 case EnterWindow:
3068 if ((event.detail & 0xFF) == 1)
3069 break; /* Coming from our own subwindow */
3070 if (event.subwindow != 0)
3071 break; /* Entering our own subwindow. */
3072
3073 {
3074 f = x_window_to_frame (event.window);
3075 x_mouse_frame = f;
3076
3077 x_new_focus_frame (f);
3078 }
3079 break;
3080
3081 case LeaveWindow:
3082 if ((event.detail & 0xFF) == 1)
3083 break; /* Entering our own subwindow */
3084 if (event.subwindow != 0)
3085 break; /* Leaving our own subwindow. */
3086
3087 x_mouse_frame = 0;
3088 if (x_focus_frame == 0
3089 && x_input_frame != 0
3090 && x_input_frame == x_window_to_frame (event.window)
3091 && event.window == FRAME_X_WINDOW (x_input_frame))
3092 {
3093 f = x_input_frame;
3094 x_input_frame = 0;
3095 if (f)
3096 frame_unhighlight (f);
3097 }
3098 break;
3099#endif /* ! defined (HAVE_X11) */
3100
3101#ifdef HAVE_X11
3102 case MotionNotify:
3103 {
3104 f = x_window_to_frame (event.xmotion.window);
3105 if (f)
3106 note_mouse_movement (f, &event.xmotion);
3107 else
3108 {
3109 struct scroll_bar *bar =
3110 x_window_to_scroll_bar (event.xmotion.window);
3111
3112 if (bar)
3113 x_scroll_bar_note_movement (bar, &event);
3114 }
3115 }
3116 break;
3117
3118 case ConfigureNotify:
3119 f = x_window_to_frame (event.xconfigure.window);
3120 if (f)
3121 {
3122 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3123 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3124
3125 /* Even if the number of character rows and columns has
3126 not changed, the font size may have changed, so we need
3127 to check the pixel dimensions as well. */
3128 if (columns != f->width
3129 || rows != f->height
3130 || event.xconfigure.width != f->display.x->pixel_width
3131 || event.xconfigure.height != f->display.x->pixel_height)
3132 {
3133 change_frame_size (f, rows, columns, 0, 1);
3134 SET_FRAME_GARBAGED (f);
3135 }
3136
3137 if (! event.xconfigure.send_event)
3138 {
3139 Window win, child;
3140 int win_x, win_y;
3141
3142 /* Coords are relative to the parent.
3143 Convert them to root-relative. */
3144 XTranslateCoordinates (x_current_display,
3145
3146 /* From-window, to-window. */
3147 f->display.x->parent_desc,
3148 ROOT_WINDOW,
3149
3150 /* From-position, to-position. */
3151 event.xconfigure.x,
3152 event.xconfigure.y,
3153 &win_x, &win_y,
3154
3155 /* Child of win. */
3156 &child);
3157 event.xconfigure.x = win_x;
3158 event.xconfigure.y = win_y;
3159 }
3160
3161 f->display.x->pixel_width = event.xconfigure.width;
3162 f->display.x->pixel_height = event.xconfigure.height;
3163 f->display.x->left_pos = event.xconfigure.x;
3164 f->display.x->top_pos = event.xconfigure.y;
3165 }
3166 break;
3167
3168 case ButtonPress:
3169 case ButtonRelease:
3170 {
3171 /* If we decide we want to generate an event to be seen
3172 by the rest of Emacs, we put it here. */
3173 struct input_event emacs_event;
3174 emacs_event.kind = no_event;
3175
3176 f = x_window_to_frame (event.xbutton.window);
3177 if (f)
3178 {
3179 if (!x_focus_frame || (f == x_focus_frame))
3180 construct_mouse_click (&emacs_event,
3181 &event, f);
3182 }
3183 else
3184 {
3185 struct scroll_bar *bar =
3186 x_window_to_scroll_bar (event.xbutton.window);
3187
3188 if (bar)
3189 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3190 }
3191
3192 if (numchars >= 1 && emacs_event.kind != no_event)
3193 {
3194 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3195 bufp++;
3196 count++;
3197 numchars--;
3198 }
3199 }
3200 break;
3201
3202#else /* ! defined (HAVE_X11) */
3203 case ButtonPressed:
3204 case ButtonReleased:
3205 f = x_window_to_frame (event.window);
3206 if (f)
3207 {
3208 if (event.window == f->display.x->icon_desc)
3209 {
3210 x_make_frame_visible (f);
3211
3212 if (warp_mouse_on_deiconify)
3213 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3214 break;
3215 }
3216 if (event.window == FRAME_X_WINDOW (f))
3217 {
3218 if (f->auto_raise)
3219 x_raise_frame (f);
3220 }
3221 }
3222 enqueue_event (&event, &x_mouse_queue);
3223 if (numchars >= 2)
3224 {
3225 bufp->kind = ascii_keystroke;
3226 bufp->code = (char) 'X' & 037; /* C-x */
3227 XSET (bufp->frame_or_window, Lisp_Frame, f);
3228 XSET (bufp->time, Lisp_Int, event.xkey.time);
3229 bufp++;
3230
3231 bufp->kind = ascii_keystroke;
3232 bufp->code = (char) 0; /* C-@ */
3233 XSET (bufp->frame_or_window, Lisp_Frame, f);
3234 XSET (bufp->time, Lisp_Int, event.xkey.time);
3235 bufp++;
3236
3237 count += 2;
3238 numchars -= 2;
3239 }
3240 break;
3241#endif /* ! defined (HAVE_X11) */
3242
3243#ifdef HAVE_X11
3244
3245 case CirculateNotify:
3246 break;
3247 case CirculateRequest:
3248 break;
3249
3250#endif /* ! defined (HAVE_X11) */
3251
3252 case MappingNotify:
3253 /* Someone has changed the keyboard mapping - update the
3254 local cache. */
3255 switch (event.xmapping.request)
3256 {
3257 case MappingModifier:
3258 x_find_modifier_meanings ();
3259 /* This is meant to fall through. */
3260 case MappingKeyboard:
3261 XRefreshKeyboardMapping (&event.xmapping);
3262 }
3263 break;
3264
3265 default:
3266 break;
3267 }
3268 }
3269
3270#if 0
3271#ifdef HAVE_SELECT
3272 if (expected && ! event_found)
3273 {
3274 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3275 there is an EOF condition; in other words, that X has died.
3276 Act as if there had been a hangup. */
3277
3278 int fd = ConnectionNumber (x_current_display);
3279 int mask = 1 << fd;
3280
3281 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3282 (EMACS_TIME) 0)
3283 && !XStuffPending ())
3284 kill (getpid (), SIGHUP);
3285 }
3286#endif /* ! defined (HAVE_SELECT) */
3287#endif /* ! 0 */
3288
3289#ifndef HAVE_X11
3290 if (updating_frame == 0)
3291 x_do_pending_expose ();
3292#endif
3293
3294 UNBLOCK_INPUT;
3295 return count;
3296}
3297
3298#ifndef HAVE_X11
3299/* Read and process only Expose events
3300 until we get an ExposeCopy event; then return.
3301 This is used in insert/delete line.
3302 We assume input is already blocked. */
3303
3304static void
3305x_read_exposes ()
3306{
3307 struct frame *f;
3308 XKeyPressedEvent event;
3309
3310 while (1)
3311 {
3312 /* while there are more events*/
3313 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3314 switch (event.type)
3315 {
3316 case ExposeWindow:
3317 if (event.subwindow != 0)
3318 break; /* duplicate event */
3319 f = x_window_to_frame (event.window);
3320 if (event.window == f->display.x->icon_desc)
3321 {
3322 refreshicon (f);
3323 break;
3324 }
3325 if (event.window == FRAME_X_WINDOW (f))
3326 {
3327 expose_all_windows = 1;
3328 f->display.x->needs_exposure = 1;
3329 break;
3330 }
3331 break;
3332
3333 case ExposeRegion:
3334 if (event.subwindow != 0)
3335 break; /* duplicate event */
3336 f = x_window_to_frame (event.window);
3337 if (event.window == f->display.x->icon_desc)
3338 {
3339 refreshicon (f);
3340 break;
3341 }
3342 /* If window already needs full redraw, ignore this rectangle. */
3343 if (expose_all_windows && f->display.x->needs_exposure)
3344 break;
3345 /* Put the event on the queue of rectangles to redraw. */
3346 if (enqueue_event (&event, &x_expose_queue))
3347 /* If it is full, we can't record the rectangle,
3348 so redraw this entire window. */
3349 {
3350 /* Say must check all windows' needs_exposure flags. */
3351 expose_all_windows = 1;
3352 f->display.x->needs_exposure = 1;
3353 }
3354 break;
3355
3356 case ExposeCopy:
3357 return;
3358 }
3359 }
3360}
3361#endif /* HAVE_X11 */
3362
3363\f
3364/* Drawing the cursor. */
3365
3366
3367/* Draw a hollow box cursor. Don't change the inside of the box. */
3368
3369static void
3370x_draw_box (f)
3371 struct frame *f;
3372{
3373 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3374 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3375 int width = FONT_WIDTH (f->display.x->font);
3376 int height = FONT_HEIGHT (f->display.x->font);
3377
3378#ifdef HAVE_X11
3379 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3380 f->display.x->cursor_gc,
3381 left, top, width - 1, height - 1);
3382#else /* ! defined (HAVE_X11) */
3383 XPixSet (FRAME_X_WINDOW (f),
3384 left, top, width, 1,
3385 f->display.x->cursor_pixel);
3386
3387 XPixSet (FRAME_X_WINDOW (f),
3388 left, top, 1, height,
3389 f->display.x->cursor_pixel);
3390
3391 XPixSet (FRAME_X_WINDOW (f),
3392 left+width-1, top, 1, height,
3393 f->display.x->cursor_pixel);
3394
3395 XPixSet (FRAME_X_WINDOW (f),
3396 left, top+height-1, width, 1,
3397 f->display.x->cursor_pixel);
3398#endif /* ! defined (HAVE_X11) */
3399}
3400
3401/* Clear the cursor of frame F to background color,
3402 and mark the cursor as not shown.
3403 This is used when the text where the cursor is
3404 is about to be rewritten. */
3405
3406static void
3407clear_cursor (f)
3408 struct frame *f;
3409{
3410 int mask;
3411
3412 if (! FRAME_VISIBLE_P (f)
3413 || f->phys_cursor_x < 0)
3414 return;
3415
3416#ifdef HAVE_X11
3417 x_display_cursor (f, 0);
3418#else /* ! defined (HAVE_X11) */
3419 XPixSet (FRAME_X_WINDOW (f),
3420 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3421 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3422 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3423 f->display.x->background_pixel);
3424#endif /* ! defined (HAVE_X11) */
3425 f->phys_cursor_x = -1;
3426}
3427
3428/* Redraw the glyph at ROW, COLUMN on frame F, in the style
3429 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3430 glyph drawn. */
3431
3432static void
3433x_draw_single_glyph (f, row, column, glyph, highlight)
3434 struct frame *f;
3435 int row, column;
3436 GLYPH glyph;
3437 int highlight;
3438{
3439 dumpglyphs (f,
3440 CHAR_TO_PIXEL_COL (f, column),
3441 CHAR_TO_PIXEL_ROW (f, row),
3442 &glyph, 1, highlight);
3443}
3444
3445static void
3446x_display_bar_cursor (f, on)
3447 struct frame *f;
3448 int on;
3449{
3450 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3451
3452 /* This is pointless on invisible frames, and dangerous on garbaged
3453 frames; in the latter case, the frame may be in the midst of
3454 changing its size, and curs_x and curs_y may be off the frame. */
3455 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3456 return;
3457
3458 if (! on && f->phys_cursor_x < 0)
3459 return;
3460
3461 /* If we're not updating, then we want to use the current frame's
3462 cursor position, not our local idea of where the cursor ought to be. */
3463 if (f != updating_frame)
3464 {
3465 curs_x = FRAME_CURSOR_X (f);
3466 curs_y = FRAME_CURSOR_Y (f);
3467 }
3468
3469 /* If there is anything wrong with the current cursor state, remove it. */
3470 if (f->phys_cursor_x >= 0
3471 && (!on
3472 || f->phys_cursor_x != curs_x
3473 || f->phys_cursor_y != curs_y
3474 || f->display.x->current_cursor != bar_cursor))
3475 {
3476 /* Erase the cursor by redrawing the character underneath it. */
3477 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3478 f->phys_cursor_glyph,
3479 current_glyphs->highlight[f->phys_cursor_y]);
3480 f->phys_cursor_x = -1;
3481 }
3482
3483 /* If we now need a cursor in the new place or in the new form, do it so. */
3484 if (on
3485 && (f->phys_cursor_x < 0
3486 || (f->display.x->current_cursor != bar_cursor)))
3487 {
3488 f->phys_cursor_glyph
3489 = ((current_glyphs->enable[curs_y]
3490 && curs_x < current_glyphs->used[curs_y])
3491 ? current_glyphs->glyphs[curs_y][curs_x]
3492 : SPACEGLYPH);
3493 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3494 f->display.x->cursor_gc,
3495 CHAR_TO_PIXEL_COL (f, curs_x),
3496 CHAR_TO_PIXEL_ROW (f, curs_y),
3497 1, FONT_HEIGHT (f->display.x->font));
3498
3499 f->phys_cursor_x = curs_x;
3500 f->phys_cursor_y = curs_y;
3501
3502 f->display.x->current_cursor = bar_cursor;
3503 }
3504
3505 if (updating_frame != f)
3506 XFlushQueue ();
3507}
3508
3509
3510/* Turn the displayed cursor of frame F on or off according to ON.
3511 If ON is nonzero, where to put the cursor is specified
3512 by F->cursor_x and F->cursor_y. */
3513
3514static void
3515x_display_box_cursor (f, on)
3516 struct frame *f;
3517 int on;
3518{
3519 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3520
3521 /* This is pointless on invisible frames, and dangerous on garbaged
3522 frames; in the latter case, the frame may be in the midst of
3523 changing its size, and curs_x and curs_y may be off the frame. */
3524 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3525 return;
3526
3527 /* If cursor is off and we want it off, return quickly. */
3528 if (!on && f->phys_cursor_x < 0)
3529 return;
3530
3531 /* If we're not updating, then we want to use the current frame's
3532 cursor position, not our local idea of where the cursor ought to be. */
3533 if (f != updating_frame)
3534 {
3535 curs_x = FRAME_CURSOR_X (f);
3536 curs_y = FRAME_CURSOR_Y (f);
3537 }
3538
3539 /* If cursor is currently being shown and we don't want it to be
3540 or it is in the wrong place,
3541 or we want a hollow box and it's not so, (pout!)
3542 erase it. */
3543 if (f->phys_cursor_x >= 0
3544 && (!on
3545 || f->phys_cursor_x != curs_x
3546 || f->phys_cursor_y != curs_y
3547 || (f->display.x->current_cursor != hollow_box_cursor
3548 && (f != x_highlight_frame))))
3549 {
3550 /* Erase the cursor by redrawing the character underneath it. */
3551 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3552 f->phys_cursor_glyph,
3553 current_glyphs->highlight[f->phys_cursor_y]);
3554 f->phys_cursor_x = -1;
3555 }
3556
3557 /* If we want to show a cursor,
3558 or we want a box cursor and it's not so,
3559 write it in the right place. */
3560 if (on
3561 && (f->phys_cursor_x < 0
3562 || (f->display.x->current_cursor != filled_box_cursor
3563 && f == x_highlight_frame)))
3564 {
3565 f->phys_cursor_glyph
3566 = ((current_glyphs->enable[curs_y]
3567 && curs_x < current_glyphs->used[curs_y])
3568 ? current_glyphs->glyphs[curs_y][curs_x]
3569 : SPACEGLYPH);
3570 if (f != x_highlight_frame)
3571 {
3572 x_draw_box (f);
3573 f->display.x->current_cursor = hollow_box_cursor;
3574 }
3575 else
3576 {
3577 x_draw_single_glyph (f, curs_y, curs_x,
3578 f->phys_cursor_glyph, 2);
3579 f->display.x->current_cursor = filled_box_cursor;
3580 }
3581
3582 f->phys_cursor_x = curs_x;
3583 f->phys_cursor_y = curs_y;
3584 }
3585
3586 if (updating_frame != f)
3587 XFlushQueue ();
3588}
3589
3590x_display_cursor (f, on)
3591 struct frame *f;
3592 int on;
3593{
3594 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3595 x_display_box_cursor (f, on);
3596 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3597 x_display_bar_cursor (f, on);
3598 else
3599 /* Those are the only two we have implemented! */
3600 abort ();
3601}
3602\f
3603/* Icons. */
3604
3605/* Refresh bitmap kitchen sink icon for frame F
3606 when we get an expose event for it. */
3607
3608refreshicon (f)
3609 struct frame *f;
3610{
3611#ifdef HAVE_X11
3612 /* Normally, the window manager handles this function. */
3613#else /* ! defined (HAVE_X11) */
3614 int mask;
3615
3616 if (f->display.x->icon_bitmap_flag)
3617 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3618 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3619 icon_bitmap, GXcopy, AllPlanes);
3620 else
3621 {
3622 extern struct frame *selected_frame;
3623 struct Lisp_String *str;
3624 unsigned char *string;
3625
3626 string
3627 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3628
3629 if (f->display.x->icon_label != string)
3630 {
3631 f->display.x->icon_label = string;
3632 XChangeWindow (f->display.x->icon_desc,
3633 XQueryWidth (string, icon_font_info->id) + 10,
3634 icon_font_info->height + 10);
3635 }
3636
3637 XText (f->display.x->icon_desc, 5, 5, string,
3638 str->size, icon_font_info->id,
3639 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3640 }
3641 XFlushQueue ();
3642#endif /* ! defined (HAVE_X11) */
3643}
3644
3645/* Make the x-window of frame F use the gnu icon bitmap. */
3646
3647int
3648x_bitmap_icon (f)
3649 struct frame *f;
3650{
3651 int mask;
3652 Window icon_window;
3653
3654 if (FRAME_X_WINDOW (f) == 0)
3655 return 1;
3656
3657#ifdef HAVE_X11
3658 if (! icon_bitmap)
3659 icon_bitmap =
3660 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3661 gnu_bits, gnu_width, gnu_height);
3662 x_wm_set_icon_pixmap (f, icon_bitmap);
3663 f->display.x->icon_bitmap_flag = 1;
3664#else /* ! defined (HAVE_X11) */
3665 if (f->display.x->icon_desc)
3666 {
3667 XClearIconWindow (FRAME_X_WINDOW (f));
3668 XDestroyWindow (f->display.x->icon_desc);
3669 }
3670
3671 icon_window = XCreateWindow (f->display.x->parent_desc,
3672 0, 0, sink_width, sink_height,
3673 2, WhitePixmap, (Pixmap) NULL);
3674
3675 if (icon_window == 0)
3676 return 1;
3677
3678 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3679 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3680
3681 f->display.x->icon_desc = icon_window;
3682 f->display.x->icon_bitmap_flag = 1;
3683
3684 if (icon_bitmap == 0)
3685 icon_bitmap
3686 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3687#endif /* ! defined (HAVE_X11) */
3688
3689 return 0;
3690}
3691
3692
3693/* Make the x-window of frame F use a rectangle with text. */
3694
3695int
3696x_text_icon (f, icon_name)
3697 struct frame *f;
3698 char *icon_name;
3699{
3700#ifndef HAVE_X11
3701 int mask;
3702 int width;
3703 Window icon_window;
3704 char *X_DefaultValue;
3705 Bitmap b1;
3706
3707#ifndef WhitePixel
3708#define WhitePixel 1
3709#endif /* WhitePixel */
3710
3711#ifndef BlackPixel
3712#define BlackPixel 0
3713#endif /* BlackPixel */
3714#endif /* HAVE_X11 */
3715
3716 if (FRAME_X_WINDOW (f) == 0)
3717 return 1;
3718
3719#ifdef HAVE_X11
3720 if (icon_name)
3721 f->display.x->icon_label = icon_name;
3722 else
3723 if (! f->display.x->icon_label)
3724 f->display.x->icon_label = " *emacs* ";
3725
3726#if 0
3727 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3728 (char *) f->display.x->icon_label);
3729#endif
3730
3731 f->display.x->icon_bitmap_flag = 0;
3732 x_wm_set_icon_pixmap (f, 0);
3733#else /* ! defined (HAVE_X11) */
3734 if (icon_font_info == 0)
3735 icon_font_info
3736 = XGetFont (XGetDefault (XDISPLAY
3737 (char *) XSTRING (Vinvocation_name)->data,
3738 "BodyFont"));
3739
3740 if (f->display.x->icon_desc)
3741 {
3742 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3743 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3744 }
3745
3746 if (icon_name)
3747 f->display.x->icon_label = (unsigned char *) icon_name;
3748 else
3749 if (! f->display.x->icon_label)
3750 f->display.x->icon_label = XSTRING (f->name)->data;
3751
3752 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3753 icon_window = XCreateWindow (f->display.x->parent_desc,
3754 f->display.x->left_pos,
3755 f->display.x->top_pos,
3756 width + 10, icon_font_info->height + 10,
3757 2, BlackPixmap, WhitePixmap);
3758
3759 if (icon_window == 0)
3760 return 1;
3761
3762 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3763 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3764
3765 f->display.x->icon_desc = icon_window;
3766 f->display.x->icon_bitmap_flag = 0;
3767 f->display.x->icon_label = 0;
3768#endif /* ! defined (HAVE_X11) */
3769
3770 return 0;
3771}
3772\f
3773/* Handling X errors. */
3774
3775/* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3776 X server's connection, or an error reported via the X protocol. */
3777
3778static SIGTYPE
3779x_connection_closed ()
3780{
3781 if (_Xdebug)
3782 abort ();
3783
3784 shut_down_emacs (0, 1, Qnil);
3785
3786 exit (70);
3787}
3788
3789/* An X error handler which prints an error message and then kills
3790 Emacs. This is what's normally installed as Xlib's handler for
3791 protocol errors. */
3792static int
3793x_error_quitter (display, error)
3794 Display *display;
3795 XErrorEvent *error;
3796{
3797 char buf[256];
3798
3799 /* Note that there is no real way portable across R3/R4 to get the
3800 original error handler. */
3801
3802 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3803 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3804 buf, error->request_code);
3805
3806#if 0
3807 /* While we're testing Emacs 19, we'll just dump core whenever we
3808 get an X error, so we can figure out why it happened. */
3809 abort ();
3810#endif
3811
3812 x_connection_closed ();
3813}
3814
3815/* A handler for X IO errors which prints an error message and then
3816 kills Emacs. This is what is always installed as Xlib's handler
3817 for I/O errors. */
3818static int
3819x_io_error_quitter (display)
3820 Display *display;
3821{
3822 fprintf (stderr, "Connection to X server %s lost.\n",
3823 XDisplayName (DisplayString (display)));
3824
3825#if 0
3826 /* While we're testing Emacs 19, we'll just dump core whenever we
3827 get an X error, so we can figure out why it happened. */
3828 abort ();
3829#endif
3830
3831 x_connection_closed ();
3832}
3833
3834/* A buffer for storing X error messages. */
3835static char *x_caught_error_message;
3836#define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3837
3838/* An X error handler which stores the error message in
3839 x_caught_error_message. This is what's installed when
3840 x_catch_errors is in effect. */
3841static int
3842x_error_catcher (display, error)
3843 Display *display;
3844 XErrorEvent *error;
3845{
3846 XGetErrorText (display, error->error_code,
3847 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
3848}
3849
3850
3851/* Begin trapping X errors.
3852
3853 After calling this function, X protocol errors no longer cause
3854 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3855
3856 Calling x_check_errors signals an Emacs error if an X error has
3857 occurred since the last call to x_catch_errors or x_check_errors.
3858
3859 Calling x_uncatch_errors resumes the normal error handling. */
3860
3861void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3862
3863void
3864x_catch_errors ()
3865{
3866 /* Make sure any errors from previous requests have been dealt with. */
3867 XSync (x_current_display, False);
3868
3869 /* Set up the error buffer. */
3870 x_caught_error_message
3871 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
3872 x_caught_error_message[0] = '\0';
3873
3874 /* Install our little error handler. */
3875 XHandleError (x_error_catcher);
3876}
3877
3878/* If any X protocol errors have arrived since the last call to
3879 x_catch_errors or x_check_errors, signal an Emacs error using
3880 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3881void
3882x_check_errors (format)
3883 char *format;
3884{
3885 /* Make sure to catch any errors incurred so far. */
3886 XSync (x_current_display, False);
3887
3888 if (x_caught_error_message[0])
3889 {
3890 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
3891
3892 sprintf (buf, format, x_caught_error_message);
3893 x_uncatch_errors ();
3894 error (buf);
3895 }
3896}
3897
3898void
3899x_uncatch_errors ()
3900{
3901 xfree (x_caught_error_message);
3902 x_caught_error_message = 0;
3903 XHandleError (x_error_quitter);
3904}
3905
3906#if 0
3907static unsigned int x_wire_count;
3908x_trace_wire ()
3909{
3910 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3911}
3912#endif /* ! 0 */
3913
3914\f
3915/* Changing the font of the frame. */
3916
3917/* Set the font of the x-window specified by frame F
3918 to the font named NEWNAME. This is safe to use
3919 even before F has an actual x-window. */
3920
3921#ifdef HAVE_X11
3922
3923/* A table of all the fonts we have already loaded. */
3924static XFontStruct **x_font_table;
3925
3926/* The current capacity of x_font_table. */
3927static int x_font_table_size;
3928
3929/* The number of fonts actually stored in x_font_table.
3930 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3931 0 <= n_fonts <= x_font_table_size. */
3932static int n_fonts;
3933
3934Lisp_Object
3935x_new_font (f, fontname)
3936 struct frame *f;
3937 register char *fontname;
3938{
3939 int already_loaded;
3940 int n_matching_fonts;
3941 XFontStruct *font_info;
3942 char **font_names;
3943
3944 /* Get a list of all the fonts that match this name. Once we
3945 have a list of matching fonts, we compare them against the fonts
3946 we already have by comparing font ids. */
3947 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3948 1024, &n_matching_fonts,
3949 &font_info);
3950 /* Apparently it doesn't set n_matching_fonts to zero when it can't
3951 find any matches; font_names == 0 is the only clue. */
3952 if (! font_names)
3953 n_matching_fonts = 0;
3954
3955 /* Don't just give up if n_matching_fonts is 0.
3956 Apparently there's a bug on Suns: XListFontsWithInfo can
3957 fail to find a font, but XLoadQueryFont may still find it. */
3958
3959 /* See if we've already loaded a matching font. */
3960 already_loaded = -1;
3961 if (n_matching_fonts != 0)
3962 {
3963 int i, j;
3964
3965 for (i = 0; i < n_fonts; i++)
3966 for (j = 0; j < n_matching_fonts; j++)
3967 if (x_font_table[i]->fid == font_info[j].fid)
3968 {
3969 already_loaded = i;
3970 fontname = font_names[j];
3971 goto found_font;
3972 }
3973 }
3974 found_font:
3975
3976 /* If we have, just return it from the table. */
3977 if (already_loaded > 0)
3978 f->display.x->font = x_font_table[already_loaded];
3979
3980 /* Otherwise, load the font and add it to the table. */
3981 else
3982 {
3983 int i;
3984 XFontStruct *font;
3985
3986 /* Try to find a character-cell font in the list. */
3987#if 0
3988 /* A laudable goal, but this isn't how to do it. */
3989 for (i = 0; i < n_matching_fonts; i++)
3990 if (! font_info[i].per_char)
3991 break;
3992#else
3993 i = 0;
3994#endif
3995
3996 /* See comment above. */
3997 if (n_matching_fonts != 0)
3998 fontname = font_names[i];
3999
4000 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
4001 if (! font)
4002 {
4003 /* Free the information from XListFontsWithInfo. */
4004 if (n_matching_fonts)
4005 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4006 return Qnil;
4007 }
4008
4009 /* Do we need to create the table? */
4010 if (x_font_table_size == 0)
4011 {
4012 x_font_table_size = 16;
4013 x_font_table
4014 = (XFontStruct **) xmalloc (x_font_table_size
4015 * sizeof (x_font_table[0]));
4016 }
4017 /* Do we need to grow the table? */
4018 else if (n_fonts >= x_font_table_size)
4019 {
4020 x_font_table_size *= 2;
4021 x_font_table
4022 = (XFontStruct **) xrealloc (x_font_table,
4023 (x_font_table_size
4024 * sizeof (x_font_table[0])));
4025 }
4026
4027 f->display.x->font = x_font_table[n_fonts++] = font;
4028 }
4029
4030 /* Now make the frame display the given font. */
4031 if (FRAME_X_WINDOW (f) != 0)
4032 {
4033 XSetFont (x_current_display, f->display.x->normal_gc,
4034 f->display.x->font->fid);
4035 XSetFont (x_current_display, f->display.x->reverse_gc,
4036 f->display.x->font->fid);
4037 XSetFont (x_current_display, f->display.x->cursor_gc,
4038 f->display.x->font->fid);
4039
4040 x_set_window_size (f, f->width, f->height);
4041 }
4042
4043 {
4044 Lisp_Object lispy_name = build_string (fontname);
4045
4046
4047 /* Free the information from XListFontsWithInfo. The data
4048 we actually retain comes from XLoadQueryFont. */
4049 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4050
4051 return lispy_name;
4052 }
4053}
4054#else /* ! defined (HAVE_X11) */
4055x_new_font (f, newname)
4056 struct frame *f;
4057 register char *newname;
4058{
4059 FONT_TYPE *temp;
4060 int mask;
4061
4062 temp = XGetFont (newname);
4063 if (temp == (FONT_TYPE *) 0)
4064 return 1;
4065
4066 if (f->display.x->font)
4067 XLoseFont (f->display.x->font);
4068
4069 f->display.x->font = temp;
4070
4071 if (FRAME_X_WINDOW (f) != 0)
4072 x_set_window_size (f, f->width, f->height);
4073
4074 return 0;
4075}
4076#endif /* ! defined (HAVE_X11) */
4077\f
4078/* X Window sizes and positions. */
4079
4080x_calc_absolute_position (f)
4081 struct frame *f;
4082{
4083#ifdef HAVE_X11
4084 if (f->display.x->left_pos < 0)
4085 f->display.x->left_pos
4086 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
4087
4088 if (f->display.x->top_pos < 0)
4089 f->display.x->top_pos
4090 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
4091#else /* ! defined (HAVE_X11) */
4092 WINDOWINFO_TYPE parentinfo;
4093
4094 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
4095
4096 if (f->display.x->left_pos < 0)
4097 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4098 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
4099
4100 if (f->display.x->top_pos < 0)
4101 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4102 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
4103#endif /* ! defined (HAVE_X11) */
4104}
4105
4106x_set_offset (f, xoff, yoff)
4107 struct frame *f;
4108 register int xoff, yoff;
4109{
4110 f->display.x->top_pos = yoff;
4111 f->display.x->left_pos = xoff;
4112 x_calc_absolute_position (f);
4113
4114 BLOCK_INPUT;
4115 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
4116 f->display.x->left_pos, f->display.x->top_pos);
4117#ifdef HAVE_X11
4118 x_wm_set_size_hint (f, 0);
4119#endif /* ! defined (HAVE_X11) */
4120 UNBLOCK_INPUT;
4121}
4122
4123/* Call this to change the size of frame F's x-window. */
4124
4125x_set_window_size (f, cols, rows)
4126 struct frame *f;
4127 int cols, rows;
4128{
4129 int pixelwidth, pixelheight;
4130 int mask;
4131
4132 BLOCK_INPUT;
4133
4134 check_frame_size (f, &rows, &cols);
4135 f->display.x->vertical_scroll_bar_extra =
4136 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4137 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
4138 : 0);
4139 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4140 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4141
4142#ifdef HAVE_X11
4143 x_wm_set_size_hint (f, 0);
4144#endif /* ! defined (HAVE_X11) */
4145 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
4146
4147 /* Now, strictly speaking, we can't be sure that this is accurate,
4148 but the window manager will get around to dealing with the size
4149 change request eventually, and we'll hear how it went when the
4150 ConfigureNotify event gets here.
4151
4152 We could just not bother storing any of this information here,
4153 and let the ConfigureNotify event set everything up, but that
4154 might be kind of confusing to the lisp code, since size changes
4155 wouldn't be reported in the frame parameters until some random
4156 point in the future when the ConfigureNotify event arrives. */
4157 change_frame_size (f, rows, cols, 0, 0);
4158 PIXEL_WIDTH (f) = pixelwidth;
4159 PIXEL_HEIGHT (f) = pixelheight;
4160
4161 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4162 receive in the ConfigureNotify event; if we get what we asked
4163 for, then the event won't cause the screen to become garbaged, so
4164 we have to make sure to do it here. */
4165 SET_FRAME_GARBAGED (f);
4166
4167 XFlushQueue ();
4168 UNBLOCK_INPUT;
4169}
4170
4171#ifndef HAVE_X11
4172x_set_resize_hint (f)
4173 struct frame *f;
4174{
4175 XSetResizeHint (FRAME_X_WINDOW (f),
4176 2 * f->display.x->internal_border_width,
4177 2 * f->display.x->internal_border_width,
4178 FONT_WIDTH (f->display.x->font),
4179 FONT_HEIGHT (f->display.x->font));
4180}
4181#endif /* HAVE_X11 */
4182\f
4183/* Mouse warping, focus shifting, raising and lowering. */
4184
4185x_set_mouse_position (f, x, y)
4186 struct frame *f;
4187 int x, y;
4188{
4189 int pix_x, pix_y;
4190
4191 x_raise_frame (f);
4192
4193 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4194 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4195
4196 if (pix_x < 0) pix_x = 0;
4197 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4198
4199 if (pix_y < 0) pix_y = 0;
4200 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4201
4202 BLOCK_INPUT;
4203
4204 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4205 UNBLOCK_INPUT;
4206}
4207
4208#ifdef HAVE_X11
4209x_focus_on_frame (f)
4210 struct frame *f;
4211{
4212 x_raise_frame (f);
4213#if 0
4214 /* I don't think that the ICCCM allows programs to do things like this
4215 without the interaction of the window manager. Whatever you end up
4216 doing with this code, do it to x_unfocus_frame too. */
4217 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4218 RevertToPointerRoot, CurrentTime);
4219#endif /* ! 0 */
4220}
4221
4222x_unfocus_frame (f)
4223 struct frame *f;
4224{
4225#if 0
4226 /* Look at the remarks in x_focus_on_frame. */
4227 if (x_focus_frame == f)
4228 XSetInputFocus (x_current_display, PointerRoot,
4229 RevertToPointerRoot, CurrentTime);
4230#endif /* ! 0 */
4231}
4232
4233#endif /* ! defined (HAVE_X11) */
4234
4235/* Raise frame F. */
4236
4237x_raise_frame (f)
4238 struct frame *f;
4239{
4240 if (f->async_visible)
4241 {
4242 BLOCK_INPUT;
4243 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4244 XFlushQueue ();
4245 UNBLOCK_INPUT;
4246 }
4247}
4248
4249/* Lower frame F. */
4250
4251x_lower_frame (f)
4252 struct frame *f;
4253{
4254 if (f->async_visible)
4255 {
4256 BLOCK_INPUT;
4257 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4258 XFlushQueue ();
4259 UNBLOCK_INPUT;
4260 }
4261}
4262
4263static void
4264XTframe_raise_lower (f, raise)
4265 FRAME_PTR f;
4266 int raise;
4267{
4268 if (raise)
4269 x_raise_frame (f);
4270 else
4271 x_lower_frame (f);
4272}
4273
4274
4275/* Change from withdrawn state to mapped state. */
4276
4277x_make_frame_visible (f)
4278 struct frame *f;
4279{
4280 int mask;
4281
4282 BLOCK_INPUT;
4283
4284 if (! FRAME_VISIBLE_P (f))
4285 {
4286#ifdef HAVE_X11
4287 if (! EQ (Vx_no_window_manager, Qt))
4288 x_wm_set_window_state (f, NormalState);
4289
4290 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4291 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4292 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4293#else /* ! defined (HAVE_X11) */
4294 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4295 if (f->display.x->icon_desc != 0)
4296 XUnmapWindow (f->display.x->icon_desc);
4297
4298 /* Handled by the MapNotify event for X11 */
4299 f->async_visible = 1;
4300 f->async_iconified = 0;
4301
4302 /* NOTE: this may cause problems for the first frame. */
4303 XTcursor_to (0, 0);
4304#endif /* ! defined (HAVE_X11) */
4305 }
4306
4307 XFlushQueue ();
4308
4309 UNBLOCK_INPUT;
4310}
4311
4312/* Change from mapped state to withdrawn state. */
4313
4314x_make_frame_invisible (f)
4315 struct frame *f;
4316{
4317 int mask;
4318
4319 /* Don't keep the highlight on an invisible frame. */
4320 if (x_highlight_frame == f)
4321 x_highlight_frame = 0;
4322
4323 if (! f->async_visible && ! f->async_iconified)
4324 return;
4325
4326 BLOCK_INPUT;
4327
4328#ifdef HAVE_X11R4
4329
4330 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4331 DefaultScreen (x_current_display)))
4332 {
4333 UNBLOCK_INPUT_RESIGNAL;
4334 error ("can't notify window manager of window withdrawal");
4335 }
4336
4337#else /* ! defined (HAVE_X11R4) */
4338#ifdef HAVE_X11
4339
4340 /* Tell the window manager what we're going to do. */
4341 if (! EQ (Vx_no_window_manager, Qt))
4342 {
4343 XEvent unmap;
4344
4345 unmap.xunmap.type = UnmapNotify;
4346 unmap.xunmap.window = FRAME_X_WINDOW (f);
4347 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4348 unmap.xunmap.from_configure = False;
4349 if (! XSendEvent (x_current_display,
4350 DefaultRootWindow (x_current_display),
4351 False,
4352 SubstructureRedirectMask|SubstructureNotifyMask,
4353 &unmap))
4354 {
4355 UNBLOCK_INPUT_RESIGNAL;
4356 error ("can't notify window manager of withdrawal");
4357 }
4358 }
4359
4360 /* Unmap the window ourselves. Cheeky! */
4361 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4362
4363#else /* ! defined (HAVE_X11) */
4364
4365 XUnmapWindow (FRAME_X_WINDOW (f));
4366 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4367 if (f->display.x->icon_desc != 0)
4368 XUnmapWindow (f->display.x->icon_desc);
4369
4370#endif /* ! defined (HAVE_X11) */
4371#endif /* ! defined (HAVE_X11R4) */
4372
4373 XFlushQueue ();
4374 UNBLOCK_INPUT;
4375}
4376
4377/* Change window state from mapped to iconified. */
4378
4379x_iconify_frame (f)
4380 struct frame *f;
4381{
4382 int mask;
4383
4384 /* Don't keep the highlight on an invisible frame. */
4385 if (x_highlight_frame == f)
4386 x_highlight_frame = 0;
4387
4388 if (f->async_iconified)
4389 return;
4390
4391 BLOCK_INPUT;
4392
4393#ifdef HAVE_X11
4394 /* Since we don't know which revision of X we're running, we'll use both
4395 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4396
4397 /* X11R4: send a ClientMessage to the window manager using the
4398 WM_CHANGE_STATE type. */
4399 {
4400 XEvent message;
4401
4402 message.xclient.window = FRAME_X_WINDOW (f);
4403 message.xclient.type = ClientMessage;
4404 message.xclient.message_type = Xatom_wm_change_state;
4405 message.xclient.format = 32;
4406 message.xclient.data.l[0] = IconicState;
4407
4408 if (! XSendEvent (x_current_display,
4409 DefaultRootWindow (x_current_display),
4410 False,
4411 SubstructureRedirectMask | SubstructureNotifyMask,
4412 &message))
4413 {
4414 UNBLOCK_INPUT_RESIGNAL;
4415 error ("Can't notify window manager of iconification.");
4416 }
4417 }
4418
4419 /* X11R3: set the initial_state field of the window manager hints to
4420 IconicState. */
4421 x_wm_set_window_state (f, IconicState);
4422
4423 f->async_iconified = 1;
4424#else /* ! defined (HAVE_X11) */
4425 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4426
4427 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4428 if (f->display.x->icon_desc != 0)
4429 {
4430 XMapWindow (XDISPLAY f->display.x->icon_desc);
4431 refreshicon (f);
4432 }
4433#endif /* ! defined (HAVE_X11) */
4434
4435 XFlushQueue ();
4436 UNBLOCK_INPUT;
4437}
4438
4439/* Destroy the X window of frame F. */
4440
4441x_destroy_window (f)
4442 struct frame *f;
4443{
4444 BLOCK_INPUT;
4445
4446 if (f->display.x->icon_desc != 0)
4447 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4448 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4449 free_frame_faces (f);
4450 XFlushQueue ();
4451
4452 xfree (f->display.x);
4453 f->display.x = 0;
4454 if (f == x_focus_frame)
4455 x_focus_frame = 0;
4456 if (f == x_highlight_frame)
4457 x_highlight_frame = 0;
4458
4459 UNBLOCK_INPUT;
4460}
4461\f
4462/* Manage event queues for X10. */
4463
4464#ifndef HAVE_X11
4465
4466/* Manage event queues.
4467
4468 This code is only used by the X10 support.
4469
4470 We cannot leave events in the X queue and get them when we are ready
4471 because X does not provide a subroutine to get only a certain kind
4472 of event but not block if there are no queued events of that kind.
4473
4474 Therefore, we must examine events as they come in and copy events
4475 of certain kinds into our private queues.
4476
4477 All ExposeRegion events are put in x_expose_queue.
4478 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4479
4480
4481/* Write the event *P_XREP into the event queue *QUEUE.
4482 If the queue is full, do nothing, but return nonzero. */
4483
4484int
4485enqueue_event (p_xrep, queue)
4486 register XEvent *p_xrep;
4487 register struct event_queue *queue;
4488{
4489 int newindex = queue->windex + 1;
4490 if (newindex == EVENT_BUFFER_SIZE)
4491 newindex = 0;
4492 if (newindex == queue->rindex)
4493 return -1;
4494 queue->xrep[queue->windex] = *p_xrep;
4495 queue->windex = newindex;
4496 return 0;
4497}
4498
4499/* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4500 If *QUEUE is empty, do nothing and return 0. */
4501
4502int
4503dequeue_event (p_xrep, queue)
4504 register XEvent *p_xrep;
4505 register struct event_queue *queue;
4506{
4507 if (queue->windex == queue->rindex)
4508 return 0;
4509 *p_xrep = queue->xrep[queue->rindex++];
4510 if (queue->rindex == EVENT_BUFFER_SIZE)
4511 queue->rindex = 0;
4512 return 1;
4513}
4514
4515/* Return the number of events buffered in *QUEUE. */
4516
4517int
4518queue_event_count (queue)
4519 register struct event_queue *queue;
4520{
4521 int tem = queue->windex - queue->rindex;
4522 if (tem >= 0)
4523 return tem;
4524 return EVENT_BUFFER_SIZE + tem;
4525}
4526
4527/* Return nonzero if mouse input is pending. */
4528
4529int
4530mouse_event_pending_p ()
4531{
4532 return queue_event_count (&x_mouse_queue);
4533}
4534#endif /* HAVE_X11 */
4535\f
4536/* Setting window manager hints. */
4537
4538#ifdef HAVE_X11
4539
4540x_wm_set_size_hint (f, prompting)
4541 struct frame *f;
4542 long prompting;
4543{
4544 XSizeHints size_hints;
4545 Window window = FRAME_X_WINDOW (f);
4546
4547 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
4548
4549 flexlines = f->height;
4550
4551 size_hints.x = f->display.x->left_pos;
4552 size_hints.y = f->display.x->top_pos;
4553 size_hints.height = PIXEL_HEIGHT (f);
4554 size_hints.width = PIXEL_WIDTH (f);
4555 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4556 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4557#if 0
4558 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4559 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4560#endif
4561 {
4562 int base_width, base_height;
4563
4564 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4565 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4566
4567 {
4568 int min_rows = 0, min_cols = 0;
4569 check_frame_size (f, &min_rows, &min_cols);
4570
4571 /* The window manager uses the base width hints to calculate the
4572 current number of rows and columns in the frame while
4573 resizing; min_width and min_height aren't useful for this
4574 purpose, since they might not give the dimensions for a
4575 zero-row, zero-column frame.
4576
4577 We use the base_width and base_height members if we have
4578 them; otherwise, we set the min_width and min_height members
4579 to the size for a zero x zero frame. */
4580
4581#ifdef HAVE_X11R4
4582 size_hints.flags |= PBaseSize;
4583 size_hints.base_width = base_width;
4584 size_hints.base_height = base_height;
4585 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4586 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4587#else
4588 size_hints.min_width = base_width;
4589 size_hints.min_height = base_height;
4590#endif
4591 }
4592
4593 }
4594
4595 if (prompting)
4596 size_hints.flags |= prompting;
4597 else
4598 {
4599 XSizeHints hints; /* Sometimes I hate X Windows... */
4600
4601 if (XGetNormalHints (x_current_display, window, &hints) == 0)
4602 hints.flags = 0;
4603 if (hints.flags & PSize)
4604 size_hints.flags |= PSize;
4605 if (hints.flags & PPosition)
4606 size_hints.flags |= PPosition;
4607 if (hints.flags & USPosition)
4608 size_hints.flags |= USPosition;
4609 if (hints.flags & USSize)
4610 size_hints.flags |= USSize;
4611 }
4612
4613#ifdef HAVE_X11R4
4614 XSetWMNormalHints (x_current_display, window, &size_hints);
4615#else
4616 XSetNormalHints (x_current_display, window, &size_hints);
4617#endif
4618}
4619
4620/* Used for IconicState or NormalState */
4621x_wm_set_window_state (f, state)
4622 struct frame *f;
4623 int state;
4624{
4625 Window window = FRAME_X_WINDOW (f);
4626
4627 f->display.x->wm_hints.flags |= StateHint;
4628 f->display.x->wm_hints.initial_state = state;
4629
4630 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4631}
4632
4633x_wm_set_icon_pixmap (f, icon_pixmap)
4634 struct frame *f;
4635 Pixmap icon_pixmap;
4636{
4637 Window window = FRAME_X_WINDOW (f);
4638
4639 if (icon_pixmap)
4640 {
4641 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4642 f->display.x->wm_hints.flags |= IconPixmapHint;
4643 }
4644 else
4645 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4646
4647 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4648}
4649
4650x_wm_set_icon_position (f, icon_x, icon_y)
4651 struct frame *f;
4652 int icon_x, icon_y;
4653{
4654 Window window = FRAME_X_WINDOW (f);
4655
4656 f->display.x->wm_hints.flags |= IconPositionHint;
4657 f->display.x->wm_hints.icon_x = icon_x;
4658 f->display.x->wm_hints.icon_y = icon_y;
4659
4660 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4661}
4662
4663\f
4664/* Initialization. */
4665
4666void
4667x_term_init (display_name)
4668 char *display_name;
4669{
4670 Lisp_Object frame;
4671 char *defaultvalue;
4672#ifdef F_SETOWN
4673 extern int old_fcntl_owner;
4674#endif /* ! defined (F_SETOWN) */
4675
4676 x_focus_frame = x_highlight_frame = 0;
4677
4678 x_current_display = XOpenDisplay (display_name);
4679 if (x_current_display == 0)
4680 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4681 display_name);
4682
4683#ifdef HAVE_X11
4684 {
4685 int hostname_size = 256;
4686
4687 hostname = (char *) xmalloc (hostname_size);
4688
4689#if 0
4690 XSetAfterFunction (x_current_display, x_trace_wire);
4691#endif /* ! 0 */
4692
4693 /* Try to get the host name; if the buffer is too short, try
4694 again. Apparently, the only indication gethostname gives of
4695 whether the buffer was large enough is the presence or absence
4696 of a '\0' in the string. Eech. */
4697 for (;;)
4698 {
4699 gethostname (hostname, hostname_size - 1);
4700 hostname[hostname_size - 1] = '\0';
4701
4702 /* Was the buffer large enough for gethostname to store the '\0'? */
4703 if (strlen (hostname) < hostname_size - 1)
4704 break;
4705
4706 hostname_size <<= 1;
4707 hostname = (char *) xrealloc (hostname, hostname_size);
4708 }
4709 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4710 + strlen (hostname)
4711 + 2);
4712 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4713 }
4714
4715 /* Figure out which modifier bits mean what. */
4716 x_find_modifier_meanings ();
4717
4718 /* Get the scroll bar cursor. */
4719 x_vertical_scroll_bar_cursor
4720 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4721
4722#if 0
4723 /* Watch for PropertyNotify events on the root window; we use them
4724 to figure out when to invalidate our cache of the cut buffers. */
4725 x_watch_cut_buffer_cache ();
4726#endif
4727
4728 if (ConnectionNumber (x_current_display) != 0)
4729 {
4730 dup2 (ConnectionNumber (x_current_display), 0);
4731
4732#ifndef SYSV_STREAMS
4733 /* Streams somehow keeps track of which descriptor number
4734 is being used to talk to X. So it is not safe to substitute
4735 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4736 close (ConnectionNumber (x_current_display));
4737 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4738 * check the def of the macro;
4739 * it is a genuine lvalue */
4740#endif /* SYSV_STREAMS */
4741 }
4742
4743#endif /* ! defined (HAVE_X11) */
4744
4745#ifdef F_SETOWN
4746 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4747#ifdef F_SETOWN_SOCK_NEG
4748 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4749#else /* ! defined (F_SETOWN_SOCK_NEG) */
4750 fcntl (0, F_SETOWN, getpid ());
4751#endif /* ! defined (F_SETOWN_SOCK_NEG) */
4752#endif /* ! defined (F_SETOWN) */
4753
4754#ifdef SIGIO
4755 init_sigio ();
4756#endif /* ! defined (SIGIO) */
4757
4758 /* Must use interrupt input because we cannot otherwise
4759 arrange for C-g to be noticed immediately.
4760 We cannot connect it to SIGINT. */
4761 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4762
4763 expose_all_windows = 0;
4764
4765 clear_frame_hook = XTclear_frame;
4766 clear_end_of_line_hook = XTclear_end_of_line;
4767 ins_del_lines_hook = XTins_del_lines;
4768 change_line_highlight_hook = XTchange_line_highlight;
4769 insert_glyphs_hook = XTinsert_glyphs;
4770 write_glyphs_hook = XTwrite_glyphs;
4771 delete_glyphs_hook = XTdelete_glyphs;
4772 ring_bell_hook = XTring_bell;
4773 reset_terminal_modes_hook = XTreset_terminal_modes;
4774 set_terminal_modes_hook = XTset_terminal_modes;
4775 update_begin_hook = XTupdate_begin;
4776 update_end_hook = XTupdate_end;
4777 set_terminal_window_hook = XTset_terminal_window;
4778 read_socket_hook = XTread_socket;
4779 cursor_to_hook = XTcursor_to;
4780 reassert_line_highlight_hook = XTreassert_line_highlight;
4781 mouse_position_hook = XTmouse_position;
4782 frame_rehighlight_hook = XTframe_rehighlight;
4783 frame_raise_lower_hook = XTframe_raise_lower;
4784 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4785 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4786 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4787 judge_scroll_bars_hook = XTjudge_scroll_bars;
4788
4789 scroll_region_ok = 1; /* we'll scroll partial frames */
4790 char_ins_del_ok = 0; /* just as fast to write the line */
4791 line_ins_del_ok = 1; /* we'll just blt 'em */
4792 fast_clear_end_of_line = 1; /* X does this well */
4793 memory_below_frame = 0; /* we don't remember what scrolls
4794 off the bottom */
4795 baud_rate = 19200;
4796
4797 /* Note that there is no real way portable across R3/R4 to get the
4798 original error handler. */
4799 XHandleError (x_error_quitter);
4800 XHandleIOError (x_io_error_quitter);
4801
4802 /* Disable Window Change signals; they are handled by X events. */
4803#ifdef SIGWINCH
4804 signal (SIGWINCH, SIG_DFL);
4805#endif /* ! defined (SIGWINCH) */
4806
4807 signal (SIGPIPE, x_connection_closed);
4808}
4809
4810void
4811syms_of_xterm ()
4812{
4813 staticpro (&last_mouse_scroll_bar);
4814}
4815#endif /* ! defined (HAVE_X11) */
4816#endif /* ! defined (HAVE_X_WINDOWS) */