1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997 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)
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. */
35 #include "blockinput.h"
37 /* Need syssignal.h for various externs and definitions that may be required
38 by some configurations for calls to signal later in this source file. */
39 #include "syssignal.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
44 #include <X11/cursorfont.h>
47 /* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
50 #include <sys/types.h>
55 #include <sys/ioctl.h>
56 #endif /* ! defined (BSD_SYSTEM) */
61 #ifndef INCLUDED_FCNTL
68 /* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
69 /* #include <sys/param.h> */
75 #include "dispextern.h"
76 #include "termhooks.h"
88 #include "intervals.h"
92 #include <X11/Shell.h>
96 extern void free_frame_menubar ();
97 extern FRAME_PTR
x_menubar_window_to_frame ();
98 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
100 extern void _XEditResCheckMessages ();
101 #endif /* not NO_EDITRES */
102 #endif /* USE_X_TOOLKIT */
104 #ifndef USE_X_TOOLKIT
105 #define x_any_window_to_frame x_window_to_frame
106 #define x_top_window_to_frame x_window_to_frame
111 #ifndef XtNinitialState
112 #define XtNinitialState "initialState"
116 #ifdef HAVE_SETLOCALE
117 /* So we can do setlocale. */
122 /* memmove will be defined as a macro in Xfuncs.h unless
123 <string.h> is included beforehand. The declaration for memmove in
124 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
129 #define min(a,b) ((a)<(b) ? (a) : (b))
132 #define max(a,b) ((a)>(b) ? (a) : (b))
135 /* This is a chain of structures for all the X displays currently in use. */
136 struct x_display_info
*x_display_list
;
138 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
139 one for each element of x_display_list and in the same order.
140 NAME is the name of the frame.
141 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
142 Lisp_Object x_display_name_list
;
144 /* Frame being updated by update_frame. This is declared in term.c.
145 This is set by update_begin and looked at by all the
146 XT functions. It is zero while not inside an update.
147 In that case, the XT functions assume that `selected_frame'
148 is the frame to apply to. */
149 extern struct frame
*updating_frame
;
151 extern int waiting_for_input
;
153 /* This is a frame waiting to be autoraised, within XTread_socket. */
154 struct frame
*pending_autoraise_frame
;
157 /* The application context for Xt use. */
158 XtAppContext Xt_app_con
;
160 static String Xt_default_resources
[] =
166 /* During an update, maximum vpos for ins/del line operations to affect. */
168 static int flexlines
;
170 /* During an update, nonzero if chars output now should be highlighted. */
172 static int highlight
;
174 /* Nominal cursor position -- where to draw output.
175 During an update, these are different from the cursor-box position. */
182 Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK)
183 so that we would have to call XQueryPointer after each MotionNotify
184 event to ask for another such event. However, this made mouse tracking
185 slow, and there was a bug that made it eventually stop.
187 Simply asking for MotionNotify all the time seems to work better.
189 In order to avoid asking for motion events and then throwing most
190 of them away or busy-polling the server for mouse positions, we ask
191 the server for pointer motion hints. This means that we get only
192 one event per group of mouse movements. "Groups" are delimited by
193 other kinds of events (focus changes and button clicks, for
194 example), or by XQueryPointer calls; when one of these happens, we
195 get another MotionNotify event the next time the mouse moves. This
196 is at least as efficient as getting motion events when mouse
197 tracking is on, and I suspect only negligibly worse when tracking
200 /* Where the mouse was last time we reported a mouse event. */
201 static FRAME_PTR last_mouse_frame
;
202 static XRectangle last_mouse_glyph
;
204 static Lisp_Object last_mouse_press_frame
;
206 /* The scroll bar in which the last X motion event occurred.
208 If the last X motion event occurred in a scroll bar, we set this
209 so XTmouse_position can know whether to report a scroll bar motion or
212 If the last X motion event didn't occur in a scroll bar, we set this
213 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
214 static Lisp_Object last_mouse_scroll_bar
;
216 /* This is a hack. We would really prefer that XTmouse_position would
217 return the time associated with the position it returns, but there
218 doesn't seem to be any way to wrest the timestamp from the server
219 along with the position query. So, we just keep track of the time
220 of the last movement we received, and return that in hopes that
221 it's somewhat accurate. */
222 static Time last_mouse_movement_time
;
224 /* Incremented by XTread_socket whenever it really tries to read events. */
226 static int volatile input_signal_count
;
228 static int input_signal_count
;
231 /* Used locally within XTread_socket. */
232 static int x_noop_count
;
234 /* Initial values of argv and argc. */
235 extern char **initial_argv
;
236 extern int initial_argc
;
238 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
240 /* Tells if a window manager is present or not. */
242 extern Lisp_Object Vx_no_window_manager
;
244 extern Lisp_Object Qface
, Qmouse_face
;
248 /* A mask of extra modifier bits to put into every keyboard char. */
249 extern int extra_keyboard_modifiers
;
251 static Lisp_Object Qvendor_specific_keysyms
;
253 extern XrmDatabase
x_load_resources ();
255 extern Lisp_Object
x_icon_type ();
257 void x_delete_display ();
259 static void redraw_previous_char ();
260 static void redraw_following_char ();
261 static unsigned int x_x_to_emacs_modifiers ();
263 static int fast_find_position ();
264 static void note_mouse_highlight ();
265 static void clear_mouse_face ();
266 static void show_mouse_face ();
267 static void do_line_dance ();
269 static void XTcursor_to ();
270 static void XTclear_end_of_line ();
271 static int x_io_error_quitter ();
272 int x_catch_errors ();
273 void x_uncatch_errors ();
276 /* This is a function useful for recording debugging information
277 about the sequence of occurrences in this file. */
285 struct record event_record
[100];
287 int event_record_index
;
289 record_event (locus
, type
)
293 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
294 event_record_index
= 0;
296 event_record
[event_record_index
].locus
= locus
;
297 event_record
[event_record_index
].type
= type
;
298 event_record_index
++;
303 /* Return the struct x_display_info corresponding to DPY. */
305 struct x_display_info
*
306 x_display_info_for_display (dpy
)
309 struct x_display_info
*dpyinfo
;
311 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
312 if (dpyinfo
->display
== dpy
)
318 /* Starting and ending updates.
320 These hooks are called by update_frame at the beginning and end
321 of a frame update. We record in `updating_frame' the identity
322 of the frame being updated, so that the XT... functions do not
323 need to take a frame as argument. Most of the XT... functions
324 should never be called except during an update, the only exceptions
325 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
336 flexlines
= f
->height
;
341 curs_x
= FRAME_CURSOR_X (f
);
342 curs_y
= FRAME_CURSOR_Y (f
);
344 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
346 /* Don't do highlighting for mouse motion during the update. */
347 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
349 /* If the frame needs to be redrawn,
350 simply forget about any prior mouse highlighting. */
351 if (FRAME_GARBAGED_P (f
))
352 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
354 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
356 int firstline
, lastline
, i
;
357 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
359 /* Find the first, and the last+1, lines affected by redisplay. */
360 for (firstline
= 0; firstline
< f
->height
; firstline
++)
361 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
364 lastline
= f
->height
;
365 for (i
= f
->height
- 1; i
>= 0; i
--)
367 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
373 /* Can we tell that this update does not affect the window
374 where the mouse highlight is? If so, no need to turn off.
375 Likewise, don't do anything if the frame is garbaged;
376 in that case, the FRAME_CURRENT_GLYPHS that we would use
377 are all wrong, and we will redisplay that line anyway. */
378 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
379 || lastline
< XFASTINT (w
->top
)))
380 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
396 x_display_cursor (f
, 1, curs_x
, curs_y
);
398 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
400 /* This fails in the case of having updated only the echo area
401 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
402 has no relation to the current contents, and its charstarts
403 have no relation to the contents of the window-buffer.
404 I don't know a clean way to check
405 for that case. window_end_valid isn't set up yet. */
406 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
407 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
408 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
411 XFlush (FRAME_X_DISPLAY (f
));
415 /* This is called after a redisplay on frame F. */
418 XTframe_up_to_date (f
)
422 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
423 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
425 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
426 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
427 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
428 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
429 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
434 /* External interface to control of standout mode.
435 Call this when about to modify line at position VPOS
436 and not change whether it is highlighted. */
439 XTreassert_line_highlight (new, vpos
)
445 /* Call this when about to modify line at position VPOS
446 and change whether it is highlighted. */
449 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
450 int new_highlight
, vpos
, first_unused_hpos
;
452 highlight
= new_highlight
;
453 XTcursor_to (vpos
, 0);
454 XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame
));
457 /* This is used when starting Emacs and when restarting after suspend.
458 When starting Emacs, no X window is mapped. And nothing must be done
459 to Emacs's own window if it is suspended (though that rarely happens). */
462 XTset_terminal_modes ()
466 /* This is called when exiting or suspending Emacs.
467 Exiting will make the X-windows go away, and suspending
468 requires no action. */
471 XTreset_terminal_modes ()
473 /* XTclear_frame (); */
476 /* Set the nominal cursor position of the frame.
477 This is where display update commands will take effect.
478 This does not affect the place where the cursor-box is displayed. */
481 XTcursor_to (row
, col
)
482 register int row
, col
;
493 if (curs_x
>= FRAME_CURSOR_X_LIMIT (f
))
494 curs_x
= FRAME_CURSOR_X_LIMIT (f
) - 1;
498 if (updating_frame
== 0)
501 x_display_cursor (selected_frame
, 1, curs_x
, curs_y
);
502 XFlush (FRAME_X_DISPLAY (selected_frame
));
508 /* Return a pointer to per char metric information in FONT of a
509 character pointed by B (*XChar2b). */
511 #define PER_CHAR_METRIC(font, b) \
513 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
514 + (((font)->min_byte1 || (font)->max_byte1) \
515 ? (((b)->byte1 - (font)->min_byte1) \
516 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
518 : &((font)->max_bounds))
520 /* Display a sequence of N glyphs found at GP.
521 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
522 HL is 1 if this text is highlighted, 2 if the cursor is on it,
523 3 if should appear in its mouse-face.
524 JUST_FOREGROUND if 1 means draw only the foreground;
525 don't alter the background.
527 CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which
528 means drawing glyphs on the same column. This is set to non NULL
529 only when recursively called within dumpglyphs to draw a composite
530 character specified by CMPCHAR.
532 FONT is the default font to use (for glyphs whose font-code is 0).
534 Since the display generation code is responsible for calling
535 compute_char_face and compute_glyph_face on everything it puts in
536 the display structure, we can assume that the face code on each
537 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
538 to which we can actually apply intern_face.
539 Call this function with input blocked.
541 Return overall pixel width of the drawn glyphs. */
544 /* This is the multi-face code. */
547 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
550 register GLYPH
*gp
; /* Points to first GLYPH. */
551 register int n
; /* Number of glyphs to display. */
554 struct cmpchar_info
*cmpcharp
;
556 /* Holds characters to be displayed. */
557 XChar2b
*x_2byte_buffer
558 = (XChar2b
*) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_2byte_buffer
));
559 register XChar2b
*cp
; /* Steps through x_2byte_buffer[]. */
561 = (char *) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*x_1byte_buffer
));
562 register int tlen
= GLYPH_TABLE_LENGTH
;
563 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
564 Window window
= FRAME_X_WINDOW (f
);
565 int orig_left
= left
;
571 /* Get the face-code of the next GLYPH. */
575 Lisp_Object first_ch
;
576 /* HIGHEST and LOWEST are used while drawing a composite
577 character. The meanings are described later. */
580 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
581 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
582 ch
= FAST_GLYPH_CHAR (g
);
583 if (unibyte_display_via_language_environment
584 && SINGLE_BYTE_CHAR_P (ch
)
585 && (ch
>= 0240 || !NILP (Vnonascii_translation_table
)))
586 ch
= unibyte_char_to_multibyte (ch
);
587 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
588 charset
= CHAR_CHARSET (ch
);
589 if (charset
== CHARSET_COMPOSITION
)
591 /* We must draw components of the composite character on the
593 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
595 /* Set the face in the slot for work. */
596 cmpcharp
->face_work
= cf
;
598 /* We don't need the return value ... */
599 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
600 hl
, just_foreground
, cmpcharp
);
601 /* ... because the width of just drawn text can be
602 calculated as follows. */
603 left
+= FONT_WIDTH (f
->output_data
.x
->font
) * cmpcharp
->width
;
606 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
611 /* Find the run of consecutive glyphs which can be drawn with
612 the same GC (i.e. the same charset and the same face-code).
613 Extract their character codes into X_2BYTE_BUFFER.
614 If CMPCHARP is not NULL, face-code is not checked because we
615 use only the face specified in `cmpcharp->face_work'. */
619 int this_charset
, c1
, c2
;
622 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
623 ch
= FAST_GLYPH_CHAR (g
);
624 if (unibyte_display_via_language_environment
625 && SINGLE_BYTE_CHAR_P (ch
)
626 && (ch
>= 0240 || !NILP (Vnonascii_translation_table
)))
627 ch
= unibyte_char_to_multibyte (ch
);
628 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
629 if (this_charset
!= charset
630 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
634 cp
->byte1
= c1
, cp
->byte2
= c2
;
636 cp
->byte1
= 0, cp
->byte2
= c1
;
639 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
643 /* LEN gets the length of the run. */
644 len
= cp
- x_2byte_buffer
;
645 /* Now output this run of chars, with the font and pixel values
646 determined by the face code CF. */
648 struct face
*face
= FRAME_DEFAULT_FACE (f
);
649 XFontStruct
*font
= NULL
;
652 int line_height
= f
->output_data
.x
->line_height
;
653 /* Pixel width of each glyph in this run. */
655 = (FONT_WIDTH (f
->output_data
.x
->font
)
656 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
657 /* Overall pixel width of this run. */
659 = (FONT_WIDTH (f
->output_data
.x
->font
)
660 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
661 /* A flag to tell if we have already filled background. We
662 fill background in advance in the following cases:
663 1) A face has stipple.
664 2) A height of font is shorter than LINE_HEIGHT.
665 3) Drawing a composite character.
666 4) Font has non-zero _MULE_BASELINE_OFFSET property.
667 After filling background, we draw glyphs by XDrawString16. */
668 int background_filled
;
669 /* Baseline position of a character, offset from TOP. */
671 /* The property value of `_MULE_RELATIVE_COMPOSE' and
672 `_MULE_DEFAULT_ASCENT'. */
673 int relative_compose
= 0, default_ascent
= 0;
674 /* 1 if we find no font or a font of inappropriate size. */
675 int require_clipping
;
677 /* HL = 3 means use a mouse face previously chosen. */
679 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
681 /* First look at the face of the text itself. */
684 /* It's possible for the display table to specify
685 a face code that is out of range. Use 0 in that case. */
686 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
687 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
691 face
= FRAME_MODE_LINE_FACE (f
);
693 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
694 if (FACE_STIPPLE (face
))
698 /* Then comes the distinction between modeline and normal text. */
703 face
= FRAME_MODE_LINE_FACE (f
);
704 if (FACE_STIPPLE (face
))
708 #define FACE_DEFAULT (~0)
710 /* Setting appropriate font and gc for this charset. */
711 if (charset
!= CHARSET_ASCII
)
714 int fontset
= FACE_FONTSET (face
);
715 struct font_info
*fontp
;
717 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
718 || !(fontp
= FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
719 charset
, NULL
, fontset
)))
722 font
= (XFontStruct
*) (fontp
->font
);
723 gc
= FACE_NON_ASCII_GC (face
);
724 XSetFont (FRAME_X_DISPLAY (f
), gc
, font
->fid
);
726 = (font
->max_byte1
!= 0
727 ? (line_height
+ font
->ascent
- font
->descent
) / 2
728 : f
->output_data
.x
->font_baseline
- fontp
->baseline_offset
);
729 if (FONT_HEIGHT (font
) <= line_height
730 && (font
->ascent
> baseline
731 || font
->descent
> line_height
- baseline
))
732 /* Adjust baseline for this font to show the whole
734 baseline
= line_height
- font
->descent
;
736 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
738 relative_compose
= fontp
->relative_compose
;
739 default_ascent
= fontp
->default_ascent
;
742 /* We have to change code points in the following cases. */
743 if (fontp
->font_encoder
)
745 /* This font requires CCL program to calculate code
746 point of characters. */
747 struct ccl_program
*ccl
= fontp
->font_encoder
;
749 if (CHARSET_DIMENSION (charset
) == 1)
750 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
752 ccl
->reg
[0] = charset
;
753 ccl
->reg
[1] = cp
->byte2
;
754 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
755 /* We assume that MSBs are appropriately
756 set/reset by CCL program. */
757 if (font
->max_byte1
== 0) /* 1-byte font */
758 cp
->byte1
= 0, cp
->byte2
= ccl
->reg
[1];
760 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
763 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
765 ccl
->reg
[0] = charset
;
766 ccl
->reg
[1] = cp
->byte1
, ccl
->reg
[2] = cp
->byte2
;
767 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
768 /* We assume that MSBs are appropriately
769 set/reset by CCL program. */
770 if (font
->max_byte1
== 0) /* 1-byte font */
771 cp
->byte1
= 0, cp
->byte2
= ccl
->reg
[1];
773 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
776 else if (fontp
->encoding
[charset
])
778 int enc
= fontp
->encoding
[charset
];
780 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
781 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
783 if (enc
== 1 || enc
== 3)
784 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
791 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
793 font
= FACE_FONT (face
);
794 if (!font
|| font
== (XFontStruct
*) FACE_DEFAULT
)
795 font
= f
->output_data
.x
->font
;
796 baseline
= FONT_BASE (f
->output_data
.x
->font
);
797 if (charset
== charset_latin_iso8859_1
)
799 if (font
->max_char_or_byte2
< 0x80)
800 /* This font can't display Latin1 characters. */
804 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
812 /* Now override that if the cursor's on this character. */
815 /* The cursor overrides stippling. */
818 if (font
== f
->output_data
.x
->font
819 && face
->background
== f
->output_data
.x
->background_pixel
820 && face
->foreground
== f
->output_data
.x
->foreground_pixel
823 gc
= f
->output_data
.x
->cursor_gc
;
825 /* Cursor on non-default face: must merge. */
831 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
832 xgcv
.foreground
= face
->background
;
833 /* If the glyph would be invisible,
834 try a different foreground. */
835 if (xgcv
.foreground
== xgcv
.background
)
836 xgcv
.foreground
= face
->foreground
;
837 if (xgcv
.foreground
== xgcv
.background
)
838 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
839 if (xgcv
.foreground
== xgcv
.background
)
840 xgcv
.foreground
= face
->foreground
;
841 /* Make sure the cursor is distinct from text in this face. */
842 if (xgcv
.background
== face
->background
843 && xgcv
.foreground
== face
->foreground
)
845 xgcv
.background
= face
->foreground
;
846 xgcv
.foreground
= face
->background
;
848 xgcv
.graphics_exposures
= 0;
849 mask
= GCForeground
| GCBackground
| GCGraphicsExposures
;
852 xgcv
.font
= font
->fid
;
856 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
857 XChangeGC (FRAME_X_DISPLAY (f
),
858 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
861 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
862 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
863 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
865 /* If this code is restored, it must also reset to the default stipple
867 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
868 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
874 require_clipping
= (!NILP (Vclip_large_size_font
)
875 && (font
->ascent
> baseline
876 || font
->descent
> line_height
- baseline
878 && FONT_WIDTH (font
) > glyph_width
)));
880 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
881 background_filled
= 1;
884 /* Turn stipple on. */
885 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
887 /* Draw stipple or background color on background. */
888 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
889 left
, top
, run_width
, line_height
);
891 /* Turn stipple off. */
892 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
894 background_filled
= 1;
897 || FONT_HEIGHT (font
) < line_height
898 || FONT_WIDTH (font
) < glyph_width
901 /* Fill a area for the current run in background pixle of GC. */
903 unsigned long mask
= GCForeground
| GCBackground
| GCFillStyle
;
905 /* The current code at first set foreground to background,
906 fill the area, then recover the original foreground.
907 Aren't there any smarter ways? */
909 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
910 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
911 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
912 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
913 left
, top
, run_width
, line_height
);
914 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
916 background_filled
= 1;
918 /* To assure not to fill background while drawing
919 remaining components. */
923 background_filled
= 0;
927 if (require_clipping
)
929 Region region
; /* Region used for setting clip mask to GC. */
930 XPoint x
[4]; /* Data used for creating REGION. */
932 x
[0].x
= x
[3].x
= left
, x
[1].x
= x
[2].x
= left
+ glyph_width
;
933 x
[0].y
= x
[1].y
= top
, x
[2].y
= x
[3].y
= top
+ line_height
;
934 region
= XPolygonRegion (x
, 4, EvenOddRule
);
935 XSetRegion (FRAME_X_DISPLAY (f
), gc
, region
);
936 XDestroyRegion (region
);
941 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
)
942 for (i
= 0; i
< len
; i
++)
944 if (require_clipping
&& i
> 0)
945 XSetClipOrigin (FRAME_X_DISPLAY (f
), gc
,
947 if (background_filled
)
948 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
949 left
+ glyph_width
* i
,
950 top
+ baseline
, x_2byte_buffer
+ i
, 1);
952 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
953 left
+ glyph_width
* i
,
954 top
+ baseline
, x_2byte_buffer
+ i
, 1);
958 /* See if this whole buffer can be output as 8-bit chars.
959 If so, copy x_2byte_buffer to x_1byte_buffer
960 and do it as 8-bit chars. */
961 for (i
= 0; i
< len
; i
++)
963 if (x_2byte_buffer
[i
].byte1
!= 0)
965 x_1byte_buffer
[i
] = x_2byte_buffer
[i
].byte2
;
970 if (background_filled
)
971 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
972 left
, top
+ baseline
, x_1byte_buffer
, len
);
974 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
975 left
, top
+ baseline
, x_1byte_buffer
, len
);
979 /* We can't output them as 8-bit chars,
980 so do it as 16-bit chars. */
982 if (background_filled
)
983 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
984 left
, top
+ baseline
, x_2byte_buffer
, len
);
986 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
987 left
, top
+ baseline
, x_2byte_buffer
, len
);
993 /* Handle composite characters. */
994 XCharStruct
*pcm
; /* Pointer to per char metric info. */
996 if ((cmpcharp
->cmp_rule
|| relative_compose
)
999 /* This is the first character. Initialize variables.
1000 HIGHEST is the highest position of glyphs ever
1001 written, LOWEST the lowest position. */
1005 && CHAR_TABLE_P (Vuse_default_ascent
)
1006 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
1008 highest
= default_ascent
;
1013 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
);
1014 highest
= pcm
->ascent
+ 1;
1015 lowest
= - pcm
->descent
;
1018 if (cmpcharp
->cmp_rule
)
1019 x_offset
= (cmpcharp
->col_offset
[0]
1020 * FONT_WIDTH (f
->output_data
.x
->font
));
1021 /* Draw the first character at the normal position. */
1022 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1023 left
+ x_offset
, top
+ baseline
, x_2byte_buffer
, 1);
1030 for (; i
< len
; i
++, gidx
++)
1032 int x_offset
= 0, y_offset
= 0;
1034 if (relative_compose
)
1036 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1037 if (NILP (Vignore_relative_composition
)
1038 || NILP (Faref (Vignore_relative_composition
,
1039 make_number (cmpcharp
->glyph
[gidx
]))))
1041 if (- pcm
->descent
>= relative_compose
)
1043 /* Draw above the current glyphs. */
1044 y_offset
= highest
+ pcm
->descent
;
1045 highest
+= pcm
->ascent
+ pcm
->descent
;
1047 else if (pcm
->ascent
<= 0)
1049 /* Draw beneath the current glyphs. */
1050 y_offset
= lowest
- pcm
->ascent
;
1051 lowest
-= pcm
->ascent
+ pcm
->descent
;
1056 /* Draw the glyph at normal position. If
1057 it sticks out of HIGHEST or LOWEST,
1058 update them appropriately. */
1059 if (pcm
->ascent
> highest
)
1060 highest
= pcm
->ascent
;
1061 else if (- pcm
->descent
< lowest
)
1062 lowest
= - pcm
->descent
;
1065 else if (cmpcharp
->cmp_rule
)
1067 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1068 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1071 /* Re-encode GREF and NREF so that they specify
1072 only Y-axis information:
1073 0:top, 1:base, 2:bottom, 3:center */
1074 gref
= gref
/ 3 + (gref
== 4) * 2;
1075 nref
= nref
/ 3 + (nref
== 4) * 2;
1077 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1078 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1079 : gref
== 2 ? lowest
1080 : (highest
+ lowest
) / 2)
1081 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
1082 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
1083 : (pcm
->ascent
+ pcm
->descent
) / 2));
1084 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
1087 if (bottom
< lowest
)
1089 y_offset
= bottom
+ pcm
->descent
;
1090 x_offset
= (cmpcharp
->col_offset
[gidx
]
1091 * FONT_WIDTH (f
->output_data
.x
->font
));
1093 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1094 left
+ x_offset
, top
+ baseline
- y_offset
,
1095 x_2byte_buffer
+ i
, 1);
1098 if (require_clipping
)
1099 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
1101 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
1102 which often is not up to date yet. */
1103 if (!just_foreground
)
1105 if (left
== orig_left
)
1106 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
1107 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1109 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
1110 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1116 /* Show rectangles to indicate that we found no font. */
1117 int limit
= cmpcharp
? 1 : len
;
1119 for (i
= 0; i
< limit
; i
++)
1120 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1121 left
+ glyph_width
* i
, top
,
1122 glyph_width
- 1, line_height
- 1);
1124 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1126 /* Show ??? to indicate that we found a font of
1127 inappropriate size. */
1128 int limit
= cmpcharp
? 1 : len
;
1130 for (i
= 0; i
< limit
; i
++)
1132 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1133 left
+ glyph_width
* i
, top
+ line_height
- 1,
1134 left
+ glyph_width
* i
+ 1, top
+ line_height
- 1);
1135 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1136 left
+ glyph_width
* i
, top
+ line_height
- 3,
1137 left
+ glyph_width
* i
, top
+ line_height
- 1);
1141 /* We should probably check for XA_UNDERLINE_POSITION and
1142 XA_UNDERLINE_THICKNESS properties on the font, but let's
1143 just get the thing working, and come back to that. */
1145 /* Setting underline position based on the metric of the
1146 current font results in shaky underline if it strides
1147 over different fonts. So, we set the position based only
1148 on the default font of this frame. */
1149 int underline_position
= f
->output_data
.x
->font_baseline
+ 1;
1151 if (underline_position
>= line_height
)
1152 underline_position
= line_height
- 1;
1154 if (face
->underline
)
1155 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1157 left
, top
+ underline_position
, run_width
, 1);
1165 return (left
- orig_left
);
1170 /* This is the old single-face code. */
1173 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
1176 register GLYPH
*gp
; /* Points to first GLYPH. */
1177 register int n
; /* Number of glyphs to display. */
1182 Window window
= FRAME_X_WINDOW (f
);
1183 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
1184 : (hl
? f
->output_data
.x
->reverse_gc
1185 : f
->output_data
.x
->normal_gc
));
1187 if (sizeof (GLYPH
) == sizeof (XChar2b
))
1188 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1189 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
1190 else if (sizeof (GLYPH
) == sizeof (unsigned char))
1191 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1192 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
1194 /* What size of glyph ARE you using? And does X have a function to
1200 /* Output some text at the nominal frame cursor position.
1201 Advance the cursor over the text.
1202 Output LEN glyphs at START.
1204 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
1205 controls the pixel values used for foreground and background. */
1208 XTwrite_glyphs (start
, len
)
1209 register GLYPH
*start
;
1212 register int temp_length
;
1223 /* If not within an update,
1224 output at the frame's visible cursor. */
1225 curs_x
= FRAME_CURSOR_X (f
);
1226 curs_y
= FRAME_CURSOR_Y (f
);
1230 CHAR_TO_PIXEL_COL (f
, curs_x
),
1231 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1232 start
, len
, highlight
, 0, NULL
);
1234 /* If we drew on top of the cursor, note that it is turned off. */
1235 if (curs_y
== f
->phys_cursor_y
1236 && curs_x
<= f
->phys_cursor_x
1237 && curs_x
+ len
> f
->phys_cursor_x
)
1238 f
->phys_cursor_on
= 0;
1241 if (curs_x
>= FRAME_CURSOR_X_LIMIT (f
))
1242 curs_x
= FRAME_CURSOR_X_LIMIT (f
) - 1;
1244 if (updating_frame
== 0)
1245 x_display_cursor (f
, 1, curs_x
, FRAME_CURSOR_Y (f
));
1251 /* Clear to the end of the line.
1252 Erase the current text line from the nominal cursor position (inclusive)
1253 to column FIRST_UNUSED (exclusive). The idea is that everything
1254 from FIRST_UNUSED onward is already erased. */
1257 XTclear_end_of_line (first_unused
)
1258 register int first_unused
;
1260 struct frame
*f
= updating_frame
;
1266 if (curs_y
< 0 || curs_y
>= f
->height
)
1268 if (first_unused
<= 0)
1271 if (first_unused
>= FRAME_WINDOW_WIDTH (f
))
1272 first_unused
= FRAME_WINDOW_WIDTH (f
);
1274 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1280 /* Notice if the cursor will be cleared by this operation. */
1281 if (curs_y
== f
->phys_cursor_y
1282 && curs_x
<= f
->phys_cursor_x
1283 && f
->phys_cursor_x
< first_unused
)
1284 f
->phys_cursor_on
= 0;
1286 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1287 CHAR_TO_PIXEL_COL (f
, curs_x
),
1288 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1289 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
1290 f
->output_data
.x
->line_height
, False
);
1292 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
1302 struct frame
*f
= updating_frame
;
1307 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1308 curs_x
= 0; /* Nominal cursor position is top left. */
1313 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
1315 /* We have to clear the scroll bars, too. If we have changed
1316 colors or something like that, then they should be notified. */
1317 x_scroll_bar_clear (f
);
1319 XFlush (FRAME_X_DISPLAY (f
));
1324 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
1325 always contain the right glyphs to use.
1327 It also needs to be changed to look at the details of the font and
1328 see whether there is really overlap, and do nothing when there is
1329 not. This can use font_char_overlap_left and font_char_overlap_right,
1330 but just how to use them is not clear. */
1332 /* Erase the character (if any) at the position just before X, Y in frame F,
1333 then redraw it and the character before it.
1334 This is necessary when we erase starting at X,
1335 in case the character after X overlaps into the one before X.
1336 Call this function with input blocked. */
1339 redraw_previous_char (f
, x
, y
, highlight_flag
)
1344 /* Erase the character before the new ones, in case
1345 what was here before overlaps it.
1346 Reoutput that character, and the previous character
1347 (in case the previous character overlaps it). */
1350 int start_x
= x
- 2;
1353 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1354 CHAR_TO_PIXEL_COL (f
, x
- 1),
1355 CHAR_TO_PIXEL_ROW (f
, y
),
1356 FONT_WIDTH (f
->output_data
.x
->font
),
1357 f
->output_data
.x
->line_height
, False
);
1359 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
1360 CHAR_TO_PIXEL_ROW (f
, y
),
1361 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
1362 x
- start_x
, highlight_flag
, 1, NULL
);
1366 /* Erase the character (if any) at the position X, Y in frame F,
1367 then redraw it and the character after it.
1368 This is necessary when we erase endng at X,
1369 in case the character after X overlaps into the one before X.
1370 Call this function with input blocked. */
1373 redraw_following_char (f
, x
, y
, highlight_flag
)
1378 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
1379 /* Erase the character after the new ones, in case
1380 what was here before overlaps it.
1381 Reoutput that character, and the following character
1382 (in case the following character overlaps it). */
1384 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1389 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1390 CHAR_TO_PIXEL_COL (f
, x
),
1391 CHAR_TO_PIXEL_ROW (f
, y
),
1392 FONT_WIDTH (f
->output_data
.x
->font
),
1393 f
->output_data
.x
->line_height
, False
);
1395 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1396 CHAR_TO_PIXEL_ROW (f
, y
),
1397 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1398 end_x
- x
, highlight_flag
, 1, NULL
);
1403 #if 0 /* Not in use yet */
1405 /* Return 1 if character C in font F extends past its left edge. */
1408 font_char_overlap_left (font
, c
)
1414 /* Find the bounding-box info for C. */
1415 if (font
->per_char
== 0)
1416 s
= &font
->max_bounds
;
1419 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1422 /* Decode char into row number (byte 1) and code within row (byte 2). */
1425 if (!(within
>= font
->min_char_or_byte2
1426 && within
<= font
->max_char_or_byte2
1427 && row
>= font
->min_byte1
1428 && row
<= font
->max_byte1
))
1430 /* If char is out of range, try the font's default char instead. */
1431 c
= font
->default_char
;
1432 row
= c
>> (BITS_PER_INT
- 8);
1435 if (!(within
>= font
->min_char_or_byte2
1436 && within
<= font
->max_char_or_byte2
1437 && row
>= font
->min_byte1
1438 && row
<= font
->max_byte1
))
1439 /* Still out of range means this char does not overlap. */
1442 /* We found the info for this char. */
1443 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1447 return (s
&& s
->lbearing
< 0);
1450 /* Return 1 if character C in font F extends past its right edge. */
1453 font_char_overlap_right (font
, c
)
1459 /* Find the bounding-box info for C. */
1460 if (font
->per_char
== 0)
1461 s
= &font
->max_bounds
;
1464 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1467 /* Decode char into row number (byte 1) and code within row (byte 2). */
1470 if (!(within
>= font
->min_char_or_byte2
1471 && within
<= font
->max_char_or_byte2
1472 && row
>= font
->min_byte1
1473 && row
<= font
->max_byte1
))
1475 /* If char is out of range, try the font's default char instead. */
1476 c
= font
->default_char
;
1477 row
= c
>> (BITS_PER_INT
- 8);
1480 if (!(within
>= font
->min_char_or_byte2
1481 && within
<= font
->max_char_or_byte2
1482 && row
>= font
->min_byte1
1483 && row
<= font
->max_byte1
))
1484 /* Still out of range means this char does not overlap. */
1487 /* We found the info for this char. */
1488 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1492 return (s
&& s
->rbearing
>= s
->width
);
1496 /* Invert the middle quarter of the frame for .15 sec. */
1498 /* We use the select system call to do the waiting, so we have to make sure
1499 it's available. If it isn't, we just won't do visual bells. */
1500 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1502 /* Subtract the `struct timeval' values X and Y,
1503 storing the result in RESULT.
1504 Return 1 if the difference is negative, otherwise 0. */
1507 timeval_subtract (result
, x
, y
)
1508 struct timeval
*result
, x
, y
;
1510 /* Perform the carry for the later subtraction by updating y.
1511 This is safer because on some systems
1512 the tv_sec member is unsigned. */
1513 if (x
.tv_usec
< y
.tv_usec
)
1515 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1516 y
.tv_usec
-= 1000000 * nsec
;
1519 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1521 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1522 y
.tv_usec
+= 1000000 * nsec
;
1526 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1527 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1528 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1530 /* Return indication of whether the result should be considered negative. */
1531 return x
.tv_sec
< y
.tv_sec
;
1543 /* Create a GC that will use the GXxor function to flip foreground pixels
1544 into background pixels. */
1548 values
.function
= GXxor
;
1549 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1550 ^ f
->output_data
.x
->background_pixel
);
1552 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1553 GCFunction
| GCForeground
, &values
);
1557 /* Get the height not including a menu bar widget. */
1558 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
1559 /* Height of each line to flash. */
1560 int flash_height
= FRAME_LINE_HEIGHT (f
);
1561 /* These will be the left and right margins of the rectangles. */
1562 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1563 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
1567 /* Don't flash the area between a scroll bar and the frame
1568 edge it is next to. */
1569 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
1571 case vertical_scroll_bar_left
:
1572 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1575 case vertical_scroll_bar_right
:
1576 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1580 width
= flash_right
- flash_left
;
1582 /* If window is tall, flash top and bottom line. */
1583 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1585 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1586 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1587 width
, flash_height
);
1588 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1590 (height
- flash_height
1591 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1592 width
, flash_height
);
1595 /* If it is short, flash it all. */
1596 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1597 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1598 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1600 XFlush (FRAME_X_DISPLAY (f
));
1603 struct timeval wakeup
, now
;
1605 EMACS_GET_TIME (wakeup
);
1607 /* Compute time to wait until, propagating carry from usecs. */
1608 wakeup
.tv_usec
+= 150000;
1609 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1610 wakeup
.tv_usec
%= 1000000;
1612 /* Keep waiting until past the time wakeup. */
1615 struct timeval timeout
;
1617 EMACS_GET_TIME (timeout
);
1619 /* In effect, timeout = wakeup - timeout.
1620 Break if result would be negative. */
1621 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1624 /* Try to wait that long--but we might wake up sooner. */
1625 select (0, NULL
, NULL
, NULL
, &timeout
);
1629 /* If window is tall, flash top and bottom line. */
1630 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1632 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1633 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1634 width
, flash_height
);
1635 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1637 (height
- flash_height
1638 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1639 width
, flash_height
);
1642 /* If it is short, flash it all. */
1643 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1644 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1645 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1647 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1648 XFlush (FRAME_X_DISPLAY (f
));
1658 /* Make audible bell. */
1660 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1665 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1668 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1670 XTflash (selected_frame
);
1676 XFlush (FRAME_X_DISPLAY (selected_frame
));
1681 /* Insert and delete character.
1682 These are not supposed to be used because we are supposed to turn
1683 off the feature of using them. */
1686 XTinsert_glyphs (start
, len
)
1687 register char *start
;
1700 /* Specify how many text lines, from the top of the window,
1701 should be affected by insert-lines and delete-lines operations.
1702 This, and those operations, are used only within an update
1703 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1706 XTset_terminal_window (n
)
1709 if (updating_frame
== 0)
1712 if ((n
<= 0) || (n
> updating_frame
->height
))
1713 flexlines
= updating_frame
->height
;
1718 /* These variables need not be per frame
1719 because redisplay is done on a frame-by-frame basis
1720 and the line dance for one frame is finished before
1721 anything is done for anoter frame. */
1723 /* Array of line numbers from cached insert/delete operations.
1724 line_dance[i] is the old position of the line that we want
1725 to move to line i, or -1 if we want a blank line there. */
1726 static int *line_dance
;
1728 /* Allocated length of that array. */
1729 static int line_dance_len
;
1731 /* Flag indicating whether we've done any work. */
1732 static int line_dance_in_progress
;
1734 /* Perform an insert-lines or delete-lines operation,
1735 inserting N lines or deleting -N lines at vertical position VPOS. */
1737 XTins_del_lines (vpos
, n
)
1740 register int fence
, i
;
1742 if (vpos
>= flexlines
)
1745 if (!line_dance_in_progress
)
1747 int ht
= updating_frame
->height
;
1748 if (ht
> line_dance_len
)
1750 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1751 line_dance_len
= ht
;
1753 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1754 line_dance_in_progress
= 1;
1758 if (n
> flexlines
- vpos
)
1759 n
= flexlines
- vpos
;
1761 for (i
= flexlines
; --i
>= fence
;)
1762 line_dance
[i
] = line_dance
[i
-n
];
1763 for (i
= fence
; --i
>= vpos
;)
1769 if (n
> flexlines
- vpos
)
1770 n
= flexlines
- vpos
;
1771 fence
= flexlines
- n
;
1772 for (i
= vpos
; i
< fence
; ++i
)
1773 line_dance
[i
] = line_dance
[i
+ n
];
1774 for (i
= fence
; i
< flexlines
; ++i
)
1779 /* Here's where we actually move the pixels around.
1780 Must be called with input blocked. */
1784 register int i
, j
, distance
;
1785 register struct frame
*f
;
1789 /* Must check this flag first. If it's not set, then not only is the
1790 array uninitialized, but we might not even have a frame. */
1791 if (!line_dance_in_progress
)
1799 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1801 x_update_cursor (updating_frame
, 0);
1803 for (i
= 0; i
< ht
; ++i
)
1804 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1806 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1807 && line_dance
[j
]-j
== distance
); ++j
);
1808 /* Copy [i,j) upward from [i+distance,j+distance) */
1809 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1810 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1811 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1812 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1813 (j
-i
) * f
->output_data
.x
->line_height
,
1814 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1818 for (i
= ht
; --i
>=0; )
1819 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1821 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1822 && line_dance
[j
]-j
== distance
););
1823 /* Copy (j,i] downward from (j+distance, i+distance] */
1824 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1825 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1826 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1827 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1828 (i
-j
) * f
->output_data
.x
->line_height
,
1829 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1833 for (i
= 0; i
< ht
; ++i
)
1834 if (line_dance
[i
] == -1)
1836 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1838 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1839 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1840 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1841 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1844 line_dance_in_progress
= 0;
1847 /* Support routines for exposure events. */
1848 static void clear_cursor ();
1850 /* Output into a rectangle of an X-window (for frame F)
1851 the characters in f->phys_lines that overlap that rectangle.
1852 TOP and LEFT are the position of the upper left corner of the rectangle.
1853 ROWS and COLS are the size of the rectangle.
1854 Call this function with input blocked. */
1857 dumprectangle (f
, left
, top
, cols
, rows
)
1859 register int left
, top
, cols
, rows
;
1861 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1862 int cursor_cleared
= 0;
1866 if (FRAME_GARBAGED_P (f
))
1869 /* Express rectangle as four edges, instead of position-and-size. */
1870 bottom
= top
+ rows
;
1871 right
= left
+ cols
;
1873 /* Convert rectangle edges in pixels to edges in chars.
1874 Round down for left and top, up for right and bottom. */
1875 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1876 left
= PIXEL_TO_CHAR_COL (f
, left
);
1877 bottom
+= (f
->output_data
.x
->line_height
- 1);
1878 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1879 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1880 right
= PIXEL_TO_CHAR_COL (f
, right
);
1882 /* Clip the rectangle to what can be visible. */
1887 if (right
> FRAME_WINDOW_WIDTH (f
))
1888 right
= FRAME_WINDOW_WIDTH (f
);
1889 if (bottom
> f
->height
)
1892 /* Get size in chars of the rectangle. */
1893 cols
= right
- left
;
1894 rows
= bottom
- top
;
1896 /* If rectangle has zero area, return. */
1897 if (rows
<= 0) return;
1898 if (cols
<= 0) return;
1900 /* Turn off the cursor if it is in the rectangle.
1901 We will turn it back on afterward. */
1902 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1903 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1909 /* Display the text in the rectangle, one text line at a time. */
1911 for (y
= top
; y
< bottom
; y
++)
1913 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1915 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1918 while (*line
& GLYPH_MASK_PADDING
)
1920 /* We must display the whole glyph of a wide-column
1927 CHAR_TO_PIXEL_COL (f
, left
),
1928 CHAR_TO_PIXEL_ROW (f
, y
),
1929 line
, min (cols
, active_frame
->used
[y
] - left
),
1930 active_frame
->highlight
[y
], 0, NULL
);
1933 /* Turn the cursor on if we turned it off. */
1936 x_update_cursor (f
, 1);
1943 /* We used to only do this if Vx_no_window_manager was non-nil, but
1944 the ICCCM (section 4.1.6) says that the window's border pixmap
1945 and border pixel are window attributes which are "private to the
1946 client", so we can always change it to whatever we want. */
1948 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1949 f
->output_data
.x
->border_pixel
);
1951 x_update_cursor (f
, 1);
1955 frame_unhighlight (f
)
1958 /* We used to only do this if Vx_no_window_manager was non-nil, but
1959 the ICCCM (section 4.1.6) says that the window's border pixmap
1960 and border pixel are window attributes which are "private to the
1961 client", so we can always change it to whatever we want. */
1963 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1964 f
->output_data
.x
->border_tile
);
1966 x_update_cursor (f
, 1);
1969 static void XTframe_rehighlight ();
1970 static void x_frame_rehighlight ();
1972 /* The focus has changed. Update the frames as necessary to reflect
1973 the new situation. Note that we can't change the selected frame
1974 here, because the Lisp code we are interrupting might become confused.
1975 Each event gets marked with the frame in which it occurred, so the
1976 Lisp code can tell when the switch took place by examining the events. */
1979 x_new_focus_frame (dpyinfo
, frame
)
1980 struct x_display_info
*dpyinfo
;
1981 struct frame
*frame
;
1983 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1984 int events_enqueued
= 0;
1986 if (frame
!= dpyinfo
->x_focus_frame
)
1988 /* Set this before calling other routines, so that they see
1989 the correct value of x_focus_frame. */
1990 dpyinfo
->x_focus_frame
= frame
;
1992 if (old_focus
&& old_focus
->auto_lower
)
1993 x_lower_frame (old_focus
);
1996 selected_frame
= frame
;
1997 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1999 Fselect_window (selected_frame
->selected_window
);
2000 choose_minibuf_frame ();
2003 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
2004 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
2006 pending_autoraise_frame
= 0;
2009 x_frame_rehighlight (dpyinfo
);
2012 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2015 x_mouse_leave (dpyinfo
)
2016 struct x_display_info
*dpyinfo
;
2018 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
2021 /* The focus has changed, or we have redirected a frame's focus to
2022 another frame (this happens when a frame uses a surrogate
2023 minibuffer frame). Shift the highlight as appropriate.
2025 The FRAME argument doesn't necessarily have anything to do with which
2026 frame is being highlighted or unhighlighted; we only use it to find
2027 the appropriate X display info. */
2029 XTframe_rehighlight (frame
)
2030 struct frame
*frame
;
2032 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
2036 x_frame_rehighlight (dpyinfo
)
2037 struct x_display_info
*dpyinfo
;
2039 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
2041 if (dpyinfo
->x_focus_frame
)
2043 dpyinfo
->x_highlight_frame
2044 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
2045 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
2046 : dpyinfo
->x_focus_frame
);
2047 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
2049 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
2050 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
2054 dpyinfo
->x_highlight_frame
= 0;
2056 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
2059 frame_unhighlight (old_highlight
);
2060 if (dpyinfo
->x_highlight_frame
)
2061 frame_highlight (dpyinfo
->x_highlight_frame
);
2065 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
2067 /* Initialize mode_switch_bit and modifier_meaning. */
2069 x_find_modifier_meanings (dpyinfo
)
2070 struct x_display_info
*dpyinfo
;
2072 int min_code
, max_code
;
2075 XModifierKeymap
*mods
;
2077 dpyinfo
->meta_mod_mask
= 0;
2078 dpyinfo
->shift_lock_mask
= 0;
2079 dpyinfo
->alt_mod_mask
= 0;
2080 dpyinfo
->super_mod_mask
= 0;
2081 dpyinfo
->hyper_mod_mask
= 0;
2084 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
2086 min_code
= dpyinfo
->display
->min_keycode
;
2087 max_code
= dpyinfo
->display
->max_keycode
;
2090 syms
= XGetKeyboardMapping (dpyinfo
->display
,
2091 min_code
, max_code
- min_code
+ 1,
2093 mods
= XGetModifierMapping (dpyinfo
->display
);
2095 /* Scan the modifier table to see which modifier bits the Meta and
2096 Alt keysyms are on. */
2098 int row
, col
; /* The row and column in the modifier table. */
2100 for (row
= 3; row
< 8; row
++)
2101 for (col
= 0; col
< mods
->max_keypermod
; col
++)
2104 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
2106 /* Zeroes are used for filler. Skip them. */
2110 /* Are any of this keycode's keysyms a meta key? */
2114 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
2116 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
2122 dpyinfo
->meta_mod_mask
|= (1 << row
);
2127 dpyinfo
->alt_mod_mask
|= (1 << row
);
2132 dpyinfo
->hyper_mod_mask
|= (1 << row
);
2137 dpyinfo
->super_mod_mask
|= (1 << row
);
2141 /* Ignore this if it's not on the lock modifier. */
2142 if ((1 << row
) == LockMask
)
2143 dpyinfo
->shift_lock_mask
= LockMask
;
2151 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
2152 if (! dpyinfo
->meta_mod_mask
)
2154 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
2155 dpyinfo
->alt_mod_mask
= 0;
2158 /* If some keys are both alt and meta,
2159 make them just meta, not alt. */
2160 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
2162 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
2165 XFree ((char *) syms
);
2166 XFreeModifiermap (mods
);
2169 /* Convert between the modifier bits X uses and the modifier bits
2172 x_x_to_emacs_modifiers (dpyinfo
, state
)
2173 struct x_display_info
*dpyinfo
;
2176 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
2177 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
2178 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
2179 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
2180 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
2181 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
2185 x_emacs_to_x_modifiers (dpyinfo
, state
)
2186 struct x_display_info
*dpyinfo
;
2189 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
2190 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
2191 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
2192 | ((state
& shift_modifier
) ? ShiftMask
: 0)
2193 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
2194 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
2197 /* Convert a keysym to its name. */
2200 x_get_keysym_name (keysym
)
2206 value
= XKeysymToString (keysym
);
2212 /* Mouse clicks and mouse movement. Rah. */
2214 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
2215 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
2216 that the glyph at X, Y occupies, if BOUNDS != 0.
2217 If NOCLIP is nonzero, do not force the value into range. */
2220 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2222 register int pix_x
, pix_y
;
2223 register int *x
, *y
;
2227 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
2228 even for negative values. */
2230 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
2232 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
2234 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
2235 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
2239 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
2240 bounds
->height
= f
->output_data
.x
->line_height
;
2241 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
2242 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
2249 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
2250 pix_x
= FRAME_WINDOW_WIDTH (f
);
2254 else if (pix_y
> f
->height
)
2263 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2266 register int *pix_x
, *pix_y
;
2268 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
2269 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
2272 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2274 If the event is a button press, then note that we have grabbed
2278 construct_mouse_click (result
, event
, f
)
2279 struct input_event
*result
;
2280 XButtonEvent
*event
;
2283 /* Make the event type no_event; we'll change that when we decide
2285 result
->kind
= mouse_click
;
2286 result
->code
= event
->button
- Button1
;
2287 result
->timestamp
= event
->time
;
2288 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2290 | (event
->type
== ButtonRelease
2298 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2299 XSETFASTINT (result
->x
, column
);
2300 XSETFASTINT (result
->y
, row
);
2302 XSETINT (result
->x
, event
->x
);
2303 XSETINT (result
->y
, event
->y
);
2304 XSETFRAME (result
->frame_or_window
, f
);
2308 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2311 construct_menu_click (result
, event
, f
)
2312 struct input_event
*result
;
2313 XButtonEvent
*event
;
2316 /* Make the event type no_event; we'll change that when we decide
2318 result
->kind
= mouse_click
;
2319 result
->code
= event
->button
- Button1
;
2320 result
->timestamp
= event
->time
;
2321 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2323 | (event
->type
== ButtonRelease
2327 XSETINT (result
->x
, event
->x
);
2328 XSETINT (result
->y
, -1);
2329 XSETFRAME (result
->frame_or_window
, f
);
2332 /* Function to report a mouse movement to the mainstream Emacs code.
2333 The input handler calls this.
2335 We have received a mouse movement event, which is given in *event.
2336 If the mouse is over a different glyph than it was last time, tell
2337 the mainstream emacs code by setting mouse_moved. If not, ask for
2338 another motion event, so we can check again the next time it moves. */
2341 note_mouse_movement (frame
, event
)
2343 XMotionEvent
*event
;
2345 last_mouse_movement_time
= event
->time
;
2347 if (event
->window
!= FRAME_X_WINDOW (frame
))
2349 frame
->mouse_moved
= 1;
2350 last_mouse_scroll_bar
= Qnil
;
2352 note_mouse_highlight (frame
, -1, -1);
2355 /* Has the mouse moved off the glyph it was on at the last sighting? */
2356 else if (event
->x
< last_mouse_glyph
.x
2357 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2358 || event
->y
< last_mouse_glyph
.y
2359 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2361 frame
->mouse_moved
= 1;
2362 last_mouse_scroll_bar
= Qnil
;
2364 note_mouse_highlight (frame
, event
->x
, event
->y
);
2368 /* This is used for debugging, to turn off note_mouse_highlight. */
2369 static int disable_mouse_highlight
;
2371 /* Take proper action when the mouse has moved to position X, Y on frame F
2372 as regards highlighting characters that have mouse-face properties.
2373 Also dehighlighting chars where the mouse was before.
2374 X and Y can be negative or out of range. */
2377 note_mouse_highlight (f
, x
, y
)
2381 int row
, column
, portion
;
2382 XRectangle new_glyph
;
2386 if (disable_mouse_highlight
)
2389 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2390 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2391 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2393 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
2398 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2402 /* Find out which glyph the mouse is on. */
2403 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2404 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
2406 /* Which window is that in? */
2407 window
= window_from_coordinates (f
, column
, row
, &portion
);
2408 w
= XWINDOW (window
);
2410 /* If we were displaying active text in another window, clear that. */
2411 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
2412 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2414 /* Are we in a window whose display is up to date?
2415 And verify the buffer's text has not changed. */
2416 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2417 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2418 && EQ (w
->window_end_valid
, w
->buffer
)
2419 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
2420 && (XFASTINT (w
->last_overlay_modified
)
2421 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
2423 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2426 /* Find which buffer position the mouse corresponds to. */
2427 for (i
= column
; i
>= 0; i
--)
2431 /* Is it outside the displayed active region (if any)? */
2433 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2434 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
2435 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2436 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2437 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2438 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2439 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2440 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2441 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2443 Lisp_Object mouse_face
, overlay
, position
;
2444 Lisp_Object
*overlay_vec
;
2445 int len
, noverlays
, ignor1
;
2446 struct buffer
*obuf
;
2449 /* If we get an out-of-range value, return now; avoid an error. */
2450 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2453 /* Make the window's buffer temporarily current for
2454 overlays_at and compute_char_face. */
2455 obuf
= current_buffer
;
2456 current_buffer
= XBUFFER (w
->buffer
);
2462 /* Yes. Clear the display of the old active region, if any. */
2463 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2465 /* Is this char mouse-active? */
2466 XSETINT (position
, pos
);
2469 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2471 /* Put all the overlays we want in a vector in overlay_vec.
2472 Store the length in len. */
2473 noverlays
= overlays_at (pos
, 1, &overlay_vec
, &len
,
2475 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2477 /* Find the highest priority overlay that has a mouse-face prop. */
2479 for (i
= 0; i
< noverlays
; i
++)
2481 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2482 if (!NILP (mouse_face
))
2484 overlay
= overlay_vec
[i
];
2489 /* If no overlay applies, get a text property. */
2491 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2493 /* Handle the overlay case. */
2494 if (! NILP (overlay
))
2496 /* Find the range of text around this char that
2497 should be active. */
2498 Lisp_Object before
, after
;
2501 before
= Foverlay_start (overlay
);
2502 after
= Foverlay_end (overlay
);
2503 /* Record this as the current active region. */
2504 fast_find_position (window
, XFASTINT (before
),
2505 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2506 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2507 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2508 = !fast_find_position (window
, XFASTINT (after
),
2509 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2510 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2511 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2512 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2513 = compute_char_face (f
, w
, pos
, 0, 0,
2514 &ignore
, pos
+ 1, 1);
2516 /* Display it as active. */
2517 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2519 /* Handle the text property case. */
2520 else if (! NILP (mouse_face
))
2522 /* Find the range of text around this char that
2523 should be active. */
2524 Lisp_Object before
, after
, beginning
, end
;
2527 beginning
= Fmarker_position (w
->start
);
2528 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2529 - XFASTINT (w
->window_end_pos
)));
2531 = Fprevious_single_property_change (make_number (pos
+ 1),
2533 w
->buffer
, beginning
);
2535 = Fnext_single_property_change (position
, Qmouse_face
,
2537 /* Record this as the current active region. */
2538 fast_find_position (window
, XFASTINT (before
),
2539 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2540 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2541 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2542 = !fast_find_position (window
, XFASTINT (after
),
2543 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2544 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2545 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2546 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2547 = compute_char_face (f
, w
, pos
, 0, 0,
2548 &ignore
, pos
+ 1, 1);
2550 /* Display it as active. */
2551 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2555 current_buffer
= obuf
;
2560 /* Find the row and column of position POS in window WINDOW.
2561 Store them in *COLUMNP and *ROWP.
2562 This assumes display in WINDOW is up to date.
2563 If POS is above start of WINDOW, return coords
2564 of start of first screen line.
2565 If POS is after end of WINDOW, return coords of end of last screen line.
2567 Value is 1 if POS is in range, 0 if it was off screen. */
2570 fast_find_position (window
, pos
, columnp
, rowp
)
2573 int *columnp
, *rowp
;
2575 struct window
*w
= XWINDOW (window
);
2576 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2579 int left
= WINDOW_LEFT_MARGIN (w
);
2580 int top
= XFASTINT (w
->top
);
2581 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2582 int width
= window_internal_width (w
);
2585 int maybe_next_line
= 0;
2587 /* Find the right row. */
2592 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2593 if (linestart
> pos
)
2595 /* If the position sought is the end of the buffer,
2596 don't include the blank lines at the bottom of the window. */
2597 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2599 maybe_next_line
= 1;
2606 /* Find the right column with in it. */
2607 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2609 for (i
= 0; i
< width
; i
++)
2611 if (charstarts
[left
+ i
] == pos
)
2614 *columnp
= i
+ left
;
2617 else if (charstarts
[left
+ i
] > pos
)
2619 else if (charstarts
[left
+ i
] > 0)
2620 lastcol
= left
+ i
+ 1;
2623 /* If we're looking for the end of the buffer,
2624 and we didn't find it in the line we scanned,
2625 use the start of the following line. */
2626 if (maybe_next_line
)
2637 /* Display the active region described by mouse_face_*
2638 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2641 show_mouse_face (dpyinfo
, hl
)
2642 struct x_display_info
*dpyinfo
;
2645 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2646 int width
= window_internal_width (w
);
2647 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2650 int old_curs_x
= curs_x
;
2651 int old_curs_y
= curs_y
;
2653 /* Set these variables temporarily
2654 so that if we have to turn the cursor off and on again
2655 we will put it back at the same place. */
2656 curs_x
= f
->phys_cursor_x
;
2657 curs_y
= f
->phys_cursor_y
;
2658 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2659 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2661 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2662 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2663 : WINDOW_LEFT_MARGIN (w
));
2664 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2665 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2666 : WINDOW_LEFT_MARGIN (w
) + width
);
2667 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2669 /* If the cursor's in the text we are about to rewrite,
2670 turn the cursor off. */
2672 && curs_x
>= column
- 1
2673 && curs_x
<= endcolumn
)
2675 x_update_cursor (f
, 0);
2680 CHAR_TO_PIXEL_COL (f
, column
),
2681 CHAR_TO_PIXEL_ROW (f
, i
),
2682 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2684 /* Highlight with mouse face if hl > 0. */
2685 hl
> 0 ? 3 : 0, 0, NULL
);
2688 /* If we turned the cursor off, turn it back on. */
2690 x_display_cursor (f
, 1, curs_x
, curs_y
);
2692 curs_x
= old_curs_x
;
2693 curs_y
= old_curs_y
;
2695 /* Change the mouse cursor according to the value of HL. */
2697 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2698 f
->output_data
.x
->cross_cursor
);
2700 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2701 f
->output_data
.x
->text_cursor
);
2704 /* Clear out the mouse-highlighted active region.
2705 Redraw it unhighlighted first. */
2708 clear_mouse_face (dpyinfo
)
2709 struct x_display_info
*dpyinfo
;
2711 if (! NILP (dpyinfo
->mouse_face_window
))
2712 show_mouse_face (dpyinfo
, 0);
2714 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2715 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2716 dpyinfo
->mouse_face_window
= Qnil
;
2719 /* Just discard the mouse face information for frame F, if any.
2720 This is used when the size of F is changed. */
2723 cancel_mouse_face (f
)
2727 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2729 window
= dpyinfo
->mouse_face_window
;
2730 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2732 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2733 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2734 dpyinfo
->mouse_face_window
= Qnil
;
2738 static struct scroll_bar
*x_window_to_scroll_bar ();
2739 static void x_scroll_bar_report_motion ();
2741 /* Return the current position of the mouse.
2742 *fp should be a frame which indicates which display to ask about.
2744 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2745 and *part to the frame, window, and scroll bar part that the mouse
2746 is over. Set *x and *y to the portion and whole of the mouse's
2747 position on the scroll bar.
2749 If the mouse movement started elsewhere, set *fp to the frame the
2750 mouse is on, *bar_window to nil, and *x and *y to the character cell
2753 Set *time to the server timestamp for the time at which the mouse
2754 was at this position.
2756 Don't store anything if we don't have a valid set of values to report.
2758 This clears the mouse_moved flag, so we can wait for the next mouse
2762 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2765 Lisp_Object
*bar_window
;
2766 enum scroll_bar_part
*part
;
2768 unsigned long *time
;
2774 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2775 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2781 Window dummy_window
;
2784 Lisp_Object frame
, tail
;
2786 /* Clear the mouse-moved flag for every frame on this display. */
2787 FOR_EACH_FRAME (tail
, frame
)
2788 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2789 XFRAME (frame
)->mouse_moved
= 0;
2791 last_mouse_scroll_bar
= Qnil
;
2793 /* Figure out which root window we're on. */
2794 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2795 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2797 /* The root window which contains the pointer. */
2800 /* Trash which we can't trust if the pointer is on
2801 a different screen. */
2804 /* The position on that root window. */
2807 /* More trash we can't trust. */
2810 /* Modifier keys and pointer buttons, about which
2812 (unsigned int *) &dummy
);
2814 /* Now we have a position on the root; find the innermost window
2815 containing the pointer. */
2819 int parent_x
, parent_y
;
2824 /* XTranslateCoordinates can get errors if the window
2825 structure is changing at the same time this function
2826 is running. So at least we must not crash from them. */
2828 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
2830 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2831 && FRAME_LIVE_P (last_mouse_frame
))
2833 /* If mouse was grabbed on a frame, give coords for that frame
2834 even if the mouse is now outside it. */
2835 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2837 /* From-window, to-window. */
2838 root
, FRAME_X_WINDOW (last_mouse_frame
),
2840 /* From-position, to-position. */
2841 root_x
, root_y
, &win_x
, &win_y
,
2845 f1
= last_mouse_frame
;
2851 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2853 /* From-window, to-window. */
2856 /* From-position, to-position. */
2857 root_x
, root_y
, &win_x
, &win_y
,
2862 if (child
== None
|| child
== win
)
2870 /* Now we know that:
2871 win is the innermost window containing the pointer
2872 (XTC says it has no child containing the pointer),
2873 win_x and win_y are the pointer's position in it
2874 (XTC did this the last time through), and
2875 parent_x and parent_y are the pointer's position in win's parent.
2876 (They are what win_x and win_y were when win was child.
2877 If win is the root window, it has no parent, and
2878 parent_{x,y} are invalid, but that's okay, because we'll
2879 never use them in that case.) */
2881 /* Is win one of our frames? */
2882 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2885 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2888 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
2890 /* If not, is it one of our scroll bars? */
2893 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2897 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2903 if (f1
== 0 && insist
> 0)
2904 f1
= selected_frame
;
2908 int ignore1
, ignore2
;
2910 /* Ok, we found a frame. Store all the values. */
2912 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2914 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2920 XSETINT (*x
, win_x
);
2921 XSETINT (*y
, win_y
);
2922 *time
= last_mouse_movement_time
;
2930 /* Scroll bar support. */
2932 /* Given an X window ID, find the struct scroll_bar which manages it.
2933 This can be called in GC, so we have to make sure to strip off mark
2935 static struct scroll_bar
*
2936 x_window_to_scroll_bar (window_id
)
2939 Lisp_Object tail
, frame
;
2941 for (tail
= Vframe_list
;
2942 XGCTYPE (tail
) == Lisp_Cons
;
2943 tail
= XCONS (tail
)->cdr
)
2945 Lisp_Object frame
, bar
, condemned
;
2947 frame
= XCONS (tail
)->car
;
2948 /* All elements of Vframe_list should be frames. */
2949 if (! GC_FRAMEP (frame
))
2952 /* Scan this frame's scroll bar list for a scroll bar with the
2954 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2955 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2956 /* This trick allows us to search both the ordinary and
2957 condemned scroll bar lists with one loop. */
2958 ! GC_NILP (bar
) || (bar
= condemned
,
2961 bar
= XSCROLL_BAR (bar
)->next
)
2962 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2963 return XSCROLL_BAR (bar
);
2969 /* Open a new X window to serve as a scroll bar, and return the
2970 scroll bar vector for it. */
2971 static struct scroll_bar
*
2972 x_scroll_bar_create (window
, top
, left
, width
, height
)
2973 struct window
*window
;
2974 int top
, left
, width
, height
;
2976 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2977 struct scroll_bar
*bar
2978 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2983 XSetWindowAttributes a
;
2985 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2986 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2987 | ButtonMotionMask
| PointerMotionHintMask
2989 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2991 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2996 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2997 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2998 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2999 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
3000 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
3001 sb_widget
= XtCreateManagedWidget ("box",
3003 f
->output_data
.x
->edit_widget
, al
, ac
);
3004 SET_SCROLL_BAR_X_WINDOW
3005 (bar
, sb_widget
->core
.window
);
3007 SET_SCROLL_BAR_X_WINDOW
3009 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3011 /* Position and size of scroll bar. */
3012 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, top
,
3013 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2, height
,
3015 /* Border width, depth, class, and visual. */
3016 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
3022 XSETWINDOW (bar
->window
, window
);
3023 XSETINT (bar
->top
, top
);
3024 XSETINT (bar
->left
, left
);
3025 XSETINT (bar
->width
, width
);
3026 XSETINT (bar
->height
, height
);
3027 XSETINT (bar
->start
, 0);
3028 XSETINT (bar
->end
, 0);
3029 bar
->dragging
= Qnil
;
3031 /* Add bar to its frame's list of scroll bars. */
3032 bar
->next
= FRAME_SCROLL_BARS (f
);
3034 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3035 if (! NILP (bar
->next
))
3036 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3038 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3045 /* Draw BAR's handle in the proper position.
3046 If the handle is already drawn from START to END, don't bother
3047 redrawing it, unless REBUILD is non-zero; in that case, always
3048 redraw it. (REBUILD is handy for drawing the handle after expose
3051 Normally, we want to constrain the start and end of the handle to
3052 fit inside its rectangle, but if the user is dragging the scroll bar
3053 handle, we want to let them drag it down all the way, so that the
3054 bar's top is as far down as it goes; otherwise, there's no way to
3055 move to the very end of the buffer. */
3057 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
3058 struct scroll_bar
*bar
;
3062 int dragging
= ! NILP (bar
->dragging
);
3063 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3064 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3065 GC gc
= f
->output_data
.x
->normal_gc
;
3067 /* If the display is already accurate, do nothing. */
3069 && start
== XINT (bar
->start
)
3070 && end
== XINT (bar
->end
))
3076 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
3077 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3078 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3080 /* Make sure the values are reasonable, and try to preserve
3081 the distance between start and end. */
3083 int length
= end
- start
;
3087 else if (start
> top_range
)
3089 end
= start
+ length
;
3093 else if (end
> top_range
&& ! dragging
)
3097 /* Store the adjusted setting in the scroll bar. */
3098 XSETINT (bar
->start
, start
);
3099 XSETINT (bar
->end
, end
);
3101 /* Clip the end position, just for display. */
3102 if (end
> top_range
)
3105 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
3106 below top positions, to make sure the handle is always at least
3107 that many pixels tall. */
3108 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3110 /* Draw the empty space above the handle. Note that we can't clear
3111 zero-height areas; that means "clear to end of window." */
3113 XClearArea (FRAME_X_DISPLAY (f
), w
,
3115 /* x, y, width, height, and exposures. */
3116 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3117 VERTICAL_SCROLL_BAR_TOP_BORDER
,
3118 inside_width
, start
,
3121 /* Draw the handle itself. */
3122 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3124 /* x, y, width, height */
3125 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3126 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
3127 inside_width
, end
- start
);
3130 /* Draw the empty space below the handle. Note that we can't
3131 clear zero-height areas; that means "clear to end of window." */
3132 if (end
< inside_height
)
3133 XClearArea (FRAME_X_DISPLAY (f
), w
,
3135 /* x, y, width, height, and exposures. */
3136 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3137 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
3138 inside_width
, inside_height
- end
,
3146 /* Move a scroll bar around on the screen, to accommodate changing
3147 window configurations. */
3149 x_scroll_bar_move (bar
, top
, left
, width
, height
)
3150 struct scroll_bar
*bar
;
3151 int top
, left
, width
, height
;
3153 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3154 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3160 unsigned int mask
= 0;
3162 wc
.x
= left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3165 wc
.width
= width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
3168 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
3169 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
3170 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
3171 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
3174 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
3178 XSETINT (bar
->left
, left
);
3179 XSETINT (bar
->top
, top
);
3180 XSETINT (bar
->width
, width
);
3181 XSETINT (bar
->height
, height
);
3186 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
3189 x_scroll_bar_remove (bar
)
3190 struct scroll_bar
*bar
;
3192 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3196 /* Destroy the window. */
3197 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3199 /* Disassociate this scroll bar from its window. */
3200 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3205 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3206 that we are displaying PORTION characters out of a total of WHOLE
3207 characters, starting at POSITION. If WINDOW has no scroll bar,
3210 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
3211 struct window
*window
;
3212 int portion
, whole
, position
;
3214 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3215 int top
= XINT (window
->top
);
3216 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
3217 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
3219 /* Where should this scroll bar be, pixelwise? */
3220 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
3221 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
3223 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3224 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3225 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3226 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
3228 struct scroll_bar
*bar
;
3230 /* Does the scroll bar exist yet? */
3231 if (NILP (window
->vertical_scroll_bar
))
3232 bar
= x_scroll_bar_create (window
,
3233 pixel_top
, pixel_left
,
3234 pixel_width
, pixel_height
);
3237 /* It may just need to be moved and resized. */
3238 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3239 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
3242 /* Set the scroll bar's current state, unless we're currently being
3244 if (NILP (bar
->dragging
))
3246 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
3249 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
3252 int start
= ((double) position
* top_range
) / whole
;
3253 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
3255 x_scroll_bar_set_handle (bar
, start
, end
, 0);
3259 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
3263 /* The following three hooks are used when we're doing a thorough
3264 redisplay of the frame. We don't explicitly know which scroll bars
3265 are going to be deleted, because keeping track of when windows go
3266 away is a real pain - "Can you say set-window-configuration, boys
3267 and girls?" Instead, we just assert at the beginning of redisplay
3268 that *all* scroll bars are to be removed, and then save a scroll bar
3269 from the fiery pit when we actually redisplay its window. */
3271 /* Arrange for all scroll bars on FRAME to be removed at the next call
3272 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3273 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
3275 XTcondemn_scroll_bars (frame
)
3278 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3279 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3282 bar
= FRAME_SCROLL_BARS (frame
);
3283 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3284 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3285 XSCROLL_BAR (bar
)->prev
= Qnil
;
3286 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3287 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3288 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3292 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
3293 Note that WINDOW isn't necessarily condemned at all. */
3295 XTredeem_scroll_bar (window
)
3296 struct window
*window
;
3298 struct scroll_bar
*bar
;
3300 /* We can't redeem this window's scroll bar if it doesn't have one. */
3301 if (NILP (window
->vertical_scroll_bar
))
3304 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3306 /* Unlink it from the condemned list. */
3308 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3310 if (NILP (bar
->prev
))
3312 /* If the prev pointer is nil, it must be the first in one of
3314 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3315 /* It's not condemned. Everything's fine. */
3317 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3318 window
->vertical_scroll_bar
))
3319 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3321 /* If its prev pointer is nil, it must be at the front of
3322 one or the other! */
3326 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3328 if (! NILP (bar
->next
))
3329 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3331 bar
->next
= FRAME_SCROLL_BARS (f
);
3333 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3334 if (! NILP (bar
->next
))
3335 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3339 /* Remove all scroll bars on FRAME that haven't been saved since the
3340 last call to `*condemn_scroll_bars_hook'. */
3342 XTjudge_scroll_bars (f
)
3345 Lisp_Object bar
, next
;
3347 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3349 /* Clear out the condemned list now so we won't try to process any
3350 more events on the hapless scroll bars. */
3351 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3353 for (; ! NILP (bar
); bar
= next
)
3355 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3357 x_scroll_bar_remove (b
);
3360 b
->next
= b
->prev
= Qnil
;
3363 /* Now there should be no references to the condemned scroll bars,
3364 and they should get garbage-collected. */
3368 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3370 This may be called from a signal handler, so we have to ignore GC
3373 x_scroll_bar_expose (bar
, event
)
3374 struct scroll_bar
*bar
;
3377 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3378 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3379 GC gc
= f
->output_data
.x
->normal_gc
;
3380 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3384 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3386 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3387 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3389 /* x, y, width, height */
3391 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
3392 XINT (bar
->height
) - 1);
3397 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3398 is set to something other than no_event, it is enqueued.
3400 This may be called from a signal handler, so we have to ignore GC
3403 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3404 struct scroll_bar
*bar
;
3406 struct input_event
*emacs_event
;
3408 if (! GC_WINDOWP (bar
->window
))
3411 emacs_event
->kind
= scroll_bar_click
;
3412 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3413 emacs_event
->modifiers
3414 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
3415 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
3416 event
->xbutton
.state
)
3417 | (event
->type
== ButtonRelease
3420 emacs_event
->frame_or_window
= bar
->window
;
3421 emacs_event
->timestamp
= event
->xbutton
.time
;
3423 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3425 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3427 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3428 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3431 if (y
> top_range
) y
= top_range
;
3433 if (y
< XINT (bar
->start
))
3434 emacs_event
->part
= scroll_bar_above_handle
;
3435 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3436 emacs_event
->part
= scroll_bar_handle
;
3438 emacs_event
->part
= scroll_bar_below_handle
;
3440 /* Just because the user has clicked on the handle doesn't mean
3441 they want to drag it. Lisp code needs to be able to decide
3442 whether or not we're dragging. */
3444 /* If the user has just clicked on the handle, record where they're
3446 if (event
->type
== ButtonPress
3447 && emacs_event
->part
== scroll_bar_handle
)
3448 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
3451 /* If the user has released the handle, set it to its final position. */
3452 if (event
->type
== ButtonRelease
3453 && ! NILP (bar
->dragging
))
3455 int new_start
= y
- XINT (bar
->dragging
);
3456 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3458 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3459 bar
->dragging
= Qnil
;
3462 /* Same deal here as the other #if 0. */
3464 /* Clicks on the handle are always reported as occurring at the top of
3466 if (emacs_event
->part
== scroll_bar_handle
)
3467 emacs_event
->x
= bar
->start
;
3469 XSETINT (emacs_event
->x
, y
);
3471 XSETINT (emacs_event
->x
, y
);
3474 XSETINT (emacs_event
->y
, top_range
);
3478 /* Handle some mouse motion while someone is dragging the scroll bar.
3480 This may be called from a signal handler, so we have to ignore GC
3483 x_scroll_bar_note_movement (bar
, event
)
3484 struct scroll_bar
*bar
;
3487 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
3489 last_mouse_movement_time
= event
->xmotion
.time
;
3492 XSETVECTOR (last_mouse_scroll_bar
, bar
);
3494 /* If we're dragging the bar, display it. */
3495 if (! GC_NILP (bar
->dragging
))
3497 /* Where should the handle be now? */
3498 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3500 if (new_start
!= XINT (bar
->start
))
3502 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3504 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3509 /* Return information to the user about the current position of the mouse
3510 on the scroll bar. */
3512 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3514 Lisp_Object
*bar_window
;
3515 enum scroll_bar_part
*part
;
3517 unsigned long *time
;
3519 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3520 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3521 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3523 Window dummy_window
;
3525 unsigned int dummy_mask
;
3529 /* Get the mouse's position relative to the scroll bar window, and
3531 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3533 /* Root, child, root x and root y. */
3534 &dummy_window
, &dummy_window
,
3535 &dummy_coord
, &dummy_coord
,
3537 /* Position relative to scroll bar. */
3540 /* Mouse buttons and modifier keys. */
3546 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3548 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3550 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3552 if (! NILP (bar
->dragging
))
3553 win_y
-= XINT (bar
->dragging
);
3557 if (win_y
> top_range
)
3561 *bar_window
= bar
->window
;
3563 if (! NILP (bar
->dragging
))
3564 *part
= scroll_bar_handle
;
3565 else if (win_y
< XINT (bar
->start
))
3566 *part
= scroll_bar_above_handle
;
3567 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3568 *part
= scroll_bar_handle
;
3570 *part
= scroll_bar_below_handle
;
3572 XSETINT (*x
, win_y
);
3573 XSETINT (*y
, top_range
);
3576 last_mouse_scroll_bar
= Qnil
;
3579 *time
= last_mouse_movement_time
;
3585 /* The screen has been cleared so we may have changed foreground or
3586 background colors, and the scroll bars may need to be redrawn.
3587 Clear out the scroll bars, and ask for expose events, so we can
3591 x_scroll_bar_clear (f
)
3596 /* We can have scroll bars even if this is 0,
3597 if we just turned off scroll bar mode.
3598 But in that case we should not clear them. */
3599 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3600 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3601 bar
= XSCROLL_BAR (bar
)->next
)
3602 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3606 /* This processes Expose events from the menubar specific X event
3607 loop in xmenu.c. This allows to redisplay the frame if necessary
3608 when handling menubar or popup items. */
3611 process_expose_from_menu (event
)
3615 struct x_display_info
*dpyinfo
;
3619 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3620 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3623 if (f
->async_visible
== 0)
3625 f
->async_visible
= 1;
3626 f
->async_iconified
= 0;
3627 f
->output_data
.x
->has_been_visible
= 1;
3628 SET_FRAME_GARBAGED (f
);
3632 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3633 event
.xexpose
.x
, event
.xexpose
.y
,
3634 event
.xexpose
.width
, event
.xexpose
.height
);
3639 struct scroll_bar
*bar
3640 = x_window_to_scroll_bar (event
.xexpose
.window
);
3643 x_scroll_bar_expose (bar
, &event
);
3649 /* Define a queue to save up SelectionRequest events for later handling. */
3651 struct selection_event_queue
3654 struct selection_event_queue
*next
;
3657 static struct selection_event_queue
*queue
;
3659 /* Nonzero means queue up certain events--don't process them yet. */
3660 static int x_queue_selection_requests
;
3662 /* Queue up an X event *EVENT, to be processed later. */
3665 x_queue_event (f
, event
)
3669 struct selection_event_queue
*queue_tmp
3670 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3672 if (queue_tmp
!= NULL
)
3674 queue_tmp
->event
= *event
;
3675 queue_tmp
->next
= queue
;
3680 /* Take all the queued events and put them back
3681 so that they get processed afresh. */
3684 x_unqueue_events (display
)
3687 while (queue
!= NULL
)
3689 struct selection_event_queue
*queue_tmp
= queue
;
3690 XPutBackEvent (display
, &queue_tmp
->event
);
3691 queue
= queue_tmp
->next
;
3692 free ((char *)queue_tmp
);
3696 /* Start queuing SelectionRequest events. */
3699 x_start_queuing_selection_requests (display
)
3702 x_queue_selection_requests
++;
3705 /* Stop queuing SelectionRequest events. */
3708 x_stop_queuing_selection_requests (display
)
3711 x_queue_selection_requests
--;
3712 x_unqueue_events (display
);
3715 /* The main X event-reading loop - XTread_socket. */
3717 /* Timestamp of enter window event. This is only used by XTread_socket,
3718 but we have to put it out here, since static variables within functions
3719 sometimes don't work. */
3720 static Time enter_timestamp
;
3722 /* This holds the state XLookupString needs to implement dead keys
3723 and other tricks known as "compose processing". _X Window System_
3724 says that a portable program can't use this, but Stephen Gildea assures
3725 me that letting the compiler initialize it to zeros will work okay.
3727 This must be defined outside of XTread_socket, for the same reasons
3728 given for enter_timestamp, above. */
3729 static XComposeStatus compose_status
;
3731 /* Record the last 100 characters stored
3732 to help debug the loss-of-chars-during-GC problem. */
3733 static int temp_index
;
3734 static short temp_buffer
[100];
3736 /* Set this to nonzero to fake an "X I/O error"
3737 on a particular display. */
3738 struct x_display_info
*XTread_socket_fake_io_error
;
3740 /* When we find no input here, we occasionally do a no-op command
3741 to verify that the X server is still running and we can still talk with it.
3742 We try all the open displays, one by one.
3743 This variable is used for cycling thru the displays. */
3744 static struct x_display_info
*next_noop_dpyinfo
;
3746 #define SET_SAVED_MENU_EVENT(size) { \
3747 if (f->output_data.x->saved_menu_event == 0) \
3748 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
3749 bcopy (&event, f->output_data.x->saved_menu_event, size); \
3750 if (numchars >= 1) \
3752 bufp->kind = menu_bar_activate_event; \
3753 XSETFRAME (bufp->frame_or_window, f); \
3759 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
3760 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
3762 /* Read events coming from the X server.
3763 This routine is called by the SIGIO handler.
3764 We return as soon as there are no more events to be read.
3766 Events representing keys are stored in buffer BUFP,
3767 which can hold up to NUMCHARS characters.
3768 We return the number of characters stored into the buffer,
3769 thus pretending to be `read'.
3771 EXPECTED is nonzero if the caller knows input is available. */
3774 XTread_socket (sd
, bufp
, numchars
, expected
)
3776 /* register */ struct input_event
*bufp
;
3777 /* register */ int numchars
;
3783 int items_pending
; /* How many items are in the X queue. */
3786 int event_found
= 0;
3789 struct x_display_info
*dpyinfo
;
3791 Status status_return
;
3794 if (interrupt_input_blocked
)
3796 interrupt_input_pending
= 1;
3800 interrupt_input_pending
= 0;
3803 /* So people can tell when we have read the available input. */
3804 input_signal_count
++;
3807 abort (); /* Don't think this happens. */
3809 /* Find the display we are supposed to read input for.
3810 It's the one communicating on descriptor SD. */
3811 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3813 #if 0 /* This ought to be unnecessary; let's verify it. */
3815 /* If available, Xlib uses FIOSNBIO to make the socket
3816 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3817 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3818 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3819 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3820 #endif /* ! defined (FIOSNBIO) */
3823 #if 0 /* This code can't be made to work, with multiple displays,
3824 and appears not to be used on any system any more.
3825 Also keyboard.c doesn't turn O_NDELAY on and off
3826 for X connections. */
3829 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3831 extern int read_alarm_should_throw
;
3832 read_alarm_should_throw
= 1;
3833 XPeekEvent (dpyinfo
->display
, &event
);
3834 read_alarm_should_throw
= 0;
3836 #endif /* HAVE_SELECT */
3840 /* For debugging, this gives a way to fake an I/O error. */
3841 if (dpyinfo
== XTread_socket_fake_io_error
)
3843 XTread_socket_fake_io_error
= 0;
3844 x_io_error_quitter (dpyinfo
->display
);
3847 while (XPending (dpyinfo
->display
) != 0)
3849 #ifdef USE_X_TOOLKIT
3850 /* needed to raise Motif submenus */
3851 XtAppNextEvent (Xt_app_con
, &event
);
3853 XNextEvent (dpyinfo
->display
, &event
);
3857 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
3858 event
.xclient
.window
);
3859 /* The necessity of the following line took me
3860 a full work-day to decipher from the docs!! */
3861 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
3871 if (event
.xclient
.message_type
3872 == dpyinfo
->Xatom_wm_protocols
3873 && event
.xclient
.format
== 32)
3875 if (event
.xclient
.data
.l
[0]
3876 == dpyinfo
->Xatom_wm_take_focus
)
3878 /* Use x_any_window_to_frame because this
3879 could be the shell widget window
3880 if the frame has no title bar. */
3881 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3883 /* Not quite sure this is needed -pd */
3884 if (f
&& FRAME_XIC (f
))
3885 XSetICFocus (FRAME_XIC (f
));
3887 /* Since we set WM_TAKE_FOCUS, we must call
3888 XSetInputFocus explicitly. But not if f is null,
3889 since that might be an event for a deleted frame. */
3892 Display
*d
= event
.xclient
.display
;
3893 /* Catch and ignore errors, in case window has been
3894 iconified by a window manager such as GWM. */
3895 int count
= x_catch_errors (d
);
3896 XSetInputFocus (d
, event
.xclient
.window
,
3897 RevertToPointerRoot
,
3898 event
.xclient
.data
.l
[1]);
3899 /* This is needed to detect the error
3900 if there is an error. */
3902 x_uncatch_errors (d
, count
);
3904 /* Not certain about handling scroll bars here */
3906 else if (event
.xclient
.data
.l
[0]
3907 == dpyinfo
->Xatom_wm_save_yourself
)
3909 /* Save state modify the WM_COMMAND property to
3910 something which can reinstate us. This notifies
3911 the session manager, who's looking for such a
3912 PropertyNotify. Can restart processing when
3913 a keyboard or mouse event arrives. */
3916 f
= x_top_window_to_frame (dpyinfo
,
3917 event
.xclient
.window
);
3919 /* This is just so we only give real data once
3920 for a single Emacs process. */
3921 if (f
== selected_frame
)
3922 XSetCommand (FRAME_X_DISPLAY (f
),
3923 event
.xclient
.window
,
3924 initial_argv
, initial_argc
);
3926 XSetCommand (FRAME_X_DISPLAY (f
),
3927 event
.xclient
.window
,
3931 else if (event
.xclient
.data
.l
[0]
3932 == dpyinfo
->Xatom_wm_delete_window
)
3935 = x_any_window_to_frame (dpyinfo
,
3936 event
.xclient
.window
);
3943 bufp
->kind
= delete_window_event
;
3944 XSETFRAME (bufp
->frame_or_window
, f
);
3952 else if (event
.xclient
.message_type
3953 == dpyinfo
->Xatom_wm_configure_denied
)
3956 else if (event
.xclient
.message_type
3957 == dpyinfo
->Xatom_wm_window_moved
)
3961 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3963 new_x
= event
.xclient
.data
.s
[0];
3964 new_y
= event
.xclient
.data
.s
[1];
3968 f
->output_data
.x
->left_pos
= new_x
;
3969 f
->output_data
.x
->top_pos
= new_y
;
3973 else if (event
.xclient
.message_type
3974 == dpyinfo
->Xatom_editres
)
3977 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3978 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3981 #endif /* HACK_EDITRES */
3985 case SelectionNotify
:
3986 #ifdef USE_X_TOOLKIT
3987 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3989 #endif /* not USE_X_TOOLKIT */
3990 x_handle_selection_notify (&event
.xselection
);
3993 case SelectionClear
: /* Someone has grabbed ownership. */
3994 #ifdef USE_X_TOOLKIT
3995 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3997 #endif /* USE_X_TOOLKIT */
3999 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
4004 bufp
->kind
= selection_clear_event
;
4005 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
4006 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
4007 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
4008 bufp
->frame_or_window
= Qnil
;
4016 case SelectionRequest
: /* Someone wants our selection. */
4017 #ifdef USE_X_TOOLKIT
4018 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
4020 #endif /* USE_X_TOOLKIT */
4021 if (x_queue_selection_requests
)
4022 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
4026 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
4031 bufp
->kind
= selection_request_event
;
4032 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
4033 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
4034 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
4035 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
4036 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
4037 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
4038 bufp
->frame_or_window
= Qnil
;
4046 case PropertyNotify
:
4047 #ifdef USE_X_TOOLKIT
4048 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
4050 #endif /* not USE_X_TOOLKIT */
4051 x_handle_property_notify (&event
.xproperty
);
4054 case ReparentNotify
:
4055 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
4059 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
4060 x_real_positions (f
, &x
, &y
);
4061 f
->output_data
.x
->left_pos
= x
;
4062 f
->output_data
.x
->top_pos
= y
;
4067 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
4070 if (f
->async_visible
== 0)
4072 f
->async_visible
= 1;
4073 f
->async_iconified
= 0;
4074 f
->output_data
.x
->has_been_visible
= 1;
4075 SET_FRAME_GARBAGED (f
);
4078 dumprectangle (x_window_to_frame (dpyinfo
,
4079 event
.xexpose
.window
),
4080 event
.xexpose
.x
, event
.xexpose
.y
,
4081 event
.xexpose
.width
, event
.xexpose
.height
);
4085 struct scroll_bar
*bar
4086 = x_window_to_scroll_bar (event
.xexpose
.window
);
4089 x_scroll_bar_expose (bar
, &event
);
4090 #ifdef USE_X_TOOLKIT
4093 #endif /* USE_X_TOOLKIT */
4097 case GraphicsExpose
: /* This occurs when an XCopyArea's
4098 source area was obscured or not
4100 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
4104 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
4105 event
.xgraphicsexpose
.width
,
4106 event
.xgraphicsexpose
.height
);
4108 #ifdef USE_X_TOOLKIT
4111 #endif /* USE_X_TOOLKIT */
4114 case NoExpose
: /* This occurs when an XCopyArea's
4115 source area was completely
4120 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
4121 if (f
) /* F may no longer exist if
4122 the frame was deleted. */
4124 /* While a frame is unmapped, display generation is
4125 disabled; you don't want to spend time updating a
4126 display that won't ever be seen. */
4127 f
->async_visible
= 0;
4128 /* We can't distinguish, from the event, whether the window
4129 has become iconified or invisible. So assume, if it
4130 was previously visible, than now it is iconified.
4131 But x_make_frame_invisible clears both
4132 the visible flag and the iconified flag;
4133 and that way, we know the window is not iconified now. */
4134 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
4136 f
->async_iconified
= 1;
4138 bufp
->kind
= iconify_event
;
4139 XSETFRAME (bufp
->frame_or_window
, f
);
4148 /* We use x_top_window_to_frame because map events can come
4149 for subwindows and they don't mean that the frame is visible. */
4150 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
4153 f
->async_visible
= 1;
4154 f
->async_iconified
= 0;
4155 f
->output_data
.x
->has_been_visible
= 1;
4157 /* wait_reading_process_input will notice this and update
4158 the frame's display structures. */
4159 SET_FRAME_GARBAGED (f
);
4163 bufp
->kind
= deiconify_event
;
4164 XSETFRAME (bufp
->frame_or_window
, f
);
4169 else if (! NILP (Vframe_list
)
4170 && ! NILP (XCONS (Vframe_list
)->cdr
))
4171 /* Force a redisplay sooner or later
4172 to update the frame titles
4173 in case this is the second frame. */
4174 record_asynch_buffer_change ();
4178 /* Turn off processing if we become fully obscured. */
4179 case VisibilityNotify
:
4183 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
4187 KeySym keysym
, orig_keysym
;
4188 /* al%imercury@uunet.uu.net says that making this 81 instead of
4189 80 fixed a bug whereby meta chars made his Emacs hang. */
4190 unsigned char copy_buffer
[81];
4193 #if 0 /* This was how we made f10 work in Motif.
4194 The drawback is, you can't type at Emacs when the
4195 the mouse is in the menu bar. So it is better to
4196 turn off f10 in Motif and let Emacs handle it. */
4198 if (lw_window_is_in_menubar (event
.xkey
.window
,
4199 f
->output_data
.x
->menubar_widget
4202 SET_SAVED_KEY_EVENT
;
4205 #endif /* USE_MOTIF */
4209 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
4210 extra_keyboard_modifiers
);
4211 modifiers
= event
.xkey
.state
;
4213 /* This will have to go some day... */
4215 /* make_lispy_event turns chars into control chars.
4216 Don't do it here because XLookupString is too eager. */
4217 event
.xkey
.state
&= ~ControlMask
;
4218 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
4219 | dpyinfo
->super_mod_mask
4220 | dpyinfo
->hyper_mod_mask
4221 | dpyinfo
->alt_mod_mask
);
4223 /* In case Meta is ComposeCharacter,
4224 clear its status. According to Markus Ehrnsperger
4225 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
4226 this enables ComposeCharacter to work whether or
4227 not it is combined with Meta. */
4228 if (modifiers
& dpyinfo
->meta_mod_mask
)
4229 bzero (&compose_status
, sizeof (compose_status
));
4234 /* The necessity of the following line took me
4235 a full work-day to decipher from the docs!! */
4236 if (XFilterEvent (&event
, None
))
4238 nbytes
= XmbLookupString (FRAME_XIC (f
),
4239 &event
.xkey
, copy_buffer
,
4242 if (status_return
== XLookupNone
)
4244 else if (status_return
== XLookupChars
)
4246 else if (status_return
!= XLookupKeySym
4247 && status_return
!= XLookupBoth
)
4251 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4252 80, &keysym
, &compose_status
);
4254 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4255 80, &keysym
, &compose_status
);
4258 orig_keysym
= keysym
;
4262 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
4263 || keysym
== XK_Delete
4264 #ifdef XK_ISO_Left_Tab
4265 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
4267 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
4268 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
4269 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
4271 /* This recognizes the "extended function keys".
4272 It seems there's no cleaner way.
4273 Test IsModifierKey to avoid handling mode_switch
4275 || ((unsigned) (keysym
) >= XK_Select
4276 && (unsigned)(keysym
) < XK_KP_Space
)
4278 #ifdef XK_dead_circumflex
4279 || orig_keysym
== XK_dead_circumflex
4281 #ifdef XK_dead_grave
4282 || orig_keysym
== XK_dead_grave
4284 #ifdef XK_dead_tilde
4285 || orig_keysym
== XK_dead_tilde
4287 #ifdef XK_dead_diaeresis
4288 || orig_keysym
== XK_dead_diaeresis
4290 #ifdef XK_dead_macron
4291 || orig_keysym
== XK_dead_macron
4293 #ifdef XK_dead_degree
4294 || orig_keysym
== XK_dead_degree
4296 #ifdef XK_dead_acute
4297 || orig_keysym
== XK_dead_acute
4299 #ifdef XK_dead_cedilla
4300 || orig_keysym
== XK_dead_cedilla
4302 #ifdef XK_dead_breve
4303 || orig_keysym
== XK_dead_breve
4305 #ifdef XK_dead_ogonek
4306 || orig_keysym
== XK_dead_ogonek
4308 #ifdef XK_dead_caron
4309 || orig_keysym
== XK_dead_caron
4311 #ifdef XK_dead_doubleacute
4312 || orig_keysym
== XK_dead_doubleacute
4314 #ifdef XK_dead_abovedot
4315 || orig_keysym
== XK_dead_abovedot
4317 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
4318 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
4319 /* Any "vendor-specific" key is ok. */
4320 || (orig_keysym
& (1 << 28)))
4321 && ! (IsModifierKey (orig_keysym
)
4323 #ifdef XK_Mode_switch
4324 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
4327 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
4329 #endif /* not HAVE_X11R5 */
4332 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4334 temp_buffer
[temp_index
++] = keysym
;
4335 bufp
->kind
= non_ascii_keystroke
;
4336 bufp
->code
= keysym
;
4337 XSETFRAME (bufp
->frame_or_window
, f
);
4339 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4341 bufp
->timestamp
= event
.xkey
.time
;
4346 else if (numchars
> nbytes
)
4350 for (i
= 0; i
< nbytes
; i
++)
4352 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4354 temp_buffer
[temp_index
++] = copy_buffer
[i
];
4355 bufp
->kind
= ascii_keystroke
;
4356 bufp
->code
= copy_buffer
[i
];
4357 XSETFRAME (bufp
->frame_or_window
, f
);
4359 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4361 bufp
->timestamp
= event
.xkey
.time
;
4368 if (keysym
== NoSymbol
)
4379 /* Here's a possible interpretation of the whole
4380 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
4381 FocusIn event, you have to get a FocusOut event before you
4382 relinquish the focus. If you haven't received a FocusIn event,
4383 then a mere LeaveNotify is enough to free you. */
4386 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4388 if (event
.xcrossing
.focus
) /* Entered Window */
4390 /* Avoid nasty pop/raise loops. */
4391 if (f
&& (!(f
->auto_raise
)
4393 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4395 x_new_focus_frame (dpyinfo
, f
);
4396 enter_timestamp
= event
.xcrossing
.time
;
4399 else if (f
== dpyinfo
->x_focus_frame
)
4400 x_new_focus_frame (dpyinfo
, 0);
4401 /* EnterNotify counts as mouse movement,
4402 so update things that depend on mouse position. */
4404 note_mouse_movement (f
, &event
.xmotion
);
4408 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4409 if (event
.xfocus
.detail
!= NotifyPointer
)
4410 dpyinfo
->x_focus_event_frame
= f
;
4412 x_new_focus_frame (dpyinfo
, f
);
4415 if (f
&& FRAME_XIC (f
))
4416 XSetICFocus (FRAME_XIC (f
));
4422 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4425 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4426 /* If we move outside the frame,
4427 then we're certainly no longer on any text in the frame. */
4428 clear_mouse_face (dpyinfo
);
4430 if (event
.xcrossing
.focus
)
4431 x_mouse_leave (dpyinfo
);
4434 if (f
== dpyinfo
->x_focus_event_frame
)
4435 dpyinfo
->x_focus_event_frame
= 0;
4436 if (f
== dpyinfo
->x_focus_frame
)
4437 x_new_focus_frame (dpyinfo
, 0);
4443 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4444 if (event
.xfocus
.detail
!= NotifyPointer
4445 && f
== dpyinfo
->x_focus_event_frame
)
4446 dpyinfo
->x_focus_event_frame
= 0;
4447 if (f
&& f
== dpyinfo
->x_focus_frame
)
4448 x_new_focus_frame (dpyinfo
, 0);
4451 if (f
&& FRAME_XIC (f
))
4452 XUnsetICFocus (FRAME_XIC (f
));
4459 if (dpyinfo
->grabbed
&& last_mouse_frame
4460 && FRAME_LIVE_P (last_mouse_frame
))
4461 f
= last_mouse_frame
;
4463 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
4465 note_mouse_movement (f
, &event
.xmotion
);
4468 struct scroll_bar
*bar
4469 = x_window_to_scroll_bar (event
.xmotion
.window
);
4472 x_scroll_bar_note_movement (bar
, &event
);
4474 /* If we move outside the frame,
4475 then we're certainly no longer on any text in the frame. */
4476 clear_mouse_face (dpyinfo
);
4481 case ConfigureNotify
:
4482 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
4485 #ifndef USE_X_TOOLKIT
4486 /* In the toolkit version, change_frame_size
4487 is called by the code that handles resizing
4488 of the EmacsFrame widget. */
4490 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4491 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4493 /* Even if the number of character rows and columns has
4494 not changed, the font size may have changed, so we need
4495 to check the pixel dimensions as well. */
4496 if (columns
!= f
->width
4497 || rows
!= f
->height
4498 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
4499 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
4501 change_frame_size (f
, rows
, columns
, 0, 1);
4502 SET_FRAME_GARBAGED (f
);
4503 cancel_mouse_face (f
);
4507 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
4508 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
4510 /* What we have now is the position of Emacs's own window.
4511 Convert that to the position of the window manager window. */
4512 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
4513 &f
->output_data
.x
->top_pos
);
4515 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4517 /* Since the WM decorations come below top_pos now,
4518 we must put them below top_pos in the future. */
4519 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4520 x_wm_set_size_hint (f
, (long) 0, 0);
4523 /* Some window managers pass (0,0) as the location of
4524 the window, and the Motif event handler stores it
4525 in the emacs widget, which messes up Motif menus. */
4526 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
4528 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
4529 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
4538 /* If we decide we want to generate an event to be seen
4539 by the rest of Emacs, we put it here. */
4540 struct input_event emacs_event
;
4541 emacs_event
.kind
= no_event
;
4543 bzero (&compose_status
, sizeof (compose_status
));
4545 if (dpyinfo
->grabbed
&& last_mouse_frame
4546 && FRAME_LIVE_P (last_mouse_frame
))
4547 f
= last_mouse_frame
;
4549 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4553 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4554 construct_mouse_click (&emacs_event
, &event
, f
);
4558 struct scroll_bar
*bar
4559 = x_window_to_scroll_bar (event
.xbutton
.window
);
4562 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4565 if (event
.type
== ButtonPress
)
4567 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4568 last_mouse_frame
= f
;
4569 /* Ignore any mouse motion that happened
4570 before this event; any subsequent mouse-movement
4571 Emacs events should reflect only motion after
4577 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4580 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4582 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4588 #ifdef USE_X_TOOLKIT
4589 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4590 /* For a down-event in the menu bar,
4591 don't pass it to Xt right now.
4592 Instead, save it away
4593 and we will pass it to Xt from kbd_buffer_get_event.
4594 That way, we can run some Lisp code first. */
4595 if (f
&& event
.type
== ButtonPress
4596 /* Verify the event is really within the menu bar
4597 and not just sent to it due to grabbing. */
4598 && event
.xbutton
.x
>= 0
4599 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4600 && event
.xbutton
.y
>= 0
4601 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4602 && event
.xbutton
.same_screen
)
4604 SET_SAVED_BUTTON_EVENT
;
4605 XSETFRAME (last_mouse_press_frame
, f
);
4607 else if (event
.type
== ButtonPress
)
4609 last_mouse_press_frame
= Qnil
;
4612 #ifdef USE_MOTIF /* This should do not harm for Lucid,
4613 but I am trying to be cautious. */
4614 else if (event
.type
== ButtonRelease
)
4616 if (!NILP (last_mouse_press_frame
))
4618 f
= XFRAME (last_mouse_press_frame
);
4619 if (f
->output_data
.x
)
4621 SET_SAVED_BUTTON_EVENT
;
4627 #endif /* USE_MOTIF */
4630 #endif /* USE_X_TOOLKIT */
4634 case CirculateNotify
:
4636 case CirculateRequest
:
4640 /* Someone has changed the keyboard mapping - update the
4642 switch (event
.xmapping
.request
)
4644 case MappingModifier
:
4645 x_find_modifier_meanings (dpyinfo
);
4646 /* This is meant to fall through. */
4647 case MappingKeyboard
:
4648 XRefreshKeyboardMapping (&event
.xmapping
);
4654 #ifdef USE_X_TOOLKIT
4656 XtDispatchEvent (&event
);
4658 #endif /* USE_X_TOOLKIT */
4664 /* On some systems, an X bug causes Emacs to get no more events
4665 when the window is destroyed. Detect that. (1994.) */
4668 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4669 One XNOOP in 100 loops will make Emacs terminate.
4670 B. Bretthauer, 1994 */
4672 if (x_noop_count
>= 100)
4676 if (next_noop_dpyinfo
== 0)
4677 next_noop_dpyinfo
= x_display_list
;
4679 XNoOp (next_noop_dpyinfo
->display
);
4681 /* Each time we get here, cycle through the displays now open. */
4682 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4686 /* If the focus was just given to an autoraising frame,
4688 /* ??? This ought to be able to handle more than one such frame. */
4689 if (pending_autoraise_frame
)
4691 x_raise_frame (pending_autoraise_frame
);
4692 pending_autoraise_frame
= 0;
4699 /* Drawing the cursor. */
4702 /* Draw a hollow box cursor on frame F at X, Y.
4703 Don't change the inside of the box. */
4706 x_draw_box (f
, x
, y
)
4710 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4711 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4712 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4713 int height
= f
->output_data
.x
->line_height
;
4714 int c
= FAST_GLYPH_CHAR (f
->phys_cursor_glyph
);
4715 int charset
= CHAR_CHARSET (c
);
4718 unsigned long mask
= GCForeground
;
4720 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
4722 /* cursor_gc's foreground color is typically the same as the normal
4723 background color, which can cause the cursor box to be invisible. */
4724 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
4725 XChangeGC (FRAME_X_DISPLAY (f
),
4726 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4729 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
4730 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), mask
, &xgcv
);
4732 /* If cursor is on a multi-column character, multiply WIDTH by columns. */
4733 width
*= (charset
== CHARSET_COMPOSITION
4734 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4735 : CHARSET_WIDTH (charset
));
4736 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4737 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4738 left
, top
, width
- 1, height
- 1);
4741 /* Clear the cursor of frame F to background color,
4742 and mark the cursor as not shown.
4743 This is used when the text where the cursor is
4744 is about to be rewritten. */
4752 if (! FRAME_VISIBLE_P (f
)
4753 || ! f
->phys_cursor_on
)
4756 x_update_cursor (f
, 0);
4757 f
->phys_cursor_on
= 0;
4760 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4761 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4765 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4772 CHAR_TO_PIXEL_COL (f
, column
),
4773 CHAR_TO_PIXEL_ROW (f
, row
),
4774 &glyph
, 1, highlight
, 0, NULL
);
4778 x_display_bar_cursor (f
, on
, x
, y
)
4783 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4785 /* This is pointless on invisible frames, and dangerous on garbaged
4786 frames; in the latter case, the frame may be in the midst of
4787 changing its size, and x and y may be off the frame. */
4788 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4791 if (! on
&& ! f
->phys_cursor_on
)
4794 /* If there is anything wrong with the current cursor state, remove it. */
4795 if (f
->phys_cursor_on
4797 || f
->phys_cursor_x
!= x
4798 || f
->phys_cursor_y
!= y
4799 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4801 /* Erase the cursor by redrawing the character underneath it. */
4802 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4803 f
->phys_cursor_glyph
,
4804 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4805 f
->phys_cursor_on
= 0;
4808 /* If we now need a cursor in the new place or in the new form, do it so. */
4810 && (! f
->phys_cursor_on
4811 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4813 f
->phys_cursor_glyph
4814 = ((current_glyphs
->enable
[y
]
4815 && x
< current_glyphs
->used
[y
])
4816 ? current_glyphs
->glyphs
[y
][x
]
4818 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4819 f
->output_data
.x
->cursor_gc
,
4820 CHAR_TO_PIXEL_COL (f
, x
),
4821 CHAR_TO_PIXEL_ROW (f
, y
),
4822 max (f
->output_data
.x
->cursor_width
, 1),
4823 f
->output_data
.x
->line_height
);
4825 f
->phys_cursor_x
= x
;
4826 f
->phys_cursor_y
= y
;
4827 f
->phys_cursor_on
= 1;
4829 f
->output_data
.x
->current_cursor
= bar_cursor
;
4832 if (updating_frame
!= f
)
4833 XFlush (FRAME_X_DISPLAY (f
));
4837 /* Turn the displayed cursor of frame F on or off according to ON.
4838 If ON is nonzero, where to put the cursor is specified by X and Y. */
4841 x_display_box_cursor (f
, on
, x
, y
)
4846 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4848 /* This is pointless on invisible frames, and dangerous on garbaged
4849 frames; in the latter case, the frame may be in the midst of
4850 changing its size, and x and y may be off the frame. */
4851 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4854 /* If cursor is off and we want it off, return quickly. */
4855 if (!on
&& ! f
->phys_cursor_on
)
4858 /* If cursor is currently being shown and we don't want it to be
4859 or it is in the wrong place,
4860 or we want a hollow box and it's not so, (pout!)
4862 if (f
->phys_cursor_on
4864 || f
->phys_cursor_x
!= x
4865 || f
->phys_cursor_y
!= y
4866 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4867 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4869 int mouse_face_here
= 0;
4870 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4872 /* If the cursor is in the mouse face area, redisplay that when
4873 we clear the cursor. */
4874 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4876 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4877 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4878 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4880 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4881 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4882 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4883 /* Don't redraw the cursor's spot in mouse face
4884 if it is at the end of a line (on a newline).
4885 The cursor appears there, but mouse highlighting does not. */
4886 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4887 mouse_face_here
= 1;
4889 /* If the font is not as tall as a whole line,
4890 we must explicitly clear the line's whole height. */
4891 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4892 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4893 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4894 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4895 FONT_WIDTH (f
->output_data
.x
->font
),
4896 f
->output_data
.x
->line_height
, False
);
4897 /* Erase the cursor by redrawing the character underneath it. */
4898 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4899 f
->phys_cursor_glyph
,
4902 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4903 f
->phys_cursor_on
= 0;
4906 /* If we want to show a cursor,
4907 or we want a box cursor and it's not so,
4908 write it in the right place. */
4910 && (! f
->phys_cursor_on
4911 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4912 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4914 f
->phys_cursor_glyph
4915 = ((current_glyphs
->enable
[y
]
4916 && x
< current_glyphs
->used
[y
])
4917 ? current_glyphs
->glyphs
[y
][x
]
4919 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4921 x_draw_box (f
, x
, y
);
4922 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4926 x_draw_single_glyph (f
, y
, x
,
4927 f
->phys_cursor_glyph
, 2);
4928 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4931 f
->phys_cursor_x
= x
;
4932 f
->phys_cursor_y
= y
;
4933 f
->phys_cursor_on
= 1;
4936 if (updating_frame
!= f
)
4937 XFlush (FRAME_X_DISPLAY (f
));
4940 /* Display the cursor on frame F, or clear it, according to ON.
4941 Also set the frame's cursor position to X and Y. */
4944 x_display_cursor (f
, on
, x
, y
)
4951 if ((unsigned) x
>= FRAME_CURSOR_X_LIMIT (f
)
4952 || (unsigned) y
>= FRAME_HEIGHT (f
))
4955 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4956 x_display_box_cursor (f
, on
, x
, y
);
4957 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4958 x_display_bar_cursor (f
, on
, x
, y
);
4960 /* Those are the only two we have implemented! */
4966 /* Display the cursor on frame F, or clear it, according to ON.
4967 Don't change the cursor's position. */
4970 x_update_cursor (f
, on
)
4976 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4977 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4978 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4979 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4981 /* Those are the only two we have implemented! */
4989 /* Refresh bitmap kitchen sink icon for frame F
4990 when we get an expose event for it. */
4996 /* Normally, the window manager handles this function. */
4999 /* Make the x-window of frame F use the gnu icon bitmap. */
5002 x_bitmap_icon (f
, file
)
5006 int mask
, bitmap_id
;
5009 if (FRAME_X_WINDOW (f
) == 0)
5012 /* Free up our existing icon bitmap if any. */
5013 if (f
->output_data
.x
->icon_bitmap
> 0)
5014 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
5015 f
->output_data
.x
->icon_bitmap
= 0;
5018 bitmap_id
= x_create_bitmap_from_file (f
, file
);
5021 /* Create the GNU bitmap if necessary. */
5022 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
5023 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
5024 = x_create_bitmap_from_data (f
, gnu_bits
,
5025 gnu_width
, gnu_height
);
5027 /* The first time we create the GNU bitmap,
5028 this increments the refcount one extra time.
5029 As a result, the GNU bitmap is never freed.
5030 That way, we don't have to worry about allocating it again. */
5031 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
5033 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
5036 x_wm_set_icon_pixmap (f
, bitmap_id
);
5037 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
5043 /* Make the x-window of frame F use a rectangle with text.
5044 Use ICON_NAME as the text. */
5047 x_text_icon (f
, icon_name
)
5051 if (FRAME_X_WINDOW (f
) == 0)
5057 text
.value
= (unsigned char *) icon_name
;
5058 text
.encoding
= XA_STRING
;
5060 text
.nitems
= strlen (icon_name
);
5061 #ifdef USE_X_TOOLKIT
5062 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5064 #else /* not USE_X_TOOLKIT */
5065 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
5066 #endif /* not USE_X_TOOLKIT */
5068 #else /* not HAVE_X11R4 */
5069 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
5070 #endif /* not HAVE_X11R4 */
5072 if (f
->output_data
.x
->icon_bitmap
> 0)
5073 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
5074 f
->output_data
.x
->icon_bitmap
= 0;
5075 x_wm_set_icon_pixmap (f
, 0);
5080 #define X_ERROR_MESSAGE_SIZE 200
5082 /* If non-nil, this should be a string.
5083 It means catch X errors and store the error message in this string. */
5085 static Lisp_Object x_error_message_string
;
5087 /* An X error handler which stores the error message in
5088 x_error_message_string. This is called from x_error_handler if
5089 x_catch_errors is in effect. */
5092 x_error_catcher (display
, error
)
5096 XGetErrorText (display
, error
->error_code
,
5097 XSTRING (x_error_message_string
)->data
,
5098 X_ERROR_MESSAGE_SIZE
);
5101 /* Begin trapping X errors for display DPY. Actually we trap X errors
5102 for all displays, but DPY should be the display you are actually
5105 After calling this function, X protocol errors no longer cause
5106 Emacs to exit; instead, they are recorded in the string
5107 stored in x_error_message_string.
5109 Calling x_check_errors signals an Emacs error if an X error has
5110 occurred since the last call to x_catch_errors or x_check_errors.
5112 Calling x_uncatch_errors resumes the normal error handling. */
5114 void x_check_errors ();
5115 static Lisp_Object
x_catch_errors_unwind ();
5118 x_catch_errors (dpy
)
5121 int count
= specpdl_ptr
- specpdl
;
5123 /* Make sure any errors from previous requests have been dealt with. */
5126 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
5128 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
5129 XSTRING (x_error_message_string
)->data
[0] = 0;
5134 /* Unbind the binding that we made to check for X errors. */
5137 x_catch_errors_unwind (old_val
)
5138 Lisp_Object old_val
;
5140 x_error_message_string
= old_val
;
5144 /* If any X protocol errors have arrived since the last call to
5145 x_catch_errors or x_check_errors, signal an Emacs error using
5146 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5149 x_check_errors (dpy
, format
)
5153 /* Make sure to catch any errors incurred so far. */
5156 if (XSTRING (x_error_message_string
)->data
[0])
5157 error (format
, XSTRING (x_error_message_string
)->data
);
5160 /* Nonzero if we had any X protocol errors
5161 since we did x_catch_errors on DPY. */
5164 x_had_errors_p (dpy
)
5167 /* Make sure to catch any errors incurred so far. */
5170 return XSTRING (x_error_message_string
)->data
[0] != 0;
5173 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
5176 x_clear_errors (dpy
)
5179 XSTRING (x_error_message_string
)->data
[0] = 0;
5182 /* Stop catching X protocol errors and let them make Emacs die.
5183 DPY should be the display that was passed to x_catch_errors.
5184 COUNT should be the value that was returned by
5185 the corresponding call to x_catch_errors. */
5188 x_uncatch_errors (dpy
, count
)
5192 unbind_to (count
, Qnil
);
5196 static unsigned int x_wire_count
;
5199 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5204 /* Handle SIGPIPE, which can happen when the connection to a server
5205 simply goes away. SIGPIPE is handled by x_connection_signal.
5206 Don't need to do anything, because the write which caused the
5207 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
5208 which will do the appropriate cleanup for us. */
5211 x_connection_signal (signalnum
) /* If we don't have an argument, */
5212 int signalnum
; /* some compilers complain in signal calls. */
5215 /* USG systems forget handlers when they are used;
5216 must reestablish each time */
5217 signal (signalnum
, x_connection_signal
);
5221 /* Handling X errors. */
5223 /* Handle the loss of connection to display DISPLAY. */
5226 x_connection_closed (display
, error_message
)
5228 char *error_message
;
5230 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
5231 Lisp_Object frame
, tail
;
5233 /* Indicate that this display is dead. */
5235 #ifdef USE_X_TOOLKIT
5236 XtCloseDisplay (display
);
5239 dpyinfo
->display
= 0;
5241 /* First delete frames whose minibuffers are on frames
5242 that are on the dead display. */
5243 FOR_EACH_FRAME (tail
, frame
)
5245 Lisp_Object minibuf_frame
;
5247 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
5248 if (FRAME_X_P (XFRAME (frame
))
5249 && FRAME_X_P (XFRAME (minibuf_frame
))
5250 && ! EQ (frame
, minibuf_frame
)
5251 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
5252 Fdelete_frame (frame
, Qt
);
5255 /* Now delete all remaining frames on the dead display.
5256 We are now sure none of these is used as the minibuffer
5257 for another frame that we need to delete. */
5258 FOR_EACH_FRAME (tail
, frame
)
5259 if (FRAME_X_P (XFRAME (frame
))
5260 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
5262 /* Set this to t so that Fdelete_frame won't get confused
5263 trying to find a replacement. */
5264 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
5265 Fdelete_frame (frame
, Qt
);
5269 x_delete_display (dpyinfo
);
5271 if (x_display_list
== 0)
5273 fprintf (stderr
, "%s\n", error_message
);
5274 shut_down_emacs (0, 0, Qnil
);
5278 /* Ordinary stack unwind doesn't deal with these. */
5280 sigunblock (sigmask (SIGIO
));
5282 sigunblock (sigmask (SIGALRM
));
5283 TOTALLY_UNBLOCK_INPUT
;
5285 clear_waiting_for_input ();
5286 error ("%s", error_message
);
5289 /* This is the usual handler for X protocol errors.
5290 It kills all frames on the display that we got the error for.
5291 If that was the only one, it prints an error message and kills Emacs. */
5294 x_error_quitter (display
, error
)
5298 char buf
[256], buf1
[356];
5300 /* Note that there is no real way portable across R3/R4 to get the
5301 original error handler. */
5303 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
5304 sprintf (buf1
, "X protocol error: %s on protocol request %d",
5305 buf
, error
->request_code
);
5306 x_connection_closed (display
, buf1
);
5309 /* This is the first-level handler for X protocol errors.
5310 It calls x_error_quitter or x_error_catcher. */
5313 x_error_handler (display
, error
)
5317 char buf
[256], buf1
[356];
5319 if (! NILP (x_error_message_string
))
5320 x_error_catcher (display
, error
);
5322 x_error_quitter (display
, error
);
5325 /* This is the handler for X IO errors, always.
5326 It kills all frames on the display that we lost touch with.
5327 If that was the only one, it prints an error message and kills Emacs. */
5330 x_io_error_quitter (display
)
5335 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
5336 x_connection_closed (display
, buf
);
5339 /* Changing the font of the frame. */
5341 /* Give frame F the font named FONTNAME as its default font, and
5342 return the full name of that font. FONTNAME may be a wildcard
5343 pattern; in that case, we choose some font that fits the pattern.
5344 The return value shows which font we chose. */
5347 x_new_font (f
, fontname
)
5349 register char *fontname
;
5351 struct font_info
*fontp
5352 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
5357 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
5358 f
->output_data
.x
->font_baseline
5359 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
5360 f
->output_data
.x
->fontset
= -1;
5362 /* Compute the scroll bar width in character columns. */
5363 if (f
->scroll_bar_pixel_width
> 0)
5365 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5366 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
5370 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5371 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
5374 /* Now make the frame display the given font. */
5375 if (FRAME_X_WINDOW (f
) != 0)
5377 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
5378 f
->output_data
.x
->font
->fid
);
5379 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
5380 f
->output_data
.x
->font
->fid
);
5381 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
5382 f
->output_data
.x
->font
->fid
);
5384 frame_update_line_height (f
);
5385 x_set_window_size (f
, 0, f
->width
, f
->height
);
5388 /* If we are setting a new frame's font for the first time,
5389 there are no faces yet, so this font's height is the line height. */
5390 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
5392 return build_string (fontp
->full_name
);
5395 /* Give frame F the fontset named FONTSETNAME as its default font, and
5396 return the full name of that fontset. FONTSETNAME may be a wildcard
5397 pattern; in that case, we choose some fontset that fits the pattern.
5398 The return value shows which fontset we chose. */
5401 x_new_fontset (f
, fontsetname
)
5405 int fontset
= fs_query_fontset (f
, fontsetname
);
5406 struct fontset_info
*fontsetp
;
5412 if (f
->output_data
.x
->fontset
== fontset
)
5413 /* This fontset is already set in frame F. There's nothing more
5415 return build_string (fontsetname
);
5417 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
5419 if (!fontsetp
->fontname
[CHARSET_ASCII
])
5420 /* This fontset doesn't contain ASCII font. */
5423 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
5425 if (!STRINGP (result
))
5426 /* Can't load ASCII font. */
5429 /* Since x_new_font doesn't update any fontset information, do it now. */
5430 f
->output_data
.x
->fontset
= fontset
;
5431 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
5432 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
5434 return build_string (fontsetname
);
5437 /* Calculate the absolute position in frame F
5438 from its current recorded position values and gravity. */
5441 x_calc_absolute_position (f
)
5445 int win_x
= 0, win_y
= 0;
5446 int flags
= f
->output_data
.x
->size_hint_flags
;
5449 /* We have nothing to do if the current position
5450 is already for the top-left corner. */
5451 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5454 #ifdef USE_X_TOOLKIT
5455 this_window
= XtWindow (f
->output_data
.x
->widget
);
5457 this_window
= FRAME_X_WINDOW (f
);
5460 /* Find the position of the outside upper-left corner of
5461 the inner window, with respect to the outer window.
5462 But do this only if we will need the results. */
5463 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
5468 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
5471 x_clear_errors (FRAME_X_DISPLAY (f
));
5472 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
5474 /* From-window, to-window. */
5476 f
->output_data
.x
->parent_desc
,
5478 /* From-position, to-position. */
5479 0, 0, &win_x
, &win_y
,
5483 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
5485 Window newroot
, newparent
= 0xdeadbeef;
5486 Window
*newchildren
;
5489 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
5490 &newparent
, &newchildren
, &nchildren
))
5493 XFree ((char *) newchildren
);
5495 f
->output_data
.x
->parent_desc
= newparent
;
5501 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
5505 /* Treat negative positions as relative to the leftmost bottommost
5506 position that fits on the screen. */
5507 if (flags
& XNegative
)
5508 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5509 - 2 * f
->output_data
.x
->border_width
- win_x
5511 + f
->output_data
.x
->left_pos
);
5513 if (flags
& YNegative
)
5514 /* We used to subtract f->output_data.x->menubar_height here
5515 in the toolkit case, but PIXEL_HEIGHT already includes that. */
5516 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5517 - 2 * f
->output_data
.x
->border_width
- win_y
5519 + f
->output_data
.x
->top_pos
);
5521 /* The left_pos and top_pos
5522 are now relative to the top and left screen edges,
5523 so the flags should correspond. */
5524 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5527 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5528 to really change the position, and 0 when calling from
5529 x_make_frame_visible (in that case, XOFF and YOFF are the current
5530 position values). It is -1 when calling from x_set_frame_parameters,
5531 which means, do adjust for borders but don't change the gravity. */
5534 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5536 register int xoff
, yoff
;
5539 int modified_top
, modified_left
;
5541 if (change_gravity
> 0)
5543 f
->output_data
.x
->top_pos
= yoff
;
5544 f
->output_data
.x
->left_pos
= xoff
;
5545 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5547 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5549 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5550 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5552 x_calc_absolute_position (f
);
5555 x_wm_set_size_hint (f
, (long) 0, 0);
5557 modified_left
= f
->output_data
.x
->left_pos
;
5558 modified_top
= f
->output_data
.x
->top_pos
;
5559 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
5560 this seems to be unnecessary and incorrect. rms, 4/17/97. */
5561 /* It is a mystery why we need to add the border_width here
5562 when the frame is already visible, but experiment says we do. */
5563 if (change_gravity
!= 0)
5565 modified_left
+= f
->output_data
.x
->border_width
;
5566 modified_top
+= f
->output_data
.x
->border_width
;
5570 #ifdef USE_X_TOOLKIT
5571 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5572 modified_left
, modified_top
);
5573 #else /* not USE_X_TOOLKIT */
5574 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5575 modified_left
, modified_top
);
5576 #endif /* not USE_X_TOOLKIT */
5580 /* Call this to change the size of frame F's x-window.
5581 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5582 for this size change and subsequent size changes.
5583 Otherwise we leave the window gravity unchanged. */
5586 x_set_window_size (f
, change_gravity
, cols
, rows
)
5591 int pixelwidth
, pixelheight
;
5593 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5597 #ifdef USE_X_TOOLKIT
5599 /* The x and y position of the widget is clobbered by the
5600 call to XtSetValues within EmacsFrameSetCharSize.
5601 This is a real kludge, but I don't understand Xt so I can't
5602 figure out a correct fix. Can anyone else tell me? -- rms. */
5603 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5604 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5605 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5606 f
->output_data
.x
->widget
->core
.x
= xpos
;
5607 f
->output_data
.x
->widget
->core
.y
= ypos
;
5610 #else /* not USE_X_TOOLKIT */
5612 check_frame_size (f
, &rows
, &cols
);
5613 f
->output_data
.x
->vertical_scroll_bar_extra
5614 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5616 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5617 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5618 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5619 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5620 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5622 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5623 x_wm_set_size_hint (f
, (long) 0, 0);
5625 XSync (FRAME_X_DISPLAY (f
), False
);
5626 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5627 pixelwidth
, pixelheight
);
5629 /* Now, strictly speaking, we can't be sure that this is accurate,
5630 but the window manager will get around to dealing with the size
5631 change request eventually, and we'll hear how it went when the
5632 ConfigureNotify event gets here.
5634 We could just not bother storing any of this information here,
5635 and let the ConfigureNotify event set everything up, but that
5636 might be kind of confusing to the lisp code, since size changes
5637 wouldn't be reported in the frame parameters until some random
5638 point in the future when the ConfigureNotify event arrives. */
5639 change_frame_size (f
, rows
, cols
, 0, 0);
5640 PIXEL_WIDTH (f
) = pixelwidth
;
5641 PIXEL_HEIGHT (f
) = pixelheight
;
5643 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5644 receive in the ConfigureNotify event; if we get what we asked
5645 for, then the event won't cause the screen to become garbaged, so
5646 we have to make sure to do it here. */
5647 SET_FRAME_GARBAGED (f
);
5649 XFlush (FRAME_X_DISPLAY (f
));
5651 #endif /* not USE_X_TOOLKIT */
5653 /* If cursor was outside the new size, mark it as off. */
5654 if (f
->phys_cursor_y
>= rows
5655 || f
->phys_cursor_x
>= cols
)
5657 f
->phys_cursor_x
= 0;
5658 f
->phys_cursor_y
= 0;
5659 f
->phys_cursor_on
= 0;
5662 /* Clear out any recollection of where the mouse highlighting was,
5663 since it might be in a place that's outside the new frame size.
5664 Actually checking whether it is outside is a pain in the neck,
5665 so don't try--just let the highlighting be done afresh with new size. */
5666 cancel_mouse_face (f
);
5671 /* Mouse warping. */
5674 x_set_mouse_position (f
, x
, y
)
5680 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5681 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5683 if (pix_x
< 0) pix_x
= 0;
5684 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5686 if (pix_y
< 0) pix_y
= 0;
5687 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5691 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5692 0, 0, 0, 0, pix_x
, pix_y
);
5696 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5699 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5705 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5706 0, 0, 0, 0, pix_x
, pix_y
);
5710 /* focus shifting, raising and lowering. */
5713 x_focus_on_frame (f
)
5716 #if 0 /* This proves to be unpleasant. */
5720 /* I don't think that the ICCCM allows programs to do things like this
5721 without the interaction of the window manager. Whatever you end up
5722 doing with this code, do it to x_unfocus_frame too. */
5723 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5724 RevertToPointerRoot
, CurrentTime
);
5733 /* Look at the remarks in x_focus_on_frame. */
5734 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5735 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5736 RevertToPointerRoot
, CurrentTime
);
5740 /* Raise frame F. */
5746 if (f
->async_visible
)
5749 #ifdef USE_X_TOOLKIT
5750 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5751 #else /* not USE_X_TOOLKIT */
5752 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5753 #endif /* not USE_X_TOOLKIT */
5754 XFlush (FRAME_X_DISPLAY (f
));
5759 /* Lower frame F. */
5765 if (f
->async_visible
)
5768 #ifdef USE_X_TOOLKIT
5769 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5770 #else /* not USE_X_TOOLKIT */
5771 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5772 #endif /* not USE_X_TOOLKIT */
5773 XFlush (FRAME_X_DISPLAY (f
));
5779 XTframe_raise_lower (f
, raise_flag
)
5789 /* Change of visibility. */
5791 /* This tries to wait until the frame is really visible.
5792 However, if the window manager asks the user where to position
5793 the frame, this will return before the user finishes doing that.
5794 The frame will not actually be visible at that time,
5795 but it will become visible later when the window manager
5796 finishes with it. */
5799 x_make_frame_visible (f
)
5804 int starting_flags
= f
->output_data
.x
->size_hint_flags
;
5805 int original_top
, original_left
;
5809 type
= x_icon_type (f
);
5811 x_bitmap_icon (f
, type
);
5813 if (! FRAME_VISIBLE_P (f
))
5815 /* We test FRAME_GARBAGED_P here to make sure we don't
5816 call x_set_offset a second time
5817 if we get to x_make_frame_visible a second time
5818 before the window gets really visible. */
5819 if (! FRAME_ICONIFIED_P (f
)
5820 && ! f
->output_data
.x
->asked_for_visible
)
5821 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5823 f
->output_data
.x
->asked_for_visible
= 1;
5825 if (! EQ (Vx_no_window_manager
, Qt
))
5826 x_wm_set_window_state (f
, NormalState
);
5827 #ifdef USE_X_TOOLKIT
5828 /* This was XtPopup, but that did nothing for an iconified frame. */
5829 XtMapWidget (f
->output_data
.x
->widget
);
5830 #else /* not USE_X_TOOLKIT */
5831 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5832 #endif /* not USE_X_TOOLKIT */
5833 #if 0 /* This seems to bring back scroll bars in the wrong places
5834 if the window configuration has changed. They seem
5835 to come back ok without this. */
5836 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5837 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5841 XFlush (FRAME_X_DISPLAY (f
));
5843 /* Synchronize to ensure Emacs knows the frame is visible
5844 before we do anything else. We do this loop with input not blocked
5845 so that incoming events are handled. */
5848 int count
= input_signal_count
;
5849 /* This must be before UNBLOCK_INPUT
5850 since events that arrive in response to the actions above
5851 will set it when they are handled. */
5852 int previously_visible
= f
->output_data
.x
->has_been_visible
;
5854 original_left
= f
->output_data
.x
->left_pos
;
5855 original_top
= f
->output_data
.x
->top_pos
;
5857 /* This must come after we set COUNT. */
5860 /* We unblock here so that arriving X events are processed. */
5862 /* Now move the window back to where it was "supposed to be".
5863 But don't do it if the gravity is negative.
5864 When the gravity is negative, this uses a position
5865 that is 3 pixels too low. Perhaps that's really the border width.
5867 Don't do this if the window has never been visible before,
5868 because the window manager may choose the position
5869 and we don't want to override it. */
5871 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
5872 && f
->output_data
.x
->win_gravity
== NorthWestGravity
5873 && previously_visible
)
5877 unsigned int width
, height
, border
, depth
;
5881 /* On some window managers (Such as FVWM) moving an existing window,
5882 even to the same place, causes the window manager to introduce
5883 an offset. This can cause the window to move to an unexpected
5884 location. Check the geometry (A little slow here) and then verify
5885 that the window is in the right place. If the window is not in
5886 the right place, move it there, and take the potential window
5889 XGetGeometry (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
5890 &rootw
, &x
, &y
, &width
, &height
, &border
, &depth
);
5892 if (original_left
!= x
|| original_top
!= y
)
5893 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_OUTER_WINDOW (f
),
5894 original_left
, original_top
);
5899 XSETFRAME (frame
, f
);
5904 /* Once we have handled input events,
5905 we should have received the MapNotify if one is coming.
5906 So if we have not got it yet, stop looping.
5907 Some window managers make their own decisions
5908 about visibility. */
5909 if (input_signal_count
!= count
)
5911 /* Machines that do polling rather than SIGIO have been observed
5912 to go into a busy-wait here. So we'll fake an alarm signal
5913 to let the handler know that there's something to be read.
5914 We used to raise a real alarm, but it seems that the handler
5915 isn't always enabled here. This is probably a bug. */
5916 if (input_polling_used ())
5918 /* It could be confusing if a real alarm arrives while processing
5919 the fake one. Turn it off and let the handler reset it. */
5921 input_poll_signal (0);
5923 /* Once we have handled input events,
5924 we should have received the MapNotify if one is coming.
5925 So if we have not got it yet, stop looping.
5926 Some window managers make their own decisions
5927 about visibility. */
5928 if (input_signal_count
!= count
)
5931 FRAME_SAMPLE_VISIBILITY (f
);
5935 /* Change from mapped state to withdrawn state. */
5937 /* Make the frame visible (mapped and not iconified). */
5940 x_make_frame_invisible (f
)
5946 #ifdef USE_X_TOOLKIT
5947 /* Use the frame's outermost window, not the one we normally draw on. */
5948 window
= XtWindow (f
->output_data
.x
->widget
);
5949 #else /* not USE_X_TOOLKIT */
5950 window
= FRAME_X_WINDOW (f
);
5951 #endif /* not USE_X_TOOLKIT */
5953 /* Don't keep the highlight on an invisible frame. */
5954 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5955 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5957 #if 0/* This might add unreliability; I don't trust it -- rms. */
5958 if (! f
->async_visible
&& ! f
->async_iconified
)
5964 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5965 that the current position of the window is user-specified, rather than
5966 program-specified, so that when the window is mapped again, it will be
5967 placed at the same location, without forcing the user to position it
5968 by hand again (they have already done that once for this window.) */
5969 x_wm_set_size_hint (f
, (long) 0, 1);
5973 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5974 DefaultScreen (FRAME_X_DISPLAY (f
))))
5976 UNBLOCK_INPUT_RESIGNAL
;
5977 error ("Can't notify window manager of window withdrawal");
5979 #else /* ! defined (HAVE_X11R4) */
5981 /* Tell the window manager what we're going to do. */
5982 if (! EQ (Vx_no_window_manager
, Qt
))
5986 unmap
.xunmap
.type
= UnmapNotify
;
5987 unmap
.xunmap
.window
= window
;
5988 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5989 unmap
.xunmap
.from_configure
= False
;
5990 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5991 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5993 SubstructureRedirectMask
|SubstructureNotifyMask
,
5996 UNBLOCK_INPUT_RESIGNAL
;
5997 error ("Can't notify window manager of withdrawal");
6001 /* Unmap the window ourselves. Cheeky! */
6002 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
6003 #endif /* ! defined (HAVE_X11R4) */
6005 /* We can't distinguish this from iconification
6006 just by the event that we get from the server.
6007 So we can't win using the usual strategy of letting
6008 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
6009 and synchronize with the server to make sure we agree. */
6011 FRAME_ICONIFIED_P (f
) = 0;
6012 f
->async_visible
= 0;
6013 f
->async_iconified
= 0;
6020 /* Change window state from mapped to iconified. */
6030 /* Don't keep the highlight on an invisible frame. */
6031 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
6032 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
6034 if (f
->async_iconified
)
6039 FRAME_SAMPLE_VISIBILITY (f
);
6041 type
= x_icon_type (f
);
6043 x_bitmap_icon (f
, type
);
6045 #ifdef USE_X_TOOLKIT
6047 if (! FRAME_VISIBLE_P (f
))
6049 if (! EQ (Vx_no_window_manager
, Qt
))
6050 x_wm_set_window_state (f
, IconicState
);
6051 /* This was XtPopup, but that did nothing for an iconified frame. */
6052 XtMapWidget (f
->output_data
.x
->widget
);
6053 /* The server won't give us any event to indicate
6054 that an invisible frame was changed to an icon,
6055 so we have to record it here. */
6058 f
->async_iconified
= 1;
6059 f
->async_visible
= 0;
6064 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
6065 XtWindow (f
->output_data
.x
->widget
),
6066 DefaultScreen (FRAME_X_DISPLAY (f
)));
6070 error ("Can't notify window manager of iconification");
6072 f
->async_iconified
= 1;
6073 f
->async_visible
= 0;
6077 XFlush (FRAME_X_DISPLAY (f
));
6079 #else /* not USE_X_TOOLKIT */
6081 /* Make sure the X server knows where the window should be positioned,
6082 in case the user deiconifies with the window manager. */
6083 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
6084 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
6086 /* Since we don't know which revision of X we're running, we'll use both
6087 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
6089 /* X11R4: send a ClientMessage to the window manager using the
6090 WM_CHANGE_STATE type. */
6094 message
.xclient
.window
= FRAME_X_WINDOW (f
);
6095 message
.xclient
.type
= ClientMessage
;
6096 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
6097 message
.xclient
.format
= 32;
6098 message
.xclient
.data
.l
[0] = IconicState
;
6100 if (! XSendEvent (FRAME_X_DISPLAY (f
),
6101 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
6103 SubstructureRedirectMask
| SubstructureNotifyMask
,
6106 UNBLOCK_INPUT_RESIGNAL
;
6107 error ("Can't notify window manager of iconification");
6111 /* X11R3: set the initial_state field of the window manager hints to
6113 x_wm_set_window_state (f
, IconicState
);
6115 if (!FRAME_VISIBLE_P (f
))
6117 /* If the frame was withdrawn, before, we must map it. */
6118 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
6121 f
->async_iconified
= 1;
6122 f
->async_visible
= 0;
6124 XFlush (FRAME_X_DISPLAY (f
));
6126 #endif /* not USE_X_TOOLKIT */
6129 /* Destroy the X window of frame F. */
6132 x_destroy_window (f
)
6135 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6139 /* If a display connection is dead, don't try sending more
6140 commands to the X server. */
6141 if (dpyinfo
->display
!= 0)
6143 if (f
->output_data
.x
->icon_desc
!= 0)
6144 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
6148 XDestroyIC (FRAME_XIC (f
));
6149 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
6150 /* This line causes crashes on Solaris with Openwin,
6151 due to an apparent bug in XCloseIM.
6152 X11R6 seems not to have the bug. */
6153 XCloseIM (FRAME_XIM (f
));
6157 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
6158 #ifdef USE_X_TOOLKIT
6159 XtDestroyWidget (f
->output_data
.x
->widget
);
6160 free_frame_menubar (f
);
6161 #endif /* USE_X_TOOLKIT */
6163 free_frame_faces (f
);
6164 XFlush (FRAME_X_DISPLAY (f
));
6167 if (f
->output_data
.x
->saved_menu_event
)
6168 free (f
->output_data
.x
->saved_menu_event
);
6170 xfree (f
->output_data
.x
);
6171 f
->output_data
.x
= 0;
6172 if (f
== dpyinfo
->x_focus_frame
)
6173 dpyinfo
->x_focus_frame
= 0;
6174 if (f
== dpyinfo
->x_focus_event_frame
)
6175 dpyinfo
->x_focus_event_frame
= 0;
6176 if (f
== dpyinfo
->x_highlight_frame
)
6177 dpyinfo
->x_highlight_frame
= 0;
6179 dpyinfo
->reference_count
--;
6181 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6183 dpyinfo
->mouse_face_beg_row
6184 = dpyinfo
->mouse_face_beg_col
= -1;
6185 dpyinfo
->mouse_face_end_row
6186 = dpyinfo
->mouse_face_end_col
= -1;
6187 dpyinfo
->mouse_face_window
= Qnil
;
6188 dpyinfo
->mouse_face_deferred_gc
= 0;
6189 dpyinfo
->mouse_face_mouse_frame
= 0;
6195 /* Setting window manager hints. */
6197 /* Set the normal size hints for the window manager, for frame F.
6198 FLAGS is the flags word to use--or 0 meaning preserve the flags
6199 that the window now has.
6200 If USER_POSITION is nonzero, we set the USPosition
6201 flag (this is useful when FLAGS is 0). */
6204 x_wm_set_size_hint (f
, flags
, user_position
)
6209 XSizeHints size_hints
;
6211 #ifdef USE_X_TOOLKIT
6214 Dimension widget_width
, widget_height
;
6215 Window window
= XtWindow (f
->output_data
.x
->widget
);
6216 #else /* not USE_X_TOOLKIT */
6217 Window window
= FRAME_X_WINDOW (f
);
6218 #endif /* not USE_X_TOOLKIT */
6220 /* Setting PMaxSize caused various problems. */
6221 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6223 flexlines
= f
->height
;
6225 size_hints
.x
= f
->output_data
.x
->left_pos
;
6226 size_hints
.y
= f
->output_data
.x
->top_pos
;
6228 #ifdef USE_X_TOOLKIT
6229 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6230 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6231 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
6232 size_hints
.height
= widget_height
;
6233 size_hints
.width
= widget_width
;
6234 #else /* not USE_X_TOOLKIT */
6235 size_hints
.height
= PIXEL_HEIGHT (f
);
6236 size_hints
.width
= PIXEL_WIDTH (f
);
6237 #endif /* not USE_X_TOOLKIT */
6239 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
6240 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
6241 size_hints
.max_width
6242 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6243 size_hints
.max_height
6244 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6246 /* Calculate the base and minimum sizes.
6248 (When we use the X toolkit, we don't do it here.
6249 Instead we copy the values that the widgets are using, below.) */
6250 #ifndef USE_X_TOOLKIT
6252 int base_width
, base_height
;
6253 int min_rows
= 0, min_cols
= 0;
6255 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6256 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6258 check_frame_size (f
, &min_rows
, &min_cols
);
6260 /* The window manager uses the base width hints to calculate the
6261 current number of rows and columns in the frame while
6262 resizing; min_width and min_height aren't useful for this
6263 purpose, since they might not give the dimensions for a
6264 zero-row, zero-column frame.
6266 We use the base_width and base_height members if we have
6267 them; otherwise, we set the min_width and min_height members
6268 to the size for a zero x zero frame. */
6271 size_hints
.flags
|= PBaseSize
;
6272 size_hints
.base_width
= base_width
;
6273 size_hints
.base_height
= base_height
;
6274 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6275 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6277 size_hints
.min_width
= base_width
;
6278 size_hints
.min_height
= base_height
;
6282 /* If we don't need the old flags, we don't need the old hint at all. */
6285 size_hints
.flags
|= flags
;
6288 #endif /* not USE_X_TOOLKIT */
6291 XSizeHints hints
; /* Sometimes I hate X Windows... */
6292 long supplied_return
;
6296 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
6299 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
6302 #ifdef USE_X_TOOLKIT
6303 size_hints
.base_height
= hints
.base_height
;
6304 size_hints
.base_width
= hints
.base_width
;
6305 size_hints
.min_height
= hints
.min_height
;
6306 size_hints
.min_width
= hints
.min_width
;
6310 size_hints
.flags
|= flags
;
6315 if (hints
.flags
& PSize
)
6316 size_hints
.flags
|= PSize
;
6317 if (hints
.flags
& PPosition
)
6318 size_hints
.flags
|= PPosition
;
6319 if (hints
.flags
& USPosition
)
6320 size_hints
.flags
|= USPosition
;
6321 if (hints
.flags
& USSize
)
6322 size_hints
.flags
|= USSize
;
6329 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
6330 size_hints
.flags
|= PWinGravity
;
6334 size_hints
.flags
&= ~ PPosition
;
6335 size_hints
.flags
|= USPosition
;
6337 #endif /* PWinGravity */
6340 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6342 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6346 /* Used for IconicState or NormalState */
6348 x_wm_set_window_state (f
, state
)
6352 #ifdef USE_X_TOOLKIT
6355 XtSetArg (al
[0], XtNinitialState
, state
);
6356 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6357 #else /* not USE_X_TOOLKIT */
6358 Window window
= FRAME_X_WINDOW (f
);
6360 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6361 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6363 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6364 #endif /* not USE_X_TOOLKIT */
6368 x_wm_set_icon_pixmap (f
, pixmap_id
)
6374 #ifdef USE_X_TOOLKIT
6375 Window window
= XtWindow (f
->output_data
.x
->widget
);
6377 Window window
= FRAME_X_WINDOW (f
);
6382 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6383 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6387 /* It seems there is no way to turn off use of an icon pixmap.
6388 The following line does it, only if no icon has yet been created,
6389 for some window managers. But with mwm it crashes.
6390 Some people say it should clear the IconPixmapHint bit in this case,
6391 but that doesn't work, and the X consortium said it isn't the
6392 right thing at all. Since there is no way to win,
6393 best to explicitly give up. */
6395 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6401 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6405 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6406 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6409 #else /* not USE_X_TOOLKIT */
6411 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6412 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6414 #endif /* not USE_X_TOOLKIT */
6418 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6422 #ifdef USE_X_TOOLKIT
6423 Window window
= XtWindow (f
->output_data
.x
->widget
);
6425 Window window
= FRAME_X_WINDOW (f
);
6428 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6429 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6430 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6432 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6436 /* Interface to fontset handler. */
6438 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6440 x_get_font_info (f
, font_idx
)
6444 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
6448 /* Return a list of names of available fonts matching PATTERN on frame
6449 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6450 to be listed. Frame F NULL means we have not yet created any
6451 frame on X, and consult the first display in x_display_list.
6452 MAXNAMES sets a limit on how many fonts to match. */
6455 x_list_fonts (f
, pattern
, size
, maxnames
)
6457 Lisp_Object pattern
;
6461 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
, tem
, second_best
;
6462 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
6463 int try_XLoadQueryFont
= 0;
6465 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6466 if (NILP (patterns
))
6467 patterns
= Fcons (pattern
, Qnil
);
6469 if (maxnames
== 1 && !size
)
6470 /* We can return any single font matching PATTERN. */
6471 try_XLoadQueryFont
= 1;
6474 /* We try at least 10 fonts because XListFonts will return
6475 auto-scaled fonts at the head. */
6476 if (maxnames
< 10) maxnames
= 10;
6479 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
6484 pattern
= XCONS (patterns
)->car
;
6485 /* See if we cached the result for this particular query.
6486 The cache is an alist of the form:
6487 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
6489 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
6490 key
= Fcons (pattern
, make_number (maxnames
)),
6491 !NILP (list
= Fassoc (key
, tem
))))
6493 list
= Fcdr_safe (list
);
6494 /* We have a cashed list. Don't have to get the list again. */
6498 /* At first, put PATTERN in the cache. */
6501 if (try_XLoadQueryFont
)
6504 unsigned long value
;
6506 font
= XLoadQueryFont (dpy
, XSTRING (pattern
)->data
);
6508 && XGetFontProperty (font
, XA_FONT
, &value
))
6510 char *name
= (char *) XGetAtomName (dpy
, (Atom
) value
);
6511 int len
= strlen (name
);
6514 /* If DXPC (a Differential X Protocol Compressor)
6515 Ver.3.7 is running, XGetAtomName will return null
6516 string. We must avoid such a name. */
6518 try_XLoadQueryFont
= 0;
6522 names
= (char **) alloca (sizeof (char *));
6523 /* Some systems only allow alloca assigned to a
6525 tmp
= (char *) alloca (len
+ 1); names
[0] = tmp
;
6526 bcopy (name
, names
[0], len
+ 1);
6531 try_XLoadQueryFont
= 0;
6534 XFreeFont (dpy
, font
);
6537 if (!try_XLoadQueryFont
)
6538 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, maxnames
,
6546 /* Make a list of all the fonts we got back.
6547 Store that in the font cache for the display. */
6548 for (i
= 0; i
< num_fonts
; i
++)
6551 int average_width
= -1, dashes
= 0, width
= 0;
6553 /* Count the number of dashes in NAMES[I]. If there are
6554 14 dashes, and the field value following 12th dash
6555 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
6556 is usually too ugly to be used for editing. Let's
6562 if (dashes
== 7) /* PIXEL_SIZE field */
6564 else if (dashes
== 12) /* AVERAGE_WIDTH field */
6565 average_width
= atoi (p
);
6567 if (dashes
< 14 || average_width
!= 0)
6569 tem
= build_string (names
[i
]);
6570 if (NILP (Fassoc (tem
, list
)))
6572 if (STRINGP (Vx_pixel_size_width_font_regexp
)
6573 && ((fast_c_string_match_ignore_case
6574 (Vx_pixel_size_width_font_regexp
, names
[i
]))
6576 /* We can set the value of PIXEL_SIZE to the
6577 width of this font. */
6578 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
6580 /* For the moment, width is not known. */
6581 list
= Fcons (Fcons (tem
, Qnil
), list
);
6585 if (!try_XLoadQueryFont
)
6586 XFreeFontNames (names
);
6589 /* Now store the result in the cache. */
6591 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
6592 = Fcons (Fcons (key
, list
),
6593 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6596 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6598 newlist
= second_best
= Qnil
;
6599 /* Make a list of the fonts that have the right width. */
6600 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
6604 tem
= XCONS (list
)->car
;
6606 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
6610 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6614 if (!INTEGERP (XCONS (tem
)->cdr
))
6616 /* Since we have not yet known the size of this font, we
6617 must try slow function call XLoadQueryFont. */
6618 XFontStruct
*thisinfo
;
6621 thisinfo
= XLoadQueryFont (dpy
,
6622 XSTRING (XCONS (tem
)->car
)->data
);
6628 = (thisinfo
->min_bounds
.width
== 0
6630 : make_number (thisinfo
->max_bounds
.width
));
6631 XFreeFont (dpy
, thisinfo
);
6634 /* For unknown reason, the previous call of XListFont had
6635 retruned a font which can't be opened. Record the size
6636 as 0 not to try to open it again. */
6637 XCONS (tem
)->cdr
= make_number (0);
6640 found_size
= XINT (XCONS (tem
)->cdr
);
6641 if (found_size
== size
)
6642 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6643 else if (found_size
> 0)
6645 if (NILP (second_best
))
6647 else if (found_size
< size
)
6649 if (XINT (XCONS (second_best
)->cdr
) > size
6650 || XINT (XCONS (second_best
)->cdr
) < found_size
)
6655 if (XINT (XCONS (second_best
)->cdr
) > size
6656 && XINT (XCONS (second_best
)->cdr
) > found_size
)
6661 if (!NILP (newlist
))
6663 else if (!NILP (second_best
))
6665 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6673 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6674 pointer to the structure font_info while allocating it dynamically.
6675 If SIZE is 0, load any size of font.
6676 If loading is failed, return NULL. */
6679 x_load_font (f
, fontname
, size
)
6681 register char *fontname
;
6684 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6685 Lisp_Object font_names
;
6687 /* Get a list of all the fonts that match this name. Once we
6688 have a list of matching fonts, we compare them against the fonts
6689 we already have by comparing names. */
6690 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 1);
6692 if (!NILP (font_names
))
6697 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6698 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
6699 if (!strcmp (dpyinfo
->font_table
[i
].name
,
6700 XSTRING (XCONS (tail
)->car
)->data
)
6701 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6702 XSTRING (XCONS (tail
)->car
)->data
))
6703 return (dpyinfo
->font_table
+ i
);
6706 /* Load the font and add it to the table. */
6710 struct font_info
*fontp
;
6711 unsigned long value
;
6713 /* If we have found fonts by x_list_font, load one of them. If
6714 not, we still try to load a font by the name given as FONTNAME
6715 because XListFonts (called in x_list_font) of some X server has
6716 a bug of not finding a font even if the font surely exists and
6717 is loadable by XLoadQueryFont. */
6718 if (size
> 0 && !NILP (font_names
))
6719 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
6722 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
6727 /* Do we need to create the table? */
6728 if (dpyinfo
->font_table_size
== 0)
6730 dpyinfo
->font_table_size
= 16;
6732 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
6733 * sizeof (struct font_info
));
6735 /* Do we need to grow the table? */
6736 else if (dpyinfo
->n_fonts
6737 >= dpyinfo
->font_table_size
)
6739 dpyinfo
->font_table_size
*= 2;
6741 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
6742 (dpyinfo
->font_table_size
6743 * sizeof (struct font_info
)));
6746 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
6748 /* Now fill in the slots of *FONTP. */
6751 fontp
->font_idx
= dpyinfo
->n_fonts
;
6752 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
6753 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
6755 /* Try to get the full name of FONT. Put it in FULL_NAME. */
6757 if (XGetFontProperty (font
, XA_FONT
, &value
))
6759 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
6763 /* Count the number of dashes in the "full name".
6764 If it is too few, this isn't really the font's full name,
6766 In X11R4, the fonts did not come with their canonical names
6777 full_name
= (char *) xmalloc (p
- name
+ 1);
6778 bcopy (name
, full_name
, p
- name
+ 1);
6785 fontp
->full_name
= full_name
;
6787 fontp
->full_name
= fontp
->name
;
6789 fontp
->size
= font
->max_bounds
.width
;
6790 fontp
->height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6792 if (NILP (font_names
))
6794 /* We come here because of a bug of XListFonts mentioned at
6795 the head of this block. Let's store this information in
6796 the cache for x_list_fonts. */
6797 Lisp_Object lispy_name
= build_string (fontname
);
6798 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
6800 XCONS (dpyinfo
->name_list_element
)->cdr
6801 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
6802 Fcons (Fcons (lispy_full_name
,
6803 make_number (fontp
->size
)),
6805 XCONS (dpyinfo
->name_list_element
)->cdr
);
6807 XCONS (dpyinfo
->name_list_element
)->cdr
6808 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
6809 Fcons (Fcons (lispy_full_name
,
6810 make_number (fontp
->size
)),
6812 XCONS (dpyinfo
->name_list_element
)->cdr
);
6815 /* The slot `encoding' specifies how to map a character
6816 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6817 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
6818 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
6819 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
6820 2:0xA020..0xFF7F). For the moment, we don't know which charset
6821 uses this font. So, we set informatoin in fontp->encoding[1]
6822 which is never used by any charset. If mapping can't be
6823 decided, set FONT_ENCODING_NOT_DECIDED. */
6825 = (font
->max_byte1
== 0
6827 ? (font
->min_char_or_byte2
< 0x80
6828 ? (font
->max_char_or_byte2
< 0x80
6829 ? 0 /* 0x20..0x7F */
6830 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6831 : 1) /* 0xA0..0xFF */
6833 : (font
->min_byte1
< 0x80
6834 ? (font
->max_byte1
< 0x80
6835 ? (font
->min_char_or_byte2
< 0x80
6836 ? (font
->max_char_or_byte2
< 0x80
6837 ? 0 /* 0x2020..0x7F7F */
6838 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6839 : 3) /* 0x20A0..0x7FFF */
6840 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6841 : (font
->min_char_or_byte2
< 0x80
6842 ? (font
->max_char_or_byte2
< 0x80
6843 ? 2 /* 0xA020..0xFF7F */
6844 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6845 : 1))); /* 0xA0A0..0xFFFF */
6847 fontp
->baseline_offset
6848 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6849 ? (long) value
: 0);
6850 fontp
->relative_compose
6851 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6852 ? (long) value
: 0);
6853 fontp
->default_ascent
6854 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6855 ? (long) value
: 0);
6864 /* Return a pointer to struct font_info of a font named FONTNAME for frame F.
6865 If no such font is loaded, return NULL. */
6867 x_query_font (f
, fontname
)
6869 register char *fontname
;
6871 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6874 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6875 if (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6876 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
))
6877 return (dpyinfo
->font_table
+ i
);
6881 /* Find a CCL program for a font specified by FONTP, and set the memer
6882 `encoder' of the structure. */
6885 x_find_ccl_program (fontp
)
6886 struct font_info
*fontp
;
6888 extern Lisp_Object Vfont_ccl_encoder_alist
, Vccl_program_table
;
6889 extern Lisp_Object Qccl_program_idx
;
6890 extern Lisp_Object
resolve_symbol_ccl_program ();
6891 Lisp_Object list
, elt
, ccl_prog
, ccl_id
;
6893 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCONS (list
)->cdr
)
6895 elt
= XCONS (list
)->car
;
6897 && STRINGP (XCONS (elt
)->car
)
6898 && (fast_c_string_match_ignore_case (XCONS (elt
)->car
, fontp
->name
)
6901 if (SYMBOLP (XCONS (elt
)->cdr
) &&
6902 (!NILP (ccl_id
= Fget (XCONS (elt
)->cdr
, Qccl_program_idx
))))
6904 ccl_prog
= XVECTOR (Vccl_program_table
)->contents
[XUINT (ccl_id
)];
6905 if (!CONSP (ccl_prog
)) continue;
6906 ccl_prog
= XCONS (ccl_prog
)->cdr
;
6910 ccl_prog
= XCONS (elt
)->cdr
;
6911 if (!VECTORP (ccl_prog
)) continue;
6915 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6916 setup_ccl_program (fontp
->font_encoder
,
6917 resolve_symbol_ccl_program (ccl_prog
));
6924 /* Initialization. */
6926 #ifdef USE_X_TOOLKIT
6927 static XrmOptionDescRec emacs_options
[] = {
6928 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6929 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6931 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6932 XrmoptionSepArg
, NULL
},
6933 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6935 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6936 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6937 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6938 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6939 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6940 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6941 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6943 #endif /* USE_X_TOOLKIT */
6945 static int x_initialized
;
6948 /* Test whether two display-name strings agree up to the dot that separates
6949 the screen number from the server number. */
6951 same_x_server (name1
, name2
)
6952 char *name1
, *name2
;
6955 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
6959 if (seen_colon
&& *name1
== '.')
6963 && (*name1
== '.' || *name1
== '\0')
6964 && (*name2
== '.' || *name2
== '\0'));
6968 #if defined (HAVE_X_I18N) || (defined (USE_X_TOOLKIT) && defined (HAVE_X11XTR6))
6969 /* Recover from setlocale (LC_ALL, ""). */
6973 /* Currently we require strerror to use the "C" locale,
6974 since we don't yet support decoding its string result. */
6976 setlocale (LC_MESSAGES
, "C");
6979 /* The Emacs Lisp reader needs LC_NUMERIC to be "C",
6980 so that numbers are read and printed properly for Emacs Lisp. */
6981 setlocale (LC_NUMERIC
, "C");
6983 /* Currently we require strftime to use the "C" locale,
6984 since we don't yet support encoding its format argument,
6985 or decoding its string result. */
6986 setlocale (LC_TIME
, "C");
6990 struct x_display_info
*
6991 x_term_init (display_name
, xrm_option
, resource_name
)
6992 Lisp_Object display_name
;
6994 char *resource_name
;
7000 struct x_display_info
*dpyinfo
;
7012 setlocale (LC_ALL
, "");
7016 #ifdef USE_X_TOOLKIT
7017 /* weiner@footloose.sps.mot.com reports that this causes
7019 X protocol error: BadAtom (invalid Atom parameter)
7020 on protocol request 18skiloaf.
7021 So let's not use it until R6. */
7023 XtSetLanguageProc (NULL
, NULL
, NULL
);
7034 argv
[argc
++] = "-xrm";
7035 argv
[argc
++] = xrm_option
;
7037 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
7038 resource_name
, EMACS_CLASS
,
7039 emacs_options
, XtNumber (emacs_options
),
7043 /* I think this is to compensate for XtSetLanguageProc. */
7048 #else /* not USE_X_TOOLKIT */
7050 XSetLocaleModifiers ("");
7052 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
7053 #endif /* not USE_X_TOOLKIT */
7055 /* Detect failure. */
7062 /* We have definitely succeeded. Record the new connection. */
7064 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
7068 struct x_display_info
*share
;
7071 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
7072 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
7073 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
7074 XSTRING (display_name
)->data
))
7077 dpyinfo
->kboard
= share
->kboard
;
7080 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
7081 init_kboard (dpyinfo
->kboard
);
7082 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
7084 char *vendor
= ServerVendor (dpy
);
7085 dpyinfo
->kboard
->Vsystem_key_alist
7086 = call1 (Qvendor_specific_keysyms
,
7087 build_string (vendor
? vendor
: ""));
7090 dpyinfo
->kboard
->next_kboard
= all_kboards
;
7091 all_kboards
= dpyinfo
->kboard
;
7092 /* Don't let the initial kboard remain current longer than necessary.
7093 That would cause problems if a file loaded on startup tries to
7094 prompt in the minibuffer. */
7095 if (current_kboard
== initial_kboard
)
7096 current_kboard
= dpyinfo
->kboard
;
7098 dpyinfo
->kboard
->reference_count
++;
7102 /* Put this display on the chain. */
7103 dpyinfo
->next
= x_display_list
;
7104 x_display_list
= dpyinfo
;
7106 /* Put it on x_display_name_list as well, to keep them parallel. */
7107 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
7108 x_display_name_list
);
7109 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
7111 dpyinfo
->display
= dpy
;
7114 XSetAfterFunction (x_current_display
, x_trace_wire
);
7118 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
7119 + STRING_BYTES (XSTRING (Vsystem_name
))
7121 sprintf (dpyinfo
->x_id_name
, "%s@%s",
7122 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
7124 /* Figure out which modifier bits mean what. */
7125 x_find_modifier_meanings (dpyinfo
);
7127 /* Get the scroll bar cursor. */
7128 dpyinfo
->vertical_scroll_bar_cursor
7129 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
7131 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
7132 resource_name
, EMACS_CLASS
);
7133 #ifdef HAVE_XRMSETDATABASE
7134 XrmSetDatabase (dpyinfo
->display
, xrdb
);
7136 dpyinfo
->display
->db
= xrdb
;
7138 /* Put the rdb where we can find it in a way that works on
7140 dpyinfo
->xrdb
= xrdb
;
7142 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
7143 DefaultScreen (dpyinfo
->display
));
7144 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
7145 &dpyinfo
->n_planes
);
7146 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
7147 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
7148 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
7149 dpyinfo
->grabbed
= 0;
7150 dpyinfo
->reference_count
= 0;
7151 dpyinfo
->icon_bitmap_id
= -1;
7152 dpyinfo
->n_fonts
= 0;
7153 dpyinfo
->font_table_size
= 0;
7154 dpyinfo
->bitmaps
= 0;
7155 dpyinfo
->bitmaps_size
= 0;
7156 dpyinfo
->bitmaps_last
= 0;
7157 dpyinfo
->scratch_cursor_gc
= 0;
7158 dpyinfo
->mouse_face_mouse_frame
= 0;
7159 dpyinfo
->mouse_face_deferred_gc
= 0;
7160 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7161 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7162 dpyinfo
->mouse_face_face_id
= 0;
7163 dpyinfo
->mouse_face_window
= Qnil
;
7164 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
7165 dpyinfo
->mouse_face_defer
= 0;
7166 dpyinfo
->x_focus_frame
= 0;
7167 dpyinfo
->x_focus_event_frame
= 0;
7168 dpyinfo
->x_highlight_frame
= 0;
7170 dpyinfo
->Xatom_wm_protocols
7171 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
7172 dpyinfo
->Xatom_wm_take_focus
7173 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
7174 dpyinfo
->Xatom_wm_save_yourself
7175 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
7176 dpyinfo
->Xatom_wm_delete_window
7177 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
7178 dpyinfo
->Xatom_wm_change_state
7179 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
7180 dpyinfo
->Xatom_wm_configure_denied
7181 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
7182 dpyinfo
->Xatom_wm_window_moved
7183 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
7184 dpyinfo
->Xatom_editres
7185 = XInternAtom (dpyinfo
->display
, "Editres", False
);
7186 dpyinfo
->Xatom_CLIPBOARD
7187 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
7188 dpyinfo
->Xatom_TIMESTAMP
7189 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
7191 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
7192 dpyinfo
->Xatom_COMPOUND_TEXT
7193 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
7194 dpyinfo
->Xatom_DELETE
7195 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
7196 dpyinfo
->Xatom_MULTIPLE
7197 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
7199 = XInternAtom (dpyinfo
->display
, "INCR", False
);
7200 dpyinfo
->Xatom_EMACS_TMP
7201 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
7202 dpyinfo
->Xatom_TARGETS
7203 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
7205 = XInternAtom (dpyinfo
->display
, "NULL", False
);
7206 dpyinfo
->Xatom_ATOM_PAIR
7207 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
7208 /* For properties of font. */
7209 dpyinfo
->Xatom_PIXEL_SIZE
7210 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
7211 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
7212 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
7213 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
7214 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
7215 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
7216 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
7218 dpyinfo
->cut_buffers_initialized
= 0;
7220 connection
= ConnectionNumber (dpyinfo
->display
);
7221 dpyinfo
->connection
= connection
;
7226 null_bits
[0] = 0x00;
7229 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
7230 null_bits
, 1, 1, (long) 0, (long) 0,
7235 /* This is only needed for distinguishing keyboard and process input. */
7236 if (connection
!= 0)
7237 add_keyboard_wait_descriptor (connection
);
7240 #ifndef F_SETOWN_BUG
7242 #ifdef F_SETOWN_SOCK_NEG
7243 /* stdin is a socket here */
7244 fcntl (connection
, F_SETOWN
, -getpid ());
7245 #else /* ! defined (F_SETOWN_SOCK_NEG) */
7246 fcntl (connection
, F_SETOWN
, getpid ());
7247 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
7248 #endif /* ! defined (F_SETOWN) */
7249 #endif /* F_SETOWN_BUG */
7252 if (interrupt_input
)
7253 init_sigio (connection
);
7254 #endif /* ! defined (SIGIO) */
7257 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
7258 /* Make sure that we have a valid font for dialog boxes
7259 so that Xt does not crash. */
7261 Display
*dpy
= dpyinfo
->display
;
7266 d
.addr
= (XPointer
)&dpy
;
7267 d
.size
= sizeof (Display
*);
7268 fr
.addr
= XtDefaultFont
;
7269 fr
.size
= sizeof (XtDefaultFont
);
7270 to
.size
= sizeof (Font
*);
7271 to
.addr
= (XPointer
)&font
;
7272 count
= x_catch_errors (dpy
);
7273 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
7275 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
7276 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
7277 x_uncatch_errors (dpy
, count
);
7288 /* Get rid of display DPYINFO, assuming all frames are already gone,
7289 and without sending any more commands to the X server. */
7292 x_delete_display (dpyinfo
)
7293 struct x_display_info
*dpyinfo
;
7295 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
7297 /* Discard this display from x_display_name_list and x_display_list.
7298 We can't use Fdelq because that can quit. */
7299 if (! NILP (x_display_name_list
)
7300 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
7301 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
7306 tail
= x_display_name_list
;
7307 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
7309 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
7310 dpyinfo
->name_list_element
))
7312 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
7315 tail
= XCONS (tail
)->cdr
;
7319 if (x_display_list
== dpyinfo
)
7320 x_display_list
= dpyinfo
->next
;
7323 struct x_display_info
*tail
;
7325 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
7326 if (tail
->next
== dpyinfo
)
7327 tail
->next
= tail
->next
->next
;
7330 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
7331 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
7332 XrmDestroyDatabase (dpyinfo
->xrdb
);
7336 if (--dpyinfo
->kboard
->reference_count
== 0)
7337 delete_kboard (dpyinfo
->kboard
);
7339 xfree (dpyinfo
->font_table
);
7340 xfree (dpyinfo
->x_id_name
);
7344 /* Set up use of X before we make the first connection. */
7349 clear_frame_hook
= XTclear_frame
;
7350 clear_end_of_line_hook
= XTclear_end_of_line
;
7351 ins_del_lines_hook
= XTins_del_lines
;
7352 change_line_highlight_hook
= XTchange_line_highlight
;
7353 insert_glyphs_hook
= XTinsert_glyphs
;
7354 write_glyphs_hook
= XTwrite_glyphs
;
7355 delete_glyphs_hook
= XTdelete_glyphs
;
7356 ring_bell_hook
= XTring_bell
;
7357 reset_terminal_modes_hook
= XTreset_terminal_modes
;
7358 set_terminal_modes_hook
= XTset_terminal_modes
;
7359 update_begin_hook
= XTupdate_begin
;
7360 update_end_hook
= XTupdate_end
;
7361 set_terminal_window_hook
= XTset_terminal_window
;
7362 read_socket_hook
= XTread_socket
;
7363 frame_up_to_date_hook
= XTframe_up_to_date
;
7364 cursor_to_hook
= XTcursor_to
;
7365 reassert_line_highlight_hook
= XTreassert_line_highlight
;
7366 mouse_position_hook
= XTmouse_position
;
7367 frame_rehighlight_hook
= XTframe_rehighlight
;
7368 frame_raise_lower_hook
= XTframe_raise_lower
;
7369 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
7370 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
7371 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
7372 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
7374 scroll_region_ok
= 1; /* we'll scroll partial frames */
7375 char_ins_del_ok
= 0; /* just as fast to write the line */
7376 line_ins_del_ok
= 1; /* we'll just blt 'em */
7377 fast_clear_end_of_line
= 1; /* X does this well */
7378 memory_below_frame
= 0; /* we don't remember what scrolls
7384 /* Try to use interrupt input; if we can't, then start polling. */
7385 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
7387 #ifdef USE_X_TOOLKIT
7388 XtToolkitInitialize ();
7389 Xt_app_con
= XtCreateApplicationContext ();
7390 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
7393 /* Note that there is no real way portable across R3/R4 to get the
7394 original error handler. */
7395 XSetErrorHandler (x_error_handler
);
7396 XSetIOErrorHandler (x_io_error_quitter
);
7398 /* Disable Window Change signals; they are handled by X events. */
7400 signal (SIGWINCH
, SIG_DFL
);
7401 #endif /* ! defined (SIGWINCH) */
7403 signal (SIGPIPE
, x_connection_signal
);
7409 staticpro (&x_error_message_string
);
7410 x_error_message_string
= Qnil
;
7412 staticpro (&x_display_name_list
);
7413 x_display_name_list
= Qnil
;
7415 staticpro (&last_mouse_scroll_bar
);
7416 last_mouse_scroll_bar
= Qnil
;
7418 staticpro (&Qvendor_specific_keysyms
);
7419 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
7421 staticpro (&last_mouse_press_frame
);
7422 last_mouse_press_frame
= Qnil
;
7425 #endif /* not HAVE_X_WINDOWS */