Give subprocess creation a way to find a valid current directory
[bpt/emacs.git] / src / xterm.c
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1992 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 #include "config.h"
29
30 #ifdef HAVE_X_WINDOWS
31
32 #include "lisp.h"
33
34 /* On 4.3 these lose if they come after xterm.h. */
35 #include <stdio.h>
36 #include <signal.h>
37
38 /* This may include sys/types.h, and that somehow loses
39 if this is not done before the other system files. */
40 #include "xterm.h"
41
42 #ifndef USG
43 /* Load sys/types.h if not already loaded.
44 In some systems loading it twice is suicidal. */
45 #ifndef makedev
46 #include <sys/types.h>
47 #endif /* makedev */
48 #endif /* USG */
49
50 #ifdef BSD
51 #include <sys/ioctl.h>
52 #include <strings.h>
53 #else /* ! defined (BSD) */
54 #include <sys/termio.h>
55 #include <string.h>
56 #endif /* ! defined (BSD) */
57
58 /* Allow m- file to inhibit use of FIONREAD. */
59 #ifdef BROKEN_FIONREAD
60 #undef FIONREAD
61 #endif /* ! defined (BROKEN_FIONREAD) */
62
63 /* We are unable to use interrupts if FIONREAD is not available,
64 so flush SIGIO so we won't try. */
65 #ifndef FIONREAD
66 #ifdef SIGIO
67 #undef SIGIO
68 #endif /* ! defined (SIGIO) */
69 #endif /* FIONREAD */
70
71 #include "systime.h"
72
73 #include <fcntl.h>
74 #include <ctype.h>
75 #include <errno.h>
76 #include <setjmp.h>
77 #include <sys/stat.h>
78 #include <sys/param.h>
79
80 #include "dispextern.h"
81 #include "termhooks.h"
82 #include "termopts.h"
83 #include "termchar.h"
84 #if 0
85 #include "sink.h"
86 #include "sinkmask.h"
87 #endif /* ! 0 */
88 #include "gnu.h"
89 #include "frame.h"
90 #include "disptab.h"
91 #include "buffer.h"
92
93 #ifdef HAVE_X11
94 #define XMapWindow XMapRaised /* Raise them when mapping. */
95 #else /* ! defined (HAVE_X11) */
96 #include <X/Xkeyboard.h>
97 /*#include <X/Xproto.h> */
98 #endif /* ! defined (HAVE_X11) */
99
100 /* For sending Meta-characters. Do we need this? */
101 #define METABIT 0200
102
103 #define min(a,b) ((a)<(b) ? (a) : (b))
104 #define max(a,b) ((a)>(b) ? (a) : (b))
105
106 /* Nonzero means we must reprint all windows
107 because 1) we received an ExposeWindow event
108 or 2) we received too many ExposeRegion events to record. */
109
110 static int expose_all_windows;
111
112 /* Nonzero means we must reprint all icon windows. */
113
114 static int expose_all_icons;
115
116 #ifndef HAVE_X11
117 /* ExposeRegion events, when received, are copied into this queue
118 for later processing. */
119
120 static struct event_queue x_expose_queue;
121
122 /* ButtonPressed and ButtonReleased events, when received,
123 are copied into this queue for later processing. */
124
125 struct event_queue x_mouse_queue;
126 #endif /* HAVE_X11 */
127
128 /* Nonzero after BLOCK_INPUT; prevents input events from being
129 processed until later. */
130
131 int x_input_blocked;
132
133 #if defined (SIGIO) && defined (FIONREAD)
134 int BLOCK_INPUT_mask;
135 #endif /* ! defined (SIGIO) && defined (FIONREAD) */
136
137 /* Nonzero if input events came in while x_input_blocked was nonzero.
138 UNBLOCK_INPUT checks for this. */
139
140 int x_pending_input;
141
142 /* The id of a bitmap used for icon windows.
143 One such map is shared by all Emacs icon windows.
144 This is zero if we have not yet had a need to create the bitmap. */
145
146 static Bitmap icon_bitmap;
147
148 /* Font used for text icons. */
149
150 static FONT_TYPE *icon_font_info;
151
152 /* Stuff for dealing with the main icon title. */
153
154 extern Lisp_Object Vcommand_line_args;
155 char *hostname, *x_id_name;
156 Lisp_Object invocation_name;
157
158 /* This is the X connection that we are using. */
159
160 Display *x_current_display;
161
162 /* Frame being updated by update_frame. */
163 /* This is set by XTupdate_begin and looked at by all the
164 XT functions. It is zero while not inside an update.
165 In that case, the XT functions assume that `selected_frame'
166 is the frame to apply to. */
167
168 static struct frame *updating_frame;
169
170 /* The frame (if any) which has the X window that has keyboard focus.
171 Zero if none. This is examined by Ffocus_frame in frame.c. */
172 struct frame *x_focus_frame;
173
174 /* The frame which currently has the visual highlight, and should get
175 keyboard input (other sorts of input have the frame encoded in the
176 event). It points to the X focus frame's selected window's
177 frame. It differs from x_focus_frame when we're using a global
178 minibuffer. */
179 static struct frame *x_highlight_frame;
180
181 /* From .Xdefaults, the value of "emacs.WarpMouse". If non-zero,
182 mouse is moved to inside of frame when frame is de-iconified. */
183
184 static int warp_mouse_on_deiconify;
185
186 /* During an update, maximum vpos for ins/del line operations to affect. */
187
188 static int flexlines;
189
190 /* During an update, nonzero if chars output now should be highlighted. */
191
192 static int highlight;
193
194 /* Nominal cursor position -- where to draw output.
195 During an update, these are different from the cursor-box position. */
196
197 static int curs_x;
198 static int curs_y;
199
200 #ifdef HAVE_X11
201 /* `t' if a mouse button is depressed. */
202
203 extern Lisp_Object Vmouse_depressed;
204
205 /* Tells if a window manager is present or not. */
206
207 extern Lisp_Object Vx_no_window_manager;
208
209 /* Timestamp that we requested selection data was made. */
210 extern Time requestor_time;
211
212 /* ID of the window requesting selection data. */
213 extern Window requestor_window;
214
215 /* Nonzero enables some debugging for the X interface code. */
216 extern int _Xdebug;
217
218 #else /* ! defined (HAVE_X11) */
219
220 /* Bit patterns for the mouse cursor. */
221
222 short MouseCursor[] = {
223 0x0000, 0x0008, 0x0018, 0x0038,
224 0x0078, 0x00f8, 0x01f8, 0x03f8,
225 0x07f8, 0x00f8, 0x00d8, 0x0188,
226 0x0180, 0x0300, 0x0300, 0x0000};
227
228 short MouseMask[] = {
229 0x000c, 0x001c, 0x003c, 0x007c,
230 0x00fc, 0x01fc, 0x03fc, 0x07fc,
231 0x0ffc, 0x0ffc, 0x01fc, 0x03dc,
232 0x03cc, 0x0780, 0x0780, 0x0300};
233
234 static short grey_bits[] = {
235 0x0005, 0x000a, 0x0005, 0x000a};
236
237 static Pixmap GreyPixmap = 0;
238 #endif /* ! defined (HAVE_X11) */
239
240 /* From time to time we get info on an Emacs window, here. */
241
242 static WINDOWINFO_TYPE windowinfo;
243
244 extern int errno;
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 /* These hooks are called by update_frame at the beginning and end
264 of a frame update. We record in `updating_frame' the identity
265 of the frame being updated, so that the XT... functions do not
266 need to take a frame as argument. Most of the XT... functions
267 should never be called except during an update, the only exceptions
268 being XTcursor_to, XTwrite_char and XTreassert_line_highlight. */
269
270 extern int mouse_track_top, mouse_track_left, mouse_track_width;
271
272 static
273 XTupdate_begin (f)
274 struct frame *f;
275 {
276 int mask;
277
278 if (f == 0)
279 abort ();
280
281 updating_frame = f;
282 flexlines = f->height;
283 highlight = 0;
284
285 BLOCK_INPUT;
286 #ifndef HAVE_X11
287 dumpqueue ();
288 #endif /* HAVE_X11 */
289 UNBLOCK_INPUT;
290 }
291
292 static void x_do_pending_expose ();
293
294 static
295 XTupdate_end (f)
296 struct frame *f;
297 {
298 int mask;
299
300 if (updating_frame == 0
301 || updating_frame != f)
302 abort ();
303
304 BLOCK_INPUT;
305 #ifndef HAVE_X11
306 dumpqueue ();
307 #endif /* HAVE_X11 */
308 adjust_scrollbars (f);
309 x_do_pending_expose ();
310
311 x_display_cursor (f, 1);
312
313 updating_frame = 0;
314 XFlushQueue ();
315 UNBLOCK_INPUT;
316 }
317 \f
318 /* External interface to control of standout mode.
319 Call this when about to modify line at position VPOS
320 and not change whether it is highlighted. */
321
322 XTreassert_line_highlight (new, vpos)
323 int new, vpos;
324 {
325 highlight = new;
326 }
327
328 /* Call this when about to modify line at position VPOS
329 and change whether it is highlighted. */
330
331 static
332 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
333 int new_highlight, vpos, first_unused_hpos;
334 {
335 highlight = new_highlight;
336 XTcursor_to (vpos, 0);
337 XTclear_end_of_line (updating_frame->width);
338 }
339
340 /* This is used when starting Emacs and when restarting after suspend.
341 When starting Emacs, no X window is mapped. And nothing must be done
342 to Emacs's own window if it is suspended (though that rarely happens). */
343
344 static
345 XTset_terminal_modes ()
346 {
347 }
348
349 /* This is called when exiting or suspending Emacs.
350 Exiting will make the X-windows go away, and suspending
351 requires no action. */
352
353 static
354 XTreset_terminal_modes ()
355 {
356 /* XTclear_frame (); */
357 }
358 \f
359 /* Set the nominal cursor position of the frame:
360 where display update commands will take effect.
361 This does not affect the place where the cursor-box is displayed. */
362
363 static int
364 XTcursor_to (row, col)
365 register int row, col;
366 {
367 int mask;
368 int orow = row;
369
370 curs_x = col;
371 curs_y = row;
372
373 if (updating_frame == 0)
374 {
375 BLOCK_INPUT;
376 x_display_cursor (selected_frame, 1);
377 XFlushQueue ();
378 UNBLOCK_INPUT;
379 }
380 }
381 \f
382 /* Display a sequence of N glyphs found at GP.
383 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
384 HL is 1 if this text is highlighted, 2 if the cursor is on it.
385
386 FONT is the default font to use (for glyphs whose font-code is 0). */
387
388 static void
389 dumpglyphs (f, left, top, gp, n, hl, font)
390 struct frame *f;
391 int left, top;
392 register GLYPH *gp; /* Points to first GLYPH. */
393 register int n; /* Number of glyphs to display. */
394 int hl;
395 FONT_TYPE *font;
396 {
397 register int len;
398 Window window = FRAME_X_WINDOW (f);
399 GC drawing_gc = (hl == 2 ? f->display.x->cursor_gc
400 : (hl ? f->display.x->reverse_gc
401 : f->display.x->normal_gc));
402
403 if (sizeof (GLYPH) == sizeof (XChar2b))
404 XDrawImageString16 (x_current_display, window, drawing_gc,
405 left, top + FONT_BASE (font), (XChar2b *) gp, n);
406 else if (sizeof (GLYPH) == sizeof (unsigned char))
407 XDrawImageString (x_current_display, window, drawing_gc,
408 left, top + FONT_BASE (font), (char *) gp, n);
409 else
410 /* What size of glyph ARE you using? And does X have a function to
411 draw them? */
412 abort ();
413 }
414
415 #if 0
416 static void
417 dumpglyphs (f, left, top, gp, n, hl, font)
418 struct frame *f;
419 int left, top;
420 register GLYPH *gp; /* Points to first GLYPH. */
421 register int n; /* Number of glyphs to display. */
422 int hl;
423 FONT_TYPE *font;
424 {
425 char buf[f->width]; /* Holds characters to be displayed. */
426 register char *cp; /* Steps through buf[]. */
427 register int tlen = GLYPH_TABLE_LENGTH;
428 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
429 Window window = FRAME_X_WINDOW (f);
430 int cursor_pixel = f->display.x->cursor_pixel;
431 int fg_pixel = f->display.x->foreground_pixel;
432 int bg_pixel = f->display.x->background_pixel;
433 int intborder = f->display.x->internal_border_width;
434
435 while (n)
436 {
437 /* Get the face-code of the next GLYPH. */
438 int cf, len;
439 int g = *gp;
440
441 while (GLYPH_ALIAS_P (tbase, tlen, g))
442 g = GLYPH_ALIAS (tbase, g);
443
444 cf = g >> 8;
445
446 /* Find the run of consecutive glyphs with the same face-code.
447 Extract their character codes into BUF. */
448 cp = buf;
449 while (n > 0)
450 {
451 g = *gp;
452 while (GLYPH_ALIAS_P (tbase, tlen, g))
453 g = GLYPH_ALIAS (tbase, g);
454 if ((g >> 8) != cf)
455 break;
456
457 *cp++ = 0377 & g;
458 --n;
459 ++gp;
460 }
461
462 /* LEN gets the length of the run. */
463 len = cp - buf;
464
465 /* Now output this run of chars, with the font and pixel values
466 determined by the face code CF. */
467 if (cf == 0)
468 {
469 #ifdef HAVE_X11
470 GC GC_cursor = f->display.x->cursor_gc;
471 GC GC_reverse = f->display.x->reverse_gc;
472 GC GC_normal = f->display.x->normal_gc;
473
474 XDrawImageString (x_current_display, window,
475 (hl == 2
476 ? GC_cursor
477 : (hl ? GC_reverse : GC_normal)),
478 left, top + FONT_BASE (font), buf, len);
479 #else /* ! defined (HAVE_X11) */
480 XText (window, left, top,
481 buf,
482 len,
483 font->id,
484 (hl == 2
485 ? (cursor_pixel == fg_pixel ? bg_pixel : fg_pixel)
486 : hl ? bg_pixel : fg_pixel),
487 (hl == 2 ? cursor_pixel
488 : hl ? fg_pixel : bg_pixel));
489 #endif /* ! defined (HAVE_X11) */
490 }
491 else
492 {
493 #ifdef HAVE_X11
494 if (FACE_IS_FONT (cf))
495 XDrawImageString (x_current_display, FRAME_X_WINDOW (f),
496 FACE_GC (cf),
497 left, top + FONT_BASE (FACE_FONT (cf)),
498 buf, len);
499 else if (FACE_IS_IMAGE (cf))
500 XCopyPlane (x_current_display, FACE_IMAGE (cf),
501 FRAME_X_WINDOW (f),
502 f->display.x->normal_gc,
503 0, 0,
504 FACE_IMAGE_WIDTH (cf),
505 FACE_IMAGE_HEIGHT (cf), left, top);
506 else
507 abort ();
508 #else /* ! defined (HAVE_X11) */
509 register struct face *fp = x_face_table[cf];
510
511 XText (window, left, top,
512 buf,
513 len,
514 fp->font->id,
515 (hl == 2
516 ? (cursor_pixel == fp->fg ? fp->bg : fp->fg)
517 : hl ? fp->bg : fp->fg),
518 (hl == 2 ? cursor_pixel
519 : hl ? fp->fg : fp->bg));
520 #endif /* ! defined (HAVE_X11) */
521 }
522 left += len * FONT_WIDTH (font);
523 }
524 }
525 #endif /* ! 0 */
526 \f
527 /* Output some text at the nominal frame cursor position,
528 advancing the cursor over the text.
529 Output LEN glyphs at START.
530
531 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
532 controls the pixel values used for foreground and background. */
533
534 static
535 XTwrite_glyphs (start, len)
536 register GLYPH *start;
537 int len;
538 {
539 register int temp_length;
540 int mask;
541 struct frame *f;
542
543 BLOCK_INPUT;
544
545 f = updating_frame;
546 if (f == 0)
547 {
548 f = selected_frame;
549 /* If not within an update,
550 output at the frame's visible cursor. */
551 curs_x = f->cursor_x;
552 curs_y = f->cursor_y;
553 }
554
555 dumpglyphs (f,
556 (curs_x * FONT_WIDTH (f->display.x->font)
557 + f->display.x->internal_border_width),
558 (curs_y * FONT_HEIGHT (f->display.x->font)
559 + f->display.x->internal_border_width),
560 start, len, highlight, f->display.x->font);
561
562 /* If we drew on top of the cursor, note that it is turned off. */
563 if (curs_y == f->phys_cursor_y
564 && curs_x <= f->phys_cursor_x
565 && curs_x + len > f->phys_cursor_x)
566 f->phys_cursor_x = -1;
567
568 if (updating_frame == 0)
569 {
570 f->cursor_x += len;
571 x_display_cursor (f, 1);
572 f->cursor_x -= len;
573 }
574 else
575 curs_x += len;
576
577 UNBLOCK_INPUT;
578 }
579 \f
580 /* Erase the current text line from the nominal cursor position (inclusive)
581 to column FIRST_UNUSED (exclusive). The idea is that everything
582 from FIRST_UNUSED onward is already erased. */
583
584 static int
585 XTclear_end_of_line (first_unused)
586 register int first_unused;
587 {
588 struct frame *f = updating_frame;
589 int mask;
590
591 if (f == 0)
592 abort ();
593
594 if (curs_y < 0 || curs_y >= f->height)
595 return;
596 if (first_unused <= 0)
597 return;
598
599 if (first_unused >= f->width)
600 first_unused = f->width;
601
602 BLOCK_INPUT;
603
604 /* Notice if the cursor will be cleared by this operation. */
605 if (curs_y == f->phys_cursor_y
606 && curs_x <= f->phys_cursor_x
607 && f->phys_cursor_x < first_unused)
608 f->phys_cursor_x = -1;
609
610 #ifdef HAVE_X11
611 XClearArea (x_current_display, FRAME_X_WINDOW (f),
612 curs_x * FONT_WIDTH (f->display.x->font)
613 + f->display.x->internal_border_width,
614 curs_y * FONT_HEIGHT (f->display.x->font)
615 + f->display.x->internal_border_width,
616 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
617 FONT_HEIGHT (f->display.x->font), False);
618
619 #else /* ! defined (HAVE_X11) */
620 XPixSet (FRAME_X_WINDOW (f),
621 curs_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width,
622 curs_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width,
623 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x),
624 FONT_HEIGHT (f->display.x->font),
625 f->display.x->background_pixel);
626 #endif /* ! defined (HAVE_X11) */
627
628 UNBLOCK_INPUT;
629 }
630
631 static
632 XTclear_frame ()
633 {
634 int mask;
635 struct frame *f = updating_frame;
636
637 if (f == 0)
638 f = selected_frame;
639
640 f->phys_cursor_x = -1; /* Cursor not visible. */
641 curs_x = 0; /* Nominal cursor position is top left. */
642 curs_y = 0;
643
644 BLOCK_INPUT;
645 XClear (FRAME_X_WINDOW (f));
646 #ifndef HAVE_X11
647 dumpborder (f, 0);
648 #endif /* HAVE_X11 */
649 XFlushQueue ();
650 UNBLOCK_INPUT;
651 }
652 \f
653 /* Paint horzontal bars down the frame for a visible bell.
654 Note that this may be way too slow on some machines. */
655
656 XTflash (f)
657 struct frame *f;
658 {
659 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
660 register int i;
661 int x, y;
662
663 if (updating_frame != 0)
664 abort ();
665
666 BLOCK_INPUT;
667 #ifdef HAVE_X11
668 #if 0
669 for (i = f->height * FONT_HEIGHT (f->display.x->font) - 10;
670 i >= 0;
671 i -= 100) /* Should be NO LOWER than 75 for speed reasons. */
672 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
673 f->display.x->cursor_gc,
674 0, i, f->width * FONT_WIDTH (f->display.x->font)
675 + 2 * f->display.x->internal_border_width, 25);
676 #endif /* ! 0 */
677
678 x = (f->width * FONT_WIDTH (f->display.x->font)) / 4;
679 y = (f->height * FONT_HEIGHT (f->display.x->font)) / 4;
680 XFillRectangle (x_current_display, FRAME_X_WINDOW (f),
681 f->display.x->cursor_gc,
682 x, y, 2 * x, 2 * y);
683 dumpglyphs (f, (x + f->display.x->internal_border_width),
684 (y + f->display.x->internal_border_width),
685 &active_frame->glyphs[(f->height / 4) + 1][(f->width / 4)],
686 1, 0, f->display.x->font);
687
688 #else /* ! defined (HAVE_X11) */
689 for (i = f->height * FONT_HEIGHT (f->display.x->font) - 10;
690 i >= 0;
691 i -= 50)
692 XPixFill (FRAME_X_WINDOW (f), 0, i,
693 f->width * FONT_WIDTH (f->display.x->font)
694 + 2 * f->display.x->internal_border_width, 10,
695 WHITE_PIX_DEFAULT, ClipModeClipped, GXinvert, AllPlanes);
696 #endif /* ! defined (HAVE_X11) */
697
698 XFlushQueue ();
699 UNBLOCK_INPUT;
700 }
701
702 /* Flip background and forground colors of the frame. */
703
704 x_invert_frame (f)
705 struct frame *f;
706 {
707 #ifdef HAVE_X11
708 GC temp;
709 unsigned long pix_temp;
710
711 x_display_cursor (f, 0);
712 XClearWindow (x_current_display, FRAME_X_WINDOW (f));
713 temp = f->display.x->normal_gc;
714 f->display.x->normal_gc = f->display.x->reverse_gc;
715 f->display.x->reverse_gc = temp;
716 pix_temp = f->display.x->foreground_pixel;
717 f->display.x->foreground_pixel = f->display.x->background_pixel;
718 f->display.x->background_pixel = pix_temp;
719
720 XSetWindowBackground (x_current_display, FRAME_X_WINDOW (f),
721 f->display.x->background_pixel);
722 if (f->display.x->background_pixel == f->display.x->cursor_pixel)
723 {
724 f->display.x->cursor_pixel = f->display.x->foreground_pixel;
725 XSetBackground (x_current_display, f->display.x->cursor_gc,
726 f->display.x->cursor_pixel);
727 XSetForeground (x_current_display, f->display.x->cursor_gc,
728 f->display.x->background_pixel);
729 }
730 redraw_frame (f);
731 #endif /* ! defined (HAVE_X11) */
732 }
733
734 /* Make audible bell. */
735
736 #ifdef HAVE_X11
737 #define XRINGBELL XBell(x_current_display, 0)
738 #else /* ! defined (HAVE_X11) */
739 #define XRINGBELL XFeep(0);
740 #endif /* ! defined (HAVE_X11) */
741
742 XTring_bell ()
743 {
744 if (visible_bell)
745 #if 0
746 XTflash (selected_frame);
747 #endif /* ! 0 */
748 {
749 x_invert_frame (selected_frame);
750 x_invert_frame (selected_frame);
751 }
752 else
753 {
754 BLOCK_INPUT;
755 XRINGBELL;
756 XFlushQueue ();
757 UNBLOCK_INPUT;
758 }
759 }
760 \f
761 /* Insert and delete character are not supposed to be used
762 because we are supposed to turn off the feature of using them. */
763
764 static
765 XTinsert_glyphs (start, len)
766 register char *start;
767 register int len;
768 {
769 abort ();
770 }
771
772 static
773 XTdelete_glyphs (n)
774 register int n;
775 {
776 abort ();
777 }
778 \f
779 /* Specify how many text lines, from the top of the window,
780 should be affected by insert-lines and delete-lines operations.
781 This, and those operations, are used only within an update
782 that is bounded by calls to XTupdate_begin and XTupdate_end. */
783
784 static
785 XTset_terminal_window (n)
786 register int n;
787 {
788 if (updating_frame == 0)
789 abort ();
790
791 if ((n <= 0) || (n > updating_frame->height))
792 flexlines = updating_frame->height;
793 else
794 flexlines = n;
795 }
796 \f
797 /* Perform an insert-lines operation, inserting N lines
798 at a vertical position curs_y. */
799
800 static void
801 stufflines (n)
802 register int n;
803 {
804 register int topregion, bottomregion;
805 register int length, newtop, mask;
806 register struct frame *f = updating_frame;
807 int intborder = f->display.x->internal_border_width;
808
809 if (curs_y >= flexlines)
810 return;
811
812 topregion = curs_y;
813 bottomregion = flexlines - (n + 1);
814 newtop = topregion + n;
815 length = (bottomregion - topregion) + 1;
816
817 #ifndef HAVE_X11
818 dumpqueue ();
819 #endif /* HAVE_X11 */
820
821 if ((length > 0) && (newtop <= flexlines))
822 {
823 #ifdef HAVE_X11
824 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
825 FRAME_X_WINDOW (f), f->display.x->normal_gc,
826 intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder,
827 f->width * FONT_WIDTH (f->display.x->font),
828 length * FONT_HEIGHT (f->display.x->font), intborder,
829 newtop * FONT_HEIGHT (f->display.x->font) + intborder);
830 #else /* ! defined (HAVE_X11) */
831 XMoveArea (FRAME_X_WINDOW (f),
832 intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder,
833 intborder, newtop * FONT_HEIGHT (f->display.x->font) + intborder,
834 f->width * FONT_WIDTH (f->display.x->font),
835 length * FONT_HEIGHT (f->display.x->font));
836 /* Now we must process any ExposeRegion events that occur
837 if the area being copied from is obscured.
838 We can't let it wait because further i/d operations
839 may want to copy this area to another area. */
840 x_read_exposes ();
841 #endif /* ! defined (HAVE_X11) */
842 }
843
844 newtop = min (newtop, (flexlines - 1));
845 length = newtop - topregion;
846 if (length > 0)
847 {
848 #ifdef HAVE_X11
849 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
850 topregion * FONT_HEIGHT (f->display.x->font) + intborder,
851 f->width * FONT_WIDTH (f->display.x->font),
852 n * FONT_HEIGHT (f->display.x->font), False);
853 #else /* ! defined (HAVE_X11) */
854 XPixSet (FRAME_X_WINDOW (f),
855 intborder,
856 topregion * FONT_HEIGHT (f->display.x->font) + intborder,
857 f->width * FONT_WIDTH (f->display.x->font),
858 n * FONT_HEIGHT (f->display.x->font),
859 f->display.x->background_pixel);
860 #endif /* ! defined (HAVE_X11) */
861 }
862 }
863
864 /* Perform a delete-lines operation, deleting N lines
865 at a vertical position curs_y. */
866
867 static void
868 scraplines (n)
869 register int n;
870 {
871 int mask;
872 register struct frame *f = updating_frame;
873 int intborder = f->display.x->internal_border_width;
874
875 if (curs_y >= flexlines)
876 return;
877
878 #ifndef HAVE_X11
879 dumpqueue ();
880 #endif /* HAVE_X11 */
881
882 if ((curs_y + n) >= flexlines)
883 {
884 if (flexlines >= (curs_y + 1))
885 {
886 #ifdef HAVE_X11
887 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder,
888 curs_y * FONT_HEIGHT (f->display.x->font) + intborder,
889 f->width * FONT_WIDTH (f->display.x->font),
890 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False);
891 #else /* ! defined (HAVE_X11) */
892 XPixSet (FRAME_X_WINDOW (f),
893 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder,
894 f->width * FONT_WIDTH (f->display.x->font),
895 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font),
896 f->display.x->background_pixel);
897 #endif /* ! defined (HAVE_X11) */
898 }
899 }
900 else
901 {
902 #ifdef HAVE_X11
903 XCopyArea (x_current_display, FRAME_X_WINDOW (f),
904 FRAME_X_WINDOW (f), f->display.x->normal_gc,
905 intborder,
906 (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder,
907 f->width * FONT_WIDTH (f->display.x->font),
908 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font),
909 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder);
910 XClearArea (x_current_display, FRAME_X_WINDOW (f),
911 intborder,
912 (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder,
913 f->width * FONT_WIDTH (f->display.x->font),
914 n * FONT_HEIGHT (f->display.x->font), False);
915 #else /* ! defined (HAVE_X11) */
916 XMoveArea (FRAME_X_WINDOW (f),
917 intborder,
918 (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder,
919 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder,
920 f->width * FONT_WIDTH (f->display.x->font),
921 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font));
922 /* Now we must process any ExposeRegion events that occur
923 if the area being copied from is obscured.
924 We can't let it wait because further i/d operations
925 may want to copy this area to another area. */
926 x_read_exposes ();
927 XPixSet (FRAME_X_WINDOW (f), intborder,
928 (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder,
929 f->width * FONT_WIDTH (f->display.x->font),
930 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel);
931 #endif /* ! defined (HAVE_X11) */
932 }
933 }
934
935 /* Perform an insert-lines or delete-lines operation,
936 inserting N lines or deleting -N lines at vertical position VPOS. */
937
938 XTins_del_lines (vpos, n)
939 int vpos, n;
940 {
941 if (updating_frame == 0)
942 abort ();
943
944 /* Hide the cursor. */
945 x_display_cursor (updating_frame, 0);
946
947 XTcursor_to (vpos, 0);
948
949 BLOCK_INPUT;
950 if (n >= 0)
951 stufflines (n);
952 else
953 scraplines (-n);
954 XFlushQueue ();
955 UNBLOCK_INPUT;
956 }
957 \f
958 static void clear_cursor ();
959
960 /* Output into a rectangle of an X-window (for frame F)
961 the characters in f->phys_lines that overlap that rectangle.
962 TOP and LEFT are the position of the upper left corner of the rectangle.
963 ROWS and COLS are the size of the rectangle. */
964
965 static void
966 dumprectangle (f, left, top, cols, rows)
967 struct frame *f;
968 register int left, top, cols, rows;
969 {
970 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
971 int cursor_cleared = 0;
972 int bottom, right;
973 register int y;
974
975 if (FRAME_GARBAGED_P (f))
976 return;
977
978 top -= f->display.x->internal_border_width;
979 left -= f->display.x->internal_border_width;
980
981 /* Express rectangle as four edges, instead of position-and-size. */
982 bottom = top + rows;
983 right = left + cols;
984
985 #ifndef HAVE_X11 /* Window manger does this for X11. */
986 /* If the rectangle includes any of the internal border area,
987 redisplay the border emphasis. */
988 if (top < 0 || left < 0
989 || bottom > f->height * FONT_HEIGHT (f->display.x->font)
990 || right > f->width * FONT_WIDTH (f->display.x->font))
991 dumpborder (f, 0);
992 #endif /* HAVE_X11 /* Window manger does this for X11. */ */
993
994 /* Convert rectangle edges in pixels to edges in chars.
995 Round down for left and top, up for right and bottom. */
996 top /= FONT_HEIGHT (f->display.x->font);
997 left /= FONT_WIDTH (f->display.x->font);
998 bottom += (FONT_HEIGHT (f->display.x->font) - 1);
999 right += (FONT_WIDTH (f->display.x->font) - 1);
1000 bottom /= FONT_HEIGHT (f->display.x->font);
1001 right /= FONT_WIDTH (f->display.x->font);
1002
1003 /* Clip the rectangle to what can be visible. */
1004 if (left < 0)
1005 left = 0;
1006 if (top < 0)
1007 top = 0;
1008 if (right > f->width)
1009 right = f->width;
1010 if (bottom > f->height)
1011 bottom = f->height;
1012
1013 /* Get size in chars of the rectangle. */
1014 cols = right - left;
1015 rows = bottom - top;
1016
1017 /* If rectangle has zero area, return. */
1018 if (rows <= 0) return;
1019 if (cols <= 0) return;
1020
1021 /* Turn off the cursor if it is in the rectangle.
1022 We will turn it back on afterward. */
1023 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1024 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1025 {
1026 clear_cursor (f);
1027 cursor_cleared = 1;
1028 }
1029
1030 /* Display the text in the rectangle, one text line at a time. */
1031
1032 for (y = top; y < bottom; y++)
1033 {
1034 GLYPH *line = &active_frame->glyphs[y][left];
1035
1036 if (! active_frame->enable[y] || left > active_frame->used[y])
1037 continue;
1038
1039 dumpglyphs (f,
1040 (left * FONT_WIDTH (f->display.x->font)
1041 + f->display.x->internal_border_width),
1042 (y * FONT_HEIGHT (f->display.x->font)
1043 + f->display.x->internal_border_width),
1044 line, min (cols, active_frame->used[y] - left),
1045 active_frame->highlight[y], f->display.x->font);
1046 }
1047
1048 /* Turn the cursor on if we turned it off. */
1049
1050 if (cursor_cleared)
1051 x_display_cursor (f, 1);
1052 }
1053
1054 #ifndef HAVE_X11
1055 /* Process all queued ExposeRegion events. */
1056
1057 static void
1058 dumpqueue ()
1059 {
1060 register int i;
1061 XExposeRegionEvent r;
1062
1063 while (dequeue_event (&r, &x_expose_queue))
1064 {
1065 struct frame *f = x_window_to_frame (r.window);
1066 if (f->display.x->icon_desc == r.window)
1067 refreshicon (f);
1068 else
1069 dumprectangle (f, r.x, r.y, r.width, r.height);
1070 }
1071 XFlushQueue ();
1072 }
1073 #endif /* HAVE_X11 */
1074 \f
1075 /* Process all expose events that are pending.
1076 Redraws the cursor if necessary on any frame that
1077 is not in the process of being updated with update_frame. */
1078
1079 static void
1080 x_do_pending_expose ()
1081 {
1082 int mask;
1083 struct frame *f;
1084 Lisp_Object tail, frame;
1085
1086 if (expose_all_windows)
1087 {
1088 expose_all_windows = 0;
1089 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
1090 {
1091 register int temp_width, temp_height;
1092 int intborder;
1093
1094 frame = XCONS (tail)->car;
1095 if (XTYPE (frame) != Lisp_Frame)
1096 continue;
1097 f = XFRAME (frame);
1098 if (! FRAME_X_P (f))
1099 continue;
1100 if (!f->async_visible)
1101 continue;
1102 if (!f->display.x->needs_exposure)
1103 continue;
1104
1105 intborder = f->display.x->internal_border_width;
1106
1107 clear_cursor (f);
1108 XGetWindowInfo (FRAME_X_WINDOW (f), &windowinfo);
1109 temp_width = ((windowinfo.width - 2 * intborder
1110 - f->display.x->v_scrollbar_width)
1111 / FONT_WIDTH (f->display.x->font));
1112 temp_height = ((windowinfo.height- 2 * intborder
1113 - f->display.x->h_scrollbar_height)
1114 / FONT_HEIGHT (f->display.x->font));
1115 if (temp_width != f->width || temp_height != f->height)
1116 {
1117 change_frame_size (f, max (1, temp_height),
1118 max (1, temp_width), 0, 1);
1119 x_resize_scrollbars (f);
1120 }
1121 f->display.x->left_pos = windowinfo.x;
1122 f->display.x->top_pos = windowinfo.y;
1123 dumprectangle (f, 0, 0, PIXEL_WIDTH (f), PIXEL_HEIGHT (f));
1124 #if 0
1125 dumpborder (f, 0);
1126 #endif /* ! 0 */
1127 f->display.x->needs_exposure = 0;
1128 if (updating_frame != f)
1129 x_display_cursor (f, 1);
1130 XFlushQueue ();
1131 }
1132 }
1133 else
1134 /* Handle any individual-rectangle expose events queued
1135 for various windows. */
1136 #ifdef HAVE_X11
1137 ;
1138 #else /* ! defined (HAVE_X11) */
1139 dumpqueue ();
1140 #endif /* ! defined (HAVE_X11) */
1141 }
1142
1143 #ifdef HAVE_X11
1144 static void
1145 frame_highlight (frame)
1146 struct frame *frame;
1147 {
1148 if (! EQ (Vx_no_window_manager, Qnil))
1149 XSetWindowBorder (x_current_display, FRAME_X_WINDOW (frame),
1150 frame->display.x->border_pixel);
1151 x_display_cursor (frame, 1);
1152 }
1153
1154 static void
1155 frame_unhighlight (frame)
1156 struct frame *frame;
1157 {
1158 if (! EQ (Vx_no_window_manager, Qnil))
1159 XSetWindowBorderPixmap (x_current_display, FRAME_X_WINDOW (frame),
1160 frame->display.x->border_tile);
1161 x_display_cursor (frame, 1);
1162 }
1163 #else /* ! defined (HAVE_X11) */
1164 /* Dump the border-emphasis of frame F.
1165 If F is selected, this is a lining of the same color as the border,
1166 just within the border, occupying a portion of the internal border.
1167 If F is not selected, it is background in the same place.
1168 If ALWAYS is 0, don't bother explicitly drawing if it's background.
1169
1170 ALWAYS = 1 is used when a frame becomes selected or deselected.
1171 In that case, we also turn the cursor off and on again
1172 so it will appear in the proper shape (solid if selected; else hollow.) */
1173
1174 static void
1175 dumpborder (f, always)
1176 struct frame *f;
1177 int always;
1178 {
1179 int thickness = f->display.x->internal_border_width / 2;
1180 int width = PIXEL_WIDTH (f);
1181 int height = PIXEL_HEIGHT (f);
1182 int pixel;
1183
1184 if (f != selected_frame)
1185 {
1186 if (!always)
1187 return;
1188
1189 pixel = f->display.x->background_pixel;
1190 }
1191 else
1192 {
1193 pixel = f->display.x->border_pixel;
1194 }
1195
1196 XPixSet (FRAME_X_WINDOW (f), 0, 0, width, thickness, pixel);
1197 XPixSet (FRAME_X_WINDOW (f), 0, 0, thickness, height, pixel);
1198 XPixSet (FRAME_X_WINDOW (f), 0, height - thickness, width,
1199 thickness, pixel);
1200 XPixSet (FRAME_X_WINDOW (f), width - thickness, 0, thickness,
1201 height, pixel);
1202
1203 if (always)
1204 x_display_cursor (f, 1);
1205 }
1206 #endif /* ! defined (HAVE_X11) */
1207
1208 static void XTframe_rehighlight ();
1209
1210 /* The focus has changed. Update the frames as necessary to reflect
1211 the new situation. Note that we can't change the selected frame
1212 here, because the lisp code we are interrupting might become confused.
1213 Each event gets marked with the frame in which it occured, so the
1214 lisp code can tell when the switch took place by examining the events. */
1215
1216 static void
1217 x_new_focus_frame (frame)
1218 struct frame *frame;
1219 {
1220 struct frame *old_focus = x_focus_frame;
1221 int events_enqueued = 0;
1222
1223 if (frame != x_focus_frame)
1224 {
1225 /* Set this before calling other routines, so that they see
1226 the correct value of x_focus_frame. */
1227 x_focus_frame = frame;
1228
1229 if (old_focus && old_focus->auto_lower)
1230 x_lower_frame (old_focus);
1231
1232 #if 0
1233 selected_frame = frame;
1234 XSET (XWINDOW (selected_frame->selected_window)->frame,
1235 Lisp_Frame, selected_frame);
1236 Fselect_window (selected_frame->selected_window);
1237 choose_minibuf_frame ();
1238 #endif /* ! 0 */
1239
1240 if (x_focus_frame && x_focus_frame->auto_raise)
1241 x_raise_frame (x_focus_frame);
1242 }
1243
1244 XTframe_rehighlight ();
1245 }
1246
1247
1248 /* The focus has changed, or we have make a frame's selected window
1249 point to a window on a different frame (this happens with global
1250 minibuffer frames). Shift the highlight as appropriate. */
1251 static void
1252 XTframe_rehighlight ()
1253 {
1254 struct frame *old_highlight = x_highlight_frame;
1255
1256 if (x_focus_frame)
1257 {
1258 x_highlight_frame = XFRAME (FRAME_FOCUS_FRAME (x_focus_frame));
1259 if (x_highlight_frame->display.nothing == 0)
1260 XSET (FRAME_FOCUS_FRAME (x_focus_frame), Lisp_Frame,
1261 (x_highlight_frame = x_focus_frame));
1262 }
1263 else
1264 x_highlight_frame = 0;
1265
1266 if (x_highlight_frame != old_highlight)
1267 {
1268 if (old_highlight)
1269 frame_unhighlight (old_highlight);
1270 if (x_highlight_frame)
1271 frame_highlight (x_highlight_frame);
1272 }
1273 }
1274 \f
1275 enum window_type
1276 {
1277 no_window,
1278 scrollbar_window,
1279 text_window,
1280 };
1281
1282 /* Position of the mouse in characters */
1283 unsigned int x_mouse_x, x_mouse_y;
1284
1285 /* Offset in buffer of character under the pointer, or 0. */
1286 extern int mouse_buffer_offset;
1287
1288 extern int buffer_posn_from_coords ();
1289
1290 /* Symbols from xfns.c to denote the different parts of a window. */
1291 extern Lisp_Object Qmodeline_part, Qtext_part;
1292
1293 #if 0
1294 /* Set *RESULT to an emacs input_event corresponding to MOTION_EVENT.
1295 F is the frame in which the event occurred.
1296
1297 WINDOW_TYPE says whether the event happened in a scrollbar window
1298 or a text window, affecting the format of the event created.
1299
1300 PART specifies which part of the scrollbar the event happened in,
1301 if WINDOW_TYPE == scrollbar_window.
1302
1303 If the mouse is over the same character as the last time we checked,
1304 don't return an event; set result->kind to no_event. */
1305
1306 static void
1307 notice_mouse_movement (result, motion_event, f, window_type, part)
1308 struct input_event *result;
1309 XMotionEvent motion_event;
1310 struct frame *f;
1311 int window_type;
1312 Lisp_Object part;
1313 {
1314 int x, y, root_x, root_y, pix_x, pix_y;
1315 unsigned int keys_and_buttons;
1316 Window w, root_window;
1317
1318 /* Unless we decide otherwise below, return a non-event. */
1319 result->kind = no_event;
1320
1321 if (XQueryPointer (x_current_display,
1322 FRAME_X_WINDOW (f),
1323 &root_window, &w,
1324 &root_x, &root_y, &pix_x, &pix_y,
1325 &keys_and_buttons)
1326 == False)
1327 return;
1328
1329 #if 0
1330 if (w == None) /* Mouse no longer in window. */
1331 return Qnil;
1332 #endif /* ! 0 */
1333
1334 pixel_to_glyph_translation (f, pix_x, pix_y, &x, &y);
1335 if (x == x_mouse_x && y == x_mouse_y)
1336 return;
1337
1338 x_mouse_x = x;
1339 x_mouse_y = y;
1340
1341 /* What sort of window are we in now? */
1342 if (window_type == text_window) /* Text part */
1343 {
1344 int modeline_p;
1345
1346 Vmouse_window = window_from_coordinates (f, x, y, &modeline_p);
1347
1348 if (XTYPE (Vmouse_window) == Lisp_Window)
1349 mouse_buffer_offset
1350 = buffer_posn_from_coords (XWINDOW (Vmouse_window), x, y);
1351 else
1352 mouse_buffer_offset = 0;
1353
1354 if (EQ (Vmouse_window, Qnil))
1355 Vmouse_frame_part = Qnil;
1356 else if (modeline_p)
1357 Vmouse_frame_part = Qmodeline_part;
1358 else
1359 Vmouse_frame_part = Qtext_part;
1360
1361 result->kind = window_sys_event;
1362 result->code = Qmouse_moved;
1363
1364 return;
1365 }
1366 else if (window_type == scrollbar_window) /* Scrollbar */
1367 {
1368 Vmouse_window = f->selected_window;
1369 mouse_buffer_offset = 0;
1370 Vmouse_frame_part = part;
1371
1372 result->kind = window_sys_event;
1373 result->code = Qmouse_moved;
1374
1375 return;
1376 }
1377
1378 return;
1379 }
1380 #endif /* ! 0 */
1381
1382 \f
1383 /* Mouse clicks and mouse movement. Rah. */
1384 #ifdef HAVE_X11
1385
1386 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1387 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1388 that the glyph at X, Y occupies, if BOUNDS != 0. */
1389 static void
1390 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds)
1391 FRAME_PTR f;
1392 register unsigned int pix_x, pix_y;
1393 register int *x, *y;
1394 XRectangle *bounds;
1395 {
1396 int ibw = f->display.x->internal_border_width;
1397 int width, height;
1398 FONT_TYPE *font = f->display.x->font;
1399
1400 width = FONT_WIDTH (font);
1401 height = FONT_HEIGHT (font);
1402
1403 /* What line is it on? */
1404 if (pix_y < ibw)
1405 *y = 0;
1406 else if (pix_y > f->display.x->pixel_height - ibw)
1407 *y = FRAME_HEIGHT (f) - 1;
1408 else
1409 *y = (pix_y - ibw) / height;
1410
1411 /* And what column? */
1412 if (pix_x < ibw)
1413 *x = 0;
1414 else if (pix_x > f->display.x->pixel_width - ibw)
1415 *x = FRAME_WIDTH (f) - 1;
1416 else
1417 *x = (pix_x - ibw) / width;
1418
1419 if (bounds)
1420 {
1421 bounds->width = width;
1422 bounds->height = height;
1423 bounds->x = ibw + (*x * width);
1424 bounds->y = ibw + (*y * height);
1425 }
1426 }
1427
1428 /* Any buttons grabbed. */
1429 unsigned int x_mouse_grabbed;
1430
1431 /* Which modifier keys are on which modifier bits?
1432
1433 With each keystroke, X returns eight bits indicating which modifier
1434 keys were held down when the key was pressed. The interpretation
1435 of the top five modifier bits depends on what keys are attached
1436 to them. If the Meta_L and Meta_R keysyms are on mod5, then mod5
1437 is the meta bit.
1438
1439 x_meta_mod_mask is a mask containing the bits used for the meta key.
1440 It may have more than one bit set, if more than one modifier bit
1441 has meta keys on it. Basically, if EVENT is a KeyPress event,
1442 the meta key is pressed if (EVENT.state & x_meta_mod_mask) != 0.
1443
1444 x_shift_lock_mask is LockMask if the XK_Shift_Lock keysym is on the
1445 lock modifier bit, or zero otherwise. Non-alphabetic keys should
1446 only be affected by the lock modifier bit if XK_Shift_Lock is in
1447 use; XK_Caps_Lock should only affect alphabetic keys. With this
1448 arrangement, the lock modifier should shift the character if
1449 (EVENT.state & x_shift_lock_mask) != 0. */
1450 static int x_meta_mod_mask, x_shift_lock_mask;
1451
1452 /* Initialize mode_switch_bit and modifier_meaning. */
1453 static void
1454 x_find_modifier_meanings ()
1455 {
1456 int min_code, max_code;
1457 KeySym *syms;
1458 int syms_per_code;
1459 XModifierKeymap *mods;
1460 int alt_mod_mask = 0;
1461
1462 x_meta_mod_mask = 0;
1463 x_shift_lock_mask = 0;
1464
1465 XDisplayKeycodes (x_current_display, &min_code, &max_code);
1466 syms = XGetKeyboardMapping (x_current_display,
1467 min_code, max_code - min_code + 1,
1468 &syms_per_code);
1469 mods = XGetModifierMapping (x_current_display);
1470
1471 /* Scan the modifier table to see which modifier bits the Meta and
1472 Alt keysyms are on. */
1473 {
1474 int row, col; /* The row and column in the modifier table. */
1475
1476 for (row = 3; row < 8; row++)
1477 for (col = 0; col < mods->max_keypermod; col++)
1478 {
1479 KeyCode code =
1480 mods->modifiermap[(row * mods->max_keypermod) + col];
1481
1482 /* Are any of this keycode's keysyms a meta key? */
1483 {
1484 int code_col;
1485
1486 for (code_col = 0; code_col < syms_per_code; code_col++)
1487 {
1488 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1489
1490 switch (sym)
1491 {
1492 case XK_Meta_L:
1493 case XK_Meta_R:
1494 x_meta_mod_mask |= (1 << row);
1495 break;
1496
1497 case XK_Alt_L:
1498 case XK_Alt_R:
1499 alt_mod_mask |= (1 << row);
1500 break;
1501
1502 case XK_Shift_Lock:
1503 /* Ignore this if it's not on the lock modifier. */
1504 if ((1 << row) == LockMask)
1505 x_shift_lock_mask = LockMask;
1506 break;
1507 }
1508 }
1509 }
1510 }
1511 }
1512
1513 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1514 if (! x_meta_mod_mask)
1515 x_meta_mod_mask = alt_mod_mask;
1516
1517 XFree ((char *) syms);
1518 XFreeModifiermap (mods);
1519 }
1520
1521
1522 /* Convert a set of X modifier bits to the proper form for a
1523 struct input_event modifiers value. */
1524
1525 static unsigned int
1526 x_convert_modifiers (state)
1527 unsigned int state;
1528 {
1529 return ( ((state & (ShiftMask | x_shift_lock_mask)) ? shift_modifier : 0)
1530 | ((state & ControlMask) ? ctrl_modifier : 0)
1531 | ((state & x_meta_mod_mask) ? meta_modifier : 0));
1532 }
1533
1534 extern struct frame *x_window_to_scrollbar ();
1535 extern Lisp_Object Vmouse_event;
1536
1537 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1538
1539 If the event is a button press, then note that we have grabbed
1540 the mouse.
1541
1542 If PART and PREFIX are 0, then the event occurred in the text part;
1543 otherwise it happened in a scrollbar. */
1544
1545 static Lisp_Object
1546 construct_mouse_click (result, event, f, part, prefix)
1547 struct input_event *result;
1548 XButtonEvent *event;
1549 struct frame *f;
1550 int prefix;
1551 Lisp_Object part;
1552 {
1553 /* Initialize those fields text and scrollbar clicks hold in common.
1554 Make the event type no_event; we'll change that when we decide
1555 otherwise. */
1556 result->kind = no_event;
1557 XSET (result->code, Lisp_Int, event->button);
1558 result->timestamp = event->time;
1559 result->modifiers = (x_convert_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 if (! NILP (part)) /* Scrollbar event */
1579 {
1580 int pos, len;
1581
1582 pos = event->y - (f->display.x->v_scrollbar_width - 2);
1583 x_mouse_x = pos;
1584 len = ((FONT_HEIGHT (f->display.x->font) * f->height)
1585 + f->display.x->internal_border_width
1586 - (2 * (f->display.x->v_scrollbar_width - 2)));
1587 x_mouse_y = len;
1588
1589 result->kind = scrollbar_click;
1590 result->part = part;
1591 XSET (result->x, Lisp_Int, (f->display.x->top_pos - event->y));
1592 XSET (result->y, Lisp_Int, f->display.x->pixel_height);
1593 result->frame = f;
1594 }
1595 else /* Text Window Event */
1596 {
1597 int row, column;
1598
1599 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1600 result->kind = mouse_click;
1601 XFASTINT (result->x) = column;
1602 XFASTINT (result->y) = row;
1603 result->frame = f;
1604 }
1605 }
1606
1607
1608 /* Mouse movement. Rah.
1609
1610 In order to avoid asking for motion events and then throwing most
1611 of them away or busy-polling the server for mouse positions, we ask
1612 the server for pointer motion hints. This means that we get only
1613 one event per group of mouse movements. "Groups" are delimited by
1614 other kinds of events (focus changes and button clicks, for
1615 example), or by XQueryPointer calls; when one of these happens, we
1616 get another MotionNotify event the next time the mouse moves. This
1617 is at least as efficient as getting motion events when mouse
1618 tracking is on, and I suspect only negligibly worse when tracking
1619 is off.
1620
1621 The silly O'Reilly & Associates Nutshell guides barely document
1622 pointer motion hints at all (I think you have to infer how they
1623 work from an example), and the description of XQueryPointer doesn't
1624 mention that calling it causes you to get another motion hint from
1625 the server, which is very important. */
1626
1627 /* Where the mouse was last time we reported a mouse event. */
1628 static FRAME_PTR last_mouse_frame;
1629 static XRectangle last_mouse_glyph;
1630
1631 /* This is a hack. We would really prefer that XTmouse_position would
1632 return the time associated with the position it returns, but there
1633 doesn't seem to be any way to wrest the timestamp from the server
1634 along with the position query. So, we just keep track of the time
1635 of the last movement we received, and return that in hopes that
1636 it's somewhat accurate. */
1637 static Time last_mouse_movement_time;
1638
1639 /* Function to report a mouse movement to the mainstream Emacs code.
1640 The input handler calls this.
1641
1642 We have received a mouse movement event, which is given in *event.
1643 If the mouse is over a different glyph than it was last time, tell
1644 the mainstream emacs code by setting mouse_moved. If not, ask for
1645 another motion event, so we can check again the next time it moves. */
1646 static void
1647 note_mouse_position (frame, event)
1648 FRAME_PTR frame;
1649 XMotionEvent *event;
1650
1651 {
1652 last_mouse_movement_time = event->time;
1653
1654 /* Has the mouse moved off the glyph it was on at the last sighting? */
1655 if (event->x < last_mouse_glyph.x
1656 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1657 || event->y < last_mouse_glyph.y
1658 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1659 mouse_moved = 1;
1660 else
1661 {
1662 /* It's on the same glyph. Call XQueryPointer so we'll get an
1663 event the next time the mouse moves and we can see if it's
1664 *still* on the same glyph. */
1665 int dummy;
1666
1667 XQueryPointer (event->display, event->window,
1668 (Window *) &dummy, (Window *) &dummy,
1669 &dummy, &dummy, &dummy, &dummy,
1670 (unsigned int *) &dummy);
1671 }
1672 }
1673
1674 /* Return the current position of the mouse.
1675
1676 This clears the mouse_moved flag, so we can wait for the next mouse
1677 position. This also calls XQueryPointer, which will cause the
1678 server to give us another MotionNotify when the mouse moves again.
1679 */
1680
1681 static void
1682 XTmouse_position (f, x, y, time)
1683 FRAME_PTR *f;
1684 Lisp_Object *x, *y;
1685 unsigned long *time;
1686 {
1687 int ix, iy, dummy;
1688 Display *d = x_current_display;
1689 Window guess, root, child;
1690
1691 BLOCK_INPUT;
1692
1693 /* I would like to have an X function that just told me the
1694 innermost window containing the mouse.
1695
1696 /* There doesn't seem to be any way to just get the innermost window
1697 containing the pointer, no matter what X frame it's on; you have
1698 to guess a window, and then X will tell you which one of that
1699 window's children it's in. If the pointer isn't in any of that
1700 window's children, it gives you a root window that contains it.
1701
1702 So we start with the selected frame's window and chase down
1703 branches under the guidance of XQueryPointer until we hit a leaf
1704 (all of the Emacs windows we care about are leaf windows). If at
1705 any time XQueryPointer returns false, that means that the current
1706 window does not contain the pointer any more (perhaps it moved),
1707 so we start with the root window XQueryPointer has given us and
1708 start again. */
1709
1710 guess = FRAME_X_WINDOW (selected_frame);
1711 for (;;)
1712 if (XQueryPointer (d, guess, &root, &child,
1713 &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
1714 {
1715 if (child == None)
1716 /* Guess is a leaf window, and it contains the pointer. */
1717 break;
1718 else
1719 guess = child;
1720 }
1721 else
1722 /* When XQueryPointer returns False, the pointer isn't in guess
1723 anymore, but root is the root window of the frame we should
1724 try instead. */
1725 guess = root;
1726
1727 *f = last_mouse_frame = x_window_to_frame (guess);
1728 if (! *f)
1729 *x = *y = Qnil;
1730 else
1731 {
1732 pixel_to_glyph_coords (*f, ix, iy, &ix, &iy, &last_mouse_glyph);
1733 XSET (*x, Lisp_Int, ix);
1734 XSET (*y, Lisp_Int, iy);
1735 }
1736
1737 mouse_moved = 0;
1738
1739 /* I don't know how to find the time for the last movement; it seems
1740 like XQueryPointer ought to return it, but it doesn't. So, we'll
1741 return the time of the last MotionNotify event we received. Note
1742 that the use of motion hints means that this isn't guaranteed to
1743 be accurate at all. */
1744 *time = last_mouse_movement_time;
1745
1746 UNBLOCK_INPUT;
1747 }
1748
1749 #else /* ! defined (HAVE_X11) */
1750 #define XEvent XKeyPressedEvent
1751 #endif /* ! defined (HAVE_X11) */
1752 \f
1753
1754 /* Timestamp of enter window event. This is only used by XTread_socket,
1755 but we have to put it out here, since static variables within functions
1756 sometimes don't work. */
1757 static Time enter_timestamp;
1758
1759 /* This holds the state XLookupString needs to implement dead keys
1760 and other tricks known as "compose processing". _X Window System_
1761 says that a portable program can't use this, but Stephen Gildea assures
1762 me that letting the compiler initialize it to zeros will work okay.
1763
1764 This must be defined outside of XTread_socket, for the same reasons
1765 given for enter_timestamp, above. */
1766 static XComposeStatus compose_status;
1767
1768 /* Communication with window managers. */
1769 Atom Xatom_wm_protocols;
1770
1771 /* Kinds of protocol things we may receive. */
1772 Atom Xatom_wm_take_focus;
1773 Atom Xatom_wm_save_yourself;
1774 Atom Xatom_wm_delete_window;
1775
1776 /* Other WM communication */
1777 Atom Xatom_wm_configure_denied; /* When our config request is denied */
1778 Atom Xatom_wm_window_moved; /* When the WM moves us. */
1779
1780 /* Read events coming from the X server.
1781 This routine is called by the SIGIO handler.
1782 We return as soon as there are no more events to be read.
1783
1784 Events representing keys are stored in buffer BUFP,
1785 which can hold up to NUMCHARS characters.
1786 We return the number of characters stored into the buffer,
1787 thus pretending to be `read'.
1788
1789 WAITP is nonzero if we should block until input arrives.
1790 EXPECTED is nonzero if the caller knows input is available. */
1791
1792 int
1793 XTread_socket (sd, bufp, numchars, waitp, expected)
1794 register int sd;
1795 register struct input_event *bufp;
1796 register int numchars;
1797 int waitp;
1798 int expected;
1799 {
1800 int count = 0;
1801 int nbytes = 0;
1802 int mask;
1803 int items_pending; /* How many items are in the X queue. */
1804 XEvent event;
1805 struct frame *f;
1806 int event_found;
1807 int prefix;
1808 Lisp_Object part;
1809
1810 if (x_input_blocked)
1811 {
1812 x_pending_input = 1;
1813 return -1;
1814 }
1815
1816 x_pending_input = 0;
1817 BLOCK_INPUT;
1818
1819 if (numchars <= 0)
1820 abort (); /* Don't think this happens. */
1821
1822 #ifdef FIOSNBIO
1823 /* If available, Xlib uses FIOSNBIO to make the socket
1824 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
1825 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
1826 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
1827 fcntl (fileno (stdin), F_SETFL, 0);
1828 #endif /* ! defined (FIOSNBIO) */
1829
1830 #ifndef SIGIO
1831 #ifndef HAVE_SELECT
1832 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
1833 {
1834 extern int read_alarm_should_throw;
1835 read_alarm_should_throw = 1;
1836 XPeekEvent (XDISPLAY &event);
1837 read_alarm_should_throw = 0;
1838 }
1839 #endif /* HAVE_SELECT */
1840 #endif /* SIGIO */
1841
1842 while (XStuffPending () != 0)
1843 {
1844 XNextEvent (XDISPLAY &event);
1845 event_found = 1;
1846
1847 switch (event.type)
1848 {
1849 #ifdef HAVE_X11
1850 case ClientMessage:
1851 {
1852 if (event.xclient.message_type == Xatom_wm_protocols
1853 && event.xclient.format == 32)
1854 {
1855 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
1856 {
1857 f = x_window_to_frame (event.xclient.window);
1858 if (f)
1859 x_focus_on_frame (f);
1860 /* Not certain about handling scrollbars here */
1861 }
1862 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
1863 {
1864 /* Save state modify the WM_COMMAND property to
1865 something which can reinstate us. This notifies
1866 the session manager, who's looking for such a
1867 PropertyNotify. Can restart processing when
1868 a keyboard or mouse event arrives. */
1869 if (numchars > 0)
1870 {
1871 }
1872 }
1873 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
1874 {
1875 struct frame *f = x_window_to_frame (event.xclient.window);
1876
1877 if (f)
1878 if (numchars > 0)
1879 {
1880 }
1881 }
1882 }
1883 else if (event.xclient.message_type == Xatom_wm_configure_denied)
1884 {
1885 }
1886 else if (event.xclient.message_type == Xatom_wm_window_moved)
1887 {
1888 int new_x, new_y;
1889
1890 new_x = event.xclient.data.s[0];
1891 new_y = event.xclient.data.s[1];
1892 }
1893 }
1894 break;
1895
1896 case SelectionClear: /* Someone has grabbed ownership. */
1897 x_disown_selection (event.xselectionclear.window,
1898 event.xselectionclear.selection,
1899 event.xselectionclear.time);
1900 break;
1901
1902 case SelectionRequest: /* Someone wants our selection. */
1903 x_answer_selection_request (event);
1904 break;
1905
1906 case PropertyNotify:
1907
1908 /* If we're being told about a root window property, then it's
1909 a cut buffer change. */
1910 if (event.xproperty.window == ROOT_WINDOW)
1911 x_invalidate_cut_buffer_cache (&event.xproperty);
1912
1913 /* Otherwise, we're probably handling an incremental
1914 selection transmission. */
1915 else
1916 {
1917 /* If we were to do this synchronously, there'd be no worry
1918 about re-selecting. */
1919 x_send_incremental (event);
1920 }
1921 break;
1922
1923 case Expose:
1924 f = x_window_to_frame (event.xexpose.window);
1925 if (f)
1926 {
1927 if (f->async_visible == 0)
1928 {
1929 f->async_visible = 1;
1930 f->async_iconified = 0;
1931 SET_FRAME_GARBAGED (f);
1932 }
1933 else
1934 dumprectangle (x_window_to_frame (event.xexpose.window),
1935 event.xexpose.x, event.xexpose.y,
1936 event.xexpose.width, event.xexpose.height);
1937 }
1938 break;
1939
1940 case GraphicsExpose: /* This occurs when an XCopyArea's
1941 source area was obscured or not
1942 available.*/
1943 dumprectangle (x_window_to_frame (event.xgraphicsexpose.drawable),
1944 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
1945 event.xgraphicsexpose.width,
1946 event.xgraphicsexpose.height);
1947 break;
1948
1949 case NoExpose: /* This occurs when an XCopyArea's
1950 source area was completely
1951 available */
1952 break;
1953 #else /* ! defined (HAVE_X11) */
1954 case ExposeWindow:
1955 if (event.subwindow != 0)
1956 break; /* duplicate event */
1957 f = x_window_to_frame (event.window);
1958 if (event.window == f->display.x->icon_desc)
1959 {
1960 refreshicon (f);
1961 f->async_iconified = 1;
1962 }
1963 if (event.window == FRAME_X_WINDOW (f))
1964 {
1965 /* Say must check all windows' needs_exposure flags. */
1966 expose_all_windows = 1;
1967 f->display.x->needs_exposure = 1;
1968 f->async_visible = 1;
1969 }
1970 break;
1971
1972 case ExposeRegion:
1973 if (event.subwindow != 0)
1974 break; /* duplicate event */
1975 f = x_window_to_frame (event.window);
1976 if (event.window == f->display.x->icon_desc)
1977 {
1978 refreshicon (f);
1979 break;
1980 }
1981 /* If window already needs full redraw, ignore this rectangle. */
1982 if (expose_all_windows && f->display.x->needs_exposure)
1983 break;
1984 /* Put the event on the queue of rectangles to redraw. */
1985 if (enqueue_event (&event, &x_expose_queue))
1986 /* If it is full, we can't record the rectangle,
1987 so redraw this entire window. */
1988 {
1989 /* Say must check all windows' needs_exposure flags. */
1990 expose_all_windows = 1;
1991 f->display.x->needs_exposure = 1;
1992 }
1993 break;
1994
1995 case ExposeCopy:
1996 /* This should happen only when we are expecting it,
1997 in x_read_exposes. */
1998 abort ();
1999 #endif /* ! defined (HAVE_X11) */
2000
2001 #ifdef HAVE_X11
2002 case UnmapNotify:
2003 {
2004 XWMHints *hints;
2005
2006 f = x_window_to_frame (event.xunmap.window);
2007 if (f) /* F may no longer exist if
2008 the frame was deleted. */
2009 {
2010 /* While a frame is unmapped, display generation is
2011 disabled; you don't want to spend time updating a
2012 display that won't ever be seen. */
2013 f->async_visible = 0;
2014 x_mouse_x = x_mouse_y = -1;
2015 }
2016 }
2017 break;
2018
2019 case MapNotify:
2020 f = x_window_to_frame (event.xmap.window);
2021 if (f)
2022 {
2023 f->async_visible = 1;
2024 f->async_iconified = 0;
2025
2026 /* wait_reading_process_input will notice this and update
2027 the frame's display structures. */
2028 SET_FRAME_GARBAGED (f);
2029 }
2030 break;
2031
2032 /* Turn off processing if we become fully obscured. */
2033 case VisibilityNotify:
2034 break;
2035
2036 #else /* ! defined (HAVE_X11) */
2037 case UnmapWindow:
2038 f = x_window_to_frame (event.window);
2039 if (event.window == f->display.x->icon_desc)
2040 f->async_iconified = 0;
2041 if (event.window == FRAME_X_WINDOW (f))
2042 f->async_visible = 0;
2043 break;
2044 #endif /* ! defined (HAVE_X11) */
2045
2046 #ifdef HAVE_X11
2047 case KeyPress:
2048 f = x_window_to_frame (event.xkey.window);
2049 if (f != 0)
2050 {
2051 KeySym keysym;
2052 char copy_buffer[80];
2053 int modifiers = event.xkey.state;
2054
2055 /* Some keyboards generate different characters
2056 depending on the state of the meta key, in an attempt
2057 to support non-English typists. It would be nice to
2058 keep this functionality somehow, but for now, we will
2059 just clear the meta-key flag to get the 'pure' character. */
2060 event.xkey.state &= ~Mod1Mask;
2061
2062 /* This will have to go some day... */
2063 nbytes =
2064 XLookupString (&event.xkey, copy_buffer, 80, &keysym,
2065 &compose_status);
2066
2067 /* Strip off the vendor-specific keysym bit, and take a shot
2068 at recognizing the codes. HP servers have extra keysyms
2069 that fit into the MiscFunctionKey category. */
2070 keysym &= ~(1<<28);
2071
2072 if (numchars > 1)
2073 {
2074 if (IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
2075 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
2076 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
2077 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
2078 {
2079 bufp->kind = non_ascii_keystroke;
2080 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
2081 bufp->frame = f;
2082 bufp->modifiers = x_convert_modifiers (modifiers);
2083 bufp->timestamp = event.xkey.time;
2084 bufp++;
2085 count++;
2086 numchars--;
2087 }
2088 else if (numchars > nbytes)
2089 {
2090 register int i;
2091
2092 if (nbytes == 1)
2093 {
2094 if (modifiers & x_meta_mod_mask)
2095 *copy_buffer |= METABIT;
2096 bufp->kind = ascii_keystroke;
2097 XSET (bufp->code, Lisp_Int, *copy_buffer);
2098 bufp->frame = f;
2099 bufp->timestamp = event.xkey.time;
2100 bufp++;
2101 }
2102 else
2103 for (i = nbytes - 1; i > 1; i--)
2104 {
2105 bufp->kind = ascii_keystroke;
2106 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
2107 bufp->frame = f;
2108 bufp->timestamp = event.xkey.time;
2109 bufp++;
2110 }
2111
2112 count += nbytes;
2113 numchars -= nbytes;
2114 }
2115 }
2116 }
2117 break;
2118 #else /* ! defined (HAVE_X11) */
2119 case KeyPressed:
2120 {
2121 register char *where_mapping;
2122
2123 f = x_window_to_frame (event.window);
2124 /* Ignore keys typed on icon windows. */
2125 if (f != 0 && event.window == f->display.x->icon_desc)
2126 break;
2127 where_mapping = XLookupMapping (&event, &nbytes);
2128 /* Nasty fix for arrow keys */
2129 if (!nbytes && IsCursorKey (event.detail & 0xff))
2130 {
2131 switch (event.detail & 0xff)
2132 {
2133 case KC_CURSOR_LEFT:
2134 where_mapping = "\002";
2135 break;
2136 case KC_CURSOR_RIGHT:
2137 where_mapping = "\006";
2138 break;
2139 case KC_CURSOR_UP:
2140 where_mapping = "\020";
2141 break;
2142 case KC_CURSOR_DOWN:
2143 where_mapping = "\016";
2144 break;
2145 }
2146 nbytes = 1;
2147 }
2148 if (numchars - nbytes > 0)
2149 {
2150 register int i;
2151
2152 for (i = 0; i < nbytes; i++)
2153 {
2154 bufp->kind = ascii_keystroke;
2155 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2156 XSET (bufp->time, Lisp_Int, event.xkey.time);
2157 bufp->frame = f;
2158 bufp++;
2159 }
2160 count += nbytes;
2161 numchars -= nbytes;
2162 }
2163 }
2164 break;
2165 #endif /* ! defined (HAVE_X11) */
2166
2167 #ifdef HAVE_X11
2168 case EnterNotify:
2169 f = x_window_to_frame (event.xcrossing.window);
2170
2171 if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
2172 ;
2173 else if (event.xcrossing.focus) /* Entered Window */
2174 {
2175 /* If we decide we want to generate an event to be seen
2176 by the rest of Emacs, we put it here. */
2177 struct input_event emacs_event;
2178 emacs_event.kind = no_event;
2179
2180 /* Avoid nasty pop/raise loops. */
2181 if (f && (!(f->auto_raise)
2182 || !(f->auto_lower)
2183 || (event.xcrossing.time - enter_timestamp) > 500))
2184 {
2185 x_new_focus_frame (f);
2186 enter_timestamp = event.xcrossing.time;
2187 }
2188 #if 0
2189 else if ((f = x_window_to_scrollbar (event.xcrossing.window,
2190 &part, &prefix)))
2191 /* Fake a motion event */
2192 notice_mouse_movement (&emacs_event,
2193 event.xmotion, f, scrollbar_window,
2194 part);
2195 #endif /* ! 0 */
2196
2197 #if 0
2198 if (! EQ (Vx_send_mouse_movement_events, Qnil)
2199 && numchars >= 1
2200 && emacs_event.kind != no_event)
2201 {
2202 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2203 bufp++;
2204 count++;
2205 numchars--;
2206 }
2207 #endif /* ! 0 */
2208 }
2209 else if (f == x_focus_frame)
2210 x_new_focus_frame (0);
2211 #if 0
2212 else if (f = x_window_to_frame (event.xcrossing.window))
2213 x_mouse_frame = f;
2214 #endif /* ! 0 */
2215
2216 break;
2217
2218 case FocusIn:
2219 f = x_window_to_frame (event.xfocus.window);
2220 if (f)
2221 x_new_focus_frame (f);
2222 break;
2223
2224 case LeaveNotify:
2225 if (event.xcrossing.detail != NotifyInferior
2226 && event.xcrossing.subwindow == None
2227 && event.xcrossing.mode == NotifyNormal)
2228 {
2229 f = x_window_to_frame (event.xcrossing.window);
2230
2231 if (event.xcrossing.focus)
2232 x_new_focus_frame (f);
2233 else if (f == x_focus_frame)
2234 x_new_focus_frame (0);
2235 }
2236 break;
2237
2238 case FocusOut:
2239 f = x_window_to_frame (event.xfocus.window);
2240 if (f && f == x_focus_frame)
2241 x_new_focus_frame (0);
2242 break;
2243
2244 #else /* ! defined (HAVE_X11) */
2245
2246 case EnterWindow:
2247 if ((event.detail & 0xFF) == 1)
2248 break; /* Coming from our own subwindow */
2249 if (event.subwindow != 0)
2250 break; /* Entering our own subwindow. */
2251
2252 {
2253 f = x_window_to_frame (event.window);
2254 x_mouse_frame = f;
2255
2256 x_new_focus_frame (f);
2257 }
2258 break;
2259
2260 case LeaveWindow:
2261 if ((event.detail & 0xFF) == 1)
2262 break; /* Entering our own subwindow */
2263 if (event.subwindow != 0)
2264 break; /* Leaving our own subwindow. */
2265
2266 x_mouse_frame = 0;
2267 if (x_focus_frame == 0
2268 && x_input_frame != 0
2269 && x_input_frame == x_window_to_frame (event.window)
2270 && event.window == FRAME_X_WINDOW (x_input_frame))
2271 {
2272 f = x_input_frame;
2273 x_input_frame = 0;
2274 if (f)
2275 frame_unhighlight (f);
2276 }
2277 break;
2278 #endif /* ! defined (HAVE_X11) */
2279
2280 #ifdef HAVE_X11
2281 case MotionNotify:
2282 {
2283 f = x_window_to_frame (event.xmotion.window);
2284 if (f)
2285 note_mouse_position (f, &event.xmotion);
2286 #if 0
2287 else if ((f = x_window_to_scrollbar (event.xmotion.window,
2288 &part, &prefix)))
2289 {
2290 What should go here?
2291 }
2292 #endif /* ! 0 */
2293 }
2294 break;
2295
2296 case ConfigureNotify:
2297 {
2298 int rows, columns;
2299 f = x_window_to_frame (event.xconfigure.window);
2300 if (!f)
2301 break;
2302
2303 columns = ((event.xconfigure.width -
2304 (2 * f->display.x->internal_border_width)
2305 - f->display.x->v_scrollbar_width)
2306 / FONT_WIDTH (f->display.x->font));
2307 rows = ((event.xconfigure.height -
2308 (2 * f->display.x->internal_border_width)
2309 - f->display.x->h_scrollbar_height)
2310 / FONT_HEIGHT (f->display.x->font));
2311
2312 /* Even if the number of character rows and columns has
2313 not changed, the font size may have changed, so we need
2314 to check the pixel dimensions as well. */
2315 if (columns != f->width
2316 || rows != f->height
2317 || event.xconfigure.width != f->display.x->pixel_width
2318 || event.xconfigure.height != f->display.x->pixel_height)
2319 {
2320 change_frame_size (f, rows, columns, 0, 1);
2321 x_resize_scrollbars (f);
2322 SET_FRAME_GARBAGED (f);
2323 }
2324
2325 f->display.x->pixel_width = event.xconfigure.width;
2326 f->display.x->pixel_height = event.xconfigure.height;
2327 f->display.x->left_pos = event.xconfigure.x;
2328 f->display.x->top_pos = event.xconfigure.y;
2329 break;
2330 }
2331
2332 case ButtonPress:
2333 case ButtonRelease:
2334 {
2335 /* If we decide we want to generate an event to be seen
2336 by the rest of Emacs, we put it here. */
2337 struct input_event emacs_event;
2338 emacs_event.kind = no_event;
2339
2340 f = x_window_to_frame (event.xbutton.window);
2341 if (f)
2342 if (!x_focus_frame || (f == x_focus_frame))
2343 construct_mouse_click (&emacs_event,
2344 &event, f, Qnil, 0);
2345 else
2346 continue;
2347 else
2348 if ((f = x_window_to_scrollbar (event.xbutton.window,
2349 &part, &prefix)))
2350 {
2351 if (!x_focus_frame || (selected_frame == x_focus_frame))
2352 construct_mouse_click (&emacs_event,
2353 &event, f, part, prefix);
2354 else
2355 continue;
2356 }
2357
2358 if (numchars >= 1 && emacs_event.kind != no_event)
2359 {
2360 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2361 bufp++;
2362 count++;
2363 numchars--;
2364 }
2365 }
2366 break;
2367
2368 #else /* ! defined (HAVE_X11) */
2369 case ButtonPressed:
2370 case ButtonReleased:
2371 f = x_window_to_frame (event.window);
2372 if (f)
2373 {
2374 if (event.window == f->display.x->icon_desc)
2375 {
2376 x_make_frame_visible (f);
2377
2378 if (warp_mouse_on_deiconify)
2379 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
2380 break;
2381 }
2382 if (event.window == FRAME_X_WINDOW (f))
2383 {
2384 if (f->auto_raise)
2385 x_raise_frame (f);
2386 }
2387 }
2388 enqueue_event (&event, &x_mouse_queue);
2389 if (numchars >= 2)
2390 {
2391 bufp->kind = ascii_keystroke;
2392 bufp->code = (char) 'X' & 037; /* C-x */
2393 bufp->frame = f;
2394 XSET (bufp->time, Lisp_Int, event.xkey.time);
2395 bufp++;
2396
2397 bufp->kind = ascii_keystroke;
2398 bufp->code = (char) 0; /* C-@ */
2399 bufp->frame = f;
2400 XSET (bufp->time, Lisp_Int, event.xkey.time);
2401 bufp++;
2402
2403 count += 2;
2404 numchars -= 2;
2405 }
2406 break;
2407 #endif /* ! defined (HAVE_X11) */
2408
2409 #ifdef HAVE_X11
2410
2411 case CirculateNotify:
2412 break;
2413 case CirculateRequest:
2414 break;
2415
2416 #endif /* ! defined (HAVE_X11) */
2417
2418 case MappingNotify:
2419 /* Someone has changed the keyboard mapping - update the
2420 local cache. */
2421 switch (event.xmapping.request)
2422 {
2423 case MappingModifier:
2424 x_find_modifier_meanings ();
2425 /* This is meant to fall through. */
2426 case MappingKeyboard:
2427 XRefreshKeyboardMapping (&event.xmapping);
2428 }
2429 break;
2430
2431 default:
2432 break;
2433 }
2434 }
2435
2436 #if 0
2437 #ifdef HAVE_SELECT
2438 if (expected && ! event_found)
2439 {
2440 /* AOJ 880406: if select returns true but XPending doesn't, it means that
2441 there is an EOF condition; in other words, that X has died.
2442 Act as if there had been a hangup. */
2443
2444 int fd = ConnectionNumber (x_current_display);
2445 int mask = 1 << fd;
2446
2447 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
2448 (EMACS_TIME) 0)
2449 && !XStuffPending ())
2450 kill (getpid (), SIGHUP);
2451 }
2452 #endif /* ! defined (HAVE_SELECT) */
2453 #endif /* ! 0 */
2454
2455 if (updating_frame == 0)
2456 x_do_pending_expose ();
2457
2458 UNBLOCK_INPUT;
2459 return count;
2460 }
2461
2462 #ifndef HAVE_X11
2463 /* Read and process only Expose events
2464 until we get an ExposeCopy event; then return.
2465 This is used in insert/delete line.
2466 We assume input is already blocked. */
2467
2468 static void
2469 x_read_exposes ()
2470 {
2471 struct frame *f;
2472 XKeyPressedEvent event;
2473
2474 while (1)
2475 {
2476 /* while there are more events*/
2477 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
2478 switch (event.type)
2479 {
2480 case ExposeWindow:
2481 if (event.subwindow != 0)
2482 break; /* duplicate event */
2483 f = x_window_to_frame (event.window);
2484 if (event.window == f->display.x->icon_desc)
2485 {
2486 refreshicon (f);
2487 break;
2488 }
2489 if (event.window == FRAME_X_WINDOW (f))
2490 {
2491 expose_all_windows = 1;
2492 f->display.x->needs_exposure = 1;
2493 break;
2494 }
2495 break;
2496
2497 case ExposeRegion:
2498 if (event.subwindow != 0)
2499 break; /* duplicate event */
2500 f = x_window_to_frame (event.window);
2501 if (event.window == f->display.x->icon_desc)
2502 {
2503 refreshicon (f);
2504 break;
2505 }
2506 /* If window already needs full redraw, ignore this rectangle. */
2507 if (expose_all_windows && f->display.x->needs_exposure)
2508 break;
2509 /* Put the event on the queue of rectangles to redraw. */
2510 if (enqueue_event (&event, &x_expose_queue))
2511 /* If it is full, we can't record the rectangle,
2512 so redraw this entire window. */
2513 {
2514 /* Say must check all windows' needs_exposure flags. */
2515 expose_all_windows = 1;
2516 f->display.x->needs_exposure = 1;
2517 }
2518 break;
2519
2520 case ExposeCopy:
2521 return;
2522 }
2523 }
2524 }
2525 #endif /* HAVE_X11 */
2526
2527 \f
2528 /* Draw a hollow box cursor. Don't change the inside of the box. */
2529
2530 static void
2531 x_draw_box (f)
2532 struct frame *f;
2533 {
2534 int left = f->cursor_x * FONT_WIDTH (f->display.x->font)
2535 + f->display.x->internal_border_width;
2536 int top = f->cursor_y * FONT_HEIGHT (f->display.x->font)
2537 + f->display.x->internal_border_width;
2538 int width = FONT_WIDTH (f->display.x->font);
2539 int height = FONT_HEIGHT (f->display.x->font);
2540
2541 #ifdef HAVE_X11
2542 /* Perhaps we should subtract 1 from width and height... */
2543 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
2544 f->display.x->cursor_gc,
2545 left, top, width - 1, height - 1);
2546 #else /* ! defined (HAVE_X11) */
2547 XPixSet (FRAME_X_WINDOW (f),
2548 left, top, width, 1,
2549 f->display.x->cursor_pixel);
2550
2551 XPixSet (FRAME_X_WINDOW (f),
2552 left, top, 1, height,
2553 f->display.x->cursor_pixel);
2554
2555 XPixSet (FRAME_X_WINDOW (f),
2556 left+width-1, top, 1, height,
2557 f->display.x->cursor_pixel);
2558
2559 XPixSet (FRAME_X_WINDOW (f),
2560 left, top+height-1, width, 1,
2561 f->display.x->cursor_pixel);
2562 #endif /* ! defined (HAVE_X11) */
2563 }
2564
2565 /* Clear the cursor of frame F to background color,
2566 and mark the cursor as not shown.
2567 This is used when the text where the cursor is
2568 is about to be rewritten. */
2569
2570 static void
2571 clear_cursor (f)
2572 struct frame *f;
2573 {
2574 int mask;
2575
2576 if (! f->visible
2577 || f->phys_cursor_x < 0)
2578 return;
2579
2580 #ifdef HAVE_X11
2581 x_display_cursor (f, 0);
2582 #if 0
2583 XClearArea (x_current_display, FRAME_X_WINDOW (f),
2584 f->phys_cursor_x * FONT_WIDTH (f->display.x->font)
2585 + f->display.x->internal_border_width,
2586 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font)
2587 + f->display.x->internal_border_width,
2588 FONT_WIDTH (f->display.x->font) + 1, FONT_HEIGHT (f->display.x->font) + 1, False);
2589 #endif /* ! 0 */
2590 #else /* ! defined (HAVE_X11) */
2591 XPixSet (FRAME_X_WINDOW (f),
2592 f->phys_cursor_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width,
2593 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width,
2594 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
2595 f->display.x->background_pixel);
2596 #endif /* ! defined (HAVE_X11) */
2597 f->phys_cursor_x = -1;
2598 }
2599
2600 static void
2601 x_display_bar_cursor (f, on)
2602 struct frame *f;
2603 int on;
2604 {
2605 register int phys_x = f->phys_cursor_x;
2606 register int phys_y = f->phys_cursor_y;
2607 register int x1;
2608 register int y1;
2609 register int y2;
2610
2611 if (! f->visible || (! on && f->phys_cursor_x < 0))
2612 return;
2613
2614 #ifdef HAVE_X11
2615 if (phys_x >= 0 &&
2616 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y))
2617 {
2618 x1 = phys_x * FONT_WIDTH (f->display.x->font)
2619 + f->display.x->internal_border_width;
2620 y1 = phys_y * FONT_HEIGHT (f->display.x->font)
2621 + f->display.x->internal_border_width - 1;
2622 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1;
2623
2624 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
2625 f->display.x->reverse_gc, x1, y1, x1, y2);
2626
2627 f->phys_cursor_x = phys_x = -1;
2628 }
2629
2630 if (on && f == x_highlight_frame)
2631 {
2632 x1 = f->cursor_x * FONT_WIDTH (f->display.x->font)
2633 + f->display.x->internal_border_width;
2634 y1 = f->cursor_y * FONT_HEIGHT (f->display.x->font)
2635 + f->display.x->internal_border_width - 1;
2636 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1;
2637
2638 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
2639 f->display.x->cursor_gc, x1, y1, x1, y2);
2640
2641 f->phys_cursor_x = f->cursor_x;
2642 f->phys_cursor_y = f->cursor_y;
2643 }
2644 #else /* ! defined (HAVE_X11) */
2645 Give it up, dude.
2646 #endif /* ! defined (HAVE_X11) */
2647 }
2648
2649
2650 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2651 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2652 glyph drawn. */
2653
2654 static void
2655 x_draw_single_glyph (f, row, column, glyph, highlight)
2656 struct frame *f;
2657 int row, column;
2658 GLYPH glyph;
2659 int highlight;
2660 {
2661 dumpglyphs (f,
2662 (column * FONT_WIDTH (f->display.x->font)
2663 + f->display.x->internal_border_width),
2664 (row * FONT_HEIGHT (f->display.x->font)
2665 + f->display.x->internal_border_width),
2666 &glyph, 1, highlight, f->display.x->font);
2667 }
2668
2669 /* Turn the displayed cursor of frame F on or off according to ON.
2670 If ON is nonzero, where to put the cursor is specified
2671 by F->cursor_x and F->cursor_y. */
2672
2673 static void
2674 x_display_box_cursor (f, on)
2675 struct frame *f;
2676 int on;
2677 {
2678 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2679
2680 /* If we're not updating, then we want to use the current frame's
2681 cursor position, not our local idea of where the cursor ought to be. */
2682 if (f != updating_frame)
2683 {
2684 curs_x = FRAME_CURSOR_X (f);
2685 curs_y = FRAME_CURSOR_Y (f);
2686 }
2687
2688 if (! f->visible)
2689 return;
2690
2691 /* If cursor is off and we want it off, return quickly. */
2692 if (!on && f->phys_cursor_x < 0)
2693 return;
2694
2695 /* If cursor is currently being shown and we don't want it to be
2696 or it is in the wrong place,
2697 or we want a hollow box and it's not so, (pout!)
2698 erase it. */
2699 if (f->phys_cursor_x >= 0
2700 && (!on
2701 || f->phys_cursor_x != curs_x
2702 || f->phys_cursor_y != curs_y
2703 || (f->display.x->text_cursor_kind != hollow_box_cursor
2704 && (f != x_highlight_frame))))
2705 {
2706 /* Erase the cursor by redrawing the character underneath it. */
2707 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2708 f->phys_cursor_glyph,
2709 current_glyphs->highlight[f->phys_cursor_y]);
2710 f->phys_cursor_x = -1;
2711 }
2712
2713 /* If we want to show a cursor,
2714 or we want a box cursor and it's not so,
2715 write it in the right place. */
2716 if (on
2717 && (f->phys_cursor_x < 0
2718 || (f->display.x->text_cursor_kind != filled_box_cursor
2719 && f == x_highlight_frame)))
2720 {
2721 f->phys_cursor_glyph
2722 = ((current_glyphs->enable[curs_y]
2723 && curs_x < current_glyphs->used[curs_y])
2724 ? current_glyphs->glyphs[curs_y][curs_x]
2725 : SPACEGLYPH);
2726 if (f != x_highlight_frame)
2727 {
2728 x_draw_box (f);
2729 f->display.x->text_cursor_kind = hollow_box_cursor;
2730 }
2731 else
2732 {
2733 x_draw_single_glyph (f, curs_y, curs_x,
2734 f->phys_cursor_glyph, 2);
2735 f->display.x->text_cursor_kind = filled_box_cursor;
2736 }
2737
2738 f->phys_cursor_x = curs_x;
2739 f->phys_cursor_y = curs_y;
2740 }
2741
2742 if (updating_frame != f)
2743 XFlushQueue ();
2744 }
2745
2746 extern Lisp_Object Vbar_cursor;
2747
2748 x_display_cursor (f, on)
2749 struct frame *f;
2750 int on;
2751 {
2752 if (EQ (Vbar_cursor, Qnil))
2753 x_display_box_cursor (f, on);
2754 else
2755 x_display_bar_cursor (f, on);
2756 }
2757 \f
2758 /* Icons. */
2759
2760 /* Refresh bitmap kitchen sink icon for frame F
2761 when we get an expose event for it. */
2762
2763 refreshicon (f)
2764 struct frame *f;
2765 {
2766 #ifdef HAVE_X11
2767 /* Normally, the window manager handles this function. */
2768 #else /* ! defined (HAVE_X11) */
2769 int mask;
2770
2771 if (f->display.x->icon_bitmap_flag)
2772 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
2773 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
2774 icon_bitmap, GXcopy, AllPlanes);
2775 else
2776 {
2777 extern struct frame *selected_frame;
2778 struct Lisp_String *str;
2779 unsigned char *string;
2780
2781 string
2782 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
2783
2784 if (f->display.x->icon_label != string)
2785 {
2786 f->display.x->icon_label = string;
2787 XChangeWindow (f->display.x->icon_desc,
2788 XQueryWidth (string, icon_font_info->id) + 10,
2789 icon_font_info->height + 10);
2790 }
2791
2792 XText (f->display.x->icon_desc, 5, 5, string,
2793 str->size, icon_font_info->id,
2794 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
2795 }
2796 XFlushQueue ();
2797 #endif /* ! defined (HAVE_X11) */
2798 }
2799
2800 /* Make the x-window of frame F use the kitchen-sink icon
2801 that's a window generated by Emacs. */
2802
2803 int
2804 x_bitmap_icon (f)
2805 struct frame *f;
2806 {
2807 int mask;
2808 Window icon_window;
2809
2810 if (FRAME_X_WINDOW (f) == 0)
2811 return 1;
2812
2813 #ifdef HAVE_X11
2814 if (icon_bitmap)
2815 XFreePixmap (x_current_display, icon_bitmap);
2816
2817 icon_bitmap =
2818 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
2819 gnu_bits, gnu_width, gnu_height);
2820 x_wm_set_icon_pixmap (f, icon_bitmap);
2821 f->display.x->icon_bitmap_flag = 1;
2822 #else /* ! defined (HAVE_X11) */
2823 if (f->display.x->icon_desc)
2824 {
2825 XClearIconWindow (FRAME_X_WINDOW (f));
2826 XDestroyWindow (f->display.x->icon_desc);
2827 }
2828
2829 icon_window = XCreateWindow (f->display.x->parent_desc,
2830 0, 0, sink_width, sink_height,
2831 2, WhitePixmap, (Pixmap) NULL);
2832
2833 if (icon_window == 0)
2834 return 1;
2835
2836 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
2837 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
2838
2839 f->display.x->icon_desc = icon_window;
2840 f->display.x->icon_bitmap_flag = 1;
2841
2842 if (icon_bitmap == 0)
2843 icon_bitmap
2844 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
2845 #endif /* ! defined (HAVE_X11) */
2846
2847 return 0;
2848 }
2849
2850
2851 /* Make the x-window of frame F use a rectangle with text. */
2852
2853 int
2854 x_text_icon (f, icon_name)
2855 struct frame *f;
2856 char *icon_name;
2857 {
2858 #ifndef HAVE_X11
2859 int mask;
2860 int width;
2861 Window icon_window;
2862 char *X_DefaultValue;
2863 Bitmap b1;
2864
2865 #ifndef WhitePixel
2866 #define WhitePixel 1
2867 #endif /* WhitePixel */
2868
2869 #ifndef BlackPixel
2870 #define BlackPixel 0
2871 #endif /* BlackPixel */
2872 #endif /* HAVE_X11 */
2873
2874 if (FRAME_X_WINDOW (f) == 0)
2875 return 1;
2876
2877 if (icon_font_info == 0)
2878 icon_font_info
2879 = XGetFont (XGetDefault (XDISPLAY
2880 (char *) XSTRING (invocation_name)->data,
2881 "BodyFont"));
2882
2883 #ifdef HAVE_X11
2884 if (icon_name)
2885 f->display.x->icon_label = icon_name;
2886 else
2887 if (! f->display.x->icon_label)
2888 f->display.x->icon_label = " *emacs* ";
2889
2890 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
2891 (char *) f->display.x->icon_label);
2892
2893 f->display.x->icon_bitmap_flag = 0;
2894 x_wm_set_icon_pixmap (f, 0);
2895 #else /* ! defined (HAVE_X11) */
2896 if (f->display.x->icon_desc)
2897 {
2898 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
2899 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
2900 }
2901
2902 if (icon_name)
2903 f->display.x->icon_label = (unsigned char *) icon_name;
2904 else
2905 if (! f->display.x->icon_label)
2906 f->display.x->icon_label = XSTRING (f->name)->data;
2907
2908 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
2909 icon_window = XCreateWindow (f->display.x->parent_desc,
2910 f->display.x->left_pos,
2911 f->display.x->top_pos,
2912 width + 10, icon_font_info->height + 10,
2913 2, BlackPixmap, WhitePixmap);
2914
2915 if (icon_window == 0)
2916 return 1;
2917
2918 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
2919 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
2920
2921 f->display.x->icon_desc = icon_window;
2922 f->display.x->icon_bitmap_flag = 0;
2923 f->display.x->icon_label = 0;
2924 #endif /* ! defined (HAVE_X11) */
2925
2926 return 0;
2927 }
2928 \f
2929 /* Handling X errors. */
2930
2931 /* A handler for SIGPIPE, when it occurs on the X server's connection.
2932 This basically does an orderly shutdown of Emacs. */
2933
2934 static SIGTYPE
2935 x_connection_closed ()
2936 {
2937 if (_Xdebug)
2938 abort ();
2939 else
2940 Fkill_emacs (make_number (70));
2941 }
2942
2943 /* An X error handler which prints an error message and then kills Emacs.
2944 This is what's normally installed as Xlib's handler for protocol and
2945 I/O errors. */
2946 static int
2947 x_error_quitter (display, error)
2948 Display *display;
2949 XErrorEvent *error;
2950 {
2951 char buf[256];
2952
2953 /* Note that there is no real way portable across R3/R4 to get the
2954 original error handler. */
2955
2956 XGetErrorText (display, error->error_code, buf, sizeof (buf));
2957 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
2958 buf, error->request_code);
2959
2960 x_connection_closed ();
2961 }
2962
2963 /* A buffer for storing X error messages. */
2964 static char (*x_caught_error_message)[200];
2965
2966 /* An X error handler which stores the error message in
2967 x_caught_error_message. This is what's installed when
2968 x_catch_errors is in effect. */
2969 static int
2970 x_error_catcher (display, error)
2971 Display *display;
2972 XErrorEvent *error;
2973 {
2974 XGetErrorText (display, error->error_code,
2975 *x_caught_error_message, sizeof (*x_caught_error_message));
2976 }
2977
2978
2979 /* Begin trapping X errors.
2980
2981 After calling this function, X protocol errors no longer cause
2982 Emacs to exit; instead, they are recorded in x_cfc_error_message.
2983
2984 Calling x_check_errors signals an Emacs error if an X error has
2985 occurred since the last call to x_catch_errors or x_check_errors.
2986
2987 Calling x_uncatch_errors resumes the normal error handling. */
2988
2989 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
2990
2991 void
2992 x_catch_errors ()
2993 {
2994 /* Make sure any errors from previous requests have been dealt with. */
2995 XSync (x_current_display, False);
2996
2997 /* Set up the error buffer. */
2998 x_caught_error_message =
2999 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
3000 (*x_caught_error_message)[0] = '\0';
3001
3002 /* Install our little error handler. */
3003 XHandleError (x_error_catcher);
3004 }
3005
3006 /* If any X protocol errors have arrived since the last call to
3007 x_catch_errors or x_check_errors, signal an Emacs error using
3008 sprintf (a buffer, FORMAT, the x error message text) as the text. */
3009 void
3010 x_check_errors (format)
3011 char *format;
3012 {
3013 /* Make sure to catch any errors incurred so far. */
3014 XSync (x_current_display, False);
3015
3016 if ((*x_caught_error_message)[0])
3017 {
3018 char buf[256];
3019
3020 sprintf (buf, format, *x_caught_error_message);
3021 free (x_caught_error_message);
3022
3023 x_uncatch_errors ();
3024 error (buf);
3025 }
3026 }
3027
3028 void
3029 x_uncatch_errors ()
3030 {
3031 free (x_caught_error_message);
3032 XHandleError (x_error_quitter);
3033 }
3034
3035 #if 0
3036 static unsigned int x_wire_count;
3037 x_trace_wire ()
3038 {
3039 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
3040 }
3041 #endif /* ! 0 */
3042
3043 \f
3044 /* Set the font of the x-window specified by frame F
3045 to the font named NEWNAME. This is safe to use
3046 even before F has an actual x-window. */
3047
3048 #ifdef HAVE_X11
3049
3050 /* A table of all the fonts we have already loaded. */
3051 static XFontStruct **x_font_table;
3052
3053 /* The current capacity of x_font_table. */
3054 static int x_font_table_size;
3055
3056 /* The number of fonts actually stored in x_font_table.
3057 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
3058 0 <= n_fonts <= x_font_table_size. */
3059 static int n_fonts;
3060
3061 x_new_font (f, fontname)
3062 struct frame *f;
3063 register char *fontname;
3064 {
3065 XFontStruct *temp;
3066 int already_loaded;
3067 int n_matching_fonts;
3068 XFontStruct *font_info;
3069 char **font_names;
3070
3071 /* Get a list of all the fonts that match this name. Once we
3072 have a list of matching fonts, we compare them against the fonts
3073 we already have by comparing font ids. */
3074 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
3075 1024, &n_matching_fonts,
3076 &font_info);
3077 /* If the server couldn't find any fonts whose named matched fontname,
3078 return an error code. */
3079 if (n_matching_fonts == 0)
3080 return 1;
3081
3082 /* See if we've already loaded a matching font. */
3083 {
3084 int i, j;
3085
3086 already_loaded = 0;
3087 for (i = 0; i < n_fonts; i++)
3088 for (j = 0; j < n_matching_fonts; j++)
3089 if (x_font_table[i]->fid == font_info[j].fid)
3090 {
3091 already_loaded = i;
3092 goto found_font;
3093 }
3094 }
3095 found_font:
3096
3097 /* If we have, just return it from the table. */
3098 if (already_loaded)
3099 f->display.x->font = x_font_table[already_loaded];
3100
3101 /* Otherwise, load the font and add it to the table. */
3102 else
3103 {
3104 XFontStruct *font;
3105
3106 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
3107 if (! font)
3108 return 1;
3109
3110 /* Do we need to create the table? */
3111 if (x_font_table_size == 0)
3112 {
3113 x_font_table_size = 16;
3114 x_font_table
3115 = (XFontStruct **) xmalloc (x_font_table_size
3116 * sizeof (x_font_table[0]));
3117 }
3118 /* Do we need to grow the table? */
3119 else if (n_fonts >= x_font_table_size)
3120 {
3121 x_font_table_size *= 2;
3122 x_font_table
3123 = (XFontStruct **) xrealloc (x_font_table,
3124 (x_font_table_size
3125 * sizeof (x_font_table[0])));
3126 }
3127
3128 f->display.x->font = x_font_table[n_fonts++] = font;
3129 }
3130
3131 /* Free the information from XListFontsWithInfo. The data
3132 we actually retain comes from XLoadQueryFont. */
3133 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3134
3135 /* Now make the frame display the given font. */
3136 if (FRAME_X_WINDOW (f) != 0)
3137 {
3138 XSetFont (x_current_display, f->display.x->normal_gc,
3139 f->display.x->font->fid);
3140 XSetFont (x_current_display, f->display.x->reverse_gc,
3141 f->display.x->font->fid);
3142 XSetFont (x_current_display, f->display.x->cursor_gc,
3143 f->display.x->font->fid);
3144
3145 x_set_window_size (f, f->width, f->height);
3146 }
3147
3148 return 0;
3149 }
3150 #else /* ! defined (HAVE_X11) */
3151 x_new_font (f, newname)
3152 struct frame *f;
3153 register char *newname;
3154 {
3155 FONT_TYPE *temp;
3156 int mask;
3157
3158 temp = XGetFont (newname);
3159 if (temp == (FONT_TYPE *) 0)
3160 return 1;
3161
3162 if (f->display.x->font)
3163 XLoseFont (f->display.x->font);
3164
3165 f->display.x->font = temp;
3166
3167 if (FRAME_X_WINDOW (f) != 0)
3168 x_set_window_size (f, f->width, f->height);
3169
3170 return 0;
3171 }
3172 #endif /* ! defined (HAVE_X11) */
3173 \f
3174 x_calc_absolute_position (f)
3175 struct frame *f;
3176 {
3177 #ifdef HAVE_X11
3178 if (f->display.x->left_pos < 0)
3179 f->display.x->left_pos
3180 = x_screen_width - PIXEL_WIDTH (f) + f->display.x->left_pos;
3181
3182 if (f->display.x->top_pos < 0)
3183 f->display.x->top_pos
3184 = x_screen_height - PIXEL_HEIGHT (f) + f->display.x->top_pos;
3185 #else /* ! defined (HAVE_X11) */
3186 WINDOWINFO_TYPE parentinfo;
3187
3188 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
3189
3190 if (f->display.x->left_pos < 0)
3191 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
3192 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
3193
3194 if (f->display.x->top_pos < 0)
3195 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
3196 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
3197 #endif /* ! defined (HAVE_X11) */
3198 }
3199
3200 x_set_offset (f, xoff, yoff)
3201 struct frame *f;
3202 register int xoff, yoff;
3203 {
3204 f->display.x->top_pos = yoff;
3205 f->display.x->left_pos = xoff;
3206 x_calc_absolute_position (f);
3207
3208 BLOCK_INPUT;
3209 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
3210 f->display.x->left_pos, f->display.x->top_pos);
3211 #ifdef HAVE_X11
3212 x_wm_set_size_hint (f, 0);
3213 #endif /* ! defined (HAVE_X11) */
3214 UNBLOCK_INPUT;
3215 }
3216
3217 /* Call this to change the size of frame F's x-window. */
3218
3219 x_set_window_size (f, cols, rows)
3220 struct frame *f;
3221 int cols, rows;
3222 {
3223 int pixelwidth, pixelheight;
3224 int mask;
3225 int ibw = f->display.x->internal_border_width;
3226
3227 BLOCK_INPUT;
3228
3229 check_frame_size (f, &rows, &cols);
3230 pixelwidth = (cols * FONT_WIDTH (f->display.x->font) + 2 * ibw
3231 + f->display.x->v_scrollbar_width);
3232 pixelheight = (rows * FONT_HEIGHT (f->display.x->font) + 2 * ibw
3233 + f->display.x->h_scrollbar_height);
3234
3235 #ifdef HAVE_X11
3236 x_wm_set_size_hint (f, 0);
3237 #endif /* ! defined (HAVE_X11) */
3238 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
3239
3240 /* Now, strictly speaking, we can't be sure that this is accurate,
3241 but the window manager will get around to dealing with the size
3242 change request eventually, and we'll hear how it went when the
3243 ConfigureNotify event gets here. */
3244 FRAME_WIDTH (f) = cols;
3245 FRAME_WIDTH (f) = rows;
3246 PIXEL_WIDTH (f) = pixelwidth;
3247 PIXEL_HEIGHT (f) = pixelheight;
3248
3249 XFlushQueue ();
3250 UNBLOCK_INPUT;
3251 }
3252
3253 #ifndef HAVE_X11
3254 x_set_resize_hint (f)
3255 struct frame *f;
3256 {
3257
3258 XSetResizeHint (FRAME_X_WINDOW (f), 2 * f->display.x->internal_border_width,
3259 2 * f->display.x->internal_border_width,
3260 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font));
3261 }
3262 #endif /* HAVE_X11 */
3263 \f
3264
3265 x_set_mouse_position (f, x, y)
3266 struct frame *f;
3267 int x, y;
3268 {
3269 int pix_x, pix_y;
3270
3271 x_raise_frame (f);
3272
3273 if (x < 0)
3274 pix_x = (FRAME_WIDTH (f)
3275 * FONT_WIDTH (f->display.x->font)
3276 + 2 * f->display.x->internal_border_width
3277 + f->display.x->v_scrollbar_width) / 2;
3278 else
3279 pix_x = x * FONT_WIDTH (f->display.x->font) + 2; /* add 2 pixels to each
3280 dimension to move the
3281 mouse into the char
3282 cell */
3283
3284 if (y < 0)
3285 pix_y = (FRAME_HEIGHT (f)
3286 * FONT_HEIGHT (f->display.x->font)
3287 + 2 * f->display.x->internal_border_width
3288 + f->display.x->h_scrollbar_height) / 2;
3289 else
3290 pix_y = y * FONT_HEIGHT (f->display.x->font) + 2;
3291
3292 BLOCK_INPUT;
3293 x_mouse_x = x;
3294 x_mouse_y = y;
3295
3296 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
3297 UNBLOCK_INPUT;
3298 }
3299
3300 #ifdef HAVE_X11
3301 x_focus_on_frame (f)
3302 struct frame *f;
3303 {
3304 x_raise_frame (f);
3305 #if 0
3306 /* I don't think that the ICCCM allows programs to do things like this
3307 without the interaction of the window manager. Whatever you end up
3308 doing with this code, do it to x_unfocus_frame too. */
3309 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
3310 RevertToPointerRoot, CurrentTime);
3311 #endif /* ! 0 */
3312 }
3313
3314 x_unfocus_frame (f)
3315 struct frame *f;
3316 {
3317 #if 0
3318 /* Look at the remarks in x_focus_on_frame. */
3319 if (x_focus_frame == f)
3320 XSetInputFocus (x_current_display, PointerRoot,
3321 RevertToPointerRoot, CurrentTime);
3322 #endif /* ! 0 */
3323 }
3324
3325 #endif /* ! defined (HAVE_X11) */
3326
3327 /* Raise frame F. */
3328
3329 x_raise_frame (f)
3330 struct frame *f;
3331 {
3332 if (f->async_visible)
3333 {
3334 BLOCK_INPUT;
3335 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
3336 XFlushQueue ();
3337 UNBLOCK_INPUT;
3338 }
3339 }
3340
3341 /* Lower frame F. */
3342
3343 x_lower_frame (f)
3344 struct frame *f;
3345 {
3346 if (f->async_visible)
3347 {
3348 BLOCK_INPUT;
3349 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
3350 XFlushQueue ();
3351 UNBLOCK_INPUT;
3352 }
3353 }
3354
3355 /* Change from withdrawn state to mapped state. */
3356
3357 x_make_frame_visible (f)
3358 struct frame *f;
3359 {
3360 int mask;
3361
3362 BLOCK_INPUT;
3363
3364 if (! FRAME_VISIBLE_P (f))
3365 {
3366 #ifdef HAVE_X11
3367 if (! EQ (Vx_no_window_manager, Qt))
3368 x_wm_set_window_state (f, NormalState);
3369
3370 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3371 if (f->display.x->v_scrollbar != 0 || f->display.x->h_scrollbar != 0)
3372 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
3373 #else /* ! defined (HAVE_X11) */
3374 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3375 if (f->display.x->icon_desc != 0)
3376 XUnmapWindow (f->display.x->icon_desc);
3377
3378 /* Handled by the MapNotify event for X11 */
3379 f->async_visible = 1;
3380 f->async_iconified = 0;
3381
3382 /* NOTE: this may cause problems for the first frame. */
3383 XTcursor_to (0, 0);
3384 #endif /* ! defined (HAVE_X11) */
3385 }
3386
3387 XFlushQueue ();
3388
3389 UNBLOCK_INPUT;
3390 }
3391
3392 /* Change from mapped state to withdrawn state. */
3393
3394 x_make_frame_invisible (f)
3395 struct frame *f;
3396 {
3397 int mask;
3398
3399 if (! f->async_visible)
3400 return;
3401
3402 BLOCK_INPUT;
3403
3404 #ifdef HAVE_X11R4
3405
3406 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
3407 DefaultScreen (x_current_display)))
3408 {
3409 UNBLOCK_INPUT_RESIGNAL;
3410 error ("can't notify window manager of window withdrawl");
3411 }
3412
3413 #else /* ! defined (HAVE_X11R4) */
3414 #ifdef HAVE_X11
3415
3416 /* Tell the window manager what we're going to do. */
3417 if (! EQ (Vx_no_window_manager, Qt))
3418 {
3419 XEvent unmap;
3420
3421 unmap.xunmap.type = UnmapNotify;
3422 unmap.xunmap.window = FRAME_X_WINDOW (f);
3423 unmap.xunmap.event = DefaultRootWindow (x_current_display);
3424 unmap.xunmap.from_configure = False;
3425 if (! XSendEvent (x_current_display,
3426 DefaultRootWindow (x_current_display),
3427 False,
3428 SubstructureRedirectMask|SubstructureNotifyMask,
3429 &unmap))
3430 {
3431 UNBLOCK_INPUT_RESIGNAL;
3432 error ("can't notify window manager of withdrawal");
3433 }
3434 }
3435
3436 /* Unmap the window ourselves. Cheeky! */
3437 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
3438
3439 #else /* ! defined (HAVE_X11) */
3440
3441 XUnmapWindow (FRAME_X_WINDOW (f));
3442 f->async_visible = 0; /* Handled by the UnMap event for X11 */
3443 if (f->display.x->icon_desc != 0)
3444 XUnmapWindow (f->display.x->icon_desc);
3445
3446 #endif /* ! defined (HAVE_X11) */
3447 #endif /* ! defined (HAVE_X11R4) */
3448
3449 XFlushQueue ();
3450 UNBLOCK_INPUT;
3451 }
3452
3453 /* Window manager communication. Created in Fx_open_connection. */
3454 extern Atom Xatom_wm_change_state;
3455
3456 /* Change window state from mapped to iconified. */
3457
3458 x_iconify_frame (f)
3459 struct frame *f;
3460 {
3461 int mask;
3462
3463 if (f->async_iconified)
3464 return;
3465
3466 BLOCK_INPUT;
3467
3468 #ifdef HAVE_X11
3469 /* Since we don't know which revision of X we're running, we'll use both
3470 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
3471
3472 /* X11R4: send a ClientMessage to the window manager using the
3473 WM_CHANGE_STATE type. */
3474 {
3475 XEvent message;
3476
3477 message.xclient.window = FRAME_X_WINDOW (f);
3478 message.xclient.type = ClientMessage;
3479 message.xclient.message_type = Xatom_wm_change_state;
3480 message.xclient.format = 32;
3481 message.xclient.data.l[0] = IconicState;
3482
3483 if (! XSendEvent (x_current_display,
3484 DefaultRootWindow (x_current_display),
3485 False,
3486 SubstructureRedirectMask | SubstructureNotifyMask,
3487 &message))
3488 {
3489 UNBLOCK_INPUT_RESIGNAL;
3490 error ("Can't notify window manager of iconification.");
3491 }
3492 }
3493
3494 /* X11R3: set the initial_state field of the window manager hints to
3495 IconicState. */
3496 x_wm_set_window_state (f, IconicState);
3497
3498 f->async_iconified = 1;
3499 #else /* ! defined (HAVE_X11) */
3500 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
3501
3502 f->async_visible = 0; /* Handled in the UnMap event for X11. */
3503 if (f->display.x->icon_desc != 0)
3504 {
3505 XMapWindow (XDISPLAY f->display.x->icon_desc);
3506 refreshicon (f);
3507 }
3508 #endif /* ! defined (HAVE_X11) */
3509
3510 XFlushQueue ();
3511 UNBLOCK_INPUT;
3512 }
3513
3514 /* Destroy the X window of frame F.
3515 DISPL is the former f->display (since f->display
3516 has already been nulled out). */
3517
3518 x_destroy_window (f, displ)
3519 struct frame *f;
3520 union display displ;
3521 {
3522 int mask;
3523
3524 BLOCK_INPUT;
3525 if (displ.x->icon_desc != 0)
3526 XDestroyWindow (XDISPLAY displ.x->icon_desc);
3527 XDestroyWindow (XDISPLAY displ.x->window_desc);
3528 XFlushQueue ();
3529 UNBLOCK_INPUT;
3530
3531 free (displ.x);
3532 if (f == x_focus_frame)
3533 x_focus_frame = 0;
3534 if (f == x_highlight_frame)
3535 x_highlight_frame = 0;
3536 }
3537 \f
3538 #ifndef HAVE_X11
3539
3540 /* Manage event queues.
3541
3542 This code is only used by the X10 support.
3543
3544 We cannot leave events in the X queue and get them when we are ready
3545 because X does not provide a subroutine to get only a certain kind
3546 of event but not block if there are no queued events of that kind.
3547
3548 Therefore, we must examine events as they come in and copy events
3549 of certain kinds into our private queues.
3550
3551 All ExposeRegion events are put in x_expose_queue.
3552 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
3553
3554
3555 /* Write the event *P_XREP into the event queue *QUEUE.
3556 If the queue is full, do nothing, but return nonzero. */
3557
3558 int
3559 enqueue_event (p_xrep, queue)
3560 register XEvent *p_xrep;
3561 register struct event_queue *queue;
3562 {
3563 int newindex = queue->windex + 1;
3564 if (newindex == EVENT_BUFFER_SIZE)
3565 newindex = 0;
3566 if (newindex == queue->rindex)
3567 return -1;
3568 queue->xrep[queue->windex] = *p_xrep;
3569 queue->windex = newindex;
3570 return 0;
3571 }
3572
3573 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
3574 If *QUEUE is empty, do nothing and return 0. */
3575
3576 int
3577 dequeue_event (p_xrep, queue)
3578 register XEvent *p_xrep;
3579 register struct event_queue *queue;
3580 {
3581 if (queue->windex == queue->rindex)
3582 return 0;
3583 *p_xrep = queue->xrep[queue->rindex++];
3584 if (queue->rindex == EVENT_BUFFER_SIZE)
3585 queue->rindex = 0;
3586 return 1;
3587 }
3588
3589 /* Return the number of events buffered in *QUEUE. */
3590
3591 int
3592 queue_event_count (queue)
3593 register struct event_queue *queue;
3594 {
3595 int tem = queue->windex - queue->rindex;
3596 if (tem >= 0)
3597 return tem;
3598 return EVENT_BUFFER_SIZE + tem;
3599 }
3600
3601 /* Return nonzero if mouse input is pending. */
3602
3603 int
3604 mouse_event_pending_p ()
3605 {
3606 return queue_event_count (&x_mouse_queue);
3607 }
3608 #endif /* HAVE_X11 */
3609 \f
3610 #ifdef HAVE_X11
3611
3612 x_wm_set_size_hint (f, prompting)
3613 struct frame *f;
3614 long prompting;
3615 {
3616 XSizeHints size_hints;
3617 Window window = FRAME_X_WINDOW (f);
3618
3619 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
3620
3621 flexlines = f->height;
3622
3623 size_hints.x = f->display.x->left_pos;
3624 size_hints.y = f->display.x->top_pos;
3625 size_hints.height = PIXEL_HEIGHT (f);
3626 size_hints.width = PIXEL_WIDTH (f);
3627 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
3628 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
3629 size_hints.max_width =
3630 (x_screen_width - ((2 * f->display.x->internal_border_width)
3631 + f->display.x->v_scrollbar_width));
3632 size_hints.max_height =
3633 (x_screen_height - ((2 * f->display.x->internal_border_width)
3634 + f->display.x->h_scrollbar_height));
3635 {
3636 int base_width, base_height;
3637
3638 base_width = ((2 * f->display.x->internal_border_width)
3639 + f->display.x->v_scrollbar_width);
3640 base_height = ((2 * f->display.x->internal_border_width)
3641 + f->display.x->h_scrollbar_height);
3642
3643 {
3644 int min_rows = 0, min_cols = 0;
3645 check_frame_size (f, &min_rows, &min_cols);
3646
3647 /* The window manager uses the base width hints to calculate the
3648 current number of rows and columns in the frame while
3649 resizing; min_width and min_height aren't useful for this
3650 purpose, since they might not give the dimensions for a
3651 zero-row, zero-column frame.
3652
3653 We use the base_width and base_height members if we have
3654 them; otherwise, we set the min_width and min_height members
3655 to the size for a zero x zero frame. */
3656
3657 #ifdef HAVE_X11R4
3658 size_hints.flags |= PBaseSize;
3659 size_hints.base_width = base_width;
3660 size_hints.base_height = base_height;
3661 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
3662 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
3663 #else
3664 size_hints.min_width = base_width;
3665 size_hints.min_height = base_height;
3666 #endif
3667 }
3668
3669 }
3670
3671 if (prompting)
3672 size_hints.flags |= prompting;
3673 else
3674 {
3675 XSizeHints hints; /* Sometimes I hate X Windows... */
3676
3677 XGetNormalHints (x_current_display, window, &hints);
3678 if (hints.flags & PSize)
3679 size_hints.flags |= PSize;
3680 if (hints.flags & PPosition)
3681 size_hints.flags |= PPosition;
3682 if (hints.flags & USPosition)
3683 size_hints.flags |= USPosition;
3684 if (hints.flags & USSize)
3685 size_hints.flags |= USSize;
3686 }
3687
3688 #ifdef HAVE_X11R4
3689 XSetWMNormalHints (x_current_display, window, &size_hints);
3690 #else
3691 XSetNormalHints (x_current_display, window, &size_hints);
3692 #endif
3693 }
3694
3695 /* Used for IconicState or NormalState */
3696 x_wm_set_window_state (f, state)
3697 struct frame *f;
3698 int state;
3699 {
3700 Window window = FRAME_X_WINDOW (f);
3701
3702 f->display.x->wm_hints.flags |= StateHint;
3703 f->display.x->wm_hints.initial_state = state;
3704
3705 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3706 }
3707
3708 x_wm_set_icon_pixmap (f, icon_pixmap)
3709 struct frame *f;
3710 Pixmap icon_pixmap;
3711 {
3712 Window window = FRAME_X_WINDOW (f);
3713
3714 f->display.x->wm_hints.flags |= IconPixmapHint;
3715 f->display.x->wm_hints.icon_pixmap = icon_pixmap ? icon_pixmap : None;
3716
3717 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3718 }
3719
3720 x_wm_set_icon_position (f, icon_x, icon_y)
3721 struct frame *f;
3722 int icon_x, icon_y;
3723 {
3724 Window window = FRAME_X_WINDOW (f);
3725
3726 f->display.x->wm_hints.flags |= IconPositionHint;
3727 f->display.x->wm_hints.icon_x = icon_x;
3728 f->display.x->wm_hints.icon_y = icon_y;
3729
3730 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3731 }
3732
3733 \f
3734 void
3735 x_term_init (display_name)
3736 char *display_name;
3737 {
3738 Lisp_Object frame;
3739 char *defaultvalue;
3740 #ifdef F_SETOWN
3741 extern int old_fcntl_owner;
3742 #endif /* ! defined (F_SETOWN) */
3743
3744 x_focus_frame = x_highlight_frame = 0;
3745
3746 x_current_display = XOpenDisplay (display_name);
3747 if (x_current_display == 0)
3748 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
3749 display_name);
3750
3751 #ifdef HAVE_X11
3752 {
3753 int hostname_size = 256;
3754
3755 hostname = (char *) xmalloc (hostname_size);
3756
3757 #if 0
3758 XSetAfterFunction (x_current_display, x_trace_wire);
3759 #endif /* ! 0 */
3760
3761 invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
3762
3763 /* Try to get the host name; if the buffer is too short, try
3764 again. Apparently, the only indication gethostname gives of
3765 whether the buffer was large enough is the presence or absence
3766 of a '\0' in the string. Eech. */
3767 for (;;)
3768 {
3769 gethostname (hostname, hostname_size - 1);
3770 hostname[hostname_size - 1] = '\0';
3771
3772 /* Was the buffer large enough for gethostname to store the '\0'? */
3773 if (strlen (hostname) < hostname_size - 1)
3774 break;
3775
3776 hostname_size <<= 1;
3777 hostname = (char *) xrealloc (hostname, hostname_size);
3778 }
3779 x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
3780 + strlen (hostname)
3781 + 2);
3782 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
3783 }
3784
3785 /* Figure out which modifier bits mean what. */
3786 x_find_modifier_meanings ();
3787
3788 /* Watch for PropertyNotify events on the root window; we use them
3789 to figure out when to invalidate our cache of the cut buffers. */
3790 x_watch_cut_buffer_cache ();
3791
3792 dup2 (ConnectionNumber (x_current_display), 0);
3793
3794 #ifndef SYSV_STREAMS
3795 /* Streams somehow keeps track of which descriptor number
3796 is being used to talk to X. So it is not safe to substitute
3797 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
3798 close (ConnectionNumber (x_current_display));
3799 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
3800 * check the def of the macro;
3801 * it is a genuine lvalue */
3802 #endif /* SYSV_STREAMS */
3803
3804 #endif /* ! defined (HAVE_X11) */
3805
3806 #ifdef F_SETOWN
3807 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
3808 #ifdef F_SETOWN_SOCK_NEG
3809 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
3810 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3811 fcntl (0, F_SETOWN, getpid ());
3812 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3813 #endif /* ! defined (F_SETOWN) */
3814
3815 #ifdef SIGIO
3816 init_sigio ();
3817 #endif /* ! defined (SIGIO) */
3818
3819 /* Must use interrupt input because we cannot otherwise
3820 arrange for C-g to be noticed immediately.
3821 We cannot connect it to SIGINT. */
3822 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3823
3824 expose_all_windows = 0;
3825
3826 clear_frame_hook = XTclear_frame;
3827 clear_end_of_line_hook = XTclear_end_of_line;
3828 ins_del_lines_hook = XTins_del_lines;
3829 change_line_highlight_hook = XTchange_line_highlight;
3830 insert_glyphs_hook = XTinsert_glyphs;
3831 write_glyphs_hook = XTwrite_glyphs;
3832 delete_glyphs_hook = XTdelete_glyphs;
3833 ring_bell_hook = XTring_bell;
3834 reset_terminal_modes_hook = XTreset_terminal_modes;
3835 set_terminal_modes_hook = XTset_terminal_modes;
3836 update_begin_hook = XTupdate_begin;
3837 update_end_hook = XTupdate_end;
3838 set_terminal_window_hook = XTset_terminal_window;
3839 read_socket_hook = XTread_socket;
3840 cursor_to_hook = XTcursor_to;
3841 reassert_line_highlight_hook = XTreassert_line_highlight;
3842 frame_rehighlight_hook = XTframe_rehighlight;
3843 mouse_position_hook = XTmouse_position;
3844
3845 scroll_region_ok = 1; /* we'll scroll partial frames */
3846 char_ins_del_ok = 0; /* just as fast to write the line */
3847 line_ins_del_ok = 1; /* we'll just blt 'em */
3848 fast_clear_end_of_line = 1; /* X does this well */
3849 memory_below_frame = 0; /* we don't remember what scrolls
3850 off the bottom */
3851 baud_rate = 19200;
3852
3853 /* Note that there is no real way portable across R3/R4 to get the
3854 original error handler. */
3855 XHandleError (x_error_quitter);
3856 XHandleIOError (x_error_quitter);
3857
3858 /* Disable Window Change signals; they are handled by X events. */
3859 #ifdef SIGWINCH
3860 signal (SIGWINCH, SIG_DFL);
3861 #endif /* ! defined (SIGWINCH) */
3862
3863 signal (SIGPIPE, x_connection_closed);
3864 }
3865
3866 void
3867 syms_of_xterm ()
3868 {
3869 staticpro (&invocation_name);
3870 invocation_name = Qnil;
3871 }
3872 #endif /* ! defined (HAVE_X11) */
3873 #endif /* ! defined (HAVE_X_WINDOWS) */