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