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