]> code.delx.au - gnu-emacs/blob - src/xterm.c
* xterm.c (x_make_frame_invisible): Don't forget to check the
[gnu-emacs] / 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 this loses if it comes after xterm.h. */
35 #include <signal.h>
36
37 /* This may include sys/types.h, and that somehow loses
38 if this is not done before the other system files. */
39 #include "xterm.h"
40
41 #ifndef USG
42 /* Load sys/types.h if not already loaded.
43 In some systems loading it twice is suicidal. */
44 #ifndef makedev
45 #include <sys/types.h>
46 #endif /* makedev */
47 #endif /* USG */
48
49 #ifdef BSD
50 #include <sys/ioctl.h>
51 #include <strings.h>
52 #else /* ! defined (BSD) */
53 #include <sys/termio.h>
54 #include <string.h>
55 #endif /* ! defined (BSD) */
56
57 /* Allow m- file to inhibit use of FIONREAD. */
58 #ifdef BROKEN_FIONREAD
59 #undef FIONREAD
60 #endif /* ! defined (BROKEN_FIONREAD) */
61
62 /* We are unable to use interrupts if FIONREAD is not available,
63 so flush SIGIO so we won't try. */
64 #ifndef FIONREAD
65 #ifdef SIGIO
66 #undef SIGIO
67 #endif /* ! defined (SIGIO) */
68 #endif /* FIONREAD */
69
70 #include "systime.h"
71
72 #include <fcntl.h>
73 #include <stdio.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->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 /* Convert a set of X modifier bits to the proper form for a
1432 struct input_event modifiers value. */
1433
1434 static Lisp_Object
1435 x_convert_modifiers (state)
1436 unsigned int state;
1437 {
1438 return ( ((state & (ShiftMask | LockMask)) ? shift_modifier : 0)
1439 | ((state & ControlMask) ? ctrl_modifier : 0)
1440 | ((state & Mod1Mask) ? meta_modifier : 0));
1441 }
1442
1443 extern struct frame *x_window_to_scrollbar ();
1444 extern Lisp_Object Vmouse_event;
1445
1446 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1447
1448 If the event is a button press, then note that we have grabbed
1449 the mouse.
1450
1451 If PART and PREFIX are 0, then the event occurred in the text part;
1452 otherwise it happened in a scrollbar. */
1453
1454 static Lisp_Object
1455 construct_mouse_click (result, event, f, part, prefix)
1456 struct input_event *result;
1457 XButtonEvent *event;
1458 struct frame *f;
1459 int prefix;
1460 Lisp_Object part;
1461 {
1462 /* Initialize those fields text and scrollbar clicks hold in common.
1463 Make the event type no_event; we'll change that when we decide
1464 otherwise. */
1465 result->kind = no_event;
1466 XSET (result->code, Lisp_Int, event->button);
1467 result->timestamp = event->time;
1468 result->modifiers = (x_convert_modifiers (event->state)
1469 | (event->type == ButtonRelease ? up_modifier : 0));
1470
1471 /* Notice if the mouse is still grabbed. */
1472 if (event->type == ButtonPress)
1473 {
1474 if (! x_mouse_grabbed)
1475 Vmouse_depressed = Qt;
1476 x_mouse_grabbed |= (1 << event->button);
1477 }
1478 else if (event->type == ButtonRelease)
1479 {
1480 x_mouse_grabbed &= ~(1 << event->button);
1481 if (!x_mouse_grabbed)
1482 Vmouse_depressed = Qnil;
1483 }
1484
1485 if (part) /* Scrollbar event */
1486 {
1487 int pos, len;
1488
1489 pos = event->y - (f->display.x->v_scrollbar_width - 2);
1490 XSET (x_mouse_x, Lisp_Int, pos);
1491 len = ((FONT_HEIGHT (f->display.x->font) * f->height)
1492 + f->display.x->internal_border_width
1493 - (2 * (f->display.x->v_scrollbar_width - 2)));
1494 XSET (x_mouse_y, Lisp_Int, len);
1495
1496 result->kind = scrollbar_click;
1497 result->part = part;
1498 XSET (result->x, Lisp_Int, (f->display.x->top_pos - event->y));
1499 XSET (result->y, Lisp_Int, f->display.x->pixel_height);
1500 result->frame = f;
1501 }
1502 else /* Text Window Event */
1503 {
1504 int row, column;
1505
1506 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL);
1507 result->kind = mouse_click;
1508 result->x = column;
1509 result->y = row;
1510 result->frame = f;
1511 }
1512 }
1513
1514
1515 /* Mouse movement. Rah.
1516
1517 In order to avoid asking for motion events and then throwing most
1518 of them away or busy-polling the server for mouse positions, we ask
1519 the server for pointer motion hints. This means that we get only
1520 one event per group of mouse movements. "Groups" are delimited by
1521 other kinds of events (focus changes and button clicks, for
1522 example), or by XQueryPointer calls; when one of these happens, we
1523 get another MotionNotify event the next time the mouse moves. This
1524 is at least as efficient as getting motion events when mouse
1525 tracking is on, and I suspect only negligibly worse when tracking
1526 is off.
1527
1528 The silly O'Reilly & Associates Nutshell guides barely document
1529 pointer motion hints at all (I think you have to infer how they
1530 work from an example), and the description of XQueryPointer doesn't
1531 mention that calling it causes you to get another motion hint from
1532 the server, which is very important. */
1533
1534 /* Where the mouse was last time we reported a mouse event. */
1535 static FRAME_PTR last_mouse_frame;
1536 static XRectangle last_mouse_glyph;
1537
1538 /* This is a hack. We would really prefer that XTmouse_position would
1539 return the time associated with the position it returns, but there
1540 doesn't seem to be any way to wrest the timestamp from the server
1541 along with the position query. So, we just keep track of the time
1542 of the last movement we received, and return that in hopes that
1543 it's somewhat accurate. */
1544 static Time last_mouse_movement_time;
1545
1546 /* Function to report a mouse movement to the mainstream Emacs code.
1547 The input handler calls this.
1548
1549 We have received a mouse movement event, which is given in *event.
1550 If the mouse is over a different glyph than it was last time, tell
1551 the mainstream emacs code by setting mouse_moved. If not, ask for
1552 another motion event, so we can check again the next time it moves. */
1553 static void
1554 note_mouse_position (frame, event)
1555 FRAME_PTR frame;
1556 XMotionEvent *event;
1557
1558 {
1559 last_mouse_movement_time = event->time;
1560
1561 /* Has the mouse moved off the glyph it was on at the last sighting? */
1562 if (event->x < last_mouse_glyph.x
1563 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1564 || event->y < last_mouse_glyph.y
1565 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1566 mouse_moved = 1;
1567 else
1568 {
1569 /* It's on the same glyph. Call XQueryPointer so we'll get an
1570 event the next time the mouse moves and we can see if it's
1571 *still* on the same glyph. */
1572 int dummy;
1573
1574 XQueryPointer (event->display, event->window,
1575 (Window *) &dummy, (Window *) &dummy,
1576 &dummy, &dummy, &dummy, &dummy,
1577 (unsigned int *) &dummy);
1578 }
1579 }
1580
1581 /* Return the current position of the mouse.
1582
1583 This clears the mouse_moved flag, so we can wait for the next mouse
1584 position. This also calls XQueryPointer, which will cause the
1585 server to give us another MotionNotify when the mouse moves again.
1586 */
1587
1588 static void
1589 XTmouse_position (f, x, y, time)
1590 FRAME_PTR *f;
1591 Lisp_Object *x, *y;
1592 unsigned long *time;
1593 {
1594 int ix, iy, dummy;
1595 Display *d = x_current_display;
1596 Window guess, root, child;
1597
1598 BLOCK_INPUT;
1599
1600 /* I would like to have an X function that just told me the
1601 innermost window containing the mouse.
1602
1603 /* There doesn't seem to be any way to just get the innermost window
1604 containing the pointer, no matter what X frame it's on; you have
1605 to guess a window, and then X will tell you which one of that
1606 window's children it's in. If the pointer isn't in any of that
1607 window's children, it gives you a root window that contains it.
1608
1609 So we start with the selected frame's window and chase down
1610 branches under the guidance of XQueryPointer until we hit a leaf
1611 (all of the Emacs windows we care about are leaf windows). If at
1612 any time XQueryPointer returns false, that means that the current
1613 window does not contain the pointer any more (perhaps it moved),
1614 so we start with the root window XQueryPointer has given us and
1615 start again. */
1616
1617 guess = FRAME_X_WINDOW (selected_frame);
1618 for (;;)
1619 if (XQueryPointer (d, guess, &root, &child,
1620 &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy))
1621 {
1622 if (child == None)
1623 /* Guess is a leaf window, and it contains the pointer. */
1624 break;
1625 else
1626 guess = child;
1627 }
1628 else
1629 /* When XQueryPointer returns False, the pointer isn't in guess
1630 anymore, but root is the root window of the frame we should
1631 try instead. */
1632 guess = root;
1633
1634 *f = last_mouse_frame = x_window_to_frame (guess);
1635 if (! *f)
1636 *x = *y = Qnil;
1637 else
1638 {
1639 pixel_to_glyph_coords (*f, ix, iy, &ix, &iy, &last_mouse_glyph);
1640 XSET (*x, Lisp_Int, ix);
1641 XSET (*y, Lisp_Int, iy);
1642 }
1643
1644 mouse_moved = 0;
1645
1646 /* I don't know how to find the time for the last movement; it seems
1647 like XQueryPointer ought to return it, but it doesn't. So, we'll
1648 return the time of the last MotionNotify event we received. Note
1649 that the use of motion hints means that this isn't guaranteed to
1650 be accurate at all. */
1651 *time = last_mouse_movement_time;
1652
1653 UNBLOCK_INPUT;
1654 }
1655
1656 #else /* ! defined (HAVE_X11) */
1657 #define XEvent XKeyPressedEvent
1658 #endif /* ! defined (HAVE_X11) */
1659 \f
1660
1661 /* Timestamp of enter window event. This is only used by XTread_socket,
1662 but we have to put it out here, since static variables within functions
1663 sometimes don't work. */
1664 static Time enter_timestamp;
1665
1666 /* Communication with window managers. */
1667 Atom Xatom_wm_protocols;
1668
1669 /* Kinds of protocol things we may receive. */
1670 Atom Xatom_wm_take_focus;
1671 Atom Xatom_wm_save_yourself;
1672 Atom Xatom_wm_delete_window;
1673
1674 /* Other WM communication */
1675 Atom Xatom_wm_configure_denied; /* When our config request is denied */
1676 Atom Xatom_wm_window_moved; /* When the WM moves us. */
1677
1678 /* Read events coming from the X server.
1679 This routine is called by the SIGIO handler.
1680 We return as soon as there are no more events to be read.
1681
1682 Events representing keys are stored in buffer BUFP,
1683 which can hold up to NUMCHARS characters.
1684 We return the number of characters stored into the buffer,
1685 thus pretending to be `read'.
1686
1687 WAITP is nonzero if we should block until input arrives.
1688 EXPECTED is nonzero if the caller knows input is available. */
1689
1690 Lisp_Object
1691 XTread_socket (sd, bufp, numchars, waitp, expected)
1692 register int sd;
1693 register struct input_event *bufp;
1694 register int numchars;
1695 int waitp;
1696 int expected;
1697 {
1698 int count = 0;
1699 int nbytes = 0;
1700 int mask;
1701 int items_pending; /* How many items are in the X queue. */
1702 XEvent event;
1703 struct frame *f;
1704 int event_found;
1705 int prefix;
1706 Lisp_Object part;
1707
1708 if (x_input_blocked)
1709 {
1710 x_pending_input = 1;
1711 return -1;
1712 }
1713
1714 x_pending_input = 0;
1715 BLOCK_INPUT;
1716
1717 if (numchars <= 0)
1718 abort (); /* Don't think this happens. */
1719
1720 #ifdef FIOSNBIO
1721 /* If available, Xlib uses FIOSNBIO to make the socket
1722 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
1723 FIOSNBIO is ignored, and instead of signalling EWOULDBLOCK,
1724 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
1725 fcntl (fileno (stdin), F_SETFL, 0);
1726 #endif /* ! defined (FIOSNBIO) */
1727
1728 #ifndef SIGIO
1729 #ifndef HAVE_SELECT
1730 if (! (fcntl (fileno (stdin), F_GETFL, 0) & O_NDELAY))
1731 {
1732 extern int read_alarm_should_throw;
1733 read_alarm_should_throw = 1;
1734 XPeekEvent (XDISPLAY &event);
1735 read_alarm_should_throw = 0;
1736 }
1737 #endif /* HAVE_SELECT */
1738 #endif /* SIGIO */
1739
1740 while (XStuffPending () != 0)
1741 {
1742 XNextEvent (XDISPLAY &event);
1743 event_found = 1;
1744
1745 switch (event.type)
1746 {
1747 #ifdef HAVE_X11
1748 case ClientMessage:
1749 {
1750 if (event.xclient.message_type == Xatom_wm_protocols
1751 && event.xclient.format == 32)
1752 {
1753 if (event.xclient.data.l[0] == Xatom_wm_take_focus)
1754 {
1755 f = x_window_to_frame (event.xclient.window);
1756 if (f)
1757 x_focus_on_frame (f);
1758 /* Not certain about handling scrollbars here */
1759 }
1760 else if (event.xclient.data.l[0] == Xatom_wm_save_yourself)
1761 {
1762 /* Save state modify the WM_COMMAND property to
1763 something which can reinstate us. This notifies
1764 the session manager, who's looking for such a
1765 PropertyNotify. Can restart processing when
1766 a keyboard or mouse event arrives. */
1767 if (numchars > 0)
1768 {
1769 }
1770 }
1771 else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
1772 {
1773 struct frame *f = x_window_to_frame (event.xclient.window);
1774
1775 if (f)
1776 if (numchars > 0)
1777 {
1778 }
1779 }
1780 }
1781 else if (event.xclient.message_type == Xatom_wm_configure_denied)
1782 {
1783 }
1784 else if (event.xclient.message_type == Xatom_wm_window_moved)
1785 {
1786 int new_x, new_y;
1787
1788 new_x = event.xclient.data.s[0];
1789 new_y = event.xclient.data.s[1];
1790 }
1791 }
1792 break;
1793
1794 case SelectionClear: /* Someone has grabbed ownership. */
1795 x_disown_selection (event.xselectionclear.window,
1796 event.xselectionclear.selection,
1797 event.xselectionclear.time);
1798 break;
1799
1800 case SelectionRequest: /* Someone wants our selection. */
1801 x_answer_selection_request (event);
1802 break;
1803
1804 case PropertyNotify:
1805 /* If we were to do this synchronously, there'd be no worry
1806 about re-selecting. */
1807 x_send_incremental (event);
1808 break;
1809
1810 case Expose:
1811 f = x_window_to_frame (event.xexpose.window);
1812 if (f)
1813 {
1814 if (f->visible == 0)
1815 {
1816 f->visible = 1;
1817 f->iconified = 0;
1818 SET_FRAME_GARBAGED (f);
1819 }
1820 else
1821 dumprectangle (x_window_to_frame (event.xexpose.window),
1822 event.xexpose.x, event.xexpose.y,
1823 event.xexpose.width, event.xexpose.height);
1824 }
1825 break;
1826
1827 case GraphicsExpose: /* This occurs when an XCopyArea's
1828 source area was obscured or not
1829 available.*/
1830 dumprectangle (x_window_to_frame (event.xgraphicsexpose.drawable),
1831 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
1832 event.xgraphicsexpose.width,
1833 event.xgraphicsexpose.height);
1834 break;
1835
1836 case NoExpose: /* This occurs when an XCopyArea's
1837 source area was completely
1838 available */
1839 break;
1840 #else /* ! defined (HAVE_X11) */
1841 case ExposeWindow:
1842 if (event.subwindow != 0)
1843 break; /* duplicate event */
1844 f = x_window_to_frame (event.window);
1845 if (event.window == f->display.x->icon_desc)
1846 {
1847 refreshicon (f);
1848 f->iconified = 1;
1849 }
1850 if (event.window == FRAME_X_WINDOW (f))
1851 {
1852 /* Say must check all windows' needs_exposure flags. */
1853 expose_all_windows = 1;
1854 f->display.x->needs_exposure = 1;
1855 f->visible = 1;
1856 }
1857 break;
1858
1859 case ExposeRegion:
1860 if (event.subwindow != 0)
1861 break; /* duplicate event */
1862 f = x_window_to_frame (event.window);
1863 if (event.window == f->display.x->icon_desc)
1864 {
1865 refreshicon (f);
1866 break;
1867 }
1868 /* If window already needs full redraw, ignore this rectangle. */
1869 if (expose_all_windows && f->display.x->needs_exposure)
1870 break;
1871 /* Put the event on the queue of rectangles to redraw. */
1872 if (enqueue_event (&event, &x_expose_queue))
1873 /* If it is full, we can't record the rectangle,
1874 so redraw this entire window. */
1875 {
1876 /* Say must check all windows' needs_exposure flags. */
1877 expose_all_windows = 1;
1878 f->display.x->needs_exposure = 1;
1879 }
1880 break;
1881
1882 case ExposeCopy:
1883 /* This should happen only when we are expecting it,
1884 in x_read_exposes. */
1885 abort ();
1886 #endif /* ! defined (HAVE_X11) */
1887
1888 #ifdef HAVE_X11
1889 case UnmapNotify:
1890 {
1891 XWMHints *hints;
1892
1893 f = x_window_to_frame (event.xunmap.window);
1894 if (f) /* F may no longer exist if
1895 the frame was deleted. */
1896 {
1897 /* While a frame is unmapped, display generation is
1898 disabled; you don't want to spend time updating a
1899 display that won't ever be seen. */
1900 f->visible = 0;
1901 x_mouse_x = x_mouse_y = -1;
1902 }
1903 }
1904 break;
1905
1906 case MapNotify:
1907 f = x_window_to_frame (event.xmap.window);
1908 if (f)
1909 {
1910 f->visible = 1;
1911 f->iconified = 0;
1912
1913 /* wait_reading_process_input will notice this and update
1914 the frame's display structures. */
1915 SET_FRAME_GARBAGED (f);
1916 }
1917 break;
1918
1919 /* Turn off processing if we become fully obscured. */
1920 case VisibilityNotify:
1921 break;
1922
1923 #else /* ! defined (HAVE_X11) */
1924 case UnmapWindow:
1925 f = x_window_to_frame (event.window);
1926 if (event.window == f->display.x->icon_desc)
1927 f->iconified = 0;
1928 if (event.window == FRAME_X_WINDOW (f))
1929 f->visible = 0;
1930 break;
1931 #endif /* ! defined (HAVE_X11) */
1932
1933 #ifdef HAVE_X11
1934 case KeyPress:
1935 f = x_window_to_frame (event.xkey.window);
1936 if (f != 0)
1937 {
1938 KeySym keysym;
1939 XComposeStatus status;
1940 char copy_buffer[80];
1941 int modifiers = event.xkey.state;
1942
1943 /* Some keyboards generate different characters
1944 depending on the state of the meta key, in an attempt
1945 to support non-English typists. It would be nice to
1946 keep this functionality somehow, but for now, we will
1947 just clear the meta-key flag to get the 'pure' character. */
1948 event.xkey.state &= ~Mod1Mask;
1949
1950 /* This will have to go some day... */
1951 nbytes = XLookupString (&event.xkey,
1952 copy_buffer,
1953 80,
1954 &keysym,
1955 &status);
1956
1957 /* Strip off the vendor-specific keysym bit, and take a shot
1958 at recognizing the codes. HP servers have extra keysyms
1959 that fit into the MiscFunctionKey category. */
1960 keysym &= ~(1<<28);
1961
1962 if (numchars > 1)
1963 {
1964 if (IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
1965 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < 0xff80 */
1966 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
1967 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */
1968 {
1969 bufp->kind = non_ascii_keystroke;
1970 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50);
1971 bufp->frame = f;
1972 bufp->modifiers = x_convert_modifiers (modifiers);
1973 bufp->timestamp = event.xkey.time;
1974 bufp++;
1975 count++;
1976 numchars--;
1977 }
1978 else if (numchars > nbytes)
1979 {
1980 register int i;
1981
1982 if (nbytes == 1)
1983 {
1984 if (modifiers & Mod1Mask)
1985 *copy_buffer |= METABIT;
1986 bufp->kind = ascii_keystroke;
1987 XSET (bufp->code, Lisp_Int, *copy_buffer);
1988 bufp->frame = f;
1989 bufp->timestamp = event.xkey.time;
1990 bufp++;
1991 }
1992 else
1993 for (i = nbytes - 1; i > 1; i--)
1994 {
1995 bufp->kind = ascii_keystroke;
1996 XSET (bufp->code, Lisp_Int, copy_buffer[i]);
1997 bufp->frame = f;
1998 bufp->timestamp = event.xkey.time;
1999 bufp++;
2000 }
2001
2002 count += nbytes;
2003 numchars -= nbytes;
2004 }
2005 }
2006 }
2007 break;
2008 #else /* ! defined (HAVE_X11) */
2009 case KeyPressed:
2010 {
2011 register char *where_mapping;
2012
2013 f = x_window_to_frame (event.window);
2014 /* Ignore keys typed on icon windows. */
2015 if (f != 0 && event.window == f->display.x->icon_desc)
2016 break;
2017 where_mapping = XLookupMapping (&event, &nbytes);
2018 /* Nasty fix for arrow keys */
2019 if (!nbytes && IsCursorKey (event.detail & 0xff))
2020 {
2021 switch (event.detail & 0xff)
2022 {
2023 case KC_CURSOR_LEFT:
2024 where_mapping = "\002";
2025 break;
2026 case KC_CURSOR_RIGHT:
2027 where_mapping = "\006";
2028 break;
2029 case KC_CURSOR_UP:
2030 where_mapping = "\020";
2031 break;
2032 case KC_CURSOR_DOWN:
2033 where_mapping = "\016";
2034 break;
2035 }
2036 nbytes = 1;
2037 }
2038 if (numchars - nbytes > 0)
2039 {
2040 register int i;
2041
2042 for (i = 0; i < nbytes; i++)
2043 {
2044 bufp->kind = ascii_keystroke;
2045 XSET (bufp->code, Lisp_Int, where_mapping[i]);
2046 XSET (bufp->time, Lisp_Int, event.xkey.time);
2047 bufp->frame = f;
2048 bufp++;
2049 }
2050 count += nbytes;
2051 numchars -= nbytes;
2052 }
2053 }
2054 break;
2055 #endif /* ! defined (HAVE_X11) */
2056
2057 #ifdef HAVE_X11
2058 case EnterNotify:
2059 f = x_window_to_frame (event.xcrossing.window);
2060
2061 if (event.xcrossing.detail == NotifyInferior) /* Left Scrollbar */
2062 ;
2063 else if (event.xcrossing.focus) /* Entered Window */
2064 {
2065 /* If we decide we want to generate an event to be seen
2066 by the rest of Emacs, we put it here. */
2067 struct input_event emacs_event;
2068 emacs_event.kind = no_event;
2069
2070 /* Avoid nasty pop/raise loops. */
2071 if (f && (!(f->auto_raise)
2072 || !(f->auto_lower)
2073 || (event.xcrossing.time - enter_timestamp) > 500))
2074 {
2075 x_new_focus_frame (f);
2076 enter_timestamp = event.xcrossing.time;
2077 }
2078 #if 0
2079 else if ((f = x_window_to_scrollbar (event.xcrossing.window,
2080 &part, &prefix)))
2081 /* Fake a motion event */
2082 notice_mouse_movement (&emacs_event,
2083 event.xmotion, f, scrollbar_window,
2084 part);
2085 #endif /* ! 0 */
2086
2087 #if 0
2088 if (! EQ (Vx_send_mouse_movement_events, Qnil)
2089 && numchars >= 1
2090 && emacs_event.kind != no_event)
2091 {
2092 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2093 bufp++;
2094 count++;
2095 numchars--;
2096 }
2097 #endif /* ! 0 */
2098 }
2099 else if (f == x_focus_frame)
2100 x_new_focus_frame (0);
2101 #if 0
2102 else if (f = x_window_to_frame (event.xcrossing.window))
2103 x_mouse_frame = f;
2104 #endif /* ! 0 */
2105
2106 break;
2107
2108 case FocusIn:
2109 f = x_window_to_frame (event.xfocus.window);
2110 if (f)
2111 x_new_focus_frame (f);
2112 break;
2113
2114 case LeaveNotify:
2115 if (event.xcrossing.detail != NotifyInferior
2116 && event.xcrossing.subwindow == None
2117 && event.xcrossing.mode == NotifyNormal)
2118 {
2119 f = x_window_to_frame (event.xcrossing.window);
2120
2121 if (event.xcrossing.focus)
2122 x_new_focus_frame (f);
2123 else if (f == x_focus_frame)
2124 x_new_focus_frame (0);
2125 }
2126 break;
2127
2128 case FocusOut:
2129 f = x_window_to_frame (event.xfocus.window);
2130 if (f && f == x_focus_frame)
2131 x_new_focus_frame (0);
2132 break;
2133
2134 #else /* ! defined (HAVE_X11) */
2135
2136 case EnterWindow:
2137 if ((event.detail & 0xFF) == 1)
2138 break; /* Coming from our own subwindow */
2139 if (event.subwindow != 0)
2140 break; /* Entering our own subwindow. */
2141
2142 {
2143 f = x_window_to_frame (event.window);
2144 x_mouse_frame = f;
2145
2146 x_new_focus_frame (f);
2147 }
2148 break;
2149
2150 case LeaveWindow:
2151 if ((event.detail & 0xFF) == 1)
2152 break; /* Entering our own subwindow */
2153 if (event.subwindow != 0)
2154 break; /* Leaving our own subwindow. */
2155
2156 x_mouse_frame = 0;
2157 if (x_focus_frame == 0
2158 && x_input_frame != 0
2159 && x_input_frame == x_window_to_frame (event.window)
2160 && event.window == FRAME_X_WINDOW (x_input_frame))
2161 {
2162 f = x_input_frame;
2163 x_input_frame = 0;
2164 if (f)
2165 frame_unhighlight (f);
2166 }
2167 break;
2168 #endif /* ! defined (HAVE_X11) */
2169
2170 #ifdef HAVE_X11
2171 case MotionNotify:
2172 {
2173 f = x_window_to_frame (event.xmotion.window);
2174 if (f)
2175 note_mouse_position (f, &event.xmotion);
2176 #if 0
2177 else if ((f = x_window_to_scrollbar (event.xmotion.window,
2178 &part, &prefix)))
2179 {
2180 What should go here?
2181 }
2182 #endif /* ! 0 */
2183 }
2184 break;
2185
2186 case ConfigureNotify:
2187 {
2188 int rows, columns;
2189 f = x_window_to_frame (event.xconfigure.window);
2190 if (!f)
2191 break;
2192
2193 columns = ((event.xconfigure.width -
2194 (2 * f->display.x->internal_border_width)
2195 - f->display.x->v_scrollbar_width)
2196 / FONT_WIDTH (f->display.x->font));
2197 rows = ((event.xconfigure.height -
2198 (2 * f->display.x->internal_border_width)
2199 - f->display.x->h_scrollbar_height)
2200 / FONT_HEIGHT (f->display.x->font));
2201
2202 /* Even if the number of character rows and columns has
2203 not changed, the font size may have changed, so we need
2204 to check the pixel dimensions as well. */
2205 if (columns != f->width
2206 || rows != f->height
2207 || event.xconfigure.width != f->display.x->pixel_width
2208 || event.xconfigure.height != f->display.x->pixel_height)
2209 {
2210 change_frame_size (f, rows, columns, 0, 1);
2211 x_resize_scrollbars (f);
2212 SET_FRAME_GARBAGED (f);
2213 }
2214
2215 f->display.x->pixel_width = event.xconfigure.width;
2216 f->display.x->pixel_height = event.xconfigure.height;
2217 f->display.x->left_pos = event.xconfigure.x;
2218 f->display.x->top_pos = event.xconfigure.y;
2219 break;
2220 }
2221
2222 case ButtonPress:
2223 case ButtonRelease:
2224 {
2225 /* If we decide we want to generate an event to be seen
2226 by the rest of Emacs, we put it here. */
2227 struct input_event emacs_event;
2228 emacs_event.kind = no_event;
2229
2230 f = x_window_to_frame (event.xbutton.window);
2231 if (f)
2232 if (!x_focus_frame || (f == x_focus_frame))
2233 construct_mouse_click (&emacs_event,
2234 &event, f, 0, 0);
2235 else
2236 continue;
2237 else
2238 if ((f = x_window_to_scrollbar (event.xbutton.window,
2239 &part, &prefix)))
2240 {
2241 if (!x_focus_frame || (selected_frame == x_focus_frame))
2242 construct_mouse_click (&emacs_event,
2243 &event, f, part, prefix);
2244 else
2245 continue;
2246 }
2247
2248 if (numchars >= 1 && emacs_event.kind != no_event)
2249 {
2250 bcopy (&emacs_event, bufp, sizeof (struct input_event));
2251 bufp++;
2252 count++;
2253 numchars--;
2254 }
2255 }
2256 break;
2257
2258 #else /* ! defined (HAVE_X11) */
2259 case ButtonPressed:
2260 case ButtonReleased:
2261 f = x_window_to_frame (event.window);
2262 if (f)
2263 {
2264 if (event.window == f->display.x->icon_desc)
2265 {
2266 x_make_frame_visible (f);
2267
2268 if (warp_mouse_on_deiconify)
2269 XWarpMouse (FRAME_X_WINDOW (f), 10, 10);
2270 break;
2271 }
2272 if (event.window == FRAME_X_WINDOW (f))
2273 {
2274 if (f->auto_raise)
2275 x_raise_frame (f);
2276 }
2277 }
2278 enqueue_event (&event, &x_mouse_queue);
2279 if (numchars >= 2)
2280 {
2281 bufp->kind = ascii_keystroke;
2282 bufp->code = (char) 'X' & 037; /* C-x */
2283 bufp->frame = f;
2284 XSET (bufp->time, Lisp_Int, event.xkey.time);
2285 bufp++;
2286
2287 bufp->kind = ascii_keystroke;
2288 bufp->code = (char) 0; /* C-@ */
2289 bufp->frame = f;
2290 XSET (bufp->time, Lisp_Int, event.xkey.time);
2291 bufp++;
2292
2293 count += 2;
2294 numchars -= 2;
2295 }
2296 break;
2297 #endif /* ! defined (HAVE_X11) */
2298
2299 #ifdef HAVE_X11
2300
2301 case CirculateNotify:
2302 break;
2303 case CirculateRequest:
2304 break;
2305
2306 #endif /* ! defined (HAVE_X11) */
2307
2308 case MappingNotify:
2309 if (event.xmapping.request == MappingKeyboard)
2310 /* Someone has changed the keyboard mapping - flush the
2311 local cache. */
2312 XRefreshKeyboardMapping (&event.xmapping);
2313 break;
2314
2315 default:
2316 break;
2317 }
2318 }
2319
2320 #if 0
2321 #ifdef HAVE_SELECT
2322 if (expected && ! event_found)
2323 {
2324 /* AOJ 880406: if select returns true but XPending doesn't, it means that
2325 there is an EOF condition; in other words, that X has died.
2326 Act as if there had been a hangup. */
2327
2328 int fd = ConnectionNumber (x_current_display);
2329 int mask = 1 << fd;
2330
2331 if (0 != select (fd + 1, &mask, (long *) 0, (long *) 0,
2332 (EMACS_TIME) 0)
2333 && !XStuffPending ())
2334 kill (getpid (), SIGHUP);
2335 }
2336 #endif /* ! defined (HAVE_SELECT) */
2337 #endif /* ! 0 */
2338
2339 if (updating_frame == 0)
2340 x_do_pending_expose ();
2341
2342 UNBLOCK_INPUT;
2343 return count;
2344 }
2345
2346 #ifndef HAVE_X11
2347 /* Read and process only Expose events
2348 until we get an ExposeCopy event; then return.
2349 This is used in insert/delete line.
2350 We assume input is already blocked. */
2351
2352 static void
2353 x_read_exposes ()
2354 {
2355 struct frame *f;
2356 XKeyPressedEvent event;
2357
2358 while (1)
2359 {
2360 /* while there are more events*/
2361 XMaskEvent (ExposeWindow | ExposeRegion | ExposeCopy, &event);
2362 switch (event.type)
2363 {
2364 case ExposeWindow:
2365 if (event.subwindow != 0)
2366 break; /* duplicate event */
2367 f = x_window_to_frame (event.window);
2368 if (event.window == f->display.x->icon_desc)
2369 {
2370 refreshicon (f);
2371 break;
2372 }
2373 if (event.window == FRAME_X_WINDOW (f))
2374 {
2375 expose_all_windows = 1;
2376 f->display.x->needs_exposure = 1;
2377 break;
2378 }
2379 break;
2380
2381 case ExposeRegion:
2382 if (event.subwindow != 0)
2383 break; /* duplicate event */
2384 f = x_window_to_frame (event.window);
2385 if (event.window == f->display.x->icon_desc)
2386 {
2387 refreshicon (f);
2388 break;
2389 }
2390 /* If window already needs full redraw, ignore this rectangle. */
2391 if (expose_all_windows && f->display.x->needs_exposure)
2392 break;
2393 /* Put the event on the queue of rectangles to redraw. */
2394 if (enqueue_event (&event, &x_expose_queue))
2395 /* If it is full, we can't record the rectangle,
2396 so redraw this entire window. */
2397 {
2398 /* Say must check all windows' needs_exposure flags. */
2399 expose_all_windows = 1;
2400 f->display.x->needs_exposure = 1;
2401 }
2402 break;
2403
2404 case ExposeCopy:
2405 return;
2406 }
2407 }
2408 }
2409 #endif /* HAVE_X11 */
2410
2411 \f
2412 /* Draw a hollow box cursor. Don't change the inside of the box. */
2413
2414 static void
2415 x_draw_box (f)
2416 struct frame *f;
2417 {
2418 int left = f->cursor_x * FONT_WIDTH (f->display.x->font)
2419 + f->display.x->internal_border_width;
2420 int top = f->cursor_y * FONT_HEIGHT (f->display.x->font)
2421 + f->display.x->internal_border_width;
2422 int width = FONT_WIDTH (f->display.x->font);
2423 int height = FONT_HEIGHT (f->display.x->font);
2424
2425 #ifdef HAVE_X11
2426 /* Perhaps we should subtract 1 from width and height... */
2427 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f),
2428 f->display.x->cursor_gc,
2429 left, top, width - 1, height - 1);
2430 #else /* ! defined (HAVE_X11) */
2431 XPixSet (FRAME_X_WINDOW (f),
2432 left, top, width, 1,
2433 f->display.x->cursor_pixel);
2434
2435 XPixSet (FRAME_X_WINDOW (f),
2436 left, top, 1, height,
2437 f->display.x->cursor_pixel);
2438
2439 XPixSet (FRAME_X_WINDOW (f),
2440 left+width-1, top, 1, height,
2441 f->display.x->cursor_pixel);
2442
2443 XPixSet (FRAME_X_WINDOW (f),
2444 left, top+height-1, width, 1,
2445 f->display.x->cursor_pixel);
2446 #endif /* ! defined (HAVE_X11) */
2447 }
2448
2449 /* Clear the cursor of frame F to background color,
2450 and mark the cursor as not shown.
2451 This is used when the text where the cursor is
2452 is about to be rewritten. */
2453
2454 static void
2455 clear_cursor (f)
2456 struct frame *f;
2457 {
2458 int mask;
2459
2460 if (! f->visible
2461 || f->phys_cursor_x < 0)
2462 return;
2463
2464 #ifdef HAVE_X11
2465 x_display_cursor (f, 0);
2466 #if 0
2467 XClearArea (x_current_display, FRAME_X_WINDOW (f),
2468 f->phys_cursor_x * FONT_WIDTH (f->display.x->font)
2469 + f->display.x->internal_border_width,
2470 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font)
2471 + f->display.x->internal_border_width,
2472 FONT_WIDTH (f->display.x->font) + 1, FONT_HEIGHT (f->display.x->font) + 1, False);
2473 #endif /* ! 0 */
2474 #else /* ! defined (HAVE_X11) */
2475 XPixSet (FRAME_X_WINDOW (f),
2476 f->phys_cursor_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width,
2477 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width,
2478 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font),
2479 f->display.x->background_pixel);
2480 #endif /* ! defined (HAVE_X11) */
2481 f->phys_cursor_x = -1;
2482 }
2483
2484 static void
2485 x_display_bar_cursor (f, on)
2486 struct frame *f;
2487 int on;
2488 {
2489 register int phys_x = f->phys_cursor_x;
2490 register int phys_y = f->phys_cursor_y;
2491 register int x1;
2492 register int y1;
2493 register int y2;
2494
2495 if (! f->visible || (! on && f->phys_cursor_x < 0))
2496 return;
2497
2498 #ifdef HAVE_X11
2499 if (phys_x >= 0 &&
2500 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y))
2501 {
2502 x1 = phys_x * FONT_WIDTH (f->display.x->font)
2503 + f->display.x->internal_border_width;
2504 y1 = phys_y * FONT_HEIGHT (f->display.x->font)
2505 + f->display.x->internal_border_width - 1;
2506 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1;
2507
2508 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
2509 f->display.x->reverse_gc, x1, y1, x1, y2);
2510
2511 f->phys_cursor_x = phys_x = -1;
2512 }
2513
2514 if (on && f == x_highlight_frame)
2515 {
2516 x1 = f->cursor_x * FONT_WIDTH (f->display.x->font)
2517 + f->display.x->internal_border_width;
2518 y1 = f->cursor_y * FONT_HEIGHT (f->display.x->font)
2519 + f->display.x->internal_border_width - 1;
2520 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1;
2521
2522 XDrawLine (x_current_display, FRAME_X_WINDOW (f),
2523 f->display.x->cursor_gc, x1, y1, x1, y2);
2524
2525 f->phys_cursor_x = f->cursor_x;
2526 f->phys_cursor_y = f->cursor_y;
2527 }
2528 #else /* ! defined (HAVE_X11) */
2529 Give it up, dude.
2530 #endif /* ! defined (HAVE_X11) */
2531 }
2532
2533
2534 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
2535 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
2536 glyph drawn. */
2537
2538 static void
2539 x_draw_single_glyph (f, row, column, glyph, highlight)
2540 struct frame *f;
2541 int row, column;
2542 GLYPH glyph;
2543 int highlight;
2544 {
2545 dumpglyphs (f,
2546 (column * FONT_WIDTH (f->display.x->font)
2547 + f->display.x->internal_border_width),
2548 (row * FONT_HEIGHT (f->display.x->font)
2549 + f->display.x->internal_border_width),
2550 &glyph, 1, highlight, f->display.x->font);
2551 }
2552
2553 /* Turn the displayed cursor of frame F on or off according to ON.
2554 If ON is nonzero, where to put the cursor is specified
2555 by F->cursor_x and F->cursor_y. */
2556
2557 static void
2558 x_display_box_cursor (f, on)
2559 struct frame *f;
2560 int on;
2561 {
2562 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
2563
2564 /* If we're not updating, then we want to use the current frame's
2565 cursor position, not our local idea of where the cursor ought to be. */
2566 if (f != updating_frame)
2567 {
2568 curs_x = FRAME_CURSOR_X (f);
2569 curs_y = FRAME_CURSOR_Y (f);
2570 }
2571
2572 if (! f->visible)
2573 return;
2574
2575 /* If cursor is off and we want it off, return quickly. */
2576 if (!on && f->phys_cursor_x < 0)
2577 return;
2578
2579 /* If cursor is currently being shown and we don't want it to be
2580 or it is in the wrong place,
2581 or we want a hollow box and it's not so, (pout!)
2582 erase it. */
2583 if (f->phys_cursor_x >= 0
2584 && (!on
2585 || f->phys_cursor_x != curs_x
2586 || f->phys_cursor_y != curs_y
2587 || (f->display.x->text_cursor_kind != hollow_box_cursor
2588 && (f != x_highlight_frame))))
2589 {
2590 /* Erase the cursor by redrawing the character underneath it. */
2591 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
2592 f->phys_cursor_glyph,
2593 current_glyphs->highlight[f->phys_cursor_y]);
2594 f->phys_cursor_x = -1;
2595 }
2596
2597 /* If we want to show a cursor,
2598 or we want a box cursor and it's not so,
2599 write it in the right place. */
2600 if (on
2601 && (f->phys_cursor_x < 0
2602 || (f->display.x->text_cursor_kind != filled_box_cursor
2603 && f == x_highlight_frame)))
2604 {
2605 f->phys_cursor_glyph
2606 = ((current_glyphs->enable[curs_y]
2607 && curs_x < current_glyphs->used[curs_y])
2608 ? current_glyphs->glyphs[curs_y][curs_x]
2609 : SPACEGLYPH);
2610 if (f != x_highlight_frame)
2611 {
2612 x_draw_box (f);
2613 f->display.x->text_cursor_kind = hollow_box_cursor;
2614 }
2615 else
2616 {
2617 x_draw_single_glyph (f, curs_y, curs_x,
2618 f->phys_cursor_glyph, 2);
2619 f->display.x->text_cursor_kind = filled_box_cursor;
2620 }
2621
2622 f->phys_cursor_x = curs_x;
2623 f->phys_cursor_y = curs_y;
2624 }
2625
2626 if (updating_frame != f)
2627 XFlushQueue ();
2628 }
2629
2630 extern Lisp_Object Vbar_cursor;
2631
2632 x_display_cursor (f, on)
2633 struct frame *f;
2634 int on;
2635 {
2636 if (EQ (Vbar_cursor, Qnil))
2637 x_display_box_cursor (f, on);
2638 else
2639 x_display_bar_cursor (f, on);
2640 }
2641 \f
2642 /* Icons. */
2643
2644 /* Refresh bitmap kitchen sink icon for frame F
2645 when we get an expose event for it. */
2646
2647 refreshicon (f)
2648 struct frame *f;
2649 {
2650 #ifdef HAVE_X11
2651 /* Normally, the window manager handles this function. */
2652 #else /* ! defined (HAVE_X11) */
2653 int mask;
2654
2655 if (f->display.x->icon_bitmap_flag)
2656 XBitmapBitsPut (f->display.x->icon_desc, 0, 0, sink_width, sink_height,
2657 sink_bits, BlackPixel, WHITE_PIX_DEFAULT,
2658 icon_bitmap, GXcopy, AllPlanes);
2659 else
2660 {
2661 extern struct frame *selected_frame;
2662 struct Lisp_String *str;
2663 unsigned char *string;
2664
2665 string
2666 = XSTRING (XBUFFER (XWINDOW (f->selected_window)->buffer)->name)->data;
2667
2668 if (f->display.x->icon_label != string)
2669 {
2670 f->display.x->icon_label = string;
2671 XChangeWindow (f->display.x->icon_desc,
2672 XQueryWidth (string, icon_font_info->id) + 10,
2673 icon_font_info->height + 10);
2674 }
2675
2676 XText (f->display.x->icon_desc, 5, 5, string,
2677 str->size, icon_font_info->id,
2678 BLACK_PIX_DEFAULT, WHITE_PIX_DEFAULT);
2679 }
2680 XFlushQueue ();
2681 #endif /* ! defined (HAVE_X11) */
2682 }
2683
2684 /* Make the x-window of frame F use the kitchen-sink icon
2685 that's a window generated by Emacs. */
2686
2687 int
2688 x_bitmap_icon (f)
2689 struct frame *f;
2690 {
2691 int mask;
2692 Window icon_window;
2693
2694 if (FRAME_X_WINDOW (f) == 0)
2695 return 1;
2696
2697 #ifdef HAVE_X11
2698 if (icon_bitmap)
2699 XFreePixmap (x_current_display, icon_bitmap);
2700
2701 icon_bitmap =
2702 XCreateBitmapFromData (x_current_display, FRAME_X_WINDOW (f),
2703 gnu_bits, gnu_width, gnu_height);
2704 x_wm_set_icon_pixmap (f, icon_bitmap);
2705 f->display.x->icon_bitmap_flag = 1;
2706 #else /* ! defined (HAVE_X11) */
2707 if (f->display.x->icon_desc)
2708 {
2709 XClearIconWindow (FRAME_X_WINDOW (f));
2710 XDestroyWindow (f->display.x->icon_desc);
2711 }
2712
2713 icon_window = XCreateWindow (f->display.x->parent_desc,
2714 0, 0, sink_width, sink_height,
2715 2, WhitePixmap, (Pixmap) NULL);
2716
2717 if (icon_window == 0)
2718 return 1;
2719
2720 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
2721 XSelectInput (icon_window, ExposeWindow | UnmapWindow);
2722
2723 f->display.x->icon_desc = icon_window;
2724 f->display.x->icon_bitmap_flag = 1;
2725
2726 if (icon_bitmap == 0)
2727 icon_bitmap
2728 = XStoreBitmap (sink_mask_width, sink_mask_height, sink_mask_bits);
2729 #endif /* ! defined (HAVE_X11) */
2730
2731 return 0;
2732 }
2733
2734
2735 /* Make the x-window of frame F use a rectangle with text. */
2736
2737 int
2738 x_text_icon (f, icon_name)
2739 struct frame *f;
2740 char *icon_name;
2741 {
2742 #ifndef HAVE_X11
2743 int mask;
2744 int width;
2745 Window icon_window;
2746 char *X_DefaultValue;
2747 Bitmap b1;
2748
2749 #ifndef WhitePixel
2750 #define WhitePixel 1
2751 #endif /* WhitePixel */
2752
2753 #ifndef BlackPixel
2754 #define BlackPixel 0
2755 #endif /* BlackPixel */
2756 #endif /* HAVE_X11 */
2757
2758 if (FRAME_X_WINDOW (f) == 0)
2759 return 1;
2760
2761 if (icon_font_info == 0)
2762 icon_font_info
2763 = XGetFont (XGetDefault (XDISPLAY
2764 (char *) XSTRING (invocation_name)->data,
2765 "BodyFont"));
2766
2767 #ifdef HAVE_X11
2768 if (icon_name)
2769 f->display.x->icon_label = icon_name;
2770 else
2771 if (! f->display.x->icon_label)
2772 f->display.x->icon_label = " *emacs* ";
2773
2774 XSetIconName (x_current_display, FRAME_X_WINDOW (f),
2775 (char *) f->display.x->icon_label);
2776
2777 f->display.x->icon_bitmap_flag = 0;
2778 x_wm_set_icon_pixmap (f, 0);
2779 #else /* ! defined (HAVE_X11) */
2780 if (f->display.x->icon_desc)
2781 {
2782 XClearIconWindow (XDISPLAY FRAME_X_WINDOW (f));
2783 XDestroyWindow (XDISPLAY f->display.x->icon_desc);
2784 }
2785
2786 if (icon_name)
2787 f->display.x->icon_label = (unsigned char *) icon_name;
2788 else
2789 if (! f->display.x->icon_label)
2790 f->display.x->icon_label = XSTRING (f->name)->data;
2791
2792 width = XStringWidth (f->display.x->icon_label, icon_font_info, 0, 0);
2793 icon_window = XCreateWindow (f->display.x->parent_desc,
2794 f->display.x->left_pos,
2795 f->display.x->top_pos,
2796 width + 10, icon_font_info->height + 10,
2797 2, BlackPixmap, WhitePixmap);
2798
2799 if (icon_window == 0)
2800 return 1;
2801
2802 XSetIconWindow (FRAME_X_WINDOW (f), icon_window);
2803 XSelectInput (icon_window, ExposeWindow | ExposeRegion | UnmapWindow | ButtonPressed);
2804
2805 f->display.x->icon_desc = icon_window;
2806 f->display.x->icon_bitmap_flag = 0;
2807 f->display.x->icon_label = 0;
2808 #endif /* ! defined (HAVE_X11) */
2809
2810 return 0;
2811 }
2812 \f
2813 /* Handling X errors. */
2814
2815 /* A handler for SIGPIPE, when it occurs on the X server's connection.
2816 This basically does an orderly shutdown of Emacs. */
2817
2818 static SIGTYPE
2819 x_connection_closed ()
2820 {
2821 if (_Xdebug)
2822 abort ();
2823 else
2824 Fkill_emacs (make_number (70));
2825 }
2826
2827 /* An X error handler which prints an error message and then kills Emacs.
2828 This is what's normally installed as Xlib's handler for protocol and
2829 I/O errors. */
2830 static int
2831 x_error_quitter (display, error)
2832 Display *display;
2833 XErrorEvent *error;
2834 {
2835 char buf[256];
2836
2837 /* Note that there is no real way portable across R3/R4 to get the
2838 original error handler. */
2839
2840 XGetErrorText (display, error->error_code, buf, sizeof (buf));
2841 fprintf (stderr, "X protocol error: %s on protocol request %d\n",
2842 buf, error->request_code);
2843
2844 x_connection_closed ();
2845 }
2846
2847 /* A buffer for storing X error messages. */
2848 static char (*x_caught_error_message)[200];
2849
2850 /* An X error handler which stores the error message in
2851 x_caught_error_message. This is what's installed when
2852 x_catch_errors is in effect. */
2853 static int
2854 x_error_catcher (display, error)
2855 Display *display;
2856 XErrorEvent *error;
2857 {
2858 XGetErrorText (display, error->error_code,
2859 *x_caught_error_message, sizeof (*x_caught_error_message));
2860 }
2861
2862
2863 /* Begin trapping X errors.
2864
2865 After calling this function, X protocol errors no longer cause
2866 Emacs to exit; instead, they are recorded in x_cfc_error_message.
2867
2868 Calling x_check_errors signals an Emacs error if an X error has
2869 occurred since the last call to x_catch_errors or x_check_errors.
2870
2871 Calling x_uncatch_errors resumes the normal error handling. */
2872
2873 void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
2874
2875 void
2876 x_catch_errors ()
2877 {
2878 /* Make sure any errors from previous requests have been dealt with. */
2879 XSync (x_current_display, False);
2880
2881 /* Set up the error buffer. */
2882 x_caught_error_message =
2883 (char (*)[]) xmalloc (sizeof (*x_caught_error_message));
2884
2885 /* Install our little error handler. */
2886 XHandleError (x_error_catcher);
2887 }
2888
2889 /* If any X protocol errors have arrived since the last call to
2890 x_catch_errors or x_check_errors, signal an Emacs error using
2891 sprintf (a buffer, FORMAT, the x error message text) as the text. */
2892 void
2893 x_check_errors (format)
2894 char *format;
2895 {
2896 /* Make sure to catch any errors incurred so far. */
2897 XSync (x_current_display, False);
2898
2899 if ((*x_caught_error_message)[0])
2900 {
2901 char buf[256];
2902
2903 sprintf (buf, format, *x_caught_error_message);
2904 free (x_caught_error_message);
2905
2906 x_uncatch_errors ();
2907 error (buf);
2908 }
2909 }
2910
2911 void
2912 x_uncatch_errors ()
2913 {
2914 free (x_caught_error_message);
2915 XHandleError (x_error_quitter);
2916 }
2917
2918 #if 0
2919 static unsigned int x_wire_count;
2920 x_trace_wire ()
2921 {
2922 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
2923 }
2924 #endif /* ! 0 */
2925
2926 \f
2927 /* Set the font of the x-window specified by frame F
2928 to the font named NEWNAME. This is safe to use
2929 even before F has an actual x-window. */
2930
2931 #ifdef HAVE_X11
2932
2933 /* A table of all the fonts we have already loaded. */
2934 static XFontStruct **x_font_table;
2935
2936 /* The current capacity of x_font_table. */
2937 static int x_font_table_size;
2938
2939 /* The number of fonts actually stored in x_font_table.
2940 x_font_table[n] is used and valid iff 0 <= n < n_fonts.
2941 0 <= n_fonts <= x_font_table_size. */
2942 static int n_fonts;
2943
2944 x_new_font (f, fontname)
2945 struct frame *f;
2946 register char *fontname;
2947 {
2948 XFontStruct *temp;
2949 int already_loaded;
2950 int n_matching_fonts;
2951 XFontStruct *font_info;
2952 char **font_names;
2953
2954 /* Get a list of all the fonts that match this name. Once we
2955 have a list of matching fonts, we compare them against the fonts
2956 we already have by comparing font ids. */
2957 font_names = (char **) XListFontsWithInfo (x_current_display, fontname,
2958 1024, &n_matching_fonts,
2959 &font_info);
2960 /* If the server couldn't find any fonts whose named matched fontname,
2961 return an error code. */
2962 if (n_matching_fonts == 0)
2963 return 1;
2964
2965 /* See if we've already loaded a matching font. */
2966 {
2967 int i, j;
2968
2969 already_loaded = 0;
2970 for (i = 0; i < n_fonts; i++)
2971 for (j = 0; j < n_matching_fonts; j++)
2972 if (x_font_table[i]->fid == font_info[j].fid)
2973 {
2974 already_loaded = i;
2975 goto found_font;
2976 }
2977 }
2978 found_font:
2979
2980 /* If we have, just return it from the table. */
2981 if (already_loaded)
2982 f->display.x->font = x_font_table[already_loaded];
2983
2984 /* Otherwise, load the font and add it to the table. */
2985 else
2986 {
2987 XFontStruct *font;
2988
2989 font = (XFontStruct *) XLoadQueryFont (x_current_display, fontname);
2990 if (! font)
2991 return 1;
2992
2993 /* Do we need to create the table? */
2994 if (x_font_table_size == 0)
2995 {
2996 x_font_table_size = 16;
2997 x_font_table
2998 = (XFontStruct **) xmalloc (x_font_table_size
2999 * sizeof (x_font_table[0]));
3000 }
3001 /* Do we need to grow the table? */
3002 else if (n_fonts >= x_font_table_size)
3003 {
3004 x_font_table_size *= 2;
3005 x_font_table
3006 = (XFontStruct **) xrealloc (x_font_table,
3007 (x_font_table_size
3008 * sizeof (x_font_table[0])));
3009 }
3010
3011 f->display.x->font = x_font_table[n_fonts++] = font;
3012 }
3013
3014 /* Free the information from XListFontsWithInfo. The data
3015 we actually retain comes from XLoadQueryFont. */
3016 XFreeFontInfo (font_names, font_info, n_matching_fonts);
3017
3018 /* Now make the frame display the given font. */
3019 if (FRAME_X_WINDOW (f) != 0)
3020 {
3021 XSetFont (x_current_display, f->display.x->normal_gc,
3022 f->display.x->font->fid);
3023 XSetFont (x_current_display, f->display.x->reverse_gc,
3024 f->display.x->font->fid);
3025 XSetFont (x_current_display, f->display.x->cursor_gc,
3026 f->display.x->font->fid);
3027
3028 x_set_window_size (f, f->width, f->height);
3029 }
3030
3031 return 0;
3032 }
3033 #else /* ! defined (HAVE_X11) */
3034 x_new_font (f, newname)
3035 struct frame *f;
3036 register char *newname;
3037 {
3038 FONT_TYPE *temp;
3039 int mask;
3040
3041 temp = XGetFont (newname);
3042 if (temp == (FONT_TYPE *) 0)
3043 return 1;
3044
3045 if (f->display.x->font)
3046 XLoseFont (f->display.x->font);
3047
3048 f->display.x->font = temp;
3049
3050 if (FRAME_X_WINDOW (f) != 0)
3051 x_set_window_size (f, f->width, f->height);
3052
3053 return 0;
3054 }
3055 #endif /* ! defined (HAVE_X11) */
3056 \f
3057 x_calc_absolute_position (f)
3058 struct frame *f;
3059 {
3060 #ifdef HAVE_X11
3061 if (f->display.x->left_pos < 0)
3062 f->display.x->left_pos
3063 = XINT (x_screen_width) - PIXEL_WIDTH (f) + f->display.x->left_pos;
3064
3065 if (f->display.x->top_pos < 0)
3066 f->display.x->top_pos
3067 = XINT (x_screen_height) - PIXEL_HEIGHT (f) + f->display.x->top_pos;
3068 #else /* ! defined (HAVE_X11) */
3069 WINDOWINFO_TYPE parentinfo;
3070
3071 XGetWindowInfo (FRAME_X_WINDOW (f), &parentinfo);
3072
3073 if (f->display.x->left_pos < 0)
3074 f->display.x->left_pos = parentinfo.width + (f->display.x->left_pos + 1)
3075 - PIXEL_WIDTH (f) - 2 * f->display.x->internal_border_width;
3076
3077 if (f->display.x->top_pos < 0)
3078 f->display.x->top_pos = parentinfo.height + (f->display.x->top_pos + 1)
3079 - PIXEL_HEIGHT (f) - 2 * f->display.x->internal_border_width;
3080 #endif /* ! defined (HAVE_X11) */
3081 }
3082
3083 x_set_offset (f, xoff, yoff)
3084 struct frame *f;
3085 register int xoff, yoff;
3086 {
3087 f->display.x->top_pos = yoff;
3088 f->display.x->left_pos = xoff;
3089 x_calc_absolute_position (f);
3090
3091 BLOCK_INPUT;
3092 XMoveWindow (XDISPLAY FRAME_X_WINDOW (f),
3093 f->display.x->left_pos, f->display.x->top_pos);
3094 #ifdef HAVE_X11
3095 x_wm_set_size_hint (f, 0);
3096 #endif /* ! defined (HAVE_X11) */
3097 UNBLOCK_INPUT;
3098 }
3099
3100 /* Call this to change the size of frame F's x-window. */
3101
3102 x_set_window_size (f, cols, rows)
3103 struct frame *f;
3104 int cols, rows;
3105 {
3106 int pixelwidth, pixelheight;
3107 int mask;
3108 int ibw = f->display.x->internal_border_width;
3109
3110 BLOCK_INPUT;
3111
3112 check_frame_size (f, &rows, &cols);
3113 pixelwidth = (cols * FONT_WIDTH (f->display.x->font) + 2 * ibw
3114 + f->display.x->v_scrollbar_width);
3115 pixelheight = (rows * FONT_HEIGHT (f->display.x->font) + 2 * ibw
3116 + f->display.x->h_scrollbar_height);
3117
3118 #ifdef HAVE_X11
3119 x_wm_set_size_hint (f, 0);
3120 #endif /* ! defined (HAVE_X11) */
3121 XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
3122
3123 /* Now, strictly speaking, we can't be sure that this is accurate,
3124 but the window manager will get around to dealing with the size
3125 change request eventually, and we'll hear how it went when the
3126 ConfigureNotify event gets here. */
3127 FRAME_WIDTH (f) = cols;
3128 FRAME_WIDTH (f) = rows;
3129 PIXEL_WIDTH (f) = pixelwidth;
3130 PIXEL_HEIGHT (f) = pixelheight;
3131
3132 XFlushQueue ();
3133 UNBLOCK_INPUT;
3134 }
3135
3136 #ifndef HAVE_X11
3137 x_set_resize_hint (f)
3138 struct frame *f;
3139 {
3140
3141 XSetResizeHint (FRAME_X_WINDOW (f), 2 * f->display.x->internal_border_width,
3142 2 * f->display.x->internal_border_width,
3143 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font));
3144 }
3145 #endif /* HAVE_X11 */
3146 \f
3147
3148 x_set_mouse_position (f, x, y)
3149 struct frame *f;
3150 int x, y;
3151 {
3152 int pix_x, pix_y;
3153
3154 x_raise_frame (f);
3155
3156 if (x < 0)
3157 pix_x = (FRAME_WIDTH (f)
3158 * FONT_WIDTH (f->display.x->font)
3159 + 2 * f->display.x->internal_border_width
3160 + f->display.x->v_scrollbar_width) / 2;
3161 else
3162 pix_x = x * FONT_WIDTH (f->display.x->font) + 2; /* add 2 pixels to each
3163 dimension to move the
3164 mouse into the char
3165 cell */
3166
3167 if (y < 0)
3168 pix_y = (FRAME_HEIGHT (f)
3169 * FONT_HEIGHT (f->display.x->font)
3170 + 2 * f->display.x->internal_border_width
3171 + f->display.x->h_scrollbar_height) / 2;
3172 else
3173 pix_y = y * FONT_HEIGHT (f->display.x->font) + 2;
3174
3175 BLOCK_INPUT;
3176 x_mouse_x = x;
3177 x_mouse_y = y;
3178
3179 XWarpMousePointer (FRAME_X_WINDOW (f), pix_x, pix_y);
3180 UNBLOCK_INPUT;
3181 }
3182
3183 #ifdef HAVE_X11
3184 x_focus_on_frame (f)
3185 struct frame *f;
3186 {
3187 x_raise_frame (f);
3188 #if 0
3189 /* I don't think that the ICCCM allows programs to do things like this
3190 without the interaction of the window manager. Whatever you end up
3191 doing with this code, do it to x_unfocus_frame too. */
3192 XSetInputFocus (x_current_display, FRAME_X_WINDOW (f),
3193 RevertToPointerRoot, CurrentTime);
3194 #endif /* ! 0 */
3195 }
3196
3197 x_unfocus_frame (f)
3198 struct frame *f;
3199 {
3200 #if 0
3201 /* Look at the remarks in x_focus_on_frame. */
3202 if (x_focus_frame == f)
3203 XSetInputFocus (x_current_display, PointerRoot,
3204 RevertToPointerRoot, CurrentTime);
3205 #endif /* ! 0 */
3206 }
3207
3208 #endif /* ! defined (HAVE_X11) */
3209
3210 /* Raise frame F. */
3211
3212 x_raise_frame (f)
3213 struct frame *f;
3214 {
3215 if (f->visible)
3216 {
3217 BLOCK_INPUT;
3218 XRaiseWindow (XDISPLAY FRAME_X_WINDOW (f));
3219 XFlushQueue ();
3220 UNBLOCK_INPUT;
3221 }
3222 }
3223
3224 /* Lower frame F. */
3225
3226 x_lower_frame (f)
3227 struct frame *f;
3228 {
3229 if (f->visible)
3230 {
3231 BLOCK_INPUT;
3232 XLowerWindow (XDISPLAY FRAME_X_WINDOW (f));
3233 XFlushQueue ();
3234 UNBLOCK_INPUT;
3235 }
3236 }
3237
3238 /* Change from withdrawn state to mapped state. */
3239
3240 x_make_frame_visible (f)
3241 struct frame *f;
3242 {
3243 int mask;
3244
3245 BLOCK_INPUT;
3246
3247 if (! FRAME_VISIBLE_P (f))
3248 {
3249 #ifdef HAVE_X11
3250 if (! EQ (Vx_no_window_manager, Qt))
3251 x_wm_set_window_state (f, NormalState);
3252
3253 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3254 if (f->display.x->v_scrollbar != 0 || f->display.x->h_scrollbar != 0)
3255 XMapSubwindows (x_current_display, FRAME_X_WINDOW (f));
3256 #else /* ! defined (HAVE_X11) */
3257 XMapWindow (XDISPLAY FRAME_X_WINDOW (f));
3258 if (f->display.x->icon_desc != 0)
3259 XUnmapWindow (f->display.x->icon_desc);
3260
3261 /* Handled by the MapNotify event for X11 */
3262 f->visible = 1;
3263 f->iconified = 0;
3264
3265 /* NOTE: this may cause problems for the first frame. */
3266 XTcursor_to (0, 0);
3267 #endif /* ! defined (HAVE_X11) */
3268 }
3269
3270 XFlushQueue ();
3271
3272 UNBLOCK_INPUT;
3273 }
3274
3275 /* Change from mapped state to withdrawn state. */
3276
3277 x_make_frame_invisible (f)
3278 struct frame *f;
3279 {
3280 int mask;
3281
3282 if (! f->visible)
3283 return;
3284
3285 BLOCK_INPUT;
3286
3287 #ifdef HAVE_X11R4
3288
3289 if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
3290 DefaultScreen (x_current_display)))
3291 {
3292 UNBLOCK_INPUT_RESIGNAL;
3293 error ("can't notify window manager of window withdrawl");
3294 }
3295
3296 #else /* ! defined (HAVE_X11R4) */
3297 #ifdef HAVE_X11
3298
3299 /* Tell the window manager what we're going to do. */
3300 if (! EQ (Vx_no_window_manager, Qt))
3301 {
3302 XEvent unmap;
3303
3304 unmap.xunmap.type = UnmapNotify;
3305 unmap.xunmap.window = FRAME_X_WINDOW (f);
3306 unmap.xunmap.event = DefaultRootWindow (x_current_display);
3307 unmap.xunmap.from_configure = False;
3308 if (! XSendEvent (x_current_display,
3309 DefaultRootWindow (x_current_display),
3310 False,
3311 SubstructureRedirectMask|SubstructureNotifyMask,
3312 &unmap))
3313 {
3314 UNBLOCK_INPUT_RESIGNAL;
3315 error ("can't notify window manager of withdrawal");
3316 }
3317 }
3318
3319 /* Unmap the window ourselves. Cheeky! */
3320 XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
3321
3322 #else /* ! defined (HAVE_X11) */
3323
3324 XUnmapWindow (FRAME_X_WINDOW (f));
3325 f->visible = 0; /* Handled by the UnMap event for X11 */
3326 if (f->display.x->icon_desc != 0)
3327 XUnmapWindow (f->display.x->icon_desc);
3328
3329 #endif /* ! defined (HAVE_X11) */
3330 #endif /* ! defined (HAVE_X11R4) */
3331
3332 XFlushQueue ();
3333 UNBLOCK_INPUT;
3334 }
3335
3336 /* Window manager communication. Created in Fx_open_connection. */
3337 extern Atom Xatom_wm_change_state;
3338
3339 /* Change window state from mapped to iconified. */
3340
3341 x_iconify_frame (f)
3342 struct frame *f;
3343 {
3344 int mask;
3345
3346 if (f->iconified)
3347 return;
3348
3349 BLOCK_INPUT;
3350
3351 #ifdef HAVE_X11
3352 /* Since we don't know which revision of X we're running, we'll use both
3353 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
3354
3355 /* X11R4: send a ClientMessage to the window manager using the
3356 WM_CHANGE_STATE type. */
3357 {
3358 XEvent message;
3359
3360 message.xclient.window = FRAME_X_WINDOW (f);
3361 message.xclient.type = ClientMessage;
3362 message.xclient.message_type = Xatom_wm_change_state;
3363 message.xclient.format = 32;
3364 message.xclient.data.l[0] = IconicState;
3365
3366 if (! XSendEvent (x_current_display,
3367 DefaultRootWindow (x_current_display),
3368 False,
3369 SubstructureRedirectMask | SubstructureNotifyMask,
3370 &message))
3371 {
3372 UNBLOCK_INPUT_RESIGNAL;
3373 error ("Can't notify window manager of iconification.");
3374 }
3375 }
3376
3377 /* X11R3: set the initial_state field of the window manager hints to
3378 IconicState. */
3379 x_wm_set_window_state (f, IconicState);
3380
3381 f->iconified = 1;
3382 #else /* ! defined (HAVE_X11) */
3383 XUnmapWindow (XDISPLAY FRAME_X_WINDOW (f));
3384
3385 f->visible = 0; /* Handled in the UnMap event for X11. */
3386 if (f->display.x->icon_desc != 0)
3387 {
3388 XMapWindow (XDISPLAY f->display.x->icon_desc);
3389 refreshicon (f);
3390 }
3391 #endif /* ! defined (HAVE_X11) */
3392
3393 XFlushQueue ();
3394 UNBLOCK_INPUT;
3395 }
3396
3397 /* Destroy the X window of frame F.
3398 DISPL is the former f->display (since f->display
3399 has already been nulled out). */
3400
3401 x_destroy_window (f, displ)
3402 struct frame *f;
3403 union display displ;
3404 {
3405 int mask;
3406
3407 BLOCK_INPUT;
3408 if (displ.x->icon_desc != 0)
3409 XDestroyWindow (XDISPLAY displ.x->icon_desc);
3410 XDestroyWindow (XDISPLAY displ.x->window_desc);
3411 XFlushQueue ();
3412 UNBLOCK_INPUT;
3413
3414 free (displ.x);
3415 if (f == x_focus_frame)
3416 x_focus_frame = 0;
3417 if (f == x_highlight_frame)
3418 x_highlight_frame = 0;
3419 }
3420 \f
3421 #ifndef HAVE_X11
3422
3423 /* Manage event queues.
3424
3425 This code is only used by the X10 support.
3426
3427 We cannot leave events in the X queue and get them when we are ready
3428 because X does not provide a subroutine to get only a certain kind
3429 of event but not block if there are no queued events of that kind.
3430
3431 Therefore, we must examine events as they come in and copy events
3432 of certain kinds into our private queues.
3433
3434 All ExposeRegion events are put in x_expose_queue.
3435 All ButtonPressed and ButtonReleased events are put in x_mouse_queue. */
3436
3437
3438 /* Write the event *P_XREP into the event queue *QUEUE.
3439 If the queue is full, do nothing, but return nonzero. */
3440
3441 int
3442 enqueue_event (p_xrep, queue)
3443 register XEvent *p_xrep;
3444 register struct event_queue *queue;
3445 {
3446 int newindex = queue->windex + 1;
3447 if (newindex == EVENT_BUFFER_SIZE)
3448 newindex = 0;
3449 if (newindex == queue->rindex)
3450 return -1;
3451 queue->xrep[queue->windex] = *p_xrep;
3452 queue->windex = newindex;
3453 return 0;
3454 }
3455
3456 /* Fetch the next event from queue *QUEUE and store it in *P_XREP.
3457 If *QUEUE is empty, do nothing and return 0. */
3458
3459 int
3460 dequeue_event (p_xrep, queue)
3461 register XEvent *p_xrep;
3462 register struct event_queue *queue;
3463 {
3464 if (queue->windex == queue->rindex)
3465 return 0;
3466 *p_xrep = queue->xrep[queue->rindex++];
3467 if (queue->rindex == EVENT_BUFFER_SIZE)
3468 queue->rindex = 0;
3469 return 1;
3470 }
3471
3472 /* Return the number of events buffered in *QUEUE. */
3473
3474 int
3475 queue_event_count (queue)
3476 register struct event_queue *queue;
3477 {
3478 int tem = queue->windex - queue->rindex;
3479 if (tem >= 0)
3480 return tem;
3481 return EVENT_BUFFER_SIZE + tem;
3482 }
3483
3484 /* Return nonzero if mouse input is pending. */
3485
3486 int
3487 mouse_event_pending_p ()
3488 {
3489 return queue_event_count (&x_mouse_queue);
3490 }
3491 #endif /* HAVE_X11 */
3492 \f
3493 #ifdef HAVE_X11
3494
3495 x_wm_set_size_hint (f, prompting)
3496 struct frame *f;
3497 long prompting;
3498 {
3499 XSizeHints size_hints;
3500 Window window = FRAME_X_WINDOW (f);
3501
3502 size_hints.flags = PResizeInc | PMinSize | PMaxSize;
3503
3504 flexlines = f->height;
3505
3506 size_hints.x = f->display.x->left_pos;
3507 size_hints.y = f->display.x->top_pos;
3508 size_hints.height = PIXEL_HEIGHT (f);
3509 size_hints.width = PIXEL_WIDTH (f);
3510 size_hints.width_inc = FONT_WIDTH (f->display.x->font);
3511 size_hints.height_inc = FONT_HEIGHT (f->display.x->font);
3512 size_hints.max_width =
3513 (x_screen_width - ((2 * f->display.x->internal_border_width)
3514 + f->display.x->v_scrollbar_width));
3515 size_hints.max_height =
3516 (x_screen_height - ((2 * f->display.x->internal_border_width)
3517 + f->display.x->h_scrollbar_height));
3518 {
3519 int min_rows = 0, min_cols = 0;
3520 check_frame_size (f, &min_rows, &min_cols);
3521 size_hints.min_width = ((2 * f->display.x->internal_border_width)
3522 + min_cols * size_hints.width_inc
3523 + f->display.x->v_scrollbar_width);
3524 size_hints.min_height = ((2 * f->display.x->internal_border_width)
3525 + min_rows * size_hints.height_inc
3526 + f->display.x->h_scrollbar_height);
3527
3528 }
3529
3530 if (prompting)
3531 size_hints.flags |= prompting;
3532 else
3533 {
3534 XSizeHints hints; /* Sometimes I hate X Windows... */
3535
3536 XGetNormalHints (x_current_display, window, &hints);
3537 if (hints.flags & PSize)
3538 size_hints.flags |= PSize;
3539 if (hints.flags & PPosition)
3540 size_hints.flags |= PPosition;
3541 if (hints.flags & USPosition)
3542 size_hints.flags |= USPosition;
3543 if (hints.flags & USSize)
3544 size_hints.flags |= USSize;
3545 }
3546
3547 XSetNormalHints (x_current_display, window, &size_hints);
3548 }
3549
3550 /* Used for IconicState or NormalState */
3551 x_wm_set_window_state (f, state)
3552 struct frame *f;
3553 int state;
3554 {
3555 Window window = FRAME_X_WINDOW (f);
3556
3557 f->display.x->wm_hints.flags |= StateHint;
3558 f->display.x->wm_hints.initial_state = state;
3559
3560 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3561 }
3562
3563 x_wm_set_icon_pixmap (f, icon_pixmap)
3564 struct frame *f;
3565 Pixmap icon_pixmap;
3566 {
3567 Window window = FRAME_X_WINDOW (f);
3568
3569 f->display.x->wm_hints.flags |= IconPixmapHint;
3570 f->display.x->wm_hints.icon_pixmap = icon_pixmap ? icon_pixmap : None;
3571
3572 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3573 }
3574
3575 x_wm_set_icon_position (f, icon_x, icon_y)
3576 struct frame *f;
3577 int icon_x, icon_y;
3578 {
3579 Window window = FRAME_X_WINDOW (f);
3580
3581 f->display.x->wm_hints.flags |= IconPositionHint;
3582 f->display.x->wm_hints.icon_x = icon_x;
3583 f->display.x->wm_hints.icon_y = icon_y;
3584
3585 XSetWMHints (x_current_display, window, &f->display.x->wm_hints);
3586 }
3587
3588 \f
3589 void
3590 x_term_init (display_name)
3591 char *display_name;
3592 {
3593 Lisp_Object frame;
3594 char *defaultvalue;
3595 #ifdef F_SETOWN
3596 extern int old_fcntl_owner;
3597 #endif /* ! defined (F_SETOWN) */
3598
3599 x_focus_frame = x_highlight_frame = 0;
3600
3601 x_current_display = XOpenDisplay (display_name);
3602 if (x_current_display == 0)
3603 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n",
3604 display_name);
3605
3606 #ifdef HAVE_X11
3607 {
3608 int hostname_size = 256;
3609
3610 hostname = (char *) xmalloc (hostname_size);
3611
3612 #if 0
3613 XSetAfterFunction (x_current_display, x_trace_wire);
3614 #endif /* ! 0 */
3615
3616 invocation_name = Ffile_name_nondirectory (Fcar (Vcommand_line_args));
3617
3618 /* Try to get the host name; if the buffer is too short, try
3619 again. Apparently, the only indication gethostname gives of
3620 whether the buffer was large enough is the presence or absence
3621 of a '\0' in the string. Eech. */
3622 for (;;)
3623 {
3624 gethostname (hostname, hostname_size - 1);
3625 hostname[hostname_size - 1] = '\0';
3626
3627 /* Was the buffer large enough for gethostname to store the '\0'? */
3628 if (strlen (hostname) < hostname_size - 1)
3629 break;
3630
3631 hostname_size <<= 1;
3632 hostname = (char *) xrealloc (hostname, hostname_size);
3633 }
3634 x_id_name = (char *) xmalloc (XSTRING (invocation_name)->size
3635 + strlen (hostname)
3636 + 2);
3637 sprintf (x_id_name, "%s@%s", XSTRING (invocation_name)->data, hostname);
3638 }
3639
3640 dup2 (ConnectionNumber (x_current_display), 0);
3641
3642 #ifndef SYSV_STREAMS
3643 /* Streams somehow keeps track of which descriptor number
3644 is being used to talk to X. So it is not safe to substitute
3645 descriptor 0. But it is safe to make descriptor 0 a copy of it. */
3646 close (ConnectionNumber (x_current_display));
3647 ConnectionNumber (x_current_display) = 0; /* Looks a little strange?
3648 * check the def of the macro;
3649 * it is a genuine lvalue */
3650 #endif /* SYSV_STREAMS */
3651
3652 #endif /* ! defined (HAVE_X11) */
3653
3654 #ifdef F_SETOWN
3655 old_fcntl_owner = fcntl (0, F_GETOWN, 0);
3656 #ifdef F_SETOWN_SOCK_NEG
3657 fcntl (0, F_SETOWN, -getpid ()); /* stdin is a socket here */
3658 #else /* ! defined (F_SETOWN_SOCK_NEG) */
3659 fcntl (0, F_SETOWN, getpid ());
3660 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
3661 #endif /* ! defined (F_SETOWN) */
3662
3663 #ifdef SIGIO
3664 init_sigio ();
3665 #endif /* ! defined (SIGIO) */
3666
3667 /* Must use interrupt input because we cannot otherwise
3668 arrange for C-g to be noticed immediately.
3669 We cannot connect it to SIGINT. */
3670 Fset_input_mode (Qt, Qnil, Qt, Qnil);
3671
3672 expose_all_windows = 0;
3673
3674 clear_frame_hook = XTclear_frame;
3675 clear_end_of_line_hook = XTclear_end_of_line;
3676 ins_del_lines_hook = XTins_del_lines;
3677 change_line_highlight_hook = XTchange_line_highlight;
3678 insert_glyphs_hook = XTinsert_glyphs;
3679 write_glyphs_hook = XTwrite_glyphs;
3680 delete_glyphs_hook = XTdelete_glyphs;
3681 ring_bell_hook = XTring_bell;
3682 reset_terminal_modes_hook = XTreset_terminal_modes;
3683 set_terminal_modes_hook = XTset_terminal_modes;
3684 update_begin_hook = XTupdate_begin;
3685 update_end_hook = XTupdate_end;
3686 set_terminal_window_hook = XTset_terminal_window;
3687 read_socket_hook = XTread_socket;
3688 cursor_to_hook = XTcursor_to;
3689 reassert_line_highlight_hook = XTreassert_line_highlight;
3690 frame_rehighlight_hook = XTframe_rehighlight;
3691 mouse_position_hook = XTmouse_position;
3692
3693 scroll_region_ok = 1; /* we'll scroll partial frames */
3694 char_ins_del_ok = 0; /* just as fast to write the line */
3695 line_ins_del_ok = 1; /* we'll just blt 'em */
3696 fast_clear_end_of_line = 1; /* X does this well */
3697 memory_below_frame = 0; /* we don't remember what scrolls
3698 off the bottom */
3699 baud_rate = 19200;
3700
3701 /* Note that there is no real way portable across R3/R4 to get the
3702 original error handler. */
3703 XHandleError (x_error_quitter);
3704 XHandleIOError (x_error_quitter);
3705
3706 /* Disable Window Change signals; they are handled by X events. */
3707 #ifdef SIGWINCH
3708 signal (SIGWINCH, SIG_DFL);
3709 #endif /* ! defined (SIGWINCH) */
3710
3711 signal (SIGPIPE, x_connection_closed);
3712 }
3713
3714 void
3715 syms_of_xterm ()
3716 {
3717 staticpro (&invocation_name);
3718 invocation_name = Qnil;
3719 }
3720 #endif /* ! defined (HAVE_X11) */
3721 #endif /* ! defined (HAVE_X_WINDOWS) */