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