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