(auto-mode-alist): added pairs for .ms, .man, .mk, [Mm]akefile, .lex.
[emacs.git] / src / xterm.c
blobf1dc6a24d12b7a0f09e30133ef6176e9747fd8ff
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992, 1993 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 /* Serious problems:
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
28 #define NEW_SELECTIONS
30 #include "config.h"
32 #ifdef HAVE_X_WINDOWS
34 #include "lisp.h"
36 /* On 4.3 these lose if they come after xterm.h. */
37 #include <stdio.h>
38 #include <signal.h>
40 /* This may include sys/types.h, and that somehow loses
41 if this is not done before the other system files. */
42 #include "xterm.h"
43 #include <X11/cursorfont.h>
45 #ifndef USG
46 /* Load sys/types.h if not already loaded.
47 In some systems loading it twice is suicidal. */
48 #ifndef makedev
49 #include <sys/types.h>
50 #endif /* makedev */
51 #endif /* USG */
53 #ifdef BSD
54 #include <sys/ioctl.h>
55 #include <strings.h>
56 #else /* ! defined (BSD) */
57 #ifndef VMS
58 #include <sys/termio.h>
59 #include <string.h>
60 #endif
61 #endif /* ! defined (BSD) */
63 /* Allow m- file to inhibit use of FIONREAD. */
64 #ifdef BROKEN_FIONREAD
65 #undef FIONREAD
66 #endif /* ! defined (BROKEN_FIONREAD) */
68 /* We are unable to use interrupts if FIONREAD is not available,
69 so flush SIGIO so we won't try. */
70 #ifndef FIONREAD
71 #ifdef SIGIO
72 #undef SIGIO
73 #endif /* ! defined (SIGIO) */
74 #endif /* FIONREAD */
76 #include "systime.h"
78 #include <fcntl.h>
79 #include <ctype.h>
80 #include <errno.h>
81 #include <setjmp.h>
82 #include <sys/stat.h>
83 #include <sys/param.h>
85 #include "dispextern.h"
86 #include "termhooks.h"
87 #include "termopts.h"
88 #include "termchar.h"
89 #if 0
90 #include "sink.h"
91 #include "sinkmask.h"
92 #endif /* ! 0 */
93 #include "gnu.h"
94 #include "frame.h"
95 #include "disptab.h"
96 #include "buffer.h"
97 #include "window.h"
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 /* For sending Meta-characters. Do we need this? */
107 #define METABIT 0200
109 #define min(a,b) ((a)<(b) ? (a) : (b))
110 #define max(a,b) ((a)>(b) ? (a) : (b))
112 /* Nonzero means we must reprint all windows
113 because 1) we received an ExposeWindow event
114 or 2) we received too many ExposeRegion events to record.
116 This is never needed under X11. */
117 static int expose_all_windows;
119 /* Nonzero means we must reprint all icon windows. */
121 static int expose_all_icons;
123 #ifndef HAVE_X11
124 /* ExposeRegion events, when received, are copied into this queue
125 for later processing. */
127 static struct event_queue x_expose_queue;
129 /* ButtonPressed and ButtonReleased events, when received,
130 are copied into this queue for later processing. */
132 struct event_queue x_mouse_queue;
133 #endif /* HAVE_X11 */
135 /* Nonzero after BLOCK_INPUT; prevents input events from being
136 processed until later. */
138 int x_input_blocked;
140 #if defined (SIGIO) && defined (FIONREAD)
141 int BLOCK_INPUT_mask;
142 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
144 /* Nonzero if input events came in while x_input_blocked was nonzero.
145 UNBLOCK_INPUT checks for this. */
147 int x_pending_input;
149 /* The id of a bitmap used for icon windows.
150 One such map is shared by all Emacs icon windows.
151 This is zero if we have not yet had a need to create the bitmap. */
153 static Bitmap icon_bitmap;
155 /* Font used for text icons. */
157 static FONT_TYPE *icon_font_info;
159 /* Stuff for dealing with the main icon title. */
161 extern Lisp_Object Vcommand_line_args;
162 char *hostname, *x_id_name;
164 /* This is the X connection that we are using. */
166 Display *x_current_display;
168 /* The cursor to use for vertical scroll bars on x_current_display. */
169 static Cursor x_vertical_scroll_bar_cursor;
171 /* Frame being updated by update_frame. */
172 /* This is set by XTupdate_begin and looked at by all the
173 XT functions. It is zero while not inside an update.
174 In that case, the XT functions assume that `selected_frame'
175 is the frame to apply to. */
177 static struct frame *updating_frame;
179 /* The frame (if any) which has the X window that has keyboard focus.
180 Zero if none. This is examined by Ffocus_frame in frame.c. Note
181 that a mere EnterNotify event can set this; if you need to know the
182 last frame specified in a FocusIn or FocusOut event, use
183 x_focus_event_frame. */
184 struct frame *x_focus_frame;
186 /* The last frame mentioned in a FocusIn or FocusOut event. This is
187 separate from x_focus_frame, because whether or not LeaveNotify
188 events cause us to lose focus depends on whether or not we have
189 received a FocusIn event for it. */
190 struct frame *x_focus_event_frame;
192 /* The frame which currently has the visual highlight, and should get
193 keyboard input (other sorts of input have the frame encoded in the
194 event). It points to the X focus frame's selected window's
195 frame. It differs from x_focus_frame when we're using a global
196 minibuffer. */
197 static struct frame *x_highlight_frame;
199 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
200 mouse is moved to inside of frame when frame is de-iconified. */
202 static int warp_mouse_on_deiconify;
204 /* During an update, maximum vpos for ins/del line operations to affect. */
206 static int flexlines;
208 /* During an update, nonzero if chars output now should be highlighted. */
210 static int highlight;
212 /* Nominal cursor position -- where to draw output.
213 During an update, these are different from the cursor-box position. */
215 static int curs_x;
216 static int curs_y;
218 #ifdef HAVE_X11
219 /* `t' if a mouse button is depressed. */
221 extern Lisp_Object Vmouse_depressed;
223 /* Tells if a window manager is present or not. */
225 extern Lisp_Object Vx_no_window_manager;
227 /* Timestamp that we requested selection data was made. */
228 extern Time requestor_time;
230 /* ID of the window requesting selection data. */
231 extern Window requestor_window;
233 /* Nonzero enables some debugging for the X interface code. */
234 extern int _Xdebug;
236 #else /* ! defined (HAVE_X11) */
238 /* Bit patterns for the mouse cursor. */
240 short MouseCursor[] = {
241 0x0000, 0x0008, 0x0018, 0x0038,
242 0x0078, 0x00f8, 0x01f8, 0x03f8,
243 0x07f8, 0x00f8, 0x00d8, 0x0188,
244 0x0180, 0x0300, 0x0300, 0x0000};
246 short MouseMask[] = {
247 0x000c, 0x001c, 0x003c, 0x007c,
248 0x00fc, 0x01fc, 0x03fc, 0x07fc,
249 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
250 0x03cc, 0x0780, 0x0780, 0x0300};
252 static short grey_bits[] = {
253 0x0005, 0x000a, 0x0005, 0x000a};
255 static Pixmap GreyPixmap = 0;
256 #endif /* ! defined (HAVE_X11) */
258 /* From time to time we get info on an Emacs window, here. */
260 static WINDOWINFO_TYPE windowinfo;
262 extern int errno;
264 /* See keyboard.c. */
265 extern int extra_keyboard_modifiers;
267 extern Display *XOpenDisplay ();
268 extern Window XCreateWindow ();
270 extern Cursor XCreateCursor ();
271 extern FONT_TYPE *XOpenFont ();
273 static void flashback ();
275 #ifndef HAVE_X11
276 static void dumpqueue ();
277 #endif /* HAVE_X11 */
279 void dumpborder ();
280 static int XTcursor_to ();
281 static int XTclear_end_of_line ();
284 /* Starting and ending updates.
286 These hooks are called by update_frame at the beginning and end
287 of a frame update. We record in `updating_frame' the identity
288 of the frame being updated, so that the XT... functions do not
289 need to take a frame as argument. Most of the XT... functions
290 should never be called except during an update, the only exceptions
291 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
293 extern int mouse_track_top, mouse_track_left, mouse_track_width;
295 static
296 XTupdate_begin (f)
297 struct frame *f;
299 int mask;
301 if (f == 0)
302 abort ();
304 updating_frame = f;
305 flexlines = f->height;
306 highlight = 0;
308 BLOCK_INPUT;
309 #ifndef HAVE_X11
310 dumpqueue ();
311 #endif /* HAVE_X11 */
312 UNBLOCK_INPUT;
315 #ifndef HAVE_X11
316 static void x_do_pending_expose ();
317 #endif
319 static
320 XTupdate_end (f)
321 struct frame *f;
323 int mask;
325 if (updating_frame == 0
326 || updating_frame != f)
327 abort ();
329 BLOCK_INPUT;
330 #ifndef HAVE_X11
331 dumpqueue ();
332 x_do_pending_expose ();
333 #endif /* HAVE_X11 */
335 x_display_cursor (f, 1);
337 updating_frame = 0;
338 XFlushQueue ();
339 UNBLOCK_INPUT;
342 /* External interface to control of standout mode.
343 Call this when about to modify line at position VPOS
344 and not change whether it is highlighted. */
346 XTreassert_line_highlight (new, vpos)
347 int new, vpos;
349 highlight = new;
352 /* Call this when about to modify line at position VPOS
353 and change whether it is highlighted. */
355 static
356 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
357 int new_highlight, vpos, first_unused_hpos;
359 highlight = new_highlight;
360 XTcursor_to (vpos, 0);
361 XTclear_end_of_line (updating_frame->width);
364 /* This is used when starting Emacs and when restarting after suspend.
365 When starting Emacs, no X window is mapped. And nothing must be done
366 to Emacs's own window if it is suspended (though that rarely happens). */
368 static
369 XTset_terminal_modes ()
373 /* This is called when exiting or suspending Emacs.
374 Exiting will make the X-windows go away, and suspending
375 requires no action. */
377 static
378 XTreset_terminal_modes ()
380 /* XTclear_frame (); */
383 /* Set the nominal cursor position of the frame.
384 This is where display update commands will take effect.
385 This does not affect the place where the cursor-box is displayed. */
387 static int
388 XTcursor_to (row, col)
389 register int row, col;
391 int mask;
392 int orow = row;
394 curs_x = col;
395 curs_y = row;
397 if (updating_frame == 0)
399 BLOCK_INPUT;
400 x_display_cursor (selected_frame, 1);
401 XFlushQueue ();
402 UNBLOCK_INPUT;
406 /* Display a sequence of N glyphs found at GP.
407 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
408 HL is 1 if this text is highlighted, 2 if the cursor is on it.
410 FONT is the default font to use (for glyphs whose font-code is 0). */
412 static void
413 dumpglyphs (f, left, top, gp, n, hl, font)
414 struct frame *f;
415 int left, top;
416 register GLYPH *gp; /* Points to first GLYPH. */
417 register int n; /* Number of glyphs to display. */
418 int hl;
419 FONT_TYPE *font;
421 register int len;
422 Window window = FRAME_X_WINDOW (f);
423 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
424 : (hl ? f->display.x->reverse_gc
425 : f->display.x->normal_gc));
427 if (sizeof (GLYPH) == sizeof (XChar2b))
428 XDrawImageString16 (x_current_display, window, drawing_gc,
429 left, top + FONT_BASE (font), (XChar2b *) gp, n);
430 else if (sizeof (GLYPH) == sizeof (unsigned char))
431 XDrawImageString (x_current_display, window, drawing_gc,
432 left, top + FONT_BASE (font), (char *) gp, n);
433 else
434 /* What size of glyph ARE you using? And does X have a function to
435 draw them? */
436 abort ();
439 #if 0
440 static void
441 dumpglyphs (f, left, top, gp, n, hl, font)
442 struct frame *f;
443 int left, top;
444 register GLYPH *gp; /* Points to first GLYPH. */
445 register int n; /* Number of glyphs to display. */
446 int hl;
447 FONT_TYPE *font;
449 char buf[f->width]; /* Holds characters to be displayed. */
450 register char *cp; /* Steps through buf[]. */
451 register int tlen = GLYPH_TABLE_LENGTH;
452 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
453 Window window = FRAME_X_WINDOW (f);
454 int cursor_pixel = f->display.x->cursor_pixel;
455 int fg_pixel = f->display.x->foreground_pixel;
456 int bg_pixel = f->display.x->background_pixel;
457 int intborder = f->display.x->internal_border_width;
459 while (n)
461 /* Get the face-code of the next GLYPH. */
462 int cf, len;
463 int g = *gp;
465 while (GLYPH_ALIAS_P (tbase, tlen, g))
466 g = GLYPH_ALIAS (tbase, g);
468 cf = g >> 8;
470 /* Find the run of consecutive glyphs with the same face-code.
471 Extract their character codes into BUF. */
472 cp = buf;
473 while (n > 0)
475 g = *gp;
476 while (GLYPH_ALIAS_P (tbase, tlen, g))
477 g = GLYPH_ALIAS (tbase, g);
478 if ((g >> 8) != cf)
479 break;
481 *cp++ = 0377 & g;
482 --n;
483 ++gp;
486 /* LEN gets the length of the run. */
487 len = cp - buf;
489 /* Now output this run of chars, with the font and pixel values
490 determined by the face code CF. */
491 if (cf == 0)
493 #ifdef HAVE_X11
494 GC GC_cursor = f->display.x->cursor_gc;
495 GC GC_reverse = f->display.x->reverse_gc;
496 GC GC_normal = f->display.x->normal_gc;
498 XDrawImageString (x_current_display, window,
499 (hl == 2
500 ? GC_cursor
501 : (hl ? GC_reverse : GC_normal)),
502 left, top + FONT_BASE (font), buf, len);
503 #else /* ! defined (HAVE_X11) */
504 XText (window, left, top,
505 buf,
506 len,
507 font->id,
508 (hl == 2
509 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
510 : hl ? bg_pixel : fg_pixel),
511 (hl == 2 ? cursor_pixel
512 : hl ? fg_pixel : bg_pixel));
513 #endif /* ! defined (HAVE_X11) */
515 else
517 #ifdef HAVE_X11
518 if (FACE_IS_FONT (cf))
519 XDrawImageString (x_current_display, FRAME_X_WINDOW (f),
520 FACE_GC (cf),
521 left, top + FONT_BASE (FACE_FONT (cf)),
522 buf, len);
523 else if (FACE_IS_IMAGE (cf))
524 XCopyPlane (x_current_display, FACE_IMAGE (cf),
525 FRAME_X_WINDOW (f),
526 f->display.x->normal_gc,
527 0, 0,
528 FACE_IMAGE_WIDTH (cf),
529 FACE_IMAGE_HEIGHT (cf), left, top);
530 else
531 abort ();
532 #else /* ! defined (HAVE_X11) */
533 register struct face *fp = x_face_table[cf];
535 XText (window, left, top,
536 buf,
537 len,
538 fp->font->id,
539 (hl == 2
540 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
541 : hl ? fp->bg : fp->fg),
542 (hl == 2 ? cursor_pixel
543 : hl ? fp->fg : fp->bg));
544 #endif /* ! defined (HAVE_X11) */
546 left += len * FONT_WIDTH (font);
549 #endif /* ! 0 */
551 /* Output some text at the nominal frame cursor position.
552 Advance the cursor over the text.
553 Output LEN glyphs at START.
555 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
556 controls the pixel values used for foreground and background. */
558 static
559 XTwrite_glyphs (start, len)
560 register GLYPH *start;
561 int len;
563 register int temp_length;
564 int mask;
565 struct frame *f;
567 BLOCK_INPUT;
569 f = updating_frame;
570 if (f == 0)
572 f = selected_frame;
573 /* If not within an update,
574 output at the frame's visible cursor. */
575 curs_x = f->cursor_x;
576 curs_y = f->cursor_y;
579 dumpglyphs (f,
580 CHAR_TO_PIXEL_COL (f, curs_x),
581 CHAR_TO_PIXEL_ROW (f, curs_y),
582 start, len, highlight, f->display.x->font);
584 /* If we drew on top of the cursor, note that it is turned off. */
585 if (curs_y == f->phys_cursor_y
586 && curs_x <= f->phys_cursor_x
587 && curs_x + len > f->phys_cursor_x)
588 f->phys_cursor_x = -1;
590 if (updating_frame == 0)
592 f->cursor_x += len;
593 x_display_cursor (f, 1);
594 f->cursor_x -= len;
596 else
597 curs_x += len;
599 UNBLOCK_INPUT;
602 /* Clear to the end of the line.
603 Erase the current text line from the nominal cursor position (inclusive)
604 to column FIRST_UNUSED (exclusive). The idea is that everything
605 from FIRST_UNUSED onward is already erased. */
607 static int
608 XTclear_end_of_line (first_unused)
609 register int first_unused;
611 struct frame *f = updating_frame;
612 int mask;
614 if (f == 0)
615 abort ();
617 if (curs_y < 0 || curs_y >= f->height)
618 return;
619 if (first_unused <= 0)
620 return;
622 if (first_unused >= f->width)
623 first_unused = f->width;
625 BLOCK_INPUT;
627 /* Notice if the cursor will be cleared by this operation. */
628 if (curs_y == f->phys_cursor_y
629 && curs_x <= f->phys_cursor_x
630 && f->phys_cursor_x < first_unused)
631 f->phys_cursor_x = -1;
633 #ifdef HAVE_X11
634 XClearArea (x_current_display, FRAME_X_WINDOW (f),
635 CHAR_TO_PIXEL_COL (f, curs_x),
636 CHAR_TO_PIXEL_ROW (f, curs_y),
637 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
638 FONT_HEIGHT (f->display.x->font), False);
640 #else /* ! defined (HAVE_X11) */
641 XPixSet (FRAME_X_WINDOW (f),
642 CHAR_TO_PIXEL_COL (f, curs_x),
643 CHAR_TO_PIXEL_ROW (f, curs_y),
644 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
645 FONT_HEIGHT (f->display.x->font),
646 f->display.x->background_pixel);
647 #endif /* ! defined (HAVE_X11) */
649 UNBLOCK_INPUT;
652 static
653 XTclear_frame ()
655 int mask;
656 struct frame *f = updating_frame;
658 if (f == 0)
659 f = selected_frame;
661 f->phys_cursor_x = -1; /* Cursor not visible. */
662 curs_x = 0; /* Nominal cursor position is top left. */
663 curs_y = 0;
665 BLOCK_INPUT;
667 XClear (FRAME_X_WINDOW (f));
669 /* We have to clear the scroll bars, too. If we have changed
670 colors or something like that, then they should be notified. */
671 x_scroll_bar_clear (f);
673 #ifndef HAVE_X11
674 dumpborder (f, 0);
675 #endif /* HAVE_X11 */
677 XFlushQueue ();
678 UNBLOCK_INPUT;
681 /* Invert the middle quarter of the frame for .15 sec. */
683 /* We use the select system call to do the waiting, so we have to make sure
684 it's avaliable. If it isn't, we just won't do visual bells. */
685 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
687 /* Subtract the `struct timeval' values X and Y,
688 storing the result in RESULT.
689 Return 1 if the difference is negative, otherwise 0. */
691 static int
692 timeval_subtract (result, x, y)
693 struct timeval *result, x, y;
695 /* Perform the carry for the later subtraction by updating y.
696 This is safer because on some systems
697 the tv_sec member is unsigned. */
698 if (x.tv_usec < y.tv_usec)
700 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
701 y.tv_usec -= 1000000 * nsec;
702 y.tv_sec += nsec;
704 if (x.tv_usec - y.tv_usec > 1000000)
706 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
707 y.tv_usec += 1000000 * nsec;
708 y.tv_sec -= nsec;
711 /* Compute the time remaining to wait. tv_usec is certainly positive. */
712 result->tv_sec = x.tv_sec - y.tv_sec;
713 result->tv_usec = x.tv_usec - y.tv_usec;
715 /* Return indication of whether the result should be considered negative. */
716 return x.tv_sec < y.tv_sec;
719 XTflash (f)
720 struct frame *f;
722 BLOCK_INPUT;
725 GC gc;
727 /* Create a GC that will use the GXxor function to flip foreground pixels
728 into background pixels. */
730 XGCValues values;
732 values.function = GXxor;
733 values.foreground = (f->display.x->foreground_pixel
734 ^ f->display.x->background_pixel);
736 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
737 GCFunction | GCForeground, &values);
741 int width = PIXEL_WIDTH (f);
742 int height = PIXEL_HEIGHT (f);
744 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
745 width/4, height/4, width/2, height/2);
746 XFlush (x_current_display);
749 struct timeval wakeup, now;
751 gettimeofday (&wakeup, (struct timezone *) 0);
753 /* Compute time to wait until, propagating carry from usecs. */
754 wakeup.tv_usec += 150000;
755 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
756 wakeup.tv_usec %= 1000000;
758 /* Keep waiting until past the time wakeup. */
759 while (1)
761 struct timeval timeout;
763 gettimeofday (&timeout, (struct timezone *)0);
765 /* In effect, timeout = wakeup - timeout.
766 Break if result would be negative. */
767 if (timeval_subtract (&timeout, wakeup, timeout))
768 break;
770 /* Try to wait that long--but we might wake up sooner. */
771 select (0, 0, 0, 0, &timeout);
775 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
776 width/4, height/4, width/2, height/2);
777 XFreeGC (x_current_display, gc);
778 XFlush (x_current_display);
782 UNBLOCK_INPUT;
785 #endif
788 /* Make audible bell. */
790 #ifdef HAVE_X11
791 #define XRINGBELL XBell(x_current_display, 0)
792 #else /* ! defined (HAVE_X11) */
793 #define XRINGBELL XFeep(0);
794 #endif /* ! defined (HAVE_X11) */
796 XTring_bell ()
798 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
799 if (visible_bell)
800 XTflash (selected_frame);
801 else
802 #endif
804 BLOCK_INPUT;
805 XRINGBELL;
806 XFlushQueue ();
807 UNBLOCK_INPUT;
811 /* Insert and delete character.
812 These are not supposed to be used because we are supposed to turn
813 off the feature of using them. */
815 static
816 XTinsert_glyphs (start, len)
817 register char *start;
818 register int len;
820 abort ();
823 static
824 XTdelete_glyphs (n)
825 register int n;
827 abort ();
830 /* Specify how many text lines, from the top of the window,
831 should be affected by insert-lines and delete-lines operations.
832 This, and those operations, are used only within an update
833 that is bounded by calls to XTupdate_begin and XTupdate_end. */
835 static
836 XTset_terminal_window (n)
837 register int n;
839 if (updating_frame == 0)
840 abort ();
842 if ((n <= 0) || (n > updating_frame->height))
843 flexlines = updating_frame->height;
844 else
845 flexlines = n;
848 /* Perform an insert-lines operation.
849 Insert N lines at a vertical position curs_y. */
851 static void
852 stufflines (n)
853 register int n;
855 register int topregion, bottomregion;
856 register int length, newtop, mask;
857 register struct frame *f = updating_frame;
858 int intborder = f->display.x->internal_border_width;
860 if (curs_y >= flexlines)
861 return;
863 topregion = curs_y;
864 bottomregion = flexlines - (n + 1);
865 newtop = topregion + n;
866 length = (bottomregion - topregion) + 1;
868 #ifndef HAVE_X11
869 dumpqueue ();
870 #endif /* HAVE_X11 */
872 if ((length > 0) && (newtop <= flexlines))
874 #ifdef HAVE_X11
875 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
876 FRAME_X_WINDOW (f), f->display.x->normal_gc,
877 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
878 f->width * FONT_WIDTH (f->display.x->font),
879 length * FONT_HEIGHT (f->display.x->font), intborder,
880 CHAR_TO_PIXEL_ROW (f, newtop));
881 #else /* ! defined (HAVE_X11) */
882 XMoveArea (FRAME_X_WINDOW (f),
883 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
884 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
885 f->width * FONT_WIDTH (f->display.x->font),
886 length * FONT_HEIGHT (f->display.x->font));
887 /* Now we must process any ExposeRegion events that occur
888 if the area being copied from is obscured.
889 We can't let it wait because further i/d operations
890 may want to copy this area to another area. */
891 x_read_exposes ();
892 #endif /* ! defined (HAVE_X11) */
895 newtop = min (newtop, (flexlines - 1));
896 length = newtop - topregion;
897 if (length > 0)
899 #ifdef HAVE_X11
900 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
901 CHAR_TO_PIXEL_ROW (f, topregion),
902 f->width * FONT_WIDTH (f->display.x->font),
903 n * FONT_HEIGHT (f->display.x->font), False);
904 #else /* ! defined (HAVE_X11) */
905 XPixSet (FRAME_X_WINDOW (f),
906 intborder,
907 CHAR_TO_PIXEL_ROW (f, topregion),
908 f->width * FONT_WIDTH (f->display.x->font),
909 n * FONT_HEIGHT (f->display.x->font),
910 f->display.x->background_pixel);
911 #endif /* ! defined (HAVE_X11) */
915 /* Perform a delete-lines operation, deleting N lines
916 at a vertical position curs_y. */
918 static void
919 scraplines (n)
920 register int n;
922 int mask;
923 register struct frame *f = updating_frame;
924 int intborder = f->display.x->internal_border_width;
926 if (curs_y >= flexlines)
927 return;
929 #ifndef HAVE_X11
930 dumpqueue ();
931 #endif /* HAVE_X11 */
933 if ((curs_y + n) >= flexlines)
935 if (flexlines >= (curs_y + 1))
937 #ifdef HAVE_X11
938 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
939 CHAR_TO_PIXEL_ROW (f, curs_y),
940 f->width * FONT_WIDTH (f->display.x->font),
941 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
942 #else /* ! defined (HAVE_X11) */
943 XPixSet (FRAME_X_WINDOW (f),
944 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
945 f->width * FONT_WIDTH (f->display.x->font),
946 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
947 f->display.x->background_pixel);
948 #endif /* ! defined (HAVE_X11) */
951 else
953 #ifdef HAVE_X11
954 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
955 FRAME_X_WINDOW (f), f->display.x->normal_gc,
956 intborder,
957 CHAR_TO_PIXEL_ROW (f, curs_y + n),
958 f->width * FONT_WIDTH (f->display.x->font),
959 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
960 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
961 XClearArea (x_current_display, FRAME_X_WINDOW (f),
962 intborder,
963 CHAR_TO_PIXEL_ROW (f, flexlines - n),
964 f->width * FONT_WIDTH (f->display.x->font),
965 n * FONT_HEIGHT (f->display.x->font), False);
966 #else /* ! defined (HAVE_X11) */
967 XMoveArea (FRAME_X_WINDOW (f),
968 intborder,
969 CHAR_TO_PIXEL_ROW (f, curs_y + n),
970 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
971 f->width * FONT_WIDTH (f->display.x->font),
972 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
973 /* Now we must process any ExposeRegion events that occur
974 if the area being copied from is obscured.
975 We can't let it wait because further i/d operations
976 may want to copy this area to another area. */
977 x_read_exposes ();
978 XPixSet (FRAME_X_WINDOW (f), intborder,
979 CHAR_TO_PIXEL_ROW (f, flexlines - n),
980 f->width * FONT_WIDTH (f->display.x->font),
981 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
982 #endif /* ! defined (HAVE_X11) */
986 /* Perform an insert-lines or delete-lines operation,
987 inserting N lines or deleting -N lines at vertical position VPOS. */
989 XTins_del_lines (vpos, n)
990 int vpos, n;
992 if (updating_frame == 0)
993 abort ();
995 /* Hide the cursor. */
996 x_display_cursor (updating_frame, 0);
998 XTcursor_to (vpos, 0);
1000 BLOCK_INPUT;
1001 if (n >= 0)
1002 stufflines (n);
1003 else
1004 scraplines (-n);
1005 XFlushQueue ();
1006 UNBLOCK_INPUT;
1009 /* Support routines for exposure events. */
1010 static void clear_cursor ();
1012 /* Output into a rectangle of an X-window (for frame F)
1013 the characters in f->phys_lines that overlap that rectangle.
1014 TOP and LEFT are the position of the upper left corner of the rectangle.
1015 ROWS and COLS are the size of the rectangle. */
1017 static void
1018 dumprectangle (f, left, top, cols, rows)
1019 struct frame *f;
1020 register int left, top, cols, rows;
1022 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1023 int cursor_cleared = 0;
1024 int bottom, right;
1025 register int y;
1027 if (FRAME_GARBAGED_P (f))
1028 return;
1030 /* Express rectangle as four edges, instead of position-and-size. */
1031 bottom = top + rows;
1032 right = left + cols;
1034 #ifndef HAVE_X11 /* Window manger does this for X11. */
1036 int intborder = f->display.x->internal_border_width;
1038 /* If the rectangle includes any of the internal border area,
1039 redisplay the border emphasis. */
1040 if (top < intborder || left < intborder
1041 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1042 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1043 dumpborder (f, 0);
1045 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
1047 /* Convert rectangle edges in pixels to edges in chars.
1048 Round down for left and top, up for right and bottom. */
1049 top = PIXEL_TO_CHAR_ROW (f, top);
1050 left = PIXEL_TO_CHAR_COL (f, left);
1051 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1052 right += (FONT_WIDTH (f->display.x->font) - 1);
1053 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1054 right = PIXEL_TO_CHAR_COL (f, right);
1056 /* Clip the rectangle to what can be visible. */
1057 if (left < 0)
1058 left = 0;
1059 if (top < 0)
1060 top = 0;
1061 if (right > f->width)
1062 right = f->width;
1063 if (bottom > f->height)
1064 bottom = f->height;
1066 /* Get size in chars of the rectangle. */
1067 cols = right - left;
1068 rows = bottom - top;
1070 /* If rectangle has zero area, return. */
1071 if (rows <= 0) return;
1072 if (cols <= 0) return;
1074 /* Turn off the cursor if it is in the rectangle.
1075 We will turn it back on afterward. */
1076 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1077 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1079 clear_cursor (f);
1080 cursor_cleared = 1;
1083 /* Display the text in the rectangle, one text line at a time. */
1085 for (y = top; y < bottom; y++)
1087 GLYPH *line = &active_frame->glyphs[y][left];
1089 if (! active_frame->enable[y] || left > active_frame->used[y])
1090 continue;
1092 dumpglyphs (f,
1093 CHAR_TO_PIXEL_COL (f, left),
1094 CHAR_TO_PIXEL_ROW (f, y),
1095 line, min (cols, active_frame->used[y] - left),
1096 active_frame->highlight[y], f->display.x->font);
1099 /* Turn the cursor on if we turned it off. */
1101 if (cursor_cleared)
1102 x_display_cursor (f, 1);
1105 #ifndef HAVE_X11
1106 /* Process all queued ExposeRegion events. */
1108 static void
1109 dumpqueue ()
1111 register int i;
1112 XExposeRegionEvent r;
1114 while (dequeue_event (&r, &x_expose_queue))
1116 struct frame *f = x_window_to_frame (r.window);
1117 if (f->display.x->icon_desc == r.window)
1118 refreshicon (f);
1119 else
1120 dumprectangle (f, r.x, r.y, r.width, r.height);
1122 XFlushQueue ();
1124 #endif /* HAVE_X11 */
1126 /* Process all expose events that are pending, for X10.
1127 Redraws the cursor if necessary on any frame that
1128 is not in the process of being updated with update_frame. */
1130 #ifndef HAVE_X11
1131 static void
1132 x_do_pending_expose ()
1134 int mask;
1135 struct frame *f;
1136 Lisp_Object tail, frame;
1138 if (expose_all_windows)
1140 expose_all_windows = 0;
1141 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1143 register int temp_width, temp_height;
1144 int intborder;
1146 frame = XCONS (tail)->car;
1147 if (XGCTYPE (frame) != Lisp_Frame)
1148 continue;
1149 f = XFRAME (frame);
1150 if (! FRAME_X_P (f))
1151 continue;
1152 if (!f->async_visible)
1153 continue;
1154 if (!f->display.x->needs_exposure)
1155 continue;
1157 intborder = f->display.x->internal_border_width;
1159 clear_cursor (f);
1160 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1161 temp_width = ((windowinfo.width - 2 * intborder
1162 - f->display.x->v_scroll_bar_width)
1163 / FONT_WIDTH (f->display.x->font));
1164 temp_height = ((windowinfo.height- 2 * intborder
1165 - f->display.x->h_scroll_bar_height)
1166 / FONT_HEIGHT (f->display.x->font));
1167 if (temp_width != f->width || temp_height != f->height)
1169 change_frame_size (f, max (1, temp_height),
1170 max (1, temp_width), 0, 1);
1171 x_resize_scroll_bars (f);
1173 f->display.x->left_pos = windowinfo.x;
1174 f->display.x->top_pos = windowinfo.y;
1175 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1176 #if 0
1177 dumpborder (f, 0);
1178 #endif /* ! 0 */
1179 f->display.x->needs_exposure = 0;
1180 if (updating_frame != f)
1181 x_display_cursor (f, 1);
1182 XFlushQueue ();
1185 else
1186 /* Handle any individual-rectangle expose events queued
1187 for various windows. */
1188 #ifdef HAVE_X11
1190 #else /* ! defined (HAVE_X11) */
1191 dumpqueue ();
1192 #endif /* ! defined (HAVE_X11) */
1194 #endif
1196 #ifdef HAVE_X11
1197 static void
1198 frame_highlight (frame)
1199 struct frame *frame;
1201 if (! EQ (Vx_no_window_manager, Qnil))
1202 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1203 frame->display.x->border_pixel);
1204 x_display_cursor (frame, 1);
1207 static void
1208 frame_unhighlight (frame)
1209 struct frame *frame;
1211 if (! EQ (Vx_no_window_manager, Qnil))
1212 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1213 frame->display.x->border_tile);
1214 x_display_cursor (frame, 1);
1216 #else /* ! defined (HAVE_X11) */
1217 /* Dump the border-emphasis of frame F.
1218 If F is selected, this is a lining of the same color as the border,
1219 just within the border, occupying a portion of the internal border.
1220 If F is not selected, it is background in the same place.
1221 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1223 ALWAYS = 1 is used when a frame becomes selected or deselected.
1224 In that case, we also turn the cursor off and on again
1225 so it will appear in the proper shape (solid if selected; else hollow.) */
1227 static void
1228 dumpborder (f, always)
1229 struct frame *f;
1230 int always;
1232 int thickness = f->display.x->internal_border_width / 2;
1233 int width = PIXEL_WIDTH (f);
1234 int height = PIXEL_HEIGHT (f);
1235 int pixel;
1237 if (f != selected_frame)
1239 if (!always)
1240 return;
1242 pixel = f->display.x->background_pixel;
1244 else
1246 pixel = f->display.x->border_pixel;
1249 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1250 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1251 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1252 thickness, pixel);
1253 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1254 height, pixel);
1256 if (always)
1257 x_display_cursor (f, 1);
1259 #endif /* ! defined (HAVE_X11) */
1261 static void XTframe_rehighlight ();
1263 /* The focus has changed. Update the frames as necessary to reflect
1264 the new situation. Note that we can't change the selected frame
1265 here, because the lisp code we are interrupting might become confused.
1266 Each event gets marked with the frame in which it occured, so the
1267 lisp code can tell when the switch took place by examining the events. */
1269 static void
1270 x_new_focus_frame (frame)
1271 struct frame *frame;
1273 struct frame *old_focus = x_focus_frame;
1274 int events_enqueued = 0;
1276 if (frame != x_focus_frame)
1278 /* Set this before calling other routines, so that they see
1279 the correct value of x_focus_frame. */
1280 x_focus_frame = frame;
1282 if (old_focus && old_focus->auto_lower)
1283 x_lower_frame (old_focus);
1285 #if 0
1286 selected_frame = frame;
1287 XSET (XWINDOW (selected_frame->selected_window)->frame,
1288 Lisp_Frame, selected_frame);
1289 Fselect_window (selected_frame->selected_window);
1290 choose_minibuf_frame ();
1291 #endif /* ! 0 */
1293 if (x_focus_frame && x_focus_frame->auto_raise)
1294 x_raise_frame (x_focus_frame);
1297 XTframe_rehighlight ();
1301 /* The focus has changed, or we have redirected a frame's focus to
1302 another frame (this happens when a frame uses a surrogate
1303 minibuffer frame). Shift the highlight as appropriate. */
1304 static void
1305 XTframe_rehighlight ()
1307 struct frame *old_highlight = x_highlight_frame;
1309 if (x_focus_frame)
1311 x_highlight_frame =
1312 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1313 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1314 : x_focus_frame);
1315 if (! FRAME_LIVE_P (x_highlight_frame))
1317 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1318 x_highlight_frame = x_focus_frame;
1321 else
1322 x_highlight_frame = 0;
1324 if (x_highlight_frame != old_highlight)
1326 if (old_highlight)
1327 frame_unhighlight (old_highlight);
1328 if (x_highlight_frame)
1329 frame_highlight (x_highlight_frame);
1333 /* Mouse clicks and mouse movement. Rah. */
1334 #ifdef HAVE_X11
1336 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1337 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1338 that the glyph at X, Y occupies, if BOUNDS != 0. */
1339 static void
1340 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1341 FRAME_PTR f;
1342 register unsigned int pix_x, pix_y;
1343 register int *x, *y;
1344 XRectangle *bounds;
1346 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1347 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1349 if (bounds)
1351 bounds->width = FONT_WIDTH (f->display.x->font);
1352 bounds->height = FONT_HEIGHT (f->display.x->font);
1353 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1354 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1357 if (pix_x < 0) pix_x = 0;
1358 else if (pix_x > f->width) pix_x = f->width;
1360 if (pix_y < 0) pix_y = 0;
1361 else if (pix_y > f->height) pix_y = f->height;
1363 *x = pix_x;
1364 *y = pix_y;
1367 /* Any buttons grabbed. */
1368 unsigned int x_mouse_grabbed;
1370 /* Which modifier keys are on which modifier bits?
1372 With each keystroke, X returns eight bits indicating which modifier
1373 keys were held down when the key was pressed. The interpretation
1374 of the top five modifier bits depends on what keys are attached
1375 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1376 is the meta bit.
1378 x_meta_mod_mask is a mask containing the bits used for the meta key.
1379 It may have more than one bit set, if more than one modifier bit
1380 has meta keys on it. Basically, if EVENT is a KeyPress event,
1381 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1383 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1384 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1385 only be affected by the lock modifier bit if XK_Shift_Lock is in
1386 use; XK_Caps_Lock should only affect alphabetic keys. With this
1387 arrangement, the lock modifier should shift the character if
1388 (EVENT.state & x_shift_lock_mask) != 0. */
1389 static int x_meta_mod_mask, x_shift_lock_mask;
1391 /* These are like x_meta_mod_mask, but for different modifiers. */
1392 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1394 /* Initialize mode_switch_bit and modifier_meaning. */
1395 static void
1396 x_find_modifier_meanings ()
1398 int min_code, max_code;
1399 KeySym *syms;
1400 int syms_per_code;
1401 XModifierKeymap *mods;
1403 x_meta_mod_mask = 0;
1404 x_shift_lock_mask = 0;
1405 x_alt_mod_mask = 0;
1406 x_super_mod_mask = 0;
1407 x_hyper_mod_mask = 0;
1409 #ifdef HAVE_X11R4
1410 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1411 #else
1412 min_code = x_current_display->min_keycode;
1413 max_code = x_current_display->max_keycode;
1414 #endif
1416 syms = XGetKeyboardMapping (x_current_display,
1417 min_code, max_code - min_code + 1,
1418 &syms_per_code);
1419 mods = XGetModifierMapping (x_current_display);
1421 /* Scan the modifier table to see which modifier bits the Meta and
1422 Alt keysyms are on. */
1424 int row, col; /* The row and column in the modifier table. */
1426 for (row = 3; row < 8; row++)
1427 for (col = 0; col < mods->max_keypermod; col++)
1429 KeyCode code =
1430 mods->modifiermap[(row * mods->max_keypermod) + col];
1432 /* Are any of this keycode's keysyms a meta key? */
1434 int code_col;
1436 for (code_col = 0; code_col < syms_per_code; code_col++)
1438 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1440 switch (sym)
1442 case XK_Meta_L:
1443 case XK_Meta_R:
1444 x_meta_mod_mask |= (1 << row);
1445 break;
1447 case XK_Alt_L:
1448 case XK_Alt_R:
1449 x_alt_mod_mask |= (1 << row);
1450 break;
1452 case XK_Hyper_L:
1453 case XK_Hyper_R:
1454 x_hyper_mod_mask |= (1 << row);
1455 break;
1457 case XK_Super_L:
1458 case XK_Super_R:
1459 x_super_mod_mask |= (1 << row);
1460 break;
1462 case XK_Shift_Lock:
1463 /* Ignore this if it's not on the lock modifier. */
1464 if ((1 << row) == LockMask)
1465 x_shift_lock_mask = LockMask;
1466 break;
1473 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1474 if (! x_meta_mod_mask)
1476 x_meta_mod_mask = x_alt_mod_mask;
1477 x_alt_mod_mask = 0;
1480 XFree ((char *) syms);
1481 XFreeModifiermap (mods);
1485 /* Convert a set of X modifier bits to the proper form for a
1486 struct input_event modifiers value. */
1488 static unsigned int
1489 x_convert_modifiers (state)
1490 unsigned int state;
1492 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1493 | ((state & ControlMask) ? ctrl_modifier : 0)
1494 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1495 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1496 | ((state & x_super_mod_mask) ? super_modifier : 0)
1497 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1500 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1502 If the event is a button press, then note that we have grabbed
1503 the mouse. */
1505 static Lisp_Object
1506 construct_mouse_click (result, event, f)
1507 struct input_event *result;
1508 XButtonEvent *event;
1509 struct frame *f;
1511 /* Make the event type no_event; we'll change that when we decide
1512 otherwise. */
1513 result->kind = mouse_click;
1514 XSET (result->code, Lisp_Int, event->button - Button1);
1515 result->timestamp = event->time;
1516 result->modifiers = (x_convert_modifiers (event->state)
1517 | (event->type == ButtonRelease
1518 ? up_modifier
1519 : down_modifier));
1521 /* Notice if the mouse is still grabbed. */
1522 if (event->type == ButtonPress)
1524 if (! x_mouse_grabbed)
1525 Vmouse_depressed = Qt;
1526 x_mouse_grabbed |= (1 << event->button);
1528 else if (event->type == ButtonRelease)
1530 x_mouse_grabbed &= ~(1 << event->button);
1531 if (!x_mouse_grabbed)
1532 Vmouse_depressed = Qnil;
1536 int row, column;
1538 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1539 XFASTINT (result->x) = column;
1540 XFASTINT (result->y) = row;
1541 XSET (result->frame_or_window, Lisp_Frame, f);
1546 /* Mouse movement. Rah.
1548 In order to avoid asking for motion events and then throwing most
1549 of them away or busy-polling the server for mouse positions, we ask
1550 the server for pointer motion hints. This means that we get only
1551 one event per group of mouse movements. "Groups" are delimited by
1552 other kinds of events (focus changes and button clicks, for
1553 example), or by XQueryPointer calls; when one of these happens, we
1554 get another MotionNotify event the next time the mouse moves. This
1555 is at least as efficient as getting motion events when mouse
1556 tracking is on, and I suspect only negligibly worse when tracking
1557 is off.
1559 The silly O'Reilly & Associates Nutshell guides barely document
1560 pointer motion hints at all (I think you have to infer how they
1561 work from an example), and the description of XQueryPointer doesn't
1562 mention that calling it causes you to get another motion hint from
1563 the server, which is very important. */
1565 /* Where the mouse was last time we reported a mouse event. */
1566 static FRAME_PTR last_mouse_frame;
1567 static XRectangle last_mouse_glyph;
1569 /* The scroll bar in which the last X motion event occurred.
1571 If the last X motion event occured in a scroll bar, we set this
1572 so XTmouse_position can know whether to report a scroll bar motion or
1573 an ordinary motion.
1575 If the last X motion event didn't occur in a scroll bar, we set this
1576 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1577 static Lisp_Object last_mouse_scroll_bar;
1579 /* This is a hack. We would really prefer that XTmouse_position would
1580 return the time associated with the position it returns, but there
1581 doesn't seem to be any way to wrest the timestamp from the server
1582 along with the position query. So, we just keep track of the time
1583 of the last movement we received, and return that in hopes that
1584 it's somewhat accurate. */
1585 static Time last_mouse_movement_time;
1587 /* Function to report a mouse movement to the mainstream Emacs code.
1588 The input handler calls this.
1590 We have received a mouse movement event, which is given in *event.
1591 If the mouse is over a different glyph than it was last time, tell
1592 the mainstream emacs code by setting mouse_moved. If not, ask for
1593 another motion event, so we can check again the next time it moves. */
1594 static void
1595 note_mouse_movement (frame, event)
1596 FRAME_PTR frame;
1597 XMotionEvent *event;
1600 last_mouse_movement_time = event->time;
1602 /* Has the mouse moved off the glyph it was on at the last sighting? */
1603 if (event->x < last_mouse_glyph.x
1604 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1605 || event->y < last_mouse_glyph.y
1606 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1608 mouse_moved = 1;
1609 last_mouse_scroll_bar = Qnil;
1611 else
1613 /* It's on the same glyph. Call XQueryPointer so we'll get an
1614 event the next time the mouse moves and we can see if it's
1615 *still* on the same glyph. */
1616 int dummy;
1618 XQueryPointer (event->display, event->window,
1619 (Window *) &dummy, (Window *) &dummy,
1620 &dummy, &dummy, &dummy, &dummy,
1621 (unsigned int *) &dummy);
1625 static struct scroll_bar *x_window_to_scroll_bar ();
1626 static void x_scroll_bar_report_motion ();
1628 /* Return the current position of the mouse.
1630 If the mouse movement started in a scroll bar, set *f, *bar_window,
1631 and *part to the frame, window, and scroll bar part that the mouse
1632 is over. Set *x and *y to the portion and whole of the mouse's
1633 position on the scroll bar.
1635 If the mouse movement started elsewhere, set *f to the frame the
1636 mouse is on, *bar_window to nil, and *x and *y to the character cell
1637 the mouse is over.
1639 Set *time to the server timestamp for the time at which the mouse
1640 was at this position.
1642 This clears the mouse_moved flag, so we can wait for the next mouse
1643 movement. This also calls XQueryPointer, which will cause the
1644 server to give us another MotionNotify when the mouse moves
1645 again. */
1647 static void
1648 XTmouse_position (f, bar_window, part, x, y, time)
1649 FRAME_PTR *f;
1650 Lisp_Object *bar_window;
1651 enum scroll_bar_part *part;
1652 Lisp_Object *x, *y;
1653 unsigned long *time;
1655 BLOCK_INPUT;
1657 if (! NILP (last_mouse_scroll_bar))
1658 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1659 else
1661 Window root;
1662 int root_x, root_y;
1664 Window dummy_window;
1665 int dummy;
1667 mouse_moved = 0;
1668 last_mouse_scroll_bar = Qnil;
1670 /* Figure out which root window we're on. */
1671 XQueryPointer (x_current_display,
1672 DefaultRootWindow (x_current_display),
1674 /* The root window which contains the pointer. */
1675 &root,
1677 /* Trash which we can't trust if the pointer is on
1678 a different screen. */
1679 &dummy_window,
1681 /* The position on that root window. */
1682 &root_x, &root_y,
1684 /* More trash we can't trust. */
1685 &dummy, &dummy,
1687 /* Modifier keys and pointer buttons, about which
1688 we don't care. */
1689 (unsigned int *) &dummy);
1691 /* Now we have a position on the root; find the innermost window
1692 containing the pointer. */
1694 Window win, child;
1695 int win_x, win_y;
1696 int parent_x, parent_y;
1698 win = root;
1699 for (;;)
1701 XTranslateCoordinates (x_current_display,
1703 /* From-window, to-window. */
1704 root, win,
1706 /* From-position, to-position. */
1707 root_x, root_y, &win_x, &win_y,
1709 /* Child of win. */
1710 &child);
1712 if (child == None)
1713 break;
1715 win = child;
1716 parent_x = win_x;
1717 parent_y = win_y;
1720 /* Now we know that:
1721 win is the innermost window containing the pointer
1722 (XTC says it has no child containing the pointer),
1723 win_x and win_y are the pointer's position in it
1724 (XTC did this the last time through), and
1725 parent_x and parent_y are the pointer's position in win's parent.
1726 (They are what win_x and win_y were when win was child.
1727 If win is the root window, it has no parent, and
1728 parent_{x,y} are invalid, but that's okay, because we'll
1729 never use them in that case.) */
1731 /* Is win one of our frames? */
1732 *f = x_window_to_frame (win);
1734 /* If not, is it one of our scroll bars? */
1735 if (! *f)
1737 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1739 if (bar)
1741 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1742 win_x = parent_x;
1743 win_y = parent_y;
1747 if (*f)
1749 pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y,
1750 &last_mouse_glyph);
1752 *bar_window = Qnil;
1753 *part = 0;
1754 XSET (*x, Lisp_Int, win_x);
1755 XSET (*y, Lisp_Int, win_y);
1756 *time = last_mouse_movement_time;
1761 UNBLOCK_INPUT;
1764 #else /* ! defined (HAVE_X11) */
1765 #define XEvent XKeyPressedEvent
1766 #endif /* ! defined (HAVE_X11) */
1768 /* Scroll bar support. */
1770 /* Given an X window ID, find the struct scroll_bar which manages it.
1771 This can be called in GC, so we have to make sure to strip off mark
1772 bits. */
1773 static struct scroll_bar *
1774 x_window_to_scroll_bar (window_id)
1775 Window window_id;
1777 Lisp_Object tail, frame;
1779 for (tail = Vframe_list;
1780 XGCTYPE (tail) == Lisp_Cons;
1781 tail = XCONS (tail)->cdr)
1783 Lisp_Object frame = XCONS (tail)->car;
1784 Lisp_Object bar, condemned;
1786 /* All elements of Vframe_list should be frames. */
1787 if (XGCTYPE (frame) != Lisp_Frame)
1788 abort ();
1790 /* Scan this frame's scroll bar list for a scroll bar with the
1791 right window ID. */
1792 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1793 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1794 /* This trick allows us to search both the ordinary and
1795 condemned scroll bar lists with one loop. */
1796 ! GC_NILP (bar) || (bar = condemned,
1797 condemned = Qnil,
1798 ! GC_NILP (bar));
1799 bar = XSCROLL_BAR(bar)->next)
1800 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1801 return XSCROLL_BAR (bar);
1804 return 0;
1807 /* Open a new X window to serve as a scroll bar, and return the
1808 scroll bar vector for it. */
1809 static struct scroll_bar *
1810 x_scroll_bar_create (window, top, left, width, height)
1811 struct window *window;
1812 int top, left, width, height;
1814 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1815 struct scroll_bar *bar =
1816 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1818 BLOCK_INPUT;
1821 XSetWindowAttributes a;
1822 unsigned long mask;
1824 a.background_pixel = frame->display.x->background_pixel;
1825 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1826 | ButtonMotionMask | PointerMotionHintMask
1827 | ExposureMask);
1828 a.cursor = x_vertical_scroll_bar_cursor;
1830 mask = (CWBackPixel | CWEventMask | CWCursor);
1832 SET_SCROLL_BAR_X_WINDOW
1833 (bar,
1834 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1836 /* Position and size of scroll bar. */
1837 left, top, width, height,
1839 /* Border width, depth, class, and visual. */
1840 0, CopyFromParent, CopyFromParent, CopyFromParent,
1842 /* Attributes. */
1843 mask, &a));
1846 XSET (bar->window, Lisp_Window, window);
1847 XSET (bar->top, Lisp_Int, top);
1848 XSET (bar->left, Lisp_Int, left);
1849 XSET (bar->width, Lisp_Int, width);
1850 XSET (bar->height, Lisp_Int, height);
1851 XSET (bar->start, Lisp_Int, 0);
1852 XSET (bar->end, Lisp_Int, 0);
1853 bar->dragging = Qnil;
1855 /* Add bar to its frame's list of scroll bars. */
1856 bar->next = FRAME_SCROLL_BARS (frame);
1857 bar->prev = Qnil;
1858 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1859 if (! NILP (bar->next))
1860 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1862 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1864 UNBLOCK_INPUT;
1866 return bar;
1869 /* Draw BAR's handle in the proper position.
1870 If the handle is already drawn from START to END, don't bother
1871 redrawing it, unless REBUILD is non-zero; in that case, always
1872 redraw it. (REBUILD is handy for drawing the handle after expose
1873 events.)
1875 Normally, we want to constrain the start and end of the handle to
1876 fit inside its rectangle, but if the user is dragging the scroll bar
1877 handle, we want to let them drag it down all the way, so that the
1878 bar's top is as far down as it goes; otherwise, there's no way to
1879 move to the very end of the buffer. */
1880 static void
1881 x_scroll_bar_set_handle (bar, start, end, rebuild)
1882 struct scroll_bar *bar;
1883 int start, end;
1884 int rebuild;
1886 int dragging = ! NILP (bar->dragging);
1887 Window w = SCROLL_BAR_X_WINDOW (bar);
1888 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1890 /* If the display is already accurate, do nothing. */
1891 if (! rebuild
1892 && start == XINT (bar->start)
1893 && end == XINT (bar->end))
1894 return;
1896 BLOCK_INPUT;
1899 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1900 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1901 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
1903 /* Make sure the values are reasonable, and try to preserve
1904 the distance between start and end. */
1906 int length = end - start;
1908 if (start < 0)
1909 start = 0;
1910 else if (start > top_range)
1911 start = top_range;
1912 end = start + length;
1914 if (end < start)
1915 end = start;
1916 else if (end > top_range && ! dragging)
1917 end = top_range;
1920 /* Store the adjusted setting in the scroll bar. */
1921 XSET (bar->start, Lisp_Int, start);
1922 XSET (bar->end, Lisp_Int, end);
1924 /* Clip the end position, just for display. */
1925 if (end > top_range)
1926 end = top_range;
1928 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
1929 below top positions, to make sure the handle is always at least
1930 that many pixels tall. */
1931 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
1933 /* Draw the empty space above the handle. Note that we can't clear
1934 zero-height areas; that means "clear to end of window." */
1935 if (0 < start)
1936 XClearArea (x_current_display, w,
1938 /* x, y, width, height, and exposures. */
1939 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1940 VERTICAL_SCROLL_BAR_TOP_BORDER,
1941 inside_width, start,
1942 False);
1944 /* Draw the handle itself. */
1945 XFillRectangle (x_current_display, w, gc,
1947 /* x, y, width, height */
1948 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1949 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
1950 inside_width, end - start);
1953 /* Draw the empty space below the handle. Note that we can't
1954 clear zero-height areas; that means "clear to end of window." */
1955 if (end < inside_height)
1956 XClearArea (x_current_display, w,
1958 /* x, y, width, height, and exposures. */
1959 VERTICAL_SCROLL_BAR_LEFT_BORDER,
1960 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
1961 inside_width, inside_height - end,
1962 False);
1966 UNBLOCK_INPUT;
1969 /* Move a scroll bar around on the screen, to accomodate changing
1970 window configurations. */
1971 static void
1972 x_scroll_bar_move (bar, top, left, width, height)
1973 struct scroll_bar *bar;
1974 int top, left, width, height;
1976 BLOCK_INPUT;
1979 XWindowChanges wc;
1980 unsigned int mask = 0;
1982 wc.x = left;
1983 wc.y = top;
1984 wc.width = width;
1985 wc.height = height;
1987 if (left != XINT (bar->left)) mask |= CWX;
1988 if (top != XINT (bar->top)) mask |= CWY;
1989 if (width != XINT (bar->width)) mask |= CWWidth;
1990 if (height != XINT (bar->height)) mask |= CWHeight;
1992 if (mask)
1993 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
1994 mask, &wc);
1997 XSET (bar->left, Lisp_Int, left);
1998 XSET (bar->top, Lisp_Int, top);
1999 XSET (bar->width, Lisp_Int, width);
2000 XSET (bar->height, Lisp_Int, height);
2002 UNBLOCK_INPUT;
2005 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2006 to nil. */
2007 static void
2008 x_scroll_bar_remove (bar)
2009 struct scroll_bar *bar;
2011 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2013 BLOCK_INPUT;
2015 /* Destroy the window. */
2016 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2018 /* Disassociate this scroll bar from its window. */
2019 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2021 UNBLOCK_INPUT;
2024 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2025 that we are displaying PORTION characters out of a total of WHOLE
2026 characters, starting at POSITION. If WINDOW has no scroll bar,
2027 create one. */
2028 static void
2029 XTset_vertical_scroll_bar (window, portion, whole, position)
2030 struct window *window;
2031 int portion, whole, position;
2033 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2034 int top = XINT (window->top);
2035 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2036 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2038 /* Where should this scroll bar be, pixelwise? */
2039 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2040 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2041 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2042 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2044 struct scroll_bar *bar;
2046 /* Does the scroll bar exist yet? */
2047 if (NILP (window->vertical_scroll_bar))
2048 bar = x_scroll_bar_create (window,
2049 pixel_top, pixel_left,
2050 pixel_width, pixel_height);
2051 else
2053 /* It may just need to be moved and resized. */
2054 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2055 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2058 /* Set the scroll bar's current state, unless we're currently being
2059 dragged. */
2060 if (NILP (bar->dragging))
2062 int top_range =
2063 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2065 if (whole == 0)
2066 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2067 else
2069 int start = (position * top_range) / whole;
2070 int end = ((position + portion) * top_range) / whole;
2072 x_scroll_bar_set_handle (bar, start, end, 0);
2076 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2080 /* The following three hooks are used when we're doing a thorough
2081 redisplay of the frame. We don't explicitly know which scroll bars
2082 are going to be deleted, because keeping track of when windows go
2083 away is a real pain - "Can you say set-window-configuration, boys
2084 and girls?" Instead, we just assert at the beginning of redisplay
2085 that *all* scroll bars are to be removed, and then save a scroll bar
2086 from the fiery pit when we actually redisplay its window. */
2088 /* Arrange for all scroll bars on FRAME to be removed at the next call
2089 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2090 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2091 static void
2092 XTcondemn_scroll_bars (frame)
2093 FRAME_PTR frame;
2095 /* The condemned list should be empty at this point; if it's not,
2096 then the rest of Emacs isn't using the condemn/redeem/judge
2097 protocol correctly. */
2098 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2099 abort ();
2101 /* Move them all to the "condemned" list. */
2102 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2103 FRAME_SCROLL_BARS (frame) = Qnil;
2106 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2107 Note that WINDOW isn't necessarily condemned at all. */
2108 static void
2109 XTredeem_scroll_bar (window)
2110 struct window *window;
2112 struct scroll_bar *bar;
2114 /* We can't redeem this window's scroll bar if it doesn't have one. */
2115 if (NILP (window->vertical_scroll_bar))
2116 abort ();
2118 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2120 /* Unlink it from the condemned list. */
2122 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2124 if (NILP (bar->prev))
2126 /* If the prev pointer is nil, it must be the first in one of
2127 the lists. */
2128 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2129 /* It's not condemned. Everything's fine. */
2130 return;
2131 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2132 window->vertical_scroll_bar))
2133 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2134 else
2135 /* If its prev pointer is nil, it must be at the front of
2136 one or the other! */
2137 abort ();
2139 else
2140 XSCROLL_BAR (bar->prev)->next = bar->next;
2142 if (! NILP (bar->next))
2143 XSCROLL_BAR (bar->next)->prev = bar->prev;
2145 bar->next = FRAME_SCROLL_BARS (f);
2146 bar->prev = Qnil;
2147 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2148 if (! NILP (bar->next))
2149 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2153 /* Remove all scroll bars on FRAME that haven't been saved since the
2154 last call to `*condemn_scroll_bars_hook'. */
2155 static void
2156 XTjudge_scroll_bars (f)
2157 FRAME_PTR f;
2159 Lisp_Object bar, next;
2161 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2163 /* Clear out the condemned list now so we won't try to process any
2164 more events on the hapless scroll bars. */
2165 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2167 for (; ! NILP (bar); bar = next)
2169 struct scroll_bar *b = XSCROLL_BAR (bar);
2171 x_scroll_bar_remove (b);
2173 next = b->next;
2174 b->next = b->prev = Qnil;
2177 /* Now there should be no references to the condemned scroll bars,
2178 and they should get garbage-collected. */
2182 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2184 This may be called from a signal handler, so we have to ignore GC
2185 mark bits. */
2186 static void
2187 x_scroll_bar_expose (bar, event)
2188 struct scroll_bar *bar;
2189 XEvent *event;
2191 Window w = SCROLL_BAR_X_WINDOW (bar);
2192 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2194 BLOCK_INPUT;
2196 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2198 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2199 XDrawRectangle (x_current_display, w, gc,
2201 /* x, y, width, height */
2202 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2204 /* Draw another line to make the extra-thick border on the right. */
2205 XFillRectangle (x_current_display, w, gc,
2207 /* x, y, width, height */
2208 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2210 UNBLOCK_INPUT;
2213 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2214 is set to something other than no_event, it is enqueued.
2216 This may be called from a signal handler, so we have to ignore GC
2217 mark bits. */
2218 static void
2219 x_scroll_bar_handle_click (bar, event, emacs_event)
2220 struct scroll_bar *bar;
2221 XEvent *event;
2222 struct input_event *emacs_event;
2224 if (XGCTYPE (bar->window) != Lisp_Window)
2225 abort ();
2227 emacs_event->kind = scroll_bar_click;
2228 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2229 emacs_event->modifiers =
2230 (x_convert_modifiers (event->xbutton.state)
2231 | (event->type == ButtonRelease
2232 ? up_modifier
2233 : down_modifier));
2234 emacs_event->frame_or_window = bar->window;
2235 emacs_event->timestamp = event->xbutton.time;
2237 int internal_height =
2238 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2239 int top_range =
2240 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2241 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2243 if (y < 0) y = 0;
2244 if (y > top_range) y = top_range;
2246 if (y < XINT (bar->start))
2247 emacs_event->part = scroll_bar_above_handle;
2248 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2249 emacs_event->part = scroll_bar_handle;
2250 else
2251 emacs_event->part = scroll_bar_below_handle;
2253 /* If the user has just clicked on the handle, record where they're
2254 holding it. */
2255 if (event->type == ButtonPress
2256 && emacs_event->part == scroll_bar_handle)
2257 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2259 /* If the user has released the handle, set it to its final position. */
2260 if (event->type == ButtonRelease
2261 && ! NILP (bar->dragging))
2263 int new_start = y - XINT (bar->dragging);
2264 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2266 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2267 bar->dragging = Qnil;
2270 /* Clicks on the handle are always reported as occuring at the top of
2271 the handle. */
2272 if (emacs_event->part == scroll_bar_handle)
2273 emacs_event->x = bar->start;
2274 else
2275 XSET (emacs_event->x, Lisp_Int, y);
2277 XSET (emacs_event->y, Lisp_Int, top_range);
2281 /* Handle some mouse motion while someone is dragging the scroll bar.
2283 This may be called from a signal handler, so we have to ignore GC
2284 mark bits. */
2285 static void
2286 x_scroll_bar_note_movement (bar, event)
2287 struct scroll_bar *bar;
2288 XEvent *event;
2290 last_mouse_movement_time = event->xmotion.time;
2292 mouse_moved = 1;
2293 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2295 /* If we're dragging the bar, display it. */
2296 if (! GC_NILP (bar->dragging))
2298 /* Where should the handle be now? */
2299 int new_start = event->xmotion.y - XINT (bar->dragging);
2301 if (new_start != XINT (bar->start))
2303 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2305 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2309 /* Call XQueryPointer so we'll get an event the next time the mouse
2310 moves and we can see *still* on the same position. */
2312 int dummy;
2314 XQueryPointer (event->xmotion.display, event->xmotion.window,
2315 (Window *) &dummy, (Window *) &dummy,
2316 &dummy, &dummy, &dummy, &dummy,
2317 (unsigned int *) &dummy);
2321 /* Return information to the user about the current position of the mouse
2322 on the scroll bar. */
2323 static void
2324 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2325 FRAME_PTR *f;
2326 Lisp_Object *bar_window;
2327 enum scroll_bar_part *part;
2328 Lisp_Object *x, *y;
2329 unsigned long *time;
2331 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2332 int win_x, win_y;
2334 BLOCK_INPUT;
2336 /* Get the mouse's position relative to the scroll bar window, and
2337 report that. */
2339 Window dummy_window;
2340 int dummy_coord;
2341 unsigned int dummy_mask;
2343 if (! XQueryPointer (x_current_display,
2344 SCROLL_BAR_X_WINDOW (bar),
2346 /* Root, child, root x and root y. */
2347 &dummy_window, &dummy_window,
2348 &dummy_coord, &dummy_coord,
2350 /* Position relative to scroll bar. */
2351 &win_x, &win_y,
2353 /* Mouse buttons and modifier keys. */
2354 &dummy_mask))
2356 *f = 0;
2357 goto done;
2362 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2363 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2365 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2367 if (! NILP (bar->dragging))
2368 win_y -= XINT (bar->dragging);
2370 if (win_y < 0)
2371 win_y = 0;
2372 if (win_y > top_range)
2373 win_y = top_range;
2375 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2376 *bar_window = bar->window;
2378 if (! NILP (bar->dragging))
2379 *part = scroll_bar_handle;
2380 else if (win_y < XINT (bar->start))
2381 *part = scroll_bar_above_handle;
2382 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2383 *part = scroll_bar_handle;
2384 else
2385 *part = scroll_bar_below_handle;
2387 XSET (*x, Lisp_Int, win_y);
2388 XSET (*y, Lisp_Int, top_range);
2389 *time = last_mouse_movement_time;
2392 mouse_moved = 0;
2393 last_mouse_scroll_bar = Qnil;
2395 done:
2396 UNBLOCK_INPUT;
2400 /* The screen has been cleared so we may have changed foreground or
2401 background colors, and the scroll bars may need to be redrawn.
2402 Clear out the scroll bars, and ask for expose events, so we can
2403 redraw them. */
2405 x_scroll_bar_clear (f)
2406 FRAME_PTR f;
2408 Lisp_Object bar;
2410 for (bar = FRAME_SCROLL_BARS (f);
2411 XTYPE (bar) == Lisp_Vector;
2412 bar = XSCROLL_BAR (bar)->next)
2413 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2414 0, 0, 0, 0, True);
2419 /* The main X event-reading loop - XTread_socket. */
2421 /* Timestamp of enter window event. This is only used by XTread_socket,
2422 but we have to put it out here, since static variables within functions
2423 sometimes don't work. */
2424 static Time enter_timestamp;
2426 /* This holds the state XLookupString needs to implement dead keys
2427 and other tricks known as "compose processing". _X Window System_
2428 says that a portable program can't use this, but Stephen Gildea assures
2429 me that letting the compiler initialize it to zeros will work okay.
2431 This must be defined outside of XTread_socket, for the same reasons
2432 given for enter_timestamp, above. */
2433 static XComposeStatus compose_status;
2435 /* Communication with window managers. */
2436 Atom Xatom_wm_protocols;
2438 /* Kinds of protocol things we may receive. */
2439 Atom Xatom_wm_take_focus;
2440 Atom Xatom_wm_save_yourself;
2441 Atom Xatom_wm_delete_window;
2443 /* Other WM communication */
2444 Atom Xatom_wm_configure_denied; /* When our config request is denied */
2445 Atom Xatom_wm_window_moved; /* When the WM moves us. */
2447 /* Window manager communication. */
2448 Atom Xatom_wm_change_state;
2450 /* Record the last 100 characters stored
2451 to help debug the loss-of-chars-during-GC problem. */
2452 int temp_index;
2453 short temp_buffer[100];
2455 /* Read events coming from the X server.
2456 This routine is called by the SIGIO handler.
2457 We return as soon as there are no more events to be read.
2459 Events representing keys are stored in buffer BUFP,
2460 which can hold up to NUMCHARS characters.
2461 We return the number of characters stored into the buffer,
2462 thus pretending to be `read'.
2464 WAITP is nonzero if we should block until input arrives.
2465 EXPECTED is nonzero if the caller knows input is available. */
2468 XTread_socket (sd, bufp, numchars, waitp, expected)
2469 register int sd;
2470 register struct input_event *bufp;
2471 register int numchars;
2472 int waitp;
2473 int expected;
2475 int count = 0;
2476 int nbytes = 0;
2477 int mask;
2478 int items_pending; /* How many items are in the X queue. */
2479 XEvent event;
2480 struct frame *f;
2481 int event_found;
2482 int prefix;
2483 Lisp_Object part;
2485 if (x_input_blocked)
2487 x_pending_input = 1;
2488 return -1;
2491 x_pending_input = 0;
2492 BLOCK_INPUT;
2494 if (numchars <= 0)
2495 abort (); /* Don't think this happens. */
2497 #ifdef FIOSNBIO
2498 /* If available, Xlib uses FIOSNBIO to make the socket
2499 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2500 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2501 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2502 fcntl (fileno (stdin), F_SETFL, 0);
2503 #endif /* ! defined (FIOSNBIO) */
2505 #ifndef SIGIO
2506 #ifndef HAVE_SELECT
2507 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2509 extern int read_alarm_should_throw;
2510 read_alarm_should_throw = 1;
2511 XPeekEvent (XDISPLAY &event);
2512 read_alarm_should_throw = 0;
2514 #endif /* HAVE_SELECT */
2515 #endif /* SIGIO */
2517 while (XStuffPending () != 0)
2519 XNextEvent (XDISPLAY &event);
2520 event_found = 1;
2522 switch (event.type)
2524 #ifdef HAVE_X11
2525 case ClientMessage:
2527 if (event.xclient.message_type == Xatom_wm_protocols
2528 && event.xclient.format == 32)
2530 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2532 f = x_window_to_frame (event.xclient.window);
2533 if (f)
2534 x_focus_on_frame (f);
2535 /* Not certain about handling scroll bars here */
2537 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2539 /* Save state modify the WM_COMMAND property to
2540 something which can reinstate us. This notifies
2541 the session manager, who's looking for such a
2542 PropertyNotify. Can restart processing when
2543 a keyboard or mouse event arrives. */
2544 if (numchars > 0)
2548 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2550 struct frame *f = x_window_to_frame (event.xclient.window);
2552 if (f)
2553 if (numchars > 0)
2558 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2561 else if (event.xclient.message_type == Xatom_wm_window_moved)
2563 int new_x, new_y;
2565 new_x = event.xclient.data.s[0];
2566 new_y = event.xclient.data.s[1];
2569 break;
2571 #ifdef NEW_SELECTIONS
2572 case SelectionNotify:
2573 x_handle_selection_notify (&event);
2574 break;
2575 #endif
2577 case SelectionClear: /* Someone has grabbed ownership. */
2578 #ifdef NEW_SELECTIONS
2580 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2582 if (numchars == 0)
2583 abort ();
2585 bufp->kind = selection_clear_event;
2586 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2587 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2588 SELECTION_EVENT_TIME (bufp) = eventp->time;
2589 bufp++;
2591 count += 1;
2592 numchars -= 1;
2594 #else
2595 x_disown_selection (event.xselectionclear.window,
2596 event.xselectionclear.selection,
2597 event.xselectionclear.time);
2598 #endif
2599 break;
2601 case SelectionRequest: /* Someone wants our selection. */
2602 #ifdef NEW_SELECTIONS
2604 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2606 if (numchars == 0)
2607 abort ();
2609 bufp->kind = selection_request_event;
2610 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2611 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2612 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2613 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2614 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2615 SELECTION_EVENT_TIME (bufp) = eventp->time;
2616 bufp++;
2618 count += 1;
2619 numchars -= 1;
2621 #else
2622 x_answer_selection_request (event);
2623 #endif
2624 break;
2626 case PropertyNotify:
2627 #ifdef NEW_SELECTIONS
2628 x_handle_property_notify (&event);
2629 #else
2630 /* If we're being told about a root window property, then it's
2631 a cut buffer change. */
2632 if (event.xproperty.window == ROOT_WINDOW)
2633 x_invalidate_cut_buffer_cache (&event.xproperty);
2635 /* Otherwise, we're probably handling an incremental
2636 selection transmission. */
2637 else
2639 /* If we were to do this synchronously, there'd be no worry
2640 about re-selecting. */
2641 x_send_incremental (event);
2643 #endif
2644 break;
2646 case Expose:
2647 f = x_window_to_frame (event.xexpose.window);
2648 if (f)
2650 if (f->async_visible == 0)
2652 f->async_visible = 1;
2653 f->async_iconified = 0;
2654 SET_FRAME_GARBAGED (f);
2656 else
2658 dumprectangle (x_window_to_frame (event.xexpose.window),
2659 event.xexpose.x, event.xexpose.y,
2660 event.xexpose.width, event.xexpose.height);
2663 else
2665 struct scroll_bar *bar
2666 = x_window_to_scroll_bar (event.xexpose.window);
2668 if (bar)
2669 x_scroll_bar_expose (bar, &event);
2671 break;
2673 case GraphicsExpose: /* This occurs when an XCopyArea's
2674 source area was obscured or not
2675 available.*/
2676 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2677 if (f)
2679 dumprectangle (f,
2680 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2681 event.xgraphicsexpose.width,
2682 event.xgraphicsexpose.height);
2684 break;
2686 case NoExpose: /* This occurs when an XCopyArea's
2687 source area was completely
2688 available */
2689 break;
2690 #else /* ! defined (HAVE_X11) */
2691 case ExposeWindow:
2692 if (event.subwindow != 0)
2693 break; /* duplicate event */
2694 f = x_window_to_frame (event.window);
2695 if (event.window == f->display.x->icon_desc)
2697 refreshicon (f);
2698 f->async_iconified = 1;
2700 if (event.window == FRAME_X_WINDOW (f))
2702 /* Say must check all windows' needs_exposure flags. */
2703 expose_all_windows = 1;
2704 f->display.x->needs_exposure = 1;
2705 f->async_visible = 1;
2707 break;
2709 case ExposeRegion:
2710 if (event.subwindow != 0)
2711 break; /* duplicate event */
2712 f = x_window_to_frame (event.window);
2713 if (event.window == f->display.x->icon_desc)
2715 refreshicon (f);
2716 break;
2718 /* If window already needs full redraw, ignore this rectangle. */
2719 if (expose_all_windows && f->display.x->needs_exposure)
2720 break;
2721 /* Put the event on the queue of rectangles to redraw. */
2722 if (enqueue_event (&event, &x_expose_queue))
2723 /* If it is full, we can't record the rectangle,
2724 so redraw this entire window. */
2726 /* Say must check all windows' needs_exposure flags. */
2727 expose_all_windows = 1;
2728 f->display.x->needs_exposure = 1;
2730 break;
2732 case ExposeCopy:
2733 /* This should happen only when we are expecting it,
2734 in x_read_exposes. */
2735 abort ();
2736 #endif /* ! defined (HAVE_X11) */
2738 #ifdef HAVE_X11
2739 case UnmapNotify:
2740 f = x_window_to_frame (event.xunmap.window);
2741 if (f) /* F may no longer exist if
2742 the frame was deleted. */
2744 /* While a frame is unmapped, display generation is
2745 disabled; you don't want to spend time updating a
2746 display that won't ever be seen. */
2747 f->async_visible = 0;
2749 break;
2751 case MapNotify:
2752 f = x_window_to_frame (event.xmap.window);
2753 if (f)
2755 f->async_visible = 1;
2756 f->async_iconified = 0;
2758 /* wait_reading_process_input will notice this and update
2759 the frame's display structures. */
2760 SET_FRAME_GARBAGED (f);
2762 break;
2764 /* Turn off processing if we become fully obscured. */
2765 case VisibilityNotify:
2766 break;
2768 #else /* ! defined (HAVE_X11) */
2769 case UnmapWindow:
2770 f = x_window_to_frame (event.window);
2771 if (event.window == f->display.x->icon_desc)
2772 f->async_iconified = 0;
2773 if (event.window == FRAME_X_WINDOW (f))
2774 f->async_visible = 0;
2775 break;
2776 #endif /* ! defined (HAVE_X11) */
2778 #ifdef HAVE_X11
2779 case KeyPress:
2780 f = x_window_to_frame (event.xkey.window);
2782 if (f != 0)
2784 KeySym keysym;
2785 char copy_buffer[80];
2786 int modifiers;
2788 event.xkey.state |= extra_keyboard_modifiers;
2789 modifiers = event.xkey.state;
2791 /* Some keyboards generate different characters
2792 depending on the state of the meta key, in an attempt
2793 to support non-English typists. It would be nice to
2794 keep this functionality somehow, but for now, we will
2795 just clear the meta-key flag to get the 'pure' character. */
2796 event.xkey.state &= ~Mod1Mask;
2798 /* This will have to go some day... */
2799 nbytes =
2800 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2801 &compose_status);
2803 /* Strip off the vendor-specific keysym bit, and take a shot
2804 at recognizing the codes. HP servers have extra keysyms
2805 that fit into the MiscFunctionKey category. */
2806 keysym &= ~(1<<28);
2808 if (numchars > 1)
2810 if ((keysym >= XK_BackSpace && keysym <= XK_Escape)
2811 || keysym == XK_Delete
2812 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2813 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
2814 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2815 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
2817 if (temp_index == sizeof temp_buffer / sizeof (short))
2818 temp_index = 0;
2819 temp_buffer[temp_index++] = keysym;
2820 bufp->kind = non_ascii_keystroke;
2821 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2822 XSET (bufp->frame_or_window, Lisp_Frame, f);
2823 bufp->modifiers = x_convert_modifiers (modifiers);
2824 bufp->timestamp = event.xkey.time;
2825 bufp++;
2826 count++;
2827 numchars--;
2829 else if (numchars > nbytes)
2831 register int i;
2833 for (i = 0; i < nbytes; i++)
2835 if (temp_index == sizeof temp_buffer / sizeof (short))
2836 temp_index = 0;
2837 temp_buffer[temp_index++] = copy_buffer[i];
2838 bufp->kind = ascii_keystroke;
2839 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2840 XSET (bufp->frame_or_window, Lisp_Frame, f);
2841 bufp->modifiers = x_convert_modifiers (modifiers);
2842 bufp->timestamp = event.xkey.time;
2843 bufp++;
2846 count += nbytes;
2847 numchars -= nbytes;
2849 else
2850 abort ();
2852 else
2853 abort ();
2855 break;
2856 #else /* ! defined (HAVE_X11) */
2857 case KeyPressed:
2859 register char *where_mapping;
2861 f = x_window_to_frame (event.window);
2862 /* Ignore keys typed on icon windows. */
2863 if (f != 0 && event.window == f->display.x->icon_desc)
2864 break;
2865 where_mapping = XLookupMapping (&event, &nbytes);
2866 /* Nasty fix for arrow keys */
2867 if (!nbytes && IsCursorKey (event.detail & 0xff))
2869 switch (event.detail & 0xff)
2871 case KC_CURSOR_LEFT:
2872 where_mapping = "\002";
2873 break;
2874 case KC_CURSOR_RIGHT:
2875 where_mapping = "\006";
2876 break;
2877 case KC_CURSOR_UP:
2878 where_mapping = "\020";
2879 break;
2880 case KC_CURSOR_DOWN:
2881 where_mapping = "\016";
2882 break;
2884 nbytes = 1;
2886 if (numchars - nbytes > 0)
2888 register int i;
2890 for (i = 0; i < nbytes; i++)
2892 bufp->kind = ascii_keystroke;
2893 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2894 XSET (bufp->time, Lisp_Int, event.xkey.time);
2895 XSET (bufp->frame_or_window, Lisp_Frame, f);
2896 bufp++;
2898 count += nbytes;
2899 numchars -= nbytes;
2902 break;
2903 #endif /* ! defined (HAVE_X11) */
2905 #ifdef HAVE_X11
2907 /* Here's a possible interpretation of the whole
2908 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
2909 FocusIn event, you have to get a FocusOut event before you
2910 relinquish the focus. If you haven't received a FocusIn event,
2911 then a mere LeaveNotify is enough to free you. */
2913 case EnterNotify:
2914 f = x_window_to_frame (event.xcrossing.window);
2916 if (event.xcrossing.focus) /* Entered Window */
2918 /* Avoid nasty pop/raise loops. */
2919 if (f && (!(f->auto_raise)
2920 || !(f->auto_lower)
2921 || (event.xcrossing.time - enter_timestamp) > 500))
2923 x_new_focus_frame (f);
2924 enter_timestamp = event.xcrossing.time;
2927 else if (f == x_focus_frame)
2928 x_new_focus_frame (0);
2930 break;
2932 case FocusIn:
2933 f = x_window_to_frame (event.xfocus.window);
2934 if (event.xfocus.detail != NotifyPointer)
2935 x_focus_event_frame = f;
2936 if (f)
2937 x_new_focus_frame (f);
2938 break;
2941 case LeaveNotify:
2942 f = x_window_to_frame (event.xcrossing.window);
2944 if (event.xcrossing.focus)
2946 if (! x_focus_event_frame)
2947 x_new_focus_frame (0);
2948 else
2949 x_new_focus_frame (f);
2951 else
2953 if (f == x_focus_event_frame)
2954 x_focus_event_frame = 0;
2955 if (f == x_focus_frame)
2956 x_new_focus_frame (0);
2958 break;
2960 case FocusOut:
2961 f = x_window_to_frame (event.xfocus.window);
2962 if (event.xfocus.detail != NotifyPointer
2963 && f == x_focus_event_frame)
2964 x_focus_event_frame = 0;
2965 if (f && f == x_focus_frame)
2966 x_new_focus_frame (0);
2967 break;
2969 #else /* ! defined (HAVE_X11) */
2971 case EnterWindow:
2972 if ((event.detail & 0xFF) == 1)
2973 break; /* Coming from our own subwindow */
2974 if (event.subwindow != 0)
2975 break; /* Entering our own subwindow. */
2978 f = x_window_to_frame (event.window);
2979 x_mouse_frame = f;
2981 x_new_focus_frame (f);
2983 break;
2985 case LeaveWindow:
2986 if ((event.detail & 0xFF) == 1)
2987 break; /* Entering our own subwindow */
2988 if (event.subwindow != 0)
2989 break; /* Leaving our own subwindow. */
2991 x_mouse_frame = 0;
2992 if (x_focus_frame == 0
2993 && x_input_frame != 0
2994 && x_input_frame == x_window_to_frame (event.window)
2995 && event.window == FRAME_X_WINDOW (x_input_frame))
2997 f = x_input_frame;
2998 x_input_frame = 0;
2999 if (f)
3000 frame_unhighlight (f);
3002 break;
3003 #endif /* ! defined (HAVE_X11) */
3005 #ifdef HAVE_X11
3006 case MotionNotify:
3008 f = x_window_to_frame (event.xmotion.window);
3009 if (f)
3010 note_mouse_movement (f, &event.xmotion);
3011 else
3013 struct scroll_bar *bar =
3014 x_window_to_scroll_bar (event.xmotion.window);
3016 if (bar)
3017 x_scroll_bar_note_movement (bar, &event);
3020 break;
3022 case ConfigureNotify:
3023 f = x_window_to_frame (event.xconfigure.window);
3024 if (f)
3026 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3027 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3029 /* Even if the number of character rows and columns has
3030 not changed, the font size may have changed, so we need
3031 to check the pixel dimensions as well. */
3032 if (columns != f->width
3033 || rows != f->height
3034 || event.xconfigure.width != f->display.x->pixel_width
3035 || event.xconfigure.height != f->display.x->pixel_height)
3037 change_frame_size (f, rows, columns, 0, 1);
3038 SET_FRAME_GARBAGED (f);
3041 f->display.x->pixel_width = event.xconfigure.width;
3042 f->display.x->pixel_height = event.xconfigure.height;
3043 f->display.x->left_pos = event.xconfigure.x;
3044 f->display.x->top_pos = event.xconfigure.y;
3046 break;
3048 case ButtonPress:
3049 case ButtonRelease:
3051 /* If we decide we want to generate an event to be seen
3052 by the rest of Emacs, we put it here. */
3053 struct input_event emacs_event;
3054 emacs_event.kind = no_event;
3056 f = x_window_to_frame (event.xbutton.window);
3057 if (f)
3059 if (!x_focus_frame || (f == x_focus_frame))
3060 construct_mouse_click (&emacs_event,
3061 &event, f);
3063 else
3065 struct scroll_bar *bar =
3066 x_window_to_scroll_bar (event.xbutton.window);
3068 if (bar)
3069 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3072 if (numchars >= 1 && emacs_event.kind != no_event)
3074 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3075 bufp++;
3076 count++;
3077 numchars--;
3080 break;
3082 #else /* ! defined (HAVE_X11) */
3083 case ButtonPressed:
3084 case ButtonReleased:
3085 f = x_window_to_frame (event.window);
3086 if (f)
3088 if (event.window == f->display.x->icon_desc)
3090 x_make_frame_visible (f);
3092 if (warp_mouse_on_deiconify)
3093 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3094 break;
3096 if (event.window == FRAME_X_WINDOW (f))
3098 if (f->auto_raise)
3099 x_raise_frame (f);
3102 enqueue_event (&event, &x_mouse_queue);
3103 if (numchars >= 2)
3105 bufp->kind = ascii_keystroke;
3106 bufp->code = (char) 'X' & 037; /* C-x */
3107 XSET (bufp->frame_or_window, Lisp_Frame, f);
3108 XSET (bufp->time, Lisp_Int, event.xkey.time);
3109 bufp++;
3111 bufp->kind = ascii_keystroke;
3112 bufp->code = (char) 0; /* C-@ */
3113 XSET (bufp->frame_or_window, Lisp_Frame, f);
3114 XSET (bufp->time, Lisp_Int, event.xkey.time);
3115 bufp++;
3117 count += 2;
3118 numchars -= 2;
3120 break;
3121 #endif /* ! defined (HAVE_X11) */
3123 #ifdef HAVE_X11
3125 case CirculateNotify:
3126 break;
3127 case CirculateRequest:
3128 break;
3130 #endif /* ! defined (HAVE_X11) */
3132 case MappingNotify:
3133 /* Someone has changed the keyboard mapping - update the
3134 local cache. */
3135 switch (event.xmapping.request)
3137 case MappingModifier:
3138 x_find_modifier_meanings ();
3139 /* This is meant to fall through. */
3140 case MappingKeyboard:
3141 XRefreshKeyboardMapping (&event.xmapping);
3143 break;
3145 default:
3146 break;
3150 #if 0
3151 #ifdef HAVE_SELECT
3152 if (expected && ! event_found)
3154 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3155 there is an EOF condition; in other words, that X has died.
3156 Act as if there had been a hangup. */
3158 int fd = ConnectionNumber (x_current_display);
3159 int mask = 1 << fd;
3161 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3162 (EMACS_TIME) 0)
3163 && !XStuffPending ())
3164 kill (getpid (), SIGHUP);
3166 #endif /* ! defined (HAVE_SELECT) */
3167 #endif /* ! 0 */
3169 #ifndef HAVE_X11
3170 if (updating_frame == 0)
3171 x_do_pending_expose ();
3172 #endif
3174 UNBLOCK_INPUT;
3175 return count;
3178 #ifndef HAVE_X11
3179 /* Read and process only Expose events
3180 until we get an ExposeCopy event; then return.
3181 This is used in insert/delete line.
3182 We assume input is already blocked. */
3184 static void
3185 x_read_exposes ()
3187 struct frame *f;
3188 XKeyPressedEvent event;
3190 while (1)
3192 /* while there are more events*/
3193 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3194 switch (event.type)
3196 case ExposeWindow:
3197 if (event.subwindow != 0)
3198 break; /* duplicate event */
3199 f = x_window_to_frame (event.window);
3200 if (event.window == f->display.x->icon_desc)
3202 refreshicon (f);
3203 break;
3205 if (event.window == FRAME_X_WINDOW (f))
3207 expose_all_windows = 1;
3208 f->display.x->needs_exposure = 1;
3209 break;
3211 break;
3213 case ExposeRegion:
3214 if (event.subwindow != 0)
3215 break; /* duplicate event */
3216 f = x_window_to_frame (event.window);
3217 if (event.window == f->display.x->icon_desc)
3219 refreshicon (f);
3220 break;
3222 /* If window already needs full redraw, ignore this rectangle. */
3223 if (expose_all_windows && f->display.x->needs_exposure)
3224 break;
3225 /* Put the event on the queue of rectangles to redraw. */
3226 if (enqueue_event (&event, &x_expose_queue))
3227 /* If it is full, we can't record the rectangle,
3228 so redraw this entire window. */
3230 /* Say must check all windows' needs_exposure flags. */
3231 expose_all_windows = 1;
3232 f->display.x->needs_exposure = 1;
3234 break;
3236 case ExposeCopy:
3237 return;
3241 #endif /* HAVE_X11 */
3244 /* Drawing the cursor. */
3247 /* Draw a hollow box cursor. Don't change the inside of the box. */
3249 static void
3250 x_draw_box (f)
3251 struct frame *f;
3253 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3254 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3255 int width = FONT_WIDTH (f->display.x->font);
3256 int height = FONT_HEIGHT (f->display.x->font);
3258 #ifdef HAVE_X11
3259 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3260 f->display.x->cursor_gc,
3261 left, top, width - 1, height - 1);
3262 #else /* ! defined (HAVE_X11) */
3263 XPixSet (FRAME_X_WINDOW (f),
3264 left, top, width, 1,
3265 f->display.x->cursor_pixel);
3267 XPixSet (FRAME_X_WINDOW (f),
3268 left, top, 1, height,
3269 f->display.x->cursor_pixel);
3271 XPixSet (FRAME_X_WINDOW (f),
3272 left+width-1, top, 1, height,
3273 f->display.x->cursor_pixel);
3275 XPixSet (FRAME_X_WINDOW (f),
3276 left, top+height-1, width, 1,
3277 f->display.x->cursor_pixel);
3278 #endif /* ! defined (HAVE_X11) */
3281 /* Clear the cursor of frame F to background color,
3282 and mark the cursor as not shown.
3283 This is used when the text where the cursor is
3284 is about to be rewritten. */
3286 static void
3287 clear_cursor (f)
3288 struct frame *f;
3290 int mask;
3292 if (! FRAME_VISIBLE_P (f)
3293 || f->phys_cursor_x < 0)
3294 return;
3296 #ifdef HAVE_X11
3297 x_display_cursor (f, 0);
3298 #else /* ! defined (HAVE_X11) */
3299 XPixSet (FRAME_X_WINDOW (f),
3300 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3301 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3302 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3303 f->display.x->background_pixel);
3304 #endif /* ! defined (HAVE_X11) */
3305 f->phys_cursor_x = -1;
3308 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3309 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3310 glyph drawn. */
3312 static void
3313 x_draw_single_glyph (f, row, column, glyph, highlight)
3314 struct frame *f;
3315 int row, column;
3316 GLYPH glyph;
3317 int highlight;
3319 dumpglyphs (f,
3320 CHAR_TO_PIXEL_COL (f, column),
3321 CHAR_TO_PIXEL_ROW (f, row),
3322 &glyph, 1, highlight, f->display.x->font);
3325 static void
3326 x_display_bar_cursor (f, on)
3327 struct frame *f;
3328 int on;
3330 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3332 /* This is pointless on invisible frames, and dangerous on garbaged
3333 frames; in the latter case, the frame may be in the midst of
3334 changing its size, and curs_x and curs_y may be off the frame. */
3335 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3336 return;
3338 if (! on && f->phys_cursor_x < 0)
3339 return;
3341 /* If we're not updating, then we want to use the current frame's
3342 cursor position, not our local idea of where the cursor ought to be. */
3343 if (f != updating_frame)
3345 curs_x = FRAME_CURSOR_X (f);
3346 curs_y = FRAME_CURSOR_Y (f);
3349 /* If there is anything wrong with the current cursor state, remove it. */
3350 if (f->phys_cursor_x >= 0
3351 && (!on
3352 || f->phys_cursor_x != curs_x
3353 || f->phys_cursor_y != curs_y
3354 || f->display.x->current_cursor != bar_cursor))
3356 /* Erase the cursor by redrawing the character underneath it. */
3357 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3358 f->phys_cursor_glyph,
3359 current_glyphs->highlight[f->phys_cursor_y]);
3360 f->phys_cursor_x = -1;
3363 /* If we now need a cursor in the new place or in the new form, do it so. */
3364 if (on
3365 && (f->phys_cursor_x < 0
3366 || (f->display.x->current_cursor != bar_cursor)))
3368 f->phys_cursor_glyph
3369 = ((current_glyphs->enable[curs_y]
3370 && curs_x < current_glyphs->used[curs_y])
3371 ? current_glyphs->glyphs[curs_y][curs_x]
3372 : SPACEGLYPH);
3373 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3374 f->display.x->cursor_gc,
3375 CHAR_TO_PIXEL_COL (f, curs_x),
3376 CHAR_TO_PIXEL_ROW (f, curs_y),
3377 1, FONT_HEIGHT (f->display.x->font));
3379 f->phys_cursor_x = curs_x;
3380 f->phys_cursor_y = curs_y;
3382 f->display.x->current_cursor = bar_cursor;
3385 if (updating_frame != f)
3386 XFlushQueue ();
3390 /* Turn the displayed cursor of frame F on or off according to ON.
3391 If ON is nonzero, where to put the cursor is specified
3392 by F->cursor_x and F->cursor_y. */
3394 static void
3395 x_display_box_cursor (f, on)
3396 struct frame *f;
3397 int on;
3399 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3401 /* This is pointless on invisible frames, and dangerous on garbaged
3402 frames; in the latter case, the frame may be in the midst of
3403 changing its size, and curs_x and curs_y may be off the frame. */
3404 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3405 return;
3407 /* If cursor is off and we want it off, return quickly. */
3408 if (!on && f->phys_cursor_x < 0)
3409 return;
3411 /* If we're not updating, then we want to use the current frame's
3412 cursor position, not our local idea of where the cursor ought to be. */
3413 if (f != updating_frame)
3415 curs_x = FRAME_CURSOR_X (f);
3416 curs_y = FRAME_CURSOR_Y (f);
3419 /* If cursor is currently being shown and we don't want it to be
3420 or it is in the wrong place,
3421 or we want a hollow box and it's not so, (pout!)
3422 erase it. */
3423 if (f->phys_cursor_x >= 0
3424 && (!on
3425 || f->phys_cursor_x != curs_x
3426 || f->phys_cursor_y != curs_y
3427 || (f->display.x->current_cursor != hollow_box_cursor
3428 && (f != x_highlight_frame))))
3430 /* Erase the cursor by redrawing the character underneath it. */
3431 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3432 f->phys_cursor_glyph,
3433 current_glyphs->highlight[f->phys_cursor_y]);
3434 f->phys_cursor_x = -1;
3437 /* If we want to show a cursor,
3438 or we want a box cursor and it's not so,
3439 write it in the right place. */
3440 if (on
3441 && (f->phys_cursor_x < 0
3442 || (f->display.x->current_cursor != filled_box_cursor
3443 && f == x_highlight_frame)))
3445 f->phys_cursor_glyph
3446 = ((current_glyphs->enable[curs_y]
3447 && curs_x < current_glyphs->used[curs_y])
3448 ? current_glyphs->glyphs[curs_y][curs_x]
3449 : SPACEGLYPH);
3450 if (f != x_highlight_frame)
3452 x_draw_box (f);
3453 f->display.x->current_cursor = hollow_box_cursor;
3455 else
3457 x_draw_single_glyph (f, curs_y, curs_x,
3458 f->phys_cursor_glyph, 2);
3459 f->display.x->current_cursor = filled_box_cursor;
3462 f->phys_cursor_x = curs_x;
3463 f->phys_cursor_y = curs_y;
3466 if (updating_frame != f)
3467 XFlushQueue ();
3470 x_display_cursor (f, on)
3471 struct frame *f;
3472 int on;
3474 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3475 x_display_box_cursor (f, on);
3476 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3477 x_display_bar_cursor (f, on);
3478 else
3479 /* Those are the only two we have implemented! */
3480 abort ();
3483 /* Icons. */
3485 /* Refresh bitmap kitchen sink icon for frame F
3486 when we get an expose event for it. */
3488 refreshicon (f)
3489 struct frame *f;
3491 #ifdef HAVE_X11
3492 /* Normally, the window manager handles this function. */
3493 #else /* ! defined (HAVE_X11) */
3494 int mask;
3496 if (f->display.x->icon_bitmap_flag)
3497 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3498 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3499 icon_bitmap, GXcopy, AllPlanes);
3500 else
3502 extern struct frame *selected_frame;
3503 struct Lisp_String *str;
3504 unsigned char *string;
3506 string
3507 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3509 if (f->display.x->icon_label != string)
3511 f->display.x->icon_label = string;
3512 XChangeWindow (f->display.x->icon_desc,
3513 XQueryWidth (string, icon_font_info->id) + 10,
3514 icon_font_info->height + 10);
3517 XText (f->display.x->icon_desc, 5, 5, string,
3518 str->size, icon_font_info->id,
3519 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3521 XFlushQueue ();
3522 #endif /* ! defined (HAVE_X11) */
3525 /* Make the x-window of frame F use the gnu icon bitmap. */
3528 x_bitmap_icon (f)
3529 struct frame *f;
3531 int mask;
3532 Window icon_window;
3534 if (FRAME_X_WINDOW (f) == 0)
3535 return 1;
3537 #ifdef HAVE_X11
3538 if (icon_bitmap)
3539 XFreePixmap (x_current_display, icon_bitmap);
3541 icon_bitmap =
3542 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3543 gnu_bits, gnu_width, gnu_height);
3544 x_wm_set_icon_pixmap (f, icon_bitmap);
3545 f->display.x->icon_bitmap_flag = 1;
3546 #else /* ! defined (HAVE_X11) */
3547 if (f->display.x->icon_desc)
3549 XClearIconWindow (FRAME_X_WINDOW (f));
3550 XDestroyWindow (f->display.x->icon_desc);
3553 icon_window = XCreateWindow (f->display.x->parent_desc,
3554 0, 0, sink_width, sink_height,
3555 2, WhitePixmap, (Pixmap) NULL);
3557 if (icon_window == 0)
3558 return 1;
3560 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3561 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3563 f->display.x->icon_desc = icon_window;
3564 f->display.x->icon_bitmap_flag = 1;
3566 if (icon_bitmap == 0)
3567 icon_bitmap
3568 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3569 #endif /* ! defined (HAVE_X11) */
3571 return 0;
3575 /* Make the x-window of frame F use a rectangle with text. */
3578 x_text_icon (f, icon_name)
3579 struct frame *f;
3580 char *icon_name;
3582 #ifndef HAVE_X11
3583 int mask;
3584 int width;
3585 Window icon_window;
3586 char *X_DefaultValue;
3587 Bitmap b1;
3589 #ifndef WhitePixel
3590 #define WhitePixel 1
3591 #endif /* WhitePixel */
3593 #ifndef BlackPixel
3594 #define BlackPixel 0
3595 #endif /* BlackPixel */
3596 #endif /* HAVE_X11 */
3598 if (FRAME_X_WINDOW (f) == 0)
3599 return 1;
3601 #ifdef HAVE_X11
3602 if (icon_name)
3603 f->display.x->icon_label = icon_name;
3604 else
3605 if (! f->display.x->icon_label)
3606 f->display.x->icon_label = " *emacs* ";
3608 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3609 (char *) f->display.x->icon_label);
3611 f->display.x->icon_bitmap_flag = 0;
3612 x_wm_set_icon_pixmap (f, 0);
3613 #else /* ! defined (HAVE_X11) */
3614 if (icon_font_info == 0)
3615 icon_font_info
3616 = XGetFont (XGetDefault (XDISPLAY
3617 (char *) XSTRING (Vinvocation_name)->data,
3618 "BodyFont"));
3620 if (f->display.x->icon_desc)
3622 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3623 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3626 if (icon_name)
3627 f->display.x->icon_label = (unsigned char *) icon_name;
3628 else
3629 if (! f->display.x->icon_label)
3630 f->display.x->icon_label = XSTRING (f->name)->data;
3632 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3633 icon_window = XCreateWindow (f->display.x->parent_desc,
3634 f->display.x->left_pos,
3635 f->display.x->top_pos,
3636 width + 10, icon_font_info->height + 10,
3637 2, BlackPixmap, WhitePixmap);
3639 if (icon_window == 0)
3640 return 1;
3642 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3643 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3645 f->display.x->icon_desc = icon_window;
3646 f->display.x->icon_bitmap_flag = 0;
3647 f->display.x->icon_label = 0;
3648 #endif /* ! defined (HAVE_X11) */
3650 return 0;
3653 /* Handling X errors. */
3655 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3656 X server's connection, or an error reported via the X protocol. */
3658 static SIGTYPE
3659 x_connection_closed ()
3661 if (_Xdebug)
3662 abort ();
3664 shut_down_emacs (0);
3666 exit (70);
3669 /* An X error handler which prints an error message and then kills
3670 Emacs. This is what's normally installed as Xlib's handler for
3671 protocol errors. */
3672 static int
3673 x_error_quitter (display, error)
3674 Display *display;
3675 XErrorEvent *error;
3677 char buf[256];
3679 /* Note that there is no real way portable across R3/R4 to get the
3680 original error handler. */
3682 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3683 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3684 buf, error->request_code);
3686 /* While we're testing Emacs 19, we'll just dump core whenever we
3687 get an X error, so we can figure out why it happened. */
3688 abort ();
3690 x_connection_closed ();
3693 /* A handler for X IO errors which prints an error message and then
3694 kills Emacs. This is what is always installed as Xlib's handler
3695 for I/O errors. */
3696 static int
3697 x_io_error_quitter (display)
3698 Display *display;
3700 fprintf (stderr, "Connection to X server %s lost.\n",
3701 XDisplayName (DisplayString (display)));
3703 /* While we're testing Emacs 19, we'll just dump core whenever we
3704 get an X error, so we can figure out why it happened. */
3705 abort ();
3707 x_connection_closed ();
3710 /* A buffer for storing X error messages. */
3711 static char (*x_caught_error_message)[200];
3713 /* An X error handler which stores the error message in
3714 x_caught_error_message. This is what's installed when
3715 x_catch_errors is in effect. */
3716 static int
3717 x_error_catcher (display, error)
3718 Display *display;
3719 XErrorEvent *error;
3721 XGetErrorText (display, error->error_code,
3722 *x_caught_error_message, sizeof (*x_caught_error_message));
3726 /* Begin trapping X errors.
3728 After calling this function, X protocol errors no longer cause
3729 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3731 Calling x_check_errors signals an Emacs error if an X error has
3732 occurred since the last call to x_catch_errors or x_check_errors.
3734 Calling x_uncatch_errors resumes the normal error handling. */
3736 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3738 void
3739 x_catch_errors ()
3741 /* Make sure any errors from previous requests have been dealt with. */
3742 XSync (x_current_display, False);
3744 /* Set up the error buffer. */
3745 x_caught_error_message =
3746 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
3747 (*x_caught_error_message)[0] = '\0';
3749 /* Install our little error handler. */
3750 XHandleError (x_error_catcher);
3753 /* If any X protocol errors have arrived since the last call to
3754 x_catch_errors or x_check_errors, signal an Emacs error using
3755 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3756 void
3757 x_check_errors (format)
3758 char *format;
3760 /* Make sure to catch any errors incurred so far. */
3761 XSync (x_current_display, False);
3763 if ((*x_caught_error_message)[0])
3765 char buf[256];
3767 sprintf (buf, format, *x_caught_error_message);
3768 free (x_caught_error_message);
3770 x_uncatch_errors ();
3771 error (buf);
3775 void
3776 x_uncatch_errors ()
3778 free (x_caught_error_message);
3779 XHandleError (x_error_quitter);
3782 #if 0
3783 static unsigned int x_wire_count;
3784 x_trace_wire ()
3786 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3788 #endif /* ! 0 */
3791 /* Changing the font of the frame. */
3793 /* Set the font of the x-window specified by frame F
3794 to the font named NEWNAME. This is safe to use
3795 even before F has an actual x-window. */
3797 #ifdef HAVE_X11
3799 /* A table of all the fonts we have already loaded. */
3800 static XFontStruct **x_font_table;
3802 /* The current capacity of x_font_table. */
3803 static int x_font_table_size;
3805 /* The number of fonts actually stored in x_font_table.
3806 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3807 0 <= n_fonts <= x_font_table_size. */
3808 static int n_fonts;
3810 x_new_font (f, fontname)
3811 struct frame *f;
3812 register char *fontname;
3814 XFontStruct *temp;
3815 int already_loaded;
3816 int n_matching_fonts;
3817 XFontStruct *font_info;
3818 char **font_names;
3820 /* Get a list of all the fonts that match this name. Once we
3821 have a list of matching fonts, we compare them against the fonts
3822 we already have by comparing font ids. */
3823 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3824 1024, &n_matching_fonts,
3825 &font_info);
3826 /* If the server couldn't find any fonts whose named matched fontname,
3827 return an error code. */
3828 if (n_matching_fonts == 0)
3829 return 1;
3831 /* See if we've already loaded a matching font. */
3833 int i, j;
3835 already_loaded = 0;
3836 for (i = 0; i < n_fonts; i++)
3837 for (j = 0; j < n_matching_fonts; j++)
3838 if (x_font_table[i]->fid == font_info[j].fid)
3840 already_loaded = i;
3841 goto found_font;
3844 found_font:
3846 /* If we have, just return it from the table. */
3847 if (already_loaded)
3848 f->display.x->font = x_font_table[already_loaded];
3850 /* Otherwise, load the font and add it to the table. */
3851 else
3853 XFontStruct *font;
3855 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3856 if (! font)
3857 return 1;
3859 /* Do we need to create the table? */
3860 if (x_font_table_size == 0)
3862 x_font_table_size = 16;
3863 x_font_table
3864 = (XFontStruct **) xmalloc (x_font_table_size
3865 * sizeof (x_font_table[0]));
3867 /* Do we need to grow the table? */
3868 else if (n_fonts >= x_font_table_size)
3870 x_font_table_size *= 2;
3871 x_font_table
3872 = (XFontStruct **) xrealloc (x_font_table,
3873 (x_font_table_size
3874 * sizeof (x_font_table[0])));
3877 f->display.x->font = x_font_table[n_fonts++] = font;
3880 /* Free the information from XListFontsWithInfo. The data
3881 we actually retain comes from XLoadQueryFont. */
3882 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3884 /* Now make the frame display the given font. */
3885 if (FRAME_X_WINDOW (f) != 0)
3887 XSetFont (x_current_display, f->display.x->normal_gc,
3888 f->display.x->font->fid);
3889 XSetFont (x_current_display, f->display.x->reverse_gc,
3890 f->display.x->font->fid);
3891 XSetFont (x_current_display, f->display.x->cursor_gc,
3892 f->display.x->font->fid);
3894 x_set_window_size (f, f->width, f->height);
3897 return 0;
3899 #else /* ! defined (HAVE_X11) */
3900 x_new_font (f, newname)
3901 struct frame *f;
3902 register char *newname;
3904 FONT_TYPE *temp;
3905 int mask;
3907 temp = XGetFont (newname);
3908 if (temp == (FONT_TYPE *) 0)
3909 return 1;
3911 if (f->display.x->font)
3912 XLoseFont (f->display.x->font);
3914 f->display.x->font = temp;
3916 if (FRAME_X_WINDOW (f) != 0)
3917 x_set_window_size (f, f->width, f->height);
3919 return 0;
3921 #endif /* ! defined (HAVE_X11) */
3923 /* X Window sizes and positions. */
3925 x_calc_absolute_position (f)
3926 struct frame *f;
3928 #ifdef HAVE_X11
3929 if (f->display.x->left_pos < 0)
3930 f->display.x->left_pos
3931 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
3933 if (f->display.x->top_pos < 0)
3934 f->display.x->top_pos
3935 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
3936 #else /* ! defined (HAVE_X11) */
3937 WINDOWINFO_TYPE parentinfo;
3939 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
3941 if (f->display.x->left_pos < 0)
3942 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
3943 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
3945 if (f->display.x->top_pos < 0)
3946 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
3947 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
3948 #endif /* ! defined (HAVE_X11) */
3951 x_set_offset (f, xoff, yoff)
3952 struct frame *f;
3953 register int xoff, yoff;
3955 f->display.x->top_pos = yoff;
3956 f->display.x->left_pos = xoff;
3957 x_calc_absolute_position (f);
3959 BLOCK_INPUT;
3960 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
3961 f->display.x->left_pos, f->display.x->top_pos);
3962 #ifdef HAVE_X11
3963 x_wm_set_size_hint (f, 0);
3964 #endif /* ! defined (HAVE_X11) */
3965 UNBLOCK_INPUT;
3968 /* Call this to change the size of frame F's x-window. */
3970 x_set_window_size (f, cols, rows)
3971 struct frame *f;
3972 int cols, rows;
3974 int pixelwidth, pixelheight;
3975 int mask;
3977 BLOCK_INPUT;
3979 check_frame_size (f, &rows, &cols);
3980 f->display.x->vertical_scroll_bar_extra =
3981 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3982 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
3983 : 0);
3984 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
3985 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
3987 #ifdef HAVE_X11
3988 x_wm_set_size_hint (f, 0);
3989 #endif /* ! defined (HAVE_X11) */
3990 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
3992 /* Now, strictly speaking, we can't be sure that this is accurate,
3993 but the window manager will get around to dealing with the size
3994 change request eventually, and we'll hear how it went when the
3995 ConfigureNotify event gets here.
3997 We could just not bother storing any of this information here,
3998 and let the ConfigureNotify event set everything up, but that
3999 might be kind of confusing to the lisp code, since size changes
4000 wouldn't be reported in the frame parameters until some random
4001 point in the future when the ConfigureNotify event arrives. */
4002 change_frame_size (f, rows, cols, 0, 0);
4003 PIXEL_WIDTH (f) = pixelwidth;
4004 PIXEL_HEIGHT (f) = pixelheight;
4006 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4007 receive in the ConfigureNotify event; if we get what we asked
4008 for, then the event won't cause the screen to become garbaged, so
4009 we have to make sure to do it here. */
4010 SET_FRAME_GARBAGED (f);
4012 XFlushQueue ();
4013 UNBLOCK_INPUT;
4016 #ifndef HAVE_X11
4017 x_set_resize_hint (f)
4018 struct frame *f;
4020 XSetResizeHint (FRAME_X_WINDOW (f),
4021 2 * f->display.x->internal_border_width,
4022 2 * f->display.x->internal_border_width,
4023 FONT_WIDTH (f->display.x->font),
4024 FONT_HEIGHT (f->display.x->font));
4026 #endif /* HAVE_X11 */
4028 /* Mouse warping, focus shifting, raising and lowering. */
4030 x_set_mouse_position (f, x, y)
4031 struct frame *f;
4032 int x, y;
4034 int pix_x, pix_y;
4036 x_raise_frame (f);
4038 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4039 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4041 if (pix_x < 0) pix_x = 0;
4042 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4044 if (pix_y < 0) pix_y = 0;
4045 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4047 BLOCK_INPUT;
4049 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4050 UNBLOCK_INPUT;
4053 #ifdef HAVE_X11
4054 x_focus_on_frame (f)
4055 struct frame *f;
4057 x_raise_frame (f);
4058 #if 0
4059 /* I don't think that the ICCCM allows programs to do things like this
4060 without the interaction of the window manager. Whatever you end up
4061 doing with this code, do it to x_unfocus_frame too. */
4062 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4063 RevertToPointerRoot, CurrentTime);
4064 #endif /* ! 0 */
4067 x_unfocus_frame (f)
4068 struct frame *f;
4070 #if 0
4071 /* Look at the remarks in x_focus_on_frame. */
4072 if (x_focus_frame == f)
4073 XSetInputFocus (x_current_display, PointerRoot,
4074 RevertToPointerRoot, CurrentTime);
4075 #endif /* ! 0 */
4078 #endif /* ! defined (HAVE_X11) */
4080 /* Raise frame F. */
4082 x_raise_frame (f)
4083 struct frame *f;
4085 if (f->async_visible)
4087 BLOCK_INPUT;
4088 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4089 XFlushQueue ();
4090 UNBLOCK_INPUT;
4094 /* Lower frame F. */
4096 x_lower_frame (f)
4097 struct frame *f;
4099 if (f->async_visible)
4101 BLOCK_INPUT;
4102 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4103 XFlushQueue ();
4104 UNBLOCK_INPUT;
4108 static void
4109 XTframe_raise_lower (f, raise)
4110 FRAME_PTR f;
4111 int raise;
4113 if (raise)
4114 x_raise_frame (f);
4115 else
4116 x_lower_frame (f);
4120 /* Change from withdrawn state to mapped state. */
4122 x_make_frame_visible (f)
4123 struct frame *f;
4125 int mask;
4127 BLOCK_INPUT;
4129 if (! FRAME_VISIBLE_P (f))
4131 #ifdef HAVE_X11
4132 if (! EQ (Vx_no_window_manager, Qt))
4133 x_wm_set_window_state (f, NormalState);
4135 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4136 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4137 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4138 #else /* ! defined (HAVE_X11) */
4139 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4140 if (f->display.x->icon_desc != 0)
4141 XUnmapWindow (f->display.x->icon_desc);
4143 /* Handled by the MapNotify event for X11 */
4144 f->async_visible = 1;
4145 f->async_iconified = 0;
4147 /* NOTE: this may cause problems for the first frame. */
4148 XTcursor_to (0, 0);
4149 #endif /* ! defined (HAVE_X11) */
4152 XFlushQueue ();
4154 UNBLOCK_INPUT;
4157 /* Change from mapped state to withdrawn state. */
4159 x_make_frame_invisible (f)
4160 struct frame *f;
4162 int mask;
4164 if (! f->async_visible)
4165 return;
4167 BLOCK_INPUT;
4169 #ifdef HAVE_X11R4
4171 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4172 DefaultScreen (x_current_display)))
4174 UNBLOCK_INPUT_RESIGNAL;
4175 error ("can't notify window manager of window withdrawl");
4178 #else /* ! defined (HAVE_X11R4) */
4179 #ifdef HAVE_X11
4181 /* Tell the window manager what we're going to do. */
4182 if (! EQ (Vx_no_window_manager, Qt))
4184 XEvent unmap;
4186 unmap.xunmap.type = UnmapNotify;
4187 unmap.xunmap.window = FRAME_X_WINDOW (f);
4188 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4189 unmap.xunmap.from_configure = False;
4190 if (! XSendEvent (x_current_display,
4191 DefaultRootWindow (x_current_display),
4192 False,
4193 SubstructureRedirectMask|SubstructureNotifyMask,
4194 &unmap))
4196 UNBLOCK_INPUT_RESIGNAL;
4197 error ("can't notify window manager of withdrawal");
4201 /* Unmap the window ourselves. Cheeky! */
4202 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4204 #else /* ! defined (HAVE_X11) */
4206 XUnmapWindow (FRAME_X_WINDOW (f));
4207 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4208 if (f->display.x->icon_desc != 0)
4209 XUnmapWindow (f->display.x->icon_desc);
4211 #endif /* ! defined (HAVE_X11) */
4212 #endif /* ! defined (HAVE_X11R4) */
4214 XFlushQueue ();
4215 UNBLOCK_INPUT;
4218 /* Change window state from mapped to iconified. */
4220 x_iconify_frame (f)
4221 struct frame *f;
4223 int mask;
4225 if (f->async_iconified)
4226 return;
4228 BLOCK_INPUT;
4230 #ifdef HAVE_X11
4231 /* Since we don't know which revision of X we're running, we'll use both
4232 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4234 /* X11R4: send a ClientMessage to the window manager using the
4235 WM_CHANGE_STATE type. */
4237 XEvent message;
4239 message.xclient.window = FRAME_X_WINDOW (f);
4240 message.xclient.type = ClientMessage;
4241 message.xclient.message_type = Xatom_wm_change_state;
4242 message.xclient.format = 32;
4243 message.xclient.data.l[0] = IconicState;
4245 if (! XSendEvent (x_current_display,
4246 DefaultRootWindow (x_current_display),
4247 False,
4248 SubstructureRedirectMask | SubstructureNotifyMask,
4249 &message))
4251 UNBLOCK_INPUT_RESIGNAL;
4252 error ("Can't notify window manager of iconification.");
4256 /* X11R3: set the initial_state field of the window manager hints to
4257 IconicState. */
4258 x_wm_set_window_state (f, IconicState);
4260 f->async_iconified = 1;
4261 #else /* ! defined (HAVE_X11) */
4262 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4264 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4265 if (f->display.x->icon_desc != 0)
4267 XMapWindow (XDISPLAY f->display.x->icon_desc);
4268 refreshicon (f);
4270 #endif /* ! defined (HAVE_X11) */
4272 XFlushQueue ();
4273 UNBLOCK_INPUT;
4276 /* Destroy the X window of frame F. */
4278 x_destroy_window (f)
4279 struct frame *f;
4281 BLOCK_INPUT;
4283 if (f->display.x->icon_desc != 0)
4284 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4285 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4286 XFlushQueue ();
4288 free (f->display.x);
4289 f->display.x = 0;
4290 if (f == x_focus_frame)
4291 x_focus_frame = 0;
4292 if (f == x_highlight_frame)
4293 x_highlight_frame = 0;
4295 UNBLOCK_INPUT;
4298 /* Manage event queues for X10. */
4300 #ifndef HAVE_X11
4302 /* Manage event queues.
4304 This code is only used by the X10 support.
4306 We cannot leave events in the X queue and get them when we are ready
4307 because X does not provide a subroutine to get only a certain kind
4308 of event but not block if there are no queued events of that kind.
4310 Therefore, we must examine events as they come in and copy events
4311 of certain kinds into our private queues.
4313 All ExposeRegion events are put in x_expose_queue.
4314 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4317 /* Write the event *P_XREP into the event queue *QUEUE.
4318 If the queue is full, do nothing, but return nonzero. */
4321 enqueue_event (p_xrep, queue)
4322 register XEvent *p_xrep;
4323 register struct event_queue *queue;
4325 int newindex = queue->windex + 1;
4326 if (newindex == EVENT_BUFFER_SIZE)
4327 newindex = 0;
4328 if (newindex == queue->rindex)
4329 return -1;
4330 queue->xrep[queue->windex] = *p_xrep;
4331 queue->windex = newindex;
4332 return 0;
4335 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4336 If *QUEUE is empty, do nothing and return 0. */
4339 dequeue_event (p_xrep, queue)
4340 register XEvent *p_xrep;
4341 register struct event_queue *queue;
4343 if (queue->windex == queue->rindex)
4344 return 0;
4345 *p_xrep = queue->xrep[queue->rindex++];
4346 if (queue->rindex == EVENT_BUFFER_SIZE)
4347 queue->rindex = 0;
4348 return 1;
4351 /* Return the number of events buffered in *QUEUE. */
4354 queue_event_count (queue)
4355 register struct event_queue *queue;
4357 int tem = queue->windex - queue->rindex;
4358 if (tem >= 0)
4359 return tem;
4360 return EVENT_BUFFER_SIZE + tem;
4363 /* Return nonzero if mouse input is pending. */
4366 mouse_event_pending_p ()
4368 return queue_event_count (&x_mouse_queue);
4370 #endif /* HAVE_X11 */
4372 /* Setting window manager hints. */
4374 #ifdef HAVE_X11
4376 x_wm_set_size_hint (f, prompting)
4377 struct frame *f;
4378 long prompting;
4380 XSizeHints size_hints;
4381 Window window = FRAME_X_WINDOW (f);
4383 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
4385 flexlines = f->height;
4387 size_hints.x = f->display.x->left_pos;
4388 size_hints.y = f->display.x->top_pos;
4389 size_hints.height = PIXEL_HEIGHT (f);
4390 size_hints.width = PIXEL_WIDTH (f);
4391 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4392 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4393 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4394 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4397 int base_width, base_height;
4399 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4400 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4403 int min_rows = 0, min_cols = 0;
4404 check_frame_size (f, &min_rows, &min_cols);
4406 /* The window manager uses the base width hints to calculate the
4407 current number of rows and columns in the frame while
4408 resizing; min_width and min_height aren't useful for this
4409 purpose, since they might not give the dimensions for a
4410 zero-row, zero-column frame.
4412 We use the base_width and base_height members if we have
4413 them; otherwise, we set the min_width and min_height members
4414 to the size for a zero x zero frame. */
4416 #ifdef HAVE_X11R4
4417 size_hints.flags |= PBaseSize;
4418 size_hints.base_width = base_width;
4419 size_hints.base_height = base_height;
4420 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4421 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4422 #else
4423 size_hints.min_width = base_width;
4424 size_hints.min_height = base_height;
4425 #endif
4430 if (prompting)
4431 size_hints.flags |= prompting;
4432 else
4434 XSizeHints hints; /* Sometimes I hate X Windows... */
4436 XGetNormalHints (x_current_display, window, &hints);
4437 if (hints.flags & PSize)
4438 size_hints.flags |= PSize;
4439 if (hints.flags & PPosition)
4440 size_hints.flags |= PPosition;
4441 if (hints.flags & USPosition)
4442 size_hints.flags |= USPosition;
4443 if (hints.flags & USSize)
4444 size_hints.flags |= USSize;
4447 #ifdef HAVE_X11R4
4448 XSetWMNormalHints (x_current_display, window, &size_hints);
4449 #else
4450 XSetNormalHints (x_current_display, window, &size_hints);
4451 #endif
4454 /* Used for IconicState or NormalState */
4455 x_wm_set_window_state (f, state)
4456 struct frame *f;
4457 int state;
4459 Window window = FRAME_X_WINDOW (f);
4461 f->display.x->wm_hints.flags |= StateHint;
4462 f->display.x->wm_hints.initial_state = state;
4464 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4467 x_wm_set_icon_pixmap (f, icon_pixmap)
4468 struct frame *f;
4469 Pixmap icon_pixmap;
4471 Window window = FRAME_X_WINDOW (f);
4473 if (icon_pixmap)
4475 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4476 f->display.x->wm_hints.flags |= IconPixmapHint;
4478 else
4479 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4481 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4484 x_wm_set_icon_position (f, icon_x, icon_y)
4485 struct frame *f;
4486 int icon_x, icon_y;
4488 Window window = FRAME_X_WINDOW (f);
4490 f->display.x->wm_hints.flags |= IconPositionHint;
4491 f->display.x->wm_hints.icon_x = icon_x;
4492 f->display.x->wm_hints.icon_y = icon_y;
4494 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4498 /* Initialization. */
4500 void
4501 x_term_init (display_name)
4502 char *display_name;
4504 Lisp_Object frame;
4505 char *defaultvalue;
4506 #ifdef F_SETOWN
4507 extern int old_fcntl_owner;
4508 #endif /* ! defined (F_SETOWN) */
4510 x_focus_frame = x_highlight_frame = 0;
4512 x_current_display = XOpenDisplay (display_name);
4513 if (x_current_display == 0)
4514 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4515 display_name);
4517 #ifdef HAVE_X11
4519 int hostname_size = 256;
4521 hostname = (char *) xmalloc (hostname_size);
4523 #if 0
4524 XSetAfterFunction (x_current_display, x_trace_wire);
4525 #endif /* ! 0 */
4527 /* Try to get the host name; if the buffer is too short, try
4528 again. Apparently, the only indication gethostname gives of
4529 whether the buffer was large enough is the presence or absence
4530 of a '\0' in the string. Eech. */
4531 for (;;)
4533 gethostname (hostname, hostname_size - 1);
4534 hostname[hostname_size - 1] = '\0';
4536 /* Was the buffer large enough for gethostname to store the '\0'? */
4537 if (strlen (hostname) < hostname_size - 1)
4538 break;
4540 hostname_size <<= 1;
4541 hostname = (char *) xrealloc (hostname, hostname_size);
4543 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4544 + strlen (hostname)
4545 + 2);
4546 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4549 /* Figure out which modifier bits mean what. */
4550 x_find_modifier_meanings ();
4552 /* Get the scroll bar cursor. */
4553 x_vertical_scroll_bar_cursor
4554 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4556 #if 0
4557 /* Watch for PropertyNotify events on the root window; we use them
4558 to figure out when to invalidate our cache of the cut buffers. */
4559 x_watch_cut_buffer_cache ();
4560 #endif
4562 if (ConnectionNumber (x_current_display) != 0)
4564 dup2 (ConnectionNumber (x_current_display), 0);
4566 #ifndef SYSV_STREAMS
4567 /* Streams somehow keeps track of which descriptor number
4568 is being used to talk to X. So it is not safe to substitute
4569 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4570 close (ConnectionNumber (x_current_display));
4571 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4572 * check the def of the macro;
4573 * it is a genuine lvalue */
4574 #endif /* SYSV_STREAMS */
4577 #endif /* ! defined (HAVE_X11) */
4579 #ifdef F_SETOWN
4580 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4581 #ifdef F_SETOWN_SOCK_NEG
4582 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4583 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4584 fcntl (0, F_SETOWN, getpid ());
4585 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4586 #endif /* ! defined (F_SETOWN) */
4588 #ifdef SIGIO
4589 init_sigio ();
4590 #endif /* ! defined (SIGIO) */
4592 /* Must use interrupt input because we cannot otherwise
4593 arrange for C-g to be noticed immediately.
4594 We cannot connect it to SIGINT. */
4595 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4597 expose_all_windows = 0;
4599 clear_frame_hook = XTclear_frame;
4600 clear_end_of_line_hook = XTclear_end_of_line;
4601 ins_del_lines_hook = XTins_del_lines;
4602 change_line_highlight_hook = XTchange_line_highlight;
4603 insert_glyphs_hook = XTinsert_glyphs;
4604 write_glyphs_hook = XTwrite_glyphs;
4605 delete_glyphs_hook = XTdelete_glyphs;
4606 ring_bell_hook = XTring_bell;
4607 reset_terminal_modes_hook = XTreset_terminal_modes;
4608 set_terminal_modes_hook = XTset_terminal_modes;
4609 update_begin_hook = XTupdate_begin;
4610 update_end_hook = XTupdate_end;
4611 set_terminal_window_hook = XTset_terminal_window;
4612 read_socket_hook = XTread_socket;
4613 cursor_to_hook = XTcursor_to;
4614 reassert_line_highlight_hook = XTreassert_line_highlight;
4615 mouse_position_hook = XTmouse_position;
4616 frame_rehighlight_hook = XTframe_rehighlight;
4617 frame_raise_lower_hook = XTframe_raise_lower;
4618 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4619 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4620 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4621 judge_scroll_bars_hook = XTjudge_scroll_bars;
4623 scroll_region_ok = 1; /* we'll scroll partial frames */
4624 char_ins_del_ok = 0; /* just as fast to write the line */
4625 line_ins_del_ok = 1; /* we'll just blt 'em */
4626 fast_clear_end_of_line = 1; /* X does this well */
4627 memory_below_frame = 0; /* we don't remember what scrolls
4628 off the bottom */
4629 baud_rate = 19200;
4631 /* Note that there is no real way portable across R3/R4 to get the
4632 original error handler. */
4633 XHandleError (x_error_quitter);
4634 XHandleIOError (x_io_error_quitter);
4636 /* Disable Window Change signals; they are handled by X events. */
4637 #ifdef SIGWINCH
4638 signal (SIGWINCH, SIG_DFL);
4639 #endif /* ! defined (SIGWINCH) */
4641 signal (SIGPIPE, x_connection_closed);
4644 void
4645 syms_of_xterm ()
4647 staticpro (&last_mouse_scroll_bar);
4649 #endif /* ! defined (HAVE_X11) */
4650 #endif /* ! defined (HAVE_X_WINDOWS) */