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