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