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