(vmotion): Use minibuf_prompt_width despite window-start.
[emacs.git] / src / xterm.c
blob54880dc843e6143f5791fc25584a271aa40575a2
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* Xt features made by Fred Pierresteguy. */
22 #define NEW_SELECTIONS
24 /* On 4.3 these lose if they come after xterm.h. */
25 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
26 /* Putting these at the beginning seems to be standard for other .c files. */
27 #include <stdio.h>
28 #include <signal.h>
30 #include <config.h>
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
36 #ifdef HAVE_X_WINDOWS
38 #include "lisp.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
43 #include "xterm.h"
44 #include <X11/cursorfont.h>
46 #ifndef USG
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52 #endif /* USG */
54 #ifdef BSD
55 #include <sys/ioctl.h>
56 #include <strings.h>
57 #else /* ! defined (BSD) */
58 #ifndef VMS
59 #include <string.h>
60 #endif
61 #endif /* ! defined (BSD) */
63 #include "systty.h"
64 #include "systime.h"
66 #ifndef INCLUDED_FCNTL
67 #include <fcntl.h>
68 #endif
69 #include <ctype.h>
70 #include <errno.h>
71 #include <setjmp.h>
72 #include <sys/stat.h>
73 #include <sys/param.h>
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"
89 #ifdef USE_X_TOOLKIT
90 extern XtAppContext Xt_app_con;
91 extern Widget Xt_app_shell;
92 extern void free_frame_menubar ();
93 #endif /* USE_X_TOOLKIT */
95 #ifndef USE_X_TOOLKIT
96 #define x_any_window_to_frame x_window_to_frame
97 #endif
99 #ifdef HAVE_X11
100 #define XMapWindow XMapRaised /* Raise them when mapping. */
101 #else /* ! defined (HAVE_X11) */
102 #include <X/Xkeyboard.h>
103 /*#include <X/Xproto.h> */
104 #endif /* ! defined (HAVE_X11) */
106 #ifdef FD_SET
107 /* We could get this from param.h, but better not to depend on finding that.
108 And better not to risk that it might define other symbols used in this
109 file. */
110 #ifdef FD_SETSIZE
111 #define MAXDESC FD_SETSIZE
112 #else
113 #define MAXDESC 64
114 #endif
115 #define SELECT_TYPE fd_set
116 #else /* no FD_SET */
117 #define MAXDESC 32
118 #define SELECT_TYPE int
120 /* Define the macros to access a single-int bitmap of descriptors. */
121 #define FD_SET(n, p) (*(p) |= (1 << (n)))
122 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
123 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
124 #define FD_ZERO(p) (*(p) = 0)
125 #endif /* no FD_SET */
127 /* For sending Meta-characters. Do we need this? */
128 #define METABIT 0200
130 #define min(a,b) ((a)<(b) ? (a) : (b))
131 #define max(a,b) ((a)>(b) ? (a) : (b))
133 /* Nonzero means we must reprint all windows
134 because 1) we received an ExposeWindow event
135 or 2) we received too many ExposeRegion events to record.
137 This is never needed under X11. */
138 static int expose_all_windows;
140 /* Nonzero means we must reprint all icon windows. */
142 static int expose_all_icons;
144 #ifndef HAVE_X11
145 /* ExposeRegion events, when received, are copied into this queue
146 for later processing. */
148 static struct event_queue x_expose_queue;
150 /* ButtonPress and ButtonReleased events, when received,
151 are copied into this queue for later processing. */
153 struct event_queue x_mouse_queue;
154 #endif /* HAVE_X11 */
156 #if defined (SIGIO) && defined (FIONREAD)
157 int BLOCK_INPUT_mask;
158 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
160 /* The id of a bitmap used for icon windows.
161 One such map is shared by all Emacs icon windows.
162 This is zero if we have not yet had a need to create the bitmap. */
164 static Bitmap icon_bitmap;
166 /* Font used for text icons. */
168 static FONT_TYPE *icon_font_info;
170 /* Stuff for dealing with the main icon title. */
172 extern Lisp_Object Vcommand_line_args;
173 char *hostname, *x_id_name;
175 /* This is the X connection that we are using. */
177 Display *x_current_display;
179 /* The cursor to use for vertical scroll bars on x_current_display. */
180 static Cursor x_vertical_scroll_bar_cursor;
182 /* Frame being updated by update_frame. This is declared in term.c.
183 This is set by update_begin and looked at by all the
184 XT functions. It is zero while not inside an update.
185 In that case, the XT functions assume that `selected_frame'
186 is the frame to apply to. */
187 extern struct frame *updating_frame;
189 /* The frame (if any) which has the X window that has keyboard focus.
190 Zero if none. This is examined by Ffocus_frame in frame.c. Note
191 that a mere EnterNotify event can set this; if you need to know the
192 last frame specified in a FocusIn or FocusOut event, use
193 x_focus_event_frame. */
194 struct frame *x_focus_frame;
196 /* The last frame mentioned in a FocusIn or FocusOut event. This is
197 separate from x_focus_frame, because whether or not LeaveNotify
198 events cause us to lose focus depends on whether or not we have
199 received a FocusIn event for it. */
200 struct frame *x_focus_event_frame;
202 /* The frame which currently has the visual highlight, and should get
203 keyboard input (other sorts of input have the frame encoded in the
204 event). It points to the X focus frame's selected window's
205 frame. It differs from x_focus_frame when we're using a global
206 minibuffer. */
207 static struct frame *x_highlight_frame;
209 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
210 mouse is moved to inside of frame when frame is de-iconified. */
212 static int warp_mouse_on_deiconify;
214 /* During an update, maximum vpos for ins/del line operations to affect. */
216 static int flexlines;
218 /* During an update, nonzero if chars output now should be highlighted. */
220 static int highlight;
222 /* Nominal cursor position -- where to draw output.
223 During an update, these are different from the cursor-box position. */
225 static int curs_x;
226 static int curs_y;
228 /* Mouse movement.
230 In order to avoid asking for motion events and then throwing most
231 of them away or busy-polling the server for mouse positions, we ask
232 the server for pointer motion hints. This means that we get only
233 one event per group of mouse movements. "Groups" are delimited by
234 other kinds of events (focus changes and button clicks, for
235 example), or by XQueryPointer calls; when one of these happens, we
236 get another MotionNotify event the next time the mouse moves. This
237 is at least as efficient as getting motion events when mouse
238 tracking is on, and I suspect only negligibly worse when tracking
239 is off.
241 The silly O'Reilly & Associates Nutshell guides barely document
242 pointer motion hints at all (I think you have to infer how they
243 work from an example), and the description of XQueryPointer doesn't
244 mention that calling it causes you to get another motion hint from
245 the server, which is very important. */
247 /* Where the mouse was last time we reported a mouse event. */
248 static FRAME_PTR last_mouse_frame;
249 static XRectangle last_mouse_glyph;
251 /* The scroll bar in which the last X motion event occurred.
253 If the last X motion event occurred in a scroll bar, we set this
254 so XTmouse_position can know whether to report a scroll bar motion or
255 an ordinary motion.
257 If the last X motion event didn't occur in a scroll bar, we set this
258 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
259 static Lisp_Object last_mouse_scroll_bar;
261 /* Record which buttons are currently pressed. */
262 unsigned int x_mouse_grabbed;
264 /* This is a hack. We would really prefer that XTmouse_position would
265 return the time associated with the position it returns, but there
266 doesn't seem to be any way to wrest the timestamp from the server
267 along with the position query. So, we just keep track of the time
268 of the last movement we received, and return that in hopes that
269 it's somewhat accurate. */
270 static Time last_mouse_movement_time;
272 /* These variables describe the range of text currently shown
273 in its mouse-face, together with the window they apply to.
274 As long as the mouse stays within this range, we need not
275 redraw anything on its account. */
276 static int mouse_face_beg, mouse_face_end;
277 static Lisp_Object mouse_face_window;
278 static int mouse_face_face_id;
280 /* 1 if a mouse motion event came and we didn't handle it right away because
281 gc was in progress. */
282 static int mouse_face_deferred_gc;
284 /* FRAME and X, Y position of mouse when last checked for highlighting. */
285 static FRAME_PTR mouse_face_mouse_frame;
286 static int mouse_face_mouse_x, mouse_face_mouse_y;
288 /* Nonzero means defer mouse-motion highlighting. */
289 static int mouse_face_defer;
291 #ifdef HAVE_X11
292 /* `t' if a mouse button is depressed. */
294 extern Lisp_Object Vmouse_depressed;
296 /* Tells if a window manager is present or not. */
298 extern Lisp_Object Vx_no_window_manager;
300 /* Timestamp that we requested selection data was made. */
301 extern Time requestor_time;
303 /* ID of the window requesting selection data. */
304 extern Window requestor_window;
306 /* Nonzero enables some debugging for the X interface code. */
307 extern int _Xdebug;
309 extern Qface, Qmouse_face;
311 #else /* ! defined (HAVE_X11) */
313 /* Bit patterns for the mouse cursor. */
315 short MouseCursor[] = {
316 0x0000, 0x0008, 0x0018, 0x0038,
317 0x0078, 0x00f8, 0x01f8, 0x03f8,
318 0x07f8, 0x00f8, 0x00d8, 0x0188,
319 0x0180, 0x0300, 0x0300, 0x0000};
321 short MouseMask[] = {
322 0x000c, 0x001c, 0x003c, 0x007c,
323 0x00fc, 0x01fc, 0x03fc, 0x07fc,
324 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
325 0x03cc, 0x0780, 0x0780, 0x0300};
327 static short grey_bits[] = {
328 0x0005, 0x000a, 0x0005, 0x000a};
330 static Pixmap GreyPixmap = 0;
331 #endif /* ! defined (HAVE_X11) */
333 /* From time to time we get info on an Emacs window, here. */
335 static WINDOWINFO_TYPE windowinfo;
337 extern int errno;
339 /* A mask of extra modifier bits to put into every keyboard char. */
340 extern int extra_keyboard_modifiers;
342 extern Display *XOpenDisplay ();
343 extern Window XCreateWindow ();
345 extern Cursor XCreateCursor ();
346 extern FONT_TYPE *XOpenFont ();
348 static void flashback ();
349 static void redraw_previous_char ();
350 static void redraw_following_char ();
351 static unsigned int x_x_to_emacs_modifiers ();
353 static void note_mouse_highlight ();
354 static void clear_mouse_face ();
355 static void show_mouse_face ();
357 #ifndef HAVE_X11
358 static void dumpqueue ();
359 #endif /* HAVE_X11 */
361 void dumpborder ();
362 static int XTcursor_to ();
363 static int XTclear_end_of_line ();
366 /* Starting and ending updates.
368 These hooks are called by update_frame at the beginning and end
369 of a frame update. We record in `updating_frame' the identity
370 of the frame being updated, so that the XT... functions do not
371 need to take a frame as argument. Most of the XT... functions
372 should never be called except during an update, the only exceptions
373 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
375 extern int mouse_track_top, mouse_track_left, mouse_track_width;
377 static
378 XTupdate_begin (f)
379 struct frame *f;
381 int mask;
383 if (f == 0)
384 abort ();
386 flexlines = f->height;
387 highlight = 0;
389 BLOCK_INPUT;
391 if (f == mouse_face_mouse_frame)
393 /* Don't do highlighting for mouse motion during the update. */
394 mouse_face_defer = 1;
395 if (!NILP (mouse_face_window))
397 int firstline, lastline, i;
398 struct window *w = XWINDOW (mouse_face_window);
400 /* Find the first, and the last+1, lines affected by redisplay. */
401 for (firstline = 0; firstline < f->height; firstline++)
402 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
403 break;
405 lastline = f->height;
406 for (i = f->height - 1; i >= 0; i--)
408 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
409 break;
410 else
411 lastline = i;
414 /* Can we tell that this update does not affect the window
415 where the mouse highlight is? If so, no need to turn off. */
416 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
417 || lastline < XFASTINT (w->top)))
418 /* Otherwise turn off the mouse highlight now. */
419 clear_mouse_face ();
422 #ifndef HAVE_X11
423 dumpqueue ();
424 #endif /* HAVE_X11 */
425 UNBLOCK_INPUT;
428 #ifndef HAVE_X11
429 static void x_do_pending_expose ();
430 #endif
432 static
433 XTupdate_end (f)
434 struct frame *f;
436 int mask;
438 BLOCK_INPUT;
439 #ifndef HAVE_X11
440 dumpqueue ();
441 x_do_pending_expose ();
442 #endif /* HAVE_X11 */
444 x_display_cursor (f, 1);
446 if (f == mouse_face_mouse_frame)
447 mouse_face_defer = 0;
448 #if 0
449 /* This fails in the case of having updated only the echo area
450 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
451 has no relation to the current contents, and its charstarts
452 have no relation to the contents of the window-buffer.
453 I don't know a clean way to check
454 for that case. window_end_valid isn't set up yet. */
455 if (f == mouse_face_mouse_frame)
456 note_mouse_highlight (f, mouse_face_mouse_x, mouse_face_mouse_y);
457 #endif
459 XFlushQueue ();
460 UNBLOCK_INPUT;
463 /* This is called after a redisplay on frame F. */
465 static
466 XTframe_up_to_date (f)
467 FRAME_PTR f;
469 if (mouse_face_deferred_gc || f == mouse_face_mouse_frame)
471 note_mouse_highlight (mouse_face_mouse_frame,
472 mouse_face_mouse_x, mouse_face_mouse_y);
473 mouse_face_deferred_gc = 0;
477 /* External interface to control of standout mode.
478 Call this when about to modify line at position VPOS
479 and not change whether it is highlighted. */
481 XTreassert_line_highlight (new, vpos)
482 int new, vpos;
484 highlight = new;
487 /* Call this when about to modify line at position VPOS
488 and change whether it is highlighted. */
490 static
491 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
492 int new_highlight, vpos, first_unused_hpos;
494 highlight = new_highlight;
495 XTcursor_to (vpos, 0);
496 XTclear_end_of_line (updating_frame->width);
499 /* This is used when starting Emacs and when restarting after suspend.
500 When starting Emacs, no X window is mapped. And nothing must be done
501 to Emacs's own window if it is suspended (though that rarely happens). */
503 static
504 XTset_terminal_modes ()
508 /* This is called when exiting or suspending Emacs.
509 Exiting will make the X-windows go away, and suspending
510 requires no action. */
512 static
513 XTreset_terminal_modes ()
515 /* XTclear_frame (); */
518 /* Set the nominal cursor position of the frame.
519 This is where display update commands will take effect.
520 This does not affect the place where the cursor-box is displayed. */
522 static int
523 XTcursor_to (row, col)
524 register int row, col;
526 int mask;
527 int orow = row;
529 curs_x = col;
530 curs_y = row;
532 if (updating_frame == 0)
534 BLOCK_INPUT;
535 x_display_cursor (selected_frame, 1);
536 XFlushQueue ();
537 UNBLOCK_INPUT;
541 /* Display a sequence of N glyphs found at GP.
542 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
543 HL is 1 if this text is highlighted, 2 if the cursor is on it,
544 3 if should appear in its mouse-face.
545 JUST_FOREGROUND if 1 means draw only the foreground;
546 don't alter the background.
548 FONT is the default font to use (for glyphs whose font-code is 0).
550 Since the display generation code is responsible for calling
551 compute_char_face and compute_glyph_face on everything it puts in
552 the display structure, we can assume that the face code on each
553 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
554 to which we can actually apply intern_face.
555 Call this function with input blocked. */
557 #if 1
558 /* This is the multi-face code. */
560 static void
561 dumpglyphs (f, left, top, gp, n, hl, just_foreground)
562 struct frame *f;
563 int left, top;
564 register GLYPH *gp; /* Points to first GLYPH. */
565 register int n; /* Number of glyphs to display. */
566 int hl;
567 int just_foreground;
569 /* Holds characters to be displayed. */
570 char *buf = (char *) alloca (f->width * sizeof (*buf));
571 register char *cp; /* Steps through buf[]. */
572 register int tlen = GLYPH_TABLE_LENGTH;
573 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
574 Window window = FRAME_X_WINDOW (f);
575 int orig_left = left;
577 while (n > 0)
579 /* Get the face-code of the next GLYPH. */
580 int cf, len;
581 int g = *gp;
583 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
584 cf = FAST_GLYPH_FACE (g);
586 /* Find the run of consecutive glyphs with the same face-code.
587 Extract their character codes into BUF. */
588 cp = buf;
589 while (n > 0)
591 g = *gp;
592 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
593 if (FAST_GLYPH_FACE (g) != cf)
594 break;
596 *cp++ = FAST_GLYPH_CHAR (g);
597 --n;
598 ++gp;
601 /* LEN gets the length of the run. */
602 len = cp - buf;
604 /* Now output this run of chars, with the font and pixel values
605 determined by the face code CF. */
607 struct face *face = FRAME_DEFAULT_FACE (f);
608 FONT_TYPE *font = FACE_FONT (face);
609 GC gc = FACE_GC (face);
610 int defaulted = 1;
611 int gc_temporary = 0;
613 /* HL = 3 means use a mouse face previously chosen. */
614 if (hl == 3)
615 cf = mouse_face_face_id;
617 /* First look at the face of the text itself. */
618 if (cf != 0)
620 /* It's possible for the display table to specify
621 a face code that is out of range. Use 0 in that case. */
622 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
623 || FRAME_COMPUTED_FACES (f) [cf] == 0)
624 cf = 0;
626 if (cf == 1)
627 face = FRAME_MODE_LINE_FACE (f);
628 else
629 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
630 font = FACE_FONT (face);
631 gc = FACE_GC (face);
632 defaulted = 0;
635 /* Then comes the distinction between modeline and normal text. */
636 else if (hl == 0)
638 else if (hl == 1)
640 face = FRAME_MODE_LINE_FACE (f);
641 font = FACE_FONT (face);
642 gc = FACE_GC (face);
643 defaulted = 0;
646 #define FACE_DEFAULT (~0)
648 /* Now override that if the cursor's on this character. */
649 if (hl == 2)
651 if (defaulted
652 || !face->font
653 || (int) face->font == FACE_DEFAULT)
655 gc = f->display.x->cursor_gc;
657 /* Cursor on non-default face: must merge. */
658 else
660 XGCValues xgcv;
661 unsigned long mask;
663 xgcv.background = f->display.x->cursor_pixel;
664 if (face == FRAME_DEFAULT_FACE (f))
665 xgcv.foreground = f->display.x->cursor_foreground_pixel;
666 else
667 xgcv.foreground = face->foreground;
668 /* If the glyph would be invisible,
669 try a different foreground. */
670 if (xgcv.foreground == xgcv.background)
671 xgcv.foreground = face->background;
672 if (xgcv.foreground == xgcv.background)
673 xgcv.foreground = f->display.x->cursor_foreground_pixel;
674 if (xgcv.foreground == xgcv.background)
675 xgcv.foreground = face->foreground;
676 /* Make sure the cursor is distinct from text in this face. */
677 if (xgcv.background == face->background
678 && xgcv.foreground == face->foreground)
680 xgcv.background = face->foreground;
681 xgcv.foreground = face->background;
683 xgcv.font = face->font->fid;
684 xgcv.graphics_exposures = 0;
685 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
686 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
687 mask, &xgcv);
688 #if 0
689 if (face->stipple && face->stipple != FACE_DEFAULT)
690 XSetStipple (x_current_display, gc, face->stipple);
691 #endif
692 gc_temporary = 1;
696 if ((int) font == FACE_DEFAULT)
697 font = f->display.x->font;
699 if (just_foreground)
700 XDrawString (x_current_display, window, gc,
701 left, top + FONT_BASE (font), buf, len);
702 else
704 XDrawImageString (x_current_display, window, gc,
705 left, top + FONT_BASE (font), buf, len);
706 /* Clear the rest of the line's height. */
707 if (f->display.x->line_height != FONT_HEIGHT (font))
708 XClearArea (x_current_display, window, left,
709 top + FONT_HEIGHT (font),
710 FONT_WIDTH (font) * len,
711 /* This is how many pixels of height
712 we have to clear. */
713 f->display.x->line_height - FONT_HEIGHT (font),
714 False);
717 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
718 which often is not up to date yet. */
719 if (!just_foreground)
721 if (left == orig_left)
722 redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
723 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
724 if (n == 0)
725 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
726 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
728 #endif
730 if (gc_temporary)
731 XFreeGC (x_current_display, gc);
733 /* We should probably check for XA_UNDERLINE_POSITION and
734 XA_UNDERLINE_THICKNESS properties on the font, but let's
735 just get the thing working, and come back to that. */
737 int underline_position = 1;
739 if (font->descent <= underline_position)
740 underline_position = font->descent - 1;
742 if (face->underline)
743 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
744 FACE_GC (face),
745 left, (top
746 + FONT_BASE (font)
747 + underline_position),
748 len * FONT_WIDTH (font), 1);
751 left += len * FONT_WIDTH (font);
755 #endif /* 1 */
757 #if 0
758 /* This is the old single-face code. */
760 static void
761 dumpglyphs (f, left, top, gp, n, hl, font)
762 struct frame *f;
763 int left, top;
764 register GLYPH *gp; /* Points to first GLYPH. */
765 register int n; /* Number of glyphs to display. */
766 int hl;
767 FONT_TYPE *font;
769 register int len;
770 Window window = FRAME_X_WINDOW (f);
771 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
772 : (hl ? f->display.x->reverse_gc
773 : f->display.x->normal_gc));
775 if (sizeof (GLYPH) == sizeof (XChar2b))
776 XDrawImageString16 (x_current_display, window, drawing_gc,
777 left, top + FONT_BASE (font), (XChar2b *) gp, n);
778 else if (sizeof (GLYPH) == sizeof (unsigned char))
779 XDrawImageString (x_current_display, window, drawing_gc,
780 left, top + FONT_BASE (font), (char *) gp, n);
781 else
782 /* What size of glyph ARE you using? And does X have a function to
783 draw them? */
784 abort ();
786 #endif
788 /* Output some text at the nominal frame cursor position.
789 Advance the cursor over the text.
790 Output LEN glyphs at START.
792 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
793 controls the pixel values used for foreground and background. */
795 static
796 XTwrite_glyphs (start, len)
797 register GLYPH *start;
798 int len;
800 register int temp_length;
801 int mask;
802 struct frame *f;
804 BLOCK_INPUT;
806 f = updating_frame;
807 if (f == 0)
809 f = selected_frame;
810 /* If not within an update,
811 output at the frame's visible cursor. */
812 curs_x = f->cursor_x;
813 curs_y = f->cursor_y;
816 dumpglyphs (f,
817 CHAR_TO_PIXEL_COL (f, curs_x),
818 CHAR_TO_PIXEL_ROW (f, curs_y),
819 start, len, highlight, 0);
821 /* If we drew on top of the cursor, note that it is turned off. */
822 if (curs_y == f->phys_cursor_y
823 && curs_x <= f->phys_cursor_x
824 && curs_x + len > f->phys_cursor_x)
825 f->phys_cursor_x = -1;
827 if (updating_frame == 0)
829 f->cursor_x += len;
830 x_display_cursor (f, 1);
831 f->cursor_x -= len;
833 else
834 curs_x += len;
836 UNBLOCK_INPUT;
839 /* Clear to the end of the line.
840 Erase the current text line from the nominal cursor position (inclusive)
841 to column FIRST_UNUSED (exclusive). The idea is that everything
842 from FIRST_UNUSED onward is already erased. */
844 static int
845 XTclear_end_of_line (first_unused)
846 register int first_unused;
848 struct frame *f = updating_frame;
849 int mask;
851 if (f == 0)
852 abort ();
854 if (curs_y < 0 || curs_y >= f->height)
855 return;
856 if (first_unused <= 0)
857 return;
859 if (first_unused >= f->width)
860 first_unused = f->width;
862 BLOCK_INPUT;
864 /* Notice if the cursor will be cleared by this operation. */
865 if (curs_y == f->phys_cursor_y
866 && curs_x <= f->phys_cursor_x
867 && f->phys_cursor_x < first_unused)
868 f->phys_cursor_x = -1;
870 #ifdef HAVE_X11
871 XClearArea (x_current_display, FRAME_X_WINDOW (f),
872 CHAR_TO_PIXEL_COL (f, curs_x),
873 CHAR_TO_PIXEL_ROW (f, curs_y),
874 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
875 f->display.x->line_height, False);
876 #if 0
877 redraw_previous_char (f, curs_x, curs_y, highlight);
878 #endif
879 #else /* ! defined (HAVE_X11) */
880 XPixSet (FRAME_X_WINDOW (f),
881 CHAR_TO_PIXEL_COL (f, curs_x),
882 CHAR_TO_PIXEL_ROW (f, curs_y),
883 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
884 f->display.x->line_height,
885 f->display.x->background_pixel);
886 #endif /* ! defined (HAVE_X11) */
888 UNBLOCK_INPUT;
891 static
892 XTclear_frame ()
894 int mask;
895 struct frame *f = updating_frame;
897 if (f == 0)
898 f = selected_frame;
900 f->phys_cursor_x = -1; /* Cursor not visible. */
901 curs_x = 0; /* Nominal cursor position is top left. */
902 curs_y = 0;
904 BLOCK_INPUT;
906 XClear (FRAME_X_WINDOW (f));
908 /* We have to clear the scroll bars, too. If we have changed
909 colors or something like that, then they should be notified. */
910 x_scroll_bar_clear (f);
912 #ifndef HAVE_X11
913 dumpborder (f, 0);
914 #endif /* HAVE_X11 */
916 XFlushQueue ();
917 UNBLOCK_INPUT;
920 #if 0
921 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
922 always contain the right glyphs to use.
924 It also needs to be changed to look at the details of the font and
925 see whether there is really overlap, and do nothing when there is
926 not. This can use font_char_overlap_left and font_char_overlap_right,
927 but just how to use them is not clear. */
929 /* Erase the character (if any) at the position just before X, Y in frame F,
930 then redraw it and the character before it.
931 This is necessary when we erase starting at X,
932 in case the character after X overlaps into the one before X.
933 Call this function with input blocked. */
935 static void
936 redraw_previous_char (f, x, y, highlight_flag)
937 FRAME_PTR f;
938 int x, y;
939 int highlight_flag;
941 /* Erase the character before the new ones, in case
942 what was here before overlaps it.
943 Reoutput that character, and the previous character
944 (in case the previous character overlaps it). */
945 if (x > 0)
947 int start_x = x - 2;
948 if (start_x < 0)
949 start_x = 0;
950 XClearArea (x_current_display, FRAME_X_WINDOW (f),
951 CHAR_TO_PIXEL_COL (f, x - 1),
952 CHAR_TO_PIXEL_ROW (f, y),
953 FONT_WIDTH (f->display.x->font),
954 f->display.x->line_height, False);
956 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
957 CHAR_TO_PIXEL_ROW (f, y),
958 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
959 x - start_x, highlight_flag, 1);
963 /* Erase the character (if any) at the position X, Y in frame F,
964 then redraw it and the character after it.
965 This is necessary when we erase endng at X,
966 in case the character after X overlaps into the one before X.
967 Call this function with input blocked. */
969 static void
970 redraw_following_char (f, x, y, highlight_flag)
971 FRAME_PTR f;
972 int x, y;
973 int highlight_flag;
975 int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
976 /* Erase the character after the new ones, in case
977 what was here before overlaps it.
978 Reoutput that character, and the following character
979 (in case the following character overlaps it). */
980 if (x < limit
981 && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
983 int end_x = x + 2;
984 if (end_x > limit)
985 end_x = limit;
986 XClearArea (x_current_display, FRAME_X_WINDOW (f),
987 CHAR_TO_PIXEL_COL (f, x),
988 CHAR_TO_PIXEL_ROW (f, y),
989 FONT_WIDTH (f->display.x->font),
990 f->display.x->line_height, False);
992 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
993 CHAR_TO_PIXEL_ROW (f, y),
994 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
995 end_x - x, highlight_flag, 1);
998 #endif /* 0 */
1000 #if 0 /* Not in use yet */
1002 /* Return 1 if character C in font F extends past its left edge. */
1004 static int
1005 font_char_overlap_left (font, c)
1006 XFontStruct *font;
1007 int c;
1009 XCharStruct *s;
1011 /* Find the bounding-box info for C. */
1012 if (font->per_char == 0)
1013 s = &font->max_bounds;
1014 else
1016 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
1017 int row, within;
1019 /* Decode char into row number (byte 1) and code within row (byte 2). */
1020 row = c >> 8;
1021 within = c & 0177;
1022 if (!(within >= font->min_char_or_byte2
1023 && within <= font->max_char_or_byte2
1024 && row >= font->min_byte1
1025 && row <= font->max_byte1))
1027 /* If char is out of range, try the font's default char instead. */
1028 c = font->default_char;
1029 row = c >> (INTBITS - 8);
1030 within = c & 0177;
1032 if (!(within >= font->min_char_or_byte2
1033 && within <= font->max_char_or_byte2
1034 && row >= font->min_byte1
1035 && row <= font->max_byte1))
1036 /* Still out of range means this char does not overlap. */
1037 return 0;
1038 else
1039 /* We found the info for this char. */
1040 s = (font->per_char + (within - font->min_char_or_byte2)
1041 + row * rowlen);
1044 return (s && s->lbearing < 0);
1047 /* Return 1 if character C in font F extends past its right edge. */
1049 static int
1050 font_char_overlap_right (font, c)
1051 XFontStruct *font;
1052 int c;
1054 XCharStruct *s;
1056 /* Find the bounding-box info for C. */
1057 if (font->per_char == 0)
1058 s = &font->max_bounds;
1059 else
1061 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
1062 int row, within;
1064 /* Decode char into row number (byte 1) and code within row (byte 2). */
1065 row = c >> 8;
1066 within = c & 0177;
1067 if (!(within >= font->min_char_or_byte2
1068 && within <= font->max_char_or_byte2
1069 && row >= font->min_byte1
1070 && row <= font->max_byte1))
1072 /* If char is out of range, try the font's default char instead. */
1073 c = font->default_char;
1074 row = c >> (INTBITS - 8);
1075 within = c & 0177;
1077 if (!(within >= font->min_char_or_byte2
1078 && within <= font->max_char_or_byte2
1079 && row >= font->min_byte1
1080 && row <= font->max_byte1))
1081 /* Still out of range means this char does not overlap. */
1082 return 0;
1083 else
1084 /* We found the info for this char. */
1085 s = (font->per_char + (within - font->min_char_or_byte2)
1086 + row * rowlen);
1089 return (s && s->rbearing >= s->width);
1091 #endif /* 0 */
1093 /* Invert the middle quarter of the frame for .15 sec. */
1095 /* We use the select system call to do the waiting, so we have to make sure
1096 it's available. If it isn't, we just won't do visual bells. */
1097 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1099 /* Subtract the `struct timeval' values X and Y,
1100 storing the result in RESULT.
1101 Return 1 if the difference is negative, otherwise 0. */
1103 static int
1104 timeval_subtract (result, x, y)
1105 struct timeval *result, x, y;
1107 /* Perform the carry for the later subtraction by updating y.
1108 This is safer because on some systems
1109 the tv_sec member is unsigned. */
1110 if (x.tv_usec < y.tv_usec)
1112 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
1113 y.tv_usec -= 1000000 * nsec;
1114 y.tv_sec += nsec;
1116 if (x.tv_usec - y.tv_usec > 1000000)
1118 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
1119 y.tv_usec += 1000000 * nsec;
1120 y.tv_sec -= nsec;
1123 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1124 result->tv_sec = x.tv_sec - y.tv_sec;
1125 result->tv_usec = x.tv_usec - y.tv_usec;
1127 /* Return indication of whether the result should be considered negative. */
1128 return x.tv_sec < y.tv_sec;
1131 XTflash (f)
1132 struct frame *f;
1134 BLOCK_INPUT;
1137 GC gc;
1139 /* Create a GC that will use the GXxor function to flip foreground pixels
1140 into background pixels. */
1142 XGCValues values;
1144 values.function = GXxor;
1145 values.foreground = (f->display.x->foreground_pixel
1146 ^ f->display.x->background_pixel);
1148 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
1149 GCFunction | GCForeground, &values);
1153 int width = PIXEL_WIDTH (f);
1154 int height = PIXEL_HEIGHT (f);
1156 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
1157 width/4, height/4, width/2, height/2);
1158 XFlush (x_current_display);
1161 struct timeval wakeup, now;
1163 EMACS_GET_TIME (wakeup);
1165 /* Compute time to wait until, propagating carry from usecs. */
1166 wakeup.tv_usec += 150000;
1167 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
1168 wakeup.tv_usec %= 1000000;
1170 /* Keep waiting until past the time wakeup. */
1171 while (1)
1173 struct timeval timeout;
1175 EMACS_GET_TIME (timeout);
1177 /* In effect, timeout = wakeup - timeout.
1178 Break if result would be negative. */
1179 if (timeval_subtract (&timeout, wakeup, timeout))
1180 break;
1182 /* Try to wait that long--but we might wake up sooner. */
1183 select (0, 0, 0, 0, &timeout);
1187 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
1188 width/4, height/4, width/2, height/2);
1189 XFreeGC (x_current_display, gc);
1190 XFlush (x_current_display);
1194 UNBLOCK_INPUT;
1197 #endif
1200 /* Make audible bell. */
1202 #ifdef HAVE_X11
1203 #define XRINGBELL XBell (x_current_display, 0)
1204 #else /* ! defined (HAVE_X11) */
1205 #define XRINGBELL XFeep (0);
1206 #endif /* ! defined (HAVE_X11) */
1208 XTring_bell ()
1210 if (x_current_display == 0)
1211 return;
1213 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1214 if (visible_bell)
1215 XTflash (selected_frame);
1216 else
1217 #endif
1219 BLOCK_INPUT;
1220 XRINGBELL;
1221 XFlushQueue ();
1222 UNBLOCK_INPUT;
1226 /* Insert and delete character.
1227 These are not supposed to be used because we are supposed to turn
1228 off the feature of using them. */
1230 static
1231 XTinsert_glyphs (start, len)
1232 register char *start;
1233 register int len;
1235 abort ();
1238 static
1239 XTdelete_glyphs (n)
1240 register int n;
1242 abort ();
1245 /* Specify how many text lines, from the top of the window,
1246 should be affected by insert-lines and delete-lines operations.
1247 This, and those operations, are used only within an update
1248 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1250 static
1251 XTset_terminal_window (n)
1252 register int n;
1254 if (updating_frame == 0)
1255 abort ();
1257 if ((n <= 0) || (n > updating_frame->height))
1258 flexlines = updating_frame->height;
1259 else
1260 flexlines = n;
1263 /* Perform an insert-lines operation.
1264 Insert N lines at a vertical position curs_y. */
1266 static void
1267 stufflines (n)
1268 register int n;
1270 register int topregion, bottomregion;
1271 register int length, newtop, mask;
1272 register struct frame *f = updating_frame;
1273 int intborder = f->display.x->internal_border_width;
1275 if (curs_y >= flexlines)
1276 return;
1278 topregion = curs_y;
1279 bottomregion = flexlines - (n + 1);
1280 newtop = topregion + n;
1281 length = (bottomregion - topregion) + 1;
1283 #ifndef HAVE_X11
1284 dumpqueue ();
1285 #endif /* HAVE_X11 */
1287 if ((length > 0) && (newtop <= flexlines))
1289 #ifdef HAVE_X11
1290 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
1291 FRAME_X_WINDOW (f), f->display.x->normal_gc,
1292 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
1293 f->width * FONT_WIDTH (f->display.x->font),
1294 length * f->display.x->line_height, intborder,
1295 CHAR_TO_PIXEL_ROW (f, newtop));
1296 #else /* ! defined (HAVE_X11) */
1297 XMoveArea (FRAME_X_WINDOW (f),
1298 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
1299 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
1300 f->width * FONT_WIDTH (f->display.x->font),
1301 length * f->display.x->line_height);
1302 /* Now we must process any ExposeRegion events that occur
1303 if the area being copied from is obscured.
1304 We can't let it wait because further i/d operations
1305 may want to copy this area to another area. */
1306 x_read_exposes ();
1307 #endif /* ! defined (HAVE_X11) */
1310 newtop = min (newtop, (flexlines - 1));
1311 length = newtop - topregion;
1312 if (length > 0)
1314 #ifdef HAVE_X11
1315 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
1316 CHAR_TO_PIXEL_ROW (f, topregion),
1317 f->width * FONT_WIDTH (f->display.x->font),
1318 n * f->display.x->line_height, False);
1319 #else /* ! defined (HAVE_X11) */
1320 XPixSet (FRAME_X_WINDOW (f),
1321 intborder,
1322 CHAR_TO_PIXEL_ROW (f, topregion),
1323 f->width * FONT_WIDTH (f->display.x->font),
1324 n * f->display.x->line_height,
1325 f->display.x->background_pixel);
1326 #endif /* ! defined (HAVE_X11) */
1330 /* Perform a delete-lines operation, deleting N lines
1331 at a vertical position curs_y. */
1333 static void
1334 scraplines (n)
1335 register int n;
1337 int mask;
1338 register struct frame *f = updating_frame;
1339 int intborder = f->display.x->internal_border_width;
1341 if (curs_y >= flexlines)
1342 return;
1344 #ifndef HAVE_X11
1345 dumpqueue ();
1346 #endif /* HAVE_X11 */
1348 if ((curs_y + n) >= flexlines)
1350 if (flexlines >= (curs_y + 1))
1352 #ifdef HAVE_X11
1353 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
1354 CHAR_TO_PIXEL_ROW (f, curs_y),
1355 f->width * FONT_WIDTH (f->display.x->font),
1356 (flexlines - curs_y) * f->display.x->line_height, False);
1357 #else /* ! defined (HAVE_X11) */
1358 XPixSet (FRAME_X_WINDOW (f),
1359 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
1360 f->width * FONT_WIDTH (f->display.x->font),
1361 (flexlines - curs_y) * f->display.x->line_height,
1362 f->display.x->background_pixel);
1363 #endif /* ! defined (HAVE_X11) */
1366 else
1368 #ifdef HAVE_X11
1369 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
1370 FRAME_X_WINDOW (f), f->display.x->normal_gc,
1371 intborder,
1372 CHAR_TO_PIXEL_ROW (f, curs_y + n),
1373 f->width * FONT_WIDTH (f->display.x->font),
1374 (flexlines - (curs_y + n)) * f->display.x->line_height,
1375 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
1376 XClearArea (x_current_display, FRAME_X_WINDOW (f),
1377 intborder,
1378 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1379 f->width * FONT_WIDTH (f->display.x->font),
1380 n * f->display.x->line_height, False);
1381 #else /* ! defined (HAVE_X11) */
1382 XMoveArea (FRAME_X_WINDOW (f),
1383 intborder,
1384 CHAR_TO_PIXEL_ROW (f, curs_y + n),
1385 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
1386 f->width * FONT_WIDTH (f->display.x->font),
1387 (flexlines - (curs_y + n)) * f->display.x->line_height);
1388 /* Now we must process any ExposeRegion events that occur
1389 if the area being copied from is obscured.
1390 We can't let it wait because further i/d operations
1391 may want to copy this area to another area. */
1392 x_read_exposes ();
1393 XPixSet (FRAME_X_WINDOW (f), intborder,
1394 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1395 f->width * FONT_WIDTH (f->display.x->font),
1396 n * f->display.x->line_height, f->display.x->background_pixel);
1397 #endif /* ! defined (HAVE_X11) */
1401 /* Perform an insert-lines or delete-lines operation,
1402 inserting N lines or deleting -N lines at vertical position VPOS. */
1404 XTins_del_lines (vpos, n)
1405 int vpos, n;
1407 if (updating_frame == 0)
1408 abort ();
1410 /* Hide the cursor. */
1411 x_display_cursor (updating_frame, 0);
1413 XTcursor_to (vpos, 0);
1415 BLOCK_INPUT;
1416 if (n >= 0)
1417 stufflines (n);
1418 else
1419 scraplines (-n);
1420 XFlushQueue ();
1421 UNBLOCK_INPUT;
1424 /* Support routines for exposure events. */
1425 static void clear_cursor ();
1427 /* Output into a rectangle of an X-window (for frame F)
1428 the characters in f->phys_lines that overlap that rectangle.
1429 TOP and LEFT are the position of the upper left corner of the rectangle.
1430 ROWS and COLS are the size of the rectangle.
1431 Call this function with input blocked. */
1433 static void
1434 dumprectangle (f, left, top, cols, rows)
1435 struct frame *f;
1436 register int left, top, cols, rows;
1438 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1439 int cursor_cleared = 0;
1440 int bottom, right;
1441 register int y;
1443 if (FRAME_GARBAGED_P (f))
1444 return;
1446 /* Express rectangle as four edges, instead of position-and-size. */
1447 bottom = top + rows;
1448 right = left + cols;
1450 #ifndef HAVE_X11 /* Window manger does this for X11. */
1452 int intborder = f->display.x->internal_border_width;
1454 /* If the rectangle includes any of the internal border area,
1455 redisplay the border emphasis. */
1456 if (top < intborder || left < intborder
1457 || bottom > intborder + f->height * f->display.x->line_height
1458 || right > intborder + f->width * f->display.x->line_height)
1459 dumpborder (f, 0);
1461 #endif /* not HAVE_X11 Window manger does this for X11. */
1463 /* Convert rectangle edges in pixels to edges in chars.
1464 Round down for left and top, up for right and bottom. */
1465 top = PIXEL_TO_CHAR_ROW (f, top);
1466 left = PIXEL_TO_CHAR_COL (f, left);
1467 bottom += (f->display.x->line_height - 1);
1468 right += (FONT_WIDTH (f->display.x->font) - 1);
1469 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1470 right = PIXEL_TO_CHAR_COL (f, right);
1472 /* Clip the rectangle to what can be visible. */
1473 if (left < 0)
1474 left = 0;
1475 if (top < 0)
1476 top = 0;
1477 if (right > f->width)
1478 right = f->width;
1479 if (bottom > f->height)
1480 bottom = f->height;
1482 /* Get size in chars of the rectangle. */
1483 cols = right - left;
1484 rows = bottom - top;
1486 /* If rectangle has zero area, return. */
1487 if (rows <= 0) return;
1488 if (cols <= 0) return;
1490 /* Turn off the cursor if it is in the rectangle.
1491 We will turn it back on afterward. */
1492 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1493 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1495 clear_cursor (f);
1496 cursor_cleared = 1;
1499 /* Display the text in the rectangle, one text line at a time. */
1501 for (y = top; y < bottom; y++)
1503 GLYPH *line = &active_frame->glyphs[y][left];
1505 if (! active_frame->enable[y] || left > active_frame->used[y])
1506 continue;
1508 dumpglyphs (f,
1509 CHAR_TO_PIXEL_COL (f, left),
1510 CHAR_TO_PIXEL_ROW (f, y),
1511 line, min (cols, active_frame->used[y] - left),
1512 active_frame->highlight[y], 0);
1515 /* Turn the cursor on if we turned it off. */
1517 if (cursor_cleared)
1518 x_display_cursor (f, 1);
1521 #ifndef HAVE_X11
1522 /* Process all queued ExposeRegion events. */
1524 static void
1525 dumpqueue ()
1527 register int i;
1528 XExposeRegionEvent r;
1530 while (dequeue_event (&r, &x_expose_queue))
1532 struct frame *f = x_window_to_frame (r.window);
1533 if (f->display.x->icon_desc == r.window)
1534 refreshicon (f);
1535 else
1536 dumprectangle (f, r.x, r.y, r.width, r.height);
1538 XFlushQueue ();
1540 #endif /* HAVE_X11 */
1542 /* Process all expose events that are pending, for X10.
1543 Redraws the cursor if necessary on any frame that
1544 is not in the process of being updated with update_frame. */
1546 #ifndef HAVE_X11
1547 static void
1548 x_do_pending_expose ()
1550 int mask;
1551 struct frame *f;
1552 Lisp_Object tail, frame;
1554 if (expose_all_windows)
1556 expose_all_windows = 0;
1557 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1559 register int temp_width, temp_height;
1560 int intborder;
1562 frame = XCONS (tail)->car;
1563 if (XGCTYPE (frame) != Lisp_Frame)
1564 continue;
1565 f = XFRAME (frame);
1566 if (! FRAME_X_P (f))
1567 continue;
1568 if (!f->async_visible)
1569 continue;
1570 if (!f->display.x->needs_exposure)
1571 continue;
1573 intborder = f->display.x->internal_border_width;
1575 clear_cursor (f);
1576 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1577 temp_width = ((windowinfo.width - 2 * intborder
1578 - f->display.x->v_scroll_bar_width)
1579 / FONT_WIDTH (f->display.x->font));
1580 temp_height = ((windowinfo.height- 2 * intborder
1581 - f->display.x->h_scroll_bar_height)
1582 / f->display.x->line_height);
1583 if (temp_width != f->width || temp_height != f->height)
1585 change_frame_size (f, max (1, temp_height),
1586 max (1, temp_width), 0, 1);
1587 x_resize_scroll_bars (f);
1589 f->display.x->left_pos = windowinfo.x;
1590 f->display.x->top_pos = windowinfo.y;
1591 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1592 #if 0
1593 dumpborder (f, 0);
1594 #endif /* ! 0 */
1595 f->display.x->needs_exposure = 0;
1596 if (updating_frame != f)
1597 x_display_cursor (f, 1);
1598 XFlushQueue ();
1601 else
1602 /* Handle any individual-rectangle expose events queued
1603 for various windows. */
1604 #ifdef HAVE_X11
1606 #else /* ! defined (HAVE_X11) */
1607 dumpqueue ();
1608 #endif /* ! defined (HAVE_X11) */
1610 #endif
1612 #ifdef HAVE_X11
1613 static void
1614 frame_highlight (frame)
1615 struct frame *frame;
1617 /* We used to only do this if Vx_no_window_manager was non-nil, but
1618 the ICCCM (section 4.1.6) says that the window's border pixmap
1619 and border pixel are window attributes which are "private to the
1620 client", so we can always change it to whatever we want. */
1621 BLOCK_INPUT;
1622 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1623 frame->display.x->border_pixel);
1624 UNBLOCK_INPUT;
1625 x_display_cursor (frame, 1);
1628 static void
1629 frame_unhighlight (frame)
1630 struct frame *frame;
1632 /* We used to only do this if Vx_no_window_manager was non-nil, but
1633 the ICCCM (section 4.1.6) says that the window's border pixmap
1634 and border pixel are window attributes which are "private to the
1635 client", so we can always change it to whatever we want. */
1636 BLOCK_INPUT;
1637 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1638 frame->display.x->border_tile);
1639 UNBLOCK_INPUT;
1640 x_display_cursor (frame, 1);
1642 #else /* ! defined (HAVE_X11) */
1643 /* Dump the border-emphasis of frame F.
1644 If F is selected, this is a lining of the same color as the border,
1645 just within the border, occupying a portion of the internal border.
1646 If F is not selected, it is background in the same place.
1647 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1649 ALWAYS = 1 is used when a frame becomes selected or deselected.
1650 In that case, we also turn the cursor off and on again
1651 so it will appear in the proper shape (solid if selected; else hollow.) */
1653 static void
1654 dumpborder (f, always)
1655 struct frame *f;
1656 int always;
1658 int thickness = f->display.x->internal_border_width / 2;
1659 int width = PIXEL_WIDTH (f);
1660 int height = PIXEL_HEIGHT (f);
1661 int pixel;
1663 if (f != selected_frame)
1665 if (!always)
1666 return;
1668 pixel = f->display.x->background_pixel;
1670 else
1672 pixel = f->display.x->border_pixel;
1675 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1676 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1677 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1678 thickness, pixel);
1679 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1680 height, pixel);
1682 if (always)
1683 x_display_cursor (f, 1);
1685 #endif /* ! defined (HAVE_X11) */
1687 static void XTframe_rehighlight ();
1689 /* The focus has changed. Update the frames as necessary to reflect
1690 the new situation. Note that we can't change the selected frame
1691 here, because the lisp code we are interrupting might become confused.
1692 Each event gets marked with the frame in which it occurred, so the
1693 lisp code can tell when the switch took place by examining the events. */
1695 static void
1696 x_new_focus_frame (frame)
1697 struct frame *frame;
1699 struct frame *old_focus = x_focus_frame;
1700 int events_enqueued = 0;
1702 if (frame != x_focus_frame)
1704 /* Set this before calling other routines, so that they see
1705 the correct value of x_focus_frame. */
1706 x_focus_frame = frame;
1708 if (old_focus && old_focus->auto_lower)
1709 x_lower_frame (old_focus);
1711 #if 0
1712 selected_frame = frame;
1713 XSET (XWINDOW (selected_frame->selected_window)->frame,
1714 Lisp_Frame, selected_frame);
1715 Fselect_window (selected_frame->selected_window);
1716 choose_minibuf_frame ();
1717 #endif /* ! 0 */
1719 if (x_focus_frame && x_focus_frame->auto_raise)
1720 x_raise_frame (x_focus_frame);
1723 XTframe_rehighlight ();
1727 /* The focus has changed, or we have redirected a frame's focus to
1728 another frame (this happens when a frame uses a surrogate
1729 minibuffer frame). Shift the highlight as appropriate. */
1730 static void
1731 XTframe_rehighlight ()
1733 struct frame *old_highlight = x_highlight_frame;
1735 if (x_focus_frame)
1737 x_highlight_frame =
1738 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1739 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1740 : x_focus_frame);
1741 if (! FRAME_LIVE_P (x_highlight_frame))
1743 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1744 x_highlight_frame = x_focus_frame;
1747 else
1748 x_highlight_frame = 0;
1750 if (x_highlight_frame != old_highlight)
1752 if (old_highlight)
1753 frame_unhighlight (old_highlight);
1754 if (x_highlight_frame)
1755 frame_highlight (x_highlight_frame);
1759 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1761 /* Which modifier keys are on which modifier bits?
1763 With each keystroke, X returns eight bits indicating which modifier
1764 keys were held down when the key was pressed. The interpretation
1765 of the top five modifier bits depends on what keys are attached
1766 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1767 is the meta bit.
1769 x_meta_mod_mask is a mask containing the bits used for the meta key.
1770 It may have more than one bit set, if more than one modifier bit
1771 has meta keys on it. Basically, if EVENT is a KeyPress event,
1772 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1774 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1775 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1776 only be affected by the lock modifier bit if XK_Shift_Lock is in
1777 use; XK_Caps_Lock should only affect alphabetic keys. With this
1778 arrangement, the lock modifier should shift the character if
1779 (EVENT.state & x_shift_lock_mask) != 0. */
1780 static int x_meta_mod_mask, x_shift_lock_mask;
1782 /* These are like x_meta_mod_mask, but for different modifiers. */
1783 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1785 /* Initialize mode_switch_bit and modifier_meaning. */
1786 static void
1787 x_find_modifier_meanings ()
1789 int min_code, max_code;
1790 KeySym *syms;
1791 int syms_per_code;
1792 XModifierKeymap *mods;
1794 x_meta_mod_mask = 0;
1795 x_shift_lock_mask = 0;
1796 x_alt_mod_mask = 0;
1797 x_super_mod_mask = 0;
1798 x_hyper_mod_mask = 0;
1800 #ifdef HAVE_X11R4
1801 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1802 #else
1803 min_code = x_current_display->min_keycode;
1804 max_code = x_current_display->max_keycode;
1805 #endif
1807 syms = XGetKeyboardMapping (x_current_display,
1808 min_code, max_code - min_code + 1,
1809 &syms_per_code);
1810 mods = XGetModifierMapping (x_current_display);
1812 /* Scan the modifier table to see which modifier bits the Meta and
1813 Alt keysyms are on. */
1815 int row, col; /* The row and column in the modifier table. */
1817 for (row = 3; row < 8; row++)
1818 for (col = 0; col < mods->max_keypermod; col++)
1820 KeyCode code =
1821 mods->modifiermap[(row * mods->max_keypermod) + col];
1823 /* Zeroes are used for filler. Skip them. */
1824 if (code == 0)
1825 continue;
1827 /* Are any of this keycode's keysyms a meta key? */
1829 int code_col;
1831 for (code_col = 0; code_col < syms_per_code; code_col++)
1833 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1835 switch (sym)
1837 case XK_Meta_L:
1838 case XK_Meta_R:
1839 x_meta_mod_mask |= (1 << row);
1840 break;
1842 case XK_Alt_L:
1843 case XK_Alt_R:
1844 x_alt_mod_mask |= (1 << row);
1845 break;
1847 case XK_Hyper_L:
1848 case XK_Hyper_R:
1849 x_hyper_mod_mask |= (1 << row);
1850 break;
1852 case XK_Super_L:
1853 case XK_Super_R:
1854 x_super_mod_mask |= (1 << row);
1855 break;
1857 case XK_Shift_Lock:
1858 /* Ignore this if it's not on the lock modifier. */
1859 if ((1 << row) == LockMask)
1860 x_shift_lock_mask = LockMask;
1861 break;
1868 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1869 if (! x_meta_mod_mask)
1871 x_meta_mod_mask = x_alt_mod_mask;
1872 x_alt_mod_mask = 0;
1875 /* If some keys are both alt and meta,
1876 make them just meta, not alt. */
1877 if (x_alt_mod_mask & x_meta_mod_mask)
1879 x_alt_mod_mask &= ~x_meta_mod_mask;
1882 XFree ((char *) syms);
1883 XFreeModifiermap (mods);
1886 /* Convert between the modifier bits X uses and the modifier bits
1887 Emacs uses. */
1888 static unsigned int
1889 x_x_to_emacs_modifiers (state)
1890 unsigned int state;
1892 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1893 | ((state & ControlMask) ? ctrl_modifier : 0)
1894 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1895 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1896 | ((state & x_super_mod_mask) ? super_modifier : 0)
1897 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1900 static unsigned int
1901 x_emacs_to_x_modifiers (state)
1902 unsigned int state;
1904 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1905 | ((state & super_modifier) ? x_super_mod_mask : 0)
1906 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1907 | ((state & shift_modifier) ? ShiftMask : 0)
1908 | ((state & ctrl_modifier) ? ControlMask : 0)
1909 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1912 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1913 return as a function key. If you add a keysym to this, you should
1914 make sure that the tables make_lispy_event uses contain a suitable
1915 name for it. */
1916 static int
1917 x_is_vendor_fkey (sym)
1918 KeySym sym;
1920 return 0
1921 #ifdef DXK_Remove
1922 || (sym == DXK_Remove)
1923 #endif
1928 /* Mouse clicks and mouse movement. Rah. */
1929 #ifdef HAVE_X11
1931 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1932 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1933 that the glyph at X, Y occupies, if BOUNDS != 0.
1934 If NOCLIP is nonzero, do not force the value into range. */
1936 void
1937 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1938 FRAME_PTR f;
1939 register int pix_x, pix_y;
1940 register int *x, *y;
1941 XRectangle *bounds;
1942 int noclip;
1944 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1945 even for negative values. */
1946 if (pix_x < 0)
1947 pix_x -= FONT_WIDTH ((f)->display.x->font) - 1;
1948 if (pix_y < 0)
1949 pix_y -= (f)->display.x->line_height - 1;
1951 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1952 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1954 if (bounds)
1956 bounds->width = FONT_WIDTH (f->display.x->font);
1957 bounds->height = f->display.x->line_height;
1958 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1959 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1962 if (!noclip)
1964 if (pix_x < 0)
1965 pix_x = 0;
1966 else if (pix_x > f->width)
1967 pix_x = f->width;
1969 if (pix_y < 0)
1970 pix_y = 0;
1971 else if (pix_y > f->height)
1972 pix_y = f->height;
1975 *x = pix_x;
1976 *y = pix_y;
1979 void
1980 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1981 FRAME_PTR f;
1982 register int x, y;
1983 register int *pix_x, *pix_y;
1985 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1986 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1989 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1991 If the event is a button press, then note that we have grabbed
1992 the mouse. */
1994 static Lisp_Object
1995 construct_mouse_click (result, event, f)
1996 struct input_event *result;
1997 XButtonEvent *event;
1998 struct frame *f;
2000 /* Make the event type no_event; we'll change that when we decide
2001 otherwise. */
2002 result->kind = mouse_click;
2003 result->code = event->button - Button1;
2004 result->timestamp = event->time;
2005 result->modifiers = (x_x_to_emacs_modifiers (event->state)
2006 | (event->type == ButtonRelease
2007 ? up_modifier
2008 : down_modifier));
2010 /* Notice if the mouse is still grabbed. */
2011 if (event->type == ButtonPress)
2013 if (! x_mouse_grabbed)
2014 Vmouse_depressed = Qt;
2015 x_mouse_grabbed |= (1 << event->button);
2016 last_mouse_frame = f;
2018 else if (event->type == ButtonRelease)
2020 x_mouse_grabbed &= ~(1 << event->button);
2021 if (!x_mouse_grabbed)
2022 Vmouse_depressed = Qnil;
2026 int row, column;
2028 #if 0
2029 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
2030 XFASTINT (result->x) = column;
2031 XFASTINT (result->y) = row;
2032 #endif
2033 XSET (result->x, Lisp_Int, event->x);
2034 XSET (result->y, Lisp_Int, event->y);
2035 XSET (result->frame_or_window, Lisp_Frame, f);
2039 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2041 static Lisp_Object
2042 construct_menu_click (result, event, f)
2043 struct input_event *result;
2044 XButtonEvent *event;
2045 struct frame *f;
2047 /* Make the event type no_event; we'll change that when we decide
2048 otherwise. */
2049 result->kind = mouse_click;
2050 XSET (result->code, Lisp_Int, event->button - Button1);
2051 result->timestamp = event->time;
2052 result->modifiers = (x_x_to_emacs_modifiers (event->state)
2053 | (event->type == ButtonRelease
2054 ? up_modifier
2055 : down_modifier));
2057 XSET (result->x, Lisp_Int, event->x);
2058 XSET (result->y, Lisp_Int, -1);
2059 XSET (result->frame_or_window, Lisp_Frame, f);
2062 /* Function to report a mouse movement to the mainstream Emacs code.
2063 The input handler calls this.
2065 We have received a mouse movement event, which is given in *event.
2066 If the mouse is over a different glyph than it was last time, tell
2067 the mainstream emacs code by setting mouse_moved. If not, ask for
2068 another motion event, so we can check again the next time it moves. */
2070 static void
2071 note_mouse_movement (frame, event)
2072 FRAME_PTR frame;
2073 XMotionEvent *event;
2076 last_mouse_movement_time = event->time;
2078 /* Has the mouse moved off the glyph it was on at the last sighting? */
2079 if (event->x < last_mouse_glyph.x
2080 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
2081 || event->y < last_mouse_glyph.y
2082 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
2084 mouse_moved = 1;
2085 last_mouse_scroll_bar = Qnil;
2087 note_mouse_highlight (frame, event->x, event->y);
2089 /* Ask for another mouse motion event. */
2091 int dummy;
2093 XQueryPointer (event->display, event->window,
2094 (Window *) &dummy, (Window *) &dummy,
2095 &dummy, &dummy, &dummy, &dummy,
2096 (unsigned int *) &dummy);
2099 else
2101 /* It's on the same glyph. Call XQueryPointer so we'll get an
2102 event the next time the mouse moves and we can see if it's
2103 *still* on the same glyph. */
2104 int dummy;
2106 XQueryPointer (event->display, event->window,
2107 (Window *) &dummy, (Window *) &dummy,
2108 &dummy, &dummy, &dummy, &dummy,
2109 (unsigned int *) &dummy);
2113 /* This is used for debugging, to turn off note_mouse_highlight. */
2114 static int disable_mouse_highlight;
2116 /* Take proper action when the mouse has moved to position X, Y on frame F
2117 as regards highlighting characters that have mouse-face properties.
2118 Also dehighlighting chars where the mouse was before. */
2120 static void
2121 note_mouse_highlight (f, x, y)
2122 FRAME_PTR f;
2124 int row, column, portion;
2125 XRectangle new_glyph;
2126 Lisp_Object window;
2127 struct window *w;
2129 if (disable_mouse_highlight)
2130 return;
2132 mouse_face_mouse_x = x;
2133 mouse_face_mouse_y = y;
2134 mouse_face_mouse_frame = f;
2136 if (mouse_face_defer)
2137 return;
2139 if (gc_in_progress)
2141 mouse_face_deferred_gc = 1;
2142 return;
2145 /* Find out which glyph the mouse is on. */
2146 pixel_to_glyph_coords (f, x, y, &column, &row,
2147 &new_glyph, x_mouse_grabbed);
2149 /* Which window is that in? */
2150 window = window_from_coordinates (f, column, row, &portion);
2151 w = XWINDOW (window);
2153 /* If we were displaying active text in another window, clear that. */
2154 if (! EQ (window, mouse_face_window))
2155 clear_mouse_face ();
2157 /* Are we in a window whose display is up to date?
2158 And verify the buffer's text has not changed. */
2159 if (WINDOWP (window) && portion == 0
2160 && EQ (w->window_end_valid, w->buffer)
2161 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
2163 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
2164 int i, pos;
2166 /* Find which buffer position the mouse corresponds to. */
2167 for (i = column; i >= 0; i--)
2168 if (ptr[i] > 0)
2169 break;
2170 pos = ptr[i];
2171 /* Is it outside the displayed active region (if any)? */
2172 if (pos > 0
2173 && ! (EQ (window, mouse_face_window)
2174 && pos >= mouse_face_beg && pos < mouse_face_end))
2176 Lisp_Object mouse_face, overlay, position;
2177 Lisp_Object *overlay_vec;
2178 int len, noverlays, ignor1;
2179 struct buffer *obuf;
2180 int obegv, ozv;
2182 /* If we get an out-of-range value, return now; avoid an error. */
2183 if (pos > BUF_Z (XBUFFER (w->buffer)))
2184 return;
2186 /* Make the window's buffer temporarily current for
2187 overlays_at and compute_char_face. */
2188 obuf = current_buffer;
2189 current_buffer = XBUFFER (w->buffer);
2190 obegv = BEGV;
2191 ozv = ZV;
2192 BEGV = BEG;
2193 ZV = Z;
2195 /* Yes. Clear the display of the old active region, if any. */
2196 clear_mouse_face ();
2198 /* Is this char mouse-active? */
2199 XSET (position, Lisp_Int, pos);
2201 len = 10;
2202 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
2204 /* Put all the overlays we want in a vector in overlay_vec.
2205 Store the length in len. */
2206 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len, &ignor1);
2207 noverlays = sort_overlays (overlay_vec, noverlays, w);
2209 /* Find the highest priority overlay that has a mouse-face prop. */
2210 overlay = Qnil;
2211 for (i = 0; i < noverlays; i++)
2213 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2214 if (!NILP (mouse_face))
2216 overlay = overlay_vec[i];
2217 break;
2220 free (overlay_vec);
2221 /* If no overlay applies, get a text property. */
2222 if (NILP (overlay))
2223 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
2225 /* Handle the overlay case. */
2226 if (! NILP (overlay))
2228 /* Find the range of text around this char that
2229 should be active. */
2230 Lisp_Object before, after;
2231 int ignore;
2233 before = Foverlay_start (overlay);
2234 after = Foverlay_end (overlay);
2235 /* Record this as the current active region. */
2236 mouse_face_beg = XFASTINT (before);
2237 mouse_face_end = XFASTINT (after);
2238 mouse_face_window = window;
2239 mouse_face_face_id = compute_char_face (f, w, pos, 0, 0,
2240 &ignore, pos + 1, 1);
2242 /* Display it as active. */
2243 show_mouse_face (1);
2245 /* Handle the text property case. */
2246 else if (! NILP (mouse_face))
2248 /* Find the range of text around this char that
2249 should be active. */
2250 Lisp_Object before, after, beginning, end;
2251 int ignore;
2253 beginning = Fmarker_position (w->start);
2254 XSET (end, Lisp_Int,
2255 (BUF_Z (XBUFFER (w->buffer))
2256 - XFASTINT (w->window_end_pos)));
2257 before
2258 = Fprevious_single_property_change (make_number (pos + 1),
2259 Qmouse_face,
2260 w->buffer, beginning);
2261 after
2262 = Fnext_single_property_change (position, Qmouse_face,
2263 w->buffer, end);
2264 /* Record this as the current active region. */
2265 mouse_face_beg = XFASTINT (before);
2266 mouse_face_end = XFASTINT (after);
2267 mouse_face_window = window;
2268 mouse_face_face_id
2269 = compute_char_face (f, w, pos, 0, 0,
2270 &ignore, pos + 1, 1);
2272 /* Display it as active. */
2273 show_mouse_face (1);
2275 BEGV = obegv;
2276 ZV = ozv;
2277 current_buffer = obuf;
2279 else if (pos <= 0)
2280 clear_mouse_face ();
2284 /* Find the row and column of position POS in window WINDOW.
2285 Store them in *COLUMNP and *ROWP.
2286 This assumes display in WINDOW is up to date.
2287 If POS is above start of WINDOW, return coords
2288 of start of first screen line.
2289 If POS is after end of WINDOW, return coords of end of last screen line. */
2291 static int
2292 fast_find_position (window, pos, columnp, rowp)
2293 Lisp_Object window;
2294 int pos;
2295 int *columnp, *rowp;
2297 struct window *w = XWINDOW (window);
2298 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2299 int i;
2300 int row;
2301 int left = w->left;
2302 int top = w->top;
2303 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
2304 int width = window_internal_width (w);
2305 int *charstarts;
2306 int lastcol;
2308 for (i = 0;
2309 i < height;
2310 i++)
2312 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
2313 if (linestart > pos)
2314 break;
2315 if (linestart > 0)
2316 row = i;
2319 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
2320 lastcol = left;
2321 for (i = 0; i < width; i++)
2323 if (charstarts[left + i] == pos)
2325 *rowp = row + top;
2326 *columnp = i + left;
2327 return 1;
2329 else if (charstarts[left + i] > pos)
2330 lastcol = left + i;
2333 *rowp = row + top;
2334 *columnp = lastcol;
2335 return 0;
2338 /* Display the active region described by mouse_face_*
2339 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2341 static void
2342 show_mouse_face (hl)
2343 int hl;
2345 int begcol, begrow, endcol, endrow;
2346 struct window *w = XWINDOW (mouse_face_window);
2347 int width = window_internal_width (w);
2348 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2349 int i;
2350 int curs_x = f->phys_cursor_x;
2351 int curs_y = f->phys_cursor_y;
2352 int cursor_off = 0;
2354 fast_find_position (mouse_face_window, mouse_face_beg,
2355 &begcol, &begrow);
2356 fast_find_position (mouse_face_window, mouse_face_end,
2357 &endcol, &endrow);
2359 for (i = begrow; i <= endrow; i++)
2361 int column = (i == begrow ? begcol : w->left);
2362 int endcolumn = (i == endrow ? endcol : w->left + width);
2363 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i] - w->left);
2365 /* If the cursor's in the text we are about to rewrite,
2366 turn the cursor off. */
2367 if (i == curs_y
2368 && (curs_x >= begrow - 1 || curs_x <= endrow))
2370 x_display_cursor (f, 0);
2371 cursor_off = 1;
2374 dumpglyphs (f,
2375 CHAR_TO_PIXEL_COL (f, column),
2376 CHAR_TO_PIXEL_ROW (f, i),
2377 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
2378 endcolumn - column,
2379 /* Highlight with mouse face if hl > 0. */
2380 hl > 0 ? 3 : 0, 0);
2383 /* If we turned the cursor off, turn it back on. */
2384 if (cursor_off)
2385 x_display_cursor (f, 1);
2387 /* Change the mouse cursor according to the value of HL. */
2388 if (hl > 0)
2389 XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->cross_cursor);
2390 else
2391 XDefineCursor (XDISPLAY FRAME_X_WINDOW (f), f->display.x->text_cursor);
2394 /* Clear out the mouse-highlighted active region.
2395 Redraw it unhighlighted first. */
2397 static void
2398 clear_mouse_face ()
2400 if (! NILP (mouse_face_window))
2401 show_mouse_face (0);
2403 mouse_face_beg = -1;
2404 mouse_face_end = -1;
2405 mouse_face_window = Qnil;
2408 static struct scroll_bar *x_window_to_scroll_bar ();
2409 static void x_scroll_bar_report_motion ();
2411 /* Return the current position of the mouse.
2413 If the mouse movement started in a scroll bar, set *f, *bar_window,
2414 and *part to the frame, window, and scroll bar part that the mouse
2415 is over. Set *x and *y to the portion and whole of the mouse's
2416 position on the scroll bar.
2418 If the mouse movement started elsewhere, set *f to the frame the
2419 mouse is on, *bar_window to nil, and *x and *y to the character cell
2420 the mouse is over.
2422 Set *time to the server timestamp for the time at which the mouse
2423 was at this position.
2425 Don't store anything if we don't have a valid set of values to report.
2427 This clears the mouse_moved flag, so we can wait for the next mouse
2428 movement. This also calls XQueryPointer, which will cause the
2429 server to give us another MotionNotify when the mouse moves
2430 again. */
2432 static void
2433 XTmouse_position (f, bar_window, part, x, y, time)
2434 FRAME_PTR *f;
2435 Lisp_Object *bar_window;
2436 enum scroll_bar_part *part;
2437 Lisp_Object *x, *y;
2438 unsigned long *time;
2440 FRAME_PTR f1;
2442 BLOCK_INPUT;
2444 if (! NILP (last_mouse_scroll_bar))
2445 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
2446 else
2448 Window root;
2449 int root_x, root_y;
2451 Window dummy_window;
2452 int dummy;
2454 mouse_moved = 0;
2455 last_mouse_scroll_bar = Qnil;
2457 /* Figure out which root window we're on. */
2458 XQueryPointer (x_current_display,
2459 DefaultRootWindow (x_current_display),
2461 /* The root window which contains the pointer. */
2462 &root,
2464 /* Trash which we can't trust if the pointer is on
2465 a different screen. */
2466 &dummy_window,
2468 /* The position on that root window. */
2469 &root_x, &root_y,
2471 /* More trash we can't trust. */
2472 &dummy, &dummy,
2474 /* Modifier keys and pointer buttons, about which
2475 we don't care. */
2476 (unsigned int *) &dummy);
2478 /* Now we have a position on the root; find the innermost window
2479 containing the pointer. */
2481 Window win, child;
2482 int win_x, win_y;
2483 int parent_x, parent_y;
2485 win = root;
2487 if (x_mouse_grabbed)
2489 /* If mouse was grabbed on a frame, give coords for that frame
2490 even if the mouse is now outside it. */
2491 XTranslateCoordinates (x_current_display,
2493 /* From-window, to-window. */
2494 root, FRAME_X_WINDOW (last_mouse_frame),
2496 /* From-position, to-position. */
2497 root_x, root_y, &win_x, &win_y,
2499 /* Child of win. */
2500 &child);
2501 f1 = last_mouse_frame;
2503 else
2505 while (1)
2507 XTranslateCoordinates (x_current_display,
2509 /* From-window, to-window. */
2510 root, win,
2512 /* From-position, to-position. */
2513 root_x, root_y, &win_x, &win_y,
2515 /* Child of win. */
2516 &child);
2518 if (child == None)
2519 break;
2521 win = child;
2522 parent_x = win_x;
2523 parent_y = win_y;
2526 /* Now we know that:
2527 win is the innermost window containing the pointer
2528 (XTC says it has no child containing the pointer),
2529 win_x and win_y are the pointer's position in it
2530 (XTC did this the last time through), and
2531 parent_x and parent_y are the pointer's position in win's parent.
2532 (They are what win_x and win_y were when win was child.
2533 If win is the root window, it has no parent, and
2534 parent_{x,y} are invalid, but that's okay, because we'll
2535 never use them in that case.) */
2537 /* Is win one of our frames? */
2538 f1 = x_any_window_to_frame (win);
2541 /* If not, is it one of our scroll bars? */
2542 if (! f1)
2544 struct scroll_bar *bar = x_window_to_scroll_bar (win);
2546 if (bar)
2548 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2549 win_x = parent_x;
2550 win_y = parent_y;
2554 if (f1)
2556 int ignore1, ignore2;
2558 /* Ok, we found a frame. Store all the values. */
2560 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
2561 &last_mouse_glyph, x_mouse_grabbed);
2563 *bar_window = Qnil;
2564 *part = 0;
2565 *f = f1;
2566 XSET (*x, Lisp_Int, win_x);
2567 XSET (*y, Lisp_Int, win_y);
2568 *time = last_mouse_movement_time;
2573 UNBLOCK_INPUT;
2576 #else /* ! defined (HAVE_X11) */
2577 #define XEvent XKeyPressedEvent
2578 #endif /* ! defined (HAVE_X11) */
2580 /* Scroll bar support. */
2582 /* Given an X window ID, find the struct scroll_bar which manages it.
2583 This can be called in GC, so we have to make sure to strip off mark
2584 bits. */
2585 static struct scroll_bar *
2586 x_window_to_scroll_bar (window_id)
2587 Window window_id;
2589 Lisp_Object tail, frame;
2591 for (tail = Vframe_list;
2592 XGCTYPE (tail) == Lisp_Cons;
2593 tail = XCONS (tail)->cdr)
2595 Lisp_Object frame, bar, condemned;
2597 frame = XCONS (tail)->car;
2598 /* All elements of Vframe_list should be frames. */
2599 if (XGCTYPE (frame) != Lisp_Frame)
2600 abort ();
2602 /* Scan this frame's scroll bar list for a scroll bar with the
2603 right window ID. */
2604 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
2605 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
2606 /* This trick allows us to search both the ordinary and
2607 condemned scroll bar lists with one loop. */
2608 ! GC_NILP (bar) || (bar = condemned,
2609 condemned = Qnil,
2610 ! GC_NILP (bar));
2611 bar = XSCROLL_BAR (bar)->next)
2612 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
2613 return XSCROLL_BAR (bar);
2616 return 0;
2619 /* Open a new X window to serve as a scroll bar, and return the
2620 scroll bar vector for it. */
2621 static struct scroll_bar *
2622 x_scroll_bar_create (window, top, left, width, height)
2623 struct window *window;
2624 int top, left, width, height;
2626 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
2627 struct scroll_bar *bar =
2628 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
2630 BLOCK_INPUT;
2633 XSetWindowAttributes a;
2634 unsigned long mask;
2635 a.background_pixel = frame->display.x->background_pixel;
2636 a.event_mask = (ButtonPressMask | ButtonReleaseMask
2637 | ButtonMotionMask | PointerMotionHintMask
2638 | ExposureMask);
2639 a.cursor = x_vertical_scroll_bar_cursor;
2641 mask = (CWBackPixel | CWEventMask | CWCursor);
2643 #if 0
2645 ac = 0;
2646 XtSetArg (al[ac], XtNx, left); ac++;
2647 XtSetArg (al[ac], XtNy, top); ac++;
2648 XtSetArg (al[ac], XtNwidth, width); ac++;
2649 XtSetArg (al[ac], XtNheight, height); ac++;
2650 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2651 sb_widget = XtCreateManagedWidget ("box",
2652 boxWidgetClass,
2653 frame->display.x->edit_widget, al, ac);
2654 SET_SCROLL_BAR_X_WINDOW
2655 (bar, sb_widget->core.window);
2656 #endif
2657 SET_SCROLL_BAR_X_WINDOW
2658 (bar,
2659 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
2661 /* Position and size of scroll bar. */
2662 left, top, width, height,
2664 /* Border width, depth, class, and visual. */
2665 0, CopyFromParent, CopyFromParent, CopyFromParent,
2667 /* Attributes. */
2668 mask, &a));
2671 XSET (bar->window, Lisp_Window, window);
2672 XSET (bar->top, Lisp_Int, top);
2673 XSET (bar->left, Lisp_Int, left);
2674 XSET (bar->width, Lisp_Int, width);
2675 XSET (bar->height, Lisp_Int, height);
2676 XSET (bar->start, Lisp_Int, 0);
2677 XSET (bar->end, Lisp_Int, 0);
2678 bar->dragging = Qnil;
2680 /* Add bar to its frame's list of scroll bars. */
2681 bar->next = FRAME_SCROLL_BARS (frame);
2682 bar->prev = Qnil;
2683 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
2684 if (! NILP (bar->next))
2685 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2687 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2689 UNBLOCK_INPUT;
2691 return bar;
2694 /* Draw BAR's handle in the proper position.
2695 If the handle is already drawn from START to END, don't bother
2696 redrawing it, unless REBUILD is non-zero; in that case, always
2697 redraw it. (REBUILD is handy for drawing the handle after expose
2698 events.)
2700 Normally, we want to constrain the start and end of the handle to
2701 fit inside its rectangle, but if the user is dragging the scroll bar
2702 handle, we want to let them drag it down all the way, so that the
2703 bar's top is as far down as it goes; otherwise, there's no way to
2704 move to the very end of the buffer. */
2705 static void
2706 x_scroll_bar_set_handle (bar, start, end, rebuild)
2707 struct scroll_bar *bar;
2708 int start, end;
2709 int rebuild;
2711 int dragging = ! NILP (bar->dragging);
2712 Window w = SCROLL_BAR_X_WINDOW (bar);
2713 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2715 /* If the display is already accurate, do nothing. */
2716 if (! rebuild
2717 && start == XINT (bar->start)
2718 && end == XINT (bar->end))
2719 return;
2721 BLOCK_INPUT;
2724 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
2725 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2726 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2728 /* Make sure the values are reasonable, and try to preserve
2729 the distance between start and end. */
2731 int length = end - start;
2733 if (start < 0)
2734 start = 0;
2735 else if (start > top_range)
2736 start = top_range;
2737 end = start + length;
2739 if (end < start)
2740 end = start;
2741 else if (end > top_range && ! dragging)
2742 end = top_range;
2745 /* Store the adjusted setting in the scroll bar. */
2746 XSET (bar->start, Lisp_Int, start);
2747 XSET (bar->end, Lisp_Int, end);
2749 /* Clip the end position, just for display. */
2750 if (end > top_range)
2751 end = top_range;
2753 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2754 below top positions, to make sure the handle is always at least
2755 that many pixels tall. */
2756 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2758 /* Draw the empty space above the handle. Note that we can't clear
2759 zero-height areas; that means "clear to end of window." */
2760 if (0 < start)
2761 XClearArea (x_current_display, w,
2763 /* x, y, width, height, and exposures. */
2764 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2765 VERTICAL_SCROLL_BAR_TOP_BORDER,
2766 inside_width, start,
2767 False);
2769 /* Draw the handle itself. */
2770 XFillRectangle (x_current_display, w, gc,
2772 /* x, y, width, height */
2773 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2774 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2775 inside_width, end - start);
2778 /* Draw the empty space below the handle. Note that we can't
2779 clear zero-height areas; that means "clear to end of window." */
2780 if (end < inside_height)
2781 XClearArea (x_current_display, w,
2783 /* x, y, width, height, and exposures. */
2784 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2785 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2786 inside_width, inside_height - end,
2787 False);
2791 UNBLOCK_INPUT;
2794 /* Move a scroll bar around on the screen, to accommodate changing
2795 window configurations. */
2796 static void
2797 x_scroll_bar_move (bar, top, left, width, height)
2798 struct scroll_bar *bar;
2799 int top, left, width, height;
2801 BLOCK_INPUT;
2804 XWindowChanges wc;
2805 unsigned int mask = 0;
2807 wc.x = left;
2808 wc.y = top;
2809 wc.width = width;
2810 wc.height = height;
2812 if (left != XINT (bar->left)) mask |= CWX;
2813 if (top != XINT (bar->top)) mask |= CWY;
2814 if (width != XINT (bar->width)) mask |= CWWidth;
2815 if (height != XINT (bar->height)) mask |= CWHeight;
2817 if (mask)
2818 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
2819 mask, &wc);
2822 XSET (bar->left, Lisp_Int, left);
2823 XSET (bar->top, Lisp_Int, top);
2824 XSET (bar->width, Lisp_Int, width);
2825 XSET (bar->height, Lisp_Int, height);
2827 UNBLOCK_INPUT;
2830 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2831 to nil. */
2832 static void
2833 x_scroll_bar_remove (bar)
2834 struct scroll_bar *bar;
2836 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2838 BLOCK_INPUT;
2840 /* Destroy the window. */
2841 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2843 /* Disassociate this scroll bar from its window. */
2844 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2846 UNBLOCK_INPUT;
2849 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2850 that we are displaying PORTION characters out of a total of WHOLE
2851 characters, starting at POSITION. If WINDOW has no scroll bar,
2852 create one. */
2853 static void
2854 XTset_vertical_scroll_bar (window, portion, whole, position)
2855 struct window *window;
2856 int portion, whole, position;
2858 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2859 int top = XINT (window->top);
2860 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2861 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2863 /* Where should this scroll bar be, pixelwise? */
2864 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2865 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2866 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2867 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2869 struct scroll_bar *bar;
2871 /* Does the scroll bar exist yet? */
2872 if (NILP (window->vertical_scroll_bar))
2873 bar = x_scroll_bar_create (window,
2874 pixel_top, pixel_left,
2875 pixel_width, pixel_height);
2876 else
2878 /* It may just need to be moved and resized. */
2879 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2880 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2883 /* Set the scroll bar's current state, unless we're currently being
2884 dragged. */
2885 if (NILP (bar->dragging))
2887 int top_range =
2888 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2890 if (whole == 0)
2891 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2892 else
2894 int start = ((double) position * top_range) / whole;
2895 int end = ((double) (position + portion) * top_range) / whole;
2897 x_scroll_bar_set_handle (bar, start, end, 0);
2901 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2905 /* The following three hooks are used when we're doing a thorough
2906 redisplay of the frame. We don't explicitly know which scroll bars
2907 are going to be deleted, because keeping track of when windows go
2908 away is a real pain - "Can you say set-window-configuration, boys
2909 and girls?" Instead, we just assert at the beginning of redisplay
2910 that *all* scroll bars are to be removed, and then save a scroll bar
2911 from the fiery pit when we actually redisplay its window. */
2913 /* Arrange for all scroll bars on FRAME to be removed at the next call
2914 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2915 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2916 static void
2917 XTcondemn_scroll_bars (frame)
2918 FRAME_PTR frame;
2920 /* The condemned list should be empty at this point; if it's not,
2921 then the rest of Emacs isn't using the condemn/redeem/judge
2922 protocol correctly. */
2923 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2924 abort ();
2926 /* Move them all to the "condemned" list. */
2927 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2928 FRAME_SCROLL_BARS (frame) = Qnil;
2931 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2932 Note that WINDOW isn't necessarily condemned at all. */
2933 static void
2934 XTredeem_scroll_bar (window)
2935 struct window *window;
2937 struct scroll_bar *bar;
2939 /* We can't redeem this window's scroll bar if it doesn't have one. */
2940 if (NILP (window->vertical_scroll_bar))
2941 abort ();
2943 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2945 /* Unlink it from the condemned list. */
2947 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2949 if (NILP (bar->prev))
2951 /* If the prev pointer is nil, it must be the first in one of
2952 the lists. */
2953 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2954 /* It's not condemned. Everything's fine. */
2955 return;
2956 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2957 window->vertical_scroll_bar))
2958 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2959 else
2960 /* If its prev pointer is nil, it must be at the front of
2961 one or the other! */
2962 abort ();
2964 else
2965 XSCROLL_BAR (bar->prev)->next = bar->next;
2967 if (! NILP (bar->next))
2968 XSCROLL_BAR (bar->next)->prev = bar->prev;
2970 bar->next = FRAME_SCROLL_BARS (f);
2971 bar->prev = Qnil;
2972 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2973 if (! NILP (bar->next))
2974 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2978 /* Remove all scroll bars on FRAME that haven't been saved since the
2979 last call to `*condemn_scroll_bars_hook'. */
2980 static void
2981 XTjudge_scroll_bars (f)
2982 FRAME_PTR f;
2984 Lisp_Object bar, next;
2986 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2988 /* Clear out the condemned list now so we won't try to process any
2989 more events on the hapless scroll bars. */
2990 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2992 for (; ! NILP (bar); bar = next)
2994 struct scroll_bar *b = XSCROLL_BAR (bar);
2996 x_scroll_bar_remove (b);
2998 next = b->next;
2999 b->next = b->prev = Qnil;
3002 /* Now there should be no references to the condemned scroll bars,
3003 and they should get garbage-collected. */
3007 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3009 This may be called from a signal handler, so we have to ignore GC
3010 mark bits. */
3011 static void
3012 x_scroll_bar_expose (bar, event)
3013 struct scroll_bar *bar;
3014 XEvent *event;
3016 Window w = SCROLL_BAR_X_WINDOW (bar);
3017 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
3019 BLOCK_INPUT;
3021 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
3023 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3024 XDrawRectangle (x_current_display, w, gc,
3026 /* x, y, width, height */
3027 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
3029 UNBLOCK_INPUT;
3032 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3033 is set to something other than no_event, it is enqueued.
3035 This may be called from a signal handler, so we have to ignore GC
3036 mark bits. */
3037 static void
3038 x_scroll_bar_handle_click (bar, event, emacs_event)
3039 struct scroll_bar *bar;
3040 XEvent *event;
3041 struct input_event *emacs_event;
3043 if (XGCTYPE (bar->window) != Lisp_Window)
3044 abort ();
3046 emacs_event->kind = scroll_bar_click;
3047 emacs_event->code = event->xbutton.button - Button1;
3048 emacs_event->modifiers =
3049 (x_x_to_emacs_modifiers (event->xbutton.state)
3050 | (event->type == ButtonRelease
3051 ? up_modifier
3052 : down_modifier));
3053 emacs_event->frame_or_window = bar->window;
3054 emacs_event->timestamp = event->xbutton.time;
3056 int internal_height =
3057 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
3058 int top_range =
3059 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3060 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
3062 if (y < 0) y = 0;
3063 if (y > top_range) y = top_range;
3065 if (y < XINT (bar->start))
3066 emacs_event->part = scroll_bar_above_handle;
3067 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
3068 emacs_event->part = scroll_bar_handle;
3069 else
3070 emacs_event->part = scroll_bar_below_handle;
3072 /* Just because the user has clicked on the handle doesn't mean
3073 they want to drag it. Lisp code needs to be able to decide
3074 whether or not we're dragging. */
3075 #if 0
3076 /* If the user has just clicked on the handle, record where they're
3077 holding it. */
3078 if (event->type == ButtonPress
3079 && emacs_event->part == scroll_bar_handle)
3080 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
3081 #endif
3083 /* If the user has released the handle, set it to its final position. */
3084 if (event->type == ButtonRelease
3085 && ! NILP (bar->dragging))
3087 int new_start = y - XINT (bar->dragging);
3088 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
3090 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
3091 bar->dragging = Qnil;
3094 /* Same deal here as the other #if 0. */
3095 #if 0
3096 /* Clicks on the handle are always reported as occurring at the top of
3097 the handle. */
3098 if (emacs_event->part == scroll_bar_handle)
3099 emacs_event->x = bar->start;
3100 else
3101 XSET (emacs_event->x, Lisp_Int, y);
3102 #else
3103 XSET (emacs_event->x, Lisp_Int, y);
3104 #endif
3106 XSET (emacs_event->y, Lisp_Int, top_range);
3110 /* Handle some mouse motion while someone is dragging the scroll bar.
3112 This may be called from a signal handler, so we have to ignore GC
3113 mark bits. */
3114 static void
3115 x_scroll_bar_note_movement (bar, event)
3116 struct scroll_bar *bar;
3117 XEvent *event;
3119 last_mouse_movement_time = event->xmotion.time;
3121 mouse_moved = 1;
3122 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
3124 /* If we're dragging the bar, display it. */
3125 if (! GC_NILP (bar->dragging))
3127 /* Where should the handle be now? */
3128 int new_start = event->xmotion.y - XINT (bar->dragging);
3130 if (new_start != XINT (bar->start))
3132 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
3134 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
3138 /* Call XQueryPointer so we'll get an event the next time the mouse
3139 moves and we can see *still* on the same position. */
3141 int dummy;
3143 XQueryPointer (event->xmotion.display, event->xmotion.window,
3144 (Window *) &dummy, (Window *) &dummy,
3145 &dummy, &dummy, &dummy, &dummy,
3146 (unsigned int *) &dummy);
3150 /* Return information to the user about the current position of the mouse
3151 on the scroll bar. */
3152 static void
3153 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
3154 FRAME_PTR *f;
3155 Lisp_Object *bar_window;
3156 enum scroll_bar_part *part;
3157 Lisp_Object *x, *y;
3158 unsigned long *time;
3160 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3161 int win_x, win_y;
3162 Window dummy_window;
3163 int dummy_coord;
3164 unsigned int dummy_mask;
3166 BLOCK_INPUT;
3168 /* Get the mouse's position relative to the scroll bar window, and
3169 report that. */
3170 if (! XQueryPointer (x_current_display,
3171 SCROLL_BAR_X_WINDOW (bar),
3173 /* Root, child, root x and root y. */
3174 &dummy_window, &dummy_window,
3175 &dummy_coord, &dummy_coord,
3177 /* Position relative to scroll bar. */
3178 &win_x, &win_y,
3180 /* Mouse buttons and modifier keys. */
3181 &dummy_mask))
3182 *f = 0;
3183 else
3185 int inside_height
3186 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
3187 int top_range
3188 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3190 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
3192 if (! NILP (bar->dragging))
3193 win_y -= XINT (bar->dragging);
3195 if (win_y < 0)
3196 win_y = 0;
3197 if (win_y > top_range)
3198 win_y = top_range;
3200 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3201 *bar_window = bar->window;
3203 if (! NILP (bar->dragging))
3204 *part = scroll_bar_handle;
3205 else if (win_y < XINT (bar->start))
3206 *part = scroll_bar_above_handle;
3207 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
3208 *part = scroll_bar_handle;
3209 else
3210 *part = scroll_bar_below_handle;
3212 XSET (*x, Lisp_Int, win_y);
3213 XSET (*y, Lisp_Int, top_range);
3215 mouse_moved = 0;
3216 last_mouse_scroll_bar = Qnil;
3219 *time = last_mouse_movement_time;
3221 UNBLOCK_INPUT;
3225 /* The screen has been cleared so we may have changed foreground or
3226 background colors, and the scroll bars may need to be redrawn.
3227 Clear out the scroll bars, and ask for expose events, so we can
3228 redraw them. */
3230 x_scroll_bar_clear (f)
3231 FRAME_PTR f;
3233 Lisp_Object bar;
3235 for (bar = FRAME_SCROLL_BARS (f);
3236 XTYPE (bar) == Lisp_Vector;
3237 bar = XSCROLL_BAR (bar)->next)
3238 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
3239 0, 0, 0, 0, True);
3242 /* This processes Expose events from the menubar specific X event
3243 loop in menubar.c. This allows to redisplay the frame if necessary
3244 when handling menubar or popup items. */
3246 void
3247 process_expose_from_menu (event)
3248 XEvent event;
3250 FRAME_PTR f;
3252 BLOCK_INPUT;
3254 f = x_window_to_frame (event.xexpose.window);
3255 if (f)
3257 if (f->async_visible == 0)
3259 f->async_visible = 1;
3260 f->async_iconified = 0;
3261 SET_FRAME_GARBAGED (f);
3263 else
3265 dumprectangle (x_window_to_frame (event.xexpose.window),
3266 event.xexpose.x, event.xexpose.y,
3267 event.xexpose.width, event.xexpose.height);
3270 else
3272 struct scroll_bar *bar
3273 = x_window_to_scroll_bar (event.xexpose.window);
3275 if (bar)
3276 x_scroll_bar_expose (bar, &event);
3279 UNBLOCK_INPUT;
3283 /* The main X event-reading loop - XTread_socket. */
3285 /* Timestamp of enter window event. This is only used by XTread_socket,
3286 but we have to put it out here, since static variables within functions
3287 sometimes don't work. */
3288 static Time enter_timestamp;
3290 /* This holds the state XLookupString needs to implement dead keys
3291 and other tricks known as "compose processing". _X Window System_
3292 says that a portable program can't use this, but Stephen Gildea assures
3293 me that letting the compiler initialize it to zeros will work okay.
3295 This must be defined outside of XTread_socket, for the same reasons
3296 given for enter_timestamp, above. */
3297 static XComposeStatus compose_status;
3299 /* Communication with window managers. */
3300 Atom Xatom_wm_protocols;
3302 /* Kinds of protocol things we may receive. */
3303 Atom Xatom_wm_take_focus;
3304 Atom Xatom_wm_save_yourself;
3305 Atom Xatom_wm_delete_window;
3307 /* Other WM communication */
3308 Atom Xatom_wm_configure_denied; /* When our config request is denied */
3309 Atom Xatom_wm_window_moved; /* When the WM moves us. */
3311 /* Window manager communication. */
3312 Atom Xatom_wm_change_state;
3314 /* Record the last 100 characters stored
3315 to help debug the loss-of-chars-during-GC problem. */
3316 int temp_index;
3317 short temp_buffer[100];
3319 /* Read events coming from the X server.
3320 This routine is called by the SIGIO handler.
3321 We return as soon as there are no more events to be read.
3323 Events representing keys are stored in buffer BUFP,
3324 which can hold up to NUMCHARS characters.
3325 We return the number of characters stored into the buffer,
3326 thus pretending to be `read'.
3328 WAITP is nonzero if we should block until input arrives.
3329 EXPECTED is nonzero if the caller knows input is available. */
3332 XTread_socket (sd, bufp, numchars, waitp, expected)
3333 register int sd;
3334 register struct input_event *bufp;
3335 register int numchars;
3336 int waitp;
3337 int expected;
3339 int count = 0;
3340 int nbytes = 0;
3341 int mask;
3342 int items_pending; /* How many items are in the X queue. */
3343 XEvent event;
3344 struct frame *f;
3345 int event_found = 0;
3346 int prefix;
3347 Lisp_Object part;
3349 if (interrupt_input_blocked)
3351 interrupt_input_pending = 1;
3352 return -1;
3355 interrupt_input_pending = 0;
3356 BLOCK_INPUT;
3358 if (numchars <= 0)
3359 abort (); /* Don't think this happens. */
3361 #ifdef FIOSNBIO
3362 /* If available, Xlib uses FIOSNBIO to make the socket
3363 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3364 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
3365 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3366 fcntl (fileno (stdin), F_SETFL, 0);
3367 #endif /* ! defined (FIOSNBIO) */
3369 #ifndef SIGIO
3370 #ifndef HAVE_SELECT
3371 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
3373 extern int read_alarm_should_throw;
3374 read_alarm_should_throw = 1;
3375 XPeekEvent (XDISPLAY &event);
3376 read_alarm_should_throw = 0;
3378 #endif /* HAVE_SELECT */
3379 #endif /* SIGIO */
3381 while (XStuffPending () != 0)
3383 XNextEvent (XDISPLAY &event);
3384 event_found = 1;
3386 switch (event.type)
3388 #ifdef HAVE_X11
3389 case ClientMessage:
3391 if (event.xclient.message_type == Xatom_wm_protocols
3392 && event.xclient.format == 32)
3394 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
3396 #ifdef USE_X_TOOLKIT
3397 /* f = x_any_window_to_frame (event.xclient.window); */
3398 f = x_window_to_frame (event.xclient.window);
3399 #else
3400 f = x_window_to_frame (event.xclient.window);
3401 #endif
3402 if (f)
3403 x_focus_on_frame (f);
3404 /* Not certain about handling scroll bars here */
3406 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
3408 /* Save state modify the WM_COMMAND property to
3409 something which can reinstate us. This notifies
3410 the session manager, who's looking for such a
3411 PropertyNotify. Can restart processing when
3412 a keyboard or mouse event arrives. */
3413 if (numchars > 0)
3417 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
3419 struct frame *f = x_any_window_to_frame (event.xclient.window);
3421 if (f)
3423 if (numchars == 0)
3424 abort ();
3426 bufp->kind = delete_window_event;
3427 XSET (bufp->frame_or_window, Lisp_Frame, f);
3428 bufp++;
3430 count += 1;
3431 numchars -= 1;
3435 else if (event.xclient.message_type == Xatom_wm_configure_denied)
3438 else if (event.xclient.message_type == Xatom_wm_window_moved)
3440 int new_x, new_y;
3441 struct frame *f = x_window_to_frame (event.xclient.window);
3443 new_x = event.xclient.data.s[0];
3444 new_y = event.xclient.data.s[1];
3446 if (f)
3448 f->display.x->left_pos = new_x;
3449 f->display.x->top_pos = new_y;
3453 break;
3455 #ifdef NEW_SELECTIONS
3456 case SelectionNotify:
3457 #ifdef USE_X_TOOLKIT
3458 if (x_window_to_frame (event.xselection.requestor))
3459 x_handle_selection_notify (&event);
3460 else
3461 goto OTHER;
3462 #else /* not USE_X_TOOLKIT */
3463 x_handle_selection_notify (&event);
3464 #endif /* not USE_X_TOOLKIT */
3465 break;
3466 #endif /* NEW_SELECTIONS */
3468 case SelectionClear: /* Someone has grabbed ownership. */
3469 #ifdef NEW_SELECTIONS
3471 #ifdef USE_X_TOOLKIT
3472 if (x_window_to_frame (event.xselectionclear.window))
3474 #endif /* USE_X_TOOLKIT */
3475 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
3477 if (numchars == 0)
3478 abort ();
3480 bufp->kind = selection_clear_event;
3481 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3482 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3483 SELECTION_EVENT_TIME (bufp) = eventp->time;
3484 bufp++;
3486 count += 1;
3487 numchars -= 1;
3488 #ifdef USE_X_TOOLKIT
3490 else
3491 goto OTHER;
3492 #endif /* USE_X_TOOLKIT */
3494 #else /* not NEW_SELECTIONS */
3495 x_disown_selection (event.xselectionclear.window,
3496 event.xselectionclear.selection,
3497 event.xselectionclear.time);
3498 #endif /* not NEW_SELECTIONS */
3499 break;
3501 case SelectionRequest: /* Someone wants our selection. */
3502 #ifdef NEW_SELECTIONS
3504 #ifdef USE_X_TOOLKIT
3505 if (x_window_to_frame (event.xselectionrequest.owner))
3507 #endif /* USE_X_TOOLKIT */
3508 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
3510 if (numchars == 0)
3511 abort ();
3513 bufp->kind = selection_request_event;
3514 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3515 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
3516 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3517 SELECTION_EVENT_TARGET (bufp) = eventp->target;
3518 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
3519 SELECTION_EVENT_TIME (bufp) = eventp->time;
3520 bufp++;
3522 count += 1;
3523 numchars -= 1;
3524 #ifdef USE_X_TOOLKIT
3526 else
3527 goto OTHER;
3528 #endif /* USE_X_TOOLKIT */
3530 #else /* not NEW_SELECTIONS */
3531 x_answer_selection_request (event);
3532 #endif /* not NEW_SELECTIONS */
3533 break;
3535 case PropertyNotify:
3536 #ifdef NEW_SELECTIONS
3537 #ifdef USE_X_TOOLKIT
3538 if (x_any_window_to_frame (event.xproperty.window))
3539 x_handle_property_notify (&event);
3540 else
3541 goto OTHER;
3542 #else /* not USE_X_TOOLKIT */
3543 x_handle_property_notify (&event);
3544 #endif /* not USE_X_TOOLKIT */
3545 #else /* not NEW_SELECTIONS */
3546 /* If we're being told about a root window property, then it's
3547 a cut buffer change. */
3548 if (event.xproperty.window == ROOT_WINDOW)
3549 x_invalidate_cut_buffer_cache (&event.xproperty);
3551 /* Otherwise, we're probably handling an incremental
3552 selection transmission. */
3553 else
3555 /* If we were to do this synchronously, there'd be no worry
3556 about re-selecting. */
3557 x_send_incremental (event);
3559 #endif /* not NEW_SELECTIONS */
3560 break;
3562 case ReparentNotify:
3563 f = x_window_to_frame (event.xreparent.window);
3564 if (f)
3565 f->display.x->parent_desc = event.xreparent.parent;
3566 break;
3568 case Expose:
3569 f = x_window_to_frame (event.xexpose.window);
3570 if (f)
3572 if (f->async_visible == 0)
3574 f->async_visible = 1;
3575 f->async_iconified = 0;
3576 SET_FRAME_GARBAGED (f);
3578 else
3580 dumprectangle (x_window_to_frame (event.xexpose.window),
3581 event.xexpose.x, event.xexpose.y,
3582 event.xexpose.width, event.xexpose.height);
3585 else
3587 struct scroll_bar *bar
3588 = x_window_to_scroll_bar (event.xexpose.window);
3590 if (bar)
3591 x_scroll_bar_expose (bar, &event);
3592 #ifdef USE_X_TOOLKIT
3593 else
3594 goto OTHER;
3595 #endif /* USE_X_TOOLKIT */
3597 break;
3599 case GraphicsExpose: /* This occurs when an XCopyArea's
3600 source area was obscured or not
3601 available.*/
3602 f = x_window_to_frame (event.xgraphicsexpose.drawable);
3603 if (f)
3605 dumprectangle (f,
3606 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
3607 event.xgraphicsexpose.width,
3608 event.xgraphicsexpose.height);
3610 #ifdef USE_X_TOOLKIT
3611 else
3612 goto OTHER;
3613 #endif /* USE_X_TOOLKIT */
3614 break;
3616 case NoExpose: /* This occurs when an XCopyArea's
3617 source area was completely
3618 available */
3619 break;
3620 #else /* ! defined (HAVE_X11) */
3621 case ExposeWindow:
3622 if (event.subwindow != 0)
3623 break; /* duplicate event */
3624 f = x_window_to_frame (event.window);
3625 if (event.window == f->display.x->icon_desc)
3627 refreshicon (f);
3628 f->async_iconified = 1;
3630 if (event.window == FRAME_X_WINDOW (f))
3632 /* Say must check all windows' needs_exposure flags. */
3633 expose_all_windows = 1;
3634 f->display.x->needs_exposure = 1;
3635 f->async_visible = 1;
3637 break;
3639 case ExposeRegion:
3640 if (event.subwindow != 0)
3641 break; /* duplicate event */
3642 f = x_window_to_frame (event.window);
3643 if (event.window == f->display.x->icon_desc)
3645 refreshicon (f);
3646 break;
3648 /* If window already needs full redraw, ignore this rectangle. */
3649 if (expose_all_windows && f->display.x->needs_exposure)
3650 break;
3651 /* Put the event on the queue of rectangles to redraw. */
3652 if (enqueue_event (&event, &x_expose_queue))
3653 /* If it is full, we can't record the rectangle,
3654 so redraw this entire window. */
3656 /* Say must check all windows' needs_exposure flags. */
3657 expose_all_windows = 1;
3658 f->display.x->needs_exposure = 1;
3660 break;
3662 case ExposeCopy:
3663 /* This should happen only when we are expecting it,
3664 in x_read_exposes. */
3665 abort ();
3666 #endif /* ! defined (HAVE_X11) */
3668 #ifdef HAVE_X11
3669 case UnmapNotify:
3670 f = x_window_to_frame (event.xunmap.window);
3671 if (f) /* F may no longer exist if
3672 the frame was deleted. */
3674 /* While a frame is unmapped, display generation is
3675 disabled; you don't want to spend time updating a
3676 display that won't ever be seen. */
3677 f->async_visible = 0;
3678 /* The window manager never makes a window invisible
3679 ("withdrawn"); all it does is switch between visible
3680 and iconified. Frames get into the invisible state
3681 only through x_make_frame_invisible. */
3682 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
3683 f->async_iconified = 1;
3685 #ifdef USE_X_TOOLKIT
3686 goto OTHER;
3687 #endif /* USE_X_TOOLKIT */
3688 break;
3690 case MapNotify:
3691 #ifdef USE_X_TOOLKIT
3692 f = x_any_window_to_frame (event.xmap.window);
3693 #else /* not USE_X_TOOLKIT */
3694 f = x_window_to_frame (event.xmap.window);
3695 #endif /* not USE_X_TOOLKIT */
3696 if (f)
3698 f->async_visible = 1;
3699 f->async_iconified = 0;
3701 /* wait_reading_process_input will notice this and update
3702 the frame's display structures. */
3703 SET_FRAME_GARBAGED (f);
3705 #ifdef USE_X_TOOLKIT
3706 goto OTHER;
3707 #endif /* USE_X_TOOLKIT */
3708 break;
3710 /* Turn off processing if we become fully obscured. */
3711 case VisibilityNotify:
3712 break;
3714 #else /* ! defined (HAVE_X11) */
3715 case UnmapWindow:
3716 f = x_window_to_frame (event.window);
3717 if (event.window == f->display.x->icon_desc)
3718 f->async_iconified = 0;
3719 if (event.window == FRAME_X_WINDOW (f))
3720 f->async_visible = 0;
3721 break;
3722 #endif /* ! defined (HAVE_X11) */
3724 #ifdef HAVE_X11
3725 case KeyPress:
3726 f = x_any_window_to_frame (event.xkey.window);
3728 if (f != 0)
3730 KeySym keysym, orig_keysym;
3731 /* al%imercury@uunet.uu.net says that making this 81 instead of
3732 80 fixed a bug whereby meta chars made his Emacs hang. */
3733 unsigned char copy_buffer[81];
3734 int modifiers;
3736 event.xkey.state
3737 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
3738 modifiers = event.xkey.state;
3740 /* This will have to go some day... */
3742 /* make_lispy_event turns chars into control chars.
3743 Don't do it here because XLookupString is too eager. */
3744 event.xkey.state &= ~ControlMask;
3745 nbytes =
3746 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
3747 &compose_status);
3749 /* Strip off the vendor-specific keysym bit, and take a shot
3750 at recognizing the codes. HP servers have extra keysyms
3751 that fit into the MiscFunctionKey category. */
3752 orig_keysym = keysym;
3753 keysym &= ~(1<<28);
3755 if (numchars > 1)
3757 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
3758 || keysym == XK_Delete
3759 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
3760 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
3761 #ifdef HPUX
3762 /* This recognizes the "extended function keys".
3763 It seems there's no cleaner way.
3764 Test IsModifierKey to avoid handling mode_switch
3765 incorrectly. */
3766 || ((unsigned) (keysym) >= XK_Select
3767 && (unsigned)(keysym) < XK_KP_Space)
3768 #endif
3769 #ifdef XK_dead_circumflex
3770 || orig_keysym == XK_dead_circumflex
3771 #endif
3772 #ifdef XK_dead_grave
3773 || orig_keysym == XK_dead_grave
3774 #endif
3775 #ifdef XK_dead_tilde
3776 || orig_keysym == XK_dead_tilde
3777 #endif
3778 #ifdef XK_dead_diaeresis
3779 || orig_keysym == XK_dead_diaeresis
3780 #endif
3781 #ifdef XK_dead_macron
3782 || orig_keysym == XK_dead_macron
3783 #endif
3784 #ifdef XK_dead_degree
3785 || orig_keysym == XK_dead_degree
3786 #endif
3787 #ifdef XK_dead_acute
3788 || orig_keysym == XK_dead_acute
3789 #endif
3790 #ifdef XK_dead_cedilla
3791 || orig_keysym == XK_dead_cedilla
3792 #endif
3793 #ifdef XK_dead_breve
3794 || orig_keysym == XK_dead_breve
3795 #endif
3796 #ifdef XK_dead_ogonek
3797 || orig_keysym == XK_dead_ogonek
3798 #endif
3799 #ifdef XK_dead_caron
3800 || orig_keysym == XK_dead_caron
3801 #endif
3802 #ifdef XK_dead_doubleacute
3803 || orig_keysym == XK_dead_doubleacute
3804 #endif
3805 #ifdef XK_dead_abovedot
3806 || orig_keysym == XK_dead_abovedot
3807 #endif
3808 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
3809 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
3810 || x_is_vendor_fkey (orig_keysym))
3811 && ! (IsModifierKey (orig_keysym)
3812 #ifndef HAVE_X11R5
3813 #ifdef XK_Mode_switch
3814 || ((unsigned)(orig_keysym) == XK_Mode_switch)
3815 #endif
3816 #ifdef XK_Num_Lock
3817 || ((unsigned)(orig_keysym) == XK_Num_Lock)
3818 #endif
3819 #endif /* not HAVE_X11R5 */
3822 if (temp_index == sizeof temp_buffer / sizeof (short))
3823 temp_index = 0;
3824 temp_buffer[temp_index++] = keysym;
3825 bufp->kind = non_ascii_keystroke;
3826 bufp->code = keysym;
3827 XSET (bufp->frame_or_window, Lisp_Frame, f);
3828 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
3829 bufp->timestamp = event.xkey.time;
3830 bufp++;
3831 count++;
3832 numchars--;
3834 else if (numchars > nbytes)
3836 register int i;
3838 for (i = 0; i < nbytes; i++)
3840 if (temp_index == sizeof temp_buffer / sizeof (short))
3841 temp_index = 0;
3842 temp_buffer[temp_index++] = copy_buffer[i];
3843 bufp->kind = ascii_keystroke;
3844 bufp->code = copy_buffer[i];
3845 XSET (bufp->frame_or_window, Lisp_Frame, f);
3846 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
3847 bufp->timestamp = event.xkey.time;
3848 bufp++;
3851 count += nbytes;
3852 numchars -= nbytes;
3854 else
3855 abort ();
3857 else
3858 abort ();
3860 break;
3861 #else /* ! defined (HAVE_X11) */
3862 case KeyPressed:
3864 register char *where_mapping;
3866 f = x_window_to_frame (event.window);
3867 /* Ignore keys typed on icon windows. */
3868 if (f != 0 && event.window == f->display.x->icon_desc)
3869 break;
3870 where_mapping = XLookupMapping (&event, &nbytes);
3871 /* Nasty fix for arrow keys */
3872 if (!nbytes && IsCursorKey (event.detail & 0xff))
3874 switch (event.detail & 0xff)
3876 case KC_CURSOR_LEFT:
3877 where_mapping = "\002";
3878 break;
3879 case KC_CURSOR_RIGHT:
3880 where_mapping = "\006";
3881 break;
3882 case KC_CURSOR_UP:
3883 where_mapping = "\020";
3884 break;
3885 case KC_CURSOR_DOWN:
3886 where_mapping = "\016";
3887 break;
3889 nbytes = 1;
3891 if (numchars - nbytes > 0)
3893 register int i;
3895 for (i = 0; i < nbytes; i++)
3897 bufp->kind = ascii_keystroke;
3898 bufp->code = where_mapping[i];
3899 XSET (bufp->time, Lisp_Int, event.xkey.time);
3900 XSET (bufp->frame_or_window, Lisp_Frame, f);
3901 bufp++;
3903 count += nbytes;
3904 numchars -= nbytes;
3907 break;
3908 #endif /* ! defined (HAVE_X11) */
3910 #ifdef HAVE_X11
3912 /* Here's a possible interpretation of the whole
3913 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3914 FocusIn event, you have to get a FocusOut event before you
3915 relinquish the focus. If you haven't received a FocusIn event,
3916 then a mere LeaveNotify is enough to free you. */
3918 case EnterNotify:
3919 f = x_any_window_to_frame (event.xcrossing.window);
3921 if (event.xcrossing.focus) /* Entered Window */
3923 /* Avoid nasty pop/raise loops. */
3924 if (f && (!(f->auto_raise)
3925 || !(f->auto_lower)
3926 || (event.xcrossing.time - enter_timestamp) > 500))
3928 x_new_focus_frame (f);
3929 enter_timestamp = event.xcrossing.time;
3932 else if (f == x_focus_frame)
3933 x_new_focus_frame (0);
3934 #ifdef USE_X_TOOLKIT
3935 goto OTHER;
3936 #endif /* USE_X_TOOLKIT */
3937 break;
3939 case FocusIn:
3940 f = x_any_window_to_frame (event.xfocus.window);
3941 if (event.xfocus.detail != NotifyPointer)
3942 x_focus_event_frame = f;
3943 if (f)
3944 x_new_focus_frame (f);
3945 #ifdef USE_X_TOOLKIT
3946 goto OTHER;
3947 #endif /* USE_X_TOOLKIT */
3948 break;
3951 case LeaveNotify:
3952 f = x_any_window_to_frame (event.xcrossing.window);
3954 if (f == mouse_face_mouse_frame)
3955 /* If we move outside the frame,
3956 then we're certainly no longer on any text in the frame. */
3957 clear_mouse_face ();
3959 if (event.xcrossing.focus)
3961 if (! x_focus_event_frame)
3962 x_new_focus_frame (0);
3963 else
3964 x_new_focus_frame (f);
3966 else
3968 if (f == x_focus_event_frame)
3969 x_focus_event_frame = 0;
3970 if (f == x_focus_frame)
3971 x_new_focus_frame (0);
3973 #ifdef USE_X_TOOLKIT
3974 goto OTHER;
3975 #endif /* USE_X_TOOLKIT */
3976 break;
3978 case FocusOut:
3979 f = x_any_window_to_frame (event.xfocus.window);
3980 if (event.xfocus.detail != NotifyPointer
3981 && f == x_focus_event_frame)
3982 x_focus_event_frame = 0;
3983 if (f && f == x_focus_frame)
3984 x_new_focus_frame (0);
3985 #ifdef USE_X_TOOLKIT
3986 goto OTHER;
3987 #endif /* USE_X_TOOLKIT */
3988 break;
3990 #else /* ! defined (HAVE_X11) */
3992 case EnterWindow:
3993 if ((event.detail & 0xFF) == 1)
3994 break; /* Coming from our own subwindow */
3995 if (event.subwindow != 0)
3996 break; /* Entering our own subwindow. */
3999 f = x_window_to_frame (event.window);
4000 x_mouse_frame = f;
4002 x_new_focus_frame (f);
4004 break;
4006 case LeaveWindow:
4007 if ((event.detail & 0xFF) == 1)
4008 break; /* Entering our own subwindow */
4009 if (event.subwindow != 0)
4010 break; /* Leaving our own subwindow. */
4012 x_mouse_frame = 0;
4013 if (x_focus_frame == 0
4014 && x_input_frame != 0
4015 && x_input_frame == x_window_to_frame (event.window)
4016 && event.window == FRAME_X_WINDOW (x_input_frame))
4018 f = x_input_frame;
4019 x_input_frame = 0;
4020 if (f)
4021 frame_unhighlight (f);
4023 break;
4024 #endif /* ! defined (HAVE_X11) */
4026 #ifdef HAVE_X11
4027 case MotionNotify:
4029 if (x_mouse_grabbed)
4030 f = last_mouse_frame;
4031 else
4032 f = x_window_to_frame (event.xmotion.window);
4033 if (f)
4034 note_mouse_movement (f, &event.xmotion);
4035 else
4037 struct scroll_bar *bar
4038 = x_window_to_scroll_bar (event.xmotion.window);
4040 if (bar)
4041 x_scroll_bar_note_movement (bar, &event);
4043 /* If we move outside the frame,
4044 then we're certainly no longer on any text in the frame. */
4045 clear_mouse_face ();
4048 #ifdef USE_X_TOOLKIT
4049 goto OTHER;
4050 #endif /* USE_X_TOOLKIT */
4051 break;
4053 case ConfigureNotify:
4054 f = x_any_window_to_frame (event.xconfigure.window);
4055 #ifdef USE_X_TOOLKIT
4056 if (f
4057 && ! event.xconfigure.send_event
4058 && (event.xconfigure.window == XtWindow (f->display.x->widget)))
4060 Window win, child;
4061 int win_x, win_y;
4063 /* Find the position of the outside upper-left corner of
4064 the window, in the root coordinate system. Don't
4065 refer to the parent window here; we may be processing
4066 this event after the window manager has changed our
4067 parent, but before we have reached the ReparentNotify. */
4068 XTranslateCoordinates (x_current_display,
4070 /* From-window, to-window. */
4071 XtWindow (f->display.x->widget),
4072 ROOT_WINDOW,
4074 /* From-position, to-position. */
4075 -event.xconfigure.border_width,
4076 -event.xconfigure.border_width,
4077 &win_x, &win_y,
4079 /* Child of win. */
4080 &child);
4081 event.xconfigure.x = win_x;
4082 event.xconfigure.y = win_y;
4084 f->display.x->pixel_width = event.xconfigure.width;
4085 f->display.x->pixel_height = event.xconfigure.height;
4086 f->display.x->left_pos = event.xconfigure.x;
4087 f->display.x->top_pos = event.xconfigure.y;
4089 goto OTHER;
4090 #else /* not USE_X_TOOLKIT */
4091 if (f)
4093 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
4094 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
4096 /* Even if the number of character rows and columns has
4097 not changed, the font size may have changed, so we need
4098 to check the pixel dimensions as well. */
4099 if (columns != f->width
4100 || rows != f->height
4101 || event.xconfigure.width != f->display.x->pixel_width
4102 || event.xconfigure.height != f->display.x->pixel_height)
4104 change_frame_size (f, rows, columns, 0, 1);
4105 SET_FRAME_GARBAGED (f);
4108 if (! event.xconfigure.send_event)
4110 Window win, child;
4111 int win_x, win_y;
4113 /* Find the position of the outside upper-left corner of
4114 the window, in the root coordinate system. Don't
4115 refer to the parent window here; we may be processing
4116 this event after the window manager has changed our
4117 parent, but before we have reached the ReparentNotify. */
4118 XTranslateCoordinates (x_current_display,
4120 /* From-window, to-window. */
4121 f->display.x->window_desc,
4122 ROOT_WINDOW,
4124 /* From-position, to-position. */
4125 -event.xconfigure.border_width,
4126 -event.xconfigure.border_width,
4127 &win_x, &win_y,
4129 /* Child of win. */
4130 &child);
4131 event.xconfigure.x = win_x;
4132 event.xconfigure.y = win_y;
4135 f->display.x->pixel_width = event.xconfigure.width;
4136 f->display.x->pixel_height = event.xconfigure.height;
4137 f->display.x->left_pos = event.xconfigure.x;
4138 f->display.x->top_pos = event.xconfigure.y;
4140 #endif /* not USE_X_TOOLKIT */
4141 break;
4143 case ButtonPress:
4144 case ButtonRelease:
4146 /* If we decide we want to generate an event to be seen
4147 by the rest of Emacs, we put it here. */
4148 struct input_event emacs_event;
4149 emacs_event.kind = no_event;
4151 f = x_window_to_frame (event.xbutton.window);
4152 if (f)
4154 if (!x_focus_frame || (f == x_focus_frame))
4155 construct_mouse_click (&emacs_event, &event, f);
4157 else
4159 struct scroll_bar *bar =
4160 x_window_to_scroll_bar (event.xbutton.window);
4162 if (bar)
4163 x_scroll_bar_handle_click (bar, &event, &emacs_event);
4164 #ifdef USE_X_TOOLKIT
4165 else
4167 f = x_any_window_to_frame (event.xbutton.window);
4168 if (f && event.type == ButtonPress)
4169 construct_menu_click (&emacs_event,
4170 &event, f);
4172 #endif /* USE_X_TOOLKIT */
4175 if (numchars >= 1 && emacs_event.kind != no_event)
4177 bcopy (&emacs_event, bufp, sizeof (struct input_event));
4178 bufp++;
4179 count++;
4180 numchars--;
4183 #ifdef USE_X_TOOLKIT
4184 goto OTHER;
4185 #endif /* USE_X_TOOLKIT */
4187 break;
4189 #else /* ! defined (HAVE_X11) */
4190 case ButtonPressed:
4191 case ButtonReleased:
4192 f = x_window_to_frame (event.window);
4193 if (f)
4195 if (event.window == f->display.x->icon_desc)
4197 x_make_frame_visible (f);
4199 if (warp_mouse_on_deiconify)
4200 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
4201 break;
4203 if (event.window == FRAME_X_WINDOW (f))
4205 if (f->auto_raise)
4206 x_raise_frame (f);
4209 enqueue_event (&event, &x_mouse_queue);
4210 if (numchars >= 2)
4212 bufp->kind = ascii_keystroke;
4213 bufp->code = 'X' & 037; /* C-x */
4214 XSET (bufp->frame_or_window, Lisp_Frame, f);
4215 XSET (bufp->time, Lisp_Int, event.xkey.time);
4216 bufp++;
4218 bufp->kind = ascii_keystroke;
4219 bufp->code = 0; /* C-@ */
4220 XSET (bufp->frame_or_window, Lisp_Frame, f);
4221 XSET (bufp->time, Lisp_Int, event.xkey.time);
4222 bufp++;
4224 count += 2;
4225 numchars -= 2;
4227 break;
4228 #endif /* ! defined (HAVE_X11) */
4230 #ifdef HAVE_X11
4232 case CirculateNotify:
4233 break;
4234 case CirculateRequest:
4235 break;
4237 #endif /* ! defined (HAVE_X11) */
4239 case MappingNotify:
4240 /* Someone has changed the keyboard mapping - update the
4241 local cache. */
4242 switch (event.xmapping.request)
4244 case MappingModifier:
4245 x_find_modifier_meanings ();
4246 /* This is meant to fall through. */
4247 case MappingKeyboard:
4248 XRefreshKeyboardMapping (&event.xmapping);
4250 #ifdef USE_X_TOOLKIT
4251 goto OTHER;
4252 #endif /* USE_X_TOOLKIT */
4253 break;
4255 default:
4256 #ifdef USE_X_TOOLKIT
4257 OTHER:
4258 BLOCK_INPUT;
4259 XtDispatchEvent (&event);
4260 UNBLOCK_INPUT;
4261 #endif /* USE_X_TOOLKIT */
4262 break;
4266 #ifdef X_IO_BUG
4267 if (! event_found)
4268 /* On some systems, an X bug causes Emacs to get no more events
4269 when the window is destroyed. Detect that. (1994.) */
4270 XNoOp (x_current_display);
4271 #endif /* X_IO_BUG */
4273 #if 0 /* This fails for serial-line connections to the X server,
4274 because the characters arrive one by one, and a partial
4275 command makes select return but gives nothing to read.
4276 We'll have to hope that the bug that this tried to fix
4277 in 1988 has been fixed in Xlib or the X server. */
4278 #ifdef HAVE_SELECT
4279 if (expected && ! event_found)
4281 /* AOJ 880406: if select returns true but XPending doesn't, it means that
4282 there is an EOF condition; in other words, that X has died.
4283 Act as if there had been a hangup. */
4284 int fd = ConnectionNumber (x_current_display);
4285 SELECT_TYPE mask, junk1, junk2;
4286 EMACS_TIME timeout;
4288 FD_ZERO (&mask);
4289 FD_SET (fd, &mask);
4290 EMACS_SET_SECS_USECS (timeout, 0, 0);
4291 FD_ZERO (&junk1);
4292 FD_ZERO (&junk2);
4293 if (0 != select (fd + 1, &mask, &junk1, &junk2, &timeout)
4294 && !XStuffPending ())
4295 kill (getpid (), SIGHUP);
4297 #endif /* HAVE_SELECT */
4298 #endif /* 0 */
4300 #ifndef HAVE_X11
4301 if (updating_frame == 0)
4302 x_do_pending_expose ();
4303 #endif
4305 UNBLOCK_INPUT;
4306 return count;
4309 #ifndef HAVE_X11
4310 /* Read and process only Expose events
4311 until we get an ExposeCopy event; then return.
4312 This is used in insert/delete line.
4313 We assume input is already blocked. */
4315 static void
4316 x_read_exposes ()
4318 struct frame *f;
4319 XKeyPressedEvent event;
4321 while (1)
4323 /* while there are more events*/
4324 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
4325 switch (event.type)
4327 case ExposeWindow:
4328 if (event.subwindow != 0)
4329 break; /* duplicate event */
4330 f = x_window_to_frame (event.window);
4331 if (event.window == f->display.x->icon_desc)
4333 refreshicon (f);
4334 break;
4336 if (event.window == FRAME_X_WINDOW (f))
4338 expose_all_windows = 1;
4339 f->display.x->needs_exposure = 1;
4340 break;
4342 break;
4344 case ExposeRegion:
4345 if (event.subwindow != 0)
4346 break; /* duplicate event */
4347 f = x_window_to_frame (event.window);
4348 if (event.window == f->display.x->icon_desc)
4350 refreshicon (f);
4351 break;
4353 /* If window already needs full redraw, ignore this rectangle. */
4354 if (expose_all_windows && f->display.x->needs_exposure)
4355 break;
4356 /* Put the event on the queue of rectangles to redraw. */
4357 if (enqueue_event (&event, &x_expose_queue))
4358 /* If it is full, we can't record the rectangle,
4359 so redraw this entire window. */
4361 /* Say must check all windows' needs_exposure flags. */
4362 expose_all_windows = 1;
4363 f->display.x->needs_exposure = 1;
4365 break;
4367 case ExposeCopy:
4368 return;
4372 #endif /* HAVE_X11 */
4375 /* Drawing the cursor. */
4378 /* Draw a hollow box cursor. Don't change the inside of the box. */
4380 static void
4381 x_draw_box (f)
4382 struct frame *f;
4384 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
4385 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
4386 int width = FONT_WIDTH (f->display.x->font);
4387 int height = f->display.x->line_height;
4389 #ifdef HAVE_X11
4390 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
4391 f->display.x->cursor_gc,
4392 left, top, width - 1, height - 1);
4393 #else /* ! defined (HAVE_X11) */
4394 XPixSet (FRAME_X_WINDOW (f),
4395 left, top, width, 1,
4396 f->display.x->cursor_pixel);
4398 XPixSet (FRAME_X_WINDOW (f),
4399 left, top, 1, height,
4400 f->display.x->cursor_pixel);
4402 XPixSet (FRAME_X_WINDOW (f),
4403 left+width-1, top, 1, height,
4404 f->display.x->cursor_pixel);
4406 XPixSet (FRAME_X_WINDOW (f),
4407 left, top+height-1, width, 1,
4408 f->display.x->cursor_pixel);
4409 #endif /* ! defined (HAVE_X11) */
4412 /* Clear the cursor of frame F to background color,
4413 and mark the cursor as not shown.
4414 This is used when the text where the cursor is
4415 is about to be rewritten. */
4417 static void
4418 clear_cursor (f)
4419 struct frame *f;
4421 int mask;
4423 if (! FRAME_VISIBLE_P (f)
4424 || f->phys_cursor_x < 0)
4425 return;
4427 #ifdef HAVE_X11
4428 x_display_cursor (f, 0);
4429 #else /* ! defined (HAVE_X11) */
4430 XPixSet (FRAME_X_WINDOW (f),
4431 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4432 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4433 FONT_WIDTH (f->display.x->font), f->display.x->line_height,
4434 f->display.x->background_pixel);
4435 #endif /* ! defined (HAVE_X11) */
4436 f->phys_cursor_x = -1;
4439 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4440 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4441 glyph drawn. */
4443 static void
4444 x_draw_single_glyph (f, row, column, glyph, highlight)
4445 struct frame *f;
4446 int row, column;
4447 GLYPH glyph;
4448 int highlight;
4450 dumpglyphs (f,
4451 CHAR_TO_PIXEL_COL (f, column),
4452 CHAR_TO_PIXEL_ROW (f, row),
4453 &glyph, 1, highlight, 0);
4456 static void
4457 x_display_bar_cursor (f, on)
4458 struct frame *f;
4459 int on;
4461 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4463 /* This is pointless on invisible frames, and dangerous on garbaged
4464 frames; in the latter case, the frame may be in the midst of
4465 changing its size, and curs_x and curs_y may be off the frame. */
4466 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4467 return;
4469 if (! on && f->phys_cursor_x < 0)
4470 return;
4472 /* If we're not updating, then we want to use the current frame's
4473 cursor position, not our local idea of where the cursor ought to be. */
4474 if (f != updating_frame)
4476 curs_x = FRAME_CURSOR_X (f);
4477 curs_y = FRAME_CURSOR_Y (f);
4480 /* If there is anything wrong with the current cursor state, remove it. */
4481 if (f->phys_cursor_x >= 0
4482 && (!on
4483 || f->phys_cursor_x != curs_x
4484 || f->phys_cursor_y != curs_y
4485 || f->display.x->current_cursor != bar_cursor))
4487 /* Erase the cursor by redrawing the character underneath it. */
4488 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4489 f->phys_cursor_glyph,
4490 current_glyphs->highlight[f->phys_cursor_y]);
4491 f->phys_cursor_x = -1;
4494 /* If we now need a cursor in the new place or in the new form, do it so. */
4495 if (on
4496 && (f->phys_cursor_x < 0
4497 || (f->display.x->current_cursor != bar_cursor)))
4499 f->phys_cursor_glyph
4500 = ((current_glyphs->enable[curs_y]
4501 && curs_x < current_glyphs->used[curs_y])
4502 ? current_glyphs->glyphs[curs_y][curs_x]
4503 : SPACEGLYPH);
4504 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
4505 f->display.x->cursor_gc,
4506 CHAR_TO_PIXEL_COL (f, curs_x),
4507 CHAR_TO_PIXEL_ROW (f, curs_y),
4508 1, f->display.x->line_height);
4510 f->phys_cursor_x = curs_x;
4511 f->phys_cursor_y = curs_y;
4513 f->display.x->current_cursor = bar_cursor;
4516 if (updating_frame != f)
4517 XFlushQueue ();
4521 /* Turn the displayed cursor of frame F on or off according to ON.
4522 If ON is nonzero, where to put the cursor is specified
4523 by F->cursor_x and F->cursor_y. */
4525 static void
4526 x_display_box_cursor (f, on)
4527 struct frame *f;
4528 int on;
4530 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4532 /* This is pointless on invisible frames, and dangerous on garbaged
4533 frames; in the latter case, the frame may be in the midst of
4534 changing its size, and curs_x and curs_y may be off the frame. */
4535 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4536 return;
4538 /* If cursor is off and we want it off, return quickly. */
4539 if (!on && f->phys_cursor_x < 0)
4540 return;
4542 /* If we're not updating, then we want to use the current frame's
4543 cursor position, not our local idea of where the cursor ought to be. */
4544 if (f != updating_frame)
4546 curs_x = FRAME_CURSOR_X (f);
4547 curs_y = FRAME_CURSOR_Y (f);
4550 /* If cursor is currently being shown and we don't want it to be
4551 or it is in the wrong place,
4552 or we want a hollow box and it's not so, (pout!)
4553 erase it. */
4554 if (f->phys_cursor_x >= 0
4555 && (!on
4556 || f->phys_cursor_x != curs_x
4557 || f->phys_cursor_y != curs_y
4558 || (f->display.x->current_cursor != hollow_box_cursor
4559 && (f != x_highlight_frame))))
4561 /* If the font is not as tall as a whole line,
4562 we must explicitly clear the line's whole height. */
4563 if (FONT_HEIGHT (f->display.x->font) != f->display.x->line_height)
4564 XClearArea (x_current_display, FRAME_X_WINDOW (f),
4565 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4566 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4567 FONT_WIDTH (f->display.x->font),
4568 f->display.x->line_height, False);
4569 /* Erase the cursor by redrawing the character underneath it. */
4570 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4571 f->phys_cursor_glyph,
4572 current_glyphs->highlight[f->phys_cursor_y]);
4573 f->phys_cursor_x = -1;
4576 /* If we want to show a cursor,
4577 or we want a box cursor and it's not so,
4578 write it in the right place. */
4579 if (on
4580 && (f->phys_cursor_x < 0
4581 || (f->display.x->current_cursor != filled_box_cursor
4582 && f == x_highlight_frame)))
4584 f->phys_cursor_glyph
4585 = ((current_glyphs->enable[curs_y]
4586 && curs_x < current_glyphs->used[curs_y])
4587 ? current_glyphs->glyphs[curs_y][curs_x]
4588 : SPACEGLYPH);
4589 if (f != x_highlight_frame)
4591 x_draw_box (f);
4592 f->display.x->current_cursor = hollow_box_cursor;
4594 else
4596 x_draw_single_glyph (f, curs_y, curs_x,
4597 f->phys_cursor_glyph, 2);
4598 f->display.x->current_cursor = filled_box_cursor;
4601 f->phys_cursor_x = curs_x;
4602 f->phys_cursor_y = curs_y;
4605 if (updating_frame != f)
4606 XFlushQueue ();
4609 x_display_cursor (f, on)
4610 struct frame *f;
4611 int on;
4613 BLOCK_INPUT;
4615 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4616 x_display_box_cursor (f, on);
4617 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4618 x_display_bar_cursor (f, on);
4619 else
4620 /* Those are the only two we have implemented! */
4621 abort ();
4623 UNBLOCK_INPUT;
4626 /* Icons. */
4628 /* Refresh bitmap kitchen sink icon for frame F
4629 when we get an expose event for it. */
4631 refreshicon (f)
4632 struct frame *f;
4634 #ifdef HAVE_X11
4635 /* Normally, the window manager handles this function. */
4636 #else /* ! defined (HAVE_X11) */
4637 int mask;
4639 if (f->display.x->icon_bitmap_flag)
4640 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
4641 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
4642 icon_bitmap, GXcopy, AllPlanes);
4643 else
4645 extern struct frame *selected_frame;
4646 struct Lisp_String *str;
4647 unsigned char *string;
4649 string
4650 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
4652 if (f->display.x->icon_label != string)
4654 f->display.x->icon_label = string;
4655 XChangeWindow (f->display.x->icon_desc,
4656 XQueryWidth (string, icon_font_info->id) + 10,
4657 icon_font_info->height + 10);
4660 XText (f->display.x->icon_desc, 5, 5, string,
4661 str->size, icon_font_info->id,
4662 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
4664 XFlushQueue ();
4665 #endif /* ! defined (HAVE_X11) */
4668 /* Make the x-window of frame F use the gnu icon bitmap. */
4671 x_bitmap_icon (f)
4672 struct frame *f;
4674 int mask;
4675 Window icon_window;
4677 if (FRAME_X_WINDOW (f) == 0)
4678 return 1;
4680 #ifdef HAVE_X11
4681 if (! icon_bitmap)
4682 icon_bitmap =
4683 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
4684 gnu_bits, gnu_width, gnu_height);
4685 x_wm_set_icon_pixmap (f, icon_bitmap);
4686 f->display.x->icon_bitmap_flag = 1;
4687 #else /* ! defined (HAVE_X11) */
4688 if (f->display.x->icon_desc)
4690 XClearIconWindow (FRAME_X_WINDOW (f));
4691 XDestroyWindow (f->display.x->icon_desc);
4694 icon_window = XCreateWindow (f->display.x->parent_desc,
4695 0, 0, sink_width, sink_height,
4696 2, WhitePixmap, (Pixmap) NULL);
4698 if (icon_window == 0)
4699 return 1;
4701 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
4702 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
4704 f->display.x->icon_desc = icon_window;
4705 f->display.x->icon_bitmap_flag = 1;
4707 if (icon_bitmap == 0)
4708 icon_bitmap
4709 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
4710 #endif /* ! defined (HAVE_X11) */
4712 return 0;
4716 /* Make the x-window of frame F use a rectangle with text. */
4719 x_text_icon (f, icon_name)
4720 struct frame *f;
4721 char *icon_name;
4723 #ifndef HAVE_X11
4724 int mask;
4725 int width;
4726 Window icon_window;
4727 char *X_DefaultValue;
4728 Bitmap b1;
4730 #ifndef WhitePixel
4731 #define WhitePixel 1
4732 #endif /* WhitePixel */
4734 #ifndef BlackPixel
4735 #define BlackPixel 0
4736 #endif /* BlackPixel */
4737 #endif /* HAVE_X11 */
4739 if (FRAME_X_WINDOW (f) == 0)
4740 return 1;
4742 #ifdef HAVE_X11
4743 if (icon_name)
4744 f->display.x->icon_label = icon_name;
4745 else
4746 if (! f->display.x->icon_label)
4747 f->display.x->icon_label = " *emacs* ";
4749 #if 0
4750 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
4751 (char *) f->display.x->icon_label);
4752 #endif
4754 f->display.x->icon_bitmap_flag = 0;
4755 x_wm_set_icon_pixmap (f, 0);
4756 #else /* ! defined (HAVE_X11) */
4757 if (icon_font_info == 0)
4758 icon_font_info
4759 = XGetFont (XGetDefault (XDISPLAY
4760 (char *) XSTRING (Vinvocation_name)->data,
4761 "BodyFont"));
4763 if (f->display.x->icon_desc)
4765 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
4766 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4769 if (icon_name)
4770 f->display.x->icon_label = (unsigned char *) icon_name;
4771 else
4772 if (! f->display.x->icon_label)
4773 f->display.x->icon_label = XSTRING (f->name)->data;
4775 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
4776 icon_window = XCreateWindow (f->display.x->parent_desc,
4777 f->display.x->left_pos,
4778 f->display.x->top_pos,
4779 width + 10, icon_font_info->height + 10,
4780 2, BlackPixmap, WhitePixmap);
4782 if (icon_window == 0)
4783 return 1;
4785 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
4786 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
4788 f->display.x->icon_desc = icon_window;
4789 f->display.x->icon_bitmap_flag = 0;
4790 f->display.x->icon_label = 0;
4791 #endif /* ! defined (HAVE_X11) */
4793 return 0;
4796 /* Handling X errors. */
4798 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
4799 X server's connection, or an error reported via the X protocol. */
4801 static SIGTYPE
4802 x_connection_closed ()
4804 if (_Xdebug)
4805 abort ();
4807 shut_down_emacs (0, 1, Qnil);
4809 exit (70);
4812 /* An X error handler which prints an error message and then kills
4813 Emacs. This is what's normally installed as Xlib's handler for
4814 protocol errors. */
4815 static int
4816 x_error_quitter (display, error)
4817 Display *display;
4818 XErrorEvent *error;
4820 char buf[256];
4822 /* Note that there is no real way portable across R3/R4 to get the
4823 original error handler. */
4825 XGetErrorText (display, error->error_code, buf, sizeof (buf));
4826 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
4827 buf, error->request_code);
4829 #if 0
4830 /* While we're testing Emacs 19, we'll just dump core whenever we
4831 get an X error, so we can figure out why it happened. */
4832 abort ();
4833 #endif
4835 x_connection_closed ();
4838 /* A handler for X IO errors which prints an error message and then
4839 kills Emacs. This is what is always installed as Xlib's handler
4840 for I/O errors. */
4841 static int
4842 x_io_error_quitter (display)
4843 Display *display;
4845 fprintf (stderr, "Connection to X server %s lost.\n",
4846 XDisplayName (DisplayString (display)));
4848 #if 0
4849 /* While we're testing Emacs 19, we'll just dump core whenever we
4850 get an X error, so we can figure out why it happened. */
4851 abort ();
4852 #endif
4854 x_connection_closed ();
4857 /* A buffer for storing X error messages. */
4858 static char *x_caught_error_message;
4859 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4861 /* An X error handler which stores the error message in
4862 x_caught_error_message. This is what's installed when
4863 x_catch_errors is in effect. */
4864 static int
4865 x_error_catcher (display, error)
4866 Display *display;
4867 XErrorEvent *error;
4869 XGetErrorText (display, error->error_code,
4870 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
4874 /* Begin trapping X errors.
4876 After calling this function, X protocol errors no longer cause
4877 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4879 Calling x_check_errors signals an Emacs error if an X error has
4880 occurred since the last call to x_catch_errors or x_check_errors.
4882 Calling x_uncatch_errors resumes the normal error handling. */
4884 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4886 void
4887 x_catch_errors ()
4889 /* Make sure any errors from previous requests have been dealt with. */
4890 XSync (x_current_display, False);
4892 /* Set up the error buffer. */
4893 x_caught_error_message
4894 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4895 x_caught_error_message[0] = '\0';
4897 /* Install our little error handler. */
4898 XHandleError (x_error_catcher);
4901 /* If any X protocol errors have arrived since the last call to
4902 x_catch_errors or x_check_errors, signal an Emacs error using
4903 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4905 void
4906 x_check_errors (format)
4907 char *format;
4909 /* Make sure to catch any errors incurred so far. */
4910 XSync (x_current_display, False);
4912 if (x_caught_error_message[0])
4914 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
4916 sprintf (buf, format, x_caught_error_message);
4917 x_uncatch_errors ();
4918 error (buf);
4922 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4925 x_had_errors_p ()
4927 /* Make sure to catch any errors incurred so far. */
4928 XSync (x_current_display, False);
4930 return x_caught_error_message[0] != 0;
4933 /* Stop catching X protocol errors and let them make Emacs die. */
4935 void
4936 x_uncatch_errors ()
4938 xfree (x_caught_error_message);
4939 x_caught_error_message = 0;
4940 XHandleError (x_error_quitter);
4943 #if 0
4944 static unsigned int x_wire_count;
4945 x_trace_wire ()
4947 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4949 #endif /* ! 0 */
4952 /* Changing the font of the frame. */
4954 /* Set the font of the x-window specified by frame F
4955 to the font named NEWNAME. This is safe to use
4956 even before F has an actual x-window. */
4958 #ifdef HAVE_X11
4960 struct font_info
4962 XFontStruct *font;
4963 char *name;
4966 /* A table of all the fonts we have already loaded. */
4967 static struct font_info *x_font_table;
4969 /* The current capacity of x_font_table. */
4970 static int x_font_table_size;
4972 /* The number of fonts actually stored in x_font_table.
4973 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
4974 0 <= n_fonts <= x_font_table_size. */
4975 static int n_fonts;
4977 Lisp_Object
4978 x_new_font (f, fontname)
4979 struct frame *f;
4980 register char *fontname;
4982 int already_loaded;
4983 int n_matching_fonts;
4984 XFontStruct *font_info;
4985 char **font_names;
4987 /* Get a list of all the fonts that match this name. Once we
4988 have a list of matching fonts, we compare them against the fonts
4989 we already have by comparing font ids. */
4990 font_names = (char **) XListFonts (x_current_display, fontname,
4991 1024, &n_matching_fonts);
4992 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4993 find any matches; font_names == 0 is the only clue. */
4994 if (! font_names)
4995 n_matching_fonts = 0;
4997 /* Don't just give up if n_matching_fonts is 0.
4998 Apparently there's a bug on Suns: XListFontsWithInfo can
4999 fail to find a font, but XLoadQueryFont may still find it. */
5001 /* See if we've already loaded a matching font. */
5002 already_loaded = -1;
5003 if (n_matching_fonts != 0)
5005 int i, j;
5007 for (i = 0; i < n_fonts; i++)
5008 for (j = 0; j < n_matching_fonts; j++)
5009 if (!strcmp (x_font_table[i].name, font_names[j]))
5011 already_loaded = i;
5012 fontname = font_names[j];
5013 goto found_font;
5016 found_font:
5018 /* If we have, just return it from the table. */
5019 if (already_loaded >= 0)
5020 f->display.x->font = x_font_table[already_loaded].font;
5022 /* Otherwise, load the font and add it to the table. */
5023 else
5025 int i;
5026 XFontStruct *font;
5028 /* Try to find a character-cell font in the list. */
5029 #if 0
5030 /* A laudable goal, but this isn't how to do it. */
5031 for (i = 0; i < n_matching_fonts; i++)
5032 if (! font_info[i].per_char)
5033 break;
5034 #else
5035 i = 0;
5036 #endif
5038 /* See comment above. */
5039 if (n_matching_fonts != 0)
5040 fontname = font_names[i];
5042 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
5043 if (! font)
5045 /* Free the information from XListFonts. */
5046 if (n_matching_fonts)
5047 XFreeFontNames (font_names);
5048 return Qnil;
5051 /* Do we need to create the table? */
5052 if (x_font_table_size == 0)
5054 x_font_table_size = 16;
5055 x_font_table
5056 = (struct font_info *) xmalloc (x_font_table_size
5057 * sizeof (x_font_table[0]));
5059 /* Do we need to grow the table? */
5060 else if (n_fonts >= x_font_table_size)
5062 x_font_table_size *= 2;
5063 x_font_table
5064 = (struct font_info *) xrealloc (x_font_table,
5065 (x_font_table_size
5066 * sizeof (x_font_table[0])));
5069 x_font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
5070 bcopy (fontname, x_font_table[n_fonts].name, strlen (fontname) + 1);
5071 f->display.x->font = x_font_table[n_fonts++].font = font;
5074 /* Now make the frame display the given font. */
5075 if (FRAME_X_WINDOW (f) != 0)
5077 XSetFont (x_current_display, f->display.x->normal_gc,
5078 f->display.x->font->fid);
5079 XSetFont (x_current_display, f->display.x->reverse_gc,
5080 f->display.x->font->fid);
5081 XSetFont (x_current_display, f->display.x->cursor_gc,
5082 f->display.x->font->fid);
5084 frame_update_line_height (f);
5086 else
5087 /* If we are setting a new frame's font for the first time,
5088 there are no faces yet, so this font's height is the line height. */
5089 f->display.x->line_height = FONT_HEIGHT (f->display.x->font);
5092 Lisp_Object lispy_name;
5094 lispy_name = build_string (fontname);
5096 /* Free the information from XListFonts. The data
5097 we actually retain comes from XLoadQueryFont. */
5098 XFreeFontNames (font_names);
5100 return lispy_name;
5103 #else /* ! defined (HAVE_X11) */
5104 x_new_font (f, newname)
5105 struct frame *f;
5106 register char *newname;
5108 FONT_TYPE *temp;
5109 int mask;
5111 temp = XGetFont (newname);
5112 if (temp == (FONT_TYPE *) 0)
5113 return 1;
5115 if (f->display.x->font)
5116 XLoseFont (f->display.x->font);
5118 f->display.x->font = temp;
5120 if (FRAME_X_WINDOW (f) != 0)
5121 x_set_window_size (f, 0, f->width, f->height);
5123 return 0;
5125 #endif /* ! defined (HAVE_X11) */
5127 x_calc_absolute_position (f)
5128 struct frame *f;
5130 #ifdef HAVE_X11
5131 Window win, child;
5132 int win_x = 0, win_y = 0;
5134 /* Find the position of the outside upper-left corner of
5135 the inner window, with respect to the outer window. */
5136 if (f->display.x->parent_desc != ROOT_WINDOW)
5138 BLOCK_INPUT;
5139 XTranslateCoordinates (x_current_display,
5141 /* From-window, to-window. */
5142 f->display.x->window_desc,
5143 f->display.x->parent_desc,
5145 /* From-position, to-position. */
5146 0, 0, &win_x, &win_y,
5148 /* Child of win. */
5149 &child);
5150 UNBLOCK_INPUT;
5153 /* Treat negative positions as relative to the leftmost bottommost
5154 position that fits on the screen. */
5155 if (f->display.x->left_pos < 0)
5156 f->display.x->left_pos = (x_screen_width
5157 - 2 * f->display.x->border_width - win_x
5158 - PIXEL_WIDTH (f)
5159 + f->display.x->left_pos);
5161 if (f->display.x->top_pos < 0)
5162 f->display.x->top_pos = (x_screen_height
5163 - 2 * f->display.x->border_width - win_y
5164 - PIXEL_HEIGHT (f)
5165 + f->display.x->top_pos);
5167 #else /* ! defined (HAVE_X11) */
5168 WINDOWINFO_TYPE parentinfo;
5170 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
5172 if (f->display.x->left_pos < 0)
5173 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
5174 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
5176 if (f->display.x->top_pos < 0)
5177 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
5178 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
5179 #endif /* ! defined (HAVE_X11) */
5182 x_set_offset (f, xoff, yoff)
5183 struct frame *f;
5184 register int xoff, yoff;
5186 f->display.x->top_pos = yoff;
5187 f->display.x->left_pos = xoff;
5188 x_calc_absolute_position (f);
5190 BLOCK_INPUT;
5191 #ifdef USE_X_TOOLKIT
5192 XMoveWindow (XDISPLAY XtWindow (f->display.x->widget),
5193 f->display.x->left_pos, f->display.x->top_pos);
5194 #else /* not USE_X_TOOLKIT */
5195 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
5196 f->display.x->left_pos, f->display.x->top_pos);
5197 #endif /* not USE_X_TOOLKIT */
5198 #ifdef HAVE_X11
5199 x_wm_set_size_hint (f, 0, 1, xoff, yoff);
5200 #endif /* ! defined (HAVE_X11) */
5201 UNBLOCK_INPUT;
5204 /* Call this to change the size of frame F's x-window.
5205 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5206 for this size change and subsequent size changes.
5207 Otherwise we leave the window gravity unchanged. */
5209 x_set_window_size (f, change_gravity, cols, rows)
5210 struct frame *f;
5211 int change_gravity;
5212 int cols, rows;
5214 int pixelwidth, pixelheight;
5215 int mask;
5217 #ifdef USE_X_TOOLKIT
5218 BLOCK_INPUT;
5219 EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
5220 UNBLOCK_INPUT;
5222 #else /* not USE_X_TOOLKIT */
5224 BLOCK_INPUT;
5226 check_frame_size (f, &rows, &cols);
5227 f->display.x->vertical_scroll_bar_extra
5228 = (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5229 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
5230 : 0);
5231 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5232 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
5234 #ifdef HAVE_X11
5235 x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
5236 #endif /* ! defined (HAVE_X11) */
5237 XSync (x_current_display, False);
5238 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
5240 /* Now, strictly speaking, we can't be sure that this is accurate,
5241 but the window manager will get around to dealing with the size
5242 change request eventually, and we'll hear how it went when the
5243 ConfigureNotify event gets here.
5245 We could just not bother storing any of this information here,
5246 and let the ConfigureNotify event set everything up, but that
5247 might be kind of confusing to the lisp code, since size changes
5248 wouldn't be reported in the frame parameters until some random
5249 point in the future when the ConfigureNotify event arrives. */
5250 change_frame_size (f, rows, cols, 0, 0);
5251 PIXEL_WIDTH (f) = pixelwidth;
5252 PIXEL_HEIGHT (f) = pixelheight;
5254 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5255 receive in the ConfigureNotify event; if we get what we asked
5256 for, then the event won't cause the screen to become garbaged, so
5257 we have to make sure to do it here. */
5258 SET_FRAME_GARBAGED (f);
5260 XFlushQueue ();
5261 UNBLOCK_INPUT;
5262 #endif /* not USE_X_TOOLKIT */
5265 #ifndef HAVE_X11
5266 x_set_resize_hint (f)
5267 struct frame *f;
5269 XSetResizeHint (FRAME_X_WINDOW (f),
5270 2 * f->display.x->internal_border_width,
5271 2 * f->display.x->internal_border_width,
5272 FONT_WIDTH (f->display.x->font),
5273 f->display.x->line_height);
5275 #endif /* HAVE_X11 */
5277 /* Mouse warping, focus shifting, raising and lowering. */
5279 x_set_mouse_position (f, x, y)
5280 struct frame *f;
5281 int x, y;
5283 int pix_x, pix_y;
5285 #if 0 /* Let the user ask for this if he wants it. */
5286 x_raise_frame (f);
5287 #endif
5289 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
5290 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->display.x->line_height / 2;
5292 if (pix_x < 0) pix_x = 0;
5293 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5295 if (pix_y < 0) pix_y = 0;
5296 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
5298 BLOCK_INPUT;
5300 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
5301 UNBLOCK_INPUT;
5304 #ifdef HAVE_X11
5305 x_focus_on_frame (f)
5306 struct frame *f;
5308 #if 0 /* This proves to be unpleasant. */
5309 x_raise_frame (f);
5310 #endif
5311 #if 0
5312 /* I don't think that the ICCCM allows programs to do things like this
5313 without the interaction of the window manager. Whatever you end up
5314 doing with this code, do it to x_unfocus_frame too. */
5315 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
5316 RevertToPointerRoot, CurrentTime);
5317 #endif /* ! 0 */
5320 x_unfocus_frame (f)
5321 struct frame *f;
5323 #if 0
5324 /* Look at the remarks in x_focus_on_frame. */
5325 if (x_focus_frame == f)
5326 XSetInputFocus (x_current_display, PointerRoot,
5327 RevertToPointerRoot, CurrentTime);
5328 #endif /* ! 0 */
5331 #endif /* ! defined (HAVE_X11) */
5333 /* Raise frame F. */
5335 x_raise_frame (f)
5336 struct frame *f;
5338 if (f->async_visible)
5340 BLOCK_INPUT;
5341 #ifdef USE_X_TOOLKIT
5342 XRaiseWindow (XDISPLAY XtWindow (f->display.x->widget));
5343 #else /* not USE_X_TOOLKIT */
5344 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
5345 #endif /* not USE_X_TOOLKIT */
5346 XFlushQueue ();
5347 UNBLOCK_INPUT;
5351 /* Lower frame F. */
5353 x_lower_frame (f)
5354 struct frame *f;
5356 if (f->async_visible)
5358 BLOCK_INPUT;
5359 #ifdef USE_X_TOOLKIT
5360 XLowerWindow (XDISPLAY XtWindow (f->display.x->widget));
5361 #else /* not USE_X_TOOLKIT */
5362 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
5363 #endif /* not USE_X_TOOLKIT */
5364 XFlushQueue ();
5365 UNBLOCK_INPUT;
5369 static void
5370 XTframe_raise_lower (f, raise)
5371 FRAME_PTR f;
5372 int raise;
5374 if (raise)
5375 x_raise_frame (f);
5376 else
5377 x_lower_frame (f);
5381 /* Change from withdrawn state to mapped state. */
5383 x_make_frame_visible (f)
5384 struct frame *f;
5386 int mask;
5388 BLOCK_INPUT;
5390 if (! FRAME_VISIBLE_P (f))
5392 #ifdef HAVE_X11
5393 if (! EQ (Vx_no_window_manager, Qt))
5394 x_wm_set_window_state (f, NormalState);
5395 #ifdef USE_X_TOOLKIT
5396 XtPopup (f->display.x->widget, XtGrabNone);
5397 #else /* not USE_X_TOOLKIT */
5398 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
5399 #endif /* not USE_X_TOOLKIT */
5400 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5401 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
5402 #else /* ! defined (HAVE_X11) */
5403 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
5404 if (f->display.x->icon_desc != 0)
5405 XUnmapWindow (f->display.x->icon_desc);
5407 /* Handled by the MapNotify event for X11 */
5408 f->async_visible = 1;
5409 f->async_iconified = 0;
5411 /* NOTE: this may cause problems for the first frame. */
5412 XTcursor_to (0, 0);
5413 #endif /* ! defined (HAVE_X11) */
5416 XFlushQueue ();
5418 UNBLOCK_INPUT;
5421 /* Change from mapped state to withdrawn state. */
5423 x_make_frame_invisible (f)
5424 struct frame *f;
5426 int mask;
5428 /* Don't keep the highlight on an invisible frame. */
5429 if (x_highlight_frame == f)
5430 x_highlight_frame = 0;
5432 if (! f->async_visible && ! f->async_iconified)
5433 return;
5435 BLOCK_INPUT;
5437 #ifdef HAVE_X11R4
5439 #ifdef USE_X_TOOLKIT
5440 if (! XWithdrawWindow (x_current_display, XtWindow (f->display.x->widget),
5441 DefaultScreen (x_current_display)))
5442 #else /* not USE_X_TOOLKIT */
5443 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
5444 DefaultScreen (x_current_display)))
5445 #endif /* not USE_X_TOOLKIT */
5447 UNBLOCK_INPUT_RESIGNAL;
5448 error ("can't notify window manager of window withdrawal");
5451 #else /* ! defined (HAVE_X11R4) */
5452 #ifdef HAVE_X11
5454 /* Tell the window manager what we're going to do. */
5455 if (! EQ (Vx_no_window_manager, Qt))
5457 XEvent unmap;
5459 unmap.xunmap.type = UnmapNotify;
5460 #ifdef USE_X_TOOLKIT
5461 unmap.xunmap.window = XtWindow (f->display.x->widget);
5462 #else /* not USE_X_TOOLKIT */
5463 unmap.xunmap.window = FRAME_X_WINDOW (f);
5464 #endif /* not USE_X_TOOLKIT */
5465 unmap.xunmap.event = DefaultRootWindow (x_current_display);
5466 unmap.xunmap.from_configure = False;
5467 if (! XSendEvent (x_current_display,
5468 DefaultRootWindow (x_current_display),
5469 False,
5470 SubstructureRedirectMask|SubstructureNotifyMask,
5471 &unmap))
5473 UNBLOCK_INPUT_RESIGNAL;
5474 error ("can't notify window manager of withdrawal");
5478 /* Unmap the window ourselves. Cheeky! */
5479 #ifdef USE_X_TOOLKIT
5480 XUnmapWindow (x_current_display, XtWindow (f->display.x->widget));
5481 #else /* not USE_X_TOOLKIT */
5482 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
5483 #endif /* not USE_X_TOOLKIT */
5484 #else /* ! defined (HAVE_X11) */
5486 XUnmapWindow (FRAME_X_WINDOW (f));
5487 f->async_visible = 0; /* Handled by the UnMap event for X11 */
5488 if (f->display.x->icon_desc != 0)
5489 XUnmapWindow (f->display.x->icon_desc);
5491 #endif /* ! defined (HAVE_X11) */
5492 #endif /* ! defined (HAVE_X11R4) */
5494 XFlushQueue ();
5495 UNBLOCK_INPUT;
5498 /* Change window state from mapped to iconified. */
5500 x_iconify_frame (f)
5501 struct frame *f;
5503 int mask;
5504 int result;
5506 /* Don't keep the highlight on an invisible frame. */
5507 if (x_highlight_frame == f)
5508 x_highlight_frame = 0;
5510 if (f->async_iconified)
5511 return;
5513 #ifdef USE_X_TOOLKIT
5514 BLOCK_INPUT;
5515 result = XIconifyWindow (x_current_display,
5516 XtWindow (f->display.x->widget),
5517 DefaultScreen (x_current_display));
5518 UNBLOCK_INPUT;
5520 if (!result)
5521 error ("Can't notify window manager of iconification.");
5523 f->async_iconified = 1;
5525 BLOCK_INPUT;
5526 XFlushQueue ();
5527 UNBLOCK_INPUT;
5528 #else /* not USE_X_TOOLKIT */
5530 BLOCK_INPUT;
5532 #ifdef HAVE_X11
5533 /* Since we don't know which revision of X we're running, we'll use both
5534 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5536 /* X11R4: send a ClientMessage to the window manager using the
5537 WM_CHANGE_STATE type. */
5539 XEvent message;
5541 message.xclient.window = FRAME_X_WINDOW (f);
5542 message.xclient.type = ClientMessage;
5543 message.xclient.message_type = Xatom_wm_change_state;
5544 message.xclient.format = 32;
5545 message.xclient.data.l[0] = IconicState;
5547 if (! XSendEvent (x_current_display,
5548 DefaultRootWindow (x_current_display),
5549 False,
5550 SubstructureRedirectMask | SubstructureNotifyMask,
5551 &message))
5553 UNBLOCK_INPUT_RESIGNAL;
5554 error ("Can't notify window manager of iconification.");
5558 /* X11R3: set the initial_state field of the window manager hints to
5559 IconicState. */
5560 x_wm_set_window_state (f, IconicState);
5562 if (!FRAME_VISIBLE_P (f))
5564 /* If the frame was withdrawn, before, we must map it. */
5565 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
5566 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5567 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
5570 f->async_iconified = 1;
5571 #else /* ! defined (HAVE_X11) */
5572 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
5574 f->async_visible = 0; /* Handled in the UnMap event for X11. */
5575 if (f->display.x->icon_desc != 0)
5577 XMapWindow (XDISPLAY f->display.x->icon_desc);
5578 refreshicon (f);
5580 #endif /* ! defined (HAVE_X11) */
5582 XFlushQueue ();
5583 UNBLOCK_INPUT;
5584 #endif /* not USE_X_TOOLKIT */
5587 /* Destroy the X window of frame F. */
5589 x_destroy_window (f)
5590 struct frame *f;
5592 BLOCK_INPUT;
5594 if (f->display.x->icon_desc != 0)
5595 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
5596 XDestroyWindow (XDISPLAY f->display.x->window_desc);
5597 #ifdef USE_X_TOOLKIT
5598 XtDestroyWidget (f->display.x->widget);
5599 free_frame_menubar (f);
5600 #endif /* USE_X_TOOLKIT */
5602 free_frame_faces (f);
5603 XFlushQueue ();
5605 xfree (f->display.x);
5606 f->display.x = 0;
5607 if (f == x_focus_frame)
5608 x_focus_frame = 0;
5609 if (f == x_highlight_frame)
5610 x_highlight_frame = 0;
5612 UNBLOCK_INPUT;
5615 /* Manage event queues for X10. */
5617 #ifndef HAVE_X11
5619 /* Manage event queues.
5621 This code is only used by the X10 support.
5623 We cannot leave events in the X queue and get them when we are ready
5624 because X does not provide a subroutine to get only a certain kind
5625 of event but not block if there are no queued events of that kind.
5627 Therefore, we must examine events as they come in and copy events
5628 of certain kinds into our private queues.
5630 All ExposeRegion events are put in x_expose_queue.
5631 All ButtonPress and ButtonRelease events are put in x_mouse_queue. */
5634 /* Write the event *P_XREP into the event queue *QUEUE.
5635 If the queue is full, do nothing, but return nonzero. */
5638 enqueue_event (p_xrep, queue)
5639 register XEvent *p_xrep;
5640 register struct event_queue *queue;
5642 int newindex = queue->windex + 1;
5643 if (newindex == EVENT_BUFFER_SIZE)
5644 newindex = 0;
5645 if (newindex == queue->rindex)
5646 return -1;
5647 queue->xrep[queue->windex] = *p_xrep;
5648 queue->windex = newindex;
5649 return 0;
5652 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
5653 If *QUEUE is empty, do nothing and return 0. */
5656 dequeue_event (p_xrep, queue)
5657 register XEvent *p_xrep;
5658 register struct event_queue *queue;
5660 if (queue->windex == queue->rindex)
5661 return 0;
5662 *p_xrep = queue->xrep[queue->rindex++];
5663 if (queue->rindex == EVENT_BUFFER_SIZE)
5664 queue->rindex = 0;
5665 return 1;
5668 /* Return the number of events buffered in *QUEUE. */
5671 queue_event_count (queue)
5672 register struct event_queue *queue;
5674 int tem = queue->windex - queue->rindex;
5675 if (tem >= 0)
5676 return tem;
5677 return EVENT_BUFFER_SIZE + tem;
5680 /* Return nonzero if mouse input is pending. */
5683 mouse_event_pending_p ()
5685 return queue_event_count (&x_mouse_queue);
5687 #endif /* HAVE_X11 */
5689 /* Setting window manager hints. */
5691 #ifdef HAVE_X11
5693 /* Record the gravity used previously, in case CHANGE_GRAVITY is 0. */
5694 static int previous_gravity;
5696 /* SPEC_X and SPEC_Y are the specified positions.
5697 We look only at their sign, to decide the gravity.
5698 If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
5699 and leave the gravity unchanged. */
5701 x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
5702 struct frame *f;
5703 long prompting;
5704 int change_gravity;
5705 int spec_x, spec_y;
5707 XSizeHints size_hints;
5709 #ifdef USE_X_TOOLKIT
5710 Arg al[2];
5711 int ac = 0;
5712 Dimension widget_width, widget_height;
5713 Window window = XtWindow (f->display.x->widget);
5714 #else /* not USE_X_TOOLKIT */
5715 Window window = FRAME_X_WINDOW (f);
5716 #endif /* not USE_X_TOOLKIT */
5718 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5720 flexlines = f->height;
5722 size_hints.x = f->display.x->left_pos;
5723 size_hints.y = f->display.x->top_pos;
5724 #ifdef USE_X_TOOLKIT
5725 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5726 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5727 XtGetValues (f->display.x->column_widget, al, ac);
5728 size_hints.height = widget_height;
5729 size_hints.width = widget_width;
5730 #else /* not USE_X_TOOLKIT */
5731 size_hints.height = PIXEL_HEIGHT (f);
5732 size_hints.width = PIXEL_WIDTH (f);
5733 #endif /* not USE_X_TOOLKIT */
5734 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
5735 size_hints.height_inc = f->display.x->line_height;
5736 #if 0
5737 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
5738 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
5739 #endif
5741 int base_width, base_height;
5743 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5744 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
5747 int min_rows = 0, min_cols = 0;
5748 check_frame_size (f, &min_rows, &min_cols);
5750 /* The window manager uses the base width hints to calculate the
5751 current number of rows and columns in the frame while
5752 resizing; min_width and min_height aren't useful for this
5753 purpose, since they might not give the dimensions for a
5754 zero-row, zero-column frame.
5756 We use the base_width and base_height members if we have
5757 them; otherwise, we set the min_width and min_height members
5758 to the size for a zero x zero frame. */
5760 #ifdef HAVE_X11R4
5761 size_hints.flags |= PBaseSize;
5762 size_hints.base_width = base_width;
5763 size_hints.base_height = base_height;
5764 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5765 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5766 #else
5767 size_hints.min_width = base_width;
5768 size_hints.min_height = base_height;
5769 #endif
5774 if (prompting)
5775 size_hints.flags |= prompting;
5776 else
5778 XSizeHints hints; /* Sometimes I hate X Windows... */
5780 if (XGetNormalHints (x_current_display, window, &hints) == 0)
5781 hints.flags = 0;
5782 if (hints.flags & PSize)
5783 size_hints.flags |= PSize;
5784 if (hints.flags & PPosition)
5785 size_hints.flags |= PPosition;
5786 if (hints.flags & USPosition)
5787 size_hints.flags |= USPosition;
5788 if (hints.flags & USSize)
5789 size_hints.flags |= USSize;
5791 #if defined (PWinGravity)
5792 if (change_gravity)
5794 switch (((spec_x < 0) << 1) + (spec_y < 0))
5796 case 0:
5797 size_hints.win_gravity = NorthWestGravity;
5798 break;
5799 case 1:
5800 size_hints.win_gravity = NorthEastGravity;
5801 break;
5802 case 2:
5803 size_hints.win_gravity = SouthWestGravity;
5804 break;
5805 case 3:
5806 size_hints.win_gravity = SouthEastGravity;
5807 break;
5809 previous_gravity = size_hints.win_gravity;
5811 else
5812 size_hints.win_gravity = previous_gravity;
5814 size_hints.flags |= PWinGravity;
5815 #endif /* PWinGravity */
5817 #ifdef HAVE_X11R4
5818 XSetWMNormalHints (x_current_display, window, &size_hints);
5819 #else
5820 XSetNormalHints (x_current_display, window, &size_hints);
5821 #endif
5824 /* Used for IconicState or NormalState */
5825 x_wm_set_window_state (f, state)
5826 struct frame *f;
5827 int state;
5829 #ifdef USE_X_TOOLKIT
5830 Window window = XtWindow (f->display.x->widget);
5831 #else /* not USE_X_TOOLKIT */
5832 Window window = FRAME_X_WINDOW (f);
5833 #endif /* not USE_X_TOOLKIT */
5835 f->display.x->wm_hints.flags |= StateHint;
5836 f->display.x->wm_hints.initial_state = state;
5838 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
5841 x_wm_set_icon_pixmap (f, icon_pixmap)
5842 struct frame *f;
5843 Pixmap icon_pixmap;
5845 Window window = FRAME_X_WINDOW (f);
5847 if (icon_pixmap)
5849 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
5850 f->display.x->wm_hints.flags |= IconPixmapHint;
5852 else
5853 f->display.x->wm_hints.flags &= ~IconPixmapHint;
5855 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
5858 x_wm_set_icon_position (f, icon_x, icon_y)
5859 struct frame *f;
5860 int icon_x, icon_y;
5862 Window window = FRAME_X_WINDOW (f);
5864 f->display.x->wm_hints.flags |= IconPositionHint;
5865 f->display.x->wm_hints.icon_x = icon_x;
5866 f->display.x->wm_hints.icon_y = icon_y;
5868 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
5872 /* Initialization. */
5874 #ifdef USE_X_TOOLKIT
5875 static XrmOptionDescRec emacs_options[] = {
5876 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5877 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5879 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5880 XrmoptionSepArg, NULL},
5881 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5883 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5884 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5885 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5886 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5887 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5888 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5889 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5891 #endif /* USE_X_TOOLKIT */
5893 void
5894 x_term_init (display_name)
5895 char *display_name;
5897 Lisp_Object frame;
5898 char *defaultvalue;
5899 int argc = 0;
5900 char** argv = 0;
5901 #ifndef F_SETOWN_BUG
5902 #ifdef F_SETOWN
5903 extern int old_fcntl_owner;
5904 #endif /* ! defined (F_SETOWN) */
5905 #endif /* F_SETOWN_BUG */
5907 x_focus_frame = x_highlight_frame = 0;
5909 #ifdef USE_X_TOOLKIT
5910 argv = (char **) XtMalloc (3 * sizeof (char *));
5911 argv [0] = "";
5912 argv [1] = "-display";
5913 argv [2] = display_name;
5914 argc = 3;
5915 Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
5916 emacs_options, XtNumber (emacs_options),
5917 &argc, argv,
5918 NULL, NULL, 0);
5919 XtFree (argv);
5920 x_current_display = XtDisplay (Xt_app_shell);
5922 #else /* not USE_X_TOOLKIT */
5923 x_current_display = XOpenDisplay (display_name);
5924 #endif /* not USE_X_TOOLKIT */
5925 if (x_current_display == 0)
5926 fatal ("X server %s not responding.\n\
5927 Check the DISPLAY environment variable or use \"-d\"\n",
5928 display_name);
5930 #ifdef HAVE_X11
5932 #if 0
5933 XSetAfterFunction (x_current_display, x_trace_wire);
5934 #endif /* ! 0 */
5935 hostname = get_system_name ();
5936 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
5937 + strlen (hostname)
5938 + 2);
5939 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
5942 /* Figure out which modifier bits mean what. */
5943 x_find_modifier_meanings ();
5945 /* Get the scroll bar cursor. */
5946 x_vertical_scroll_bar_cursor
5947 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
5949 #if 0
5950 /* Watch for PropertyNotify events on the root window; we use them
5951 to figure out when to invalidate our cache of the cut buffers. */
5952 x_watch_cut_buffer_cache ();
5953 #endif
5955 if (ConnectionNumber (x_current_display) != 0)
5956 change_keyboard_wait_descriptor (ConnectionNumber (x_current_display));
5957 change_input_fd (ConnectionNumber (x_current_display));
5959 #endif /* ! defined (HAVE_X11) */
5961 #ifndef F_SETOWN_BUG
5962 #ifdef F_SETOWN
5963 old_fcntl_owner = fcntl (ConnectionNumber (x_current_display), F_GETOWN, 0);
5964 #ifdef F_SETOWN_SOCK_NEG
5965 /* stdin is a socket here */
5966 fcntl (ConnectionNumber (x_current_display), F_SETOWN, -getpid ());
5967 #else /* ! defined (F_SETOWN_SOCK_NEG) */
5968 fcntl (ConnectionNumber (x_current_display), F_SETOWN, getpid ());
5969 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
5970 #endif /* ! defined (F_SETOWN) */
5971 #endif /* F_SETOWN_BUG */
5973 #ifdef SIGIO
5974 init_sigio ();
5975 #endif /* ! defined (SIGIO) */
5977 expose_all_windows = 0;
5979 clear_frame_hook = XTclear_frame;
5980 clear_end_of_line_hook = XTclear_end_of_line;
5981 ins_del_lines_hook = XTins_del_lines;
5982 change_line_highlight_hook = XTchange_line_highlight;
5983 insert_glyphs_hook = XTinsert_glyphs;
5984 write_glyphs_hook = XTwrite_glyphs;
5985 delete_glyphs_hook = XTdelete_glyphs;
5986 ring_bell_hook = XTring_bell;
5987 reset_terminal_modes_hook = XTreset_terminal_modes;
5988 set_terminal_modes_hook = XTset_terminal_modes;
5989 update_begin_hook = XTupdate_begin;
5990 update_end_hook = XTupdate_end;
5991 set_terminal_window_hook = XTset_terminal_window;
5992 read_socket_hook = XTread_socket;
5993 frame_up_to_date_hook = XTframe_up_to_date;
5994 cursor_to_hook = XTcursor_to;
5995 reassert_line_highlight_hook = XTreassert_line_highlight;
5996 mouse_position_hook = XTmouse_position;
5997 frame_rehighlight_hook = XTframe_rehighlight;
5998 frame_raise_lower_hook = XTframe_raise_lower;
5999 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6000 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6001 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6002 judge_scroll_bars_hook = XTjudge_scroll_bars;
6004 scroll_region_ok = 1; /* we'll scroll partial frames */
6005 char_ins_del_ok = 0; /* just as fast to write the line */
6006 line_ins_del_ok = 1; /* we'll just blt 'em */
6007 fast_clear_end_of_line = 1; /* X does this well */
6008 memory_below_frame = 0; /* we don't remember what scrolls
6009 off the bottom */
6010 baud_rate = 19200;
6012 /* Try to use interrupt input; if we can't, then start polling. */
6013 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6015 /* Note that there is no real way portable across R3/R4 to get the
6016 original error handler. */
6017 XHandleError (x_error_quitter);
6018 XHandleIOError (x_io_error_quitter);
6020 /* Disable Window Change signals; they are handled by X events. */
6021 #ifdef SIGWINCH
6022 signal (SIGWINCH, SIG_DFL);
6023 #endif /* ! defined (SIGWINCH) */
6025 signal (SIGPIPE, x_connection_closed);
6028 void
6029 syms_of_xterm ()
6031 staticpro (&last_mouse_scroll_bar);
6032 last_mouse_scroll_bar = Qnil;
6033 staticpro (&mouse_face_window);
6034 mouse_face_window = Qnil;
6036 #endif /* ! defined (HAVE_X11) */
6037 #endif /* ! defined (HAVE_X_WINDOWS) */