]> code.delx.au - gnu-emacs/blob - src/xterm.c
3e80d64253e90675ae60a687b5cce8598d448c91
[gnu-emacs] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993 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 /* Serious problems:
21
22 Kludge: dup2 is used to put the X-connection socket into desc # 0
23 so that wait_reading_process_input will wait for it in place of
24 actual terminal input.
25
26 */
27
28 #define NEW_SELECTIONS
29
30 /* On 4.3 these lose if they come after xterm.h. */
31 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
32 /* Putting these at the beginning seems to be standard for other .c files. */
33 #include <stdio.h>
34 #include <signal.h>
35
36 #include "config.h"
37
38 #ifdef HAVE_X_WINDOWS
39
40 #include "lisp.h"
41 #include "blockinput.h"
42
43 /* This may include sys/types.h, and that somehow loses
44 if this is not done before the other system files. */
45 #include "xterm.h"
46 #include <X11/cursorfont.h>
47
48 #ifndef USG
49 /* Load sys/types.h if not already loaded.
50 In some systems loading it twice is suicidal. */
51 #ifndef makedev
52 #include <sys/types.h>
53 #endif /* makedev */
54 #endif /* USG */
55
56 #ifdef BSD
57 #include <sys/ioctl.h>
58 #include <strings.h>
59 #else /* ! defined (BSD) */
60 #ifndef VMS
61 #include <string.h>
62 #endif
63 #endif /* ! defined (BSD) */
64
65 #include "systty.h"
66 #include "systime.h"
67
68 #include <fcntl.h>
69 #include <ctype.h>
70 #include <errno.h>
71 #include <setjmp.h>
72 #include <sys/stat.h>
73 #include <sys/param.h>
74
75 #include "dispextern.h"
76 #include "termhooks.h"
77 #include "termopts.h"
78 #include "termchar.h"
79 #if 0
80 #include "sink.h"
81 #include "sinkmask.h"
82 #endif /* ! 0 */
83 #include "gnu.h"
84 #include "frame.h"
85 #include "disptab.h"
86 #include "buffer.h"
87 #include "window.h"
88
89 #ifdef HAVE_X11
90 #define XMapWindow XMapRaised /* Raise them when mapping. */
91 #else /* ! defined (HAVE_X11) */
92 #include <X/Xkeyboard.h>
93 /*#include <X/Xproto.h> */
94 #endif /* ! defined (HAVE_X11) */
95
96 #ifdef FD_SET
97 /* We could get this from param.h, but better not to depend on finding that.
98 And better not to risk that it might define other symbols used in this
99 file. */
100 #ifdef FD_SETSIZE
101 #define MAXDESC FD_SETSIZE
102 #else
103 #define MAXDESC 64
104 #endif
105 #define SELECT_TYPE fd_set
106 #else /* no FD_SET */
107 #define MAXDESC 32
108 #define SELECT_TYPE int
109
110 /* Define the macros to access a single-int bitmap of descriptors. */
111 #define FD_SET(n, p) (*(p) |= (1 << (n)))
112 #define FD_CLR(n, p) (*(p) &= ~(1 << (n)))
113 #define FD_ISSET(n, p) (*(p) & (1 << (n)))
114 #define FD_ZERO(p) (*(p) = 0)
115 #endif /* no FD_SET */
116
117 /* For sending Meta-characters. Do we need this? */
118 #define METABIT 0200
119
120 #define min(a,b) ((a)<(b) ? (a) : (b))
121 #define max(a,b) ((a)>(b) ? (a) : (b))
122
123 /* Nonzero means we must reprint all windows
124 because 1) we received an ExposeWindow event
125 or 2) we received too many ExposeRegion events to record.
126
127 This is never needed under X11. */
128 static int expose_all_windows;
129
130 /* Nonzero means we must reprint all icon windows. */
131
132 static int expose_all_icons;
133
134 #ifndef HAVE_X11
135 /* ExposeRegion events, when received, are copied into this queue
136 for later processing. */
137
138 static struct event_queue x_expose_queue;
139
140 /* ButtonPressed and ButtonReleased events, when received,
141 are copied into this queue for later processing. */
142
143 struct event_queue x_mouse_queue;
144 #endif /* HAVE_X11 */
145
146 #if defined (SIGIO) && defined (FIONREAD)
147 int BLOCK_INPUT_mask;
148 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
149
150 /* The id of a bitmap used for icon windows.
151 One such map is shared by all Emacs icon windows.
152 This is zero if we have not yet had a need to create the bitmap. */
153
154 static Bitmap icon_bitmap;
155
156 /* Font used for text icons. */
157
158 static FONT_TYPE *icon_font_info;
159
160 /* Stuff for dealing with the main icon title. */
161
162 extern Lisp_Object Vcommand_line_args;
163 char *hostname, *x_id_name;
164
165 /* This is the X connection that we are using. */
166
167 Display *x_current_display;
168
169 /* The cursor to use for vertical scroll bars on x_current_display. */
170 static Cursor x_vertical_scroll_bar_cursor;
171
172 /* Frame being updated by update_frame. This is declared in term.c.
173 This is set by update_begin and looked at by all the
174 XT functions. It is zero while not inside an update.
175 In that case, the XT functions assume that `selected_frame'
176 is the frame to apply to. */
177 extern struct frame *updating_frame;
178
179 /* The frame (if any) which has the X window that has keyboard focus.
180 Zero if none. This is examined by Ffocus_frame in frame.c. Note
181 that a mere EnterNotify event can set this; if you need to know the
182 last frame specified in a FocusIn or FocusOut event, use
183 x_focus_event_frame. */
184 struct frame *x_focus_frame;
185
186 /* The last frame mentioned in a FocusIn or FocusOut event. This is
187 separate from x_focus_frame, because whether or not LeaveNotify
188 events cause us to lose focus depends on whether or not we have
189 received a FocusIn event for it. */
190 struct frame *x_focus_event_frame;
191
192 /* The frame which currently has the visual highlight, and should get
193 keyboard input (other sorts of input have the frame encoded in the
194 event). It points to the X focus frame's selected window's
195 frame. It differs from x_focus_frame when we're using a global
196 minibuffer. */
197 static struct frame *x_highlight_frame;
198
199 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
200 mouse is moved to inside of frame when frame is de-iconified. */
201
202 static int warp_mouse_on_deiconify;
203
204 /* During an update, maximum vpos for ins/del line operations to affect. */
205
206 static int flexlines;
207
208 /* During an update, nonzero if chars output now should be highlighted. */
209
210 static int highlight;
211
212 /* Nominal cursor position -- where to draw output.
213 During an update, these are different from the cursor-box position. */
214
215 static int curs_x;
216 static int curs_y;
217
218 #ifdef HAVE_X11
219 /* `t' if a mouse button is depressed. */
220
221 extern Lisp_Object Vmouse_depressed;
222
223 /* Tells if a window manager is present or not. */
224
225 extern Lisp_Object Vx_no_window_manager;
226
227 /* Timestamp that we requested selection data was made. */
228 extern Time requestor_time;
229
230 /* ID of the window requesting selection data. */
231 extern Window requestor_window;
232
233 /* Nonzero enables some debugging for the X interface code. */
234 extern int _Xdebug;
235
236 #else /* ! defined (HAVE_X11) */
237
238 /* Bit patterns for the mouse cursor. */
239
240 short MouseCursor[] = {
241 0x0000, 0x0008, 0x0018, 0x0038,
242 0x0078, 0x00f8, 0x01f8, 0x03f8,
243 0x07f8, 0x00f8, 0x00d8, 0x0188,
244 0x0180, 0x0300, 0x0300, 0x0000};
245
246 short MouseMask[] = {
247 0x000c, 0x001c, 0x003c, 0x007c,
248 0x00fc, 0x01fc, 0x03fc, 0x07fc,
249 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
250 0x03cc, 0x0780, 0x0780, 0x0300};
251
252 static short grey_bits[] = {
253 0x0005, 0x000a, 0x0005, 0x000a};
254
255 static Pixmap GreyPixmap = 0;
256 #endif /* ! defined (HAVE_X11) */
257
258 /* From time to time we get info on an Emacs window, here. */
259
260 static WINDOWINFO_TYPE windowinfo;
261
262 extern int errno;
263
264 /* A mask of extra modifier bits to put into every keyboard char. */
265 extern int extra_keyboard_modifiers;
266
267 extern Display *XOpenDisplay ();
268 extern Window XCreateWindow ();
269
270 extern Cursor XCreateCursor ();
271 extern FONT_TYPE *XOpenFont ();
272
273 static void flashback ();
274
275 #ifndef HAVE_X11
276 static void dumpqueue ();
277 #endif /* HAVE_X11 */
278
279 void dumpborder ();
280 static int XTcursor_to ();
281 static int XTclear_end_of_line ();
282
283 \f
284 /* Starting and ending updates.
285
286 These hooks are called by update_frame at the beginning and end
287 of a frame update. We record in `updating_frame' the identity
288 of the frame being updated, so that the XT... functions do not
289 need to take a frame as argument. Most of the XT... functions
290 should never be called except during an update, the only exceptions
291 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
292
293 extern int mouse_track_top, mouse_track_left, mouse_track_width;
294
295 static
296 XTupdate_begin (f)
297 struct frame *f;
298 {
299 int mask;
300
301 if (f == 0)
302 abort ();
303
304 flexlines = f->height;
305 highlight = 0;
306
307 BLOCK_INPUT;
308 #ifndef HAVE_X11
309 dumpqueue ();
310 #endif /* HAVE_X11 */
311 UNBLOCK_INPUT;
312 }
313
314 #ifndef HAVE_X11
315 static void x_do_pending_expose ();
316 #endif
317
318 static
319 XTupdate_end (f)
320 struct frame *f;
321 {
322 int mask;
323
324 if (updating_frame == 0
325 || updating_frame != f)
326 abort ();
327
328 BLOCK_INPUT;
329 #ifndef HAVE_X11
330 dumpqueue ();
331 x_do_pending_expose ();
332 #endif /* HAVE_X11 */
333
334 x_display_cursor (f, 1);
335
336 XFlushQueue ();
337 UNBLOCK_INPUT;
338 }
339 \f
340 /* External interface to control of standout mode.
341 Call this when about to modify line at position VPOS
342 and not change whether it is highlighted. */
343
344 XTreassert_line_highlight (new, vpos)
345 int new, vpos;
346 {
347 highlight = new;
348 }
349
350 /* Call this when about to modify line at position VPOS
351 and change whether it is highlighted. */
352
353 static
354 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
355 int new_highlight, vpos, first_unused_hpos;
356 {
357 highlight = new_highlight;
358 XTcursor_to (vpos, 0);
359 XTclear_end_of_line (updating_frame->width);
360 }
361
362 /* This is used when starting Emacs and when restarting after suspend.
363 When starting Emacs, no X window is mapped. And nothing must be done
364 to Emacs's own window if it is suspended (though that rarely happens). */
365
366 static
367 XTset_terminal_modes ()
368 {
369 }
370
371 /* This is called when exiting or suspending Emacs.
372 Exiting will make the X-windows go away, and suspending
373 requires no action. */
374
375 static
376 XTreset_terminal_modes ()
377 {
378 /* XTclear_frame (); */
379 }
380 \f
381 /* Set the nominal cursor position of the frame.
382 This is where display update commands will take effect.
383 This does not affect the place where the cursor-box is displayed. */
384
385 static int
386 XTcursor_to (row, col)
387 register int row, col;
388 {
389 int mask;
390 int orow = row;
391
392 curs_x = col;
393 curs_y = row;
394
395 if (updating_frame == 0)
396 {
397 BLOCK_INPUT;
398 x_display_cursor (selected_frame, 1);
399 XFlushQueue ();
400 UNBLOCK_INPUT;
401 }
402 }
403 \f
404 /* Display a sequence of N glyphs found at GP.
405 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
406 HL is 1 if this text is highlighted, 2 if the cursor is on it.
407
408 FONT is the default font to use (for glyphs whose font-code is 0).
409
410 Since the display generation code is responsible for calling
411 compute_char_face and compute_glyph_face on everything it puts in
412 the display structure, we can assume that the face code on each
413 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
414 to which we can actually apply intern_face. */
415
416 #if 1
417 /* This is the multi-face code. */
418
419 static void
420 dumpglyphs (f, left, top, gp, n, hl)
421 struct frame *f;
422 int left, top;
423 register GLYPH *gp; /* Points to first GLYPH. */
424 register int n; /* Number of glyphs to display. */
425 int hl;
426 {
427 /* Holds characters to be displayed. */
428 char *buf = (char *) alloca (f->width * sizeof (*buf));
429 register char *cp; /* Steps through buf[]. */
430 register int tlen = GLYPH_TABLE_LENGTH;
431 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
432 Window window = FRAME_X_WINDOW (f);
433
434 while (n > 0)
435 {
436 /* Get the face-code of the next GLYPH. */
437 int cf, len;
438 int g = *gp;
439
440 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
441 cf = GLYPH_FACE (g);
442
443 /* Find the run of consecutive glyphs with the same face-code.
444 Extract their character codes into BUF. */
445 cp = buf;
446 while (n > 0)
447 {
448 g = *gp;
449 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
450 if (GLYPH_FACE (g) != cf)
451 break;
452
453 *cp++ = GLYPH_CHAR (g);
454 --n;
455 ++gp;
456 }
457
458 /* LEN gets the length of the run. */
459 len = cp - buf;
460
461 /* Now output this run of chars, with the font and pixel values
462 determined by the face code CF. */
463 {
464 struct face *face = FRAME_DEFAULT_FACE (f);
465 FONT_TYPE *font = FACE_FONT (face);
466 GC gc = FACE_GC (face);
467 int defaulted = 1;
468 int gc_temporary = 0;
469
470 /* First look at the face of the text itself. */
471 if (cf != 0)
472 {
473 /* The face codes on the glyphs must be valid indices into the
474 frame's face table. */
475 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
476 || FRAME_COMPUTED_FACES (f) [cf] == 0)
477 abort ();
478
479 if (cf == 1)
480 face = FRAME_MODE_LINE_FACE (f);
481 else
482 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
483 font = FACE_FONT (face);
484 gc = FACE_GC (face);
485 defaulted = 0;
486 }
487
488 /* Then comes the distinction between modeline and normal text. */
489 else if (hl == 0)
490 ;
491 else if (hl == 1)
492 {
493 face = FRAME_MODE_LINE_FACE (f);
494 font = FACE_FONT (face);
495 gc = FACE_GC (face);
496 defaulted = 0;
497 }
498
499 #define FACE_DEFAULT (~0)
500
501 /* Now override that if the cursor's on this character. */
502 if (hl == 2)
503 {
504 if (defaulted
505 || !face->font
506 || (int) face->font == FACE_DEFAULT)
507 {
508 gc = f->display.x->cursor_gc;
509 }
510 /* Cursor on non-default face: must merge. */
511 else
512 {
513 XGCValues xgcv;
514 unsigned long mask;
515
516 xgcv.background = f->display.x->cursor_pixel;
517 xgcv.foreground = f->display.x->cursor_foreground_pixel;
518 xgcv.font = face->font->fid;
519 xgcv.graphics_exposures = 0;
520 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
521 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
522 mask, &xgcv);
523 #if 0
524 if (face->stipple && face->stipple != FACE_DEFAULT)
525 XSetStipple (x_current_display, gc, face->stipple);
526 #endif
527 gc_temporary = 1;
528 }
529 }
530
531 if ((int) font == FACE_DEFAULT)
532 font = f->display.x->font;
533
534 XDrawImageString (x_current_display, window, gc,
535 left, top + FONT_BASE (font), buf, len);
536
537 if (gc_temporary)
538 XFreeGC (x_current_display, gc);
539
540 /* We should probably check for XA_UNDERLINE_POSITION and
541 XA_UNDERLINE_THICKNESS properties on the font, but let's
542 just get the thing working, and come back to that. */
543 {
544 int underline_position = 1;
545
546 if (font->descent <= underline_position)
547 underline_position = font->descent - 1;
548
549 if (face->underline)
550 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
551 FACE_GC (face),
552 left, (top
553 + FONT_BASE (font)
554 + underline_position),
555 len * FONT_WIDTH (font), 1);
556 }
557
558 left += len * FONT_WIDTH (font);
559 }
560 }
561 }
562 #endif /* 1 */
563
564 #if 0
565 /* This is the old single-face code. */
566
567 static void
568 dumpglyphs (f, left, top, gp, n, hl, font)
569 struct frame *f;
570 int left, top;
571 register GLYPH *gp; /* Points to first GLYPH. */
572 register int n; /* Number of glyphs to display. */
573 int hl;
574 FONT_TYPE *font;
575 {
576 register int len;
577 Window window = FRAME_X_WINDOW (f);
578 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
579 : (hl ? f->display.x->reverse_gc
580 : f->display.x->normal_gc));
581
582 if (sizeof (GLYPH) == sizeof (XChar2b))
583 XDrawImageString16 (x_current_display, window, drawing_gc,
584 left, top + FONT_BASE (font), (XChar2b *) gp, n);
585 else if (sizeof (GLYPH) == sizeof (unsigned char))
586 XDrawImageString (x_current_display, window, drawing_gc,
587 left, top + FONT_BASE (font), (char *) gp, n);
588 else
589 /* What size of glyph ARE you using? And does X have a function to
590 draw them? */
591 abort ();
592 }
593 #endif
594 \f
595 /* Output some text at the nominal frame cursor position.
596 Advance the cursor over the text.
597 Output LEN glyphs at START.
598
599 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
600 controls the pixel values used for foreground and background. */
601
602 static
603 XTwrite_glyphs (start, len)
604 register GLYPH *start;
605 int len;
606 {
607 register int temp_length;
608 int mask;
609 struct frame *f;
610
611 BLOCK_INPUT;
612
613 f = updating_frame;
614 if (f == 0)
615 {
616 f = selected_frame;
617 /* If not within an update,
618 output at the frame's visible cursor. */
619 curs_x = f->cursor_x;
620 curs_y = f->cursor_y;
621 }
622
623 dumpglyphs (f,
624 CHAR_TO_PIXEL_COL (f, curs_x),
625 CHAR_TO_PIXEL_ROW (f, curs_y),
626 start, len, highlight);
627
628 /* If we drew on top of the cursor, note that it is turned off. */
629 if (curs_y == f->phys_cursor_y
630 && curs_x <= f->phys_cursor_x
631 && curs_x + len > f->phys_cursor_x)
632 f->phys_cursor_x = -1;
633
634 if (updating_frame == 0)
635 {
636 f->cursor_x += len;
637 x_display_cursor (f, 1);
638 f->cursor_x -= len;
639 }
640 else
641 curs_x += len;
642
643 UNBLOCK_INPUT;
644 }
645 \f
646 /* Clear to the end of the line.
647 Erase the current text line from the nominal cursor position (inclusive)
648 to column FIRST_UNUSED (exclusive). The idea is that everything
649 from FIRST_UNUSED onward is already erased. */
650
651 static int
652 XTclear_end_of_line (first_unused)
653 register int first_unused;
654 {
655 struct frame *f = updating_frame;
656 int mask;
657
658 if (f == 0)
659 abort ();
660
661 if (curs_y < 0 || curs_y >= f->height)
662 return;
663 if (first_unused <= 0)
664 return;
665
666 if (first_unused >= f->width)
667 first_unused = f->width;
668
669 BLOCK_INPUT;
670
671 /* Notice if the cursor will be cleared by this operation. */
672 if (curs_y == f->phys_cursor_y
673 && curs_x <= f->phys_cursor_x
674 && f->phys_cursor_x < first_unused)
675 f->phys_cursor_x = -1;
676
677 #ifdef HAVE_X11
678 XClearArea (x_current_display, FRAME_X_WINDOW (f),
679 CHAR_TO_PIXEL_COL (f, curs_x),
680 CHAR_TO_PIXEL_ROW (f, curs_y),
681 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
682 FONT_HEIGHT (f->display.x->font), False);
683
684 #else /* ! defined (HAVE_X11) */
685 XPixSet (FRAME_X_WINDOW (f),
686 CHAR_TO_PIXEL_COL (f, curs_x),
687 CHAR_TO_PIXEL_ROW (f, curs_y),
688 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
689 FONT_HEIGHT (f->display.x->font),
690 f->display.x->background_pixel);
691 #endif /* ! defined (HAVE_X11) */
692
693 UNBLOCK_INPUT;
694 }
695
696 static
697 XTclear_frame ()
698 {
699 int mask;
700 struct frame *f = updating_frame;
701
702 if (f == 0)
703 f = selected_frame;
704
705 f->phys_cursor_x = -1; /* Cursor not visible. */
706 curs_x = 0; /* Nominal cursor position is top left. */
707 curs_y = 0;
708
709 BLOCK_INPUT;
710
711 XClear (FRAME_X_WINDOW (f));
712
713 /* We have to clear the scroll bars, too. If we have changed
714 colors or something like that, then they should be notified. */
715 x_scroll_bar_clear (f);
716
717 #ifndef HAVE_X11
718 dumpborder (f, 0);
719 #endif /* HAVE_X11 */
720
721 XFlushQueue ();
722 UNBLOCK_INPUT;
723 }
724 \f
725 /* Invert the middle quarter of the frame for .15 sec. */
726
727 /* We use the select system call to do the waiting, so we have to make sure
728 it's available. If it isn't, we just won't do visual bells. */
729 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
730
731 /* Subtract the `struct timeval' values X and Y,
732 storing the result in RESULT.
733 Return 1 if the difference is negative, otherwise 0. */
734
735 static int
736 timeval_subtract (result, x, y)
737 struct timeval *result, x, y;
738 {
739 /* Perform the carry for the later subtraction by updating y.
740 This is safer because on some systems
741 the tv_sec member is unsigned. */
742 if (x.tv_usec < y.tv_usec)
743 {
744 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
745 y.tv_usec -= 1000000 * nsec;
746 y.tv_sec += nsec;
747 }
748 if (x.tv_usec - y.tv_usec > 1000000)
749 {
750 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
751 y.tv_usec += 1000000 * nsec;
752 y.tv_sec -= nsec;
753 }
754
755 /* Compute the time remaining to wait. tv_usec is certainly positive. */
756 result->tv_sec = x.tv_sec - y.tv_sec;
757 result->tv_usec = x.tv_usec - y.tv_usec;
758
759 /* Return indication of whether the result should be considered negative. */
760 return x.tv_sec < y.tv_sec;
761 }
762
763 XTflash (f)
764 struct frame *f;
765 {
766 BLOCK_INPUT;
767
768 {
769 GC gc;
770
771 /* Create a GC that will use the GXxor function to flip foreground pixels
772 into background pixels. */
773 {
774 XGCValues values;
775
776 values.function = GXxor;
777 values.foreground = (f->display.x->foreground_pixel
778 ^ f->display.x->background_pixel);
779
780 gc = XCreateGC (x_current_display, FRAME_X_WINDOW (f),
781 GCFunction | GCForeground, &values);
782 }
783
784 {
785 int width = PIXEL_WIDTH (f);
786 int height = PIXEL_HEIGHT (f);
787
788 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
789 width/4, height/4, width/2, height/2);
790 XFlush (x_current_display);
791
792 {
793 struct timeval wakeup, now;
794
795 gettimeofday (&wakeup, (struct timezone *) 0);
796
797 /* Compute time to wait until, propagating carry from usecs. */
798 wakeup.tv_usec += 150000;
799 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
800 wakeup.tv_usec %= 1000000;
801
802 /* Keep waiting until past the time wakeup. */
803 while (1)
804 {
805 struct timeval timeout;
806
807 gettimeofday (&timeout, (struct timezone *)0);
808
809 /* In effect, timeout = wakeup - timeout.
810 Break if result would be negative. */
811 if (timeval_subtract (&timeout, wakeup, timeout))
812 break;
813
814 /* Try to wait that long--but we might wake up sooner. */
815 select (0, 0, 0, 0, &timeout);
816 }
817 }
818
819 XFillRectangle (x_current_display, FRAME_X_WINDOW (f), gc,
820 width/4, height/4, width/2, height/2);
821 XFreeGC (x_current_display, gc);
822 XFlush (x_current_display);
823 }
824 }
825
826 UNBLOCK_INPUT;
827 }
828
829 #endif
830
831
832 /* Make audible bell. */
833
834 #ifdef HAVE_X11
835 #define XRINGBELL XBell(x_current_display, 0)
836 #else /* ! defined (HAVE_X11) */
837 #define XRINGBELL XFeep(0);
838 #endif /* ! defined (HAVE_X11) */
839
840 XTring_bell ()
841 {
842 if (x_current_display == 0)
843 return;
844
845 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
846 if (visible_bell)
847 XTflash (selected_frame);
848 else
849 #endif
850 {
851 BLOCK_INPUT;
852 XRINGBELL;
853 XFlushQueue ();
854 UNBLOCK_INPUT;
855 }
856 }
857 \f
858 /* Insert and delete character.
859 These are not supposed to be used because we are supposed to turn
860 off the feature of using them. */
861
862 static
863 XTinsert_glyphs (start, len)
864 register char *start;
865 register int len;
866 {
867 abort ();
868 }
869
870 static
871 XTdelete_glyphs (n)
872 register int n;
873 {
874 abort ();
875 }
876 \f
877 /* Specify how many text lines, from the top of the window,
878 should be affected by insert-lines and delete-lines operations.
879 This, and those operations, are used only within an update
880 that is bounded by calls to XTupdate_begin and XTupdate_end. */
881
882 static
883 XTset_terminal_window (n)
884 register int n;
885 {
886 if (updating_frame == 0)
887 abort ();
888
889 if ((n <= 0) || (n > updating_frame->height))
890 flexlines = updating_frame->height;
891 else
892 flexlines = n;
893 }
894 \f
895 /* Perform an insert-lines operation.
896 Insert N lines at a vertical position curs_y. */
897
898 static void
899 stufflines (n)
900 register int n;
901 {
902 register int topregion, bottomregion;
903 register int length, newtop, mask;
904 register struct frame *f = updating_frame;
905 int intborder = f->display.x->internal_border_width;
906
907 if (curs_y >= flexlines)
908 return;
909
910 topregion = curs_y;
911 bottomregion = flexlines - (n + 1);
912 newtop = topregion + n;
913 length = (bottomregion - topregion) + 1;
914
915 #ifndef HAVE_X11
916 dumpqueue ();
917 #endif /* HAVE_X11 */
918
919 if ((length > 0) && (newtop <= flexlines))
920 {
921 #ifdef HAVE_X11
922 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
923 FRAME_X_WINDOW (f), f->display.x->normal_gc,
924 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
925 f->width * FONT_WIDTH (f->display.x->font),
926 length * FONT_HEIGHT (f->display.x->font), intborder,
927 CHAR_TO_PIXEL_ROW (f, newtop));
928 #else /* ! defined (HAVE_X11) */
929 XMoveArea (FRAME_X_WINDOW (f),
930 intborder, CHAR_TO_PIXEL_ROW (f, topregion),
931 intborder, CHAR_TO_PIXEL_ROW (f, newtop),
932 f->width * FONT_WIDTH (f->display.x->font),
933 length * FONT_HEIGHT (f->display.x->font));
934 /* Now we must process any ExposeRegion events that occur
935 if the area being copied from is obscured.
936 We can't let it wait because further i/d operations
937 may want to copy this area to another area. */
938 x_read_exposes ();
939 #endif /* ! defined (HAVE_X11) */
940 }
941
942 newtop = min (newtop, (flexlines - 1));
943 length = newtop - topregion;
944 if (length > 0)
945 {
946 #ifdef HAVE_X11
947 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
948 CHAR_TO_PIXEL_ROW (f, topregion),
949 f->width * FONT_WIDTH (f->display.x->font),
950 n * FONT_HEIGHT (f->display.x->font), False);
951 #else /* ! defined (HAVE_X11) */
952 XPixSet (FRAME_X_WINDOW (f),
953 intborder,
954 CHAR_TO_PIXEL_ROW (f, topregion),
955 f->width * FONT_WIDTH (f->display.x->font),
956 n * FONT_HEIGHT (f->display.x->font),
957 f->display.x->background_pixel);
958 #endif /* ! defined (HAVE_X11) */
959 }
960 }
961
962 /* Perform a delete-lines operation, deleting N lines
963 at a vertical position curs_y. */
964
965 static void
966 scraplines (n)
967 register int n;
968 {
969 int mask;
970 register struct frame *f = updating_frame;
971 int intborder = f->display.x->internal_border_width;
972
973 if (curs_y >= flexlines)
974 return;
975
976 #ifndef HAVE_X11
977 dumpqueue ();
978 #endif /* HAVE_X11 */
979
980 if ((curs_y + n) >= flexlines)
981 {
982 if (flexlines >= (curs_y + 1))
983 {
984 #ifdef HAVE_X11
985 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
986 CHAR_TO_PIXEL_ROW (f, curs_y),
987 f->width * FONT_WIDTH (f->display.x->font),
988 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
989 #else /* ! defined (HAVE_X11) */
990 XPixSet (FRAME_X_WINDOW (f),
991 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
992 f->width * FONT_WIDTH (f->display.x->font),
993 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
994 f->display.x->background_pixel);
995 #endif /* ! defined (HAVE_X11) */
996 }
997 }
998 else
999 {
1000 #ifdef HAVE_X11
1001 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
1002 FRAME_X_WINDOW (f), f->display.x->normal_gc,
1003 intborder,
1004 CHAR_TO_PIXEL_ROW (f, curs_y + n),
1005 f->width * FONT_WIDTH (f->display.x->font),
1006 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
1007 intborder, CHAR_TO_PIXEL_ROW (f, curs_y));
1008 XClearArea (x_current_display, FRAME_X_WINDOW (f),
1009 intborder,
1010 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1011 f->width * FONT_WIDTH (f->display.x->font),
1012 n * FONT_HEIGHT (f->display.x->font), False);
1013 #else /* ! defined (HAVE_X11) */
1014 XMoveArea (FRAME_X_WINDOW (f),
1015 intborder,
1016 CHAR_TO_PIXEL_ROW (f, curs_y + n),
1017 intborder, CHAR_TO_PIXEL_ROW (f, curs_y),
1018 f->width * FONT_WIDTH (f->display.x->font),
1019 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
1020 /* Now we must process any ExposeRegion events that occur
1021 if the area being copied from is obscured.
1022 We can't let it wait because further i/d operations
1023 may want to copy this area to another area. */
1024 x_read_exposes ();
1025 XPixSet (FRAME_X_WINDOW (f), intborder,
1026 CHAR_TO_PIXEL_ROW (f, flexlines - n),
1027 f->width * FONT_WIDTH (f->display.x->font),
1028 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
1029 #endif /* ! defined (HAVE_X11) */
1030 }
1031 }
1032
1033 /* Perform an insert-lines or delete-lines operation,
1034 inserting N lines or deleting -N lines at vertical position VPOS. */
1035
1036 XTins_del_lines (vpos, n)
1037 int vpos, n;
1038 {
1039 if (updating_frame == 0)
1040 abort ();
1041
1042 /* Hide the cursor. */
1043 x_display_cursor (updating_frame, 0);
1044
1045 XTcursor_to (vpos, 0);
1046
1047 BLOCK_INPUT;
1048 if (n >= 0)
1049 stufflines (n);
1050 else
1051 scraplines (-n);
1052 XFlushQueue ();
1053 UNBLOCK_INPUT;
1054 }
1055 \f
1056 /* Support routines for exposure events. */
1057 static void clear_cursor ();
1058
1059 /* Output into a rectangle of an X-window (for frame F)
1060 the characters in f->phys_lines that overlap that rectangle.
1061 TOP and LEFT are the position of the upper left corner of the rectangle.
1062 ROWS and COLS are the size of the rectangle. */
1063
1064 static void
1065 dumprectangle (f, left, top, cols, rows)
1066 struct frame *f;
1067 register int left, top, cols, rows;
1068 {
1069 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1070 int cursor_cleared = 0;
1071 int bottom, right;
1072 register int y;
1073
1074 if (FRAME_GARBAGED_P (f))
1075 return;
1076
1077 /* Express rectangle as four edges, instead of position-and-size. */
1078 bottom = top + rows;
1079 right = left + cols;
1080
1081 #ifndef HAVE_X11 /* Window manger does this for X11. */
1082 {
1083 int intborder = f->display.x->internal_border_width;
1084
1085 /* If the rectangle includes any of the internal border area,
1086 redisplay the border emphasis. */
1087 if (top < intborder || left < intborder
1088 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font)
1089 || right > intborder + f->width * FONT_WIDTH (f->display.x->font))
1090 dumpborder (f, 0);
1091 }
1092 #endif /* HAVE_X11 Window manger does this for X11. */
1093
1094 /* Convert rectangle edges in pixels to edges in chars.
1095 Round down for left and top, up for right and bottom. */
1096 top = PIXEL_TO_CHAR_ROW (f, top);
1097 left = PIXEL_TO_CHAR_COL (f, left);
1098 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
1099 right += (FONT_WIDTH (f->display.x->font) - 1);
1100 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1101 right = PIXEL_TO_CHAR_COL (f, right);
1102
1103 /* Clip the rectangle to what can be visible. */
1104 if (left < 0)
1105 left = 0;
1106 if (top < 0)
1107 top = 0;
1108 if (right > f->width)
1109 right = f->width;
1110 if (bottom > f->height)
1111 bottom = f->height;
1112
1113 /* Get size in chars of the rectangle. */
1114 cols = right - left;
1115 rows = bottom - top;
1116
1117 /* If rectangle has zero area, return. */
1118 if (rows <= 0) return;
1119 if (cols <= 0) return;
1120
1121 /* Turn off the cursor if it is in the rectangle.
1122 We will turn it back on afterward. */
1123 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1124 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1125 {
1126 clear_cursor (f);
1127 cursor_cleared = 1;
1128 }
1129
1130 /* Display the text in the rectangle, one text line at a time. */
1131
1132 for (y = top; y < bottom; y++)
1133 {
1134 GLYPH *line = &active_frame->glyphs[y][left];
1135
1136 if (! active_frame->enable[y] || left > active_frame->used[y])
1137 continue;
1138
1139 dumpglyphs (f,
1140 CHAR_TO_PIXEL_COL (f, left),
1141 CHAR_TO_PIXEL_ROW (f, y),
1142 line, min (cols, active_frame->used[y] - left),
1143 active_frame->highlight[y]);
1144 }
1145
1146 /* Turn the cursor on if we turned it off. */
1147
1148 if (cursor_cleared)
1149 x_display_cursor (f, 1);
1150 }
1151
1152 #ifndef HAVE_X11
1153 /* Process all queued ExposeRegion events. */
1154
1155 static void
1156 dumpqueue ()
1157 {
1158 register int i;
1159 XExposeRegionEvent r;
1160
1161 while (dequeue_event (&r, &x_expose_queue))
1162 {
1163 struct frame *f = x_window_to_frame (r.window);
1164 if (f->display.x->icon_desc == r.window)
1165 refreshicon (f);
1166 else
1167 dumprectangle (f, r.x, r.y, r.width, r.height);
1168 }
1169 XFlushQueue ();
1170 }
1171 #endif /* HAVE_X11 */
1172 \f
1173 /* Process all expose events that are pending, for X10.
1174 Redraws the cursor if necessary on any frame that
1175 is not in the process of being updated with update_frame. */
1176
1177 #ifndef HAVE_X11
1178 static void
1179 x_do_pending_expose ()
1180 {
1181 int mask;
1182 struct frame *f;
1183 Lisp_Object tail, frame;
1184
1185 if (expose_all_windows)
1186 {
1187 expose_all_windows = 0;
1188 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1189 {
1190 register int temp_width, temp_height;
1191 int intborder;
1192
1193 frame = XCONS (tail)->car;
1194 if (XGCTYPE (frame) != Lisp_Frame)
1195 continue;
1196 f = XFRAME (frame);
1197 if (! FRAME_X_P (f))
1198 continue;
1199 if (!f->async_visible)
1200 continue;
1201 if (!f->display.x->needs_exposure)
1202 continue;
1203
1204 intborder = f->display.x->internal_border_width;
1205
1206 clear_cursor (f);
1207 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1208 temp_width = ((windowinfo.width - 2 * intborder
1209 - f->display.x->v_scroll_bar_width)
1210 / FONT_WIDTH (f->display.x->font));
1211 temp_height = ((windowinfo.height- 2 * intborder
1212 - f->display.x->h_scroll_bar_height)
1213 / FONT_HEIGHT (f->display.x->font));
1214 if (temp_width != f->width || temp_height != f->height)
1215 {
1216 change_frame_size (f, max (1, temp_height),
1217 max (1, temp_width), 0, 1);
1218 x_resize_scroll_bars (f);
1219 }
1220 f->display.x->left_pos = windowinfo.x;
1221 f->display.x->top_pos = windowinfo.y;
1222 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1223 #if 0
1224 dumpborder (f, 0);
1225 #endif /* ! 0 */
1226 f->display.x->needs_exposure = 0;
1227 if (updating_frame != f)
1228 x_display_cursor (f, 1);
1229 XFlushQueue ();
1230 }
1231 }
1232 else
1233 /* Handle any individual-rectangle expose events queued
1234 for various windows. */
1235 #ifdef HAVE_X11
1236 ;
1237 #else /* ! defined (HAVE_X11) */
1238 dumpqueue ();
1239 #endif /* ! defined (HAVE_X11) */
1240 }
1241 #endif
1242
1243 #ifdef HAVE_X11
1244 static void
1245 frame_highlight (frame)
1246 struct frame *frame;
1247 {
1248 /* We used to only do this if Vx_no_window_manager was non-nil, but
1249 the ICCCM (section 4.1.6) says that the window's border pixmap
1250 and border pixel are window attributes which are "private to the
1251 client", so we can always change it to whatever we want. */
1252 BLOCK_INPUT;
1253 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1254 frame->display.x->border_pixel);
1255 UNBLOCK_INPUT;
1256 x_display_cursor (frame, 1);
1257 }
1258
1259 static void
1260 frame_unhighlight (frame)
1261 struct frame *frame;
1262 {
1263 /* We used to only do this if Vx_no_window_manager was non-nil, but
1264 the ICCCM (section 4.1.6) says that the window's border pixmap
1265 and border pixel are window attributes which are "private to the
1266 client", so we can always change it to whatever we want. */
1267 BLOCK_INPUT;
1268 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1269 frame->display.x->border_tile);
1270 UNBLOCK_INPUT;
1271 x_display_cursor (frame, 1);
1272 }
1273 #else /* ! defined (HAVE_X11) */
1274 /* Dump the border-emphasis of frame F.
1275 If F is selected, this is a lining of the same color as the border,
1276 just within the border, occupying a portion of the internal border.
1277 If F is not selected, it is background in the same place.
1278 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1279
1280 ALWAYS = 1 is used when a frame becomes selected or deselected.
1281 In that case, we also turn the cursor off and on again
1282 so it will appear in the proper shape (solid if selected; else hollow.) */
1283
1284 static void
1285 dumpborder (f, always)
1286 struct frame *f;
1287 int always;
1288 {
1289 int thickness = f->display.x->internal_border_width / 2;
1290 int width = PIXEL_WIDTH (f);
1291 int height = PIXEL_HEIGHT (f);
1292 int pixel;
1293
1294 if (f != selected_frame)
1295 {
1296 if (!always)
1297 return;
1298
1299 pixel = f->display.x->background_pixel;
1300 }
1301 else
1302 {
1303 pixel = f->display.x->border_pixel;
1304 }
1305
1306 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1307 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1308 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1309 thickness, pixel);
1310 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1311 height, pixel);
1312
1313 if (always)
1314 x_display_cursor (f, 1);
1315 }
1316 #endif /* ! defined (HAVE_X11) */
1317
1318 static void XTframe_rehighlight ();
1319
1320 /* The focus has changed. Update the frames as necessary to reflect
1321 the new situation. Note that we can't change the selected frame
1322 here, because the lisp code we are interrupting might become confused.
1323 Each event gets marked with the frame in which it occurred, so the
1324 lisp code can tell when the switch took place by examining the events. */
1325
1326 static void
1327 x_new_focus_frame (frame)
1328 struct frame *frame;
1329 {
1330 struct frame *old_focus = x_focus_frame;
1331 int events_enqueued = 0;
1332
1333 if (frame != x_focus_frame)
1334 {
1335 /* Set this before calling other routines, so that they see
1336 the correct value of x_focus_frame. */
1337 x_focus_frame = frame;
1338
1339 if (old_focus && old_focus->auto_lower)
1340 x_lower_frame (old_focus);
1341
1342 #if 0
1343 selected_frame = frame;
1344 XSET (XWINDOW (selected_frame->selected_window)->frame,
1345 Lisp_Frame, selected_frame);
1346 Fselect_window (selected_frame->selected_window);
1347 choose_minibuf_frame ();
1348 #endif /* ! 0 */
1349
1350 if (x_focus_frame && x_focus_frame->auto_raise)
1351 x_raise_frame (x_focus_frame);
1352 }
1353
1354 XTframe_rehighlight ();
1355 }
1356
1357
1358 /* The focus has changed, or we have redirected a frame's focus to
1359 another frame (this happens when a frame uses a surrogate
1360 minibuffer frame). Shift the highlight as appropriate. */
1361 static void
1362 XTframe_rehighlight ()
1363 {
1364 struct frame *old_highlight = x_highlight_frame;
1365
1366 if (x_focus_frame)
1367 {
1368 x_highlight_frame =
1369 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1370 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1371 : x_focus_frame);
1372 if (! FRAME_LIVE_P (x_highlight_frame))
1373 {
1374 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1375 x_highlight_frame = x_focus_frame;
1376 }
1377 }
1378 else
1379 x_highlight_frame = 0;
1380
1381 if (x_highlight_frame != old_highlight)
1382 {
1383 if (old_highlight)
1384 frame_unhighlight (old_highlight);
1385 if (x_highlight_frame)
1386 frame_highlight (x_highlight_frame);
1387 }
1388 }
1389 \f
1390 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1391
1392 /* Which modifier keys are on which modifier bits?
1393
1394 With each keystroke, X returns eight bits indicating which modifier
1395 keys were held down when the key was pressed. The interpretation
1396 of the top five modifier bits depends on what keys are attached
1397 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1398 is the meta bit.
1399
1400 x_meta_mod_mask is a mask containing the bits used for the meta key.
1401 It may have more than one bit set, if more than one modifier bit
1402 has meta keys on it. Basically, if EVENT is a KeyPress event,
1403 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1404
1405 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1406 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1407 only be affected by the lock modifier bit if XK_Shift_Lock is in
1408 use; XK_Caps_Lock should only affect alphabetic keys. With this
1409 arrangement, the lock modifier should shift the character if
1410 (EVENT.state & x_shift_lock_mask) != 0. */
1411 static int x_meta_mod_mask, x_shift_lock_mask;
1412
1413 /* These are like x_meta_mod_mask, but for different modifiers. */
1414 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1415
1416 /* Initialize mode_switch_bit and modifier_meaning. */
1417 static void
1418 x_find_modifier_meanings ()
1419 {
1420 int min_code, max_code;
1421 KeySym *syms;
1422 int syms_per_code;
1423 XModifierKeymap *mods;
1424
1425 x_meta_mod_mask = 0;
1426 x_shift_lock_mask = 0;
1427 x_alt_mod_mask = 0;
1428 x_super_mod_mask = 0;
1429 x_hyper_mod_mask = 0;
1430
1431 #ifdef HAVE_X11R4
1432 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1433 #else
1434 min_code = x_current_display->min_keycode;
1435 max_code = x_current_display->max_keycode;
1436 #endif
1437
1438 syms = XGetKeyboardMapping (x_current_display,
1439 min_code, max_code - min_code + 1,
1440 &syms_per_code);
1441 mods = XGetModifierMapping (x_current_display);
1442
1443 /* Scan the modifier table to see which modifier bits the Meta and
1444 Alt keysyms are on. */
1445 {
1446 int row, col; /* The row and column in the modifier table. */
1447
1448 for (row = 3; row < 8; row++)
1449 for (col = 0; col < mods->max_keypermod; col++)
1450 {
1451 KeyCode code =
1452 mods->modifiermap[(row * mods->max_keypermod) + col];
1453
1454 /* Are any of this keycode's keysyms a meta key? */
1455 {
1456 int code_col;
1457
1458 for (code_col = 0; code_col < syms_per_code; code_col++)
1459 {
1460 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1461
1462 switch (sym)
1463 {
1464 case XK_Meta_L:
1465 case XK_Meta_R:
1466 x_meta_mod_mask |= (1 << row);
1467 break;
1468
1469 case XK_Alt_L:
1470 case XK_Alt_R:
1471 x_alt_mod_mask |= (1 << row);
1472 break;
1473
1474 case XK_Hyper_L:
1475 case XK_Hyper_R:
1476 x_hyper_mod_mask |= (1 << row);
1477 break;
1478
1479 case XK_Super_L:
1480 case XK_Super_R:
1481 x_super_mod_mask |= (1 << row);
1482 break;
1483
1484 case XK_Shift_Lock:
1485 /* Ignore this if it's not on the lock modifier. */
1486 if ((1 << row) == LockMask)
1487 x_shift_lock_mask = LockMask;
1488 break;
1489 }
1490 }
1491 }
1492 }
1493 }
1494
1495 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1496 if (! x_meta_mod_mask)
1497 {
1498 x_meta_mod_mask = x_alt_mod_mask;
1499 x_alt_mod_mask = 0;
1500 }
1501
1502 /* If some keys are both alt and meta,
1503 make them just meta, not alt. */
1504 if (x_alt_mod_mask & x_meta_mod_mask)
1505 {
1506 x_alt_mod_mask &= ~x_meta_mod_mask;
1507 }
1508
1509 XFree ((char *) syms);
1510 XFreeModifiermap (mods);
1511 }
1512
1513
1514 /* Convert between the modifier bits X uses and the modifier bits
1515 Emacs uses. */
1516 static unsigned int
1517 x_x_to_emacs_modifiers (state)
1518 unsigned int state;
1519 {
1520 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1521 | ((state & ControlMask) ? ctrl_modifier : 0)
1522 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1523 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1524 | ((state & x_super_mod_mask) ? super_modifier : 0)
1525 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1526 }
1527
1528 static unsigned int
1529 x_emacs_to_x_modifiers (state)
1530 unsigned int state;
1531 {
1532 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1533 | ((state & super_modifier) ? x_super_mod_mask : 0)
1534 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1535 | ((state & shift_modifier) ? ShiftMask : 0)
1536 | ((state & ctrl_modifier) ? ControlMask : 0)
1537 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1538 }
1539
1540 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1541 return as a function key. If you add a keysym to this, you should
1542 make sure that the tables make_lispy_event uses contain a suitable
1543 name for it. */
1544 static int
1545 x_is_vendor_fkey (sym)
1546 KeySym sym;
1547 {
1548 return 0
1549 #ifdef DXK_Remove
1550 || (sym == DXK_Remove)
1551 #endif
1552 ;
1553 }
1554
1555 \f
1556 /* Mouse clicks and mouse movement. Rah. */
1557 #ifdef HAVE_X11
1558
1559 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1560 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1561 that the glyph at X, Y occupies, if BOUNDS != 0. */
1562 static void
1563 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1564 FRAME_PTR f;
1565 register unsigned int pix_x, pix_y;
1566 register int *x, *y;
1567 XRectangle *bounds;
1568 {
1569 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1570 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1571
1572 if (bounds)
1573 {
1574 bounds->width = FONT_WIDTH (f->display.x->font);
1575 bounds->height = FONT_HEIGHT (f->display.x->font);
1576 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1577 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1578 }
1579
1580 if (pix_x < 0) pix_x = 0;
1581 else if (pix_x > f->width) pix_x = f->width;
1582
1583 if (pix_y < 0) pix_y = 0;
1584 else if (pix_y > f->height) pix_y = f->height;
1585
1586 *x = pix_x;
1587 *y = pix_y;
1588 }
1589
1590 /* Any buttons grabbed. */
1591 unsigned int x_mouse_grabbed;
1592
1593 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1594
1595 If the event is a button press, then note that we have grabbed
1596 the mouse. */
1597
1598 static Lisp_Object
1599 construct_mouse_click (result, event, f)
1600 struct input_event *result;
1601 XButtonEvent *event;
1602 struct frame *f;
1603 {
1604 /* Make the event type no_event; we'll change that when we decide
1605 otherwise. */
1606 result->kind = mouse_click;
1607 XSET (result->code, Lisp_Int, event->button - Button1);
1608 result->timestamp = event->time;
1609 result->modifiers = (x_x_to_emacs_modifiers (event->state)
1610 | (event->type == ButtonRelease
1611 ? up_modifier
1612 : down_modifier));
1613
1614 /* Notice if the mouse is still grabbed. */
1615 if (event->type == ButtonPress)
1616 {
1617 if (! x_mouse_grabbed)
1618 Vmouse_depressed = Qt;
1619 x_mouse_grabbed |= (1 << event->button);
1620 }
1621 else if (event->type == ButtonRelease)
1622 {
1623 x_mouse_grabbed &= ~(1 << event->button);
1624 if (!x_mouse_grabbed)
1625 Vmouse_depressed = Qnil;
1626 }
1627
1628 {
1629 int row, column;
1630
1631 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1632 XFASTINT (result->x) = column;
1633 XFASTINT (result->y) = row;
1634 XSET (result->frame_or_window, Lisp_Frame, f);
1635 }
1636 }
1637
1638
1639 /* Mouse movement. Rah.
1640
1641 In order to avoid asking for motion events and then throwing most
1642 of them away or busy-polling the server for mouse positions, we ask
1643 the server for pointer motion hints. This means that we get only
1644 one event per group of mouse movements. "Groups" are delimited by
1645 other kinds of events (focus changes and button clicks, for
1646 example), or by XQueryPointer calls; when one of these happens, we
1647 get another MotionNotify event the next time the mouse moves. This
1648 is at least as efficient as getting motion events when mouse
1649 tracking is on, and I suspect only negligibly worse when tracking
1650 is off.
1651
1652 The silly O'Reilly & Associates Nutshell guides barely document
1653 pointer motion hints at all (I think you have to infer how they
1654 work from an example), and the description of XQueryPointer doesn't
1655 mention that calling it causes you to get another motion hint from
1656 the server, which is very important. */
1657
1658 /* Where the mouse was last time we reported a mouse event. */
1659 static FRAME_PTR last_mouse_frame;
1660 static XRectangle last_mouse_glyph;
1661
1662 /* The scroll bar in which the last X motion event occurred.
1663
1664 If the last X motion event occurred in a scroll bar, we set this
1665 so XTmouse_position can know whether to report a scroll bar motion or
1666 an ordinary motion.
1667
1668 If the last X motion event didn't occur in a scroll bar, we set this
1669 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1670 static Lisp_Object last_mouse_scroll_bar;
1671
1672 /* This is a hack. We would really prefer that XTmouse_position would
1673 return the time associated with the position it returns, but there
1674 doesn't seem to be any way to wrest the timestamp from the server
1675 along with the position query. So, we just keep track of the time
1676 of the last movement we received, and return that in hopes that
1677 it's somewhat accurate. */
1678 static Time last_mouse_movement_time;
1679
1680 /* Function to report a mouse movement to the mainstream Emacs code.
1681 The input handler calls this.
1682
1683 We have received a mouse movement event, which is given in *event.
1684 If the mouse is over a different glyph than it was last time, tell
1685 the mainstream emacs code by setting mouse_moved. If not, ask for
1686 another motion event, so we can check again the next time it moves. */
1687 static void
1688 note_mouse_movement (frame, event)
1689 FRAME_PTR frame;
1690 XMotionEvent *event;
1691
1692 {
1693 last_mouse_movement_time = event->time;
1694
1695 /* Has the mouse moved off the glyph it was on at the last sighting? */
1696 if (event->x < last_mouse_glyph.x
1697 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1698 || event->y < last_mouse_glyph.y
1699 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1700 {
1701 mouse_moved = 1;
1702 last_mouse_scroll_bar = Qnil;
1703 }
1704 else
1705 {
1706 /* It's on the same glyph. Call XQueryPointer so we'll get an
1707 event the next time the mouse moves and we can see if it's
1708 *still* on the same glyph. */
1709 int dummy;
1710
1711 XQueryPointer (event->display, event->window,
1712 (Window *) &dummy, (Window *) &dummy,
1713 &dummy, &dummy, &dummy, &dummy,
1714 (unsigned int *) &dummy);
1715 }
1716 }
1717
1718 static struct scroll_bar *x_window_to_scroll_bar ();
1719 static void x_scroll_bar_report_motion ();
1720
1721 /* Return the current position of the mouse.
1722
1723 If the mouse movement started in a scroll bar, set *f, *bar_window,
1724 and *part to the frame, window, and scroll bar part that the mouse
1725 is over. Set *x and *y to the portion and whole of the mouse's
1726 position on the scroll bar.
1727
1728 If the mouse movement started elsewhere, set *f to the frame the
1729 mouse is on, *bar_window to nil, and *x and *y to the character cell
1730 the mouse is over.
1731
1732 Set *time to the server timestamp for the time at which the mouse
1733 was at this position.
1734
1735 Don't store anything if we don't have a valid set of values to report.
1736
1737 This clears the mouse_moved flag, so we can wait for the next mouse
1738 movement. This also calls XQueryPointer, which will cause the
1739 server to give us another MotionNotify when the mouse moves
1740 again. */
1741
1742 static void
1743 XTmouse_position (f, bar_window, part, x, y, time)
1744 FRAME_PTR *f;
1745 Lisp_Object *bar_window;
1746 enum scroll_bar_part *part;
1747 Lisp_Object *x, *y;
1748 unsigned long *time;
1749 {
1750 FRAME_PTR f1;
1751
1752 BLOCK_INPUT;
1753
1754 if (! NILP (last_mouse_scroll_bar))
1755 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1756 else
1757 {
1758 Window root;
1759 int root_x, root_y;
1760
1761 Window dummy_window;
1762 int dummy;
1763
1764 mouse_moved = 0;
1765 last_mouse_scroll_bar = Qnil;
1766
1767 /* Figure out which root window we're on. */
1768 XQueryPointer (x_current_display,
1769 DefaultRootWindow (x_current_display),
1770
1771 /* The root window which contains the pointer. */
1772 &root,
1773
1774 /* Trash which we can't trust if the pointer is on
1775 a different screen. */
1776 &dummy_window,
1777
1778 /* The position on that root window. */
1779 &root_x, &root_y,
1780
1781 /* More trash we can't trust. */
1782 &dummy, &dummy,
1783
1784 /* Modifier keys and pointer buttons, about which
1785 we don't care. */
1786 (unsigned int *) &dummy);
1787
1788 /* Now we have a position on the root; find the innermost window
1789 containing the pointer. */
1790 {
1791 Window win, child;
1792 int win_x, win_y;
1793 int parent_x, parent_y;
1794
1795 win = root;
1796 for (;;)
1797 {
1798 XTranslateCoordinates (x_current_display,
1799
1800 /* From-window, to-window. */
1801 root, win,
1802
1803 /* From-position, to-position. */
1804 root_x, root_y, &win_x, &win_y,
1805
1806 /* Child of win. */
1807 &child);
1808
1809 if (child == None)
1810 break;
1811
1812 win = child;
1813 parent_x = win_x;
1814 parent_y = win_y;
1815 }
1816
1817 /* Now we know that:
1818 win is the innermost window containing the pointer
1819 (XTC says it has no child containing the pointer),
1820 win_x and win_y are the pointer's position in it
1821 (XTC did this the last time through), and
1822 parent_x and parent_y are the pointer's position in win's parent.
1823 (They are what win_x and win_y were when win was child.
1824 If win is the root window, it has no parent, and
1825 parent_{x,y} are invalid, but that's okay, because we'll
1826 never use them in that case.) */
1827
1828 /* Is win one of our frames? */
1829 f1 = x_window_to_frame (win);
1830
1831 /* If not, is it one of our scroll bars? */
1832 if (! f1)
1833 {
1834 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1835
1836 if (bar)
1837 {
1838 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1839 win_x = parent_x;
1840 win_y = parent_y;
1841 }
1842 }
1843
1844 if (f1)
1845 {
1846 /* Ok, we found a frame. Convert from pixels to characters
1847 and store all the values. */
1848
1849 pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y,
1850 &last_mouse_glyph);
1851
1852 *bar_window = Qnil;
1853 *part = 0;
1854 *f = f1;
1855 XSET (*x, Lisp_Int, win_x);
1856 XSET (*y, Lisp_Int, win_y);
1857 *time = last_mouse_movement_time;
1858 }
1859 }
1860 }
1861
1862 UNBLOCK_INPUT;
1863 }
1864
1865 #else /* ! defined (HAVE_X11) */
1866 #define XEvent XKeyPressedEvent
1867 #endif /* ! defined (HAVE_X11) */
1868 \f
1869 /* Scroll bar support. */
1870
1871 /* Given an X window ID, find the struct scroll_bar which manages it.
1872 This can be called in GC, so we have to make sure to strip off mark
1873 bits. */
1874 static struct scroll_bar *
1875 x_window_to_scroll_bar (window_id)
1876 Window window_id;
1877 {
1878 Lisp_Object tail, frame;
1879
1880 for (tail = Vframe_list;
1881 XGCTYPE (tail) == Lisp_Cons;
1882 tail = XCONS (tail)->cdr)
1883 {
1884 Lisp_Object frame = XCONS (tail)->car;
1885 Lisp_Object bar, condemned;
1886
1887 /* All elements of Vframe_list should be frames. */
1888 if (XGCTYPE (frame) != Lisp_Frame)
1889 abort ();
1890
1891 /* Scan this frame's scroll bar list for a scroll bar with the
1892 right window ID. */
1893 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1894 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1895 /* This trick allows us to search both the ordinary and
1896 condemned scroll bar lists with one loop. */
1897 ! GC_NILP (bar) || (bar = condemned,
1898 condemned = Qnil,
1899 ! GC_NILP (bar));
1900 bar = XSCROLL_BAR(bar)->next)
1901 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1902 return XSCROLL_BAR (bar);
1903 }
1904
1905 return 0;
1906 }
1907
1908 /* Open a new X window to serve as a scroll bar, and return the
1909 scroll bar vector for it. */
1910 static struct scroll_bar *
1911 x_scroll_bar_create (window, top, left, width, height)
1912 struct window *window;
1913 int top, left, width, height;
1914 {
1915 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1916 struct scroll_bar *bar =
1917 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1918
1919 BLOCK_INPUT;
1920
1921 {
1922 XSetWindowAttributes a;
1923 unsigned long mask;
1924
1925 a.background_pixel = frame->display.x->background_pixel;
1926 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1927 | ButtonMotionMask | PointerMotionHintMask
1928 | ExposureMask);
1929 a.cursor = x_vertical_scroll_bar_cursor;
1930
1931 mask = (CWBackPixel | CWEventMask | CWCursor);
1932
1933 SET_SCROLL_BAR_X_WINDOW
1934 (bar,
1935 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1936
1937 /* Position and size of scroll bar. */
1938 left, top, width, height,
1939
1940 /* Border width, depth, class, and visual. */
1941 0, CopyFromParent, CopyFromParent, CopyFromParent,
1942
1943 /* Attributes. */
1944 mask, &a));
1945 }
1946
1947 XSET (bar->window, Lisp_Window, window);
1948 XSET (bar->top, Lisp_Int, top);
1949 XSET (bar->left, Lisp_Int, left);
1950 XSET (bar->width, Lisp_Int, width);
1951 XSET (bar->height, Lisp_Int, height);
1952 XSET (bar->start, Lisp_Int, 0);
1953 XSET (bar->end, Lisp_Int, 0);
1954 bar->dragging = Qnil;
1955
1956 /* Add bar to its frame's list of scroll bars. */
1957 bar->next = FRAME_SCROLL_BARS (frame);
1958 bar->prev = Qnil;
1959 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1960 if (! NILP (bar->next))
1961 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1962
1963 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1964
1965 UNBLOCK_INPUT;
1966
1967 return bar;
1968 }
1969
1970 /* Draw BAR's handle in the proper position.
1971 If the handle is already drawn from START to END, don't bother
1972 redrawing it, unless REBUILD is non-zero; in that case, always
1973 redraw it. (REBUILD is handy for drawing the handle after expose
1974 events.)
1975
1976 Normally, we want to constrain the start and end of the handle to
1977 fit inside its rectangle, but if the user is dragging the scroll bar
1978 handle, we want to let them drag it down all the way, so that the
1979 bar's top is as far down as it goes; otherwise, there's no way to
1980 move to the very end of the buffer. */
1981 static void
1982 x_scroll_bar_set_handle (bar, start, end, rebuild)
1983 struct scroll_bar *bar;
1984 int start, end;
1985 int rebuild;
1986 {
1987 int dragging = ! NILP (bar->dragging);
1988 Window w = SCROLL_BAR_X_WINDOW (bar);
1989 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1990
1991 /* If the display is already accurate, do nothing. */
1992 if (! rebuild
1993 && start == XINT (bar->start)
1994 && end == XINT (bar->end))
1995 return;
1996
1997 BLOCK_INPUT;
1998
1999 {
2000 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
2001 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2002 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2003
2004 /* Make sure the values are reasonable, and try to preserve
2005 the distance between start and end. */
2006 {
2007 int length = end - start;
2008
2009 if (start < 0)
2010 start = 0;
2011 else if (start > top_range)
2012 start = top_range;
2013 end = start + length;
2014
2015 if (end < start)
2016 end = start;
2017 else if (end > top_range && ! dragging)
2018 end = top_range;
2019 }
2020
2021 /* Store the adjusted setting in the scroll bar. */
2022 XSET (bar->start, Lisp_Int, start);
2023 XSET (bar->end, Lisp_Int, end);
2024
2025 /* Clip the end position, just for display. */
2026 if (end > top_range)
2027 end = top_range;
2028
2029 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2030 below top positions, to make sure the handle is always at least
2031 that many pixels tall. */
2032 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2033
2034 /* Draw the empty space above the handle. Note that we can't clear
2035 zero-height areas; that means "clear to end of window." */
2036 if (0 < start)
2037 XClearArea (x_current_display, w,
2038
2039 /* x, y, width, height, and exposures. */
2040 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2041 VERTICAL_SCROLL_BAR_TOP_BORDER,
2042 inside_width, start,
2043 False);
2044
2045 /* Draw the handle itself. */
2046 XFillRectangle (x_current_display, w, gc,
2047
2048 /* x, y, width, height */
2049 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2050 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2051 inside_width, end - start);
2052
2053
2054 /* Draw the empty space below the handle. Note that we can't
2055 clear zero-height areas; that means "clear to end of window." */
2056 if (end < inside_height)
2057 XClearArea (x_current_display, w,
2058
2059 /* x, y, width, height, and exposures. */
2060 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2061 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2062 inside_width, inside_height - end,
2063 False);
2064
2065 }
2066
2067 UNBLOCK_INPUT;
2068 }
2069
2070 /* Move a scroll bar around on the screen, to accommodate changing
2071 window configurations. */
2072 static void
2073 x_scroll_bar_move (bar, top, left, width, height)
2074 struct scroll_bar *bar;
2075 int top, left, width, height;
2076 {
2077 BLOCK_INPUT;
2078
2079 {
2080 XWindowChanges wc;
2081 unsigned int mask = 0;
2082
2083 wc.x = left;
2084 wc.y = top;
2085 wc.width = width;
2086 wc.height = height;
2087
2088 if (left != XINT (bar->left)) mask |= CWX;
2089 if (top != XINT (bar->top)) mask |= CWY;
2090 if (width != XINT (bar->width)) mask |= CWWidth;
2091 if (height != XINT (bar->height)) mask |= CWHeight;
2092
2093 if (mask)
2094 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
2095 mask, &wc);
2096 }
2097
2098 XSET (bar->left, Lisp_Int, left);
2099 XSET (bar->top, Lisp_Int, top);
2100 XSET (bar->width, Lisp_Int, width);
2101 XSET (bar->height, Lisp_Int, height);
2102
2103 UNBLOCK_INPUT;
2104 }
2105
2106 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2107 to nil. */
2108 static void
2109 x_scroll_bar_remove (bar)
2110 struct scroll_bar *bar;
2111 {
2112 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2113
2114 BLOCK_INPUT;
2115
2116 /* Destroy the window. */
2117 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2118
2119 /* Disassociate this scroll bar from its window. */
2120 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2121
2122 UNBLOCK_INPUT;
2123 }
2124
2125 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2126 that we are displaying PORTION characters out of a total of WHOLE
2127 characters, starting at POSITION. If WINDOW has no scroll bar,
2128 create one. */
2129 static void
2130 XTset_vertical_scroll_bar (window, portion, whole, position)
2131 struct window *window;
2132 int portion, whole, position;
2133 {
2134 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2135 int top = XINT (window->top);
2136 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2137 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2138
2139 /* Where should this scroll bar be, pixelwise? */
2140 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2141 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2142 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2143 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2144
2145 struct scroll_bar *bar;
2146
2147 /* Does the scroll bar exist yet? */
2148 if (NILP (window->vertical_scroll_bar))
2149 bar = x_scroll_bar_create (window,
2150 pixel_top, pixel_left,
2151 pixel_width, pixel_height);
2152 else
2153 {
2154 /* It may just need to be moved and resized. */
2155 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2156 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2157 }
2158
2159 /* Set the scroll bar's current state, unless we're currently being
2160 dragged. */
2161 if (NILP (bar->dragging))
2162 {
2163 int top_range =
2164 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2165
2166 if (whole == 0)
2167 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2168 else
2169 {
2170 int start = ((double) position * top_range) / whole;
2171 int end = ((double) (position + portion) * top_range) / whole;
2172
2173 x_scroll_bar_set_handle (bar, start, end, 0);
2174 }
2175 }
2176
2177 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2178 }
2179
2180
2181 /* The following three hooks are used when we're doing a thorough
2182 redisplay of the frame. We don't explicitly know which scroll bars
2183 are going to be deleted, because keeping track of when windows go
2184 away is a real pain - "Can you say set-window-configuration, boys
2185 and girls?" Instead, we just assert at the beginning of redisplay
2186 that *all* scroll bars are to be removed, and then save a scroll bar
2187 from the fiery pit when we actually redisplay its window. */
2188
2189 /* Arrange for all scroll bars on FRAME to be removed at the next call
2190 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2191 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2192 static void
2193 XTcondemn_scroll_bars (frame)
2194 FRAME_PTR frame;
2195 {
2196 /* The condemned list should be empty at this point; if it's not,
2197 then the rest of Emacs isn't using the condemn/redeem/judge
2198 protocol correctly. */
2199 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2200 abort ();
2201
2202 /* Move them all to the "condemned" list. */
2203 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2204 FRAME_SCROLL_BARS (frame) = Qnil;
2205 }
2206
2207 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2208 Note that WINDOW isn't necessarily condemned at all. */
2209 static void
2210 XTredeem_scroll_bar (window)
2211 struct window *window;
2212 {
2213 struct scroll_bar *bar;
2214
2215 /* We can't redeem this window's scroll bar if it doesn't have one. */
2216 if (NILP (window->vertical_scroll_bar))
2217 abort ();
2218
2219 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2220
2221 /* Unlink it from the condemned list. */
2222 {
2223 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2224
2225 if (NILP (bar->prev))
2226 {
2227 /* If the prev pointer is nil, it must be the first in one of
2228 the lists. */
2229 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2230 /* It's not condemned. Everything's fine. */
2231 return;
2232 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2233 window->vertical_scroll_bar))
2234 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2235 else
2236 /* If its prev pointer is nil, it must be at the front of
2237 one or the other! */
2238 abort ();
2239 }
2240 else
2241 XSCROLL_BAR (bar->prev)->next = bar->next;
2242
2243 if (! NILP (bar->next))
2244 XSCROLL_BAR (bar->next)->prev = bar->prev;
2245
2246 bar->next = FRAME_SCROLL_BARS (f);
2247 bar->prev = Qnil;
2248 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2249 if (! NILP (bar->next))
2250 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2251 }
2252 }
2253
2254 /* Remove all scroll bars on FRAME that haven't been saved since the
2255 last call to `*condemn_scroll_bars_hook'. */
2256 static void
2257 XTjudge_scroll_bars (f)
2258 FRAME_PTR f;
2259 {
2260 Lisp_Object bar, next;
2261
2262 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2263
2264 /* Clear out the condemned list now so we won't try to process any
2265 more events on the hapless scroll bars. */
2266 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2267
2268 for (; ! NILP (bar); bar = next)
2269 {
2270 struct scroll_bar *b = XSCROLL_BAR (bar);
2271
2272 x_scroll_bar_remove (b);
2273
2274 next = b->next;
2275 b->next = b->prev = Qnil;
2276 }
2277
2278 /* Now there should be no references to the condemned scroll bars,
2279 and they should get garbage-collected. */
2280 }
2281
2282
2283 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2284
2285 This may be called from a signal handler, so we have to ignore GC
2286 mark bits. */
2287 static void
2288 x_scroll_bar_expose (bar, event)
2289 struct scroll_bar *bar;
2290 XEvent *event;
2291 {
2292 Window w = SCROLL_BAR_X_WINDOW (bar);
2293 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2294
2295 BLOCK_INPUT;
2296
2297 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2298
2299 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2300 XDrawRectangle (x_current_display, w, gc,
2301
2302 /* x, y, width, height */
2303 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2304
2305 /* Draw another line to make the extra-thick border on the right. */
2306 XFillRectangle (x_current_display, w, gc,
2307
2308 /* x, y, width, height */
2309 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2310
2311 UNBLOCK_INPUT;
2312 }
2313
2314 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2315 is set to something other than no_event, it is enqueued.
2316
2317 This may be called from a signal handler, so we have to ignore GC
2318 mark bits. */
2319 static void
2320 x_scroll_bar_handle_click (bar, event, emacs_event)
2321 struct scroll_bar *bar;
2322 XEvent *event;
2323 struct input_event *emacs_event;
2324 {
2325 if (XGCTYPE (bar->window) != Lisp_Window)
2326 abort ();
2327
2328 emacs_event->kind = scroll_bar_click;
2329 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2330 emacs_event->modifiers =
2331 (x_x_to_emacs_modifiers (event->xbutton.state)
2332 | (event->type == ButtonRelease
2333 ? up_modifier
2334 : down_modifier));
2335 emacs_event->frame_or_window = bar->window;
2336 emacs_event->timestamp = event->xbutton.time;
2337 {
2338 int internal_height =
2339 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2340 int top_range =
2341 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2342 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2343
2344 if (y < 0) y = 0;
2345 if (y > top_range) y = top_range;
2346
2347 if (y < XINT (bar->start))
2348 emacs_event->part = scroll_bar_above_handle;
2349 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2350 emacs_event->part = scroll_bar_handle;
2351 else
2352 emacs_event->part = scroll_bar_below_handle;
2353
2354 /* Just because the user has clicked on the handle doesn't mean
2355 they want to drag it. Lisp code needs to be able to decide
2356 whether or not we're dragging. */
2357 #if 0
2358 /* If the user has just clicked on the handle, record where they're
2359 holding it. */
2360 if (event->type == ButtonPress
2361 && emacs_event->part == scroll_bar_handle)
2362 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2363 #endif
2364
2365 /* If the user has released the handle, set it to its final position. */
2366 if (event->type == ButtonRelease
2367 && ! NILP (bar->dragging))
2368 {
2369 int new_start = y - XINT (bar->dragging);
2370 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2371
2372 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2373 bar->dragging = Qnil;
2374 }
2375
2376 /* Same deal here as the other #if 0. */
2377 #if 0
2378 /* Clicks on the handle are always reported as occurring at the top of
2379 the handle. */
2380 if (emacs_event->part == scroll_bar_handle)
2381 emacs_event->x = bar->start;
2382 else
2383 XSET (emacs_event->x, Lisp_Int, y);
2384 #else
2385 XSET (emacs_event->x, Lisp_Int, y);
2386 #endif
2387
2388 XSET (emacs_event->y, Lisp_Int, top_range);
2389 }
2390 }
2391
2392 /* Handle some mouse motion while someone is dragging the scroll bar.
2393
2394 This may be called from a signal handler, so we have to ignore GC
2395 mark bits. */
2396 static void
2397 x_scroll_bar_note_movement (bar, event)
2398 struct scroll_bar *bar;
2399 XEvent *event;
2400 {
2401 last_mouse_movement_time = event->xmotion.time;
2402
2403 mouse_moved = 1;
2404 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2405
2406 /* If we're dragging the bar, display it. */
2407 if (! GC_NILP (bar->dragging))
2408 {
2409 /* Where should the handle be now? */
2410 int new_start = event->xmotion.y - XINT (bar->dragging);
2411
2412 if (new_start != XINT (bar->start))
2413 {
2414 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2415
2416 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2417 }
2418 }
2419
2420 /* Call XQueryPointer so we'll get an event the next time the mouse
2421 moves and we can see *still* on the same position. */
2422 {
2423 int dummy;
2424
2425 XQueryPointer (event->xmotion.display, event->xmotion.window,
2426 (Window *) &dummy, (Window *) &dummy,
2427 &dummy, &dummy, &dummy, &dummy,
2428 (unsigned int *) &dummy);
2429 }
2430 }
2431
2432 /* Return information to the user about the current position of the mouse
2433 on the scroll bar. */
2434 static void
2435 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2436 FRAME_PTR *f;
2437 Lisp_Object *bar_window;
2438 enum scroll_bar_part *part;
2439 Lisp_Object *x, *y;
2440 unsigned long *time;
2441 {
2442 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2443 int win_x, win_y;
2444 Window dummy_window;
2445 int dummy_coord;
2446 unsigned int dummy_mask;
2447
2448 BLOCK_INPUT;
2449
2450 /* Get the mouse's position relative to the scroll bar window, and
2451 report that. */
2452 if (! XQueryPointer (x_current_display,
2453 SCROLL_BAR_X_WINDOW (bar),
2454
2455 /* Root, child, root x and root y. */
2456 &dummy_window, &dummy_window,
2457 &dummy_coord, &dummy_coord,
2458
2459 /* Position relative to scroll bar. */
2460 &win_x, &win_y,
2461
2462 /* Mouse buttons and modifier keys. */
2463 &dummy_mask))
2464 *f = 0;
2465 else
2466 {
2467 int inside_height
2468 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2469 int top_range
2470 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2471
2472 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2473
2474 if (! NILP (bar->dragging))
2475 win_y -= XINT (bar->dragging);
2476
2477 if (win_y < 0)
2478 win_y = 0;
2479 if (win_y > top_range)
2480 win_y = top_range;
2481
2482 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2483 *bar_window = bar->window;
2484
2485 if (! NILP (bar->dragging))
2486 *part = scroll_bar_handle;
2487 else if (win_y < XINT (bar->start))
2488 *part = scroll_bar_above_handle;
2489 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2490 *part = scroll_bar_handle;
2491 else
2492 *part = scroll_bar_below_handle;
2493
2494 XSET (*x, Lisp_Int, win_y);
2495 XSET (*y, Lisp_Int, top_range);
2496
2497 mouse_moved = 0;
2498 last_mouse_scroll_bar = Qnil;
2499 }
2500
2501 *time = last_mouse_movement_time;
2502
2503 UNBLOCK_INPUT;
2504 }
2505
2506
2507 /* The screen has been cleared so we may have changed foreground or
2508 background colors, and the scroll bars may need to be redrawn.
2509 Clear out the scroll bars, and ask for expose events, so we can
2510 redraw them. */
2511
2512 x_scroll_bar_clear (f)
2513 FRAME_PTR f;
2514 {
2515 Lisp_Object bar;
2516
2517 for (bar = FRAME_SCROLL_BARS (f);
2518 XTYPE (bar) == Lisp_Vector;
2519 bar = XSCROLL_BAR (bar)->next)
2520 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2521 0, 0, 0, 0, True);
2522 }
2523
2524
2525 \f
2526 /* The main X event-reading loop - XTread_socket. */
2527
2528 /* Timestamp of enter window event. This is only used by XTread_socket,
2529 but we have to put it out here, since static variables within functions
2530 sometimes don't work. */
2531 static Time enter_timestamp;
2532
2533 /* This holds the state XLookupString needs to implement dead keys
2534 and other tricks known as "compose processing". _X Window System_
2535 says that a portable program can't use this, but Stephen Gildea assures
2536 me that letting the compiler initialize it to zeros will work okay.
2537
2538 This must be defined outside of XTread_socket, for the same reasons
2539 given for enter_timestamp, above. */
2540 static XComposeStatus compose_status;
2541
2542 /* Communication with window managers. */
2543 Atom Xatom_wm_protocols;
2544
2545 /* Kinds of protocol things we may receive. */
2546 Atom Xatom_wm_take_focus;
2547 Atom Xatom_wm_save_yourself;
2548 Atom Xatom_wm_delete_window;
2549
2550 /* Other WM communication */
2551 Atom Xatom_wm_configure_denied; /* When our config request is denied */
2552 Atom Xatom_wm_window_moved; /* When the WM moves us. */
2553
2554 /* Window manager communication. */
2555 Atom Xatom_wm_change_state;
2556
2557 /* Record the last 100 characters stored
2558 to help debug the loss-of-chars-during-GC problem. */
2559 int temp_index;
2560 short temp_buffer[100];
2561
2562 /* Read events coming from the X server.
2563 This routine is called by the SIGIO handler.
2564 We return as soon as there are no more events to be read.
2565
2566 Events representing keys are stored in buffer BUFP,
2567 which can hold up to NUMCHARS characters.
2568 We return the number of characters stored into the buffer,
2569 thus pretending to be `read'.
2570
2571 WAITP is nonzero if we should block until input arrives.
2572 EXPECTED is nonzero if the caller knows input is available. */
2573
2574 int
2575 XTread_socket (sd, bufp, numchars, waitp, expected)
2576 register int sd;
2577 register struct input_event *bufp;
2578 register int numchars;
2579 int waitp;
2580 int expected;
2581 {
2582 int count = 0;
2583 int nbytes = 0;
2584 int mask;
2585 int items_pending; /* How many items are in the X queue. */
2586 XEvent event;
2587 struct frame *f;
2588 int event_found = 0;
2589 int prefix;
2590 Lisp_Object part;
2591
2592 if (interrupt_input_blocked)
2593 {
2594 interrupt_input_pending = 1;
2595 return -1;
2596 }
2597
2598 interrupt_input_pending = 0;
2599 BLOCK_INPUT;
2600
2601 if (numchars <= 0)
2602 abort (); /* Don't think this happens. */
2603
2604 #ifdef FIOSNBIO
2605 /* If available, Xlib uses FIOSNBIO to make the socket
2606 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2607 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2608 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2609 fcntl (fileno (stdin), F_SETFL, 0);
2610 #endif /* ! defined (FIOSNBIO) */
2611
2612 #ifndef SIGIO
2613 #ifndef HAVE_SELECT
2614 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2615 {
2616 extern int read_alarm_should_throw;
2617 read_alarm_should_throw = 1;
2618 XPeekEvent (XDISPLAY &event);
2619 read_alarm_should_throw = 0;
2620 }
2621 #endif /* HAVE_SELECT */
2622 #endif /* SIGIO */
2623
2624 while (XStuffPending () != 0)
2625 {
2626 XNextEvent (XDISPLAY &event);
2627 event_found = 1;
2628
2629 switch (event.type)
2630 {
2631 #ifdef HAVE_X11
2632 case ClientMessage:
2633 {
2634 if (event.xclient.message_type == Xatom_wm_protocols
2635 && event.xclient.format == 32)
2636 {
2637 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2638 {
2639 f = x_window_to_frame (event.xclient.window);
2640 if (f)
2641 x_focus_on_frame (f);
2642 /* Not certain about handling scroll bars here */
2643 }
2644 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2645 {
2646 /* Save state modify the WM_COMMAND property to
2647 something which can reinstate us. This notifies
2648 the session manager, who's looking for such a
2649 PropertyNotify. Can restart processing when
2650 a keyboard or mouse event arrives. */
2651 if (numchars > 0)
2652 {
2653 }
2654 }
2655 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2656 {
2657 struct frame *f = x_window_to_frame (event.xclient.window);
2658
2659 if (f)
2660 if (numchars > 0)
2661 {
2662 }
2663 }
2664 }
2665 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2666 {
2667 }
2668 else if (event.xclient.message_type == Xatom_wm_window_moved)
2669 {
2670 int new_x, new_y;
2671
2672 new_x = event.xclient.data.s[0];
2673 new_y = event.xclient.data.s[1];
2674 }
2675 }
2676 break;
2677
2678 #ifdef NEW_SELECTIONS
2679 case SelectionNotify:
2680 x_handle_selection_notify (&event);
2681 break;
2682 #endif
2683
2684 case SelectionClear: /* Someone has grabbed ownership. */
2685 #ifdef NEW_SELECTIONS
2686 {
2687 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2688
2689 if (numchars == 0)
2690 abort ();
2691
2692 bufp->kind = selection_clear_event;
2693 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2694 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2695 SELECTION_EVENT_TIME (bufp) = eventp->time;
2696 bufp++;
2697
2698 count += 1;
2699 numchars -= 1;
2700 }
2701 #else
2702 x_disown_selection (event.xselectionclear.window,
2703 event.xselectionclear.selection,
2704 event.xselectionclear.time);
2705 #endif
2706 break;
2707
2708 case SelectionRequest: /* Someone wants our selection. */
2709 #ifdef NEW_SELECTIONS
2710 {
2711 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2712
2713 if (numchars == 0)
2714 abort ();
2715
2716 bufp->kind = selection_request_event;
2717 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2718 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2719 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2720 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2721 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2722 SELECTION_EVENT_TIME (bufp) = eventp->time;
2723 bufp++;
2724
2725 count += 1;
2726 numchars -= 1;
2727 }
2728 #else
2729 x_answer_selection_request (event);
2730 #endif
2731 break;
2732
2733 case PropertyNotify:
2734 #ifdef NEW_SELECTIONS
2735 x_handle_property_notify (&event);
2736 #else
2737 /* If we're being told about a root window property, then it's
2738 a cut buffer change. */
2739 if (event.xproperty.window == ROOT_WINDOW)
2740 x_invalidate_cut_buffer_cache (&event.xproperty);
2741
2742 /* Otherwise, we're probably handling an incremental
2743 selection transmission. */
2744 else
2745 {
2746 /* If we were to do this synchronously, there'd be no worry
2747 about re-selecting. */
2748 x_send_incremental (event);
2749 }
2750 #endif
2751 break;
2752
2753 case ReparentNotify:
2754 f = x_window_to_frame (event.xreparent.window);
2755 if (f)
2756 f->display.x->parent_desc = event.xreparent.parent;
2757 break;
2758
2759 case Expose:
2760 f = x_window_to_frame (event.xexpose.window);
2761 if (f)
2762 {
2763 if (f->async_visible == 0)
2764 {
2765 f->async_visible = 1;
2766 f->async_iconified = 0;
2767 SET_FRAME_GARBAGED (f);
2768 }
2769 else
2770 {
2771 dumprectangle (x_window_to_frame (event.xexpose.window),
2772 event.xexpose.x, event.xexpose.y,
2773 event.xexpose.width, event.xexpose.height);
2774 }
2775 }
2776 else
2777 {
2778 struct scroll_bar *bar
2779 = x_window_to_scroll_bar (event.xexpose.window);
2780
2781 if (bar)
2782 x_scroll_bar_expose (bar, &event);
2783 }
2784 break;
2785
2786 case GraphicsExpose: /* This occurs when an XCopyArea's
2787 source area was obscured or not
2788 available.*/
2789 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2790 if (f)
2791 {
2792 dumprectangle (f,
2793 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2794 event.xgraphicsexpose.width,
2795 event.xgraphicsexpose.height);
2796 }
2797 break;
2798
2799 case NoExpose: /* This occurs when an XCopyArea's
2800 source area was completely
2801 available */
2802 break;
2803 #else /* ! defined (HAVE_X11) */
2804 case ExposeWindow:
2805 if (event.subwindow != 0)
2806 break; /* duplicate event */
2807 f = x_window_to_frame (event.window);
2808 if (event.window == f->display.x->icon_desc)
2809 {
2810 refreshicon (f);
2811 f->async_iconified = 1;
2812 }
2813 if (event.window == FRAME_X_WINDOW (f))
2814 {
2815 /* Say must check all windows' needs_exposure flags. */
2816 expose_all_windows = 1;
2817 f->display.x->needs_exposure = 1;
2818 f->async_visible = 1;
2819 }
2820 break;
2821
2822 case ExposeRegion:
2823 if (event.subwindow != 0)
2824 break; /* duplicate event */
2825 f = x_window_to_frame (event.window);
2826 if (event.window == f->display.x->icon_desc)
2827 {
2828 refreshicon (f);
2829 break;
2830 }
2831 /* If window already needs full redraw, ignore this rectangle. */
2832 if (expose_all_windows && f->display.x->needs_exposure)
2833 break;
2834 /* Put the event on the queue of rectangles to redraw. */
2835 if (enqueue_event (&event, &x_expose_queue))
2836 /* If it is full, we can't record the rectangle,
2837 so redraw this entire window. */
2838 {
2839 /* Say must check all windows' needs_exposure flags. */
2840 expose_all_windows = 1;
2841 f->display.x->needs_exposure = 1;
2842 }
2843 break;
2844
2845 case ExposeCopy:
2846 /* This should happen only when we are expecting it,
2847 in x_read_exposes. */
2848 abort ();
2849 #endif /* ! defined (HAVE_X11) */
2850
2851 #ifdef HAVE_X11
2852 case UnmapNotify:
2853 f = x_window_to_frame (event.xunmap.window);
2854 if (f) /* F may no longer exist if
2855 the frame was deleted. */
2856 {
2857 /* While a frame is unmapped, display generation is
2858 disabled; you don't want to spend time updating a
2859 display that won't ever be seen. */
2860 f->async_visible = 0;
2861 /* The window manager never makes a window invisible
2862 ("withdrawn"); all it does is switch between visible
2863 and iconified. Frames get into the invisible state
2864 only through x_make_frame_invisible.
2865 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2866 f->async_iconified = 1;
2867 }
2868 break;
2869
2870 case MapNotify:
2871 f = x_window_to_frame (event.xmap.window);
2872 if (f)
2873 {
2874 f->async_visible = 1;
2875 f->async_iconified = 0;
2876
2877 /* wait_reading_process_input will notice this and update
2878 the frame's display structures. */
2879 SET_FRAME_GARBAGED (f);
2880 }
2881 break;
2882
2883 /* Turn off processing if we become fully obscured. */
2884 case VisibilityNotify:
2885 break;
2886
2887 #else /* ! defined (HAVE_X11) */
2888 case UnmapWindow:
2889 f = x_window_to_frame (event.window);
2890 if (event.window == f->display.x->icon_desc)
2891 f->async_iconified = 0;
2892 if (event.window == FRAME_X_WINDOW (f))
2893 f->async_visible = 0;
2894 break;
2895 #endif /* ! defined (HAVE_X11) */
2896
2897 #ifdef HAVE_X11
2898 case KeyPress:
2899 f = x_window_to_frame (event.xkey.window);
2900
2901 if (f != 0)
2902 {
2903 KeySym keysym, orig_keysym;
2904 char copy_buffer[80];
2905 int modifiers;
2906
2907 event.xkey.state
2908 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
2909 modifiers = event.xkey.state;
2910
2911 /* This will have to go some day... */
2912
2913 /* make_lispy_event turns chars into control chars.
2914 Don't do it here because XLookupString is too eager. */
2915 event.xkey.state &= ~ControlMask;
2916 nbytes =
2917 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2918 &compose_status);
2919
2920 /* Strip off the vendor-specific keysym bit, and take a shot
2921 at recognizing the codes. HP servers have extra keysyms
2922 that fit into the MiscFunctionKey category. */
2923 orig_keysym = keysym;
2924 keysym &= ~(1<<28);
2925
2926 if (numchars > 1)
2927 {
2928 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
2929 || keysym == XK_Delete
2930 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2931 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
2932 #ifdef HPUX
2933 /* This recognizes the "extended function keys".
2934 It seems there's no cleaner way.
2935 Test IsModifierKey to avoid handling mode_switch
2936 incorrectly. */
2937 || ((unsigned) (keysym) >= XK_Select
2938 && (unsigned)(keysym) < XK_KP_Space)
2939 #endif
2940 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2941 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
2942 || x_is_vendor_fkey (orig_keysym))
2943 && ! IsModifierKey (orig_keysym)) /* wherever */
2944 {
2945 if (temp_index == sizeof temp_buffer / sizeof (short))
2946 temp_index = 0;
2947 temp_buffer[temp_index++] = keysym;
2948 bufp->kind = non_ascii_keystroke;
2949 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2950 XSET (bufp->frame_or_window, Lisp_Frame, f);
2951 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2952 bufp->timestamp = event.xkey.time;
2953 bufp++;
2954 count++;
2955 numchars--;
2956 }
2957 else if (numchars > nbytes)
2958 {
2959 register int i;
2960
2961 for (i = 0; i < nbytes; i++)
2962 {
2963 if (temp_index == sizeof temp_buffer / sizeof (short))
2964 temp_index = 0;
2965 temp_buffer[temp_index++] = copy_buffer[i];
2966 bufp->kind = ascii_keystroke;
2967 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2968 XSET (bufp->frame_or_window, Lisp_Frame, f);
2969 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2970 bufp->timestamp = event.xkey.time;
2971 bufp++;
2972 }
2973
2974 count += nbytes;
2975 numchars -= nbytes;
2976 }
2977 else
2978 abort ();
2979 }
2980 else
2981 abort ();
2982 }
2983 break;
2984 #else /* ! defined (HAVE_X11) */
2985 case KeyPressed:
2986 {
2987 register char *where_mapping;
2988
2989 f = x_window_to_frame (event.window);
2990 /* Ignore keys typed on icon windows. */
2991 if (f != 0 && event.window == f->display.x->icon_desc)
2992 break;
2993 where_mapping = XLookupMapping (&event, &nbytes);
2994 /* Nasty fix for arrow keys */
2995 if (!nbytes && IsCursorKey (event.detail & 0xff))
2996 {
2997 switch (event.detail & 0xff)
2998 {
2999 case KC_CURSOR_LEFT:
3000 where_mapping = "\002";
3001 break;
3002 case KC_CURSOR_RIGHT:
3003 where_mapping = "\006";
3004 break;
3005 case KC_CURSOR_UP:
3006 where_mapping = "\020";
3007 break;
3008 case KC_CURSOR_DOWN:
3009 where_mapping = "\016";
3010 break;
3011 }
3012 nbytes = 1;
3013 }
3014 if (numchars - nbytes > 0)
3015 {
3016 register int i;
3017
3018 for (i = 0; i < nbytes; i++)
3019 {
3020 bufp->kind = ascii_keystroke;
3021 XSET (bufp->code, Lisp_Int, where_mapping[i]);
3022 XSET (bufp->time, Lisp_Int, event.xkey.time);
3023 XSET (bufp->frame_or_window, Lisp_Frame, f);
3024 bufp++;
3025 }
3026 count += nbytes;
3027 numchars -= nbytes;
3028 }
3029 }
3030 break;
3031 #endif /* ! defined (HAVE_X11) */
3032
3033 #ifdef HAVE_X11
3034
3035 /* Here's a possible interpretation of the whole
3036 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3037 FocusIn event, you have to get a FocusOut event before you
3038 relinquish the focus. If you haven't received a FocusIn event,
3039 then a mere LeaveNotify is enough to free you. */
3040
3041 case EnterNotify:
3042 f = x_window_to_frame (event.xcrossing.window);
3043
3044 if (event.xcrossing.focus) /* Entered Window */
3045 {
3046 /* Avoid nasty pop/raise loops. */
3047 if (f && (!(f->auto_raise)
3048 || !(f->auto_lower)
3049 || (event.xcrossing.time - enter_timestamp) > 500))
3050 {
3051 x_new_focus_frame (f);
3052 enter_timestamp = event.xcrossing.time;
3053 }
3054 }
3055 else if (f == x_focus_frame)
3056 x_new_focus_frame (0);
3057
3058 break;
3059
3060 case FocusIn:
3061 f = x_window_to_frame (event.xfocus.window);
3062 if (event.xfocus.detail != NotifyPointer)
3063 x_focus_event_frame = f;
3064 if (f)
3065 x_new_focus_frame (f);
3066 break;
3067
3068
3069 case LeaveNotify:
3070 f = x_window_to_frame (event.xcrossing.window);
3071
3072 if (event.xcrossing.focus)
3073 {
3074 if (! x_focus_event_frame)
3075 x_new_focus_frame (0);
3076 else
3077 x_new_focus_frame (f);
3078 }
3079 else
3080 {
3081 if (f == x_focus_event_frame)
3082 x_focus_event_frame = 0;
3083 if (f == x_focus_frame)
3084 x_new_focus_frame (0);
3085 }
3086 break;
3087
3088 case FocusOut:
3089 f = x_window_to_frame (event.xfocus.window);
3090 if (event.xfocus.detail != NotifyPointer
3091 && f == x_focus_event_frame)
3092 x_focus_event_frame = 0;
3093 if (f && f == x_focus_frame)
3094 x_new_focus_frame (0);
3095 break;
3096
3097 #else /* ! defined (HAVE_X11) */
3098
3099 case EnterWindow:
3100 if ((event.detail & 0xFF) == 1)
3101 break; /* Coming from our own subwindow */
3102 if (event.subwindow != 0)
3103 break; /* Entering our own subwindow. */
3104
3105 {
3106 f = x_window_to_frame (event.window);
3107 x_mouse_frame = f;
3108
3109 x_new_focus_frame (f);
3110 }
3111 break;
3112
3113 case LeaveWindow:
3114 if ((event.detail & 0xFF) == 1)
3115 break; /* Entering our own subwindow */
3116 if (event.subwindow != 0)
3117 break; /* Leaving our own subwindow. */
3118
3119 x_mouse_frame = 0;
3120 if (x_focus_frame == 0
3121 && x_input_frame != 0
3122 && x_input_frame == x_window_to_frame (event.window)
3123 && event.window == FRAME_X_WINDOW (x_input_frame))
3124 {
3125 f = x_input_frame;
3126 x_input_frame = 0;
3127 if (f)
3128 frame_unhighlight (f);
3129 }
3130 break;
3131 #endif /* ! defined (HAVE_X11) */
3132
3133 #ifdef HAVE_X11
3134 case MotionNotify:
3135 {
3136 f = x_window_to_frame (event.xmotion.window);
3137 if (f)
3138 note_mouse_movement (f, &event.xmotion);
3139 else
3140 {
3141 struct scroll_bar *bar =
3142 x_window_to_scroll_bar (event.xmotion.window);
3143
3144 if (bar)
3145 x_scroll_bar_note_movement (bar, &event);
3146 }
3147 }
3148 break;
3149
3150 case ConfigureNotify:
3151 f = x_window_to_frame (event.xconfigure.window);
3152 if (f)
3153 {
3154 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3155 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3156
3157 /* Even if the number of character rows and columns has
3158 not changed, the font size may have changed, so we need
3159 to check the pixel dimensions as well. */
3160 if (columns != f->width
3161 || rows != f->height
3162 || event.xconfigure.width != f->display.x->pixel_width
3163 || event.xconfigure.height != f->display.x->pixel_height)
3164 {
3165 change_frame_size (f, rows, columns, 0, 1);
3166 SET_FRAME_GARBAGED (f);
3167 }
3168
3169 if (! event.xconfigure.send_event)
3170 {
3171 Window win, child;
3172 int win_x, win_y;
3173
3174 /* Coords are relative to the parent.
3175 Convert them to root-relative. */
3176 XTranslateCoordinates (x_current_display,
3177
3178 /* From-window, to-window. */
3179 f->display.x->parent_desc,
3180 ROOT_WINDOW,
3181
3182 /* From-position, to-position. */
3183 event.xconfigure.x,
3184 event.xconfigure.y,
3185 &win_x, &win_y,
3186
3187 /* Child of win. */
3188 &child);
3189 event.xconfigure.x = win_x;
3190 event.xconfigure.y = win_y;
3191 }
3192
3193 f->display.x->pixel_width = event.xconfigure.width;
3194 f->display.x->pixel_height = event.xconfigure.height;
3195 f->display.x->left_pos = event.xconfigure.x;
3196 f->display.x->top_pos = event.xconfigure.y;
3197 }
3198 break;
3199
3200 case ButtonPress:
3201 case ButtonRelease:
3202 {
3203 /* If we decide we want to generate an event to be seen
3204 by the rest of Emacs, we put it here. */
3205 struct input_event emacs_event;
3206 emacs_event.kind = no_event;
3207
3208 f = x_window_to_frame (event.xbutton.window);
3209 if (f)
3210 {
3211 if (!x_focus_frame || (f == x_focus_frame))
3212 construct_mouse_click (&emacs_event,
3213 &event, f);
3214 }
3215 else
3216 {
3217 struct scroll_bar *bar =
3218 x_window_to_scroll_bar (event.xbutton.window);
3219
3220 if (bar)
3221 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3222 }
3223
3224 if (numchars >= 1 && emacs_event.kind != no_event)
3225 {
3226 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3227 bufp++;
3228 count++;
3229 numchars--;
3230 }
3231 }
3232 break;
3233
3234 #else /* ! defined (HAVE_X11) */
3235 case ButtonPressed:
3236 case ButtonReleased:
3237 f = x_window_to_frame (event.window);
3238 if (f)
3239 {
3240 if (event.window == f->display.x->icon_desc)
3241 {
3242 x_make_frame_visible (f);
3243
3244 if (warp_mouse_on_deiconify)
3245 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3246 break;
3247 }
3248 if (event.window == FRAME_X_WINDOW (f))
3249 {
3250 if (f->auto_raise)
3251 x_raise_frame (f);
3252 }
3253 }
3254 enqueue_event (&event, &x_mouse_queue);
3255 if (numchars >= 2)
3256 {
3257 bufp->kind = ascii_keystroke;
3258 bufp->code = (char) 'X' & 037; /* C-x */
3259 XSET (bufp->frame_or_window, Lisp_Frame, f);
3260 XSET (bufp->time, Lisp_Int, event.xkey.time);
3261 bufp++;
3262
3263 bufp->kind = ascii_keystroke;
3264 bufp->code = (char) 0; /* C-@ */
3265 XSET (bufp->frame_or_window, Lisp_Frame, f);
3266 XSET (bufp->time, Lisp_Int, event.xkey.time);
3267 bufp++;
3268
3269 count += 2;
3270 numchars -= 2;
3271 }
3272 break;
3273 #endif /* ! defined (HAVE_X11) */
3274
3275 #ifdef HAVE_X11
3276
3277 case CirculateNotify:
3278 break;
3279 case CirculateRequest:
3280 break;
3281
3282 #endif /* ! defined (HAVE_X11) */
3283
3284 case MappingNotify:
3285 /* Someone has changed the keyboard mapping - update the
3286 local cache. */
3287 switch (event.xmapping.request)
3288 {
3289 case MappingModifier:
3290 x_find_modifier_meanings ();
3291 /* This is meant to fall through. */
3292 case MappingKeyboard:
3293 XRefreshKeyboardMapping (&event.xmapping);
3294 }
3295 break;
3296
3297 default:
3298 break;
3299 }
3300 }
3301
3302 #ifdef HAVE_SELECT
3303 if (expected && ! event_found)
3304 {
3305 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3306 there is an EOF condition; in other words, that X has died.
3307 Act as if there had been a hangup. */
3308 int fd = ConnectionNumber (x_current_display);
3309 SELECT_TYPE mask;
3310 EMACS_TIME timeout;
3311
3312 FD_SET(fd, &mask);
3313 EMACS_SET_SECS_USECS (timeout, 0, 0);
3314 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0, &timeout)
3315 && !XStuffPending ())
3316 kill (getpid (), SIGHUP);
3317 }
3318 #endif /* ! defined (HAVE_SELECT) */
3319
3320 #ifndef HAVE_X11
3321 if (updating_frame == 0)
3322 x_do_pending_expose ();
3323 #endif
3324
3325 UNBLOCK_INPUT;
3326 return count;
3327 }
3328
3329 #ifndef HAVE_X11
3330 /* Read and process only Expose events
3331 until we get an ExposeCopy event; then return.
3332 This is used in insert/delete line.
3333 We assume input is already blocked. */
3334
3335 static void
3336 x_read_exposes ()
3337 {
3338 struct frame *f;
3339 XKeyPressedEvent event;
3340
3341 while (1)
3342 {
3343 /* while there are more events*/
3344 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3345 switch (event.type)
3346 {
3347 case ExposeWindow:
3348 if (event.subwindow != 0)
3349 break; /* duplicate event */
3350 f = x_window_to_frame (event.window);
3351 if (event.window == f->display.x->icon_desc)
3352 {
3353 refreshicon (f);
3354 break;
3355 }
3356 if (event.window == FRAME_X_WINDOW (f))
3357 {
3358 expose_all_windows = 1;
3359 f->display.x->needs_exposure = 1;
3360 break;
3361 }
3362 break;
3363
3364 case ExposeRegion:
3365 if (event.subwindow != 0)
3366 break; /* duplicate event */
3367 f = x_window_to_frame (event.window);
3368 if (event.window == f->display.x->icon_desc)
3369 {
3370 refreshicon (f);
3371 break;
3372 }
3373 /* If window already needs full redraw, ignore this rectangle. */
3374 if (expose_all_windows && f->display.x->needs_exposure)
3375 break;
3376 /* Put the event on the queue of rectangles to redraw. */
3377 if (enqueue_event (&event, &x_expose_queue))
3378 /* If it is full, we can't record the rectangle,
3379 so redraw this entire window. */
3380 {
3381 /* Say must check all windows' needs_exposure flags. */
3382 expose_all_windows = 1;
3383 f->display.x->needs_exposure = 1;
3384 }
3385 break;
3386
3387 case ExposeCopy:
3388 return;
3389 }
3390 }
3391 }
3392 #endif /* HAVE_X11 */
3393
3394 \f
3395 /* Drawing the cursor. */
3396
3397
3398 /* Draw a hollow box cursor. Don't change the inside of the box. */
3399
3400 static void
3401 x_draw_box (f)
3402 struct frame *f;
3403 {
3404 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3405 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3406 int width = FONT_WIDTH (f->display.x->font);
3407 int height = FONT_HEIGHT (f->display.x->font);
3408
3409 #ifdef HAVE_X11
3410 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3411 f->display.x->cursor_gc,
3412 left, top, width - 1, height - 1);
3413 #else /* ! defined (HAVE_X11) */
3414 XPixSet (FRAME_X_WINDOW (f),
3415 left, top, width, 1,
3416 f->display.x->cursor_pixel);
3417
3418 XPixSet (FRAME_X_WINDOW (f),
3419 left, top, 1, height,
3420 f->display.x->cursor_pixel);
3421
3422 XPixSet (FRAME_X_WINDOW (f),
3423 left+width-1, top, 1, height,
3424 f->display.x->cursor_pixel);
3425
3426 XPixSet (FRAME_X_WINDOW (f),
3427 left, top+height-1, width, 1,
3428 f->display.x->cursor_pixel);
3429 #endif /* ! defined (HAVE_X11) */
3430 }
3431
3432 /* Clear the cursor of frame F to background color,
3433 and mark the cursor as not shown.
3434 This is used when the text where the cursor is
3435 is about to be rewritten. */
3436
3437 static void
3438 clear_cursor (f)
3439 struct frame *f;
3440 {
3441 int mask;
3442
3443 if (! FRAME_VISIBLE_P (f)
3444 || f->phys_cursor_x < 0)
3445 return;
3446
3447 #ifdef HAVE_X11
3448 x_display_cursor (f, 0);
3449 #else /* ! defined (HAVE_X11) */
3450 XPixSet (FRAME_X_WINDOW (f),
3451 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3452 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3453 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3454 f->display.x->background_pixel);
3455 #endif /* ! defined (HAVE_X11) */
3456 f->phys_cursor_x = -1;
3457 }
3458
3459 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3460 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3461 glyph drawn. */
3462
3463 static void
3464 x_draw_single_glyph (f, row, column, glyph, highlight)
3465 struct frame *f;
3466 int row, column;
3467 GLYPH glyph;
3468 int highlight;
3469 {
3470 dumpglyphs (f,
3471 CHAR_TO_PIXEL_COL (f, column),
3472 CHAR_TO_PIXEL_ROW (f, row),
3473 &glyph, 1, highlight);
3474 }
3475
3476 static void
3477 x_display_bar_cursor (f, on)
3478 struct frame *f;
3479 int on;
3480 {
3481 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3482
3483 /* This is pointless on invisible frames, and dangerous on garbaged
3484 frames; in the latter case, the frame may be in the midst of
3485 changing its size, and curs_x and curs_y may be off the frame. */
3486 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3487 return;
3488
3489 if (! on && f->phys_cursor_x < 0)
3490 return;
3491
3492 /* If we're not updating, then we want to use the current frame's
3493 cursor position, not our local idea of where the cursor ought to be. */
3494 if (f != updating_frame)
3495 {
3496 curs_x = FRAME_CURSOR_X (f);
3497 curs_y = FRAME_CURSOR_Y (f);
3498 }
3499
3500 /* If there is anything wrong with the current cursor state, remove it. */
3501 if (f->phys_cursor_x >= 0
3502 && (!on
3503 || f->phys_cursor_x != curs_x
3504 || f->phys_cursor_y != curs_y
3505 || f->display.x->current_cursor != bar_cursor))
3506 {
3507 /* Erase the cursor by redrawing the character underneath it. */
3508 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3509 f->phys_cursor_glyph,
3510 current_glyphs->highlight[f->phys_cursor_y]);
3511 f->phys_cursor_x = -1;
3512 }
3513
3514 /* If we now need a cursor in the new place or in the new form, do it so. */
3515 if (on
3516 && (f->phys_cursor_x < 0
3517 || (f->display.x->current_cursor != bar_cursor)))
3518 {
3519 f->phys_cursor_glyph
3520 = ((current_glyphs->enable[curs_y]
3521 && curs_x < current_glyphs->used[curs_y])
3522 ? current_glyphs->glyphs[curs_y][curs_x]
3523 : SPACEGLYPH);
3524 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3525 f->display.x->cursor_gc,
3526 CHAR_TO_PIXEL_COL (f, curs_x),
3527 CHAR_TO_PIXEL_ROW (f, curs_y),
3528 1, FONT_HEIGHT (f->display.x->font));
3529
3530 f->phys_cursor_x = curs_x;
3531 f->phys_cursor_y = curs_y;
3532
3533 f->display.x->current_cursor = bar_cursor;
3534 }
3535
3536 if (updating_frame != f)
3537 XFlushQueue ();
3538 }
3539
3540
3541 /* Turn the displayed cursor of frame F on or off according to ON.
3542 If ON is nonzero, where to put the cursor is specified
3543 by F->cursor_x and F->cursor_y. */
3544
3545 static void
3546 x_display_box_cursor (f, on)
3547 struct frame *f;
3548 int on;
3549 {
3550 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3551
3552 /* This is pointless on invisible frames, and dangerous on garbaged
3553 frames; in the latter case, the frame may be in the midst of
3554 changing its size, and curs_x and curs_y may be off the frame. */
3555 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3556 return;
3557
3558 /* If cursor is off and we want it off, return quickly. */
3559 if (!on && f->phys_cursor_x < 0)
3560 return;
3561
3562 /* If we're not updating, then we want to use the current frame's
3563 cursor position, not our local idea of where the cursor ought to be. */
3564 if (f != updating_frame)
3565 {
3566 curs_x = FRAME_CURSOR_X (f);
3567 curs_y = FRAME_CURSOR_Y (f);
3568 }
3569
3570 /* If cursor is currently being shown and we don't want it to be
3571 or it is in the wrong place,
3572 or we want a hollow box and it's not so, (pout!)
3573 erase it. */
3574 if (f->phys_cursor_x >= 0
3575 && (!on
3576 || f->phys_cursor_x != curs_x
3577 || f->phys_cursor_y != curs_y
3578 || (f->display.x->current_cursor != hollow_box_cursor
3579 && (f != x_highlight_frame))))
3580 {
3581 /* Erase the cursor by redrawing the character underneath it. */
3582 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3583 f->phys_cursor_glyph,
3584 current_glyphs->highlight[f->phys_cursor_y]);
3585 f->phys_cursor_x = -1;
3586 }
3587
3588 /* If we want to show a cursor,
3589 or we want a box cursor and it's not so,
3590 write it in the right place. */
3591 if (on
3592 && (f->phys_cursor_x < 0
3593 || (f->display.x->current_cursor != filled_box_cursor
3594 && f == x_highlight_frame)))
3595 {
3596 f->phys_cursor_glyph
3597 = ((current_glyphs->enable[curs_y]
3598 && curs_x < current_glyphs->used[curs_y])
3599 ? current_glyphs->glyphs[curs_y][curs_x]
3600 : SPACEGLYPH);
3601 if (f != x_highlight_frame)
3602 {
3603 x_draw_box (f);
3604 f->display.x->current_cursor = hollow_box_cursor;
3605 }
3606 else
3607 {
3608 x_draw_single_glyph (f, curs_y, curs_x,
3609 f->phys_cursor_glyph, 2);
3610 f->display.x->current_cursor = filled_box_cursor;
3611 }
3612
3613 f->phys_cursor_x = curs_x;
3614 f->phys_cursor_y = curs_y;
3615 }
3616
3617 if (updating_frame != f)
3618 XFlushQueue ();
3619 }
3620
3621 x_display_cursor (f, on)
3622 struct frame *f;
3623 int on;
3624 {
3625 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3626 x_display_box_cursor (f, on);
3627 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3628 x_display_bar_cursor (f, on);
3629 else
3630 /* Those are the only two we have implemented! */
3631 abort ();
3632 }
3633 \f
3634 /* Icons. */
3635
3636 /* Refresh bitmap kitchen sink icon for frame F
3637 when we get an expose event for it. */
3638
3639 refreshicon (f)
3640 struct frame *f;
3641 {
3642 #ifdef HAVE_X11
3643 /* Normally, the window manager handles this function. */
3644 #else /* ! defined (HAVE_X11) */
3645 int mask;
3646
3647 if (f->display.x->icon_bitmap_flag)
3648 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3649 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3650 icon_bitmap, GXcopy, AllPlanes);
3651 else
3652 {
3653 extern struct frame *selected_frame;
3654 struct Lisp_String *str;
3655 unsigned char *string;
3656
3657 string
3658 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3659
3660 if (f->display.x->icon_label != string)
3661 {
3662 f->display.x->icon_label = string;
3663 XChangeWindow (f->display.x->icon_desc,
3664 XQueryWidth (string, icon_font_info->id) + 10,
3665 icon_font_info->height + 10);
3666 }
3667
3668 XText (f->display.x->icon_desc, 5, 5, string,
3669 str->size, icon_font_info->id,
3670 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3671 }
3672 XFlushQueue ();
3673 #endif /* ! defined (HAVE_X11) */
3674 }
3675
3676 /* Make the x-window of frame F use the gnu icon bitmap. */
3677
3678 int
3679 x_bitmap_icon (f)
3680 struct frame *f;
3681 {
3682 int mask;
3683 Window icon_window;
3684
3685 if (FRAME_X_WINDOW (f) == 0)
3686 return 1;
3687
3688 #ifdef HAVE_X11
3689 if (! icon_bitmap)
3690 icon_bitmap =
3691 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3692 gnu_bits, gnu_width, gnu_height);
3693 x_wm_set_icon_pixmap (f, icon_bitmap);
3694 f->display.x->icon_bitmap_flag = 1;
3695 #else /* ! defined (HAVE_X11) */
3696 if (f->display.x->icon_desc)
3697 {
3698 XClearIconWindow (FRAME_X_WINDOW (f));
3699 XDestroyWindow (f->display.x->icon_desc);
3700 }
3701
3702 icon_window = XCreateWindow (f->display.x->parent_desc,
3703 0, 0, sink_width, sink_height,
3704 2, WhitePixmap, (Pixmap) NULL);
3705
3706 if (icon_window == 0)
3707 return 1;
3708
3709 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3710 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3711
3712 f->display.x->icon_desc = icon_window;
3713 f->display.x->icon_bitmap_flag = 1;
3714
3715 if (icon_bitmap == 0)
3716 icon_bitmap
3717 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3718 #endif /* ! defined (HAVE_X11) */
3719
3720 return 0;
3721 }
3722
3723
3724 /* Make the x-window of frame F use a rectangle with text. */
3725
3726 int
3727 x_text_icon (f, icon_name)
3728 struct frame *f;
3729 char *icon_name;
3730 {
3731 #ifndef HAVE_X11
3732 int mask;
3733 int width;
3734 Window icon_window;
3735 char *X_DefaultValue;
3736 Bitmap b1;
3737
3738 #ifndef WhitePixel
3739 #define WhitePixel 1
3740 #endif /* WhitePixel */
3741
3742 #ifndef BlackPixel
3743 #define BlackPixel 0
3744 #endif /* BlackPixel */
3745 #endif /* HAVE_X11 */
3746
3747 if (FRAME_X_WINDOW (f) == 0)
3748 return 1;
3749
3750 #ifdef HAVE_X11
3751 if (icon_name)
3752 f->display.x->icon_label = icon_name;
3753 else
3754 if (! f->display.x->icon_label)
3755 f->display.x->icon_label = " *emacs* ";
3756
3757 #if 0
3758 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3759 (char *) f->display.x->icon_label);
3760 #endif
3761
3762 f->display.x->icon_bitmap_flag = 0;
3763 x_wm_set_icon_pixmap (f, 0);
3764 #else /* ! defined (HAVE_X11) */
3765 if (icon_font_info == 0)
3766 icon_font_info
3767 = XGetFont (XGetDefault (XDISPLAY
3768 (char *) XSTRING (Vinvocation_name)->data,
3769 "BodyFont"));
3770
3771 if (f->display.x->icon_desc)
3772 {
3773 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3774 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3775 }
3776
3777 if (icon_name)
3778 f->display.x->icon_label = (unsigned char *) icon_name;
3779 else
3780 if (! f->display.x->icon_label)
3781 f->display.x->icon_label = XSTRING (f->name)->data;
3782
3783 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3784 icon_window = XCreateWindow (f->display.x->parent_desc,
3785 f->display.x->left_pos,
3786 f->display.x->top_pos,
3787 width + 10, icon_font_info->height + 10,
3788 2, BlackPixmap, WhitePixmap);
3789
3790 if (icon_window == 0)
3791 return 1;
3792
3793 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3794 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3795
3796 f->display.x->icon_desc = icon_window;
3797 f->display.x->icon_bitmap_flag = 0;
3798 f->display.x->icon_label = 0;
3799 #endif /* ! defined (HAVE_X11) */
3800
3801 return 0;
3802 }
3803 \f
3804 /* Handling X errors. */
3805
3806 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3807 X server's connection, or an error reported via the X protocol. */
3808
3809 static SIGTYPE
3810 x_connection_closed ()
3811 {
3812 if (_Xdebug)
3813 abort ();
3814
3815 shut_down_emacs (0, 1, Qnil);
3816
3817 exit (70);
3818 }
3819
3820 /* An X error handler which prints an error message and then kills
3821 Emacs. This is what's normally installed as Xlib's handler for
3822 protocol errors. */
3823 static int
3824 x_error_quitter (display, error)
3825 Display *display;
3826 XErrorEvent *error;
3827 {
3828 char buf[256];
3829
3830 /* Note that there is no real way portable across R3/R4 to get the
3831 original error handler. */
3832
3833 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3834 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3835 buf, error->request_code);
3836
3837 #if 0
3838 /* While we're testing Emacs 19, we'll just dump core whenever we
3839 get an X error, so we can figure out why it happened. */
3840 abort ();
3841 #endif
3842
3843 x_connection_closed ();
3844 }
3845
3846 /* A handler for X IO errors which prints an error message and then
3847 kills Emacs. This is what is always installed as Xlib's handler
3848 for I/O errors. */
3849 static int
3850 x_io_error_quitter (display)
3851 Display *display;
3852 {
3853 fprintf (stderr, "Connection to X server %s lost.\n",
3854 XDisplayName (DisplayString (display)));
3855
3856 #if 0
3857 /* While we're testing Emacs 19, we'll just dump core whenever we
3858 get an X error, so we can figure out why it happened. */
3859 abort ();
3860 #endif
3861
3862 x_connection_closed ();
3863 }
3864
3865 /* A buffer for storing X error messages. */
3866 static char *x_caught_error_message;
3867 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3868
3869 /* An X error handler which stores the error message in
3870 x_caught_error_message. This is what's installed when
3871 x_catch_errors is in effect. */
3872 static int
3873 x_error_catcher (display, error)
3874 Display *display;
3875 XErrorEvent *error;
3876 {
3877 XGetErrorText (display, error->error_code,
3878 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
3879 }
3880
3881
3882 /* Begin trapping X errors.
3883
3884 After calling this function, X protocol errors no longer cause
3885 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3886
3887 Calling x_check_errors signals an Emacs error if an X error has
3888 occurred since the last call to x_catch_errors or x_check_errors.
3889
3890 Calling x_uncatch_errors resumes the normal error handling. */
3891
3892 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3893
3894 void
3895 x_catch_errors ()
3896 {
3897 /* Make sure any errors from previous requests have been dealt with. */
3898 XSync (x_current_display, False);
3899
3900 /* Set up the error buffer. */
3901 x_caught_error_message
3902 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
3903 x_caught_error_message[0] = '\0';
3904
3905 /* Install our little error handler. */
3906 XHandleError (x_error_catcher);
3907 }
3908
3909 /* If any X protocol errors have arrived since the last call to
3910 x_catch_errors or x_check_errors, signal an Emacs error using
3911 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3912 void
3913 x_check_errors (format)
3914 char *format;
3915 {
3916 /* Make sure to catch any errors incurred so far. */
3917 XSync (x_current_display, False);
3918
3919 if (x_caught_error_message[0])
3920 {
3921 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
3922
3923 sprintf (buf, format, x_caught_error_message);
3924 x_uncatch_errors ();
3925 error (buf);
3926 }
3927 }
3928
3929 void
3930 x_uncatch_errors ()
3931 {
3932 xfree (x_caught_error_message);
3933 x_caught_error_message = 0;
3934 XHandleError (x_error_quitter);
3935 }
3936
3937 #if 0
3938 static unsigned int x_wire_count;
3939 x_trace_wire ()
3940 {
3941 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3942 }
3943 #endif /* ! 0 */
3944
3945 \f
3946 /* Changing the font of the frame. */
3947
3948 /* Set the font of the x-window specified by frame F
3949 to the font named NEWNAME. This is safe to use
3950 even before F has an actual x-window. */
3951
3952 #ifdef HAVE_X11
3953
3954 /* A table of all the fonts we have already loaded. */
3955 static XFontStruct **x_font_table;
3956
3957 /* The current capacity of x_font_table. */
3958 static int x_font_table_size;
3959
3960 /* The number of fonts actually stored in x_font_table.
3961 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3962 0 <= n_fonts <= x_font_table_size. */
3963 static int n_fonts;
3964
3965 Lisp_Object
3966 x_new_font (f, fontname)
3967 struct frame *f;
3968 register char *fontname;
3969 {
3970 int already_loaded;
3971 int n_matching_fonts;
3972 XFontStruct *font_info;
3973 char **font_names;
3974
3975 /* Get a list of all the fonts that match this name. Once we
3976 have a list of matching fonts, we compare them against the fonts
3977 we already have by comparing font ids. */
3978 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3979 1024, &n_matching_fonts,
3980 &font_info);
3981 /* Apparently it doesn't set n_matching_fonts to zero when it can't
3982 find any matches; font_names == 0 is the only clue. */
3983 if (! font_names)
3984 n_matching_fonts = 0;
3985
3986 /* Don't just give up if n_matching_fonts is 0.
3987 Apparently there's a bug on Suns: XListFontsWithInfo can
3988 fail to find a font, but XLoadQueryFont may still find it. */
3989
3990 /* See if we've already loaded a matching font. */
3991 already_loaded = -1;
3992 if (n_matching_fonts != 0)
3993 {
3994 int i, j;
3995
3996 for (i = 0; i < n_fonts; i++)
3997 for (j = 0; j < n_matching_fonts; j++)
3998 if (x_font_table[i]->fid == font_info[j].fid)
3999 {
4000 already_loaded = i;
4001 fontname = font_names[j];
4002 goto found_font;
4003 }
4004 }
4005 found_font:
4006
4007 /* If we have, just return it from the table. */
4008 if (already_loaded > 0)
4009 f->display.x->font = x_font_table[already_loaded];
4010
4011 /* Otherwise, load the font and add it to the table. */
4012 else
4013 {
4014 int i;
4015 XFontStruct *font;
4016
4017 /* Try to find a character-cell font in the list. */
4018 #if 0
4019 /* A laudable goal, but this isn't how to do it. */
4020 for (i = 0; i < n_matching_fonts; i++)
4021 if (! font_info[i].per_char)
4022 break;
4023 #else
4024 i = 0;
4025 #endif
4026
4027 /* See comment above. */
4028 if (n_matching_fonts != 0)
4029 fontname = font_names[i];
4030
4031 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
4032 if (! font)
4033 {
4034 /* Free the information from XListFontsWithInfo. */
4035 if (n_matching_fonts)
4036 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4037 return Qnil;
4038 }
4039
4040 /* Do we need to create the table? */
4041 if (x_font_table_size == 0)
4042 {
4043 x_font_table_size = 16;
4044 x_font_table
4045 = (XFontStruct **) xmalloc (x_font_table_size
4046 * sizeof (x_font_table[0]));
4047 }
4048 /* Do we need to grow the table? */
4049 else if (n_fonts >= x_font_table_size)
4050 {
4051 x_font_table_size *= 2;
4052 x_font_table
4053 = (XFontStruct **) xrealloc (x_font_table,
4054 (x_font_table_size
4055 * sizeof (x_font_table[0])));
4056 }
4057
4058 f->display.x->font = x_font_table[n_fonts++] = font;
4059 }
4060
4061 /* Now make the frame display the given font. */
4062 if (FRAME_X_WINDOW (f) != 0)
4063 {
4064 XSetFont (x_current_display, f->display.x->normal_gc,
4065 f->display.x->font->fid);
4066 XSetFont (x_current_display, f->display.x->reverse_gc,
4067 f->display.x->font->fid);
4068 XSetFont (x_current_display, f->display.x->cursor_gc,
4069 f->display.x->font->fid);
4070
4071 x_set_window_size (f, f->width, f->height);
4072 }
4073
4074 {
4075 Lisp_Object lispy_name = build_string (fontname);
4076
4077
4078 /* Free the information from XListFontsWithInfo. The data
4079 we actually retain comes from XLoadQueryFont. */
4080 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4081
4082 return lispy_name;
4083 }
4084 }
4085 #else /* ! defined (HAVE_X11) */
4086 x_new_font (f, newname)
4087 struct frame *f;
4088 register char *newname;
4089 {
4090 FONT_TYPE *temp;
4091 int mask;
4092
4093 temp = XGetFont (newname);
4094 if (temp == (FONT_TYPE *) 0)
4095 return 1;
4096
4097 if (f->display.x->font)
4098 XLoseFont (f->display.x->font);
4099
4100 f->display.x->font = temp;
4101
4102 if (FRAME_X_WINDOW (f) != 0)
4103 x_set_window_size (f, f->width, f->height);
4104
4105 return 0;
4106 }
4107 #endif /* ! defined (HAVE_X11) */
4108 \f
4109 /* X Window sizes and positions. */
4110
4111 x_calc_absolute_position (f)
4112 struct frame *f;
4113 {
4114 #ifdef HAVE_X11
4115 if (f->display.x->left_pos < 0)
4116 f->display.x->left_pos = (x_screen_width
4117 - 2 * f->display.x->border_width
4118 - PIXEL_WIDTH (f)
4119 + f->display.x->left_pos);
4120
4121 if (f->display.x->top_pos < 0)
4122 f->display.x->top_pos = (x_screen_height
4123 - 2 * f->display.x->border_width
4124 - PIXEL_HEIGHT (f)
4125 + f->display.x->top_pos);
4126 #else /* ! defined (HAVE_X11) */
4127 WINDOWINFO_TYPE parentinfo;
4128
4129 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
4130
4131 if (f->display.x->left_pos < 0)
4132 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4133 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
4134
4135 if (f->display.x->top_pos < 0)
4136 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4137 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
4138 #endif /* ! defined (HAVE_X11) */
4139 }
4140
4141 x_set_offset (f, xoff, yoff)
4142 struct frame *f;
4143 register int xoff, yoff;
4144 {
4145 f->display.x->top_pos = yoff;
4146 f->display.x->left_pos = xoff;
4147 x_calc_absolute_position (f);
4148
4149 BLOCK_INPUT;
4150 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
4151 f->display.x->left_pos, f->display.x->top_pos);
4152 #ifdef HAVE_X11
4153 x_wm_set_size_hint (f, 0);
4154 #endif /* ! defined (HAVE_X11) */
4155 UNBLOCK_INPUT;
4156 }
4157
4158 /* Call this to change the size of frame F's x-window. */
4159
4160 x_set_window_size (f, cols, rows)
4161 struct frame *f;
4162 int cols, rows;
4163 {
4164 int pixelwidth, pixelheight;
4165 int mask;
4166
4167 BLOCK_INPUT;
4168
4169 check_frame_size (f, &rows, &cols);
4170 f->display.x->vertical_scroll_bar_extra =
4171 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4172 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
4173 : 0);
4174 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4175 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4176
4177 #ifdef HAVE_X11
4178 x_wm_set_size_hint (f, 0);
4179 #endif /* ! defined (HAVE_X11) */
4180 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
4181
4182 /* Now, strictly speaking, we can't be sure that this is accurate,
4183 but the window manager will get around to dealing with the size
4184 change request eventually, and we'll hear how it went when the
4185 ConfigureNotify event gets here.
4186
4187 We could just not bother storing any of this information here,
4188 and let the ConfigureNotify event set everything up, but that
4189 might be kind of confusing to the lisp code, since size changes
4190 wouldn't be reported in the frame parameters until some random
4191 point in the future when the ConfigureNotify event arrives. */
4192 change_frame_size (f, rows, cols, 0, 0);
4193 PIXEL_WIDTH (f) = pixelwidth;
4194 PIXEL_HEIGHT (f) = pixelheight;
4195
4196 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4197 receive in the ConfigureNotify event; if we get what we asked
4198 for, then the event won't cause the screen to become garbaged, so
4199 we have to make sure to do it here. */
4200 SET_FRAME_GARBAGED (f);
4201
4202 XFlushQueue ();
4203 UNBLOCK_INPUT;
4204 }
4205
4206 #ifndef HAVE_X11
4207 x_set_resize_hint (f)
4208 struct frame *f;
4209 {
4210 XSetResizeHint (FRAME_X_WINDOW (f),
4211 2 * f->display.x->internal_border_width,
4212 2 * f->display.x->internal_border_width,
4213 FONT_WIDTH (f->display.x->font),
4214 FONT_HEIGHT (f->display.x->font));
4215 }
4216 #endif /* HAVE_X11 */
4217 \f
4218 /* Mouse warping, focus shifting, raising and lowering. */
4219
4220 x_set_mouse_position (f, x, y)
4221 struct frame *f;
4222 int x, y;
4223 {
4224 int pix_x, pix_y;
4225
4226 x_raise_frame (f);
4227
4228 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4229 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4230
4231 if (pix_x < 0) pix_x = 0;
4232 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4233
4234 if (pix_y < 0) pix_y = 0;
4235 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4236
4237 BLOCK_INPUT;
4238
4239 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4240 UNBLOCK_INPUT;
4241 }
4242
4243 #ifdef HAVE_X11
4244 x_focus_on_frame (f)
4245 struct frame *f;
4246 {
4247 x_raise_frame (f);
4248 #if 0
4249 /* I don't think that the ICCCM allows programs to do things like this
4250 without the interaction of the window manager. Whatever you end up
4251 doing with this code, do it to x_unfocus_frame too. */
4252 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4253 RevertToPointerRoot, CurrentTime);
4254 #endif /* ! 0 */
4255 }
4256
4257 x_unfocus_frame (f)
4258 struct frame *f;
4259 {
4260 #if 0
4261 /* Look at the remarks in x_focus_on_frame. */
4262 if (x_focus_frame == f)
4263 XSetInputFocus (x_current_display, PointerRoot,
4264 RevertToPointerRoot, CurrentTime);
4265 #endif /* ! 0 */
4266 }
4267
4268 #endif /* ! defined (HAVE_X11) */
4269
4270 /* Raise frame F. */
4271
4272 x_raise_frame (f)
4273 struct frame *f;
4274 {
4275 if (f->async_visible)
4276 {
4277 BLOCK_INPUT;
4278 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4279 XFlushQueue ();
4280 UNBLOCK_INPUT;
4281 }
4282 }
4283
4284 /* Lower frame F. */
4285
4286 x_lower_frame (f)
4287 struct frame *f;
4288 {
4289 if (f->async_visible)
4290 {
4291 BLOCK_INPUT;
4292 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4293 XFlushQueue ();
4294 UNBLOCK_INPUT;
4295 }
4296 }
4297
4298 static void
4299 XTframe_raise_lower (f, raise)
4300 FRAME_PTR f;
4301 int raise;
4302 {
4303 if (raise)
4304 x_raise_frame (f);
4305 else
4306 x_lower_frame (f);
4307 }
4308
4309
4310 /* Change from withdrawn state to mapped state. */
4311
4312 x_make_frame_visible (f)
4313 struct frame *f;
4314 {
4315 int mask;
4316
4317 BLOCK_INPUT;
4318
4319 if (! FRAME_VISIBLE_P (f))
4320 {
4321 #ifdef HAVE_X11
4322 if (! EQ (Vx_no_window_manager, Qt))
4323 x_wm_set_window_state (f, NormalState);
4324
4325 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4326 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4327 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4328 #else /* ! defined (HAVE_X11) */
4329 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4330 if (f->display.x->icon_desc != 0)
4331 XUnmapWindow (f->display.x->icon_desc);
4332
4333 /* Handled by the MapNotify event for X11 */
4334 f->async_visible = 1;
4335 f->async_iconified = 0;
4336
4337 /* NOTE: this may cause problems for the first frame. */
4338 XTcursor_to (0, 0);
4339 #endif /* ! defined (HAVE_X11) */
4340 }
4341
4342 XFlushQueue ();
4343
4344 UNBLOCK_INPUT;
4345 }
4346
4347 /* Change from mapped state to withdrawn state. */
4348
4349 x_make_frame_invisible (f)
4350 struct frame *f;
4351 {
4352 int mask;
4353
4354 /* Don't keep the highlight on an invisible frame. */
4355 if (x_highlight_frame == f)
4356 x_highlight_frame = 0;
4357
4358 if (! f->async_visible && ! f->async_iconified)
4359 return;
4360
4361 BLOCK_INPUT;
4362
4363 #ifdef HAVE_X11R4
4364
4365 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4366 DefaultScreen (x_current_display)))
4367 {
4368 UNBLOCK_INPUT_RESIGNAL;
4369 error ("can't notify window manager of window withdrawal");
4370 }
4371
4372 #else /* ! defined (HAVE_X11R4) */
4373 #ifdef HAVE_X11
4374
4375 /* Tell the window manager what we're going to do. */
4376 if (! EQ (Vx_no_window_manager, Qt))
4377 {
4378 XEvent unmap;
4379
4380 unmap.xunmap.type = UnmapNotify;
4381 unmap.xunmap.window = FRAME_X_WINDOW (f);
4382 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4383 unmap.xunmap.from_configure = False;
4384 if (! XSendEvent (x_current_display,
4385 DefaultRootWindow (x_current_display),
4386 False,
4387 SubstructureRedirectMask|SubstructureNotifyMask,
4388 &unmap))
4389 {
4390 UNBLOCK_INPUT_RESIGNAL;
4391 error ("can't notify window manager of withdrawal");
4392 }
4393 }
4394
4395 /* Unmap the window ourselves. Cheeky! */
4396 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4397
4398 #else /* ! defined (HAVE_X11) */
4399
4400 XUnmapWindow (FRAME_X_WINDOW (f));
4401 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4402 if (f->display.x->icon_desc != 0)
4403 XUnmapWindow (f->display.x->icon_desc);
4404
4405 #endif /* ! defined (HAVE_X11) */
4406 #endif /* ! defined (HAVE_X11R4) */
4407
4408 XFlushQueue ();
4409 UNBLOCK_INPUT;
4410 }
4411
4412 /* Change window state from mapped to iconified. */
4413
4414 x_iconify_frame (f)
4415 struct frame *f;
4416 {
4417 int mask;
4418
4419 /* Don't keep the highlight on an invisible frame. */
4420 if (x_highlight_frame == f)
4421 x_highlight_frame = 0;
4422
4423 if (f->async_iconified)
4424 return;
4425
4426 BLOCK_INPUT;
4427
4428 #ifdef HAVE_X11
4429 /* Since we don't know which revision of X we're running, we'll use both
4430 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4431
4432 /* X11R4: send a ClientMessage to the window manager using the
4433 WM_CHANGE_STATE type. */
4434 {
4435 XEvent message;
4436
4437 message.xclient.window = FRAME_X_WINDOW (f);
4438 message.xclient.type = ClientMessage;
4439 message.xclient.message_type = Xatom_wm_change_state;
4440 message.xclient.format = 32;
4441 message.xclient.data.l[0] = IconicState;
4442
4443 if (! XSendEvent (x_current_display,
4444 DefaultRootWindow (x_current_display),
4445 False,
4446 SubstructureRedirectMask | SubstructureNotifyMask,
4447 &message))
4448 {
4449 UNBLOCK_INPUT_RESIGNAL;
4450 error ("Can't notify window manager of iconification.");
4451 }
4452 }
4453
4454 /* X11R3: set the initial_state field of the window manager hints to
4455 IconicState. */
4456 x_wm_set_window_state (f, IconicState);
4457
4458 f->async_iconified = 1;
4459 #else /* ! defined (HAVE_X11) */
4460 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4461
4462 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4463 if (f->display.x->icon_desc != 0)
4464 {
4465 XMapWindow (XDISPLAY f->display.x->icon_desc);
4466 refreshicon (f);
4467 }
4468 #endif /* ! defined (HAVE_X11) */
4469
4470 XFlushQueue ();
4471 UNBLOCK_INPUT;
4472 }
4473
4474 /* Destroy the X window of frame F. */
4475
4476 x_destroy_window (f)
4477 struct frame *f;
4478 {
4479 BLOCK_INPUT;
4480
4481 if (f->display.x->icon_desc != 0)
4482 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4483 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4484 free_frame_faces (f);
4485 XFlushQueue ();
4486
4487 xfree (f->display.x);
4488 f->display.x = 0;
4489 if (f == x_focus_frame)
4490 x_focus_frame = 0;
4491 if (f == x_highlight_frame)
4492 x_highlight_frame = 0;
4493
4494 UNBLOCK_INPUT;
4495 }
4496 \f
4497 /* Manage event queues for X10. */
4498
4499 #ifndef HAVE_X11
4500
4501 /* Manage event queues.
4502
4503 This code is only used by the X10 support.
4504
4505 We cannot leave events in the X queue and get them when we are ready
4506 because X does not provide a subroutine to get only a certain kind
4507 of event but not block if there are no queued events of that kind.
4508
4509 Therefore, we must examine events as they come in and copy events
4510 of certain kinds into our private queues.
4511
4512 All ExposeRegion events are put in x_expose_queue.
4513 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4514
4515
4516 /* Write the event *P_XREP into the event queue *QUEUE.
4517 If the queue is full, do nothing, but return nonzero. */
4518
4519 int
4520 enqueue_event (p_xrep, queue)
4521 register XEvent *p_xrep;
4522 register struct event_queue *queue;
4523 {
4524 int newindex = queue->windex + 1;
4525 if (newindex == EVENT_BUFFER_SIZE)
4526 newindex = 0;
4527 if (newindex == queue->rindex)
4528 return -1;
4529 queue->xrep[queue->windex] = *p_xrep;
4530 queue->windex = newindex;
4531 return 0;
4532 }
4533
4534 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4535 If *QUEUE is empty, do nothing and return 0. */
4536
4537 int
4538 dequeue_event (p_xrep, queue)
4539 register XEvent *p_xrep;
4540 register struct event_queue *queue;
4541 {
4542 if (queue->windex == queue->rindex)
4543 return 0;
4544 *p_xrep = queue->xrep[queue->rindex++];
4545 if (queue->rindex == EVENT_BUFFER_SIZE)
4546 queue->rindex = 0;
4547 return 1;
4548 }
4549
4550 /* Return the number of events buffered in *QUEUE. */
4551
4552 int
4553 queue_event_count (queue)
4554 register struct event_queue *queue;
4555 {
4556 int tem = queue->windex - queue->rindex;
4557 if (tem >= 0)
4558 return tem;
4559 return EVENT_BUFFER_SIZE + tem;
4560 }
4561
4562 /* Return nonzero if mouse input is pending. */
4563
4564 int
4565 mouse_event_pending_p ()
4566 {
4567 return queue_event_count (&x_mouse_queue);
4568 }
4569 #endif /* HAVE_X11 */
4570 \f
4571 /* Setting window manager hints. */
4572
4573 #ifdef HAVE_X11
4574
4575 x_wm_set_size_hint (f, prompting)
4576 struct frame *f;
4577 long prompting;
4578 {
4579 XSizeHints size_hints;
4580 Window window = FRAME_X_WINDOW (f);
4581
4582 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
4583
4584 flexlines = f->height;
4585
4586 size_hints.x = f->display.x->left_pos;
4587 size_hints.y = f->display.x->top_pos;
4588 size_hints.height = PIXEL_HEIGHT (f);
4589 size_hints.width = PIXEL_WIDTH (f);
4590 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4591 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4592 #if 0
4593 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4594 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4595 #endif
4596 {
4597 int base_width, base_height;
4598
4599 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4600 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4601
4602 {
4603 int min_rows = 0, min_cols = 0;
4604 check_frame_size (f, &min_rows, &min_cols);
4605
4606 /* The window manager uses the base width hints to calculate the
4607 current number of rows and columns in the frame while
4608 resizing; min_width and min_height aren't useful for this
4609 purpose, since they might not give the dimensions for a
4610 zero-row, zero-column frame.
4611
4612 We use the base_width and base_height members if we have
4613 them; otherwise, we set the min_width and min_height members
4614 to the size for a zero x zero frame. */
4615
4616 #ifdef HAVE_X11R4
4617 size_hints.flags |= PBaseSize;
4618 size_hints.base_width = base_width;
4619 size_hints.base_height = base_height;
4620 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4621 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4622 #else
4623 size_hints.min_width = base_width;
4624 size_hints.min_height = base_height;
4625 #endif
4626 }
4627
4628 }
4629
4630 if (prompting)
4631 size_hints.flags |= prompting;
4632 else
4633 {
4634 XSizeHints hints; /* Sometimes I hate X Windows... */
4635
4636 if (XGetNormalHints (x_current_display, window, &hints) == 0)
4637 hints.flags = 0;
4638 if (hints.flags & PSize)
4639 size_hints.flags |= PSize;
4640 if (hints.flags & PPosition)
4641 size_hints.flags |= PPosition;
4642 if (hints.flags & USPosition)
4643 size_hints.flags |= USPosition;
4644 if (hints.flags & USSize)
4645 size_hints.flags |= USSize;
4646 }
4647
4648 #ifdef HAVE_X11R4
4649 XSetWMNormalHints (x_current_display, window, &size_hints);
4650 #else
4651 XSetNormalHints (x_current_display, window, &size_hints);
4652 #endif
4653 }
4654
4655 /* Used for IconicState or NormalState */
4656 x_wm_set_window_state (f, state)
4657 struct frame *f;
4658 int state;
4659 {
4660 Window window = FRAME_X_WINDOW (f);
4661
4662 f->display.x->wm_hints.flags |= StateHint;
4663 f->display.x->wm_hints.initial_state = state;
4664
4665 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4666 }
4667
4668 x_wm_set_icon_pixmap (f, icon_pixmap)
4669 struct frame *f;
4670 Pixmap icon_pixmap;
4671 {
4672 Window window = FRAME_X_WINDOW (f);
4673
4674 if (icon_pixmap)
4675 {
4676 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4677 f->display.x->wm_hints.flags |= IconPixmapHint;
4678 }
4679 else
4680 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4681
4682 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4683 }
4684
4685 x_wm_set_icon_position (f, icon_x, icon_y)
4686 struct frame *f;
4687 int icon_x, icon_y;
4688 {
4689 Window window = FRAME_X_WINDOW (f);
4690
4691 f->display.x->wm_hints.flags |= IconPositionHint;
4692 f->display.x->wm_hints.icon_x = icon_x;
4693 f->display.x->wm_hints.icon_y = icon_y;
4694
4695 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4696 }
4697
4698 \f
4699 /* Initialization. */
4700
4701 void
4702 x_term_init (display_name)
4703 char *display_name;
4704 {
4705 Lisp_Object frame;
4706 char *defaultvalue;
4707 #ifdef F_SETOWN
4708 extern int old_fcntl_owner;
4709 #endif /* ! defined (F_SETOWN) */
4710
4711 x_focus_frame = x_highlight_frame = 0;
4712
4713 x_current_display = XOpenDisplay (display_name);
4714 if (x_current_display == 0)
4715 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4716 display_name);
4717
4718 #ifdef HAVE_X11
4719 {
4720 int hostname_size = 256;
4721
4722 hostname = (char *) xmalloc (hostname_size);
4723
4724 #if 0
4725 XSetAfterFunction (x_current_display, x_trace_wire);
4726 #endif /* ! 0 */
4727
4728 /* Try to get the host name; if the buffer is too short, try
4729 again. Apparently, the only indication gethostname gives of
4730 whether the buffer was large enough is the presence or absence
4731 of a '\0' in the string. Eech. */
4732 for (;;)
4733 {
4734 gethostname (hostname, hostname_size - 1);
4735 hostname[hostname_size - 1] = '\0';
4736
4737 /* Was the buffer large enough for gethostname to store the '\0'? */
4738 if (strlen (hostname) < hostname_size - 1)
4739 break;
4740
4741 hostname_size <<= 1;
4742 hostname = (char *) xrealloc (hostname, hostname_size);
4743 }
4744 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4745 + strlen (hostname)
4746 + 2);
4747 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4748 }
4749
4750 /* Figure out which modifier bits mean what. */
4751 x_find_modifier_meanings ();
4752
4753 /* Get the scroll bar cursor. */
4754 x_vertical_scroll_bar_cursor
4755 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4756
4757 #if 0
4758 /* Watch for PropertyNotify events on the root window; we use them
4759 to figure out when to invalidate our cache of the cut buffers. */
4760 x_watch_cut_buffer_cache ();
4761 #endif
4762
4763 if (ConnectionNumber (x_current_display) != 0)
4764 {
4765 dup2 (ConnectionNumber (x_current_display), 0);
4766
4767 #ifndef SYSV_STREAMS
4768 /* Streams somehow keeps track of which descriptor number
4769 is being used to talk to X. So it is not safe to substitute
4770 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4771 close (ConnectionNumber (x_current_display));
4772 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4773 * check the def of the macro;
4774 * it is a genuine lvalue */
4775 #endif /* SYSV_STREAMS */
4776 }
4777
4778 #endif /* ! defined (HAVE_X11) */
4779
4780 #ifdef F_SETOWN
4781 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4782 #ifdef F_SETOWN_SOCK_NEG
4783 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4784 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4785 fcntl (0, F_SETOWN, getpid ());
4786 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4787 #endif /* ! defined (F_SETOWN) */
4788
4789 #ifdef SIGIO
4790 init_sigio ();
4791 #endif /* ! defined (SIGIO) */
4792
4793 /* Must use interrupt input because we cannot otherwise
4794 arrange for C-g to be noticed immediately.
4795 We cannot connect it to SIGINT. */
4796 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4797
4798 expose_all_windows = 0;
4799
4800 clear_frame_hook = XTclear_frame;
4801 clear_end_of_line_hook = XTclear_end_of_line;
4802 ins_del_lines_hook = XTins_del_lines;
4803 change_line_highlight_hook = XTchange_line_highlight;
4804 insert_glyphs_hook = XTinsert_glyphs;
4805 write_glyphs_hook = XTwrite_glyphs;
4806 delete_glyphs_hook = XTdelete_glyphs;
4807 ring_bell_hook = XTring_bell;
4808 reset_terminal_modes_hook = XTreset_terminal_modes;
4809 set_terminal_modes_hook = XTset_terminal_modes;
4810 update_begin_hook = XTupdate_begin;
4811 update_end_hook = XTupdate_end;
4812 set_terminal_window_hook = XTset_terminal_window;
4813 read_socket_hook = XTread_socket;
4814 cursor_to_hook = XTcursor_to;
4815 reassert_line_highlight_hook = XTreassert_line_highlight;
4816 mouse_position_hook = XTmouse_position;
4817 frame_rehighlight_hook = XTframe_rehighlight;
4818 frame_raise_lower_hook = XTframe_raise_lower;
4819 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4820 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4821 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4822 judge_scroll_bars_hook = XTjudge_scroll_bars;
4823
4824 scroll_region_ok = 1; /* we'll scroll partial frames */
4825 char_ins_del_ok = 0; /* just as fast to write the line */
4826 line_ins_del_ok = 1; /* we'll just blt 'em */
4827 fast_clear_end_of_line = 1; /* X does this well */
4828 memory_below_frame = 0; /* we don't remember what scrolls
4829 off the bottom */
4830 baud_rate = 19200;
4831
4832 /* Note that there is no real way portable across R3/R4 to get the
4833 original error handler. */
4834 XHandleError (x_error_quitter);
4835 XHandleIOError (x_io_error_quitter);
4836
4837 /* Disable Window Change signals; they are handled by X events. */
4838 #ifdef SIGWINCH
4839 signal (SIGWINCH, SIG_DFL);
4840 #endif /* ! defined (SIGWINCH) */
4841
4842 signal (SIGPIPE, x_connection_closed);
4843 }
4844
4845 void
4846 syms_of_xterm ()
4847 {
4848 staticpro (&last_mouse_scroll_bar);
4849 }
4850 #endif /* ! defined (HAVE_X11) */
4851 #endif /* ! defined (HAVE_X_WINDOWS) */