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