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