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