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