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