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