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