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