e4b514c17f48edf7008aa71e4e472cb618c413a6
[bpt/emacs.git] / 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 if (! EQ (Vx_no_window_manager, Qnil))
1249 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1250 frame->display.x->border_pixel);
1251 x_display_cursor (frame, 1);
1252 }
1253
1254 static void
1255 frame_unhighlight (frame)
1256 struct frame *frame;
1257 {
1258 if (! EQ (Vx_no_window_manager, Qnil))
1259 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1260 frame->display.x->border_tile);
1261 x_display_cursor (frame, 1);
1262 }
1263 #else /* ! defined (HAVE_X11) */
1264 /* Dump the border-emphasis of frame F.
1265 If F is selected, this is a lining of the same color as the border,
1266 just within the border, occupying a portion of the internal border.
1267 If F is not selected, it is background in the same place.
1268 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1269
1270 ALWAYS = 1 is used when a frame becomes selected or deselected.
1271 In that case, we also turn the cursor off and on again
1272 so it will appear in the proper shape (solid if selected; else hollow.) */
1273
1274 static void
1275 dumpborder (f, always)
1276 struct frame *f;
1277 int always;
1278 {
1279 int thickness = f->display.x->internal_border_width / 2;
1280 int width = PIXEL_WIDTH (f);
1281 int height = PIXEL_HEIGHT (f);
1282 int pixel;
1283
1284 if (f != selected_frame)
1285 {
1286 if (!always)
1287 return;
1288
1289 pixel = f->display.x->background_pixel;
1290 }
1291 else
1292 {
1293 pixel = f->display.x->border_pixel;
1294 }
1295
1296 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1297 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1298 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1299 thickness, pixel);
1300 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1301 height, pixel);
1302
1303 if (always)
1304 x_display_cursor (f, 1);
1305 }
1306 #endif /* ! defined (HAVE_X11) */
1307
1308 static void XTframe_rehighlight ();
1309
1310 /* The focus has changed. Update the frames as necessary to reflect
1311 the new situation. Note that we can't change the selected frame
1312 here, because the lisp code we are interrupting might become confused.
1313 Each event gets marked with the frame in which it occurred, so the
1314 lisp code can tell when the switch took place by examining the events. */
1315
1316 static void
1317 x_new_focus_frame (frame)
1318 struct frame *frame;
1319 {
1320 struct frame *old_focus = x_focus_frame;
1321 int events_enqueued = 0;
1322
1323 if (frame != x_focus_frame)
1324 {
1325 /* Set this before calling other routines, so that they see
1326 the correct value of x_focus_frame. */
1327 x_focus_frame = frame;
1328
1329 if (old_focus && old_focus->auto_lower)
1330 x_lower_frame (old_focus);
1331
1332 #if 0
1333 selected_frame = frame;
1334 XSET (XWINDOW (selected_frame->selected_window)->frame,
1335 Lisp_Frame, selected_frame);
1336 Fselect_window (selected_frame->selected_window);
1337 choose_minibuf_frame ();
1338 #endif /* ! 0 */
1339
1340 if (x_focus_frame && x_focus_frame->auto_raise)
1341 x_raise_frame (x_focus_frame);
1342 }
1343
1344 XTframe_rehighlight ();
1345 }
1346
1347
1348 /* The focus has changed, or we have redirected a frame's focus to
1349 another frame (this happens when a frame uses a surrogate
1350 minibuffer frame). Shift the highlight as appropriate. */
1351 static void
1352 XTframe_rehighlight ()
1353 {
1354 struct frame *old_highlight = x_highlight_frame;
1355
1356 if (x_focus_frame)
1357 {
1358 x_highlight_frame =
1359 ((XGCTYPE (FRAME_FOCUS_FRAME (x_focus_frame)) == Lisp_Frame)
1360 ? XFRAME (FRAME_FOCUS_FRAME (x_focus_frame))
1361 : x_focus_frame);
1362 if (! FRAME_LIVE_P (x_highlight_frame))
1363 {
1364 FRAME_FOCUS_FRAME (x_focus_frame) = Qnil;
1365 x_highlight_frame = x_focus_frame;
1366 }
1367 }
1368 else
1369 x_highlight_frame = 0;
1370
1371 if (x_highlight_frame != old_highlight)
1372 {
1373 if (old_highlight)
1374 frame_unhighlight (old_highlight);
1375 if (x_highlight_frame)
1376 frame_highlight (x_highlight_frame);
1377 }
1378 }
1379 \f
1380 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1381
1382 /* Which modifier keys are on which modifier bits?
1383
1384 With each keystroke, X returns eight bits indicating which modifier
1385 keys were held down when the key was pressed. The interpretation
1386 of the top five modifier bits depends on what keys are attached
1387 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1388 is the meta bit.
1389
1390 x_meta_mod_mask is a mask containing the bits used for the meta key.
1391 It may have more than one bit set, if more than one modifier bit
1392 has meta keys on it. Basically, if EVENT is a KeyPress event,
1393 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1394
1395 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1396 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1397 only be affected by the lock modifier bit if XK_Shift_Lock is in
1398 use; XK_Caps_Lock should only affect alphabetic keys. With this
1399 arrangement, the lock modifier should shift the character if
1400 (EVENT.state & x_shift_lock_mask) != 0. */
1401 static int x_meta_mod_mask, x_shift_lock_mask;
1402
1403 /* These are like x_meta_mod_mask, but for different modifiers. */
1404 static int x_alt_mod_mask, x_super_mod_mask, x_hyper_mod_mask;
1405
1406 /* Initialize mode_switch_bit and modifier_meaning. */
1407 static void
1408 x_find_modifier_meanings ()
1409 {
1410 int min_code, max_code;
1411 KeySym *syms;
1412 int syms_per_code;
1413 XModifierKeymap *mods;
1414
1415 x_meta_mod_mask = 0;
1416 x_shift_lock_mask = 0;
1417 x_alt_mod_mask = 0;
1418 x_super_mod_mask = 0;
1419 x_hyper_mod_mask = 0;
1420
1421 #ifdef HAVE_X11R4
1422 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1423 #else
1424 min_code = x_current_display->min_keycode;
1425 max_code = x_current_display->max_keycode;
1426 #endif
1427
1428 syms = XGetKeyboardMapping (x_current_display,
1429 min_code, max_code - min_code + 1,
1430 &syms_per_code);
1431 mods = XGetModifierMapping (x_current_display);
1432
1433 /* Scan the modifier table to see which modifier bits the Meta and
1434 Alt keysyms are on. */
1435 {
1436 int row, col; /* The row and column in the modifier table. */
1437
1438 for (row = 3; row < 8; row++)
1439 for (col = 0; col < mods->max_keypermod; col++)
1440 {
1441 KeyCode code =
1442 mods->modifiermap[(row * mods->max_keypermod) + col];
1443
1444 /* Are any of this keycode's keysyms a meta key? */
1445 {
1446 int code_col;
1447
1448 for (code_col = 0; code_col < syms_per_code; code_col++)
1449 {
1450 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1451
1452 switch (sym)
1453 {
1454 case XK_Meta_L:
1455 case XK_Meta_R:
1456 x_meta_mod_mask |= (1 << row);
1457 break;
1458
1459 case XK_Alt_L:
1460 case XK_Alt_R:
1461 x_alt_mod_mask |= (1 << row);
1462 break;
1463
1464 case XK_Hyper_L:
1465 case XK_Hyper_R:
1466 x_hyper_mod_mask |= (1 << row);
1467 break;
1468
1469 case XK_Super_L:
1470 case XK_Super_R:
1471 x_super_mod_mask |= (1 << row);
1472 break;
1473
1474 case XK_Shift_Lock:
1475 /* Ignore this if it's not on the lock modifier. */
1476 if ((1 << row) == LockMask)
1477 x_shift_lock_mask = LockMask;
1478 break;
1479 }
1480 }
1481 }
1482 }
1483 }
1484
1485 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1486 if (! x_meta_mod_mask)
1487 {
1488 x_meta_mod_mask = x_alt_mod_mask;
1489 x_alt_mod_mask = 0;
1490 }
1491
1492 /* If some keys are both alt and meta,
1493 make them just meta, not alt. */
1494 if (x_alt_mod_mask & x_meta_mod_mask)
1495 {
1496 x_alt_mod_mask &= ~x_meta_mod_mask;
1497 }
1498
1499 XFree ((char *) syms);
1500 XFreeModifiermap (mods);
1501 }
1502
1503
1504 /* Convert between the modifier bits X uses and the modifier bits
1505 Emacs uses. */
1506 static unsigned int
1507 x_x_to_emacs_modifiers (state)
1508 unsigned int state;
1509 {
1510 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1511 | ((state & ControlMask) ? ctrl_modifier : 0)
1512 | ((state & x_meta_mod_mask) ? meta_modifier : 0)
1513 | ((state & x_alt_mod_mask) ? alt_modifier : 0)
1514 | ((state & x_super_mod_mask) ? super_modifier : 0)
1515 | ((state & x_hyper_mod_mask) ? hyper_modifier : 0));
1516 }
1517
1518 static unsigned int
1519 x_emacs_to_x_modifiers (state)
1520 unsigned int state;
1521 {
1522 return ( ((state & alt_modifier) ? x_alt_mod_mask : 0)
1523 | ((state & super_modifier) ? x_super_mod_mask : 0)
1524 | ((state & hyper_modifier) ? x_hyper_mod_mask : 0)
1525 | ((state & shift_modifier) ? ShiftMask : 0)
1526 | ((state & ctrl_modifier) ? ControlMask : 0)
1527 | ((state & meta_modifier) ? x_meta_mod_mask : 0));
1528 }
1529
1530 /* Return true iff KEYSYM is a vendor-specific keysym that we should
1531 return as a function key. If you add a keysym to this, you should
1532 make sure that the tables make_lispy_event uses contain a suitable
1533 name for it. */
1534 static int
1535 x_is_vendor_fkey (sym)
1536 KeySym sym;
1537 {
1538 return 0
1539 #ifdef DXK_Remove
1540 || (sym == DXK_Remove)
1541 #endif
1542 ;
1543 }
1544
1545 \f
1546 /* Mouse clicks and mouse movement. Rah. */
1547 #ifdef HAVE_X11
1548
1549 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1550 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1551 that the glyph at X, Y occupies, if BOUNDS != 0. */
1552 static void
1553 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1554 FRAME_PTR f;
1555 register unsigned int pix_x, pix_y;
1556 register int *x, *y;
1557 XRectangle *bounds;
1558 {
1559 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1560 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1561
1562 if (bounds)
1563 {
1564 bounds->width = FONT_WIDTH (f->display.x->font);
1565 bounds->height = FONT_HEIGHT (f->display.x->font);
1566 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1567 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1568 }
1569
1570 if (pix_x < 0) pix_x = 0;
1571 else if (pix_x > f->width) pix_x = f->width;
1572
1573 if (pix_y < 0) pix_y = 0;
1574 else if (pix_y > f->height) pix_y = f->height;
1575
1576 *x = pix_x;
1577 *y = pix_y;
1578 }
1579
1580 /* Any buttons grabbed. */
1581 unsigned int x_mouse_grabbed;
1582
1583 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1584
1585 If the event is a button press, then note that we have grabbed
1586 the mouse. */
1587
1588 static Lisp_Object
1589 construct_mouse_click (result, event, f)
1590 struct input_event *result;
1591 XButtonEvent *event;
1592 struct frame *f;
1593 {
1594 /* Make the event type no_event; we'll change that when we decide
1595 otherwise. */
1596 result->kind = mouse_click;
1597 XSET (result->code, Lisp_Int, event->button - Button1);
1598 result->timestamp = event->time;
1599 result->modifiers = (x_x_to_emacs_modifiers (event->state)
1600 | (event->type == ButtonRelease
1601 ? up_modifier
1602 : down_modifier));
1603
1604 /* Notice if the mouse is still grabbed. */
1605 if (event->type == ButtonPress)
1606 {
1607 if (! x_mouse_grabbed)
1608 Vmouse_depressed = Qt;
1609 x_mouse_grabbed |= (1 << event->button);
1610 }
1611 else if (event->type == ButtonRelease)
1612 {
1613 x_mouse_grabbed &= ~(1 << event->button);
1614 if (!x_mouse_grabbed)
1615 Vmouse_depressed = Qnil;
1616 }
1617
1618 {
1619 int row, column;
1620
1621 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1622 XFASTINT (result->x) = column;
1623 XFASTINT (result->y) = row;
1624 XSET (result->frame_or_window, Lisp_Frame, f);
1625 }
1626 }
1627
1628
1629 /* Mouse movement. Rah.
1630
1631 In order to avoid asking for motion events and then throwing most
1632 of them away or busy-polling the server for mouse positions, we ask
1633 the server for pointer motion hints. This means that we get only
1634 one event per group of mouse movements. "Groups" are delimited by
1635 other kinds of events (focus changes and button clicks, for
1636 example), or by XQueryPointer calls; when one of these happens, we
1637 get another MotionNotify event the next time the mouse moves. This
1638 is at least as efficient as getting motion events when mouse
1639 tracking is on, and I suspect only negligibly worse when tracking
1640 is off.
1641
1642 The silly O'Reilly & Associates Nutshell guides barely document
1643 pointer motion hints at all (I think you have to infer how they
1644 work from an example), and the description of XQueryPointer doesn't
1645 mention that calling it causes you to get another motion hint from
1646 the server, which is very important. */
1647
1648 /* Where the mouse was last time we reported a mouse event. */
1649 static FRAME_PTR last_mouse_frame;
1650 static XRectangle last_mouse_glyph;
1651
1652 /* The scroll bar in which the last X motion event occurred.
1653
1654 If the last X motion event occurred in a scroll bar, we set this
1655 so XTmouse_position can know whether to report a scroll bar motion or
1656 an ordinary motion.
1657
1658 If the last X motion event didn't occur in a scroll bar, we set this
1659 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
1660 static Lisp_Object last_mouse_scroll_bar;
1661
1662 /* This is a hack. We would really prefer that XTmouse_position would
1663 return the time associated with the position it returns, but there
1664 doesn't seem to be any way to wrest the timestamp from the server
1665 along with the position query. So, we just keep track of the time
1666 of the last movement we received, and return that in hopes that
1667 it's somewhat accurate. */
1668 static Time last_mouse_movement_time;
1669
1670 /* Function to report a mouse movement to the mainstream Emacs code.
1671 The input handler calls this.
1672
1673 We have received a mouse movement event, which is given in *event.
1674 If the mouse is over a different glyph than it was last time, tell
1675 the mainstream emacs code by setting mouse_moved. If not, ask for
1676 another motion event, so we can check again the next time it moves. */
1677 static void
1678 note_mouse_movement (frame, event)
1679 FRAME_PTR frame;
1680 XMotionEvent *event;
1681
1682 {
1683 last_mouse_movement_time = event->time;
1684
1685 /* Has the mouse moved off the glyph it was on at the last sighting? */
1686 if (event->x < last_mouse_glyph.x
1687 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1688 || event->y < last_mouse_glyph.y
1689 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1690 {
1691 mouse_moved = 1;
1692 last_mouse_scroll_bar = Qnil;
1693 }
1694 else
1695 {
1696 /* It's on the same glyph. Call XQueryPointer so we'll get an
1697 event the next time the mouse moves and we can see if it's
1698 *still* on the same glyph. */
1699 int dummy;
1700
1701 XQueryPointer (event->display, event->window,
1702 (Window *) &dummy, (Window *) &dummy,
1703 &dummy, &dummy, &dummy, &dummy,
1704 (unsigned int *) &dummy);
1705 }
1706 }
1707
1708 static struct scroll_bar *x_window_to_scroll_bar ();
1709 static void x_scroll_bar_report_motion ();
1710
1711 /* Return the current position of the mouse.
1712
1713 If the mouse movement started in a scroll bar, set *f, *bar_window,
1714 and *part to the frame, window, and scroll bar part that the mouse
1715 is over. Set *x and *y to the portion and whole of the mouse's
1716 position on the scroll bar.
1717
1718 If the mouse movement started elsewhere, set *f to the frame the
1719 mouse is on, *bar_window to nil, and *x and *y to the character cell
1720 the mouse is over.
1721
1722 Set *time to the server timestamp for the time at which the mouse
1723 was at this position.
1724
1725 Don't store anything if we don't have a valid set of values to report.
1726
1727 This clears the mouse_moved flag, so we can wait for the next mouse
1728 movement. This also calls XQueryPointer, which will cause the
1729 server to give us another MotionNotify when the mouse moves
1730 again. */
1731
1732 static void
1733 XTmouse_position (f, bar_window, part, x, y, time)
1734 FRAME_PTR *f;
1735 Lisp_Object *bar_window;
1736 enum scroll_bar_part *part;
1737 Lisp_Object *x, *y;
1738 unsigned long *time;
1739 {
1740 FRAME_PTR f1;
1741
1742 BLOCK_INPUT;
1743
1744 if (! NILP (last_mouse_scroll_bar))
1745 x_scroll_bar_report_motion (f, bar_window, part, x, y, time);
1746 else
1747 {
1748 Window root;
1749 int root_x, root_y;
1750
1751 Window dummy_window;
1752 int dummy;
1753
1754 mouse_moved = 0;
1755 last_mouse_scroll_bar = Qnil;
1756
1757 /* Figure out which root window we're on. */
1758 XQueryPointer (x_current_display,
1759 DefaultRootWindow (x_current_display),
1760
1761 /* The root window which contains the pointer. */
1762 &root,
1763
1764 /* Trash which we can't trust if the pointer is on
1765 a different screen. */
1766 &dummy_window,
1767
1768 /* The position on that root window. */
1769 &root_x, &root_y,
1770
1771 /* More trash we can't trust. */
1772 &dummy, &dummy,
1773
1774 /* Modifier keys and pointer buttons, about which
1775 we don't care. */
1776 (unsigned int *) &dummy);
1777
1778 /* Now we have a position on the root; find the innermost window
1779 containing the pointer. */
1780 {
1781 Window win, child;
1782 int win_x, win_y;
1783 int parent_x, parent_y;
1784
1785 win = root;
1786 for (;;)
1787 {
1788 XTranslateCoordinates (x_current_display,
1789
1790 /* From-window, to-window. */
1791 root, win,
1792
1793 /* From-position, to-position. */
1794 root_x, root_y, &win_x, &win_y,
1795
1796 /* Child of win. */
1797 &child);
1798
1799 if (child == None)
1800 break;
1801
1802 win = child;
1803 parent_x = win_x;
1804 parent_y = win_y;
1805 }
1806
1807 /* Now we know that:
1808 win is the innermost window containing the pointer
1809 (XTC says it has no child containing the pointer),
1810 win_x and win_y are the pointer's position in it
1811 (XTC did this the last time through), and
1812 parent_x and parent_y are the pointer's position in win's parent.
1813 (They are what win_x and win_y were when win was child.
1814 If win is the root window, it has no parent, and
1815 parent_{x,y} are invalid, but that's okay, because we'll
1816 never use them in that case.) */
1817
1818 /* Is win one of our frames? */
1819 f1 = x_window_to_frame (win);
1820
1821 /* If not, is it one of our scroll bars? */
1822 if (! f1)
1823 {
1824 struct scroll_bar *bar = x_window_to_scroll_bar (win);
1825
1826 if (bar)
1827 {
1828 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
1829 win_x = parent_x;
1830 win_y = parent_y;
1831 }
1832 }
1833
1834 if (f1)
1835 {
1836 /* Ok, we found a frame. Convert from pixels to characters
1837 and store all the values. */
1838
1839 pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y,
1840 &last_mouse_glyph);
1841
1842 *bar_window = Qnil;
1843 *part = 0;
1844 *f = f1;
1845 XSET (*x, Lisp_Int, win_x);
1846 XSET (*y, Lisp_Int, win_y);
1847 *time = last_mouse_movement_time;
1848 }
1849 }
1850 }
1851
1852 UNBLOCK_INPUT;
1853 }
1854
1855 #else /* ! defined (HAVE_X11) */
1856 #define XEvent XKeyPressedEvent
1857 #endif /* ! defined (HAVE_X11) */
1858 \f
1859 /* Scroll bar support. */
1860
1861 /* Given an X window ID, find the struct scroll_bar which manages it.
1862 This can be called in GC, so we have to make sure to strip off mark
1863 bits. */
1864 static struct scroll_bar *
1865 x_window_to_scroll_bar (window_id)
1866 Window window_id;
1867 {
1868 Lisp_Object tail, frame;
1869
1870 for (tail = Vframe_list;
1871 XGCTYPE (tail) == Lisp_Cons;
1872 tail = XCONS (tail)->cdr)
1873 {
1874 Lisp_Object frame = XCONS (tail)->car;
1875 Lisp_Object bar, condemned;
1876
1877 /* All elements of Vframe_list should be frames. */
1878 if (XGCTYPE (frame) != Lisp_Frame)
1879 abort ();
1880
1881 /* Scan this frame's scroll bar list for a scroll bar with the
1882 right window ID. */
1883 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
1884 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
1885 /* This trick allows us to search both the ordinary and
1886 condemned scroll bar lists with one loop. */
1887 ! GC_NILP (bar) || (bar = condemned,
1888 condemned = Qnil,
1889 ! GC_NILP (bar));
1890 bar = XSCROLL_BAR(bar)->next)
1891 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
1892 return XSCROLL_BAR (bar);
1893 }
1894
1895 return 0;
1896 }
1897
1898 /* Open a new X window to serve as a scroll bar, and return the
1899 scroll bar vector for it. */
1900 static struct scroll_bar *
1901 x_scroll_bar_create (window, top, left, width, height)
1902 struct window *window;
1903 int top, left, width, height;
1904 {
1905 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window));
1906 struct scroll_bar *bar =
1907 XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
1908
1909 BLOCK_INPUT;
1910
1911 {
1912 XSetWindowAttributes a;
1913 unsigned long mask;
1914
1915 a.background_pixel = frame->display.x->background_pixel;
1916 a.event_mask = (ButtonPressMask | ButtonReleaseMask
1917 | ButtonMotionMask | PointerMotionHintMask
1918 | ExposureMask);
1919 a.cursor = x_vertical_scroll_bar_cursor;
1920
1921 mask = (CWBackPixel | CWEventMask | CWCursor);
1922
1923 SET_SCROLL_BAR_X_WINDOW
1924 (bar,
1925 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
1926
1927 /* Position and size of scroll bar. */
1928 left, top, width, height,
1929
1930 /* Border width, depth, class, and visual. */
1931 0, CopyFromParent, CopyFromParent, CopyFromParent,
1932
1933 /* Attributes. */
1934 mask, &a));
1935 }
1936
1937 XSET (bar->window, Lisp_Window, window);
1938 XSET (bar->top, Lisp_Int, top);
1939 XSET (bar->left, Lisp_Int, left);
1940 XSET (bar->width, Lisp_Int, width);
1941 XSET (bar->height, Lisp_Int, height);
1942 XSET (bar->start, Lisp_Int, 0);
1943 XSET (bar->end, Lisp_Int, 0);
1944 bar->dragging = Qnil;
1945
1946 /* Add bar to its frame's list of scroll bars. */
1947 bar->next = FRAME_SCROLL_BARS (frame);
1948 bar->prev = Qnil;
1949 XSET (FRAME_SCROLL_BARS (frame), Lisp_Vector, bar);
1950 if (! NILP (bar->next))
1951 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
1952
1953 XMapWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
1954
1955 UNBLOCK_INPUT;
1956
1957 return bar;
1958 }
1959
1960 /* Draw BAR's handle in the proper position.
1961 If the handle is already drawn from START to END, don't bother
1962 redrawing it, unless REBUILD is non-zero; in that case, always
1963 redraw it. (REBUILD is handy for drawing the handle after expose
1964 events.)
1965
1966 Normally, we want to constrain the start and end of the handle to
1967 fit inside its rectangle, but if the user is dragging the scroll bar
1968 handle, we want to let them drag it down all the way, so that the
1969 bar's top is as far down as it goes; otherwise, there's no way to
1970 move to the very end of the buffer. */
1971 static void
1972 x_scroll_bar_set_handle (bar, start, end, rebuild)
1973 struct scroll_bar *bar;
1974 int start, end;
1975 int rebuild;
1976 {
1977 int dragging = ! NILP (bar->dragging);
1978 Window w = SCROLL_BAR_X_WINDOW (bar);
1979 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
1980
1981 /* If the display is already accurate, do nothing. */
1982 if (! rebuild
1983 && start == XINT (bar->start)
1984 && end == XINT (bar->end))
1985 return;
1986
1987 BLOCK_INPUT;
1988
1989 {
1990 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
1991 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
1992 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
1993
1994 /* Make sure the values are reasonable, and try to preserve
1995 the distance between start and end. */
1996 {
1997 int length = end - start;
1998
1999 if (start < 0)
2000 start = 0;
2001 else if (start > top_range)
2002 start = top_range;
2003 end = start + length;
2004
2005 if (end < start)
2006 end = start;
2007 else if (end > top_range && ! dragging)
2008 end = top_range;
2009 }
2010
2011 /* Store the adjusted setting in the scroll bar. */
2012 XSET (bar->start, Lisp_Int, start);
2013 XSET (bar->end, Lisp_Int, end);
2014
2015 /* Clip the end position, just for display. */
2016 if (end > top_range)
2017 end = top_range;
2018
2019 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2020 below top positions, to make sure the handle is always at least
2021 that many pixels tall. */
2022 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2023
2024 /* Draw the empty space above the handle. Note that we can't clear
2025 zero-height areas; that means "clear to end of window." */
2026 if (0 < start)
2027 XClearArea (x_current_display, w,
2028
2029 /* x, y, width, height, and exposures. */
2030 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2031 VERTICAL_SCROLL_BAR_TOP_BORDER,
2032 inside_width, start,
2033 False);
2034
2035 /* Draw the handle itself. */
2036 XFillRectangle (x_current_display, w, gc,
2037
2038 /* x, y, width, height */
2039 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2040 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2041 inside_width, end - start);
2042
2043
2044 /* Draw the empty space below the handle. Note that we can't
2045 clear zero-height areas; that means "clear to end of window." */
2046 if (end < inside_height)
2047 XClearArea (x_current_display, w,
2048
2049 /* x, y, width, height, and exposures. */
2050 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2051 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2052 inside_width, inside_height - end,
2053 False);
2054
2055 }
2056
2057 UNBLOCK_INPUT;
2058 }
2059
2060 /* Move a scroll bar around on the screen, to accommodate changing
2061 window configurations. */
2062 static void
2063 x_scroll_bar_move (bar, top, left, width, height)
2064 struct scroll_bar *bar;
2065 int top, left, width, height;
2066 {
2067 BLOCK_INPUT;
2068
2069 {
2070 XWindowChanges wc;
2071 unsigned int mask = 0;
2072
2073 wc.x = left;
2074 wc.y = top;
2075 wc.width = width;
2076 wc.height = height;
2077
2078 if (left != XINT (bar->left)) mask |= CWX;
2079 if (top != XINT (bar->top)) mask |= CWY;
2080 if (width != XINT (bar->width)) mask |= CWWidth;
2081 if (height != XINT (bar->height)) mask |= CWHeight;
2082
2083 if (mask)
2084 XConfigureWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar),
2085 mask, &wc);
2086 }
2087
2088 XSET (bar->left, Lisp_Int, left);
2089 XSET (bar->top, Lisp_Int, top);
2090 XSET (bar->width, Lisp_Int, width);
2091 XSET (bar->height, Lisp_Int, height);
2092
2093 UNBLOCK_INPUT;
2094 }
2095
2096 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2097 to nil. */
2098 static void
2099 x_scroll_bar_remove (bar)
2100 struct scroll_bar *bar;
2101 {
2102 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2103
2104 BLOCK_INPUT;
2105
2106 /* Destroy the window. */
2107 XDestroyWindow (x_current_display, SCROLL_BAR_X_WINDOW (bar));
2108
2109 /* Disassociate this scroll bar from its window. */
2110 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2111
2112 UNBLOCK_INPUT;
2113 }
2114
2115 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2116 that we are displaying PORTION characters out of a total of WHOLE
2117 characters, starting at POSITION. If WINDOW has no scroll bar,
2118 create one. */
2119 static void
2120 XTset_vertical_scroll_bar (window, portion, whole, position)
2121 struct window *window;
2122 int portion, whole, position;
2123 {
2124 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2125 int top = XINT (window->top);
2126 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2127 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2128
2129 /* Where should this scroll bar be, pixelwise? */
2130 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2131 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2132 int pixel_width = VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f);
2133 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2134
2135 struct scroll_bar *bar;
2136
2137 /* Does the scroll bar exist yet? */
2138 if (NILP (window->vertical_scroll_bar))
2139 bar = x_scroll_bar_create (window,
2140 pixel_top, pixel_left,
2141 pixel_width, pixel_height);
2142 else
2143 {
2144 /* It may just need to be moved and resized. */
2145 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2146 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2147 }
2148
2149 /* Set the scroll bar's current state, unless we're currently being
2150 dragged. */
2151 if (NILP (bar->dragging))
2152 {
2153 int top_range =
2154 VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2155
2156 if (whole == 0)
2157 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2158 else
2159 {
2160 int start = ((double) position * top_range) / whole;
2161 int end = ((double) (position + portion) * top_range) / whole;
2162
2163 x_scroll_bar_set_handle (bar, start, end, 0);
2164 }
2165 }
2166
2167 XSET (window->vertical_scroll_bar, Lisp_Vector, bar);
2168 }
2169
2170
2171 /* The following three hooks are used when we're doing a thorough
2172 redisplay of the frame. We don't explicitly know which scroll bars
2173 are going to be deleted, because keeping track of when windows go
2174 away is a real pain - "Can you say set-window-configuration, boys
2175 and girls?" Instead, we just assert at the beginning of redisplay
2176 that *all* scroll bars are to be removed, and then save a scroll bar
2177 from the fiery pit when we actually redisplay its window. */
2178
2179 /* Arrange for all scroll bars on FRAME to be removed at the next call
2180 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2181 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2182 static void
2183 XTcondemn_scroll_bars (frame)
2184 FRAME_PTR frame;
2185 {
2186 /* The condemned list should be empty at this point; if it's not,
2187 then the rest of Emacs isn't using the condemn/redeem/judge
2188 protocol correctly. */
2189 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2190 abort ();
2191
2192 /* Move them all to the "condemned" list. */
2193 FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
2194 FRAME_SCROLL_BARS (frame) = Qnil;
2195 }
2196
2197 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2198 Note that WINDOW isn't necessarily condemned at all. */
2199 static void
2200 XTredeem_scroll_bar (window)
2201 struct window *window;
2202 {
2203 struct scroll_bar *bar;
2204
2205 /* We can't redeem this window's scroll bar if it doesn't have one. */
2206 if (NILP (window->vertical_scroll_bar))
2207 abort ();
2208
2209 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2210
2211 /* Unlink it from the condemned list. */
2212 {
2213 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2214
2215 if (NILP (bar->prev))
2216 {
2217 /* If the prev pointer is nil, it must be the first in one of
2218 the lists. */
2219 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2220 /* It's not condemned. Everything's fine. */
2221 return;
2222 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2223 window->vertical_scroll_bar))
2224 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2225 else
2226 /* If its prev pointer is nil, it must be at the front of
2227 one or the other! */
2228 abort ();
2229 }
2230 else
2231 XSCROLL_BAR (bar->prev)->next = bar->next;
2232
2233 if (! NILP (bar->next))
2234 XSCROLL_BAR (bar->next)->prev = bar->prev;
2235
2236 bar->next = FRAME_SCROLL_BARS (f);
2237 bar->prev = Qnil;
2238 XSET (FRAME_SCROLL_BARS (f), Lisp_Vector, bar);
2239 if (! NILP (bar->next))
2240 XSET (XSCROLL_BAR (bar->next)->prev, Lisp_Vector, bar);
2241 }
2242 }
2243
2244 /* Remove all scroll bars on FRAME that haven't been saved since the
2245 last call to `*condemn_scroll_bars_hook'. */
2246 static void
2247 XTjudge_scroll_bars (f)
2248 FRAME_PTR f;
2249 {
2250 Lisp_Object bar, next;
2251
2252 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2253
2254 /* Clear out the condemned list now so we won't try to process any
2255 more events on the hapless scroll bars. */
2256 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2257
2258 for (; ! NILP (bar); bar = next)
2259 {
2260 struct scroll_bar *b = XSCROLL_BAR (bar);
2261
2262 x_scroll_bar_remove (b);
2263
2264 next = b->next;
2265 b->next = b->prev = Qnil;
2266 }
2267
2268 /* Now there should be no references to the condemned scroll bars,
2269 and they should get garbage-collected. */
2270 }
2271
2272
2273 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2274
2275 This may be called from a signal handler, so we have to ignore GC
2276 mark bits. */
2277 static void
2278 x_scroll_bar_expose (bar, event)
2279 struct scroll_bar *bar;
2280 XEvent *event;
2281 {
2282 Window w = SCROLL_BAR_X_WINDOW (bar);
2283 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc;
2284
2285 BLOCK_INPUT;
2286
2287 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2288
2289 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2290 XDrawRectangle (x_current_display, w, gc,
2291
2292 /* x, y, width, height */
2293 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2294
2295 /* Draw another line to make the extra-thick border on the right. */
2296 XFillRectangle (x_current_display, w, gc,
2297
2298 /* x, y, width, height */
2299 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
2300
2301 UNBLOCK_INPUT;
2302 }
2303
2304 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2305 is set to something other than no_event, it is enqueued.
2306
2307 This may be called from a signal handler, so we have to ignore GC
2308 mark bits. */
2309 static void
2310 x_scroll_bar_handle_click (bar, event, emacs_event)
2311 struct scroll_bar *bar;
2312 XEvent *event;
2313 struct input_event *emacs_event;
2314 {
2315 if (XGCTYPE (bar->window) != Lisp_Window)
2316 abort ();
2317
2318 emacs_event->kind = scroll_bar_click;
2319 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1);
2320 emacs_event->modifiers =
2321 (x_x_to_emacs_modifiers (event->xbutton.state)
2322 | (event->type == ButtonRelease
2323 ? up_modifier
2324 : down_modifier));
2325 emacs_event->frame_or_window = bar->window;
2326 emacs_event->timestamp = event->xbutton.time;
2327 {
2328 int internal_height =
2329 VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2330 int top_range =
2331 VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2332 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2333
2334 if (y < 0) y = 0;
2335 if (y > top_range) y = top_range;
2336
2337 if (y < XINT (bar->start))
2338 emacs_event->part = scroll_bar_above_handle;
2339 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2340 emacs_event->part = scroll_bar_handle;
2341 else
2342 emacs_event->part = scroll_bar_below_handle;
2343
2344 /* Just because the user has clicked on the handle doesn't mean
2345 they want to drag it. Lisp code needs to be able to decide
2346 whether or not we're dragging. */
2347 #if 0
2348 /* If the user has just clicked on the handle, record where they're
2349 holding it. */
2350 if (event->type == ButtonPress
2351 && emacs_event->part == scroll_bar_handle)
2352 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start));
2353 #endif
2354
2355 /* If the user has released the handle, set it to its final position. */
2356 if (event->type == ButtonRelease
2357 && ! NILP (bar->dragging))
2358 {
2359 int new_start = y - XINT (bar->dragging);
2360 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2361
2362 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2363 bar->dragging = Qnil;
2364 }
2365
2366 /* Same deal here as the other #if 0. */
2367 #if 0
2368 /* Clicks on the handle are always reported as occurring at the top of
2369 the handle. */
2370 if (emacs_event->part == scroll_bar_handle)
2371 emacs_event->x = bar->start;
2372 else
2373 XSET (emacs_event->x, Lisp_Int, y);
2374 #else
2375 XSET (emacs_event->x, Lisp_Int, y);
2376 #endif
2377
2378 XSET (emacs_event->y, Lisp_Int, top_range);
2379 }
2380 }
2381
2382 /* Handle some mouse motion while someone is dragging the scroll bar.
2383
2384 This may be called from a signal handler, so we have to ignore GC
2385 mark bits. */
2386 static void
2387 x_scroll_bar_note_movement (bar, event)
2388 struct scroll_bar *bar;
2389 XEvent *event;
2390 {
2391 last_mouse_movement_time = event->xmotion.time;
2392
2393 mouse_moved = 1;
2394 XSET (last_mouse_scroll_bar, Lisp_Vector, bar);
2395
2396 /* If we're dragging the bar, display it. */
2397 if (! GC_NILP (bar->dragging))
2398 {
2399 /* Where should the handle be now? */
2400 int new_start = event->xmotion.y - XINT (bar->dragging);
2401
2402 if (new_start != XINT (bar->start))
2403 {
2404 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2405
2406 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2407 }
2408 }
2409
2410 /* Call XQueryPointer so we'll get an event the next time the mouse
2411 moves and we can see *still* on the same position. */
2412 {
2413 int dummy;
2414
2415 XQueryPointer (event->xmotion.display, event->xmotion.window,
2416 (Window *) &dummy, (Window *) &dummy,
2417 &dummy, &dummy, &dummy, &dummy,
2418 (unsigned int *) &dummy);
2419 }
2420 }
2421
2422 /* Return information to the user about the current position of the mouse
2423 on the scroll bar. */
2424 static void
2425 x_scroll_bar_report_motion (f, bar_window, part, x, y, time)
2426 FRAME_PTR *f;
2427 Lisp_Object *bar_window;
2428 enum scroll_bar_part *part;
2429 Lisp_Object *x, *y;
2430 unsigned long *time;
2431 {
2432 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
2433 int win_x, win_y;
2434 Window dummy_window;
2435 int dummy_coord;
2436 unsigned int dummy_mask;
2437
2438 BLOCK_INPUT;
2439
2440 /* Get the mouse's position relative to the scroll bar window, and
2441 report that. */
2442 if (! XQueryPointer (x_current_display,
2443 SCROLL_BAR_X_WINDOW (bar),
2444
2445 /* Root, child, root x and root y. */
2446 &dummy_window, &dummy_window,
2447 &dummy_coord, &dummy_coord,
2448
2449 /* Position relative to scroll bar. */
2450 &win_x, &win_y,
2451
2452 /* Mouse buttons and modifier keys. */
2453 &dummy_mask))
2454 *f = 0;
2455 else
2456 {
2457 int inside_height
2458 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2459 int top_range
2460 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2461
2462 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
2463
2464 if (! NILP (bar->dragging))
2465 win_y -= XINT (bar->dragging);
2466
2467 if (win_y < 0)
2468 win_y = 0;
2469 if (win_y > top_range)
2470 win_y = top_range;
2471
2472 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2473 *bar_window = bar->window;
2474
2475 if (! NILP (bar->dragging))
2476 *part = scroll_bar_handle;
2477 else if (win_y < XINT (bar->start))
2478 *part = scroll_bar_above_handle;
2479 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2480 *part = scroll_bar_handle;
2481 else
2482 *part = scroll_bar_below_handle;
2483
2484 XSET (*x, Lisp_Int, win_y);
2485 XSET (*y, Lisp_Int, top_range);
2486
2487 mouse_moved = 0;
2488 last_mouse_scroll_bar = Qnil;
2489 }
2490
2491 *time = last_mouse_movement_time;
2492
2493 UNBLOCK_INPUT;
2494 }
2495
2496
2497 /* The screen has been cleared so we may have changed foreground or
2498 background colors, and the scroll bars may need to be redrawn.
2499 Clear out the scroll bars, and ask for expose events, so we can
2500 redraw them. */
2501
2502 x_scroll_bar_clear (f)
2503 FRAME_PTR f;
2504 {
2505 Lisp_Object bar;
2506
2507 for (bar = FRAME_SCROLL_BARS (f);
2508 XTYPE (bar) == Lisp_Vector;
2509 bar = XSCROLL_BAR (bar)->next)
2510 XClearArea (x_current_display, SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
2511 0, 0, 0, 0, True);
2512 }
2513
2514
2515 \f
2516 /* The main X event-reading loop - XTread_socket. */
2517
2518 /* Timestamp of enter window event. This is only used by XTread_socket,
2519 but we have to put it out here, since static variables within functions
2520 sometimes don't work. */
2521 static Time enter_timestamp;
2522
2523 /* This holds the state XLookupString needs to implement dead keys
2524 and other tricks known as "compose processing". _X Window System_
2525 says that a portable program can't use this, but Stephen Gildea assures
2526 me that letting the compiler initialize it to zeros will work okay.
2527
2528 This must be defined outside of XTread_socket, for the same reasons
2529 given for enter_timestamp, above. */
2530 static XComposeStatus compose_status;
2531
2532 /* Communication with window managers. */
2533 Atom Xatom_wm_protocols;
2534
2535 /* Kinds of protocol things we may receive. */
2536 Atom Xatom_wm_take_focus;
2537 Atom Xatom_wm_save_yourself;
2538 Atom Xatom_wm_delete_window;
2539
2540 /* Other WM communication */
2541 Atom Xatom_wm_configure_denied; /* When our config request is denied */
2542 Atom Xatom_wm_window_moved; /* When the WM moves us. */
2543
2544 /* Window manager communication. */
2545 Atom Xatom_wm_change_state;
2546
2547 /* Record the last 100 characters stored
2548 to help debug the loss-of-chars-during-GC problem. */
2549 int temp_index;
2550 short temp_buffer[100];
2551
2552 /* Read events coming from the X server.
2553 This routine is called by the SIGIO handler.
2554 We return as soon as there are no more events to be read.
2555
2556 Events representing keys are stored in buffer BUFP,
2557 which can hold up to NUMCHARS characters.
2558 We return the number of characters stored into the buffer,
2559 thus pretending to be `read'.
2560
2561 WAITP is nonzero if we should block until input arrives.
2562 EXPECTED is nonzero if the caller knows input is available. */
2563
2564 int
2565 XTread_socket (sd, bufp, numchars, waitp, expected)
2566 register int sd;
2567 register struct input_event *bufp;
2568 register int numchars;
2569 int waitp;
2570 int expected;
2571 {
2572 int count = 0;
2573 int nbytes = 0;
2574 int mask;
2575 int items_pending; /* How many items are in the X queue. */
2576 XEvent event;
2577 struct frame *f;
2578 int event_found;
2579 int prefix;
2580 Lisp_Object part;
2581
2582 if (interrupt_input_blocked)
2583 {
2584 interrupt_input_pending = 1;
2585 return -1;
2586 }
2587
2588 interrupt_input_pending = 0;
2589 BLOCK_INPUT;
2590
2591 if (numchars <= 0)
2592 abort (); /* Don't think this happens. */
2593
2594 #ifdef FIOSNBIO
2595 /* If available, Xlib uses FIOSNBIO to make the socket
2596 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
2597 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
2598 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
2599 fcntl (fileno (stdin), F_SETFL, 0);
2600 #endif /* ! defined (FIOSNBIO) */
2601
2602 #ifndef SIGIO
2603 #ifndef HAVE_SELECT
2604 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
2605 {
2606 extern int read_alarm_should_throw;
2607 read_alarm_should_throw = 1;
2608 XPeekEvent (XDISPLAY &event);
2609 read_alarm_should_throw = 0;
2610 }
2611 #endif /* HAVE_SELECT */
2612 #endif /* SIGIO */
2613
2614 while (XStuffPending () != 0)
2615 {
2616 XNextEvent (XDISPLAY &event);
2617 event_found = 1;
2618
2619 switch (event.type)
2620 {
2621 #ifdef HAVE_X11
2622 case ClientMessage:
2623 {
2624 if (event.xclient.message_type == Xatom_wm_protocols
2625 && event.xclient.format == 32)
2626 {
2627 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
2628 {
2629 f = x_window_to_frame (event.xclient.window);
2630 if (f)
2631 x_focus_on_frame (f);
2632 /* Not certain about handling scroll bars here */
2633 }
2634 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
2635 {
2636 /* Save state modify the WM_COMMAND property to
2637 something which can reinstate us. This notifies
2638 the session manager, who's looking for such a
2639 PropertyNotify. Can restart processing when
2640 a keyboard or mouse event arrives. */
2641 if (numchars > 0)
2642 {
2643 }
2644 }
2645 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
2646 {
2647 struct frame *f = x_window_to_frame (event.xclient.window);
2648
2649 if (f)
2650 if (numchars > 0)
2651 {
2652 }
2653 }
2654 }
2655 else if (event.xclient.message_type == Xatom_wm_configure_denied)
2656 {
2657 }
2658 else if (event.xclient.message_type == Xatom_wm_window_moved)
2659 {
2660 int new_x, new_y;
2661
2662 new_x = event.xclient.data.s[0];
2663 new_y = event.xclient.data.s[1];
2664 }
2665 }
2666 break;
2667
2668 #ifdef NEW_SELECTIONS
2669 case SelectionNotify:
2670 x_handle_selection_notify (&event);
2671 break;
2672 #endif
2673
2674 case SelectionClear: /* Someone has grabbed ownership. */
2675 #ifdef NEW_SELECTIONS
2676 {
2677 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
2678
2679 if (numchars == 0)
2680 abort ();
2681
2682 bufp->kind = selection_clear_event;
2683 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2684 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2685 SELECTION_EVENT_TIME (bufp) = eventp->time;
2686 bufp++;
2687
2688 count += 1;
2689 numchars -= 1;
2690 }
2691 #else
2692 x_disown_selection (event.xselectionclear.window,
2693 event.xselectionclear.selection,
2694 event.xselectionclear.time);
2695 #endif
2696 break;
2697
2698 case SelectionRequest: /* Someone wants our selection. */
2699 #ifdef NEW_SELECTIONS
2700 {
2701 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
2702
2703 if (numchars == 0)
2704 abort ();
2705
2706 bufp->kind = selection_request_event;
2707 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
2708 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
2709 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
2710 SELECTION_EVENT_TARGET (bufp) = eventp->target;
2711 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
2712 SELECTION_EVENT_TIME (bufp) = eventp->time;
2713 bufp++;
2714
2715 count += 1;
2716 numchars -= 1;
2717 }
2718 #else
2719 x_answer_selection_request (event);
2720 #endif
2721 break;
2722
2723 case PropertyNotify:
2724 #ifdef NEW_SELECTIONS
2725 x_handle_property_notify (&event);
2726 #else
2727 /* If we're being told about a root window property, then it's
2728 a cut buffer change. */
2729 if (event.xproperty.window == ROOT_WINDOW)
2730 x_invalidate_cut_buffer_cache (&event.xproperty);
2731
2732 /* Otherwise, we're probably handling an incremental
2733 selection transmission. */
2734 else
2735 {
2736 /* If we were to do this synchronously, there'd be no worry
2737 about re-selecting. */
2738 x_send_incremental (event);
2739 }
2740 #endif
2741 break;
2742
2743 case ReparentNotify:
2744 f = x_window_to_frame (event.xreparent.window);
2745 if (f)
2746 f->display.x->parent_desc = event.xreparent.parent;
2747 break;
2748
2749 case Expose:
2750 f = x_window_to_frame (event.xexpose.window);
2751 if (f)
2752 {
2753 if (f->async_visible == 0)
2754 {
2755 f->async_visible = 1;
2756 f->async_iconified = 0;
2757 SET_FRAME_GARBAGED (f);
2758 }
2759 else
2760 {
2761 dumprectangle (x_window_to_frame (event.xexpose.window),
2762 event.xexpose.x, event.xexpose.y,
2763 event.xexpose.width, event.xexpose.height);
2764 }
2765 }
2766 else
2767 {
2768 struct scroll_bar *bar
2769 = x_window_to_scroll_bar (event.xexpose.window);
2770
2771 if (bar)
2772 x_scroll_bar_expose (bar, &event);
2773 }
2774 break;
2775
2776 case GraphicsExpose: /* This occurs when an XCopyArea's
2777 source area was obscured or not
2778 available.*/
2779 f = x_window_to_frame (event.xgraphicsexpose.drawable);
2780 if (f)
2781 {
2782 dumprectangle (f,
2783 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
2784 event.xgraphicsexpose.width,
2785 event.xgraphicsexpose.height);
2786 }
2787 break;
2788
2789 case NoExpose: /* This occurs when an XCopyArea's
2790 source area was completely
2791 available */
2792 break;
2793 #else /* ! defined (HAVE_X11) */
2794 case ExposeWindow:
2795 if (event.subwindow != 0)
2796 break; /* duplicate event */
2797 f = x_window_to_frame (event.window);
2798 if (event.window == f->display.x->icon_desc)
2799 {
2800 refreshicon (f);
2801 f->async_iconified = 1;
2802 }
2803 if (event.window == FRAME_X_WINDOW (f))
2804 {
2805 /* Say must check all windows' needs_exposure flags. */
2806 expose_all_windows = 1;
2807 f->display.x->needs_exposure = 1;
2808 f->async_visible = 1;
2809 }
2810 break;
2811
2812 case ExposeRegion:
2813 if (event.subwindow != 0)
2814 break; /* duplicate event */
2815 f = x_window_to_frame (event.window);
2816 if (event.window == f->display.x->icon_desc)
2817 {
2818 refreshicon (f);
2819 break;
2820 }
2821 /* If window already needs full redraw, ignore this rectangle. */
2822 if (expose_all_windows && f->display.x->needs_exposure)
2823 break;
2824 /* Put the event on the queue of rectangles to redraw. */
2825 if (enqueue_event (&event, &x_expose_queue))
2826 /* If it is full, we can't record the rectangle,
2827 so redraw this entire window. */
2828 {
2829 /* Say must check all windows' needs_exposure flags. */
2830 expose_all_windows = 1;
2831 f->display.x->needs_exposure = 1;
2832 }
2833 break;
2834
2835 case ExposeCopy:
2836 /* This should happen only when we are expecting it,
2837 in x_read_exposes. */
2838 abort ();
2839 #endif /* ! defined (HAVE_X11) */
2840
2841 #ifdef HAVE_X11
2842 case UnmapNotify:
2843 f = x_window_to_frame (event.xunmap.window);
2844 if (f) /* F may no longer exist if
2845 the frame was deleted. */
2846 {
2847 /* While a frame is unmapped, display generation is
2848 disabled; you don't want to spend time updating a
2849 display that won't ever be seen. */
2850 f->async_visible = 0;
2851 /* The window manager never makes a window invisible
2852 ("withdrawn"); all it does is switch between visible
2853 and iconified. Frames get into the invisible state
2854 only through x_make_frame_invisible.
2855 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
2856 f->async_iconified = 1;
2857 }
2858 break;
2859
2860 case MapNotify:
2861 f = x_window_to_frame (event.xmap.window);
2862 if (f)
2863 {
2864 f->async_visible = 1;
2865 f->async_iconified = 0;
2866
2867 /* wait_reading_process_input will notice this and update
2868 the frame's display structures. */
2869 SET_FRAME_GARBAGED (f);
2870 }
2871 break;
2872
2873 /* Turn off processing if we become fully obscured. */
2874 case VisibilityNotify:
2875 break;
2876
2877 #else /* ! defined (HAVE_X11) */
2878 case UnmapWindow:
2879 f = x_window_to_frame (event.window);
2880 if (event.window == f->display.x->icon_desc)
2881 f->async_iconified = 0;
2882 if (event.window == FRAME_X_WINDOW (f))
2883 f->async_visible = 0;
2884 break;
2885 #endif /* ! defined (HAVE_X11) */
2886
2887 #ifdef HAVE_X11
2888 case KeyPress:
2889 f = x_window_to_frame (event.xkey.window);
2890
2891 if (f != 0)
2892 {
2893 KeySym keysym, orig_keysym;
2894 char copy_buffer[80];
2895 int modifiers;
2896
2897 event.xkey.state
2898 |= x_emacs_to_x_modifiers (extra_keyboard_modifiers);
2899 modifiers = event.xkey.state;
2900
2901 /* This will have to go some day... */
2902
2903 /* make_lispy_event turns chars into control chars.
2904 Don't do it here because XLookupString is too eager. */
2905 event.xkey.state &= ~ControlMask;
2906 nbytes =
2907 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2908 &compose_status);
2909
2910 /* Strip off the vendor-specific keysym bit, and take a shot
2911 at recognizing the codes. HP servers have extra keysyms
2912 that fit into the MiscFunctionKey category. */
2913 orig_keysym = keysym;
2914 keysym &= ~(1<<28);
2915
2916 if (numchars > 1)
2917 {
2918 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
2919 || keysym == XK_Delete
2920 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2921 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
2922 #ifdef HPUX
2923 /* This recognizes the "extended function keys".
2924 It seems there's no cleaner way.
2925 Test IsModifierKey to avoid handling mode_switch
2926 incorrectly. */
2927 || ((unsigned) (keysym) >= XK_Select
2928 && (unsigned)(keysym) < XK_KP_Space)
2929 #endif
2930 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2931 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
2932 || x_is_vendor_fkey (orig_keysym))
2933 && ! IsModifierKey (orig_keysym)) /* wherever */
2934 {
2935 if (temp_index == sizeof temp_buffer / sizeof (short))
2936 temp_index = 0;
2937 temp_buffer[temp_index++] = keysym;
2938 bufp->kind = non_ascii_keystroke;
2939 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff00);
2940 XSET (bufp->frame_or_window, Lisp_Frame, f);
2941 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2942 bufp->timestamp = event.xkey.time;
2943 bufp++;
2944 count++;
2945 numchars--;
2946 }
2947 else if (numchars > nbytes)
2948 {
2949 register int i;
2950
2951 for (i = 0; i < nbytes; i++)
2952 {
2953 if (temp_index == sizeof temp_buffer / sizeof (short))
2954 temp_index = 0;
2955 temp_buffer[temp_index++] = copy_buffer[i];
2956 bufp->kind = ascii_keystroke;
2957 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2958 XSET (bufp->frame_or_window, Lisp_Frame, f);
2959 bufp->modifiers = x_x_to_emacs_modifiers (modifiers);
2960 bufp->timestamp = event.xkey.time;
2961 bufp++;
2962 }
2963
2964 count += nbytes;
2965 numchars -= nbytes;
2966 }
2967 else
2968 abort ();
2969 }
2970 else
2971 abort ();
2972 }
2973 break;
2974 #else /* ! defined (HAVE_X11) */
2975 case KeyPressed:
2976 {
2977 register char *where_mapping;
2978
2979 f = x_window_to_frame (event.window);
2980 /* Ignore keys typed on icon windows. */
2981 if (f != 0 && event.window == f->display.x->icon_desc)
2982 break;
2983 where_mapping = XLookupMapping (&event, &nbytes);
2984 /* Nasty fix for arrow keys */
2985 if (!nbytes && IsCursorKey (event.detail & 0xff))
2986 {
2987 switch (event.detail & 0xff)
2988 {
2989 case KC_CURSOR_LEFT:
2990 where_mapping = "\002";
2991 break;
2992 case KC_CURSOR_RIGHT:
2993 where_mapping = "\006";
2994 break;
2995 case KC_CURSOR_UP:
2996 where_mapping = "\020";
2997 break;
2998 case KC_CURSOR_DOWN:
2999 where_mapping = "\016";
3000 break;
3001 }
3002 nbytes = 1;
3003 }
3004 if (numchars - nbytes > 0)
3005 {
3006 register int i;
3007
3008 for (i = 0; i < nbytes; i++)
3009 {
3010 bufp->kind = ascii_keystroke;
3011 XSET (bufp->code, Lisp_Int, where_mapping[i]);
3012 XSET (bufp->time, Lisp_Int, event.xkey.time);
3013 XSET (bufp->frame_or_window, Lisp_Frame, f);
3014 bufp++;
3015 }
3016 count += nbytes;
3017 numchars -= nbytes;
3018 }
3019 }
3020 break;
3021 #endif /* ! defined (HAVE_X11) */
3022
3023 #ifdef HAVE_X11
3024
3025 /* Here's a possible interpretation of the whole
3026 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3027 FocusIn event, you have to get a FocusOut event before you
3028 relinquish the focus. If you haven't received a FocusIn event,
3029 then a mere LeaveNotify is enough to free you. */
3030
3031 case EnterNotify:
3032 f = x_window_to_frame (event.xcrossing.window);
3033
3034 if (event.xcrossing.focus) /* Entered Window */
3035 {
3036 /* Avoid nasty pop/raise loops. */
3037 if (f && (!(f->auto_raise)
3038 || !(f->auto_lower)
3039 || (event.xcrossing.time - enter_timestamp) > 500))
3040 {
3041 x_new_focus_frame (f);
3042 enter_timestamp = event.xcrossing.time;
3043 }
3044 }
3045 else if (f == x_focus_frame)
3046 x_new_focus_frame (0);
3047
3048 break;
3049
3050 case FocusIn:
3051 f = x_window_to_frame (event.xfocus.window);
3052 if (event.xfocus.detail != NotifyPointer)
3053 x_focus_event_frame = f;
3054 if (f)
3055 x_new_focus_frame (f);
3056 break;
3057
3058
3059 case LeaveNotify:
3060 f = x_window_to_frame (event.xcrossing.window);
3061
3062 if (event.xcrossing.focus)
3063 {
3064 if (! x_focus_event_frame)
3065 x_new_focus_frame (0);
3066 else
3067 x_new_focus_frame (f);
3068 }
3069 else
3070 {
3071 if (f == x_focus_event_frame)
3072 x_focus_event_frame = 0;
3073 if (f == x_focus_frame)
3074 x_new_focus_frame (0);
3075 }
3076 break;
3077
3078 case FocusOut:
3079 f = x_window_to_frame (event.xfocus.window);
3080 if (event.xfocus.detail != NotifyPointer
3081 && f == x_focus_event_frame)
3082 x_focus_event_frame = 0;
3083 if (f && f == x_focus_frame)
3084 x_new_focus_frame (0);
3085 break;
3086
3087 #else /* ! defined (HAVE_X11) */
3088
3089 case EnterWindow:
3090 if ((event.detail & 0xFF) == 1)
3091 break; /* Coming from our own subwindow */
3092 if (event.subwindow != 0)
3093 break; /* Entering our own subwindow. */
3094
3095 {
3096 f = x_window_to_frame (event.window);
3097 x_mouse_frame = f;
3098
3099 x_new_focus_frame (f);
3100 }
3101 break;
3102
3103 case LeaveWindow:
3104 if ((event.detail & 0xFF) == 1)
3105 break; /* Entering our own subwindow */
3106 if (event.subwindow != 0)
3107 break; /* Leaving our own subwindow. */
3108
3109 x_mouse_frame = 0;
3110 if (x_focus_frame == 0
3111 && x_input_frame != 0
3112 && x_input_frame == x_window_to_frame (event.window)
3113 && event.window == FRAME_X_WINDOW (x_input_frame))
3114 {
3115 f = x_input_frame;
3116 x_input_frame = 0;
3117 if (f)
3118 frame_unhighlight (f);
3119 }
3120 break;
3121 #endif /* ! defined (HAVE_X11) */
3122
3123 #ifdef HAVE_X11
3124 case MotionNotify:
3125 {
3126 f = x_window_to_frame (event.xmotion.window);
3127 if (f)
3128 note_mouse_movement (f, &event.xmotion);
3129 else
3130 {
3131 struct scroll_bar *bar =
3132 x_window_to_scroll_bar (event.xmotion.window);
3133
3134 if (bar)
3135 x_scroll_bar_note_movement (bar, &event);
3136 }
3137 }
3138 break;
3139
3140 case ConfigureNotify:
3141 f = x_window_to_frame (event.xconfigure.window);
3142 if (f)
3143 {
3144 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3145 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3146
3147 /* Even if the number of character rows and columns has
3148 not changed, the font size may have changed, so we need
3149 to check the pixel dimensions as well. */
3150 if (columns != f->width
3151 || rows != f->height
3152 || event.xconfigure.width != f->display.x->pixel_width
3153 || event.xconfigure.height != f->display.x->pixel_height)
3154 {
3155 change_frame_size (f, rows, columns, 0, 1);
3156 SET_FRAME_GARBAGED (f);
3157 }
3158
3159 if (! event.xconfigure.send_event)
3160 {
3161 Window win, child;
3162 int win_x, win_y;
3163
3164 /* Coords are relative to the parent.
3165 Convert them to root-relative. */
3166 XTranslateCoordinates (x_current_display,
3167
3168 /* From-window, to-window. */
3169 f->display.x->parent_desc,
3170 ROOT_WINDOW,
3171
3172 /* From-position, to-position. */
3173 event.xconfigure.x,
3174 event.xconfigure.y,
3175 &win_x, &win_y,
3176
3177 /* Child of win. */
3178 &child);
3179 event.xconfigure.x = win_x;
3180 event.xconfigure.y = win_y;
3181 }
3182
3183 f->display.x->pixel_width = event.xconfigure.width;
3184 f->display.x->pixel_height = event.xconfigure.height;
3185 f->display.x->left_pos = event.xconfigure.x;
3186 f->display.x->top_pos = event.xconfigure.y;
3187 }
3188 break;
3189
3190 case ButtonPress:
3191 case ButtonRelease:
3192 {
3193 /* If we decide we want to generate an event to be seen
3194 by the rest of Emacs, we put it here. */
3195 struct input_event emacs_event;
3196 emacs_event.kind = no_event;
3197
3198 f = x_window_to_frame (event.xbutton.window);
3199 if (f)
3200 {
3201 if (!x_focus_frame || (f == x_focus_frame))
3202 construct_mouse_click (&emacs_event,
3203 &event, f);
3204 }
3205 else
3206 {
3207 struct scroll_bar *bar =
3208 x_window_to_scroll_bar (event.xbutton.window);
3209
3210 if (bar)
3211 x_scroll_bar_handle_click (bar, &event, &emacs_event);
3212 }
3213
3214 if (numchars >= 1 && emacs_event.kind != no_event)
3215 {
3216 bcopy (&emacs_event, bufp, sizeof (struct input_event));
3217 bufp++;
3218 count++;
3219 numchars--;
3220 }
3221 }
3222 break;
3223
3224 #else /* ! defined (HAVE_X11) */
3225 case ButtonPressed:
3226 case ButtonReleased:
3227 f = x_window_to_frame (event.window);
3228 if (f)
3229 {
3230 if (event.window == f->display.x->icon_desc)
3231 {
3232 x_make_frame_visible (f);
3233
3234 if (warp_mouse_on_deiconify)
3235 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
3236 break;
3237 }
3238 if (event.window == FRAME_X_WINDOW (f))
3239 {
3240 if (f->auto_raise)
3241 x_raise_frame (f);
3242 }
3243 }
3244 enqueue_event (&event, &x_mouse_queue);
3245 if (numchars >= 2)
3246 {
3247 bufp->kind = ascii_keystroke;
3248 bufp->code = (char) 'X' & 037; /* C-x */
3249 XSET (bufp->frame_or_window, Lisp_Frame, f);
3250 XSET (bufp->time, Lisp_Int, event.xkey.time);
3251 bufp++;
3252
3253 bufp->kind = ascii_keystroke;
3254 bufp->code = (char) 0; /* C-@ */
3255 XSET (bufp->frame_or_window, Lisp_Frame, f);
3256 XSET (bufp->time, Lisp_Int, event.xkey.time);
3257 bufp++;
3258
3259 count += 2;
3260 numchars -= 2;
3261 }
3262 break;
3263 #endif /* ! defined (HAVE_X11) */
3264
3265 #ifdef HAVE_X11
3266
3267 case CirculateNotify:
3268 break;
3269 case CirculateRequest:
3270 break;
3271
3272 #endif /* ! defined (HAVE_X11) */
3273
3274 case MappingNotify:
3275 /* Someone has changed the keyboard mapping - update the
3276 local cache. */
3277 switch (event.xmapping.request)
3278 {
3279 case MappingModifier:
3280 x_find_modifier_meanings ();
3281 /* This is meant to fall through. */
3282 case MappingKeyboard:
3283 XRefreshKeyboardMapping (&event.xmapping);
3284 }
3285 break;
3286
3287 default:
3288 break;
3289 }
3290 }
3291
3292 #ifdef HAVE_SELECT
3293 if (expected && ! event_found)
3294 {
3295 /* AOJ 880406: if select returns true but XPending doesn't, it means that
3296 there is an EOF condition; in other words, that X has died.
3297 Act as if there had been a hangup. */
3298 int fd = ConnectionNumber (x_current_display);
3299 SELECT_TYPE mask;
3300
3301 FD_SET(fd, &mask);
3302 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
3303 (EMACS_TIME *) 0)
3304 && !XStuffPending ())
3305 kill (getpid (), SIGHUP);
3306 }
3307 #endif /* ! defined (HAVE_SELECT) */
3308
3309 #ifndef HAVE_X11
3310 if (updating_frame == 0)
3311 x_do_pending_expose ();
3312 #endif
3313
3314 UNBLOCK_INPUT;
3315 return count;
3316 }
3317
3318 #ifndef HAVE_X11
3319 /* Read and process only Expose events
3320 until we get an ExposeCopy event; then return.
3321 This is used in insert/delete line.
3322 We assume input is already blocked. */
3323
3324 static void
3325 x_read_exposes ()
3326 {
3327 struct frame *f;
3328 XKeyPressedEvent event;
3329
3330 while (1)
3331 {
3332 /* while there are more events*/
3333 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
3334 switch (event.type)
3335 {
3336 case ExposeWindow:
3337 if (event.subwindow != 0)
3338 break; /* duplicate event */
3339 f = x_window_to_frame (event.window);
3340 if (event.window == f->display.x->icon_desc)
3341 {
3342 refreshicon (f);
3343 break;
3344 }
3345 if (event.window == FRAME_X_WINDOW (f))
3346 {
3347 expose_all_windows = 1;
3348 f->display.x->needs_exposure = 1;
3349 break;
3350 }
3351 break;
3352
3353 case ExposeRegion:
3354 if (event.subwindow != 0)
3355 break; /* duplicate event */
3356 f = x_window_to_frame (event.window);
3357 if (event.window == f->display.x->icon_desc)
3358 {
3359 refreshicon (f);
3360 break;
3361 }
3362 /* If window already needs full redraw, ignore this rectangle. */
3363 if (expose_all_windows && f->display.x->needs_exposure)
3364 break;
3365 /* Put the event on the queue of rectangles to redraw. */
3366 if (enqueue_event (&event, &x_expose_queue))
3367 /* If it is full, we can't record the rectangle,
3368 so redraw this entire window. */
3369 {
3370 /* Say must check all windows' needs_exposure flags. */
3371 expose_all_windows = 1;
3372 f->display.x->needs_exposure = 1;
3373 }
3374 break;
3375
3376 case ExposeCopy:
3377 return;
3378 }
3379 }
3380 }
3381 #endif /* HAVE_X11 */
3382
3383 \f
3384 /* Drawing the cursor. */
3385
3386
3387 /* Draw a hollow box cursor. Don't change the inside of the box. */
3388
3389 static void
3390 x_draw_box (f)
3391 struct frame *f;
3392 {
3393 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x);
3394 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y);
3395 int width = FONT_WIDTH (f->display.x->font);
3396 int height = FONT_HEIGHT (f->display.x->font);
3397
3398 #ifdef HAVE_X11
3399 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
3400 f->display.x->cursor_gc,
3401 left, top, width - 1, height - 1);
3402 #else /* ! defined (HAVE_X11) */
3403 XPixSet (FRAME_X_WINDOW (f),
3404 left, top, width, 1,
3405 f->display.x->cursor_pixel);
3406
3407 XPixSet (FRAME_X_WINDOW (f),
3408 left, top, 1, height,
3409 f->display.x->cursor_pixel);
3410
3411 XPixSet (FRAME_X_WINDOW (f),
3412 left+width-1, top, 1, height,
3413 f->display.x->cursor_pixel);
3414
3415 XPixSet (FRAME_X_WINDOW (f),
3416 left, top+height-1, width, 1,
3417 f->display.x->cursor_pixel);
3418 #endif /* ! defined (HAVE_X11) */
3419 }
3420
3421 /* Clear the cursor of frame F to background color,
3422 and mark the cursor as not shown.
3423 This is used when the text where the cursor is
3424 is about to be rewritten. */
3425
3426 static void
3427 clear_cursor (f)
3428 struct frame *f;
3429 {
3430 int mask;
3431
3432 if (! FRAME_VISIBLE_P (f)
3433 || f->phys_cursor_x < 0)
3434 return;
3435
3436 #ifdef HAVE_X11
3437 x_display_cursor (f, 0);
3438 #else /* ! defined (HAVE_X11) */
3439 XPixSet (FRAME_X_WINDOW (f),
3440 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
3441 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
3442 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
3443 f->display.x->background_pixel);
3444 #endif /* ! defined (HAVE_X11) */
3445 f->phys_cursor_x = -1;
3446 }
3447
3448 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
3449 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
3450 glyph drawn. */
3451
3452 static void
3453 x_draw_single_glyph (f, row, column, glyph, highlight)
3454 struct frame *f;
3455 int row, column;
3456 GLYPH glyph;
3457 int highlight;
3458 {
3459 dumpglyphs (f,
3460 CHAR_TO_PIXEL_COL (f, column),
3461 CHAR_TO_PIXEL_ROW (f, row),
3462 &glyph, 1, highlight);
3463 }
3464
3465 static void
3466 x_display_bar_cursor (f, on)
3467 struct frame *f;
3468 int on;
3469 {
3470 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3471
3472 /* This is pointless on invisible frames, and dangerous on garbaged
3473 frames; in the latter case, the frame may be in the midst of
3474 changing its size, and curs_x and curs_y may be off the frame. */
3475 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3476 return;
3477
3478 if (! on && f->phys_cursor_x < 0)
3479 return;
3480
3481 /* If we're not updating, then we want to use the current frame's
3482 cursor position, not our local idea of where the cursor ought to be. */
3483 if (f != updating_frame)
3484 {
3485 curs_x = FRAME_CURSOR_X (f);
3486 curs_y = FRAME_CURSOR_Y (f);
3487 }
3488
3489 /* If there is anything wrong with the current cursor state, remove it. */
3490 if (f->phys_cursor_x >= 0
3491 && (!on
3492 || f->phys_cursor_x != curs_x
3493 || f->phys_cursor_y != curs_y
3494 || f->display.x->current_cursor != bar_cursor))
3495 {
3496 /* Erase the cursor by redrawing the character underneath it. */
3497 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3498 f->phys_cursor_glyph,
3499 current_glyphs->highlight[f->phys_cursor_y]);
3500 f->phys_cursor_x = -1;
3501 }
3502
3503 /* If we now need a cursor in the new place or in the new form, do it so. */
3504 if (on
3505 && (f->phys_cursor_x < 0
3506 || (f->display.x->current_cursor != bar_cursor)))
3507 {
3508 f->phys_cursor_glyph
3509 = ((current_glyphs->enable[curs_y]
3510 && curs_x < current_glyphs->used[curs_y])
3511 ? current_glyphs->glyphs[curs_y][curs_x]
3512 : SPACEGLYPH);
3513 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
3514 f->display.x->cursor_gc,
3515 CHAR_TO_PIXEL_COL (f, curs_x),
3516 CHAR_TO_PIXEL_ROW (f, curs_y),
3517 1, FONT_HEIGHT (f->display.x->font));
3518
3519 f->phys_cursor_x = curs_x;
3520 f->phys_cursor_y = curs_y;
3521
3522 f->display.x->current_cursor = bar_cursor;
3523 }
3524
3525 if (updating_frame != f)
3526 XFlushQueue ();
3527 }
3528
3529
3530 /* Turn the displayed cursor of frame F on or off according to ON.
3531 If ON is nonzero, where to put the cursor is specified
3532 by F->cursor_x and F->cursor_y. */
3533
3534 static void
3535 x_display_box_cursor (f, on)
3536 struct frame *f;
3537 int on;
3538 {
3539 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
3540
3541 /* This is pointless on invisible frames, and dangerous on garbaged
3542 frames; in the latter case, the frame may be in the midst of
3543 changing its size, and curs_x and curs_y may be off the frame. */
3544 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
3545 return;
3546
3547 /* If cursor is off and we want it off, return quickly. */
3548 if (!on && f->phys_cursor_x < 0)
3549 return;
3550
3551 /* If we're not updating, then we want to use the current frame's
3552 cursor position, not our local idea of where the cursor ought to be. */
3553 if (f != updating_frame)
3554 {
3555 curs_x = FRAME_CURSOR_X (f);
3556 curs_y = FRAME_CURSOR_Y (f);
3557 }
3558
3559 /* If cursor is currently being shown and we don't want it to be
3560 or it is in the wrong place,
3561 or we want a hollow box and it's not so, (pout!)
3562 erase it. */
3563 if (f->phys_cursor_x >= 0
3564 && (!on
3565 || f->phys_cursor_x != curs_x
3566 || f->phys_cursor_y != curs_y
3567 || (f->display.x->current_cursor != hollow_box_cursor
3568 && (f != x_highlight_frame))))
3569 {
3570 /* Erase the cursor by redrawing the character underneath it. */
3571 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
3572 f->phys_cursor_glyph,
3573 current_glyphs->highlight[f->phys_cursor_y]);
3574 f->phys_cursor_x = -1;
3575 }
3576
3577 /* If we want to show a cursor,
3578 or we want a box cursor and it's not so,
3579 write it in the right place. */
3580 if (on
3581 && (f->phys_cursor_x < 0
3582 || (f->display.x->current_cursor != filled_box_cursor
3583 && f == x_highlight_frame)))
3584 {
3585 f->phys_cursor_glyph
3586 = ((current_glyphs->enable[curs_y]
3587 && curs_x < current_glyphs->used[curs_y])
3588 ? current_glyphs->glyphs[curs_y][curs_x]
3589 : SPACEGLYPH);
3590 if (f != x_highlight_frame)
3591 {
3592 x_draw_box (f);
3593 f->display.x->current_cursor = hollow_box_cursor;
3594 }
3595 else
3596 {
3597 x_draw_single_glyph (f, curs_y, curs_x,
3598 f->phys_cursor_glyph, 2);
3599 f->display.x->current_cursor = filled_box_cursor;
3600 }
3601
3602 f->phys_cursor_x = curs_x;
3603 f->phys_cursor_y = curs_y;
3604 }
3605
3606 if (updating_frame != f)
3607 XFlushQueue ();
3608 }
3609
3610 x_display_cursor (f, on)
3611 struct frame *f;
3612 int on;
3613 {
3614 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
3615 x_display_box_cursor (f, on);
3616 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
3617 x_display_bar_cursor (f, on);
3618 else
3619 /* Those are the only two we have implemented! */
3620 abort ();
3621 }
3622 \f
3623 /* Icons. */
3624
3625 /* Refresh bitmap kitchen sink icon for frame F
3626 when we get an expose event for it. */
3627
3628 refreshicon (f)
3629 struct frame *f;
3630 {
3631 #ifdef HAVE_X11
3632 /* Normally, the window manager handles this function. */
3633 #else /* ! defined (HAVE_X11) */
3634 int mask;
3635
3636 if (f->display.x->icon_bitmap_flag)
3637 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
3638 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
3639 icon_bitmap, GXcopy, AllPlanes);
3640 else
3641 {
3642 extern struct frame *selected_frame;
3643 struct Lisp_String *str;
3644 unsigned char *string;
3645
3646 string
3647 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
3648
3649 if (f->display.x->icon_label != string)
3650 {
3651 f->display.x->icon_label = string;
3652 XChangeWindow (f->display.x->icon_desc,
3653 XQueryWidth (string, icon_font_info->id) + 10,
3654 icon_font_info->height + 10);
3655 }
3656
3657 XText (f->display.x->icon_desc, 5, 5, string,
3658 str->size, icon_font_info->id,
3659 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
3660 }
3661 XFlushQueue ();
3662 #endif /* ! defined (HAVE_X11) */
3663 }
3664
3665 /* Make the x-window of frame F use the gnu icon bitmap. */
3666
3667 int
3668 x_bitmap_icon (f)
3669 struct frame *f;
3670 {
3671 int mask;
3672 Window icon_window;
3673
3674 if (FRAME_X_WINDOW (f) == 0)
3675 return 1;
3676
3677 #ifdef HAVE_X11
3678 if (! icon_bitmap)
3679 icon_bitmap =
3680 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
3681 gnu_bits, gnu_width, gnu_height);
3682 x_wm_set_icon_pixmap (f, icon_bitmap);
3683 f->display.x->icon_bitmap_flag = 1;
3684 #else /* ! defined (HAVE_X11) */
3685 if (f->display.x->icon_desc)
3686 {
3687 XClearIconWindow (FRAME_X_WINDOW (f));
3688 XDestroyWindow (f->display.x->icon_desc);
3689 }
3690
3691 icon_window = XCreateWindow (f->display.x->parent_desc,
3692 0, 0, sink_width, sink_height,
3693 2, WhitePixmap, (Pixmap) NULL);
3694
3695 if (icon_window == 0)
3696 return 1;
3697
3698 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3699 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
3700
3701 f->display.x->icon_desc = icon_window;
3702 f->display.x->icon_bitmap_flag = 1;
3703
3704 if (icon_bitmap == 0)
3705 icon_bitmap
3706 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
3707 #endif /* ! defined (HAVE_X11) */
3708
3709 return 0;
3710 }
3711
3712
3713 /* Make the x-window of frame F use a rectangle with text. */
3714
3715 int
3716 x_text_icon (f, icon_name)
3717 struct frame *f;
3718 char *icon_name;
3719 {
3720 #ifndef HAVE_X11
3721 int mask;
3722 int width;
3723 Window icon_window;
3724 char *X_DefaultValue;
3725 Bitmap b1;
3726
3727 #ifndef WhitePixel
3728 #define WhitePixel 1
3729 #endif /* WhitePixel */
3730
3731 #ifndef BlackPixel
3732 #define BlackPixel 0
3733 #endif /* BlackPixel */
3734 #endif /* HAVE_X11 */
3735
3736 if (FRAME_X_WINDOW (f) == 0)
3737 return 1;
3738
3739 #ifdef HAVE_X11
3740 if (icon_name)
3741 f->display.x->icon_label = icon_name;
3742 else
3743 if (! f->display.x->icon_label)
3744 f->display.x->icon_label = " *emacs* ";
3745
3746 #if 0
3747 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
3748 (char *) f->display.x->icon_label);
3749 #endif
3750
3751 f->display.x->icon_bitmap_flag = 0;
3752 x_wm_set_icon_pixmap (f, 0);
3753 #else /* ! defined (HAVE_X11) */
3754 if (icon_font_info == 0)
3755 icon_font_info
3756 = XGetFont (XGetDefault (XDISPLAY
3757 (char *) XSTRING (Vinvocation_name)->data,
3758 "BodyFont"));
3759
3760 if (f->display.x->icon_desc)
3761 {
3762 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
3763 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
3764 }
3765
3766 if (icon_name)
3767 f->display.x->icon_label = (unsigned char *) icon_name;
3768 else
3769 if (! f->display.x->icon_label)
3770 f->display.x->icon_label = XSTRING (f->name)->data;
3771
3772 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
3773 icon_window = XCreateWindow (f->display.x->parent_desc,
3774 f->display.x->left_pos,
3775 f->display.x->top_pos,
3776 width + 10, icon_font_info->height + 10,
3777 2, BlackPixmap, WhitePixmap);
3778
3779 if (icon_window == 0)
3780 return 1;
3781
3782 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
3783 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
3784
3785 f->display.x->icon_desc = icon_window;
3786 f->display.x->icon_bitmap_flag = 0;
3787 f->display.x->icon_label = 0;
3788 #endif /* ! defined (HAVE_X11) */
3789
3790 return 0;
3791 }
3792 \f
3793 /* Handling X errors. */
3794
3795 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the
3796 X server's connection, or an error reported via the X protocol. */
3797
3798 static SIGTYPE
3799 x_connection_closed ()
3800 {
3801 if (_Xdebug)
3802 abort ();
3803
3804 shut_down_emacs (0, 1, Qnil);
3805
3806 exit (70);
3807 }
3808
3809 /* An X error handler which prints an error message and then kills
3810 Emacs. This is what's normally installed as Xlib's handler for
3811 protocol errors. */
3812 static int
3813 x_error_quitter (display, error)
3814 Display *display;
3815 XErrorEvent *error;
3816 {
3817 char buf[256];
3818
3819 /* Note that there is no real way portable across R3/R4 to get the
3820 original error handler. */
3821
3822 XGetErrorText (display, error->error_code, buf, sizeof (buf));
3823 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
3824 buf, error->request_code);
3825
3826 #if 0
3827 /* While we're testing Emacs 19, we'll just dump core whenever we
3828 get an X error, so we can figure out why it happened. */
3829 abort ();
3830 #endif
3831
3832 x_connection_closed ();
3833 }
3834
3835 /* A handler for X IO errors which prints an error message and then
3836 kills Emacs. This is what is always installed as Xlib's handler
3837 for I/O errors. */
3838 static int
3839 x_io_error_quitter (display)
3840 Display *display;
3841 {
3842 fprintf (stderr, "Connection to X server %s lost.\n",
3843 XDisplayName (DisplayString (display)));
3844
3845 #if 0
3846 /* While we're testing Emacs 19, we'll just dump core whenever we
3847 get an X error, so we can figure out why it happened. */
3848 abort ();
3849 #endif
3850
3851 x_connection_closed ();
3852 }
3853
3854 /* A buffer for storing X error messages. */
3855 static char *x_caught_error_message;
3856 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
3857
3858 /* An X error handler which stores the error message in
3859 x_caught_error_message. This is what's installed when
3860 x_catch_errors is in effect. */
3861 static int
3862 x_error_catcher (display, error)
3863 Display *display;
3864 XErrorEvent *error;
3865 {
3866 XGetErrorText (display, error->error_code,
3867 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
3868 }
3869
3870
3871 /* Begin trapping X errors.
3872
3873 After calling this function, X protocol errors no longer cause
3874 Emacs to exit; instead, they are recorded in x_cfc_error_message.
3875
3876 Calling x_check_errors signals an Emacs error if an X error has
3877 occurred since the last call to x_catch_errors or x_check_errors.
3878
3879 Calling x_uncatch_errors resumes the normal error handling. */
3880
3881 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
3882
3883 void
3884 x_catch_errors ()
3885 {
3886 /* Make sure any errors from previous requests have been dealt with. */
3887 XSync (x_current_display, False);
3888
3889 /* Set up the error buffer. */
3890 x_caught_error_message
3891 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
3892 x_caught_error_message[0] = '\0';
3893
3894 /* Install our little error handler. */
3895 XHandleError (x_error_catcher);
3896 }
3897
3898 /* If any X protocol errors have arrived since the last call to
3899 x_catch_errors or x_check_errors, signal an Emacs error using
3900 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3901 void
3902 x_check_errors (format)
3903 char *format;
3904 {
3905 /* Make sure to catch any errors incurred so far. */
3906 XSync (x_current_display, False);
3907
3908 if (x_caught_error_message[0])
3909 {
3910 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
3911
3912 sprintf (buf, format, x_caught_error_message);
3913 x_uncatch_errors ();
3914 error (buf);
3915 }
3916 }
3917
3918 void
3919 x_uncatch_errors ()
3920 {
3921 xfree (x_caught_error_message);
3922 x_caught_error_message = 0;
3923 XHandleError (x_error_quitter);
3924 }
3925
3926 #if 0
3927 static unsigned int x_wire_count;
3928 x_trace_wire ()
3929 {
3930 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3931 }
3932 #endif /* ! 0 */
3933
3934 \f
3935 /* Changing the font of the frame. */
3936
3937 /* Set the font of the x-window specified by frame F
3938 to the font named NEWNAME. This is safe to use
3939 even before F has an actual x-window. */
3940
3941 #ifdef HAVE_X11
3942
3943 /* A table of all the fonts we have already loaded. */
3944 static XFontStruct **x_font_table;
3945
3946 /* The current capacity of x_font_table. */
3947 static int x_font_table_size;
3948
3949 /* The number of fonts actually stored in x_font_table.
3950 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3951 0 <= n_fonts <= x_font_table_size. */
3952 static int n_fonts;
3953
3954 Lisp_Object
3955 x_new_font (f, fontname)
3956 struct frame *f;
3957 register char *fontname;
3958 {
3959 int already_loaded;
3960 int n_matching_fonts;
3961 XFontStruct *font_info;
3962 char **font_names;
3963
3964 /* Get a list of all the fonts that match this name. Once we
3965 have a list of matching fonts, we compare them against the fonts
3966 we already have by comparing font ids. */
3967 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3968 1024, &n_matching_fonts,
3969 &font_info);
3970 /* Apparently it doesn't set n_matching_fonts to zero when it can't
3971 find any matches; font_names == 0 is the only clue. */
3972 if (! font_names)
3973 n_matching_fonts = 0;
3974
3975 /* Don't just give up if n_matching_fonts is 0.
3976 Apparently there's a bug on Suns: XListFontsWithInfo can
3977 fail to find a font, but XLoadQueryFont may still find it. */
3978
3979 /* See if we've already loaded a matching font. */
3980 already_loaded = -1;
3981 if (n_matching_fonts != 0)
3982 {
3983 int i, j;
3984
3985 for (i = 0; i < n_fonts; i++)
3986 for (j = 0; j < n_matching_fonts; j++)
3987 if (x_font_table[i]->fid == font_info[j].fid)
3988 {
3989 already_loaded = i;
3990 fontname = font_names[j];
3991 goto found_font;
3992 }
3993 }
3994 found_font:
3995
3996 /* If we have, just return it from the table. */
3997 if (already_loaded > 0)
3998 f->display.x->font = x_font_table[already_loaded];
3999
4000 /* Otherwise, load the font and add it to the table. */
4001 else
4002 {
4003 int i;
4004 XFontStruct *font;
4005
4006 /* Try to find a character-cell font in the list. */
4007 #if 0
4008 /* A laudable goal, but this isn't how to do it. */
4009 for (i = 0; i < n_matching_fonts; i++)
4010 if (! font_info[i].per_char)
4011 break;
4012 #else
4013 i = 0;
4014 #endif
4015
4016 /* See comment above. */
4017 if (n_matching_fonts != 0)
4018 fontname = font_names[i];
4019
4020 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
4021 if (! font)
4022 {
4023 /* Free the information from XListFontsWithInfo. */
4024 if (n_matching_fonts)
4025 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4026 return Qnil;
4027 }
4028
4029 /* Do we need to create the table? */
4030 if (x_font_table_size == 0)
4031 {
4032 x_font_table_size = 16;
4033 x_font_table
4034 = (XFontStruct **) xmalloc (x_font_table_size
4035 * sizeof (x_font_table[0]));
4036 }
4037 /* Do we need to grow the table? */
4038 else if (n_fonts >= x_font_table_size)
4039 {
4040 x_font_table_size *= 2;
4041 x_font_table
4042 = (XFontStruct **) xrealloc (x_font_table,
4043 (x_font_table_size
4044 * sizeof (x_font_table[0])));
4045 }
4046
4047 f->display.x->font = x_font_table[n_fonts++] = font;
4048 }
4049
4050 /* Now make the frame display the given font. */
4051 if (FRAME_X_WINDOW (f) != 0)
4052 {
4053 XSetFont (x_current_display, f->display.x->normal_gc,
4054 f->display.x->font->fid);
4055 XSetFont (x_current_display, f->display.x->reverse_gc,
4056 f->display.x->font->fid);
4057 XSetFont (x_current_display, f->display.x->cursor_gc,
4058 f->display.x->font->fid);
4059
4060 x_set_window_size (f, f->width, f->height);
4061 }
4062
4063 {
4064 Lisp_Object lispy_name = build_string (fontname);
4065
4066
4067 /* Free the information from XListFontsWithInfo. The data
4068 we actually retain comes from XLoadQueryFont. */
4069 XFreeFontInfo (font_names, font_info, n_matching_fonts);
4070
4071 return lispy_name;
4072 }
4073 }
4074 #else /* ! defined (HAVE_X11) */
4075 x_new_font (f, newname)
4076 struct frame *f;
4077 register char *newname;
4078 {
4079 FONT_TYPE *temp;
4080 int mask;
4081
4082 temp = XGetFont (newname);
4083 if (temp == (FONT_TYPE *) 0)
4084 return 1;
4085
4086 if (f->display.x->font)
4087 XLoseFont (f->display.x->font);
4088
4089 f->display.x->font = temp;
4090
4091 if (FRAME_X_WINDOW (f) != 0)
4092 x_set_window_size (f, f->width, f->height);
4093
4094 return 0;
4095 }
4096 #endif /* ! defined (HAVE_X11) */
4097 \f
4098 /* X Window sizes and positions. */
4099
4100 x_calc_absolute_position (f)
4101 struct frame *f;
4102 {
4103 #ifdef HAVE_X11
4104 if (f->display.x->left_pos < 0)
4105 f->display.x->left_pos = (x_screen_width
4106 - 2 * f->display.x->border_width
4107 - PIXEL_WIDTH (f)
4108 + f->display.x->left_pos);
4109
4110 if (f->display.x->top_pos < 0)
4111 f->display.x->top_pos = (x_screen_height
4112 - 2 * f->display.x->border_width
4113 - PIXEL_HEIGHT (f)
4114 + f->display.x->top_pos);
4115 #else /* ! defined (HAVE_X11) */
4116 WINDOWINFO_TYPE parentinfo;
4117
4118 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
4119
4120 if (f->display.x->left_pos < 0)
4121 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
4122 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
4123
4124 if (f->display.x->top_pos < 0)
4125 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
4126 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
4127 #endif /* ! defined (HAVE_X11) */
4128 }
4129
4130 x_set_offset (f, xoff, yoff)
4131 struct frame *f;
4132 register int xoff, yoff;
4133 {
4134 f->display.x->top_pos = yoff;
4135 f->display.x->left_pos = xoff;
4136 x_calc_absolute_position (f);
4137
4138 BLOCK_INPUT;
4139 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
4140 f->display.x->left_pos, f->display.x->top_pos);
4141 #ifdef HAVE_X11
4142 x_wm_set_size_hint (f, 0);
4143 #endif /* ! defined (HAVE_X11) */
4144 UNBLOCK_INPUT;
4145 }
4146
4147 /* Call this to change the size of frame F's x-window. */
4148
4149 x_set_window_size (f, cols, rows)
4150 struct frame *f;
4151 int cols, rows;
4152 {
4153 int pixelwidth, pixelheight;
4154 int mask;
4155
4156 BLOCK_INPUT;
4157
4158 check_frame_size (f, &rows, &cols);
4159 f->display.x->vertical_scroll_bar_extra =
4160 (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4161 ? VERTICAL_SCROLL_BAR_PIXEL_WIDTH (f)
4162 : 0);
4163 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
4164 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
4165
4166 #ifdef HAVE_X11
4167 x_wm_set_size_hint (f, 0);
4168 #endif /* ! defined (HAVE_X11) */
4169 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
4170
4171 /* Now, strictly speaking, we can't be sure that this is accurate,
4172 but the window manager will get around to dealing with the size
4173 change request eventually, and we'll hear how it went when the
4174 ConfigureNotify event gets here.
4175
4176 We could just not bother storing any of this information here,
4177 and let the ConfigureNotify event set everything up, but that
4178 might be kind of confusing to the lisp code, since size changes
4179 wouldn't be reported in the frame parameters until some random
4180 point in the future when the ConfigureNotify event arrives. */
4181 change_frame_size (f, rows, cols, 0, 0);
4182 PIXEL_WIDTH (f) = pixelwidth;
4183 PIXEL_HEIGHT (f) = pixelheight;
4184
4185 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
4186 receive in the ConfigureNotify event; if we get what we asked
4187 for, then the event won't cause the screen to become garbaged, so
4188 we have to make sure to do it here. */
4189 SET_FRAME_GARBAGED (f);
4190
4191 XFlushQueue ();
4192 UNBLOCK_INPUT;
4193 }
4194
4195 #ifndef HAVE_X11
4196 x_set_resize_hint (f)
4197 struct frame *f;
4198 {
4199 XSetResizeHint (FRAME_X_WINDOW (f),
4200 2 * f->display.x->internal_border_width,
4201 2 * f->display.x->internal_border_width,
4202 FONT_WIDTH (f->display.x->font),
4203 FONT_HEIGHT (f->display.x->font));
4204 }
4205 #endif /* HAVE_X11 */
4206 \f
4207 /* Mouse warping, focus shifting, raising and lowering. */
4208
4209 x_set_mouse_position (f, x, y)
4210 struct frame *f;
4211 int x, y;
4212 {
4213 int pix_x, pix_y;
4214
4215 x_raise_frame (f);
4216
4217 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2;
4218 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2;
4219
4220 if (pix_x < 0) pix_x = 0;
4221 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
4222
4223 if (pix_y < 0) pix_y = 0;
4224 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
4225
4226 BLOCK_INPUT;
4227
4228 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
4229 UNBLOCK_INPUT;
4230 }
4231
4232 #ifdef HAVE_X11
4233 x_focus_on_frame (f)
4234 struct frame *f;
4235 {
4236 x_raise_frame (f);
4237 #if 0
4238 /* I don't think that the ICCCM allows programs to do things like this
4239 without the interaction of the window manager. Whatever you end up
4240 doing with this code, do it to x_unfocus_frame too. */
4241 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
4242 RevertToPointerRoot, CurrentTime);
4243 #endif /* ! 0 */
4244 }
4245
4246 x_unfocus_frame (f)
4247 struct frame *f;
4248 {
4249 #if 0
4250 /* Look at the remarks in x_focus_on_frame. */
4251 if (x_focus_frame == f)
4252 XSetInputFocus (x_current_display, PointerRoot,
4253 RevertToPointerRoot, CurrentTime);
4254 #endif /* ! 0 */
4255 }
4256
4257 #endif /* ! defined (HAVE_X11) */
4258
4259 /* Raise frame F. */
4260
4261 x_raise_frame (f)
4262 struct frame *f;
4263 {
4264 if (f->async_visible)
4265 {
4266 BLOCK_INPUT;
4267 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
4268 XFlushQueue ();
4269 UNBLOCK_INPUT;
4270 }
4271 }
4272
4273 /* Lower frame F. */
4274
4275 x_lower_frame (f)
4276 struct frame *f;
4277 {
4278 if (f->async_visible)
4279 {
4280 BLOCK_INPUT;
4281 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
4282 XFlushQueue ();
4283 UNBLOCK_INPUT;
4284 }
4285 }
4286
4287 static void
4288 XTframe_raise_lower (f, raise)
4289 FRAME_PTR f;
4290 int raise;
4291 {
4292 if (raise)
4293 x_raise_frame (f);
4294 else
4295 x_lower_frame (f);
4296 }
4297
4298
4299 /* Change from withdrawn state to mapped state. */
4300
4301 x_make_frame_visible (f)
4302 struct frame *f;
4303 {
4304 int mask;
4305
4306 BLOCK_INPUT;
4307
4308 if (! FRAME_VISIBLE_P (f))
4309 {
4310 #ifdef HAVE_X11
4311 if (! EQ (Vx_no_window_manager, Qt))
4312 x_wm_set_window_state (f, NormalState);
4313
4314 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4315 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4316 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
4317 #else /* ! defined (HAVE_X11) */
4318 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
4319 if (f->display.x->icon_desc != 0)
4320 XUnmapWindow (f->display.x->icon_desc);
4321
4322 /* Handled by the MapNotify event for X11 */
4323 f->async_visible = 1;
4324 f->async_iconified = 0;
4325
4326 /* NOTE: this may cause problems for the first frame. */
4327 XTcursor_to (0, 0);
4328 #endif /* ! defined (HAVE_X11) */
4329 }
4330
4331 XFlushQueue ();
4332
4333 UNBLOCK_INPUT;
4334 }
4335
4336 /* Change from mapped state to withdrawn state. */
4337
4338 x_make_frame_invisible (f)
4339 struct frame *f;
4340 {
4341 int mask;
4342
4343 /* Don't keep the highlight on an invisible frame. */
4344 if (x_highlight_frame == f)
4345 x_highlight_frame = 0;
4346
4347 if (! f->async_visible && ! f->async_iconified)
4348 return;
4349
4350 BLOCK_INPUT;
4351
4352 #ifdef HAVE_X11R4
4353
4354 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
4355 DefaultScreen (x_current_display)))
4356 {
4357 UNBLOCK_INPUT_RESIGNAL;
4358 error ("can't notify window manager of window withdrawal");
4359 }
4360
4361 #else /* ! defined (HAVE_X11R4) */
4362 #ifdef HAVE_X11
4363
4364 /* Tell the window manager what we're going to do. */
4365 if (! EQ (Vx_no_window_manager, Qt))
4366 {
4367 XEvent unmap;
4368
4369 unmap.xunmap.type = UnmapNotify;
4370 unmap.xunmap.window = FRAME_X_WINDOW (f);
4371 unmap.xunmap.event = DefaultRootWindow (x_current_display);
4372 unmap.xunmap.from_configure = False;
4373 if (! XSendEvent (x_current_display,
4374 DefaultRootWindow (x_current_display),
4375 False,
4376 SubstructureRedirectMask|SubstructureNotifyMask,
4377 &unmap))
4378 {
4379 UNBLOCK_INPUT_RESIGNAL;
4380 error ("can't notify window manager of withdrawal");
4381 }
4382 }
4383
4384 /* Unmap the window ourselves. Cheeky! */
4385 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
4386
4387 #else /* ! defined (HAVE_X11) */
4388
4389 XUnmapWindow (FRAME_X_WINDOW (f));
4390 f->async_visible = 0; /* Handled by the UnMap event for X11 */
4391 if (f->display.x->icon_desc != 0)
4392 XUnmapWindow (f->display.x->icon_desc);
4393
4394 #endif /* ! defined (HAVE_X11) */
4395 #endif /* ! defined (HAVE_X11R4) */
4396
4397 XFlushQueue ();
4398 UNBLOCK_INPUT;
4399 }
4400
4401 /* Change window state from mapped to iconified. */
4402
4403 x_iconify_frame (f)
4404 struct frame *f;
4405 {
4406 int mask;
4407
4408 /* Don't keep the highlight on an invisible frame. */
4409 if (x_highlight_frame == f)
4410 x_highlight_frame = 0;
4411
4412 if (f->async_iconified)
4413 return;
4414
4415 BLOCK_INPUT;
4416
4417 #ifdef HAVE_X11
4418 /* Since we don't know which revision of X we're running, we'll use both
4419 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
4420
4421 /* X11R4: send a ClientMessage to the window manager using the
4422 WM_CHANGE_STATE type. */
4423 {
4424 XEvent message;
4425
4426 message.xclient.window = FRAME_X_WINDOW (f);
4427 message.xclient.type = ClientMessage;
4428 message.xclient.message_type = Xatom_wm_change_state;
4429 message.xclient.format = 32;
4430 message.xclient.data.l[0] = IconicState;
4431
4432 if (! XSendEvent (x_current_display,
4433 DefaultRootWindow (x_current_display),
4434 False,
4435 SubstructureRedirectMask | SubstructureNotifyMask,
4436 &message))
4437 {
4438 UNBLOCK_INPUT_RESIGNAL;
4439 error ("Can't notify window manager of iconification.");
4440 }
4441 }
4442
4443 /* X11R3: set the initial_state field of the window manager hints to
4444 IconicState. */
4445 x_wm_set_window_state (f, IconicState);
4446
4447 f->async_iconified = 1;
4448 #else /* ! defined (HAVE_X11) */
4449 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
4450
4451 f->async_visible = 0; /* Handled in the UnMap event for X11. */
4452 if (f->display.x->icon_desc != 0)
4453 {
4454 XMapWindow (XDISPLAY f->display.x->icon_desc);
4455 refreshicon (f);
4456 }
4457 #endif /* ! defined (HAVE_X11) */
4458
4459 XFlushQueue ();
4460 UNBLOCK_INPUT;
4461 }
4462
4463 /* Destroy the X window of frame F. */
4464
4465 x_destroy_window (f)
4466 struct frame *f;
4467 {
4468 BLOCK_INPUT;
4469
4470 if (f->display.x->icon_desc != 0)
4471 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
4472 XDestroyWindow (XDISPLAY f->display.x->window_desc);
4473 free_frame_faces (f);
4474 XFlushQueue ();
4475
4476 xfree (f->display.x);
4477 f->display.x = 0;
4478 if (f == x_focus_frame)
4479 x_focus_frame = 0;
4480 if (f == x_highlight_frame)
4481 x_highlight_frame = 0;
4482
4483 UNBLOCK_INPUT;
4484 }
4485 \f
4486 /* Manage event queues for X10. */
4487
4488 #ifndef HAVE_X11
4489
4490 /* Manage event queues.
4491
4492 This code is only used by the X10 support.
4493
4494 We cannot leave events in the X queue and get them when we are ready
4495 because X does not provide a subroutine to get only a certain kind
4496 of event but not block if there are no queued events of that kind.
4497
4498 Therefore, we must examine events as they come in and copy events
4499 of certain kinds into our private queues.
4500
4501 All ExposeRegion events are put in x_expose_queue.
4502 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
4503
4504
4505 /* Write the event *P_XREP into the event queue *QUEUE.
4506 If the queue is full, do nothing, but return nonzero. */
4507
4508 int
4509 enqueue_event (p_xrep, queue)
4510 register XEvent *p_xrep;
4511 register struct event_queue *queue;
4512 {
4513 int newindex = queue->windex + 1;
4514 if (newindex == EVENT_BUFFER_SIZE)
4515 newindex = 0;
4516 if (newindex == queue->rindex)
4517 return -1;
4518 queue->xrep[queue->windex] = *p_xrep;
4519 queue->windex = newindex;
4520 return 0;
4521 }
4522
4523 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
4524 If *QUEUE is empty, do nothing and return 0. */
4525
4526 int
4527 dequeue_event (p_xrep, queue)
4528 register XEvent *p_xrep;
4529 register struct event_queue *queue;
4530 {
4531 if (queue->windex == queue->rindex)
4532 return 0;
4533 *p_xrep = queue->xrep[queue->rindex++];
4534 if (queue->rindex == EVENT_BUFFER_SIZE)
4535 queue->rindex = 0;
4536 return 1;
4537 }
4538
4539 /* Return the number of events buffered in *QUEUE. */
4540
4541 int
4542 queue_event_count (queue)
4543 register struct event_queue *queue;
4544 {
4545 int tem = queue->windex - queue->rindex;
4546 if (tem >= 0)
4547 return tem;
4548 return EVENT_BUFFER_SIZE + tem;
4549 }
4550
4551 /* Return nonzero if mouse input is pending. */
4552
4553 int
4554 mouse_event_pending_p ()
4555 {
4556 return queue_event_count (&x_mouse_queue);
4557 }
4558 #endif /* HAVE_X11 */
4559 \f
4560 /* Setting window manager hints. */
4561
4562 #ifdef HAVE_X11
4563
4564 x_wm_set_size_hint (f, prompting)
4565 struct frame *f;
4566 long prompting;
4567 {
4568 XSizeHints size_hints;
4569 Window window = FRAME_X_WINDOW (f);
4570
4571 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
4572
4573 flexlines = f->height;
4574
4575 size_hints.x = f->display.x->left_pos;
4576 size_hints.y = f->display.x->top_pos;
4577 size_hints.height = PIXEL_HEIGHT (f);
4578 size_hints.width = PIXEL_WIDTH (f);
4579 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
4580 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
4581 #if 0
4582 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0);
4583 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0);
4584 #endif
4585 {
4586 int base_width, base_height;
4587
4588 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
4589 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
4590
4591 {
4592 int min_rows = 0, min_cols = 0;
4593 check_frame_size (f, &min_rows, &min_cols);
4594
4595 /* The window manager uses the base width hints to calculate the
4596 current number of rows and columns in the frame while
4597 resizing; min_width and min_height aren't useful for this
4598 purpose, since they might not give the dimensions for a
4599 zero-row, zero-column frame.
4600
4601 We use the base_width and base_height members if we have
4602 them; otherwise, we set the min_width and min_height members
4603 to the size for a zero x zero frame. */
4604
4605 #ifdef HAVE_X11R4
4606 size_hints.flags |= PBaseSize;
4607 size_hints.base_width = base_width;
4608 size_hints.base_height = base_height;
4609 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
4610 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
4611 #else
4612 size_hints.min_width = base_width;
4613 size_hints.min_height = base_height;
4614 #endif
4615 }
4616
4617 }
4618
4619 if (prompting)
4620 size_hints.flags |= prompting;
4621 else
4622 {
4623 XSizeHints hints; /* Sometimes I hate X Windows... */
4624
4625 if (XGetNormalHints (x_current_display, window, &hints) == 0)
4626 hints.flags = 0;
4627 if (hints.flags & PSize)
4628 size_hints.flags |= PSize;
4629 if (hints.flags & PPosition)
4630 size_hints.flags |= PPosition;
4631 if (hints.flags & USPosition)
4632 size_hints.flags |= USPosition;
4633 if (hints.flags & USSize)
4634 size_hints.flags |= USSize;
4635 }
4636
4637 #ifdef HAVE_X11R4
4638 XSetWMNormalHints (x_current_display, window, &size_hints);
4639 #else
4640 XSetNormalHints (x_current_display, window, &size_hints);
4641 #endif
4642 }
4643
4644 /* Used for IconicState or NormalState */
4645 x_wm_set_window_state (f, state)
4646 struct frame *f;
4647 int state;
4648 {
4649 Window window = FRAME_X_WINDOW (f);
4650
4651 f->display.x->wm_hints.flags |= StateHint;
4652 f->display.x->wm_hints.initial_state = state;
4653
4654 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4655 }
4656
4657 x_wm_set_icon_pixmap (f, icon_pixmap)
4658 struct frame *f;
4659 Pixmap icon_pixmap;
4660 {
4661 Window window = FRAME_X_WINDOW (f);
4662
4663 if (icon_pixmap)
4664 {
4665 f->display.x->wm_hints.icon_pixmap = icon_pixmap;
4666 f->display.x->wm_hints.flags |= IconPixmapHint;
4667 }
4668 else
4669 f->display.x->wm_hints.flags &= ~IconPixmapHint;
4670
4671 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4672 }
4673
4674 x_wm_set_icon_position (f, icon_x, icon_y)
4675 struct frame *f;
4676 int icon_x, icon_y;
4677 {
4678 Window window = FRAME_X_WINDOW (f);
4679
4680 f->display.x->wm_hints.flags |= IconPositionHint;
4681 f->display.x->wm_hints.icon_x = icon_x;
4682 f->display.x->wm_hints.icon_y = icon_y;
4683
4684 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
4685 }
4686
4687 \f
4688 /* Initialization. */
4689
4690 void
4691 x_term_init (display_name)
4692 char *display_name;
4693 {
4694 Lisp_Object frame;
4695 char *defaultvalue;
4696 #ifdef F_SETOWN
4697 extern int old_fcntl_owner;
4698 #endif /* ! defined (F_SETOWN) */
4699
4700 x_focus_frame = x_highlight_frame = 0;
4701
4702 x_current_display = XOpenDisplay (display_name);
4703 if (x_current_display == 0)
4704 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
4705 display_name);
4706
4707 #ifdef HAVE_X11
4708 {
4709 int hostname_size = 256;
4710
4711 hostname = (char *) xmalloc (hostname_size);
4712
4713 #if 0
4714 XSetAfterFunction (x_current_display, x_trace_wire);
4715 #endif /* ! 0 */
4716
4717 /* Try to get the host name; if the buffer is too short, try
4718 again. Apparently, the only indication gethostname gives of
4719 whether the buffer was large enough is the presence or absence
4720 of a '\0' in the string. Eech. */
4721 for (;;)
4722 {
4723 gethostname (hostname, hostname_size - 1);
4724 hostname[hostname_size - 1] = '\0';
4725
4726 /* Was the buffer large enough for gethostname to store the '\0'? */
4727 if (strlen (hostname) < hostname_size - 1)
4728 break;
4729
4730 hostname_size <<= 1;
4731 hostname = (char *) xrealloc (hostname, hostname_size);
4732 }
4733 x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
4734 + strlen (hostname)
4735 + 2);
4736 sprintf (x_id_name, "%s@%s", XSTRING (Vinvocation_name)->data, hostname);
4737 }
4738
4739 /* Figure out which modifier bits mean what. */
4740 x_find_modifier_meanings ();
4741
4742 /* Get the scroll bar cursor. */
4743 x_vertical_scroll_bar_cursor
4744 = XCreateFontCursor (x_current_display, XC_sb_v_double_arrow);
4745
4746 #if 0
4747 /* Watch for PropertyNotify events on the root window; we use them
4748 to figure out when to invalidate our cache of the cut buffers. */
4749 x_watch_cut_buffer_cache ();
4750 #endif
4751
4752 if (ConnectionNumber (x_current_display) != 0)
4753 {
4754 dup2 (ConnectionNumber (x_current_display), 0);
4755
4756 #ifndef SYSV_STREAMS
4757 /* Streams somehow keeps track of which descriptor number
4758 is being used to talk to X. So it is not safe to substitute
4759 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
4760 close (ConnectionNumber (x_current_display));
4761 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
4762 * check the def of the macro;
4763 * it is a genuine lvalue */
4764 #endif /* SYSV_STREAMS */
4765 }
4766
4767 #endif /* ! defined (HAVE_X11) */
4768
4769 #ifdef F_SETOWN
4770 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
4771 #ifdef F_SETOWN_SOCK_NEG
4772 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
4773 #else /* ! defined (F_SETOWN_SOCK_NEG) */
4774 fcntl (0, F_SETOWN, getpid ());
4775 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
4776 #endif /* ! defined (F_SETOWN) */
4777
4778 #ifdef SIGIO
4779 init_sigio ();
4780 #endif /* ! defined (SIGIO) */
4781
4782 /* Must use interrupt input because we cannot otherwise
4783 arrange for C-g to be noticed immediately.
4784 We cannot connect it to SIGINT. */
4785 Fset_input_mode (Qt, Qnil, Qt, Qnil);
4786
4787 expose_all_windows = 0;
4788
4789 clear_frame_hook = XTclear_frame;
4790 clear_end_of_line_hook = XTclear_end_of_line;
4791 ins_del_lines_hook = XTins_del_lines;
4792 change_line_highlight_hook = XTchange_line_highlight;
4793 insert_glyphs_hook = XTinsert_glyphs;
4794 write_glyphs_hook = XTwrite_glyphs;
4795 delete_glyphs_hook = XTdelete_glyphs;
4796 ring_bell_hook = XTring_bell;
4797 reset_terminal_modes_hook = XTreset_terminal_modes;
4798 set_terminal_modes_hook = XTset_terminal_modes;
4799 update_begin_hook = XTupdate_begin;
4800 update_end_hook = XTupdate_end;
4801 set_terminal_window_hook = XTset_terminal_window;
4802 read_socket_hook = XTread_socket;
4803 cursor_to_hook = XTcursor_to;
4804 reassert_line_highlight_hook = XTreassert_line_highlight;
4805 mouse_position_hook = XTmouse_position;
4806 frame_rehighlight_hook = XTframe_rehighlight;
4807 frame_raise_lower_hook = XTframe_raise_lower;
4808 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
4809 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
4810 redeem_scroll_bar_hook = XTredeem_scroll_bar;
4811 judge_scroll_bars_hook = XTjudge_scroll_bars;
4812
4813 scroll_region_ok = 1; /* we'll scroll partial frames */
4814 char_ins_del_ok = 0; /* just as fast to write the line */
4815 line_ins_del_ok = 1; /* we'll just blt 'em */
4816 fast_clear_end_of_line = 1; /* X does this well */
4817 memory_below_frame = 0; /* we don't remember what scrolls
4818 off the bottom */
4819 baud_rate = 19200;
4820
4821 /* Note that there is no real way portable across R3/R4 to get the
4822 original error handler. */
4823 XHandleError (x_error_quitter);
4824 XHandleIOError (x_io_error_quitter);
4825
4826 /* Disable Window Change signals; they are handled by X events. */
4827 #ifdef SIGWINCH
4828 signal (SIGWINCH, SIG_DFL);
4829 #endif /* ! defined (SIGWINCH) */
4830
4831 signal (SIGPIPE, x_connection_closed);
4832 }
4833
4834 void
4835 syms_of_xterm ()
4836 {
4837 staticpro (&last_mouse_scroll_bar);
4838 }
4839 #endif /* ! defined (HAVE_X11) */
4840 #endif /* ! defined (HAVE_X_WINDOWS) */