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