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