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