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