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