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