(run-with-idle-timer): New function.
[emacs.git] / src / xterm.c
blobcb4704db937834c295d69e07dcb6307359112b90
1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
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.
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.
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, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 /* Xt features made by Fred Pierresteguy. */
23 /* On 4.3 these lose if they come after xterm.h. */
24 /* On HP-UX 8.0 signal.h loses if it comes after config.h. */
25 /* Putting these at the beginning seems to be standard for other .c files. */
26 #include <signal.h>
28 #include <config.h>
30 #include <stdio.h>
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
36 #ifdef HAVE_X_WINDOWS
38 #include "lisp.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
43 #include "xterm.h"
44 #include <X11/cursorfont.h>
46 #ifndef USG
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49 #ifndef makedev
50 #include <sys/types.h>
51 #endif /* makedev */
52 #endif /* USG */
54 #ifdef BSD
55 #include <sys/ioctl.h>
56 #endif /* ! defined (BSD) */
58 #include "systty.h"
59 #include "systime.h"
61 #ifndef INCLUDED_FCNTL
62 #include <fcntl.h>
63 #endif
64 #include <ctype.h>
65 #include <errno.h>
66 #include <setjmp.h>
67 #include <sys/stat.h>
68 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
69 /* #include <sys/param.h> */
71 #include "frame.h"
72 #include "dispextern.h"
73 #include "termhooks.h"
74 #include "termopts.h"
75 #include "termchar.h"
76 #if 0
77 #include "sink.h"
78 #include "sinkmask.h"
79 #endif /* ! 0 */
80 #include "gnu.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "keyboard.h"
85 #include "intervals.h"
87 #ifdef USE_X_TOOLKIT
88 extern void free_frame_menubar ();
89 extern FRAME_PTR x_menubar_window_to_frame ();
90 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
91 #define HACK_EDITRES
92 extern void _XEditResCheckMessages ();
93 #endif /* not NO_EDITRES */
94 #endif /* USE_X_TOOLKIT */
96 #ifndef USE_X_TOOLKIT
97 #define x_any_window_to_frame x_window_to_frame
98 #define x_top_window_to_frame x_window_to_frame
99 #endif
101 #ifdef USE_X_TOOLKIT
102 #include "widget.h"
103 #ifndef XtNinitialState
104 #define XtNinitialState "initialState"
105 #endif
106 #endif
108 #ifdef HAVE_X11XTR6
109 /* So we can do setlocale. */
110 #include <locale.h>
111 #endif
113 #ifdef SOLARIS2
114 /* For XlibDisplayWriting */
115 #include <X11/Xlibint.h>
116 #endif
118 #ifndef min
119 #define min(a,b) ((a)<(b) ? (a) : (b))
120 #endif
121 #ifndef max
122 #define max(a,b) ((a)>(b) ? (a) : (b))
123 #endif
125 /* This is a chain of structures for all the X displays currently in use. */
126 struct x_display_info *x_display_list;
128 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
129 one for each element of x_display_list and in the same order.
130 NAME is the name of the frame.
131 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
132 Lisp_Object x_display_name_list;
134 /* Frame being updated by update_frame. This is declared in term.c.
135 This is set by update_begin and looked at by all the
136 XT functions. It is zero while not inside an update.
137 In that case, the XT functions assume that `selected_frame'
138 is the frame to apply to. */
139 extern struct frame *updating_frame;
141 /* This is a frame waiting to be autoraised, within XTread_socket. */
142 struct frame *pending_autoraise_frame;
144 #ifdef USE_X_TOOLKIT
145 /* The application context for Xt use. */
146 XtAppContext Xt_app_con;
148 static String Xt_default_resources[] =
152 #endif
154 /* During an update, maximum vpos for ins/del line operations to affect. */
156 static int flexlines;
158 /* During an update, nonzero if chars output now should be highlighted. */
160 static int highlight;
162 /* Nominal cursor position -- where to draw output.
163 During an update, these are different from the cursor-box position. */
165 static int curs_x;
166 static int curs_y;
168 /* Mouse movement.
170 In order to avoid asking for motion events and then throwing most
171 of them away or busy-polling the server for mouse positions, we ask
172 the server for pointer motion hints. This means that we get only
173 one event per group of mouse movements. "Groups" are delimited by
174 other kinds of events (focus changes and button clicks, for
175 example), or by XQueryPointer calls; when one of these happens, we
176 get another MotionNotify event the next time the mouse moves. This
177 is at least as efficient as getting motion events when mouse
178 tracking is on, and I suspect only negligibly worse when tracking
179 is off.
181 The silly O'Reilly & Associates Nutshell guides barely document
182 pointer motion hints at all (I think you have to infer how they
183 work from an example), and the description of XQueryPointer doesn't
184 mention that calling it causes you to get another motion hint from
185 the server, which is very important. */
187 /* Where the mouse was last time we reported a mouse event. */
188 static FRAME_PTR last_mouse_frame;
189 static XRectangle last_mouse_glyph;
191 /* The scroll bar in which the last X motion event occurred.
193 If the last X motion event occurred in a scroll bar, we set this
194 so XTmouse_position can know whether to report a scroll bar motion or
195 an ordinary motion.
197 If the last X motion event didn't occur in a scroll bar, we set this
198 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
199 static Lisp_Object last_mouse_scroll_bar;
201 /* This is a hack. We would really prefer that XTmouse_position would
202 return the time associated with the position it returns, but there
203 doesn't seem to be any way to wrest the timestamp from the server
204 along with the position query. So, we just keep track of the time
205 of the last movement we received, and return that in hopes that
206 it's somewhat accurate. */
207 static Time last_mouse_movement_time;
209 /* Incremented by XTread_socket whenever it really tries to read events. */
210 #ifdef __STDC__
211 static int volatile input_signal_count;
212 #else
213 static int input_signal_count;
214 #endif
216 /* Used locally within XTread_socket. */
217 static int x_noop_count;
219 /* Initial values of argv and argc. */
220 extern char **initial_argv;
221 extern int initial_argc;
223 extern Lisp_Object Vcommand_line_args, Vsystem_name;
225 /* Tells if a window manager is present or not. */
227 extern Lisp_Object Vx_no_window_manager;
229 /* Nonzero enables some debugging for the X interface code. */
230 extern int _Xdebug;
232 extern Lisp_Object Qface, Qmouse_face;
234 extern int errno;
236 /* A mask of extra modifier bits to put into every keyboard char. */
237 extern int extra_keyboard_modifiers;
239 static Lisp_Object Qvendor_specific_keysyms;
241 extern XrmDatabase x_load_resources ();
243 extern Lisp_Object x_icon_type ();
245 void x_delete_display ();
247 static void redraw_previous_char ();
248 static void redraw_following_char ();
249 static unsigned int x_x_to_emacs_modifiers ();
251 static int fast_find_position ();
252 static void note_mouse_highlight ();
253 static void clear_mouse_face ();
254 static void show_mouse_face ();
255 static void do_line_dance ();
257 static int XTcursor_to ();
258 static int XTclear_end_of_line ();
259 static int x_io_error_quitter ();
260 void x_catch_errors ();
261 void x_uncatch_errors ();
263 #if 0
264 /* This is a function useful for recording debugging information
265 about the sequence of occurrences in this file. */
267 struct record
269 char *locus;
270 int type;
273 struct record event_record[100];
275 int event_record_index;
277 record_event (locus, type)
278 char *locus;
279 int type;
281 if (event_record_index == sizeof (event_record) / sizeof (struct record))
282 event_record_index = 0;
284 event_record[event_record_index].locus = locus;
285 event_record[event_record_index].type = type;
286 event_record_index++;
289 #endif /* 0 */
291 /* Return the struct x_display_info corresponding to DPY. */
293 struct x_display_info *
294 x_display_info_for_display (dpy)
295 Display *dpy;
297 struct x_display_info *dpyinfo;
299 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
300 if (dpyinfo->display == dpy)
301 return dpyinfo;
303 return 0;
306 /* Starting and ending updates.
308 These hooks are called by update_frame at the beginning and end
309 of a frame update. We record in `updating_frame' the identity
310 of the frame being updated, so that the XT... functions do not
311 need to take a frame as argument. Most of the XT... functions
312 should never be called except during an update, the only exceptions
313 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
315 static
316 XTupdate_begin (f)
317 struct frame *f;
319 int mask;
321 if (f == 0)
322 abort ();
324 flexlines = f->height;
325 highlight = 0;
327 BLOCK_INPUT;
329 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
331 /* Don't do highlighting for mouse motion during the update. */
332 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 1;
334 /* If the frame needs to be redrawn,
335 simply forget about any prior mouse highlighting. */
336 if (FRAME_GARBAGED_P (f))
337 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = Qnil;
339 if (!NILP (FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
341 int firstline, lastline, i;
342 struct window *w = XWINDOW (FRAME_X_DISPLAY_INFO (f)->mouse_face_window);
344 /* Find the first, and the last+1, lines affected by redisplay. */
345 for (firstline = 0; firstline < f->height; firstline++)
346 if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
347 break;
349 lastline = f->height;
350 for (i = f->height - 1; i >= 0; i--)
352 if (FRAME_DESIRED_GLYPHS (f)->enable[i])
353 break;
354 else
355 lastline = i;
358 /* Can we tell that this update does not affect the window
359 where the mouse highlight is? If so, no need to turn off.
360 Likewise, don't do anything if the frame is garbaged;
361 in that case, the FRAME_CURRENT_GLYPHS that we would use
362 are all wrong, and we will redisplay that line anyway. */
363 if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
364 || lastline < XFASTINT (w->top)))
365 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
369 UNBLOCK_INPUT;
372 static
373 XTupdate_end (f)
374 struct frame *f;
376 int mask;
378 BLOCK_INPUT;
380 do_line_dance ();
381 x_display_cursor (f, 1);
383 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
384 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
385 #if 0
386 /* This fails in the case of having updated only the echo area
387 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
388 has no relation to the current contents, and its charstarts
389 have no relation to the contents of the window-buffer.
390 I don't know a clean way to check
391 for that case. window_end_valid isn't set up yet. */
392 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
393 note_mouse_highlight (f, FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
394 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
395 #endif
397 XFlush (FRAME_X_DISPLAY (f));
398 UNBLOCK_INPUT;
401 /* This is called after a redisplay on frame F. */
403 static
404 XTframe_up_to_date (f)
405 FRAME_PTR f;
407 BLOCK_INPUT;
408 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc
409 || f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame)
411 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame,
412 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x,
413 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y);
414 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
416 UNBLOCK_INPUT;
419 /* External interface to control of standout mode.
420 Call this when about to modify line at position VPOS
421 and not change whether it is highlighted. */
423 XTreassert_line_highlight (new, vpos)
424 int new, vpos;
426 highlight = new;
429 /* Call this when about to modify line at position VPOS
430 and change whether it is highlighted. */
432 static
433 XTchange_line_highlight (new_highlight, vpos, first_unused_hpos)
434 int new_highlight, vpos, first_unused_hpos;
436 highlight = new_highlight;
437 XTcursor_to (vpos, 0);
438 XTclear_end_of_line (updating_frame->width);
441 /* This is used when starting Emacs and when restarting after suspend.
442 When starting Emacs, no X window is mapped. And nothing must be done
443 to Emacs's own window if it is suspended (though that rarely happens). */
445 static
446 XTset_terminal_modes ()
450 /* This is called when exiting or suspending Emacs.
451 Exiting will make the X-windows go away, and suspending
452 requires no action. */
454 static
455 XTreset_terminal_modes ()
457 /* XTclear_frame (); */
460 /* Set the nominal cursor position of the frame.
461 This is where display update commands will take effect.
462 This does not affect the place where the cursor-box is displayed. */
464 static int
465 XTcursor_to (row, col)
466 register int row, col;
468 int mask;
469 int orow = row;
471 curs_x = col;
472 curs_y = row;
474 if (updating_frame == 0)
476 BLOCK_INPUT;
477 x_display_cursor (selected_frame, 1);
478 XFlush (FRAME_X_DISPLAY (selected_frame));
479 UNBLOCK_INPUT;
483 /* Display a sequence of N glyphs found at GP.
484 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
485 HL is 1 if this text is highlighted, 2 if the cursor is on it,
486 3 if should appear in its mouse-face.
487 JUST_FOREGROUND if 1 means draw only the foreground;
488 don't alter the background.
490 FONT is the default font to use (for glyphs whose font-code is 0).
492 Since the display generation code is responsible for calling
493 compute_char_face and compute_glyph_face on everything it puts in
494 the display structure, we can assume that the face code on each
495 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
496 to which we can actually apply intern_face.
497 Call this function with input blocked. */
499 #if 1
500 /* This is the multi-face code. */
502 static void
503 dumpglyphs (f, left, top, gp, n, hl, just_foreground)
504 struct frame *f;
505 int left, top;
506 register GLYPH *gp; /* Points to first GLYPH. */
507 register int n; /* Number of glyphs to display. */
508 int hl;
509 int just_foreground;
511 /* Holds characters to be displayed. */
512 char *buf = (char *) alloca (f->width * sizeof (*buf));
513 register char *cp; /* Steps through buf[]. */
514 register int tlen = GLYPH_TABLE_LENGTH;
515 register Lisp_Object *tbase = GLYPH_TABLE_BASE;
516 Window window = FRAME_X_WINDOW (f);
517 int orig_left = left;
519 while (n > 0)
521 /* Get the face-code of the next GLYPH. */
522 int cf, len;
523 int g = *gp;
525 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
526 cf = FAST_GLYPH_FACE (g);
528 /* Find the run of consecutive glyphs with the same face-code.
529 Extract their character codes into BUF. */
530 cp = buf;
531 while (n > 0)
533 g = *gp;
534 GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
535 if (FAST_GLYPH_FACE (g) != cf)
536 break;
538 *cp++ = FAST_GLYPH_CHAR (g);
539 --n;
540 ++gp;
543 /* LEN gets the length of the run. */
544 len = cp - buf;
546 /* Now output this run of chars, with the font and pixel values
547 determined by the face code CF. */
549 struct face *face = FRAME_DEFAULT_FACE (f);
550 XFontStruct *font = FACE_FONT (face);
551 GC gc = FACE_GC (face);
552 int stippled = 0;
554 /* HL = 3 means use a mouse face previously chosen. */
555 if (hl == 3)
556 cf = FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id;
558 /* First look at the face of the text itself. */
559 if (cf != 0)
561 /* It's possible for the display table to specify
562 a face code that is out of range. Use 0 in that case. */
563 if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
564 || FRAME_COMPUTED_FACES (f) [cf] == 0)
565 cf = 0;
567 if (cf == 1)
568 face = FRAME_MODE_LINE_FACE (f);
569 else
570 face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
571 font = FACE_FONT (face);
572 gc = FACE_GC (face);
573 if (FACE_STIPPLE (face))
574 stippled = 1;
577 /* Then comes the distinction between modeline and normal text. */
578 else if (hl == 0)
580 else if (hl == 1)
582 face = FRAME_MODE_LINE_FACE (f);
583 font = FACE_FONT (face);
584 gc = FACE_GC (face);
585 if (FACE_STIPPLE (face))
586 stippled = 1;
589 #define FACE_DEFAULT (~0)
591 /* Now override that if the cursor's on this character. */
592 if (hl == 2)
594 /* The cursor overrides stippling. */
595 stippled = 0;
597 if ((!face->font
598 || face->font == (XFontStruct *) FACE_DEFAULT
599 || face->font == f->output_data.x->font)
600 && face->background == f->output_data.x->background_pixel
601 && face->foreground == f->output_data.x->foreground_pixel)
603 gc = f->output_data.x->cursor_gc;
605 /* Cursor on non-default face: must merge. */
606 else
608 XGCValues xgcv;
609 unsigned long mask;
611 xgcv.background = f->output_data.x->cursor_pixel;
612 xgcv.foreground = face->background;
613 /* If the glyph would be invisible,
614 try a different foreground. */
615 if (xgcv.foreground == xgcv.background)
616 xgcv.foreground = face->foreground;
617 if (xgcv.foreground == xgcv.background)
618 xgcv.foreground = f->output_data.x->cursor_foreground_pixel;
619 if (xgcv.foreground == xgcv.background)
620 xgcv.foreground = face->foreground;
621 /* Make sure the cursor is distinct from text in this face. */
622 if (xgcv.background == face->background
623 && xgcv.foreground == face->foreground)
625 xgcv.background = face->foreground;
626 xgcv.foreground = face->background;
628 xgcv.font = face->font->fid;
629 xgcv.graphics_exposures = 0;
630 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
631 if (FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc)
632 XChangeGC (FRAME_X_DISPLAY (f),
633 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc,
634 mask, &xgcv);
635 else
636 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc
637 = XCreateGC (FRAME_X_DISPLAY (f), window, mask, &xgcv);
638 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
639 #if 0
640 /* If this code is restored, it must also reset to the default stipple
641 if necessary. */
642 if (face->stipple && face->stipple != FACE_DEFAULT)
643 XSetStipple (FRAME_X_DISPLAY (f), gc, face->stipple);
644 #endif
648 if (font == (XFontStruct *) FACE_DEFAULT)
649 font = f->output_data.x->font;
651 if (just_foreground)
652 XDrawString (FRAME_X_DISPLAY (f), window, gc,
653 left, top + FONT_BASE (font), buf, len);
654 else
656 if (stippled)
658 /* Turn stipple on. */
659 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillOpaqueStippled);
661 /* Draw stipple on background. */
662 XFillRectangle (FRAME_X_DISPLAY (f), window, gc,
663 left, top,
664 FONT_WIDTH (font) * len,
665 FONT_HEIGHT (font));
667 /* Turn stipple off. */
668 XSetFillStyle (FRAME_X_DISPLAY (f), gc, FillSolid);
670 /* Draw the text, solidly, onto the stipple pattern. */
671 XDrawString (FRAME_X_DISPLAY (f), window, gc,
672 left, top + FONT_BASE (font), buf, len);
674 else
675 XDrawImageString (FRAME_X_DISPLAY (f), window, gc,
676 left, top + FONT_BASE (font), buf, len);
678 /* Clear the rest of the line's height. */
679 if (f->output_data.x->line_height != FONT_HEIGHT (font))
680 XClearArea (FRAME_X_DISPLAY (f), window, left,
681 top + FONT_HEIGHT (font),
682 FONT_WIDTH (font) * len,
683 /* This is how many pixels of height
684 we have to clear. */
685 f->output_data.x->line_height - FONT_HEIGHT (font),
686 False);
689 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
690 which often is not up to date yet. */
691 if (!just_foreground)
693 if (left == orig_left)
694 redraw_previous_char (f, PIXEL_TO_CHAR_COL (f, left),
695 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
696 if (n == 0)
697 redraw_following_char (f, PIXEL_TO_CHAR_COL (f, left + len * FONT_WIDTH (font)),
698 PIXEL_TO_CHAR_ROW (f, top), hl == 1);
700 #endif
702 /* We should probably check for XA_UNDERLINE_POSITION and
703 XA_UNDERLINE_THICKNESS properties on the font, but let's
704 just get the thing working, and come back to that. */
706 int underline_position = 1;
708 if (font->descent <= underline_position)
709 underline_position = font->descent - 1;
711 if (face->underline)
712 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
713 FACE_GC (face),
714 left, (top
715 + FONT_BASE (font)
716 + underline_position),
717 len * FONT_WIDTH (font), 1);
720 left += len * FONT_WIDTH (font);
724 #endif /* 1 */
726 #if 0
727 /* This is the old single-face code. */
729 static void
730 dumpglyphs (f, left, top, gp, n, hl, font)
731 struct frame *f;
732 int left, top;
733 register GLYPH *gp; /* Points to first GLYPH. */
734 register int n; /* Number of glyphs to display. */
735 int hl;
736 XFontStruct *font;
738 register int len;
739 Window window = FRAME_X_WINDOW (f);
740 GC drawing_gc = (hl == 2 ? f->output_data.x->cursor_gc
741 : (hl ? f->output_data.x->reverse_gc
742 : f->output_data.x->normal_gc));
744 if (sizeof (GLYPH) == sizeof (XChar2b))
745 XDrawImageString16 (FRAME_X_DISPLAY (f), window, drawing_gc,
746 left, top + FONT_BASE (font), (XChar2b *) gp, n);
747 else if (sizeof (GLYPH) == sizeof (unsigned char))
748 XDrawImageString (FRAME_X_DISPLAY (f), window, drawing_gc,
749 left, top + FONT_BASE (font), (char *) gp, n);
750 else
751 /* What size of glyph ARE you using? And does X have a function to
752 draw them? */
753 abort ();
755 #endif
757 /* Output some text at the nominal frame cursor position.
758 Advance the cursor over the text.
759 Output LEN glyphs at START.
761 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
762 controls the pixel values used for foreground and background. */
764 static
765 XTwrite_glyphs (start, len)
766 register GLYPH *start;
767 int len;
769 register int temp_length;
770 int mask;
771 struct frame *f;
773 BLOCK_INPUT;
775 do_line_dance ();
776 f = updating_frame;
777 if (f == 0)
779 f = selected_frame;
780 /* If not within an update,
781 output at the frame's visible cursor. */
782 curs_x = f->cursor_x;
783 curs_y = f->cursor_y;
786 dumpglyphs (f,
787 CHAR_TO_PIXEL_COL (f, curs_x),
788 CHAR_TO_PIXEL_ROW (f, curs_y),
789 start, len, highlight, 0);
791 /* If we drew on top of the cursor, note that it is turned off. */
792 if (curs_y == f->phys_cursor_y
793 && curs_x <= f->phys_cursor_x
794 && curs_x + len > f->phys_cursor_x)
795 f->phys_cursor_x = -1;
797 if (updating_frame == 0)
799 f->cursor_x += len;
800 x_display_cursor (f, 1);
801 f->cursor_x -= len;
803 else
804 curs_x += len;
806 UNBLOCK_INPUT;
809 /* Clear to the end of the line.
810 Erase the current text line from the nominal cursor position (inclusive)
811 to column FIRST_UNUSED (exclusive). The idea is that everything
812 from FIRST_UNUSED onward is already erased. */
814 static
815 XTclear_end_of_line (first_unused)
816 register int first_unused;
818 struct frame *f = updating_frame;
819 int mask;
821 if (f == 0)
822 abort ();
824 if (curs_y < 0 || curs_y >= f->height)
825 return;
826 if (first_unused <= 0)
827 return;
829 if (first_unused >= f->width)
830 first_unused = f->width;
832 BLOCK_INPUT;
834 do_line_dance ();
836 /* Notice if the cursor will be cleared by this operation. */
837 if (curs_y == f->phys_cursor_y
838 && curs_x <= f->phys_cursor_x
839 && f->phys_cursor_x < first_unused)
840 f->phys_cursor_x = -1;
842 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
843 CHAR_TO_PIXEL_COL (f, curs_x),
844 CHAR_TO_PIXEL_ROW (f, curs_y),
845 FONT_WIDTH (f->output_data.x->font) * (first_unused - curs_x),
846 f->output_data.x->line_height, False);
847 #if 0
848 redraw_previous_char (f, curs_x, curs_y, highlight);
849 #endif
851 UNBLOCK_INPUT;
854 static
855 XTclear_frame ()
857 int mask;
858 struct frame *f = updating_frame;
860 if (f == 0)
861 f = selected_frame;
863 f->phys_cursor_x = -1; /* Cursor not visible. */
864 curs_x = 0; /* Nominal cursor position is top left. */
865 curs_y = 0;
867 BLOCK_INPUT;
869 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
871 /* We have to clear the scroll bars, too. If we have changed
872 colors or something like that, then they should be notified. */
873 x_scroll_bar_clear (f);
875 XFlush (FRAME_X_DISPLAY (f));
876 UNBLOCK_INPUT;
879 #if 0
880 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
881 always contain the right glyphs to use.
883 It also needs to be changed to look at the details of the font and
884 see whether there is really overlap, and do nothing when there is
885 not. This can use font_char_overlap_left and font_char_overlap_right,
886 but just how to use them is not clear. */
888 /* Erase the character (if any) at the position just before X, Y in frame F,
889 then redraw it and the character before it.
890 This is necessary when we erase starting at X,
891 in case the character after X overlaps into the one before X.
892 Call this function with input blocked. */
894 static void
895 redraw_previous_char (f, x, y, highlight_flag)
896 FRAME_PTR f;
897 int x, y;
898 int highlight_flag;
900 /* Erase the character before the new ones, in case
901 what was here before overlaps it.
902 Reoutput that character, and the previous character
903 (in case the previous character overlaps it). */
904 if (x > 0)
906 int start_x = x - 2;
907 if (start_x < 0)
908 start_x = 0;
909 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
910 CHAR_TO_PIXEL_COL (f, x - 1),
911 CHAR_TO_PIXEL_ROW (f, y),
912 FONT_WIDTH (f->output_data.x->font),
913 f->output_data.x->line_height, False);
915 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, start_x),
916 CHAR_TO_PIXEL_ROW (f, y),
917 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][start_x],
918 x - start_x, highlight_flag, 1);
922 /* Erase the character (if any) at the position X, Y in frame F,
923 then redraw it and the character after it.
924 This is necessary when we erase endng at X,
925 in case the character after X overlaps into the one before X.
926 Call this function with input blocked. */
928 static void
929 redraw_following_char (f, x, y, highlight_flag)
930 FRAME_PTR f;
931 int x, y;
932 int highlight_flag;
934 int limit = FRAME_CURRENT_GLYPHS (f)->used[y];
935 /* Erase the character after the new ones, in case
936 what was here before overlaps it.
937 Reoutput that character, and the following character
938 (in case the following character overlaps it). */
939 if (x < limit
940 && FRAME_CURRENT_GLYPHS (f)->glyphs[y][x] != SPACEGLYPH)
942 int end_x = x + 2;
943 if (end_x > limit)
944 end_x = limit;
945 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
946 CHAR_TO_PIXEL_COL (f, x),
947 CHAR_TO_PIXEL_ROW (f, y),
948 FONT_WIDTH (f->output_data.x->font),
949 f->output_data.x->line_height, False);
951 dumpglyphs (f, CHAR_TO_PIXEL_COL (f, x),
952 CHAR_TO_PIXEL_ROW (f, y),
953 &FRAME_CURRENT_GLYPHS (f)->glyphs[y][x],
954 end_x - x, highlight_flag, 1);
957 #endif /* 0 */
959 #if 0 /* Not in use yet */
961 /* Return 1 if character C in font F extends past its left edge. */
963 static int
964 font_char_overlap_left (font, c)
965 XFontStruct *font;
966 int c;
968 XCharStruct *s;
970 /* Find the bounding-box info for C. */
971 if (font->per_char == 0)
972 s = &font->max_bounds;
973 else
975 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
976 int row, within;
978 /* Decode char into row number (byte 1) and code within row (byte 2). */
979 row = c >> 8;
980 within = c & 0177;
981 if (!(within >= font->min_char_or_byte2
982 && within <= font->max_char_or_byte2
983 && row >= font->min_byte1
984 && row <= font->max_byte1))
986 /* If char is out of range, try the font's default char instead. */
987 c = font->default_char;
988 row = c >> (BITS_PER_INT - 8);
989 within = c & 0177;
991 if (!(within >= font->min_char_or_byte2
992 && within <= font->max_char_or_byte2
993 && row >= font->min_byte1
994 && row <= font->max_byte1))
995 /* Still out of range means this char does not overlap. */
996 return 0;
997 else
998 /* We found the info for this char. */
999 s = (font->per_char + (within - font->min_char_or_byte2)
1000 + row * rowlen);
1003 return (s && s->lbearing < 0);
1006 /* Return 1 if character C in font F extends past its right edge. */
1008 static int
1009 font_char_overlap_right (font, c)
1010 XFontStruct *font;
1011 int c;
1013 XCharStruct *s;
1015 /* Find the bounding-box info for C. */
1016 if (font->per_char == 0)
1017 s = &font->max_bounds;
1018 else
1020 int rowlen = font->max_char_or_byte2 - font->min_char_or_byte2 + 1;
1021 int row, within;
1023 /* Decode char into row number (byte 1) and code within row (byte 2). */
1024 row = c >> 8;
1025 within = c & 0177;
1026 if (!(within >= font->min_char_or_byte2
1027 && within <= font->max_char_or_byte2
1028 && row >= font->min_byte1
1029 && row <= font->max_byte1))
1031 /* If char is out of range, try the font's default char instead. */
1032 c = font->default_char;
1033 row = c >> (BITS_PER_INT - 8);
1034 within = c & 0177;
1036 if (!(within >= font->min_char_or_byte2
1037 && within <= font->max_char_or_byte2
1038 && row >= font->min_byte1
1039 && row <= font->max_byte1))
1040 /* Still out of range means this char does not overlap. */
1041 return 0;
1042 else
1043 /* We found the info for this char. */
1044 s = (font->per_char + (within - font->min_char_or_byte2)
1045 + row * rowlen);
1048 return (s && s->rbearing >= s->width);
1050 #endif /* 0 */
1052 /* Invert the middle quarter of the frame for .15 sec. */
1054 /* We use the select system call to do the waiting, so we have to make sure
1055 it's available. If it isn't, we just won't do visual bells. */
1056 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1058 /* Subtract the `struct timeval' values X and Y,
1059 storing the result in RESULT.
1060 Return 1 if the difference is negative, otherwise 0. */
1062 static int
1063 timeval_subtract (result, x, y)
1064 struct timeval *result, x, y;
1066 /* Perform the carry for the later subtraction by updating y.
1067 This is safer because on some systems
1068 the tv_sec member is unsigned. */
1069 if (x.tv_usec < y.tv_usec)
1071 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
1072 y.tv_usec -= 1000000 * nsec;
1073 y.tv_sec += nsec;
1075 if (x.tv_usec - y.tv_usec > 1000000)
1077 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
1078 y.tv_usec += 1000000 * nsec;
1079 y.tv_sec -= nsec;
1082 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1083 result->tv_sec = x.tv_sec - y.tv_sec;
1084 result->tv_usec = x.tv_usec - y.tv_usec;
1086 /* Return indication of whether the result should be considered negative. */
1087 return x.tv_sec < y.tv_sec;
1090 XTflash (f)
1091 struct frame *f;
1093 BLOCK_INPUT;
1096 GC gc;
1098 /* Create a GC that will use the GXxor function to flip foreground pixels
1099 into background pixels. */
1101 XGCValues values;
1103 values.function = GXxor;
1104 values.foreground = (f->output_data.x->foreground_pixel
1105 ^ f->output_data.x->background_pixel);
1107 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1108 GCFunction | GCForeground, &values);
1112 int width = PIXEL_WIDTH (f);
1113 int height = PIXEL_HEIGHT (f);
1115 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
1116 width/4, height/4, width/2, height/2);
1117 XFlush (FRAME_X_DISPLAY (f));
1120 struct timeval wakeup, now;
1122 EMACS_GET_TIME (wakeup);
1124 /* Compute time to wait until, propagating carry from usecs. */
1125 wakeup.tv_usec += 150000;
1126 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
1127 wakeup.tv_usec %= 1000000;
1129 /* Keep waiting until past the time wakeup. */
1130 while (1)
1132 struct timeval timeout;
1134 EMACS_GET_TIME (timeout);
1136 /* In effect, timeout = wakeup - timeout.
1137 Break if result would be negative. */
1138 if (timeval_subtract (&timeout, wakeup, timeout))
1139 break;
1141 /* Try to wait that long--but we might wake up sooner. */
1142 select (0, NULL, NULL, NULL, &timeout);
1146 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
1147 width/4, height/4, width/2, height/2);
1148 XFreeGC (FRAME_X_DISPLAY (f), gc);
1149 XFlush (FRAME_X_DISPLAY (f));
1153 UNBLOCK_INPUT;
1156 #endif
1159 /* Make audible bell. */
1161 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1163 XTring_bell ()
1165 if (FRAME_X_DISPLAY (selected_frame) == 0)
1166 return;
1168 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1169 if (visible_bell)
1170 XTflash (selected_frame);
1171 else
1172 #endif
1174 BLOCK_INPUT;
1175 XRINGBELL;
1176 XFlush (FRAME_X_DISPLAY (selected_frame));
1177 UNBLOCK_INPUT;
1181 /* Insert and delete character.
1182 These are not supposed to be used because we are supposed to turn
1183 off the feature of using them. */
1185 static
1186 XTinsert_glyphs (start, len)
1187 register char *start;
1188 register int len;
1190 abort ();
1193 static
1194 XTdelete_glyphs (n)
1195 register int n;
1197 abort ();
1200 /* Specify how many text lines, from the top of the window,
1201 should be affected by insert-lines and delete-lines operations.
1202 This, and those operations, are used only within an update
1203 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1205 static
1206 XTset_terminal_window (n)
1207 register int n;
1209 if (updating_frame == 0)
1210 abort ();
1212 if ((n <= 0) || (n > updating_frame->height))
1213 flexlines = updating_frame->height;
1214 else
1215 flexlines = n;
1218 /* These variables need not be per frame
1219 because redisplay is done on a frame-by-frame basis
1220 and the line dance for one frame is finished before
1221 anything is done for anoter frame. */
1223 /* Array of line numbers from cached insert/delete operations.
1224 line_dance[i] is the old position of the line that we want
1225 to move to line i, or -1 if we want a blank line there. */
1226 static int *line_dance;
1228 /* Allocated length of that array. */
1229 static int line_dance_len;
1231 /* Flag indicating whether we've done any work. */
1232 static int line_dance_in_progress;
1234 /* Perform an insert-lines or delete-lines operation,
1235 inserting N lines or deleting -N lines at vertical position VPOS. */
1236 XTins_del_lines (vpos, n)
1237 int vpos, n;
1239 register int fence, i;
1241 if (vpos >= flexlines)
1242 return;
1244 if (!line_dance_in_progress)
1246 int ht = updating_frame->height;
1247 if (ht > line_dance_len)
1249 line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
1250 line_dance_len = ht;
1252 for (i = 0; i < ht; ++i) line_dance[i] = i;
1253 line_dance_in_progress = 1;
1255 if (n >= 0)
1257 if (n > flexlines - vpos)
1258 n = flexlines - vpos;
1259 fence = vpos + n;
1260 for (i = flexlines; --i >= fence;)
1261 line_dance[i] = line_dance[i-n];
1262 for (i = fence; --i >= vpos;)
1263 line_dance[i] = -1;
1265 else
1267 n = -n;
1268 if (n > flexlines - vpos)
1269 n = flexlines - vpos;
1270 fence = flexlines - n;
1271 for (i = vpos; i < fence; ++i)
1272 line_dance[i] = line_dance[i + n];
1273 for (i = fence; i < flexlines; ++i)
1274 line_dance[i] = -1;
1278 /* Here's where we actually move the pixels around.
1279 Must be called with input blocked. */
1280 static void
1281 do_line_dance ()
1283 register int i, j, distance;
1284 register struct frame *f;
1285 int ht;
1286 int intborder;
1288 /* Must check this flag first. If it's not set, then not only is the
1289 array uninitialized, but we might not even have a frame. */
1290 if (!line_dance_in_progress)
1291 return;
1293 f = updating_frame;
1294 if (f == 0)
1295 abort ();
1297 ht = f->height;
1298 intborder = f->output_data.x->internal_border_width;
1300 x_display_cursor (updating_frame, 0);
1302 for (i = 0; i < ht; ++i)
1303 if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
1305 for (j = i; (j < ht && line_dance[j] != -1
1306 && line_dance[j]-j == distance); ++j);
1307 /* Copy [i,j) upward from [i+distance,j+distance) */
1308 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1309 FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
1310 intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
1311 f->width * FONT_WIDTH (f->output_data.x->font),
1312 (j-i) * f->output_data.x->line_height,
1313 intborder, CHAR_TO_PIXEL_ROW (f, i));
1314 i = j-1;
1317 for (i = ht; --i >=0; )
1318 if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
1320 for (j = i; (--j >= 0 && line_dance[j] != -1
1321 && line_dance[j]-j == distance););
1322 /* Copy (j,i] downward from (j+distance, i+distance] */
1323 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1324 FRAME_X_WINDOW (f), f->output_data.x->normal_gc,
1325 intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
1326 f->width * FONT_WIDTH (f->output_data.x->font),
1327 (i-j) * f->output_data.x->line_height,
1328 intborder, CHAR_TO_PIXEL_ROW (f, j+1));
1329 i = j+1;
1332 for (i = 0; i < ht; ++i)
1333 if (line_dance[i] == -1)
1335 for (j = i; j < ht && line_dance[j] == -1; ++j);
1336 /* Clear [i,j) */
1337 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1338 intborder, CHAR_TO_PIXEL_ROW (f, i),
1339 f->width * FONT_WIDTH (f->output_data.x->font),
1340 (j-i) * f->output_data.x->line_height, False);
1341 i = j-1;
1343 line_dance_in_progress = 0;
1346 /* Support routines for exposure events. */
1347 static void clear_cursor ();
1349 /* Output into a rectangle of an X-window (for frame F)
1350 the characters in f->phys_lines that overlap that rectangle.
1351 TOP and LEFT are the position of the upper left corner of the rectangle.
1352 ROWS and COLS are the size of the rectangle.
1353 Call this function with input blocked. */
1355 static void
1356 dumprectangle (f, left, top, cols, rows)
1357 struct frame *f;
1358 register int left, top, cols, rows;
1360 register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
1361 int cursor_cleared = 0;
1362 int bottom, right;
1363 register int y;
1365 if (FRAME_GARBAGED_P (f))
1366 return;
1368 /* Express rectangle as four edges, instead of position-and-size. */
1369 bottom = top + rows;
1370 right = left + cols;
1372 /* Convert rectangle edges in pixels to edges in chars.
1373 Round down for left and top, up for right and bottom. */
1374 top = PIXEL_TO_CHAR_ROW (f, top);
1375 left = PIXEL_TO_CHAR_COL (f, left);
1376 bottom += (f->output_data.x->line_height - 1);
1377 right += (FONT_WIDTH (f->output_data.x->font) - 1);
1378 bottom = PIXEL_TO_CHAR_ROW (f, bottom);
1379 right = PIXEL_TO_CHAR_COL (f, right);
1381 /* Clip the rectangle to what can be visible. */
1382 if (left < 0)
1383 left = 0;
1384 if (top < 0)
1385 top = 0;
1386 if (right > f->width)
1387 right = f->width;
1388 if (bottom > f->height)
1389 bottom = f->height;
1391 /* Get size in chars of the rectangle. */
1392 cols = right - left;
1393 rows = bottom - top;
1395 /* If rectangle has zero area, return. */
1396 if (rows <= 0) return;
1397 if (cols <= 0) return;
1399 /* Turn off the cursor if it is in the rectangle.
1400 We will turn it back on afterward. */
1401 if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
1402 && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
1404 clear_cursor (f);
1405 cursor_cleared = 1;
1408 /* Display the text in the rectangle, one text line at a time. */
1410 for (y = top; y < bottom; y++)
1412 GLYPH *line = &active_frame->glyphs[y][left];
1414 if (! active_frame->enable[y] || left > active_frame->used[y])
1415 continue;
1417 dumpglyphs (f,
1418 CHAR_TO_PIXEL_COL (f, left),
1419 CHAR_TO_PIXEL_ROW (f, y),
1420 line, min (cols, active_frame->used[y] - left),
1421 active_frame->highlight[y], 0);
1424 /* Turn the cursor on if we turned it off. */
1426 if (cursor_cleared)
1427 x_display_cursor (f, 1);
1430 static void
1431 frame_highlight (f)
1432 struct frame *f;
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 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1440 f->output_data.x->border_pixel);
1441 UNBLOCK_INPUT;
1442 x_update_cursor (f, 1);
1445 static void
1446 frame_unhighlight (f)
1447 struct frame *f;
1449 /* We used to only do this if Vx_no_window_manager was non-nil, but
1450 the ICCCM (section 4.1.6) says that the window's border pixmap
1451 and border pixel are window attributes which are "private to the
1452 client", so we can always change it to whatever we want. */
1453 BLOCK_INPUT;
1454 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1455 f->output_data.x->border_tile);
1456 UNBLOCK_INPUT;
1457 x_update_cursor (f, 1);
1460 static void XTframe_rehighlight ();
1461 static void x_frame_rehighlight ();
1463 /* The focus has changed. Update the frames as necessary to reflect
1464 the new situation. Note that we can't change the selected frame
1465 here, because the Lisp code we are interrupting might become confused.
1466 Each event gets marked with the frame in which it occurred, so the
1467 Lisp code can tell when the switch took place by examining the events. */
1469 static void
1470 x_new_focus_frame (dpyinfo, frame)
1471 struct x_display_info *dpyinfo;
1472 struct frame *frame;
1474 struct frame *old_focus = dpyinfo->x_focus_frame;
1475 int events_enqueued = 0;
1477 if (frame != dpyinfo->x_focus_frame)
1479 /* Set this before calling other routines, so that they see
1480 the correct value of x_focus_frame. */
1481 dpyinfo->x_focus_frame = frame;
1483 if (old_focus && old_focus->auto_lower)
1484 x_lower_frame (old_focus);
1486 #if 0
1487 selected_frame = frame;
1488 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
1489 selected_frame);
1490 Fselect_window (selected_frame->selected_window);
1491 choose_minibuf_frame ();
1492 #endif /* ! 0 */
1494 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
1495 pending_autoraise_frame = dpyinfo->x_focus_frame;
1496 else
1497 pending_autoraise_frame = 0;
1500 x_frame_rehighlight (dpyinfo);
1503 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1505 void
1506 x_mouse_leave (dpyinfo)
1507 struct x_display_info *dpyinfo;
1509 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
1512 /* The focus has changed, or we have redirected a frame's focus to
1513 another frame (this happens when a frame uses a surrogate
1514 minibuffer frame). Shift the highlight as appropriate.
1516 The FRAME argument doesn't necessarily have anything to do with which
1517 frame is being highlighted or unhighlighted; we only use it to find
1518 the appropriate X display info. */
1519 static void
1520 XTframe_rehighlight (frame)
1521 struct frame *frame;
1523 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
1526 static void
1527 x_frame_rehighlight (dpyinfo)
1528 struct x_display_info *dpyinfo;
1530 struct frame *old_highlight = dpyinfo->x_highlight_frame;
1532 if (dpyinfo->x_focus_frame)
1534 dpyinfo->x_highlight_frame
1535 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
1536 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
1537 : dpyinfo->x_focus_frame);
1538 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
1540 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
1541 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
1544 else
1545 dpyinfo->x_highlight_frame = 0;
1547 if (dpyinfo->x_highlight_frame != old_highlight)
1549 if (old_highlight)
1550 frame_unhighlight (old_highlight);
1551 if (dpyinfo->x_highlight_frame)
1552 frame_highlight (dpyinfo->x_highlight_frame);
1556 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1558 /* Initialize mode_switch_bit and modifier_meaning. */
1559 static void
1560 x_find_modifier_meanings (dpyinfo)
1561 struct x_display_info *dpyinfo;
1563 int min_code, max_code;
1564 KeySym *syms;
1565 int syms_per_code;
1566 XModifierKeymap *mods;
1568 dpyinfo->meta_mod_mask = 0;
1569 dpyinfo->shift_lock_mask = 0;
1570 dpyinfo->alt_mod_mask = 0;
1571 dpyinfo->super_mod_mask = 0;
1572 dpyinfo->hyper_mod_mask = 0;
1574 #ifdef HAVE_X11R4
1575 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
1576 #else
1577 min_code = dpyinfo->display->min_keycode;
1578 max_code = dpyinfo->display->max_keycode;
1579 #endif
1581 syms = XGetKeyboardMapping (dpyinfo->display,
1582 min_code, max_code - min_code + 1,
1583 &syms_per_code);
1584 mods = XGetModifierMapping (dpyinfo->display);
1586 /* Scan the modifier table to see which modifier bits the Meta and
1587 Alt keysyms are on. */
1589 int row, col; /* The row and column in the modifier table. */
1591 for (row = 3; row < 8; row++)
1592 for (col = 0; col < mods->max_keypermod; col++)
1594 KeyCode code
1595 = mods->modifiermap[(row * mods->max_keypermod) + col];
1597 /* Zeroes are used for filler. Skip them. */
1598 if (code == 0)
1599 continue;
1601 /* Are any of this keycode's keysyms a meta key? */
1603 int code_col;
1605 for (code_col = 0; code_col < syms_per_code; code_col++)
1607 int sym = syms[((code - min_code) * syms_per_code) + code_col];
1609 switch (sym)
1611 case XK_Meta_L:
1612 case XK_Meta_R:
1613 dpyinfo->meta_mod_mask |= (1 << row);
1614 break;
1616 case XK_Alt_L:
1617 case XK_Alt_R:
1618 dpyinfo->alt_mod_mask |= (1 << row);
1619 break;
1621 case XK_Hyper_L:
1622 case XK_Hyper_R:
1623 dpyinfo->hyper_mod_mask |= (1 << row);
1624 break;
1626 case XK_Super_L:
1627 case XK_Super_R:
1628 dpyinfo->super_mod_mask |= (1 << row);
1629 break;
1631 case XK_Shift_Lock:
1632 /* Ignore this if it's not on the lock modifier. */
1633 if ((1 << row) == LockMask)
1634 dpyinfo->shift_lock_mask = LockMask;
1635 break;
1642 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
1643 if (! dpyinfo->meta_mod_mask)
1645 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
1646 dpyinfo->alt_mod_mask = 0;
1649 /* If some keys are both alt and meta,
1650 make them just meta, not alt. */
1651 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
1653 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
1656 XFree ((char *) syms);
1657 XFreeModifiermap (mods);
1660 /* Convert between the modifier bits X uses and the modifier bits
1661 Emacs uses. */
1662 static unsigned int
1663 x_x_to_emacs_modifiers (dpyinfo, state)
1664 struct x_display_info *dpyinfo;
1665 unsigned int state;
1667 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
1668 | ((state & ControlMask) ? ctrl_modifier : 0)
1669 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
1670 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
1671 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
1672 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
1675 static unsigned int
1676 x_emacs_to_x_modifiers (dpyinfo, state)
1677 struct x_display_info *dpyinfo;
1678 unsigned int state;
1680 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
1681 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
1682 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
1683 | ((state & shift_modifier) ? ShiftMask : 0)
1684 | ((state & ctrl_modifier) ? ControlMask : 0)
1685 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
1688 /* Convert a keysym to its name. */
1690 char *
1691 x_get_keysym_name (keysym)
1692 KeySym keysym;
1694 char *value;
1696 BLOCK_INPUT;
1697 value = XKeysymToString (keysym);
1698 UNBLOCK_INPUT;
1700 return value;
1703 /* Mouse clicks and mouse movement. Rah. */
1705 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
1706 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
1707 that the glyph at X, Y occupies, if BOUNDS != 0.
1708 If NOCLIP is nonzero, do not force the value into range. */
1710 void
1711 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1712 FRAME_PTR f;
1713 register int pix_x, pix_y;
1714 register int *x, *y;
1715 XRectangle *bounds;
1716 int noclip;
1718 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
1719 even for negative values. */
1720 if (pix_x < 0)
1721 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
1722 if (pix_y < 0)
1723 pix_y -= (f)->output_data.x->line_height - 1;
1725 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
1726 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
1728 if (bounds)
1730 bounds->width = FONT_WIDTH (f->output_data.x->font);
1731 bounds->height = f->output_data.x->line_height;
1732 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
1733 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
1736 if (!noclip)
1738 if (pix_x < 0)
1739 pix_x = 0;
1740 else if (pix_x > f->width)
1741 pix_x = f->width;
1743 if (pix_y < 0)
1744 pix_y = 0;
1745 else if (pix_y > f->height)
1746 pix_y = f->height;
1749 *x = pix_x;
1750 *y = pix_y;
1753 void
1754 glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
1755 FRAME_PTR f;
1756 register int x, y;
1757 register int *pix_x, *pix_y;
1759 *pix_x = CHAR_TO_PIXEL_COL (f, x);
1760 *pix_y = CHAR_TO_PIXEL_ROW (f, y);
1763 /* Prepare a mouse-event in *RESULT for placement in the input queue.
1765 If the event is a button press, then note that we have grabbed
1766 the mouse. */
1768 static Lisp_Object
1769 construct_mouse_click (result, event, f)
1770 struct input_event *result;
1771 XButtonEvent *event;
1772 struct frame *f;
1774 /* Make the event type no_event; we'll change that when we decide
1775 otherwise. */
1776 result->kind = mouse_click;
1777 result->code = event->button - Button1;
1778 result->timestamp = event->time;
1779 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
1780 event->state)
1781 | (event->type == ButtonRelease
1782 ? up_modifier
1783 : down_modifier));
1786 int row, column;
1788 #if 0
1789 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
1790 XSETFASTINT (result->x, column);
1791 XSETFASTINT (result->y, row);
1792 #endif
1793 XSETINT (result->x, event->x);
1794 XSETINT (result->y, event->y);
1795 XSETFRAME (result->frame_or_window, f);
1799 /* Prepare a menu-event in *RESULT for placement in the input queue. */
1801 static Lisp_Object
1802 construct_menu_click (result, event, f)
1803 struct input_event *result;
1804 XButtonEvent *event;
1805 struct frame *f;
1807 /* Make the event type no_event; we'll change that when we decide
1808 otherwise. */
1809 result->kind = mouse_click;
1810 XSETINT (result->code, event->button - Button1);
1811 result->timestamp = event->time;
1812 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
1813 event->state)
1814 | (event->type == ButtonRelease
1815 ? up_modifier
1816 : down_modifier));
1818 XSETINT (result->x, event->x);
1819 XSETINT (result->y, -1);
1820 XSETFRAME (result->frame_or_window, f);
1823 /* Function to report a mouse movement to the mainstream Emacs code.
1824 The input handler calls this.
1826 We have received a mouse movement event, which is given in *event.
1827 If the mouse is over a different glyph than it was last time, tell
1828 the mainstream emacs code by setting mouse_moved. If not, ask for
1829 another motion event, so we can check again the next time it moves. */
1831 static void
1832 note_mouse_movement (frame, event)
1833 FRAME_PTR frame;
1834 XMotionEvent *event;
1836 last_mouse_movement_time = event->time;
1838 if (event->window != FRAME_X_WINDOW (frame))
1840 frame->mouse_moved = 1;
1841 last_mouse_scroll_bar = Qnil;
1843 note_mouse_highlight (frame, -1, -1);
1845 /* Ask for another mouse motion event. */
1847 int dummy;
1848 Window dummy_window;
1850 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1851 &dummy_window, &dummy_window,
1852 &dummy, &dummy, &dummy, &dummy,
1853 (unsigned int *) &dummy);
1857 /* Has the mouse moved off the glyph it was on at the last sighting? */
1858 else if (event->x < last_mouse_glyph.x
1859 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
1860 || event->y < last_mouse_glyph.y
1861 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
1863 frame->mouse_moved = 1;
1864 last_mouse_scroll_bar = Qnil;
1866 note_mouse_highlight (frame, event->x, event->y);
1868 /* Ask for another mouse motion event. */
1870 int dummy;
1871 Window dummy_window;
1873 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1874 &dummy_window, &dummy_window,
1875 &dummy, &dummy, &dummy, &dummy,
1876 (unsigned int *) &dummy);
1879 else
1881 /* It's on the same glyph. Call XQueryPointer so we'll get an
1882 event the next time the mouse moves and we can see if it's
1883 *still* on the same glyph. */
1884 int dummy;
1885 Window dummy_window;
1887 XQueryPointer (event->display, FRAME_X_WINDOW (frame),
1888 &dummy_window, &dummy_window,
1889 &dummy, &dummy, &dummy, &dummy,
1890 (unsigned int *) &dummy);
1894 /* This is used for debugging, to turn off note_mouse_highlight. */
1895 static int disable_mouse_highlight;
1897 /* Take proper action when the mouse has moved to position X, Y on frame F
1898 as regards highlighting characters that have mouse-face properties.
1899 Also dehighlighting chars where the mouse was before.
1900 X and Y can be negative or out of range. */
1902 static void
1903 note_mouse_highlight (f, x, y)
1904 FRAME_PTR f;
1905 int x, y;
1907 int row, column, portion;
1908 XRectangle new_glyph;
1909 Lisp_Object window;
1910 struct window *w;
1912 if (disable_mouse_highlight)
1913 return;
1915 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
1916 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
1917 FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
1919 if (FRAME_X_DISPLAY_INFO (f)->mouse_face_defer)
1920 return;
1922 if (gc_in_progress)
1924 FRAME_X_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
1925 return;
1928 /* Find out which glyph the mouse is on. */
1929 pixel_to_glyph_coords (f, x, y, &column, &row,
1930 &new_glyph, FRAME_X_DISPLAY_INFO (f)->grabbed);
1932 /* Which window is that in? */
1933 window = window_from_coordinates (f, column, row, &portion);
1934 w = XWINDOW (window);
1936 /* If we were displaying active text in another window, clear that. */
1937 if (! EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window))
1938 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1940 /* Are we in a window whose display is up to date?
1941 And verify the buffer's text has not changed. */
1942 if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
1943 && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
1944 && EQ (w->window_end_valid, w->buffer)
1945 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer)))
1947 int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
1948 int i, pos;
1950 /* Find which buffer position the mouse corresponds to. */
1951 for (i = column; i >= 0; i--)
1952 if (ptr[i] > 0)
1953 break;
1954 pos = ptr[i];
1955 /* Is it outside the displayed active region (if any)? */
1956 if (pos <= 0)
1957 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1958 else if (! (EQ (window, FRAME_X_DISPLAY_INFO (f)->mouse_face_window)
1959 && row >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
1960 && row <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
1961 && (row > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
1962 || column >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col)
1963 && (row < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
1964 || column < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
1965 || FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end)))
1967 Lisp_Object mouse_face, overlay, position;
1968 Lisp_Object *overlay_vec;
1969 int len, noverlays, ignor1;
1970 struct buffer *obuf;
1971 int obegv, ozv;
1973 /* If we get an out-of-range value, return now; avoid an error. */
1974 if (pos > BUF_Z (XBUFFER (w->buffer)))
1975 return;
1977 /* Make the window's buffer temporarily current for
1978 overlays_at and compute_char_face. */
1979 obuf = current_buffer;
1980 current_buffer = XBUFFER (w->buffer);
1981 obegv = BEGV;
1982 ozv = ZV;
1983 BEGV = BEG;
1984 ZV = Z;
1986 /* Yes. Clear the display of the old active region, if any. */
1987 clear_mouse_face (FRAME_X_DISPLAY_INFO (f));
1989 /* Is this char mouse-active? */
1990 XSETINT (position, pos);
1992 len = 10;
1993 overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
1995 /* Put all the overlays we want in a vector in overlay_vec.
1996 Store the length in len. */
1997 noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
1998 NULL, NULL);
1999 noverlays = sort_overlays (overlay_vec, noverlays, w);
2001 /* Find the highest priority overlay that has a mouse-face prop. */
2002 overlay = Qnil;
2003 for (i = 0; i < noverlays; i++)
2005 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
2006 if (!NILP (mouse_face))
2008 overlay = overlay_vec[i];
2009 break;
2012 free (overlay_vec);
2013 /* If no overlay applies, get a text property. */
2014 if (NILP (overlay))
2015 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
2017 /* Handle the overlay case. */
2018 if (! NILP (overlay))
2020 /* Find the range of text around this char that
2021 should be active. */
2022 Lisp_Object before, after;
2023 int ignore;
2025 before = Foverlay_start (overlay);
2026 after = Foverlay_end (overlay);
2027 /* Record this as the current active region. */
2028 fast_find_position (window, before,
2029 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
2030 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
2031 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
2032 = !fast_find_position (window, after,
2033 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
2034 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
2035 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
2036 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
2037 = compute_char_face (f, w, pos, 0, 0,
2038 &ignore, pos + 1, 1);
2040 /* Display it as active. */
2041 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
2043 /* Handle the text property case. */
2044 else if (! NILP (mouse_face))
2046 /* Find the range of text around this char that
2047 should be active. */
2048 Lisp_Object before, after, beginning, end;
2049 int ignore;
2051 beginning = Fmarker_position (w->start);
2052 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
2053 - XFASTINT (w->window_end_pos)));
2054 before
2055 = Fprevious_single_property_change (make_number (pos + 1),
2056 Qmouse_face,
2057 w->buffer, beginning);
2058 after
2059 = Fnext_single_property_change (position, Qmouse_face,
2060 w->buffer, end);
2061 /* Record this as the current active region. */
2062 fast_find_position (window, before,
2063 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col,
2064 &FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row);
2065 FRAME_X_DISPLAY_INFO (f)->mouse_face_past_end
2066 = !fast_find_position (window, after,
2067 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col,
2068 &FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row);
2069 FRAME_X_DISPLAY_INFO (f)->mouse_face_window = window;
2070 FRAME_X_DISPLAY_INFO (f)->mouse_face_face_id
2071 = compute_char_face (f, w, pos, 0, 0,
2072 &ignore, pos + 1, 1);
2074 /* Display it as active. */
2075 show_mouse_face (FRAME_X_DISPLAY_INFO (f), 1);
2077 BEGV = obegv;
2078 ZV = ozv;
2079 current_buffer = obuf;
2084 /* Find the row and column of position POS in window WINDOW.
2085 Store them in *COLUMNP and *ROWP.
2086 This assumes display in WINDOW is up to date.
2087 If POS is above start of WINDOW, return coords
2088 of start of first screen line.
2089 If POS is after end of WINDOW, return coords of end of last screen line.
2091 Value is 1 if POS is in range, 0 if it was off screen. */
2093 static int
2094 fast_find_position (window, pos, columnp, rowp)
2095 Lisp_Object window;
2096 int pos;
2097 int *columnp, *rowp;
2099 struct window *w = XWINDOW (window);
2100 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2101 int i;
2102 int row = 0;
2103 int left = w->left;
2104 int top = w->top;
2105 int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
2106 int width = window_internal_width (w);
2107 int *charstarts;
2108 int lastcol;
2109 int maybe_next_line = 0;
2111 /* Find the right row. */
2112 for (i = 0;
2113 i < height;
2114 i++)
2116 int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
2117 if (linestart > pos)
2118 break;
2119 /* If the position sought is the end of the buffer,
2120 don't include the blank lines at the bottom of the window. */
2121 if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
2123 maybe_next_line = 1;
2124 break;
2126 if (linestart > 0)
2127 row = i;
2130 /* Find the right column with in it. */
2131 charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
2132 lastcol = left;
2133 for (i = 0; i < width; i++)
2135 if (charstarts[left + i] == pos)
2137 *rowp = row + top;
2138 *columnp = i + left;
2139 return 1;
2141 else if (charstarts[left + i] > pos)
2142 break;
2143 else if (charstarts[left + i] > 0)
2144 lastcol = left + i;
2147 /* If we're looking for the end of the buffer,
2148 and we didn't find it in the line we scanned,
2149 use the start of the following line. */
2150 if (maybe_next_line)
2152 row++;
2153 i = 0;
2156 *rowp = row + top;
2157 *columnp = lastcol;
2158 return 0;
2161 /* Display the active region described by mouse_face_*
2162 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2164 static void
2165 show_mouse_face (dpyinfo, hl)
2166 struct x_display_info *dpyinfo;
2167 int hl;
2169 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
2170 int width = window_internal_width (w);
2171 FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
2172 int i;
2173 int cursor_off = 0;
2174 int old_curs_x = curs_x;
2175 int old_curs_y = curs_y;
2177 /* Set these variables temporarily
2178 so that if we have to turn the cursor off and on again
2179 we will put it back at the same place. */
2180 curs_x = f->phys_cursor_x;
2181 curs_y = f->phys_cursor_y;
2183 for (i = FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row;
2184 i <= FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row; i++)
2186 int column = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
2187 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col
2188 : w->left);
2189 int endcolumn = (i == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
2190 ? FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col
2191 : w->left + width);
2192 endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
2194 /* If the cursor's in the text we are about to rewrite,
2195 turn the cursor off. */
2196 if (i == curs_y
2197 && curs_x >= column - 1
2198 && curs_x <= endcolumn)
2200 x_display_cursor (f, 0);
2201 cursor_off = 1;
2204 dumpglyphs (f,
2205 CHAR_TO_PIXEL_COL (f, column),
2206 CHAR_TO_PIXEL_ROW (f, i),
2207 FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
2208 endcolumn - column,
2209 /* Highlight with mouse face if hl > 0. */
2210 hl > 0 ? 3 : 0, 0);
2213 /* If we turned the cursor off, turn it back on. */
2214 if (cursor_off)
2215 x_display_cursor (f, 1);
2217 curs_x = old_curs_x;
2218 curs_y = old_curs_y;
2220 /* Change the mouse cursor according to the value of HL. */
2221 if (hl > 0)
2222 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2223 f->output_data.x->cross_cursor);
2224 else
2225 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2226 f->output_data.x->text_cursor);
2229 /* Clear out the mouse-highlighted active region.
2230 Redraw it unhighlighted first. */
2232 static void
2233 clear_mouse_face (dpyinfo)
2234 struct x_display_info *dpyinfo;
2236 if (! NILP (dpyinfo->mouse_face_window))
2237 show_mouse_face (dpyinfo, 0);
2239 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
2240 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
2241 dpyinfo->mouse_face_window = Qnil;
2244 static struct scroll_bar *x_window_to_scroll_bar ();
2245 static void x_scroll_bar_report_motion ();
2247 /* Return the current position of the mouse.
2248 *fp should be a frame which indicates which display to ask about.
2250 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2251 and *part to the frame, window, and scroll bar part that the mouse
2252 is over. Set *x and *y to the portion and whole of the mouse's
2253 position on the scroll bar.
2255 If the mouse movement started elsewhere, set *fp to the frame the
2256 mouse is on, *bar_window to nil, and *x and *y to the character cell
2257 the mouse is over.
2259 Set *time to the server timestamp for the time at which the mouse
2260 was at this position.
2262 Don't store anything if we don't have a valid set of values to report.
2264 This clears the mouse_moved flag, so we can wait for the next mouse
2265 movement. This also calls XQueryPointer, which will cause the
2266 server to give us another MotionNotify when the mouse moves
2267 again. */
2269 static void
2270 XTmouse_position (fp, insist, bar_window, part, x, y, time)
2271 FRAME_PTR *fp;
2272 int insist;
2273 Lisp_Object *bar_window;
2274 enum scroll_bar_part *part;
2275 Lisp_Object *x, *y;
2276 unsigned long *time;
2278 FRAME_PTR f1;
2280 BLOCK_INPUT;
2282 if (! NILP (last_mouse_scroll_bar))
2283 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
2284 else
2286 Window root;
2287 int root_x, root_y;
2289 Window dummy_window;
2290 int dummy;
2292 Lisp_Object frame, tail;
2294 /* Clear the mouse-moved flag for every frame on this display. */
2295 FOR_EACH_FRAME (tail, frame)
2296 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
2297 XFRAME (frame)->mouse_moved = 0;
2299 last_mouse_scroll_bar = Qnil;
2301 /* Figure out which root window we're on. */
2302 XQueryPointer (FRAME_X_DISPLAY (*fp),
2303 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
2305 /* The root window which contains the pointer. */
2306 &root,
2308 /* Trash which we can't trust if the pointer is on
2309 a different screen. */
2310 &dummy_window,
2312 /* The position on that root window. */
2313 &root_x, &root_y,
2315 /* More trash we can't trust. */
2316 &dummy, &dummy,
2318 /* Modifier keys and pointer buttons, about which
2319 we don't care. */
2320 (unsigned int *) &dummy);
2322 /* Now we have a position on the root; find the innermost window
2323 containing the pointer. */
2325 Window win, child;
2326 int win_x, win_y;
2327 int parent_x, parent_y;
2329 win = root;
2331 /* XTranslateCoordinates can get errors if the window
2332 structure is changing at the same time this function
2333 is running. So at least we must not crash from them. */
2335 x_catch_errors (FRAME_X_DISPLAY (*fp));
2337 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
2338 && FRAME_LIVE_P (last_mouse_frame))
2340 /* If mouse was grabbed on a frame, give coords for that frame
2341 even if the mouse is now outside it. */
2342 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
2344 /* From-window, to-window. */
2345 root, FRAME_X_WINDOW (last_mouse_frame),
2347 /* From-position, to-position. */
2348 root_x, root_y, &win_x, &win_y,
2350 /* Child of win. */
2351 &child);
2352 f1 = last_mouse_frame;
2354 else
2356 while (1)
2358 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
2360 /* From-window, to-window. */
2361 root, win,
2363 /* From-position, to-position. */
2364 root_x, root_y, &win_x, &win_y,
2366 /* Child of win. */
2367 &child);
2369 if (child == None || child == win)
2370 break;
2372 win = child;
2373 parent_x = win_x;
2374 parent_y = win_y;
2377 /* Now we know that:
2378 win is the innermost window containing the pointer
2379 (XTC says it has no child containing the pointer),
2380 win_x and win_y are the pointer's position in it
2381 (XTC did this the last time through), and
2382 parent_x and parent_y are the pointer's position in win's parent.
2383 (They are what win_x and win_y were when win was child.
2384 If win is the root window, it has no parent, and
2385 parent_{x,y} are invalid, but that's okay, because we'll
2386 never use them in that case.) */
2388 /* Is win one of our frames? */
2389 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
2392 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
2393 f1 = 0;
2395 x_uncatch_errors (FRAME_X_DISPLAY (*fp));
2397 /* If not, is it one of our scroll bars? */
2398 if (! f1)
2400 struct scroll_bar *bar = x_window_to_scroll_bar (win);
2402 if (bar)
2404 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2405 win_x = parent_x;
2406 win_y = parent_y;
2410 if (f1 == 0 && insist)
2411 f1 = selected_frame;
2413 if (f1)
2415 int ignore1, ignore2;
2417 /* Ok, we found a frame. Store all the values. */
2419 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
2420 &last_mouse_glyph,
2421 FRAME_X_DISPLAY_INFO (f1)->grabbed
2422 || insist);
2424 *bar_window = Qnil;
2425 *part = 0;
2426 *fp = f1;
2427 XSETINT (*x, win_x);
2428 XSETINT (*y, win_y);
2429 *time = last_mouse_movement_time;
2434 UNBLOCK_INPUT;
2437 /* Scroll bar support. */
2439 /* Given an X window ID, find the struct scroll_bar which manages it.
2440 This can be called in GC, so we have to make sure to strip off mark
2441 bits. */
2442 static struct scroll_bar *
2443 x_window_to_scroll_bar (window_id)
2444 Window window_id;
2446 Lisp_Object tail, frame;
2448 for (tail = Vframe_list;
2449 XGCTYPE (tail) == Lisp_Cons;
2450 tail = XCONS (tail)->cdr)
2452 Lisp_Object frame, bar, condemned;
2454 frame = XCONS (tail)->car;
2455 /* All elements of Vframe_list should be frames. */
2456 if (! GC_FRAMEP (frame))
2457 abort ();
2459 /* Scan this frame's scroll bar list for a scroll bar with the
2460 right window ID. */
2461 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
2462 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
2463 /* This trick allows us to search both the ordinary and
2464 condemned scroll bar lists with one loop. */
2465 ! GC_NILP (bar) || (bar = condemned,
2466 condemned = Qnil,
2467 ! GC_NILP (bar));
2468 bar = XSCROLL_BAR (bar)->next)
2469 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
2470 return XSCROLL_BAR (bar);
2473 return 0;
2476 /* Open a new X window to serve as a scroll bar, and return the
2477 scroll bar vector for it. */
2478 static struct scroll_bar *
2479 x_scroll_bar_create (window, top, left, width, height)
2480 struct window *window;
2481 int top, left, width, height;
2483 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2484 struct scroll_bar *bar
2485 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
2487 BLOCK_INPUT;
2490 XSetWindowAttributes a;
2491 unsigned long mask;
2492 a.background_pixel = f->output_data.x->background_pixel;
2493 a.event_mask = (ButtonPressMask | ButtonReleaseMask
2494 | ButtonMotionMask | PointerMotionHintMask
2495 | ExposureMask);
2496 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
2498 mask = (CWBackPixel | CWEventMask | CWCursor);
2500 #if 0
2502 ac = 0;
2503 XtSetArg (al[ac], XtNx, left); ac++;
2504 XtSetArg (al[ac], XtNy, top); ac++;
2505 XtSetArg (al[ac], XtNwidth, width); ac++;
2506 XtSetArg (al[ac], XtNheight, height); ac++;
2507 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2508 sb_widget = XtCreateManagedWidget ("box",
2509 boxWidgetClass,
2510 f->output_data.x->edit_widget, al, ac);
2511 SET_SCROLL_BAR_X_WINDOW
2512 (bar, sb_widget->core.window);
2513 #endif
2514 SET_SCROLL_BAR_X_WINDOW
2515 (bar,
2516 XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2518 /* Position and size of scroll bar. */
2519 left, top, width, height,
2521 /* Border width, depth, class, and visual. */
2522 0, CopyFromParent, CopyFromParent, CopyFromParent,
2524 /* Attributes. */
2525 mask, &a));
2528 XSETWINDOW (bar->window, window);
2529 XSETINT (bar->top, top);
2530 XSETINT (bar->left, left);
2531 XSETINT (bar->width, width);
2532 XSETINT (bar->height, height);
2533 XSETINT (bar->start, 0);
2534 XSETINT (bar->end, 0);
2535 bar->dragging = Qnil;
2537 /* Add bar to its frame's list of scroll bars. */
2538 bar->next = FRAME_SCROLL_BARS (f);
2539 bar->prev = Qnil;
2540 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2541 if (! NILP (bar->next))
2542 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2544 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
2546 UNBLOCK_INPUT;
2548 return bar;
2551 /* Draw BAR's handle in the proper position.
2552 If the handle is already drawn from START to END, don't bother
2553 redrawing it, unless REBUILD is non-zero; in that case, always
2554 redraw it. (REBUILD is handy for drawing the handle after expose
2555 events.)
2557 Normally, we want to constrain the start and end of the handle to
2558 fit inside its rectangle, but if the user is dragging the scroll bar
2559 handle, we want to let them drag it down all the way, so that the
2560 bar's top is as far down as it goes; otherwise, there's no way to
2561 move to the very end of the buffer. */
2562 static void
2563 x_scroll_bar_set_handle (bar, start, end, rebuild)
2564 struct scroll_bar *bar;
2565 int start, end;
2566 int rebuild;
2568 int dragging = ! NILP (bar->dragging);
2569 Window w = SCROLL_BAR_X_WINDOW (bar);
2570 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2571 GC gc = f->output_data.x->normal_gc;
2573 /* If the display is already accurate, do nothing. */
2574 if (! rebuild
2575 && start == XINT (bar->start)
2576 && end == XINT (bar->end))
2577 return;
2579 BLOCK_INPUT;
2582 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (XINT (bar->width));
2583 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2584 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2586 /* Make sure the values are reasonable, and try to preserve
2587 the distance between start and end. */
2589 int length = end - start;
2591 if (start < 0)
2592 start = 0;
2593 else if (start > top_range)
2594 start = top_range;
2595 end = start + length;
2597 if (end < start)
2598 end = start;
2599 else if (end > top_range && ! dragging)
2600 end = top_range;
2603 /* Store the adjusted setting in the scroll bar. */
2604 XSETINT (bar->start, start);
2605 XSETINT (bar->end, end);
2607 /* Clip the end position, just for display. */
2608 if (end > top_range)
2609 end = top_range;
2611 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2612 below top positions, to make sure the handle is always at least
2613 that many pixels tall. */
2614 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
2616 /* Draw the empty space above the handle. Note that we can't clear
2617 zero-height areas; that means "clear to end of window." */
2618 if (0 < start)
2619 XClearArea (FRAME_X_DISPLAY (f), w,
2621 /* x, y, width, height, and exposures. */
2622 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2623 VERTICAL_SCROLL_BAR_TOP_BORDER,
2624 inside_width, start,
2625 False);
2627 /* Draw the handle itself. */
2628 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
2630 /* x, y, width, height */
2631 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2632 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
2633 inside_width, end - start);
2636 /* Draw the empty space below the handle. Note that we can't
2637 clear zero-height areas; that means "clear to end of window." */
2638 if (end < inside_height)
2639 XClearArea (FRAME_X_DISPLAY (f), w,
2641 /* x, y, width, height, and exposures. */
2642 VERTICAL_SCROLL_BAR_LEFT_BORDER,
2643 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
2644 inside_width, inside_height - end,
2645 False);
2649 UNBLOCK_INPUT;
2652 /* Move a scroll bar around on the screen, to accommodate changing
2653 window configurations. */
2654 static void
2655 x_scroll_bar_move (bar, top, left, width, height)
2656 struct scroll_bar *bar;
2657 int top, left, width, height;
2659 Window w = SCROLL_BAR_X_WINDOW (bar);
2660 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2662 BLOCK_INPUT;
2665 XWindowChanges wc;
2666 unsigned int mask = 0;
2668 wc.x = left;
2669 wc.y = top;
2670 wc.width = width;
2671 wc.height = height;
2673 if (left != XINT (bar->left)) mask |= CWX;
2674 if (top != XINT (bar->top)) mask |= CWY;
2675 if (width != XINT (bar->width)) mask |= CWWidth;
2676 if (height != XINT (bar->height)) mask |= CWHeight;
2678 if (mask)
2679 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
2680 mask, &wc);
2683 XSETINT (bar->left, left);
2684 XSETINT (bar->top, top);
2685 XSETINT (bar->width, width);
2686 XSETINT (bar->height, height);
2688 UNBLOCK_INPUT;
2691 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
2692 to nil. */
2693 static void
2694 x_scroll_bar_remove (bar)
2695 struct scroll_bar *bar;
2697 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2699 BLOCK_INPUT;
2701 /* Destroy the window. */
2702 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
2704 /* Disassociate this scroll bar from its window. */
2705 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
2707 UNBLOCK_INPUT;
2710 /* Set the handle of the vertical scroll bar for WINDOW to indicate
2711 that we are displaying PORTION characters out of a total of WHOLE
2712 characters, starting at POSITION. If WINDOW has no scroll bar,
2713 create one. */
2714 static void
2715 XTset_vertical_scroll_bar (window, portion, whole, position)
2716 struct window *window;
2717 int portion, whole, position;
2719 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2720 int top = XINT (window->top);
2721 int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
2722 int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
2724 /* Where should this scroll bar be, pixelwise? */
2725 int pixel_top = CHAR_TO_PIXEL_ROW (f, top);
2726 int pixel_left = CHAR_TO_PIXEL_COL (f, left);
2727 int pixel_width
2728 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
2729 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
2730 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
2731 int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
2733 struct scroll_bar *bar;
2735 /* Does the scroll bar exist yet? */
2736 if (NILP (window->vertical_scroll_bar))
2737 bar = x_scroll_bar_create (window,
2738 pixel_top, pixel_left,
2739 pixel_width, pixel_height);
2740 else
2742 /* It may just need to be moved and resized. */
2743 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2744 x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
2747 /* Set the scroll bar's current state, unless we're currently being
2748 dragged. */
2749 if (NILP (bar->dragging))
2751 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
2753 if (whole == 0)
2754 x_scroll_bar_set_handle (bar, 0, top_range, 0);
2755 else
2757 int start = ((double) position * top_range) / whole;
2758 int end = ((double) (position + portion) * top_range) / whole;
2760 x_scroll_bar_set_handle (bar, start, end, 0);
2764 XSETVECTOR (window->vertical_scroll_bar, bar);
2768 /* The following three hooks are used when we're doing a thorough
2769 redisplay of the frame. We don't explicitly know which scroll bars
2770 are going to be deleted, because keeping track of when windows go
2771 away is a real pain - "Can you say set-window-configuration, boys
2772 and girls?" Instead, we just assert at the beginning of redisplay
2773 that *all* scroll bars are to be removed, and then save a scroll bar
2774 from the fiery pit when we actually redisplay its window. */
2776 /* Arrange for all scroll bars on FRAME to be removed at the next call
2777 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
2778 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
2779 static void
2780 XTcondemn_scroll_bars (frame)
2781 FRAME_PTR frame;
2783 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
2784 while (! NILP (FRAME_SCROLL_BARS (frame)))
2786 Lisp_Object bar;
2787 bar = FRAME_SCROLL_BARS (frame);
2788 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
2789 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
2790 XSCROLL_BAR (bar)->prev = Qnil;
2791 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
2792 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
2793 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
2797 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
2798 Note that WINDOW isn't necessarily condemned at all. */
2799 static void
2800 XTredeem_scroll_bar (window)
2801 struct window *window;
2803 struct scroll_bar *bar;
2805 /* We can't redeem this window's scroll bar if it doesn't have one. */
2806 if (NILP (window->vertical_scroll_bar))
2807 abort ();
2809 bar = XSCROLL_BAR (window->vertical_scroll_bar);
2811 /* Unlink it from the condemned list. */
2813 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
2815 if (NILP (bar->prev))
2817 /* If the prev pointer is nil, it must be the first in one of
2818 the lists. */
2819 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
2820 /* It's not condemned. Everything's fine. */
2821 return;
2822 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
2823 window->vertical_scroll_bar))
2824 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
2825 else
2826 /* If its prev pointer is nil, it must be at the front of
2827 one or the other! */
2828 abort ();
2830 else
2831 XSCROLL_BAR (bar->prev)->next = bar->next;
2833 if (! NILP (bar->next))
2834 XSCROLL_BAR (bar->next)->prev = bar->prev;
2836 bar->next = FRAME_SCROLL_BARS (f);
2837 bar->prev = Qnil;
2838 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
2839 if (! NILP (bar->next))
2840 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
2844 /* Remove all scroll bars on FRAME that haven't been saved since the
2845 last call to `*condemn_scroll_bars_hook'. */
2846 static void
2847 XTjudge_scroll_bars (f)
2848 FRAME_PTR f;
2850 Lisp_Object bar, next;
2852 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
2854 /* Clear out the condemned list now so we won't try to process any
2855 more events on the hapless scroll bars. */
2856 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
2858 for (; ! NILP (bar); bar = next)
2860 struct scroll_bar *b = XSCROLL_BAR (bar);
2862 x_scroll_bar_remove (b);
2864 next = b->next;
2865 b->next = b->prev = Qnil;
2868 /* Now there should be no references to the condemned scroll bars,
2869 and they should get garbage-collected. */
2873 /* Handle an Expose or GraphicsExpose event on a scroll bar.
2875 This may be called from a signal handler, so we have to ignore GC
2876 mark bits. */
2877 static void
2878 x_scroll_bar_expose (bar, event)
2879 struct scroll_bar *bar;
2880 XEvent *event;
2882 Window w = SCROLL_BAR_X_WINDOW (bar);
2883 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
2884 GC gc = f->output_data.x->normal_gc;
2886 BLOCK_INPUT;
2888 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
2890 /* Draw a one-pixel border just inside the edges of the scroll bar. */
2891 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
2893 /* x, y, width, height */
2894 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
2896 UNBLOCK_INPUT;
2899 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2900 is set to something other than no_event, it is enqueued.
2902 This may be called from a signal handler, so we have to ignore GC
2903 mark bits. */
2904 static void
2905 x_scroll_bar_handle_click (bar, event, emacs_event)
2906 struct scroll_bar *bar;
2907 XEvent *event;
2908 struct input_event *emacs_event;
2910 if (! GC_WINDOWP (bar->window))
2911 abort ();
2913 emacs_event->kind = scroll_bar_click;
2914 emacs_event->code = event->xbutton.button - Button1;
2915 emacs_event->modifiers
2916 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
2917 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
2918 event->xbutton.state)
2919 | (event->type == ButtonRelease
2920 ? up_modifier
2921 : down_modifier));
2922 emacs_event->frame_or_window = bar->window;
2923 emacs_event->timestamp = event->xbutton.time;
2925 int internal_height
2926 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
2927 int top_range
2928 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
2929 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
2931 if (y < 0) y = 0;
2932 if (y > top_range) y = top_range;
2934 if (y < XINT (bar->start))
2935 emacs_event->part = scroll_bar_above_handle;
2936 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
2937 emacs_event->part = scroll_bar_handle;
2938 else
2939 emacs_event->part = scroll_bar_below_handle;
2941 /* Just because the user has clicked on the handle doesn't mean
2942 they want to drag it. Lisp code needs to be able to decide
2943 whether or not we're dragging. */
2944 #if 0
2945 /* If the user has just clicked on the handle, record where they're
2946 holding it. */
2947 if (event->type == ButtonPress
2948 && emacs_event->part == scroll_bar_handle)
2949 XSETINT (bar->dragging, y - XINT (bar->start));
2950 #endif
2952 /* If the user has released the handle, set it to its final position. */
2953 if (event->type == ButtonRelease
2954 && ! NILP (bar->dragging))
2956 int new_start = y - XINT (bar->dragging);
2957 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
2959 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
2960 bar->dragging = Qnil;
2963 /* Same deal here as the other #if 0. */
2964 #if 0
2965 /* Clicks on the handle are always reported as occurring at the top of
2966 the handle. */
2967 if (emacs_event->part == scroll_bar_handle)
2968 emacs_event->x = bar->start;
2969 else
2970 XSETINT (emacs_event->x, y);
2971 #else
2972 XSETINT (emacs_event->x, y);
2973 #endif
2975 XSETINT (emacs_event->y, top_range);
2979 /* Handle some mouse motion while someone is dragging the scroll bar.
2981 This may be called from a signal handler, so we have to ignore GC
2982 mark bits. */
2983 static void
2984 x_scroll_bar_note_movement (bar, event)
2985 struct scroll_bar *bar;
2986 XEvent *event;
2988 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
2990 last_mouse_movement_time = event->xmotion.time;
2992 f->mouse_moved = 1;
2993 XSETVECTOR (last_mouse_scroll_bar, bar);
2995 /* If we're dragging the bar, display it. */
2996 if (! GC_NILP (bar->dragging))
2998 /* Where should the handle be now? */
2999 int new_start = event->xmotion.y - XINT (bar->dragging);
3001 if (new_start != XINT (bar->start))
3003 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
3005 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
3009 /* Call XQueryPointer so we'll get an event the next time the mouse
3010 moves and we can see *still* on the same position. */
3012 int dummy;
3013 Window dummy_window;
3015 XQueryPointer (event->xmotion.display, event->xmotion.window,
3016 &dummy_window, &dummy_window,
3017 &dummy, &dummy, &dummy, &dummy,
3018 (unsigned int *) &dummy);
3022 /* Return information to the user about the current position of the mouse
3023 on the scroll bar. */
3024 static void
3025 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
3026 FRAME_PTR *fp;
3027 Lisp_Object *bar_window;
3028 enum scroll_bar_part *part;
3029 Lisp_Object *x, *y;
3030 unsigned long *time;
3032 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
3033 Window w = SCROLL_BAR_X_WINDOW (bar);
3034 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
3035 int win_x, win_y;
3036 Window dummy_window;
3037 int dummy_coord;
3038 unsigned int dummy_mask;
3040 BLOCK_INPUT;
3042 /* Get the mouse's position relative to the scroll bar window, and
3043 report that. */
3044 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
3046 /* Root, child, root x and root y. */
3047 &dummy_window, &dummy_window,
3048 &dummy_coord, &dummy_coord,
3050 /* Position relative to scroll bar. */
3051 &win_x, &win_y,
3053 /* Mouse buttons and modifier keys. */
3054 &dummy_mask))
3056 else
3058 int inside_height
3059 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (XINT (bar->height));
3060 int top_range
3061 = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
3063 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
3065 if (! NILP (bar->dragging))
3066 win_y -= XINT (bar->dragging);
3068 if (win_y < 0)
3069 win_y = 0;
3070 if (win_y > top_range)
3071 win_y = top_range;
3073 *fp = f;
3074 *bar_window = bar->window;
3076 if (! NILP (bar->dragging))
3077 *part = scroll_bar_handle;
3078 else if (win_y < XINT (bar->start))
3079 *part = scroll_bar_above_handle;
3080 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
3081 *part = scroll_bar_handle;
3082 else
3083 *part = scroll_bar_below_handle;
3085 XSETINT (*x, win_y);
3086 XSETINT (*y, top_range);
3088 f->mouse_moved = 0;
3089 last_mouse_scroll_bar = Qnil;
3092 *time = last_mouse_movement_time;
3094 UNBLOCK_INPUT;
3098 /* The screen has been cleared so we may have changed foreground or
3099 background colors, and the scroll bars may need to be redrawn.
3100 Clear out the scroll bars, and ask for expose events, so we can
3101 redraw them. */
3103 x_scroll_bar_clear (f)
3104 FRAME_PTR f;
3106 Lisp_Object bar;
3108 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
3109 bar = XSCROLL_BAR (bar)->next)
3110 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
3111 0, 0, 0, 0, True);
3114 /* This processes Expose events from the menubar specific X event
3115 loop in xmenu.c. This allows to redisplay the frame if necessary
3116 when handling menubar or popup items. */
3118 void
3119 process_expose_from_menu (event)
3120 XEvent event;
3122 FRAME_PTR f;
3123 struct x_display_info *dpyinfo;
3125 BLOCK_INPUT;
3127 dpyinfo = x_display_info_for_display (event.xexpose.display);
3128 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3129 if (f)
3131 if (f->async_visible == 0)
3133 f->async_visible = 1;
3134 f->async_iconified = 0;
3135 SET_FRAME_GARBAGED (f);
3137 else
3139 dumprectangle (x_window_to_frame (dpyinfo, event.xexpose.window),
3140 event.xexpose.x, event.xexpose.y,
3141 event.xexpose.width, event.xexpose.height);
3144 else
3146 struct scroll_bar *bar
3147 = x_window_to_scroll_bar (event.xexpose.window);
3149 if (bar)
3150 x_scroll_bar_expose (bar, &event);
3153 UNBLOCK_INPUT;
3156 /* Define a queue to save up SelectionRequest events for later handling. */
3158 struct selection_event_queue
3160 XEvent event;
3161 struct selection_event_queue *next;
3164 static struct selection_event_queue *queue;
3166 /* Nonzero means queue up certain events--don't process them yet. */
3167 static int x_queue_selection_requests;
3169 /* Queue up an X event *EVENT, to be processed later. */
3171 static void
3172 x_queue_event (f, event)
3173 FRAME_PTR f;
3174 XEvent *event;
3176 struct selection_event_queue *queue_tmp
3177 = (struct selection_event_queue *) malloc (sizeof (struct selection_event_queue));
3179 if (queue_tmp != NULL)
3181 queue_tmp->event = *event;
3182 queue_tmp->next = queue;
3183 queue = queue_tmp;
3187 /* Take all the queued events and put them back
3188 so that they get processed afresh. */
3190 static void
3191 x_unqueue_events (display)
3192 Display *display;
3194 while (queue != NULL)
3196 struct selection_event_queue *queue_tmp = queue;
3197 XPutBackEvent (display, &queue_tmp->event);
3198 queue = queue_tmp->next;
3199 free ((char *)queue_tmp);
3203 /* Start queuing SelectionRequest events. */
3205 void
3206 x_start_queuing_selection_requests (display)
3207 Display *display;
3209 x_queue_selection_requests++;
3212 /* Stop queuing SelectionRequest events. */
3214 void
3215 x_stop_queuing_selection_requests (display)
3216 Display *display;
3218 x_queue_selection_requests--;
3219 x_unqueue_events (display);
3222 /* The main X event-reading loop - XTread_socket. */
3224 /* Timestamp of enter window event. This is only used by XTread_socket,
3225 but we have to put it out here, since static variables within functions
3226 sometimes don't work. */
3227 static Time enter_timestamp;
3229 /* This holds the state XLookupString needs to implement dead keys
3230 and other tricks known as "compose processing". _X Window System_
3231 says that a portable program can't use this, but Stephen Gildea assures
3232 me that letting the compiler initialize it to zeros will work okay.
3234 This must be defined outside of XTread_socket, for the same reasons
3235 given for enter_timestamp, above. */
3236 static XComposeStatus compose_status;
3238 /* Record the last 100 characters stored
3239 to help debug the loss-of-chars-during-GC problem. */
3240 static int temp_index;
3241 static short temp_buffer[100];
3243 /* Set this to nonzero to fake an "X I/O error"
3244 on a particular display. */
3245 struct x_display_info *XTread_socket_fake_io_error;
3247 /* When we find no input here, we occasionally do a no-op command
3248 to verify that the X server is still running and we can still talk with it.
3249 We try all the open displays, one by one.
3250 This variable is used for cycling thru the displays. */
3251 static struct x_display_info *next_noop_dpyinfo;
3253 /* Read events coming from the X server.
3254 This routine is called by the SIGIO handler.
3255 We return as soon as there are no more events to be read.
3257 Events representing keys are stored in buffer BUFP,
3258 which can hold up to NUMCHARS characters.
3259 We return the number of characters stored into the buffer,
3260 thus pretending to be `read'.
3262 WAITP is nonzero if we should block until input arrives.
3263 EXPECTED is nonzero if the caller knows input is available. */
3266 XTread_socket (sd, bufp, numchars, waitp, expected)
3267 register int sd;
3268 register struct input_event *bufp;
3269 register int numchars;
3270 int waitp;
3271 int expected;
3273 int count = 0;
3274 int nbytes = 0;
3275 int mask;
3276 int items_pending; /* How many items are in the X queue. */
3277 XEvent event;
3278 struct frame *f;
3279 int event_found = 0;
3280 int prefix;
3281 Lisp_Object part;
3282 struct x_display_info *dpyinfo;
3283 #ifdef HAVE_X_I18N
3284 Status status_return;
3285 #endif
3287 if (interrupt_input_blocked)
3289 interrupt_input_pending = 1;
3290 return -1;
3293 interrupt_input_pending = 0;
3294 BLOCK_INPUT;
3296 /* So people can tell when we have read the available input. */
3297 input_signal_count++;
3299 if (numchars <= 0)
3300 abort (); /* Don't think this happens. */
3302 /* Find the display we are supposed to read input for.
3303 It's the one communicating on descriptor SD. */
3304 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
3306 #if 0 /* This ought to be unnecessary; let's verify it. */
3307 #ifdef FIOSNBIO
3308 /* If available, Xlib uses FIOSNBIO to make the socket
3309 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3310 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3311 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3312 fcntl (dpyinfo->connection, F_SETFL, 0);
3313 #endif /* ! defined (FIOSNBIO) */
3314 #endif
3316 #if 0 /* This code can't be made to work, with multiple displays,
3317 and appears not to be used on any system any more.
3318 Also keyboard.c doesn't turn O_NDELAY on and off
3319 for X connections. */
3320 #ifndef SIGIO
3321 #ifndef HAVE_SELECT
3322 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
3324 extern int read_alarm_should_throw;
3325 read_alarm_should_throw = 1;
3326 XPeekEvent (dpyinfo->display, &event);
3327 read_alarm_should_throw = 0;
3329 #endif /* HAVE_SELECT */
3330 #endif /* SIGIO */
3331 #endif
3333 /* For debugging, this gives a way to fake an I/O error. */
3334 if (dpyinfo == XTread_socket_fake_io_error)
3336 XTread_socket_fake_io_error = 0;
3337 x_io_error_quitter (dpyinfo->display);
3340 while (XPending (dpyinfo->display) != 0)
3342 XNextEvent (dpyinfo->display, &event);
3343 event_found = 1;
3345 switch (event.type)
3347 case ClientMessage:
3349 if (event.xclient.message_type
3350 == dpyinfo->Xatom_wm_protocols
3351 && event.xclient.format == 32)
3353 if (event.xclient.data.l[0]
3354 == dpyinfo->Xatom_wm_take_focus)
3356 f = x_window_to_frame (dpyinfo, event.xclient.window);
3357 /* Since we set WM_TAKE_FOCUS, we must call
3358 XSetInputFocus explicitly. But not if f is null,
3359 since that might be an event for a deleted frame. */
3360 #ifdef HAVE_X_I18N
3361 /* Not quite sure this is needed -pd */
3362 if (f)
3363 XSetICFocus (FRAME_XIC (f));
3364 #endif
3365 if (f)
3366 XSetInputFocus (event.xclient.display,
3367 event.xclient.window,
3368 RevertToPointerRoot,
3369 event.xclient.data.l[1]);
3370 /* Not certain about handling scroll bars here */
3372 else if (event.xclient.data.l[0]
3373 == dpyinfo->Xatom_wm_save_yourself)
3375 /* Save state modify the WM_COMMAND property to
3376 something which can reinstate us. This notifies
3377 the session manager, who's looking for such a
3378 PropertyNotify. Can restart processing when
3379 a keyboard or mouse event arrives. */
3380 if (numchars > 0)
3382 f = x_top_window_to_frame (dpyinfo,
3383 event.xclient.window);
3385 /* This is just so we only give real data once
3386 for a single Emacs process. */
3387 if (f == selected_frame)
3388 XSetCommand (FRAME_X_DISPLAY (f),
3389 event.xclient.window,
3390 initial_argv, initial_argc);
3391 else
3392 XSetCommand (FRAME_X_DISPLAY (f),
3393 event.xclient.window,
3394 0, 0);
3397 else if (event.xclient.data.l[0]
3398 == dpyinfo->Xatom_wm_delete_window)
3400 struct frame *f
3401 = x_any_window_to_frame (dpyinfo,
3402 event.xclient.window);
3404 if (f)
3406 if (numchars == 0)
3407 abort ();
3409 bufp->kind = delete_window_event;
3410 XSETFRAME (bufp->frame_or_window, f);
3411 bufp++;
3413 count += 1;
3414 numchars -= 1;
3418 else if (event.xclient.message_type
3419 == dpyinfo->Xatom_wm_configure_denied)
3422 else if (event.xclient.message_type
3423 == dpyinfo->Xatom_wm_window_moved)
3425 int new_x, new_y;
3426 struct frame *f
3427 = x_window_to_frame (dpyinfo, event.xclient.window);
3429 new_x = event.xclient.data.s[0];
3430 new_y = event.xclient.data.s[1];
3432 if (f)
3434 f->output_data.x->left_pos = new_x;
3435 f->output_data.x->top_pos = new_y;
3438 #ifdef HACK_EDITRES
3439 else if (event.xclient.message_type
3440 == dpyinfo->Xatom_editres)
3442 struct frame *f
3443 = x_any_window_to_frame (dpyinfo, event.xclient.window);
3444 _XEditResCheckMessages (f->output_data.x->widget, NULL,
3445 &event, NULL);
3447 #endif /* HACK_EDITRES */
3449 break;
3451 case SelectionNotify:
3452 #ifdef USE_X_TOOLKIT
3453 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
3454 goto OTHER;
3455 #endif /* not USE_X_TOOLKIT */
3456 x_handle_selection_notify (&event);
3457 break;
3459 case SelectionClear: /* Someone has grabbed ownership. */
3460 #ifdef USE_X_TOOLKIT
3461 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
3462 goto OTHER;
3463 #endif /* USE_X_TOOLKIT */
3465 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
3467 if (numchars == 0)
3468 abort ();
3470 bufp->kind = selection_clear_event;
3471 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3472 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3473 SELECTION_EVENT_TIME (bufp) = eventp->time;
3474 bufp->frame_or_window = Qnil;
3475 bufp++;
3477 count += 1;
3478 numchars -= 1;
3480 break;
3482 case SelectionRequest: /* Someone wants our selection. */
3483 #ifdef USE_X_TOOLKIT
3484 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
3485 goto OTHER;
3486 #endif /* USE_X_TOOLKIT */
3487 if (x_queue_selection_requests)
3488 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
3489 &event);
3490 else
3492 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
3494 if (numchars == 0)
3495 abort ();
3497 bufp->kind = selection_request_event;
3498 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
3499 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
3500 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
3501 SELECTION_EVENT_TARGET (bufp) = eventp->target;
3502 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
3503 SELECTION_EVENT_TIME (bufp) = eventp->time;
3504 bufp->frame_or_window = Qnil;
3505 bufp++;
3507 count += 1;
3508 numchars -= 1;
3510 break;
3512 case PropertyNotify:
3513 #ifdef USE_X_TOOLKIT
3514 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
3515 goto OTHER;
3516 #endif /* not USE_X_TOOLKIT */
3517 x_handle_property_notify (&event);
3518 break;
3520 case ReparentNotify:
3521 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
3522 if (f)
3524 int x, y;
3525 f->output_data.x->parent_desc = event.xreparent.parent;
3526 x_real_positions (f, &x, &y);
3527 f->output_data.x->left_pos = x;
3528 f->output_data.x->top_pos = y;
3530 break;
3532 case Expose:
3533 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3534 if (f)
3536 if (f->async_visible == 0)
3538 f->async_visible = 1;
3539 f->async_iconified = 0;
3540 SET_FRAME_GARBAGED (f);
3542 else
3543 dumprectangle (x_window_to_frame (dpyinfo,
3544 event.xexpose.window),
3545 event.xexpose.x, event.xexpose.y,
3546 event.xexpose.width, event.xexpose.height);
3548 else
3550 struct scroll_bar *bar
3551 = x_window_to_scroll_bar (event.xexpose.window);
3553 if (bar)
3554 x_scroll_bar_expose (bar, &event);
3555 #ifdef USE_X_TOOLKIT
3556 else
3557 goto OTHER;
3558 #endif /* USE_X_TOOLKIT */
3560 break;
3562 case GraphicsExpose: /* This occurs when an XCopyArea's
3563 source area was obscured or not
3564 available.*/
3565 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
3566 if (f)
3568 dumprectangle (f,
3569 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
3570 event.xgraphicsexpose.width,
3571 event.xgraphicsexpose.height);
3573 #ifdef USE_X_TOOLKIT
3574 else
3575 goto OTHER;
3576 #endif /* USE_X_TOOLKIT */
3577 break;
3579 case NoExpose: /* This occurs when an XCopyArea's
3580 source area was completely
3581 available */
3582 break;
3584 case UnmapNotify:
3585 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
3586 if (f) /* F may no longer exist if
3587 the frame was deleted. */
3589 /* While a frame is unmapped, display generation is
3590 disabled; you don't want to spend time updating a
3591 display that won't ever be seen. */
3592 f->async_visible = 0;
3593 /* We can't distinguish, from the event, whether the window
3594 has become iconified or invisible. So assume, if it
3595 was previously visible, than now it is iconified.
3596 We depend on x_make_frame_invisible to mark it iconified. */
3597 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
3598 f->async_iconified = 1;
3600 bufp->kind = iconify_event;
3601 XSETFRAME (bufp->frame_or_window, f);
3602 bufp++;
3603 count++;
3604 numchars--;
3606 goto OTHER;
3608 case MapNotify:
3609 /* We use x_top_window_to_frame because map events can come
3610 for subwindows and they don't mean that the frame is visible. */
3611 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
3612 if (f)
3614 f->async_visible = 1;
3615 f->async_iconified = 0;
3617 /* wait_reading_process_input will notice this and update
3618 the frame's display structures. */
3619 SET_FRAME_GARBAGED (f);
3621 if (f->iconified)
3623 bufp->kind = deiconify_event;
3624 XSETFRAME (bufp->frame_or_window, f);
3625 bufp++;
3626 count++;
3627 numchars--;
3629 else
3630 /* Force a redisplay sooner or later
3631 to update the frame titles
3632 in case this is the second frame. */
3633 record_asynch_buffer_change ();
3635 goto OTHER;
3637 /* Turn off processing if we become fully obscured. */
3638 case VisibilityNotify:
3639 break;
3641 case KeyPress:
3642 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
3644 if (f != 0)
3646 KeySym keysym, orig_keysym;
3647 /* al%imercury@uunet.uu.net says that making this 81 instead of
3648 80 fixed a bug whereby meta chars made his Emacs hang. */
3649 unsigned char copy_buffer[81];
3650 int modifiers;
3652 event.xkey.state
3653 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
3654 extra_keyboard_modifiers);
3655 modifiers = event.xkey.state;
3657 /* This will have to go some day... */
3659 /* make_lispy_event turns chars into control chars.
3660 Don't do it here because XLookupString is too eager. */
3661 event.xkey.state &= ~ControlMask;
3662 event.xkey.state &= ~(dpyinfo->meta_mod_mask
3663 | dpyinfo->super_mod_mask
3664 | dpyinfo->hyper_mod_mask
3665 | dpyinfo->alt_mod_mask);
3667 #ifdef HAVE_X_I18N
3668 if (FRAME_XIC (f))
3670 /* The necessity of the following line took me
3671 a full work-day to decipher from the docs!! */
3672 if (XFilterEvent (&event, None))
3673 break;
3674 nbytes = XmbLookupString (FRAME_XIC (f),
3675 &event.xkey, copy_buffer,
3676 80, &keysym,
3677 &status_return);
3679 else
3680 nbytes = XLookupString (&event.xkey, copy_buffer,
3681 80, &keysym, &compose_status);
3682 #else
3683 nbytes = XLookupString (&event.xkey, copy_buffer,
3684 80, &keysym, &compose_status);
3685 #endif
3687 orig_keysym = keysym;
3689 if (numchars > 1)
3691 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
3692 || keysym == XK_Delete
3693 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
3694 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
3695 #ifdef HPUX
3696 /* This recognizes the "extended function keys".
3697 It seems there's no cleaner way.
3698 Test IsModifierKey to avoid handling mode_switch
3699 incorrectly. */
3700 || ((unsigned) (keysym) >= XK_Select
3701 && (unsigned)(keysym) < XK_KP_Space)
3702 #endif
3703 #ifdef XK_dead_circumflex
3704 || orig_keysym == XK_dead_circumflex
3705 #endif
3706 #ifdef XK_dead_grave
3707 || orig_keysym == XK_dead_grave
3708 #endif
3709 #ifdef XK_dead_tilde
3710 || orig_keysym == XK_dead_tilde
3711 #endif
3712 #ifdef XK_dead_diaeresis
3713 || orig_keysym == XK_dead_diaeresis
3714 #endif
3715 #ifdef XK_dead_macron
3716 || orig_keysym == XK_dead_macron
3717 #endif
3718 #ifdef XK_dead_degree
3719 || orig_keysym == XK_dead_degree
3720 #endif
3721 #ifdef XK_dead_acute
3722 || orig_keysym == XK_dead_acute
3723 #endif
3724 #ifdef XK_dead_cedilla
3725 || orig_keysym == XK_dead_cedilla
3726 #endif
3727 #ifdef XK_dead_breve
3728 || orig_keysym == XK_dead_breve
3729 #endif
3730 #ifdef XK_dead_ogonek
3731 || orig_keysym == XK_dead_ogonek
3732 #endif
3733 #ifdef XK_dead_caron
3734 || orig_keysym == XK_dead_caron
3735 #endif
3736 #ifdef XK_dead_doubleacute
3737 || orig_keysym == XK_dead_doubleacute
3738 #endif
3739 #ifdef XK_dead_abovedot
3740 || orig_keysym == XK_dead_abovedot
3741 #endif
3742 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
3743 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
3744 /* Any "vendor-specific" key is ok. */
3745 || (orig_keysym & (1 << 28)))
3746 && ! (IsModifierKey (orig_keysym)
3747 #ifndef HAVE_X11R5
3748 #ifdef XK_Mode_switch
3749 || ((unsigned)(orig_keysym) == XK_Mode_switch)
3750 #endif
3751 #ifdef XK_Num_Lock
3752 || ((unsigned)(orig_keysym) == XK_Num_Lock)
3753 #endif
3754 #endif /* not HAVE_X11R5 */
3757 if (temp_index == sizeof temp_buffer / sizeof (short))
3758 temp_index = 0;
3759 temp_buffer[temp_index++] = keysym;
3760 bufp->kind = non_ascii_keystroke;
3761 bufp->code = keysym;
3762 XSETFRAME (bufp->frame_or_window, f);
3763 bufp->modifiers
3764 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3765 modifiers);
3766 bufp->timestamp = event.xkey.time;
3767 bufp++;
3768 count++;
3769 numchars--;
3771 else if (numchars > nbytes)
3773 register int i;
3775 for (i = 0; i < nbytes; i++)
3777 if (temp_index == sizeof temp_buffer / sizeof (short))
3778 temp_index = 0;
3779 temp_buffer[temp_index++] = copy_buffer[i];
3780 bufp->kind = ascii_keystroke;
3781 bufp->code = copy_buffer[i];
3782 XSETFRAME (bufp->frame_or_window, f);
3783 bufp->modifiers
3784 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
3785 modifiers);
3786 bufp->timestamp = event.xkey.time;
3787 bufp++;
3790 count += nbytes;
3791 numchars -= nbytes;
3793 else
3794 abort ();
3796 else
3797 abort ();
3799 goto OTHER;
3801 /* Here's a possible interpretation of the whole
3802 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
3803 FocusIn event, you have to get a FocusOut event before you
3804 relinquish the focus. If you haven't received a FocusIn event,
3805 then a mere LeaveNotify is enough to free you. */
3807 case EnterNotify:
3808 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
3810 if (event.xcrossing.focus) /* Entered Window */
3812 /* Avoid nasty pop/raise loops. */
3813 if (f && (!(f->auto_raise)
3814 || !(f->auto_lower)
3815 || (event.xcrossing.time - enter_timestamp) > 500))
3817 x_new_focus_frame (dpyinfo, f);
3818 enter_timestamp = event.xcrossing.time;
3821 else if (f == dpyinfo->x_focus_frame)
3822 x_new_focus_frame (dpyinfo, 0);
3823 /* EnterNotify counts as mouse movement,
3824 so update things that depend on mouse position. */
3825 if (f)
3826 note_mouse_movement (f, &event.xmotion);
3827 goto OTHER;
3829 case FocusIn:
3830 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3831 if (event.xfocus.detail != NotifyPointer)
3832 dpyinfo->x_focus_event_frame = f;
3833 if (f)
3834 x_new_focus_frame (dpyinfo, f);
3836 #ifdef HAVE_X_I18N
3837 if (f && FRAME_XIC (f))
3838 XSetICFocus (FRAME_XIC (f));
3839 #endif
3841 goto OTHER;
3843 case LeaveNotify:
3844 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
3845 if (f)
3847 if (f == dpyinfo->mouse_face_mouse_frame)
3848 /* If we move outside the frame,
3849 then we're certainly no longer on any text in the frame. */
3850 clear_mouse_face (dpyinfo);
3852 if (event.xcrossing.focus)
3853 x_mouse_leave (dpyinfo);
3854 else
3856 if (f == dpyinfo->x_focus_event_frame)
3857 dpyinfo->x_focus_event_frame = 0;
3858 if (f == dpyinfo->x_focus_frame)
3859 x_new_focus_frame (dpyinfo, 0);
3862 goto OTHER;
3864 case FocusOut:
3865 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
3866 if (event.xfocus.detail != NotifyPointer
3867 && f == dpyinfo->x_focus_event_frame)
3868 dpyinfo->x_focus_event_frame = 0;
3869 if (f && f == dpyinfo->x_focus_frame)
3870 x_new_focus_frame (dpyinfo, 0);
3872 #ifdef HAVE_X_I18N
3873 if (f && FRAME_XIC (f))
3874 XUnsetICFocus (FRAME_XIC (f));
3875 #endif
3877 goto OTHER;
3879 case MotionNotify:
3881 if (dpyinfo->grabbed && last_mouse_frame
3882 && FRAME_LIVE_P (last_mouse_frame))
3883 f = last_mouse_frame;
3884 else
3885 f = x_window_to_frame (dpyinfo, event.xmotion.window);
3886 if (f)
3887 note_mouse_movement (f, &event.xmotion);
3888 else
3890 struct scroll_bar *bar
3891 = x_window_to_scroll_bar (event.xmotion.window);
3893 if (bar)
3894 x_scroll_bar_note_movement (bar, &event);
3896 /* If we move outside the frame,
3897 then we're certainly no longer on any text in the frame. */
3898 clear_mouse_face (dpyinfo);
3901 goto OTHER;
3903 case ConfigureNotify:
3904 f = x_any_window_to_frame (dpyinfo, event.xconfigure.window);
3905 if (f
3906 #ifdef USE_X_TOOLKIT
3907 && (event.xconfigure.window == XtWindow (f->output_data.x->widget))
3908 #endif
3911 #ifndef USE_X_TOOLKIT
3912 /* In the toolkit version, change_frame_size
3913 is called by the code that handles resizing
3914 of the EmacsFrame widget. */
3916 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
3917 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
3919 /* Even if the number of character rows and columns has
3920 not changed, the font size may have changed, so we need
3921 to check the pixel dimensions as well. */
3922 if (columns != f->width
3923 || rows != f->height
3924 || event.xconfigure.width != f->output_data.x->pixel_width
3925 || event.xconfigure.height != f->output_data.x->pixel_height)
3927 change_frame_size (f, rows, columns, 0, 1);
3928 SET_FRAME_GARBAGED (f);
3930 #endif
3932 /* Formerly, in the USE_X_TOOLKIT version,
3933 we did not test send_event here. */
3934 if (1
3935 #ifndef USE_X_TOOLKIT
3936 && ! event.xconfigure.send_event
3937 #endif
3940 Window win, child;
3941 int win_x, win_y;
3943 /* Find the position of the outside upper-left corner of
3944 the window, in the root coordinate system. Don't
3945 refer to the parent window here; we may be processing
3946 this event after the window manager has changed our
3947 parent, but before we have reached the ReparentNotify. */
3948 XTranslateCoordinates (FRAME_X_DISPLAY (f),
3950 /* From-window, to-window. */
3951 event.xconfigure.window,
3952 FRAME_X_DISPLAY_INFO (f)->root_window,
3954 /* From-position, to-position. */
3955 -event.xconfigure.border_width,
3956 -event.xconfigure.border_width,
3957 &win_x, &win_y,
3959 /* Child of win. */
3960 &child);
3961 event.xconfigure.x = win_x;
3962 event.xconfigure.y = win_y;
3965 f->output_data.x->pixel_width = event.xconfigure.width;
3966 f->output_data.x->pixel_height = event.xconfigure.height;
3967 f->output_data.x->left_pos = event.xconfigure.x;
3968 f->output_data.x->top_pos = event.xconfigure.y;
3970 /* What we have now is the position of Emacs's own window.
3971 Convert that to the position of the window manager window. */
3973 int x, y;
3974 x_real_positions (f, &x, &y);
3975 f->output_data.x->left_pos = x;
3976 f->output_data.x->top_pos = y;
3977 /* Formerly we did not do this in the USE_X_TOOLKIT
3978 version. Let's try making them the same. */
3979 /* #ifndef USE_X_TOOLKIT */
3980 if (y != event.xconfigure.y)
3982 /* Since the WM decorations come below top_pos now,
3983 we must put them below top_pos in the future. */
3984 f->output_data.x->win_gravity = NorthWestGravity;
3985 x_wm_set_size_hint (f, (long) 0, 0);
3987 /* #endif */
3990 goto OTHER;
3992 case ButtonPress:
3993 case ButtonRelease:
3995 /* If we decide we want to generate an event to be seen
3996 by the rest of Emacs, we put it here. */
3997 struct input_event emacs_event;
3998 emacs_event.kind = no_event;
4000 bzero (&compose_status, sizeof (compose_status));
4002 if (dpyinfo->grabbed && last_mouse_frame
4003 && FRAME_LIVE_P (last_mouse_frame))
4004 f = last_mouse_frame;
4005 else
4006 f = x_window_to_frame (dpyinfo, event.xbutton.window);
4008 if (f)
4010 if (!dpyinfo->x_focus_frame || f == dpyinfo->x_focus_frame)
4011 construct_mouse_click (&emacs_event, &event, f);
4013 else
4015 struct scroll_bar *bar
4016 = x_window_to_scroll_bar (event.xbutton.window);
4018 if (bar)
4019 x_scroll_bar_handle_click (bar, &event, &emacs_event);
4022 if (event.type == ButtonPress)
4024 dpyinfo->grabbed |= (1 << event.xbutton.button);
4025 last_mouse_frame = f;
4027 else
4029 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
4032 if (numchars >= 1 && emacs_event.kind != no_event)
4034 bcopy (&emacs_event, bufp, sizeof (struct input_event));
4035 bufp++;
4036 count++;
4037 numchars--;
4040 #ifdef USE_X_TOOLKIT
4041 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
4042 /* For a down-event in the menu bar,
4043 don't pass it to Xt right now.
4044 Instead, save it away
4045 and we will pass it to Xt from kbd_buffer_get_event.
4046 That way, we can run some Lisp code first. */
4047 if (f && event.type == ButtonPress
4048 /* Verify the event is really within the menu bar
4049 and not just sent to it due to grabbing. */
4050 && event.xbutton.x >= 0
4051 && event.xbutton.x < f->output_data.x->pixel_width
4052 && event.xbutton.y >= 0
4053 && event.xbutton.y < f->output_data.x->menubar_height
4054 && event.xbutton.same_screen)
4056 if (f->output_data.x->saved_button_event == 0)
4057 f->output_data.x->saved_button_event
4058 = (XButtonEvent *) xmalloc (sizeof (XButtonEvent));
4059 bcopy (&event, f->output_data.x->saved_button_event,
4060 sizeof (XButtonEvent));
4061 if (numchars >= 1)
4063 bufp->kind = menu_bar_activate_event;
4064 XSETFRAME (bufp->frame_or_window, f);
4065 bufp++;
4066 count++;
4067 numchars--;
4070 else
4071 goto OTHER;
4072 #endif /* USE_X_TOOLKIT */
4074 break;
4076 case CirculateNotify:
4077 break;
4078 case CirculateRequest:
4079 break;
4081 case MappingNotify:
4082 /* Someone has changed the keyboard mapping - update the
4083 local cache. */
4084 switch (event.xmapping.request)
4086 case MappingModifier:
4087 x_find_modifier_meanings (dpyinfo);
4088 /* This is meant to fall through. */
4089 case MappingKeyboard:
4090 XRefreshKeyboardMapping (&event.xmapping);
4092 goto OTHER;
4094 default:
4095 OTHER:
4096 #ifdef USE_X_TOOLKIT
4097 BLOCK_INPUT;
4098 XtDispatchEvent (&event);
4099 UNBLOCK_INPUT;
4100 #endif /* USE_X_TOOLKIT */
4101 break;
4106 /* On some systems, an X bug causes Emacs to get no more events
4107 when the window is destroyed. Detect that. (1994.) */
4108 if (! event_found)
4110 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4111 One XNOOP in 100 loops will make Emacs terminate.
4112 B. Bretthauer, 1994 */
4113 x_noop_count++;
4114 if (x_noop_count >= 100)
4116 x_noop_count=0;
4118 if (next_noop_dpyinfo == 0)
4119 next_noop_dpyinfo = x_display_list;
4121 XNoOp (next_noop_dpyinfo->display);
4123 /* Each time we get here, cycle through the displays now open. */
4124 next_noop_dpyinfo = next_noop_dpyinfo->next;
4128 /* If the focus was just given to an autoraising frame,
4129 raise it now. */
4130 /* ??? This ought to be able to handle more than one such frame. */
4131 if (pending_autoraise_frame)
4133 x_raise_frame (pending_autoraise_frame);
4134 pending_autoraise_frame = 0;
4137 UNBLOCK_INPUT;
4138 return count;
4141 /* Drawing the cursor. */
4144 /* Draw a hollow box cursor on frame F at X, Y.
4145 Don't change the inside of the box. */
4147 static void
4148 x_draw_box (f, x, y)
4149 struct frame *f;
4150 int x, y;
4152 int left = CHAR_TO_PIXEL_COL (f, x);
4153 int top = CHAR_TO_PIXEL_ROW (f, y);
4154 int width = FONT_WIDTH (f->output_data.x->font);
4155 int height = f->output_data.x->line_height;
4157 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4158 f->output_data.x->cursor_gc,
4159 left, top, width - 1, height - 1);
4162 /* Clear the cursor of frame F to background color,
4163 and mark the cursor as not shown.
4164 This is used when the text where the cursor is
4165 is about to be rewritten. */
4167 static void
4168 clear_cursor (f)
4169 struct frame *f;
4171 int mask;
4173 if (! FRAME_VISIBLE_P (f)
4174 || f->phys_cursor_x < 0)
4175 return;
4177 x_display_cursor (f, 0);
4178 f->phys_cursor_x = -1;
4181 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4182 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4183 glyph drawn. */
4185 static void
4186 x_draw_single_glyph (f, row, column, glyph, highlight)
4187 struct frame *f;
4188 int row, column;
4189 GLYPH glyph;
4190 int highlight;
4192 dumpglyphs (f,
4193 CHAR_TO_PIXEL_COL (f, column),
4194 CHAR_TO_PIXEL_ROW (f, row),
4195 &glyph, 1, highlight, 0);
4198 static void
4199 x_display_bar_cursor (f, on, x, y)
4200 struct frame *f;
4201 int on;
4202 int x, y;
4204 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4206 /* This is pointless on invisible frames, and dangerous on garbaged
4207 frames; in the latter case, the frame may be in the midst of
4208 changing its size, and x and y may be off the frame. */
4209 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4210 return;
4212 if (! on && f->phys_cursor_x < 0)
4213 return;
4215 /* If there is anything wrong with the current cursor state, remove it. */
4216 if (f->phys_cursor_x >= 0
4217 && (!on
4218 || f->phys_cursor_x != x
4219 || f->phys_cursor_y != y
4220 || f->output_data.x->current_cursor != bar_cursor))
4222 /* Erase the cursor by redrawing the character underneath it. */
4223 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4224 f->phys_cursor_glyph,
4225 current_glyphs->highlight[f->phys_cursor_y]);
4226 f->phys_cursor_x = -1;
4229 /* If we now need a cursor in the new place or in the new form, do it so. */
4230 if (on
4231 && (f->phys_cursor_x < 0
4232 || (f->output_data.x->current_cursor != bar_cursor)))
4234 f->phys_cursor_glyph
4235 = ((current_glyphs->enable[y]
4236 && x < current_glyphs->used[y])
4237 ? current_glyphs->glyphs[y][x]
4238 : SPACEGLYPH);
4239 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4240 f->output_data.x->cursor_gc,
4241 CHAR_TO_PIXEL_COL (f, x),
4242 CHAR_TO_PIXEL_ROW (f, y),
4243 max (f->output_data.x->cursor_width, 1),
4244 f->output_data.x->line_height);
4246 f->phys_cursor_x = x;
4247 f->phys_cursor_y = y;
4249 f->output_data.x->current_cursor = bar_cursor;
4252 if (updating_frame != f)
4253 XFlush (FRAME_X_DISPLAY (f));
4257 /* Turn the displayed cursor of frame F on or off according to ON.
4258 If ON is nonzero, where to put the cursor is specified by X and Y. */
4260 static void
4261 x_display_box_cursor (f, on, x, y)
4262 struct frame *f;
4263 int on;
4264 int x, y;
4266 struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
4268 /* This is pointless on invisible frames, and dangerous on garbaged
4269 frames; in the latter case, the frame may be in the midst of
4270 changing its size, and x and y may be off the frame. */
4271 if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
4272 return;
4274 /* If cursor is off and we want it off, return quickly. */
4275 if (!on && f->phys_cursor_x < 0)
4276 return;
4278 /* If cursor is currently being shown and we don't want it to be
4279 or it is in the wrong place,
4280 or we want a hollow box and it's not so, (pout!)
4281 erase it. */
4282 if (f->phys_cursor_x >= 0
4283 && (!on
4284 || f->phys_cursor_x != x
4285 || f->phys_cursor_y != y
4286 || (f->output_data.x->current_cursor != hollow_box_cursor
4287 && (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame))))
4289 int mouse_face_here = 0;
4290 struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
4292 /* If the cursor is in the mouse face area, redisplay that when
4293 we clear the cursor. */
4294 if (f == FRAME_X_DISPLAY_INFO (f)->mouse_face_mouse_frame
4296 (f->phys_cursor_y > FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4297 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_row
4298 && f->phys_cursor_x >= FRAME_X_DISPLAY_INFO (f)->mouse_face_beg_col))
4300 (f->phys_cursor_y < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4301 || (f->phys_cursor_y == FRAME_X_DISPLAY_INFO (f)->mouse_face_end_row
4302 && f->phys_cursor_x < FRAME_X_DISPLAY_INFO (f)->mouse_face_end_col))
4303 /* Don't redraw the cursor's spot in mouse face
4304 if it is at the end of a line (on a newline).
4305 The cursor appears there, but mouse highlighting does not. */
4306 && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
4307 mouse_face_here = 1;
4309 /* If the font is not as tall as a whole line,
4310 we must explicitly clear the line's whole height. */
4311 if (FONT_HEIGHT (f->output_data.x->font) != f->output_data.x->line_height)
4312 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4313 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
4314 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
4315 FONT_WIDTH (f->output_data.x->font),
4316 f->output_data.x->line_height, False);
4317 /* Erase the cursor by redrawing the character underneath it. */
4318 x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
4319 f->phys_cursor_glyph,
4320 (mouse_face_here
4322 : current_glyphs->highlight[f->phys_cursor_y]));
4323 f->phys_cursor_x = -1;
4326 /* If we want to show a cursor,
4327 or we want a box cursor and it's not so,
4328 write it in the right place. */
4329 if (on
4330 && (f->phys_cursor_x < 0
4331 || (f->output_data.x->current_cursor != filled_box_cursor
4332 && f == FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)))
4334 f->phys_cursor_glyph
4335 = ((current_glyphs->enable[y]
4336 && x < current_glyphs->used[y])
4337 ? current_glyphs->glyphs[y][x]
4338 : SPACEGLYPH);
4339 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
4341 x_draw_box (f, x, y);
4342 f->output_data.x->current_cursor = hollow_box_cursor;
4344 else
4346 x_draw_single_glyph (f, y, x,
4347 f->phys_cursor_glyph, 2);
4348 f->output_data.x->current_cursor = filled_box_cursor;
4351 f->phys_cursor_x = x;
4352 f->phys_cursor_y = y;
4355 if (updating_frame != f)
4356 XFlush (FRAME_X_DISPLAY (f));
4359 /* Display the cursor on frame F, or clear it, according to ON.
4360 Use the position specified by curs_x and curs_y
4361 if we are doing an update of frame F now.
4362 Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
4363 of F. */
4365 x_display_cursor (f, on)
4366 struct frame *f;
4367 int on;
4369 BLOCK_INPUT;
4371 /* If we're not updating, then don't change the physical cursor
4372 position. Just change (if appropriate) the style of display. */
4373 if (f != updating_frame)
4375 curs_x = FRAME_CURSOR_X (f);
4376 curs_y = FRAME_CURSOR_Y (f);
4379 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4380 x_display_box_cursor (f, on, curs_x, curs_y);
4381 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4382 x_display_bar_cursor (f, on, curs_x, curs_y);
4383 else
4384 /* Those are the only two we have implemented! */
4385 abort ();
4387 UNBLOCK_INPUT;
4390 /* Display the cursor on frame F, or clear it, according to ON.
4391 Don't change the cursor's position. */
4393 x_update_cursor (f, on)
4394 struct frame *f;
4395 int on;
4397 BLOCK_INPUT;
4399 if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
4400 x_display_box_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4401 else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
4402 x_display_bar_cursor (f, on, f->phys_cursor_x, f->phys_cursor_y);
4403 else
4404 /* Those are the only two we have implemented! */
4405 abort ();
4407 UNBLOCK_INPUT;
4410 /* Icons. */
4412 /* Refresh bitmap kitchen sink icon for frame F
4413 when we get an expose event for it. */
4415 refreshicon (f)
4416 struct frame *f;
4418 /* Normally, the window manager handles this function. */
4421 /* Make the x-window of frame F use the gnu icon bitmap. */
4424 x_bitmap_icon (f, file)
4425 struct frame *f;
4426 Lisp_Object file;
4428 int mask, bitmap_id;
4429 Window icon_window;
4431 if (FRAME_X_WINDOW (f) == 0)
4432 return 1;
4434 /* Free up our existing icon bitmap if any. */
4435 if (f->output_data.x->icon_bitmap > 0)
4436 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4437 f->output_data.x->icon_bitmap = 0;
4439 if (STRINGP (file))
4440 bitmap_id = x_create_bitmap_from_file (f, file);
4441 else
4443 /* Create the GNU bitmap if necessary. */
4444 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
4445 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
4446 = x_create_bitmap_from_data (f, gnu_bits,
4447 gnu_width, gnu_height);
4449 /* The first time we create the GNU bitmap,
4450 this increments the refcount one extra time.
4451 As a result, the GNU bitmap is never freed.
4452 That way, we don't have to worry about allocating it again. */
4453 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
4455 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
4458 x_wm_set_icon_pixmap (f, bitmap_id);
4459 f->output_data.x->icon_bitmap = bitmap_id;
4461 return 0;
4465 /* Make the x-window of frame F use a rectangle with text.
4466 Use ICON_NAME as the text. */
4469 x_text_icon (f, icon_name)
4470 struct frame *f;
4471 char *icon_name;
4473 if (FRAME_X_WINDOW (f) == 0)
4474 return 1;
4476 #ifdef HAVE_X11R4
4478 XTextProperty text;
4479 text.value = (unsigned char *) icon_name;
4480 text.encoding = XA_STRING;
4481 text.format = 8;
4482 text.nitems = strlen (icon_name);
4483 #ifdef USE_X_TOOLKIT
4484 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4485 &text);
4486 #else /* not USE_X_TOOLKIT */
4487 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
4488 #endif /* not USE_X_TOOLKIT */
4490 #else /* not HAVE_X11R4 */
4491 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
4492 #endif /* not HAVE_X11R4 */
4494 if (f->output_data.x->icon_bitmap > 0)
4495 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
4496 f->output_data.x->icon_bitmap = 0;
4497 x_wm_set_icon_pixmap (f, 0);
4499 return 0;
4502 /* Handling X errors. */
4504 /* Handle the loss of connection to display DISPLAY. */
4506 static SIGTYPE
4507 x_connection_closed (display, error_message)
4508 Display *display;
4509 char *error_message;
4511 struct x_display_info *dpyinfo = x_display_info_for_display (display);
4512 Lisp_Object frame, tail;
4514 /* Whatever we were in the middle of, we are going to throw out of it,
4515 so reassure various things that have error checks about being
4516 called with input blocked. */
4517 TOTALLY_UNBLOCK_INPUT;
4519 if (_Xdebug)
4520 abort ();
4522 /* Indicate that this display is dead. */
4524 dpyinfo->display = 0;
4526 /* First delete frames whose minibuffers are on frames
4527 that are on the dead display. */
4528 FOR_EACH_FRAME (tail, frame)
4530 Lisp_Object minibuf_frame;
4531 minibuf_frame
4532 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
4533 if (FRAME_X_P (XFRAME (frame))
4534 && FRAME_X_P (XFRAME (minibuf_frame))
4535 && ! EQ (frame, minibuf_frame)
4536 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
4537 Fdelete_frame (frame, Qt);
4540 /* Now delete all remaining frames on the dead display.
4541 We are now sure none of these is used as the minibuffer
4542 for another frame that we need to delete. */
4543 FOR_EACH_FRAME (tail, frame)
4544 if (FRAME_X_P (XFRAME (frame))
4545 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
4547 /* Set this to t so that Fdelete_frame won't get confused
4548 trying to find a replacement. */
4549 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
4550 Fdelete_frame (frame, Qt);
4553 if (dpyinfo)
4554 x_delete_display (dpyinfo);
4556 if (x_display_list == 0)
4558 fprintf (stderr, "%s", error_message);
4559 shut_down_emacs (0, 0, Qnil);
4560 exit (70);
4563 /* Ordinary stack unwind doesn't deal with these. */
4564 #ifdef SIGIO
4565 sigunblock (sigmask (SIGIO));
4566 #endif
4567 sigunblock (sigmask (SIGALRM));
4568 TOTALLY_UNBLOCK_INPUT;
4570 error ("%s", error_message);
4573 /* This is the usual handler for X protocol errors.
4574 It kills all frames on the display that we got the error for.
4575 If that was the only one, it prints an error message and kills Emacs. */
4577 static int
4578 x_error_quitter (display, error)
4579 Display *display;
4580 XErrorEvent *error;
4582 char buf[256], buf1[356];
4584 /* Note that there is no real way portable across R3/R4 to get the
4585 original error handler. */
4587 XGetErrorText (display, error->error_code, buf, sizeof (buf));
4588 sprintf (buf1, "X protocol error: %s on protocol request %d\n",
4589 buf, error->request_code);
4590 x_connection_closed (display, buf1);
4593 /* This is the handler for X IO errors, always.
4594 It kills all frames on the display that we lost touch with.
4595 If that was the only one, it prints an error message and kills Emacs. */
4597 static int
4598 x_io_error_quitter (display)
4599 Display *display;
4601 char buf[256];
4603 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
4604 x_connection_closed (display, buf);
4607 /* Handle SIGPIPE, which can happen when the connection to a server
4608 simply goes away. SIGPIPE is handled by x_connection_signal.
4609 It works by sending a no-op command to each X server connection.
4610 When we try a connection that has closed, we get SIGPIPE again.
4611 But this time, it is handled by x_connection_signal_1.
4612 That function knows which connection we were testing,
4613 so it closes that one.
4615 x_connection_closed never returns,
4616 so if more than one connection was lost at once,
4617 we only find one. But XTread_socket keeps trying them all,
4618 so it will notice the other closed one sooner or later. */
4621 static struct x_display_info *x_connection_signal_dpyinfo;
4623 static SIGTYPE x_connection_signal ();
4625 static SIGTYPE
4626 x_connection_signal_1 (signalnum) /* If we don't have an argument, */
4627 int signalnum; /* some compilers complain in signal calls. */
4629 signal (SIGPIPE, x_connection_signal);
4630 x_connection_closed (x_connection_signal_dpyinfo,
4631 "connection was lost");
4634 static SIGTYPE
4635 x_connection_signal (signalnum) /* If we don't have an argument, */
4636 int signalnum; /* some compilers complain in signal calls. */
4638 x_connection_signal_dpyinfo = x_display_list;
4640 sigunblock (SIGPIPE);
4642 while (x_connection_signal_dpyinfo)
4644 signal (SIGPIPE, x_connection_signal_1);
4646 #ifdef SOLARIS2
4647 #ifdef XlibDisplayWriting
4648 /* If the thread-interlock is locked, assume this connection is dead.
4649 This assumes that the library does not make other threads
4650 that can be locking the display legitimately. */
4651 if (x_connection_signal_dpyinfo->display->flags & XlibDisplayWriting)
4653 x_connection_signal_dpyinfo->display->flags &= ~XlibDisplayWriting;
4654 x_connection_closed (x_connection_signal_dpyinfo->display,
4655 "connection was lost");
4657 #endif
4658 #endif
4660 XNoOp (x_connection_signal_dpyinfo->display);
4662 XSync (x_connection_signal_dpyinfo->display, False);
4664 /* Each time we get here, cycle through the displays now open. */
4665 x_connection_signal_dpyinfo = x_connection_signal_dpyinfo->next;
4668 /* We should have found some closed connection. */
4669 abort ();
4672 /* A buffer for storing X error messages. */
4673 static char *x_caught_error_message;
4674 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
4676 /* An X error handler which stores the error message in
4677 x_caught_error_message. This is what's installed when
4678 x_catch_errors is in effect. */
4680 static int
4681 x_error_catcher (display, error)
4682 Display *display;
4683 XErrorEvent *error;
4685 XGetErrorText (display, error->error_code,
4686 x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE);
4690 /* Begin trapping X errors for display DPY. Actually we trap X errors
4691 for all displays, but DPY should be the display you are actually
4692 operating on.
4694 After calling this function, X protocol errors no longer cause
4695 Emacs to exit; instead, they are recorded in x_cfc_error_message.
4697 Calling x_check_errors signals an Emacs error if an X error has
4698 occurred since the last call to x_catch_errors or x_check_errors.
4700 Calling x_uncatch_errors resumes the normal error handling. */
4702 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
4704 void
4705 x_catch_errors (dpy)
4706 Display *dpy;
4708 /* Make sure any errors from previous requests have been dealt with. */
4709 XSync (dpy, False);
4711 /* Set up the error buffer. */
4712 x_caught_error_message
4713 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE);
4714 x_caught_error_message[0] = '\0';
4716 /* Install our little error handler. */
4717 XSetErrorHandler (x_error_catcher);
4720 /* If any X protocol errors have arrived since the last call to
4721 x_catch_errors or x_check_errors, signal an Emacs error using
4722 sprintf (a buffer, FORMAT, the x error message text) as the text. */
4724 void
4725 x_check_errors (dpy, format)
4726 Display *dpy;
4727 char *format;
4729 /* Make sure to catch any errors incurred so far. */
4730 XSync (dpy, False);
4732 if (x_caught_error_message[0])
4734 char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56];
4736 sprintf (buf, format, x_caught_error_message);
4737 x_uncatch_errors (dpy);
4738 error (buf);
4742 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
4745 x_had_errors_p (dpy)
4746 Display *dpy;
4748 /* Make sure to catch any errors incurred so far. */
4749 XSync (dpy, False);
4751 return x_caught_error_message[0] != 0;
4754 /* Stop catching X protocol errors and let them make Emacs die. */
4756 void
4757 x_uncatch_errors (dpy)
4758 Display *dpy;
4760 xfree (x_caught_error_message);
4761 x_caught_error_message = 0;
4762 XSetErrorHandler (x_error_quitter);
4765 #if 0
4766 static unsigned int x_wire_count;
4767 x_trace_wire ()
4769 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
4771 #endif /* ! 0 */
4774 /* Changing the font of the frame. */
4776 /* Give frame F the font named FONTNAME as its default font, and
4777 return the full name of that font. FONTNAME may be a wildcard
4778 pattern; in that case, we choose some font that fits the pattern.
4779 The return value shows which font we chose. */
4781 Lisp_Object
4782 x_new_font (f, fontname)
4783 struct frame *f;
4784 register char *fontname;
4786 int already_loaded;
4787 int n_matching_fonts;
4788 XFontStruct *font_info;
4789 char **font_names;
4791 /* Get a list of all the fonts that match this name. Once we
4792 have a list of matching fonts, we compare them against the fonts
4793 we already have by comparing font ids. */
4794 font_names = (char **) XListFonts (FRAME_X_DISPLAY (f), fontname,
4795 1024, &n_matching_fonts);
4796 /* Apparently it doesn't set n_matching_fonts to zero when it can't
4797 find any matches; font_names == 0 is the only clue. */
4798 if (! font_names)
4799 n_matching_fonts = 0;
4801 /* Don't just give up if n_matching_fonts is 0.
4802 Apparently there's a bug on Suns: XListFontsWithInfo can
4803 fail to find a font, but XLoadQueryFont may still find it. */
4805 /* See if we've already loaded a matching font. */
4806 already_loaded = -1;
4807 if (n_matching_fonts != 0)
4809 int i, j;
4811 for (i = 0; i < FRAME_X_DISPLAY_INFO (f)->n_fonts; i++)
4812 for (j = 0; j < n_matching_fonts; j++)
4813 if (!strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].name, font_names[j])
4814 || !strcmp (FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name, font_names[j]))
4816 already_loaded = i;
4817 fontname = FRAME_X_DISPLAY_INFO (f)->font_table[i].full_name;
4818 goto found_font;
4821 found_font:
4823 /* If we have, just return it from the table. */
4824 if (already_loaded >= 0)
4825 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[already_loaded].font;
4826 /* Otherwise, load the font and add it to the table. */
4827 else
4829 int i;
4830 char *full_name;
4831 XFontStruct *font;
4832 int n_fonts;
4834 /* Try to find a character-cell font in the list. */
4835 #if 0
4836 /* A laudable goal, but this isn't how to do it. */
4837 for (i = 0; i < n_matching_fonts; i++)
4838 if (! font_info[i].per_char)
4839 break;
4840 #else
4841 i = 0;
4842 #endif
4844 /* See comment above. */
4845 if (n_matching_fonts != 0)
4846 fontname = font_names[i];
4848 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
4849 if (! font)
4851 /* Free the information from XListFonts. */
4852 if (n_matching_fonts)
4853 XFreeFontNames (font_names);
4854 return Qnil;
4857 /* Do we need to create the table? */
4858 if (FRAME_X_DISPLAY_INFO (f)->font_table_size == 0)
4860 FRAME_X_DISPLAY_INFO (f)->font_table_size = 16;
4861 FRAME_X_DISPLAY_INFO (f)->font_table
4862 = (struct font_info *) xmalloc (FRAME_X_DISPLAY_INFO (f)->font_table_size
4863 * sizeof (struct font_info));
4865 /* Do we need to grow the table? */
4866 else if (FRAME_X_DISPLAY_INFO (f)->n_fonts
4867 >= FRAME_X_DISPLAY_INFO (f)->font_table_size)
4869 FRAME_X_DISPLAY_INFO (f)->font_table_size *= 2;
4870 FRAME_X_DISPLAY_INFO (f)->font_table
4871 = (struct font_info *) xrealloc (FRAME_X_DISPLAY_INFO (f)->font_table,
4872 (FRAME_X_DISPLAY_INFO (f)->font_table_size
4873 * sizeof (struct font_info)));
4876 /* Try to get the full name of FONT. Put it in full_name. */
4877 full_name = 0;
4878 for (i = 0; i < font->n_properties; i++)
4880 char *atom
4881 = XGetAtomName (FRAME_X_DISPLAY (f), font->properties[i].name);
4882 if (!strcmp (atom, "FONT"))
4884 char *name = XGetAtomName (FRAME_X_DISPLAY (f),
4885 (Atom) (font->properties[i].card32));
4886 char *p = name;
4887 int dashes = 0;
4889 /* Count the number of dashes in the "full name".
4890 If it is too few, this isn't really the font's full name,
4891 so don't use it.
4892 In X11R4, the fonts did not come with their canonical names
4893 stored in them. */
4894 while (*p)
4896 if (*p == '-')
4897 dashes++;
4898 p++;
4901 if (dashes >= 13)
4902 full_name = name;
4904 break;
4907 XFree (atom);
4910 n_fonts = FRAME_X_DISPLAY_INFO (f)->n_fonts;
4911 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
4912 bcopy (fontname, FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
4913 if (full_name != 0)
4914 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = full_name;
4915 else
4916 FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].full_name = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].name;
4917 f->output_data.x->font = FRAME_X_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
4918 FRAME_X_DISPLAY_INFO (f)->n_fonts++;
4920 if (full_name)
4921 fontname = full_name;
4924 /* Compute the scroll bar width in character columns. */
4925 if (f->scroll_bar_pixel_width > 0)
4927 int wid = FONT_WIDTH (f->output_data.x->font);
4928 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
4930 else
4931 f->scroll_bar_cols = 2;
4933 /* Now make the frame display the given font. */
4934 if (FRAME_X_WINDOW (f) != 0)
4936 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
4937 f->output_data.x->font->fid);
4938 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
4939 f->output_data.x->font->fid);
4940 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
4941 f->output_data.x->font->fid);
4943 frame_update_line_height (f);
4944 x_set_window_size (f, 0, f->width, f->height);
4946 else
4947 /* If we are setting a new frame's font for the first time,
4948 there are no faces yet, so this font's height is the line height. */
4949 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
4952 Lisp_Object lispy_name;
4954 lispy_name = build_string (fontname);
4956 /* Free the information from XListFonts. The data
4957 we actually retain comes from XLoadQueryFont. */
4958 XFreeFontNames (font_names);
4960 return lispy_name;
4964 x_calc_absolute_position (f)
4965 struct frame *f;
4967 Window win, child;
4968 int win_x = 0, win_y = 0;
4969 int flags = f->output_data.x->size_hint_flags;
4970 int this_window;
4972 #ifdef USE_X_TOOLKIT
4973 this_window = XtWindow (f->output_data.x->widget);
4974 #else
4975 this_window = FRAME_X_WINDOW (f);
4976 #endif
4978 /* Find the position of the outside upper-left corner of
4979 the inner window, with respect to the outer window. */
4980 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
4982 BLOCK_INPUT;
4983 XTranslateCoordinates (FRAME_X_DISPLAY (f),
4985 /* From-window, to-window. */
4986 this_window,
4987 f->output_data.x->parent_desc,
4989 /* From-position, to-position. */
4990 0, 0, &win_x, &win_y,
4992 /* Child of win. */
4993 &child);
4994 UNBLOCK_INPUT;
4997 /* Treat negative positions as relative to the leftmost bottommost
4998 position that fits on the screen. */
4999 if (flags & XNegative)
5000 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
5001 - 2 * f->output_data.x->border_width - win_x
5002 - PIXEL_WIDTH (f)
5003 + f->output_data.x->left_pos);
5005 if (flags & YNegative)
5006 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
5007 - 2 * f->output_data.x->border_width - win_y
5008 - PIXEL_HEIGHT (f)
5009 - (FRAME_EXTERNAL_MENU_BAR (f)
5010 ? f->output_data.x->menubar_height : 0)
5011 + f->output_data.x->top_pos);
5012 /* The left_pos and top_pos
5013 are now relative to the top and left screen edges,
5014 so the flags should correspond. */
5015 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
5018 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5019 to really change the position, and 0 when calling from
5020 x_make_frame_visible (in that case, XOFF and YOFF are the current
5021 position values). It is -1 when calling from x_set_frame_parameters,
5022 which means, do adjust for borders but don't change the gravity. */
5024 x_set_offset (f, xoff, yoff, change_gravity)
5025 struct frame *f;
5026 register int xoff, yoff;
5027 int change_gravity;
5029 int modified_top, modified_left;
5031 if (change_gravity > 0)
5033 f->output_data.x->top_pos = yoff;
5034 f->output_data.x->left_pos = xoff;
5035 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
5036 if (xoff < 0)
5037 f->output_data.x->size_hint_flags |= XNegative;
5038 if (yoff < 0)
5039 f->output_data.x->size_hint_flags |= YNegative;
5040 f->output_data.x->win_gravity = NorthWestGravity;
5042 x_calc_absolute_position (f);
5044 BLOCK_INPUT;
5045 x_wm_set_size_hint (f, (long) 0, 0);
5047 /* It is a mystery why we need to add the border_width here
5048 when the frame is already visible, but experiment says we do. */
5049 modified_left = f->output_data.x->left_pos;
5050 modified_top = f->output_data.x->top_pos;
5051 if (change_gravity != 0)
5053 modified_left += f->output_data.x->border_width;
5054 modified_top += f->output_data.x->border_width;
5057 #ifdef USE_X_TOOLKIT
5058 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
5059 modified_left, modified_top);
5060 #else /* not USE_X_TOOLKIT */
5061 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5062 modified_left, modified_top);
5063 #endif /* not USE_X_TOOLKIT */
5064 UNBLOCK_INPUT;
5067 /* Call this to change the size of frame F's x-window.
5068 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5069 for this size change and subsequent size changes.
5070 Otherwise we leave the window gravity unchanged. */
5072 x_set_window_size (f, change_gravity, cols, rows)
5073 struct frame *f;
5074 int change_gravity;
5075 int cols, rows;
5077 int pixelwidth, pixelheight;
5078 int mask;
5080 #ifdef USE_X_TOOLKIT
5081 BLOCK_INPUT;
5083 /* The x and y position of the widget is clobbered by the
5084 call to XtSetValues within EmacsFrameSetCharSize.
5085 This is a real kludge, but I don't understand Xt so I can't
5086 figure out a correct fix. Can anyone else tell me? -- rms. */
5087 int xpos = f->output_data.x->widget->core.x;
5088 int ypos = f->output_data.x->widget->core.y;
5089 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
5090 f->output_data.x->widget->core.x = xpos;
5091 f->output_data.x->widget->core.y = ypos;
5093 UNBLOCK_INPUT;
5095 #else /* not USE_X_TOOLKIT */
5097 BLOCK_INPUT;
5099 check_frame_size (f, &rows, &cols);
5100 f->output_data.x->vertical_scroll_bar_extra
5101 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5103 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
5104 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
5105 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
5106 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
5107 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
5109 f->output_data.x->win_gravity = NorthWestGravity;
5110 x_wm_set_size_hint (f, (long) 0, 0);
5112 XSync (FRAME_X_DISPLAY (f), False);
5113 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5114 pixelwidth, pixelheight);
5116 /* Now, strictly speaking, we can't be sure that this is accurate,
5117 but the window manager will get around to dealing with the size
5118 change request eventually, and we'll hear how it went when the
5119 ConfigureNotify event gets here.
5121 We could just not bother storing any of this information here,
5122 and let the ConfigureNotify event set everything up, but that
5123 might be kind of confusing to the lisp code, since size changes
5124 wouldn't be reported in the frame parameters until some random
5125 point in the future when the ConfigureNotify event arrives. */
5126 change_frame_size (f, rows, cols, 0, 0);
5127 PIXEL_WIDTH (f) = pixelwidth;
5128 PIXEL_HEIGHT (f) = pixelheight;
5130 /* If cursor was outside the new size, mark it as off. */
5131 if (f->phys_cursor_y >= rows
5132 || f->phys_cursor_x >= cols)
5134 f->phys_cursor_x = -1;
5135 f->phys_cursor_y = -1;
5138 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5139 receive in the ConfigureNotify event; if we get what we asked
5140 for, then the event won't cause the screen to become garbaged, so
5141 we have to make sure to do it here. */
5142 SET_FRAME_GARBAGED (f);
5144 XFlush (FRAME_X_DISPLAY (f));
5145 UNBLOCK_INPUT;
5146 #endif /* not USE_X_TOOLKIT */
5149 /* Mouse warping. */
5151 void
5152 x_set_mouse_position (f, x, y)
5153 struct frame *f;
5154 int x, y;
5156 int pix_x, pix_y;
5158 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
5159 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
5161 if (pix_x < 0) pix_x = 0;
5162 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
5164 if (pix_y < 0) pix_y = 0;
5165 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
5167 BLOCK_INPUT;
5169 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5170 0, 0, 0, 0, pix_x, pix_y);
5171 UNBLOCK_INPUT;
5174 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5176 void
5177 x_set_mouse_pixel_position (f, pix_x, pix_y)
5178 struct frame *f;
5179 int pix_x, pix_y;
5181 BLOCK_INPUT;
5183 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5184 0, 0, 0, 0, pix_x, pix_y);
5185 UNBLOCK_INPUT;
5188 /* focus shifting, raising and lowering. */
5190 x_focus_on_frame (f)
5191 struct frame *f;
5193 #if 0 /* This proves to be unpleasant. */
5194 x_raise_frame (f);
5195 #endif
5196 #if 0
5197 /* I don't think that the ICCCM allows programs to do things like this
5198 without the interaction of the window manager. Whatever you end up
5199 doing with this code, do it to x_unfocus_frame too. */
5200 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5201 RevertToPointerRoot, CurrentTime);
5202 #endif /* ! 0 */
5205 x_unfocus_frame (f)
5206 struct frame *f;
5208 #if 0
5209 /* Look at the remarks in x_focus_on_frame. */
5210 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
5211 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
5212 RevertToPointerRoot, CurrentTime);
5213 #endif /* ! 0 */
5216 /* Raise frame F. */
5218 x_raise_frame (f)
5219 struct frame *f;
5221 if (f->async_visible)
5223 BLOCK_INPUT;
5224 #ifdef USE_X_TOOLKIT
5225 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5226 #else /* not USE_X_TOOLKIT */
5227 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5228 #endif /* not USE_X_TOOLKIT */
5229 XFlush (FRAME_X_DISPLAY (f));
5230 UNBLOCK_INPUT;
5234 /* Lower frame F. */
5236 x_lower_frame (f)
5237 struct frame *f;
5239 if (f->async_visible)
5241 BLOCK_INPUT;
5242 #ifdef USE_X_TOOLKIT
5243 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
5244 #else /* not USE_X_TOOLKIT */
5245 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5246 #endif /* not USE_X_TOOLKIT */
5247 XFlush (FRAME_X_DISPLAY (f));
5248 UNBLOCK_INPUT;
5252 static void
5253 XTframe_raise_lower (f, raise_flag)
5254 FRAME_PTR f;
5255 int raise_flag;
5257 if (raise_flag)
5258 x_raise_frame (f);
5259 else
5260 x_lower_frame (f);
5263 /* Change of visibility. */
5265 /* This tries to wait until the frame is really visible.
5266 However, if the window manager asks the user where to position
5267 the frame, this will return before the user finishes doing that.
5268 The frame will not actually be visible at that time,
5269 but it will become visible later when the window manager
5270 finishes with it. */
5272 x_make_frame_visible (f)
5273 struct frame *f;
5275 int mask;
5276 Lisp_Object type;
5278 BLOCK_INPUT;
5280 type = x_icon_type (f);
5281 if (!NILP (type))
5282 x_bitmap_icon (f, type);
5284 if (! FRAME_VISIBLE_P (f))
5286 /* We test FRAME_GARBAGED_P here to make sure we don't
5287 call x_set_offset a second time
5288 if we get to x_make_frame_visible a second time
5289 before the window gets really visible. */
5290 if (! FRAME_ICONIFIED_P (f)
5291 && ! f->output_data.x->asked_for_visible)
5292 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5294 f->output_data.x->asked_for_visible = 1;
5296 if (! EQ (Vx_no_window_manager, Qt))
5297 x_wm_set_window_state (f, NormalState);
5298 #ifdef USE_X_TOOLKIT
5299 /* This was XtPopup, but that did nothing for an iconified frame. */
5300 XtMapWidget (f->output_data.x->widget);
5301 #else /* not USE_X_TOOLKIT */
5302 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5303 #endif /* not USE_X_TOOLKIT */
5304 #if 0 /* This seems to bring back scroll bars in the wrong places
5305 if the window configuration has changed. They seem
5306 to come back ok without this. */
5307 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5308 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5309 #endif
5312 XFlush (FRAME_X_DISPLAY (f));
5314 /* Synchronize to ensure Emacs knows the frame is visible
5315 before we do anything else. We do this loop with input not blocked
5316 so that incoming events are handled. */
5318 Lisp_Object frame;
5319 int count = input_signal_count;
5321 /* This must come after we set COUNT. */
5322 UNBLOCK_INPUT;
5324 XSETFRAME (frame, f);
5326 while (1)
5328 x_sync (f);
5329 /* Once we have handled input events,
5330 we should have received the MapNotify if one is coming.
5331 So if we have not got it yet, stop looping.
5332 Some window managers make their own decisions
5333 about visibility. */
5334 if (input_signal_count != count)
5335 break;
5336 /* Machines that do polling rather than SIGIO have been observed
5337 to go into a busy-wait here. So we'll fake an alarm signal
5338 to let the handler know that there's something to be read.
5339 We used to raise a real alarm, but it seems that the handler
5340 isn't always enabled here. This is probably a bug. */
5341 if (input_polling_used ())
5343 /* It could be confusing if a real alarm arrives while processing
5344 the fake one. Turn it off and let the handler reset it. */
5345 alarm (0);
5346 input_poll_signal ();
5348 /* Once we have handled input events,
5349 we should have received the MapNotify if one is coming.
5350 So if we have not got it yet, stop looping.
5351 Some window managers make their own decisions
5352 about visibility. */
5353 if (input_signal_count != count)
5354 break;
5356 FRAME_SAMPLE_VISIBILITY (f);
5360 /* Change from mapped state to withdrawn state. */
5362 /* Make the frame visible (mapped and not iconified). */
5364 x_make_frame_invisible (f)
5365 struct frame *f;
5367 int mask;
5368 Window window;
5370 #ifdef USE_X_TOOLKIT
5371 /* Use the frame's outermost window, not the one we normally draw on. */
5372 window = XtWindow (f->output_data.x->widget);
5373 #else /* not USE_X_TOOLKIT */
5374 window = FRAME_X_WINDOW (f);
5375 #endif /* not USE_X_TOOLKIT */
5377 /* Don't keep the highlight on an invisible frame. */
5378 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5379 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5381 #if 0/* This might add unreliability; I don't trust it -- rms. */
5382 if (! f->async_visible && ! f->async_iconified)
5383 return;
5384 #endif
5386 BLOCK_INPUT;
5388 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5389 that the current position of the window is user-specified, rather than
5390 program-specified, so that when the window is mapped again, it will be
5391 placed at the same location, without forcing the user to position it
5392 by hand again (they have already done that once for this window.) */
5393 x_wm_set_size_hint (f, (long) 0, 1);
5395 #ifdef HAVE_X11R4
5397 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
5398 DefaultScreen (FRAME_X_DISPLAY (f))))
5400 UNBLOCK_INPUT_RESIGNAL;
5401 error ("Can't notify window manager of window withdrawal");
5403 #else /* ! defined (HAVE_X11R4) */
5405 /* Tell the window manager what we're going to do. */
5406 if (! EQ (Vx_no_window_manager, Qt))
5408 XEvent unmap;
5410 unmap.xunmap.type = UnmapNotify;
5411 unmap.xunmap.window = window;
5412 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
5413 unmap.xunmap.from_configure = False;
5414 if (! XSendEvent (FRAME_X_DISPLAY (f),
5415 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5416 False,
5417 SubstructureRedirectMask|SubstructureNotifyMask,
5418 &unmap))
5420 UNBLOCK_INPUT_RESIGNAL;
5421 error ("Can't notify window manager of withdrawal");
5425 /* Unmap the window ourselves. Cheeky! */
5426 XUnmapWindow (FRAME_X_DISPLAY (f), window);
5427 #endif /* ! defined (HAVE_X11R4) */
5429 /* We can't distinguish this from iconification
5430 just by the event that we get from the server.
5431 So we can't win using the usual strategy of letting
5432 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5433 and synchronize with the server to make sure we agree. */
5434 f->visible = 0;
5435 FRAME_ICONIFIED_P (f) = 0;
5436 f->async_visible = 0;
5437 f->async_iconified = 0;
5439 x_sync (f);
5441 UNBLOCK_INPUT;
5444 /* Change window state from mapped to iconified. */
5446 x_iconify_frame (f)
5447 struct frame *f;
5449 int mask;
5450 int result;
5451 Lisp_Object type;
5453 /* Don't keep the highlight on an invisible frame. */
5454 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
5455 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
5457 if (f->async_iconified)
5458 return;
5460 BLOCK_INPUT;
5462 FRAME_SAMPLE_VISIBILITY (f);
5464 type = x_icon_type (f);
5465 if (!NILP (type))
5466 x_bitmap_icon (f, type);
5468 #ifdef USE_X_TOOLKIT
5470 if (! FRAME_VISIBLE_P (f))
5472 if (! EQ (Vx_no_window_manager, Qt))
5473 x_wm_set_window_state (f, IconicState);
5474 /* This was XtPopup, but that did nothing for an iconified frame. */
5475 XtMapWidget (f->output_data.x->widget);
5476 UNBLOCK_INPUT;
5477 return;
5480 result = XIconifyWindow (FRAME_X_DISPLAY (f),
5481 XtWindow (f->output_data.x->widget),
5482 DefaultScreen (FRAME_X_DISPLAY (f)));
5483 UNBLOCK_INPUT;
5485 if (!result)
5486 error ("Can't notify window manager of iconification");
5488 f->async_iconified = 1;
5490 BLOCK_INPUT;
5491 XFlush (FRAME_X_DISPLAY (f));
5492 UNBLOCK_INPUT;
5493 #else /* not USE_X_TOOLKIT */
5495 /* Make sure the X server knows where the window should be positioned,
5496 in case the user deiconifies with the window manager. */
5497 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
5498 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
5500 /* Since we don't know which revision of X we're running, we'll use both
5501 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5503 /* X11R4: send a ClientMessage to the window manager using the
5504 WM_CHANGE_STATE type. */
5506 XEvent message;
5508 message.xclient.window = FRAME_X_WINDOW (f);
5509 message.xclient.type = ClientMessage;
5510 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
5511 message.xclient.format = 32;
5512 message.xclient.data.l[0] = IconicState;
5514 if (! XSendEvent (FRAME_X_DISPLAY (f),
5515 DefaultRootWindow (FRAME_X_DISPLAY (f)),
5516 False,
5517 SubstructureRedirectMask | SubstructureNotifyMask,
5518 &message))
5520 UNBLOCK_INPUT_RESIGNAL;
5521 error ("Can't notify window manager of iconification");
5525 /* X11R3: set the initial_state field of the window manager hints to
5526 IconicState. */
5527 x_wm_set_window_state (f, IconicState);
5529 if (!FRAME_VISIBLE_P (f))
5531 /* If the frame was withdrawn, before, we must map it. */
5532 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5535 f->async_iconified = 1;
5537 XFlush (FRAME_X_DISPLAY (f));
5538 UNBLOCK_INPUT;
5539 #endif /* not USE_X_TOOLKIT */
5542 /* Destroy the X window of frame F. */
5544 x_destroy_window (f)
5545 struct frame *f;
5547 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5549 BLOCK_INPUT;
5551 /* If a display connection is dead, don't try sending more
5552 commands to the X server. */
5553 if (dpyinfo->display != 0)
5555 if (f->output_data.x->icon_desc != 0)
5556 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
5557 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
5558 #ifdef USE_X_TOOLKIT
5559 XtDestroyWidget (f->output_data.x->widget);
5560 free_frame_menubar (f);
5561 #endif /* USE_X_TOOLKIT */
5563 free_frame_faces (f);
5564 XFlush (FRAME_X_DISPLAY (f));
5567 xfree (f->output_data.x);
5568 f->output_data.x = 0;
5569 if (f == dpyinfo->x_focus_frame)
5570 dpyinfo->x_focus_frame = 0;
5571 if (f == dpyinfo->x_focus_event_frame)
5572 dpyinfo->x_focus_event_frame = 0;
5573 if (f == dpyinfo->x_highlight_frame)
5574 dpyinfo->x_highlight_frame = 0;
5576 dpyinfo->reference_count--;
5578 if (f == dpyinfo->mouse_face_mouse_frame)
5580 dpyinfo->mouse_face_beg_row
5581 = dpyinfo->mouse_face_beg_col = -1;
5582 dpyinfo->mouse_face_end_row
5583 = dpyinfo->mouse_face_end_col = -1;
5584 dpyinfo->mouse_face_window = Qnil;
5587 UNBLOCK_INPUT;
5590 /* Setting window manager hints. */
5592 /* Set the normal size hints for the window manager, for frame F.
5593 FLAGS is the flags word to use--or 0 meaning preserve the flags
5594 that the window now has.
5595 If USER_POSITION is nonzero, we set the USPosition
5596 flag (this is useful when FLAGS is 0). */
5598 x_wm_set_size_hint (f, flags, user_position)
5599 struct frame *f;
5600 long flags;
5601 int user_position;
5603 XSizeHints size_hints;
5605 #ifdef USE_X_TOOLKIT
5606 Arg al[2];
5607 int ac = 0;
5608 Dimension widget_width, widget_height;
5609 Window window = XtWindow (f->output_data.x->widget);
5610 #else /* not USE_X_TOOLKIT */
5611 Window window = FRAME_X_WINDOW (f);
5612 #endif /* not USE_X_TOOLKIT */
5614 /* Setting PMaxSize caused various problems. */
5615 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5617 flexlines = f->height;
5619 size_hints.x = f->output_data.x->left_pos;
5620 size_hints.y = f->output_data.x->top_pos;
5622 #ifdef USE_X_TOOLKIT
5623 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5624 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5625 XtGetValues (f->output_data.x->widget, al, ac);
5626 size_hints.height = widget_height;
5627 size_hints.width = widget_width;
5628 #else /* not USE_X_TOOLKIT */
5629 size_hints.height = PIXEL_HEIGHT (f);
5630 size_hints.width = PIXEL_WIDTH (f);
5631 #endif /* not USE_X_TOOLKIT */
5633 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
5634 size_hints.height_inc = f->output_data.x->line_height;
5635 size_hints.max_width
5636 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
5637 size_hints.max_height
5638 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
5640 /* Calculate the base and minimum sizes.
5642 (When we use the X toolkit, we don't do it here.
5643 Instead we copy the values that the widgets are using, below.) */
5644 #ifndef USE_X_TOOLKIT
5646 int base_width, base_height;
5647 int min_rows = 0, min_cols = 0;
5649 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
5650 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
5652 check_frame_size (f, &min_rows, &min_cols);
5654 /* The window manager uses the base width hints to calculate the
5655 current number of rows and columns in the frame while
5656 resizing; min_width and min_height aren't useful for this
5657 purpose, since they might not give the dimensions for a
5658 zero-row, zero-column frame.
5660 We use the base_width and base_height members if we have
5661 them; otherwise, we set the min_width and min_height members
5662 to the size for a zero x zero frame. */
5664 #ifdef HAVE_X11R4
5665 size_hints.flags |= PBaseSize;
5666 size_hints.base_width = base_width;
5667 size_hints.base_height = base_height;
5668 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5669 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5670 #else
5671 size_hints.min_width = base_width;
5672 size_hints.min_height = base_height;
5673 #endif
5676 /* If we don't need the old flags, we don't need the old hint at all. */
5677 if (flags)
5679 size_hints.flags |= flags;
5680 goto no_read;
5682 #endif /* not USE_X_TOOLKIT */
5685 XSizeHints hints; /* Sometimes I hate X Windows... */
5686 long supplied_return;
5687 int value;
5689 #ifdef HAVE_X11R4
5690 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5691 &supplied_return);
5692 #else
5693 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5694 #endif
5696 #ifdef USE_X_TOOLKIT
5697 size_hints.base_height = hints.base_height;
5698 size_hints.base_width = hints.base_width;
5699 size_hints.min_height = hints.min_height;
5700 size_hints.min_width = hints.min_width;
5701 #endif
5703 if (flags)
5704 size_hints.flags |= flags;
5705 else
5707 if (value == 0)
5708 hints.flags = 0;
5709 if (hints.flags & PSize)
5710 size_hints.flags |= PSize;
5711 if (hints.flags & PPosition)
5712 size_hints.flags |= PPosition;
5713 if (hints.flags & USPosition)
5714 size_hints.flags |= USPosition;
5715 if (hints.flags & USSize)
5716 size_hints.flags |= USSize;
5720 no_read:
5722 #ifdef PWinGravity
5723 size_hints.win_gravity = f->output_data.x->win_gravity;
5724 size_hints.flags |= PWinGravity;
5726 if (user_position)
5728 size_hints.flags &= ~ PPosition;
5729 size_hints.flags |= USPosition;
5731 #endif /* PWinGravity */
5733 #ifdef HAVE_X11R4
5734 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5735 #else
5736 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5737 #endif
5740 /* Used for IconicState or NormalState */
5741 x_wm_set_window_state (f, state)
5742 struct frame *f;
5743 int state;
5745 #ifdef USE_X_TOOLKIT
5746 Arg al[1];
5748 XtSetArg (al[0], XtNinitialState, state);
5749 XtSetValues (f->output_data.x->widget, al, 1);
5750 #else /* not USE_X_TOOLKIT */
5751 Window window = FRAME_X_WINDOW (f);
5753 f->output_data.x->wm_hints.flags |= StateHint;
5754 f->output_data.x->wm_hints.initial_state = state;
5756 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5757 #endif /* not USE_X_TOOLKIT */
5760 x_wm_set_icon_pixmap (f, pixmap_id)
5761 struct frame *f;
5762 int pixmap_id;
5764 #ifdef USE_X_TOOLKIT
5765 Window window = XtWindow (f->output_data.x->widget);
5766 #else
5767 Window window = FRAME_X_WINDOW (f);
5768 #endif
5770 if (pixmap_id > 0)
5772 Pixmap icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5773 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5775 else
5777 /* It seems there is no way to turn off use of an icon pixmap.
5778 The following line does it, only if no icon has yet been created,
5779 for some window managers. But with mwm it crashes.
5780 Some people say it should clear the IconPixmapHint bit in this case,
5781 but that doesn't work, and the X consortium said it isn't the
5782 right thing at all. Since there is no way to win,
5783 best to explicitly give up. */
5784 #if 0
5785 f->output_data.x->wm_hints.icon_pixmap = None;
5786 #else
5787 return;
5788 #endif
5791 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5792 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5795 x_wm_set_icon_position (f, icon_x, icon_y)
5796 struct frame *f;
5797 int icon_x, icon_y;
5799 #ifdef USE_X_TOOLKIT
5800 Window window = XtWindow (f->output_data.x->widget);
5801 #else
5802 Window window = FRAME_X_WINDOW (f);
5803 #endif
5805 f->output_data.x->wm_hints.flags |= IconPositionHint;
5806 f->output_data.x->wm_hints.icon_x = icon_x;
5807 f->output_data.x->wm_hints.icon_y = icon_y;
5809 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5813 /* Initialization. */
5815 #ifdef USE_X_TOOLKIT
5816 static XrmOptionDescRec emacs_options[] = {
5817 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
5818 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
5820 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
5821 XrmoptionSepArg, NULL},
5822 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
5824 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5825 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5826 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
5827 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5828 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
5829 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
5830 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
5832 #endif /* USE_X_TOOLKIT */
5834 static int x_initialized;
5836 #ifdef MULTI_KBOARD
5837 /* Test whether two display-name strings agree up to the dot that separates
5838 the screen number from the server number. */
5839 static int
5840 same_x_server (name1, name2)
5841 char *name1, *name2;
5843 int seen_colon = 0;
5844 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
5846 if (*name1 == ':')
5847 seen_colon++;
5848 if (seen_colon && *name1 == '.')
5849 return 1;
5851 return (seen_colon
5852 && (*name1 == '.' || *name1 == '\0')
5853 && (*name2 == '.' || *name2 == '\0'));
5855 #endif
5857 struct x_display_info *
5858 x_term_init (display_name, xrm_option, resource_name)
5859 Lisp_Object display_name;
5860 char *xrm_option;
5861 char *resource_name;
5863 Lisp_Object frame;
5864 char *defaultvalue;
5865 int connection;
5866 Display *dpy;
5867 struct x_display_info *dpyinfo;
5868 XrmDatabase xrdb;
5870 BLOCK_INPUT;
5872 if (!x_initialized)
5874 x_initialize ();
5875 x_initialized = 1;
5878 #ifdef HAVE_X_I18N
5879 setlocale (LC_ALL, "");
5880 #endif
5882 #ifdef USE_X_TOOLKIT
5883 /* weiner@footloose.sps.mot.com reports that this causes
5884 errors with X11R5:
5885 X protocol error: BadAtom (invalid Atom parameter)
5886 on protocol request 18skiloaf.
5887 So let's not use it until R6. */
5888 #ifdef HAVE_X11XTR6
5889 XtSetLanguageProc (NULL, NULL, NULL);
5890 #endif
5893 int argc = 0;
5894 char *argv[3];
5896 argv[0] = "";
5897 argc = 1;
5898 if (xrm_option)
5900 argv[argc++] = "-xrm";
5901 argv[argc++] = xrm_option;
5903 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
5904 resource_name, EMACS_CLASS,
5905 emacs_options, XtNumber (emacs_options),
5906 &argc, argv);
5908 #ifdef HAVE_X11XTR6
5909 setlocale (LC_NUMERIC, "C");
5910 setlocale (LC_TIME, "C");
5911 #endif
5914 #else /* not USE_X_TOOLKIT */
5915 #ifdef HAVE_X11R5
5916 XSetLocaleModifiers ("");
5917 #endif
5918 dpy = XOpenDisplay (XSTRING (display_name)->data);
5919 #endif /* not USE_X_TOOLKIT */
5921 /* Detect failure. */
5922 if (dpy == 0)
5924 UNBLOCK_INPUT;
5925 return 0;
5928 /* We have definitely succeeded. Record the new connection. */
5930 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
5932 #ifdef MULTI_KBOARD
5934 struct x_display_info *share;
5935 Lisp_Object tail;
5937 for (share = x_display_list, tail = x_display_name_list; share;
5938 share = share->next, tail = XCONS (tail)->cdr)
5939 if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
5940 XSTRING (display_name)->data))
5941 break;
5942 if (share)
5943 dpyinfo->kboard = share->kboard;
5944 else
5946 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
5947 init_kboard (dpyinfo->kboard);
5948 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
5950 char *vendor = ServerVendor (dpy);
5951 dpyinfo->kboard->Vsystem_key_alist
5952 = call1 (Qvendor_specific_keysyms,
5953 build_string (vendor ? vendor : ""));
5956 dpyinfo->kboard->next_kboard = all_kboards;
5957 all_kboards = dpyinfo->kboard;
5958 /* Don't let the initial kboard remain current longer than necessary.
5959 That would cause problems if a file loaded on startup tries to
5960 prompt in the minibuffer. */
5961 if (current_kboard == initial_kboard)
5962 current_kboard = dpyinfo->kboard;
5964 dpyinfo->kboard->reference_count++;
5966 #endif
5968 /* Put this display on the chain. */
5969 dpyinfo->next = x_display_list;
5970 x_display_list = dpyinfo;
5972 /* Put it on x_display_name_list as well, to keep them parallel. */
5973 x_display_name_list = Fcons (Fcons (display_name, Qnil),
5974 x_display_name_list);
5975 dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
5977 dpyinfo->display = dpy;
5979 #if 0
5980 XSetAfterFunction (x_current_display, x_trace_wire);
5981 #endif /* ! 0 */
5983 dpyinfo->x_id_name
5984 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
5985 + XSTRING (Vsystem_name)->size
5986 + 2);
5987 sprintf (dpyinfo->x_id_name, "%s@%s",
5988 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
5990 /* Figure out which modifier bits mean what. */
5991 x_find_modifier_meanings (dpyinfo);
5993 /* Get the scroll bar cursor. */
5994 dpyinfo->vertical_scroll_bar_cursor
5995 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
5997 xrdb = x_load_resources (dpyinfo->display, xrm_option,
5998 resource_name, EMACS_CLASS);
5999 #ifdef HAVE_XRMSETDATABASE
6000 XrmSetDatabase (dpyinfo->display, xrdb);
6001 #else
6002 dpyinfo->display->db = xrdb;
6003 #endif
6004 /* Put the rdb where we can find it in a way that works on
6005 all versions. */
6006 dpyinfo->xrdb = xrdb;
6008 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
6009 DefaultScreen (dpyinfo->display));
6010 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
6011 &dpyinfo->n_planes);
6012 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
6013 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
6014 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
6015 dpyinfo->grabbed = 0;
6016 dpyinfo->reference_count = 0;
6017 dpyinfo->icon_bitmap_id = -1;
6018 dpyinfo->n_fonts = 0;
6019 dpyinfo->font_table_size = 0;
6020 dpyinfo->bitmaps = 0;
6021 dpyinfo->bitmaps_size = 0;
6022 dpyinfo->bitmaps_last = 0;
6023 dpyinfo->scratch_cursor_gc = 0;
6024 dpyinfo->mouse_face_mouse_frame = 0;
6025 dpyinfo->mouse_face_deferred_gc = 0;
6026 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6027 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6028 dpyinfo->mouse_face_face_id = 0;
6029 dpyinfo->mouse_face_window = Qnil;
6030 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
6031 dpyinfo->mouse_face_defer = 0;
6032 dpyinfo->x_focus_frame = 0;
6033 dpyinfo->x_focus_event_frame = 0;
6034 dpyinfo->x_highlight_frame = 0;
6036 dpyinfo->Xatom_wm_protocols
6037 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
6038 dpyinfo->Xatom_wm_take_focus
6039 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
6040 dpyinfo->Xatom_wm_save_yourself
6041 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
6042 dpyinfo->Xatom_wm_delete_window
6043 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
6044 dpyinfo->Xatom_wm_change_state
6045 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
6046 dpyinfo->Xatom_wm_configure_denied
6047 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
6048 dpyinfo->Xatom_wm_window_moved
6049 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
6050 dpyinfo->Xatom_editres
6051 = XInternAtom (dpyinfo->display, "Editres", False);
6052 dpyinfo->Xatom_CLIPBOARD
6053 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
6054 dpyinfo->Xatom_TIMESTAMP
6055 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
6056 dpyinfo->Xatom_TEXT
6057 = XInternAtom (dpyinfo->display, "TEXT", False);
6058 dpyinfo->Xatom_DELETE
6059 = XInternAtom (dpyinfo->display, "DELETE", False);
6060 dpyinfo->Xatom_MULTIPLE
6061 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
6062 dpyinfo->Xatom_INCR
6063 = XInternAtom (dpyinfo->display, "INCR", False);
6064 dpyinfo->Xatom_EMACS_TMP
6065 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
6066 dpyinfo->Xatom_TARGETS
6067 = XInternAtom (dpyinfo->display, "TARGETS", False);
6068 dpyinfo->Xatom_NULL
6069 = XInternAtom (dpyinfo->display, "NULL", False);
6070 dpyinfo->Xatom_ATOM_PAIR
6071 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
6073 dpyinfo->cut_buffers_initialized = 0;
6075 connection = ConnectionNumber (dpyinfo->display);
6076 dpyinfo->connection = connection;
6078 #ifdef subprocesses
6079 /* This is only needed for distinguishing keyboard and process input. */
6080 if (connection != 0)
6081 add_keyboard_wait_descriptor (connection);
6082 #endif
6084 #ifndef F_SETOWN_BUG
6085 #ifdef F_SETOWN
6086 #ifdef F_SETOWN_SOCK_NEG
6087 /* stdin is a socket here */
6088 fcntl (connection, F_SETOWN, -getpid ());
6089 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6090 fcntl (connection, F_SETOWN, getpid ());
6091 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6092 #endif /* ! defined (F_SETOWN) */
6093 #endif /* F_SETOWN_BUG */
6095 #ifdef SIGIO
6096 if (interrupt_input)
6097 init_sigio (connection);
6098 #endif /* ! defined (SIGIO) */
6100 UNBLOCK_INPUT;
6102 return dpyinfo;
6105 /* Get rid of display DPYINFO, assuming all frames are already gone,
6106 and without sending any more commands to the X server. */
6108 void
6109 x_delete_display (dpyinfo)
6110 struct x_display_info *dpyinfo;
6112 delete_keyboard_wait_descriptor (dpyinfo->connection);
6114 /* Discard this display from x_display_name_list and x_display_list.
6115 We can't use Fdelq because that can quit. */
6116 if (! NILP (x_display_name_list)
6117 && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
6118 x_display_name_list = XCONS (x_display_name_list)->cdr;
6119 else
6121 Lisp_Object tail;
6123 tail = x_display_name_list;
6124 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
6126 if (EQ (XCONS (XCONS (tail)->cdr)->car,
6127 dpyinfo->name_list_element))
6129 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
6130 break;
6132 tail = XCONS (tail)->cdr;
6136 if (x_display_list == dpyinfo)
6137 x_display_list = dpyinfo->next;
6138 else
6140 struct x_display_info *tail;
6142 for (tail = x_display_list; tail; tail = tail->next)
6143 if (tail->next == dpyinfo)
6144 tail->next = tail->next->next;
6147 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6148 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6149 XrmDestroyDatabase (dpyinfo->xrdb);
6150 #endif
6151 #endif
6152 #ifdef MULTI_KBOARD
6153 if (--dpyinfo->kboard->reference_count == 0)
6154 delete_kboard (dpyinfo->kboard);
6155 #endif
6156 xfree (dpyinfo->font_table);
6157 xfree (dpyinfo->x_id_name);
6158 xfree (dpyinfo);
6161 /* Set up use of X before we make the first connection. */
6163 x_initialize ()
6165 clear_frame_hook = XTclear_frame;
6166 clear_end_of_line_hook = XTclear_end_of_line;
6167 ins_del_lines_hook = XTins_del_lines;
6168 change_line_highlight_hook = XTchange_line_highlight;
6169 insert_glyphs_hook = XTinsert_glyphs;
6170 write_glyphs_hook = XTwrite_glyphs;
6171 delete_glyphs_hook = XTdelete_glyphs;
6172 ring_bell_hook = XTring_bell;
6173 reset_terminal_modes_hook = XTreset_terminal_modes;
6174 set_terminal_modes_hook = XTset_terminal_modes;
6175 update_begin_hook = XTupdate_begin;
6176 update_end_hook = XTupdate_end;
6177 set_terminal_window_hook = XTset_terminal_window;
6178 read_socket_hook = XTread_socket;
6179 frame_up_to_date_hook = XTframe_up_to_date;
6180 cursor_to_hook = XTcursor_to;
6181 reassert_line_highlight_hook = XTreassert_line_highlight;
6182 mouse_position_hook = XTmouse_position;
6183 frame_rehighlight_hook = XTframe_rehighlight;
6184 frame_raise_lower_hook = XTframe_raise_lower;
6185 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
6186 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
6187 redeem_scroll_bar_hook = XTredeem_scroll_bar;
6188 judge_scroll_bars_hook = XTjudge_scroll_bars;
6190 scroll_region_ok = 1; /* we'll scroll partial frames */
6191 char_ins_del_ok = 0; /* just as fast to write the line */
6192 line_ins_del_ok = 1; /* we'll just blt 'em */
6193 fast_clear_end_of_line = 1; /* X does this well */
6194 memory_below_frame = 0; /* we don't remember what scrolls
6195 off the bottom */
6196 baud_rate = 19200;
6198 x_noop_count = 0;
6200 /* Try to use interrupt input; if we can't, then start polling. */
6201 Fset_input_mode (Qt, Qnil, Qt, Qnil);
6203 #ifdef USE_X_TOOLKIT
6204 XtToolkitInitialize ();
6205 Xt_app_con = XtCreateApplicationContext ();
6206 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
6207 #endif
6209 /* Note that there is no real way portable across R3/R4 to get the
6210 original error handler. */
6211 XSetErrorHandler (x_error_quitter);
6212 XSetIOErrorHandler (x_io_error_quitter);
6214 /* Disable Window Change signals; they are handled by X events. */
6215 #ifdef SIGWINCH
6216 signal (SIGWINCH, SIG_DFL);
6217 #endif /* ! defined (SIGWINCH) */
6219 signal (SIGPIPE, x_connection_signal);
6222 void
6223 syms_of_xterm ()
6225 staticpro (&x_display_name_list);
6226 x_display_name_list = Qnil;
6228 staticpro (&last_mouse_scroll_bar);
6229 last_mouse_scroll_bar = Qnil;
6231 staticpro (&Qvendor_specific_keysyms);
6232 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
6234 #endif /* ! defined (HAVE_X_WINDOWS) */