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