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