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