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