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