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