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