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 (gidx
== 0) XSETFASTINT (first_ch
, ch
);
584 charset
= CHAR_CHARSET (ch
);
585 if (charset
== CHARSET_COMPOSITION
)
587 /* We must draw components of the composite character on the
589 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
591 /* Set the face in the slot for work. */
592 cmpcharp
->face_work
= cf
;
594 /* We don't need the return value ... */
595 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
596 hl
, just_foreground
, cmpcharp
);
597 /* ... because the width of just drawn text can be
598 calculated as follows. */
599 left
+= FONT_WIDTH (f
->output_data
.x
->font
) * cmpcharp
->width
;
602 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
607 /* Find the run of consecutive glyphs which can be drawn with
608 the same GC (i.e. the same charset and the same face-code).
609 Extract their character codes into X_2BYTE_BUFFER.
610 If CMPCHARP is not NULL, face-code is not checked because we
611 use only the face specified in `cmpcharp->face_work'. */
615 int this_charset
, c1
, c2
;
618 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
619 ch
= FAST_GLYPH_CHAR (g
);
620 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
621 if (this_charset
!= charset
622 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
626 cp
->byte1
= c1
, cp
->byte2
= c2
;
628 cp
->byte1
= 0, cp
->byte2
= c1
;
631 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
635 /* LEN gets the length of the run. */
636 len
= cp
- x_2byte_buffer
;
637 /* Now output this run of chars, with the font and pixel values
638 determined by the face code CF. */
640 struct face
*face
= FRAME_DEFAULT_FACE (f
);
641 XFontStruct
*font
= NULL
;
644 int line_height
= f
->output_data
.x
->line_height
;
645 /* Pixel width of each glyph in this run. */
647 = (FONT_WIDTH (f
->output_data
.x
->font
)
648 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
649 /* Overall pixel width of this run. */
651 = (FONT_WIDTH (f
->output_data
.x
->font
)
652 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
653 /* A flag to tell if we have already filled background. We
654 fill background in advance in the following cases:
655 1) A face has stipple.
656 2) A height of font is shorter than LINE_HEIGHT.
657 3) Drawing a composite character.
658 4) Font has non-zero _MULE_BASELINE_OFFSET property.
659 After filling background, we draw glyphs by XDrawString16. */
660 int background_filled
;
661 /* Baseline position of a character, offset from TOP. */
663 /* The property value of `_MULE_RELATIVE_COMPOSE' and
664 `_MULE_DEFAULT_ASCENT'. */
665 int relative_compose
= 0, default_ascent
= 0;
666 /* 1 if we find no font or a font of inappropriate size. */
667 int require_clipping
;
669 /* HL = 3 means use a mouse face previously chosen. */
671 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
673 /* First look at the face of the text itself. */
676 /* It's possible for the display table to specify
677 a face code that is out of range. Use 0 in that case. */
678 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
679 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
683 face
= FRAME_MODE_LINE_FACE (f
);
685 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
686 if (FACE_STIPPLE (face
))
690 /* Then comes the distinction between modeline and normal text. */
695 face
= FRAME_MODE_LINE_FACE (f
);
696 if (FACE_STIPPLE (face
))
700 #define FACE_DEFAULT (~0)
702 /* Setting appropriate font and gc for this charset. */
703 if (charset
!= CHARSET_ASCII
)
706 int fontset
= FACE_FONTSET (face
);
707 struct font_info
*fontp
;
709 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
710 || !(fontp
= FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
711 charset
, NULL
, fontset
)))
714 font
= (XFontStruct
*) (fontp
->font
);
715 gc
= FACE_NON_ASCII_GC (face
);
716 XSetFont (FRAME_X_DISPLAY (f
), gc
, font
->fid
);
718 = (font
->max_byte1
!= 0
719 ? (line_height
+ font
->ascent
- font
->descent
) / 2
720 : f
->output_data
.x
->font_baseline
- fontp
->baseline_offset
);
721 if (FONT_HEIGHT (font
) <= line_height
722 && (font
->ascent
> baseline
723 || font
->descent
> line_height
- baseline
))
724 /* Adjust baseline for this font to show the whole
726 baseline
= line_height
- font
->descent
;
728 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
730 relative_compose
= fontp
->relative_compose
;
731 default_ascent
= fontp
->default_ascent
;
734 /* We have to change code points in the following cases. */
735 if (fontp
->font_encoder
)
737 /* This font requires CCL program to calculate code
738 point of characters. */
739 struct ccl_program
*ccl
= fontp
->font_encoder
;
741 if (CHARSET_DIMENSION (charset
) == 1)
742 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
744 ccl
->reg
[0] = charset
;
745 ccl
->reg
[1] = cp
->byte2
;
746 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
747 /* We assume that MSBs are appropriately
748 set/reset by CCL program. */
749 if (font
->max_byte1
== 0) /* 1-byte font */
750 cp
->byte2
= ccl
->reg
[1];
752 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
755 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
757 ccl
->reg
[0] = charset
;
758 ccl
->reg
[1] = cp
->byte1
, ccl
->reg
[2] = cp
->byte2
;
759 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
760 /* We assume that MSBs are appropriately
761 set/reset by CCL program. */
762 if (font
->max_byte1
== 0) /* 1-byte font */
763 cp
->byte2
= ccl
->reg
[1];
765 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
768 else if (fontp
->encoding
[charset
])
770 int enc
= fontp
->encoding
[charset
];
772 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
773 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
775 if (enc
== 1 || enc
== 3)
776 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
783 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
785 font
= FACE_FONT (face
);
786 if (font
== (XFontStruct
*) FACE_DEFAULT
)
787 font
= f
->output_data
.x
->font
;
788 baseline
= FONT_BASE (f
->output_data
.x
->font
);
789 if (charset
== charset_latin_iso8859_1
)
791 if (font
->max_char_or_byte2
< 0x80)
792 /* This font can't display Latin1 characters. */
796 for (cp
= x_2byte_buffer
; cp
< x_2byte_buffer
+ len
; cp
++)
804 /* Now override that if the cursor's on this character. */
807 /* The cursor overrides stippling. */
810 if (font
== f
->output_data
.x
->font
811 && face
->background
== f
->output_data
.x
->background_pixel
812 && face
->foreground
== f
->output_data
.x
->foreground_pixel
815 gc
= f
->output_data
.x
->cursor_gc
;
817 /* Cursor on non-default face: must merge. */
823 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
824 xgcv
.foreground
= face
->background
;
825 /* If the glyph would be invisible,
826 try a different foreground. */
827 if (xgcv
.foreground
== xgcv
.background
)
828 xgcv
.foreground
= face
->foreground
;
829 if (xgcv
.foreground
== xgcv
.background
)
830 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
831 if (xgcv
.foreground
== xgcv
.background
)
832 xgcv
.foreground
= face
->foreground
;
833 /* Make sure the cursor is distinct from text in this face. */
834 if (xgcv
.background
== face
->background
835 && xgcv
.foreground
== face
->foreground
)
837 xgcv
.background
= face
->foreground
;
838 xgcv
.foreground
= face
->background
;
841 xgcv
.font
= font
->fid
;
843 xgcv
.font
= FACE_FONT (face
)->fid
;
844 xgcv
.graphics_exposures
= 0;
845 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
846 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
847 XChangeGC (FRAME_X_DISPLAY (f
),
848 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
851 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
852 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
853 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
855 /* If this code is restored, it must also reset to the default stipple
857 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
858 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
864 require_clipping
= (!NILP (Vclip_large_size_font
)
865 && (font
->ascent
> baseline
866 || font
->descent
> line_height
- baseline
868 && FONT_WIDTH (font
) > glyph_width
)));
870 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
871 background_filled
= 1;
874 /* Turn stipple on. */
875 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
877 /* Draw stipple or background color on background. */
878 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
879 left
, top
, run_width
, line_height
);
881 /* Turn stipple off. */
882 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
884 background_filled
= 1;
887 || FONT_HEIGHT (font
) < line_height
888 || FONT_WIDTH (font
) < glyph_width
891 /* Fill a area for the current run in background pixle of GC. */
893 unsigned long mask
= GCForeground
| GCBackground
| GCFillStyle
;
895 /* The current code at first set foreground to background,
896 fill the area, then recover the original foreground.
897 Aren't there any smarter ways? */
899 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
900 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
901 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
902 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
903 left
, top
, run_width
, line_height
);
904 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
906 background_filled
= 1;
908 /* To assure not to fill background while drawing
909 remaining components. */
913 background_filled
= 0;
917 if (require_clipping
)
919 Region region
; /* Region used for setting clip mask to GC. */
920 XPoint x
[4]; /* Data used for creating REGION. */
922 x
[0].x
= x
[3].x
= left
, x
[1].x
= x
[2].x
= left
+ glyph_width
;
923 x
[0].y
= x
[1].y
= top
, x
[2].y
= x
[3].y
= top
+ line_height
;
924 region
= XPolygonRegion (x
, 4, EvenOddRule
);
925 XSetRegion (FRAME_X_DISPLAY (f
), gc
, region
);
926 XDestroyRegion (region
);
931 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
)
932 for (i
= 0; i
< len
; i
++)
934 if (require_clipping
&& i
> 0)
935 XSetClipOrigin (FRAME_X_DISPLAY (f
), gc
,
937 if (background_filled
)
938 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
939 left
+ glyph_width
* i
,
940 top
+ baseline
, x_2byte_buffer
+ i
, 1);
942 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
943 left
+ glyph_width
* i
,
944 top
+ baseline
, x_2byte_buffer
+ i
, 1);
948 /* See if this whole buffer can be output as 8-bit chars.
949 If so, copy x_2byte_buffer to x_1byte_buffer
950 and do it as 8-bit chars. */
951 for (i
= 0; i
< len
; i
++)
953 if (x_2byte_buffer
[i
].byte1
!= 0)
955 x_1byte_buffer
[i
] = x_2byte_buffer
[i
].byte2
;
960 if (background_filled
)
961 XDrawString (FRAME_X_DISPLAY (f
), window
, gc
,
962 left
, top
+ baseline
, x_1byte_buffer
, len
);
964 XDrawImageString (FRAME_X_DISPLAY (f
), window
, gc
,
965 left
, top
+ baseline
, x_1byte_buffer
, len
);
969 /* We can't output them as 8-bit chars,
970 so do it as 16-bit chars. */
972 if (background_filled
)
973 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
974 left
, top
+ baseline
, x_2byte_buffer
, len
);
976 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
977 left
, top
+ baseline
, x_2byte_buffer
, len
);
983 /* Handle composite characters. */
984 XCharStruct
*pcm
; /* Pointer to per char metric info. */
986 if ((cmpcharp
->cmp_rule
|| relative_compose
)
989 /* This is the first character. Initialize variables.
990 HIGHEST is the highest position of glyphs ever
991 written, LOWEST the lowest position. */
995 && CHAR_TABLE_P (Vuse_default_ascent
)
996 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
998 highest
= default_ascent
;
1003 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
);
1004 highest
= pcm
->ascent
+ 1;
1005 lowest
= - pcm
->descent
;
1008 if (cmpcharp
->cmp_rule
)
1009 x_offset
= (cmpcharp
->col_offset
[0]
1010 * FONT_WIDTH (f
->output_data
.x
->font
));
1011 /* Draw the first character at the normal position. */
1012 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1013 left
+ x_offset
, top
+ baseline
, x_2byte_buffer
, 1);
1020 for (; i
< len
; i
++, gidx
++)
1022 int x_offset
= 0, y_offset
= 0;
1024 if (relative_compose
)
1026 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1027 if (NILP (Vignore_relative_composition
)
1028 || NILP (Faref (Vignore_relative_composition
,
1029 make_number (cmpcharp
->glyph
[gidx
]))))
1031 if (- pcm
->descent
>= relative_compose
)
1033 /* Draw above the current glyphs. */
1034 y_offset
= highest
+ pcm
->descent
;
1035 highest
+= pcm
->ascent
+ pcm
->descent
;
1037 else if (pcm
->ascent
<= 0)
1039 /* Draw beneath the current glyphs. */
1040 y_offset
= lowest
- pcm
->ascent
;
1041 lowest
-= pcm
->ascent
+ pcm
->descent
;
1046 /* Draw the glyph at normal position. If
1047 it sticks out of HIGHEST or LOWEST,
1048 update them appropriately. */
1049 if (pcm
->ascent
> highest
)
1050 highest
= pcm
->ascent
;
1051 else if (- pcm
->descent
< lowest
)
1052 lowest
= - pcm
->descent
;
1055 else if (cmpcharp
->cmp_rule
)
1057 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
1058 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
1061 /* Re-encode GREF and NREF so that they specify
1062 only Y-axis information:
1063 0:top, 1:base, 2:bottom, 3:center */
1064 gref
= gref
/ 3 + (gref
== 4) * 2;
1065 nref
= nref
/ 3 + (nref
== 4) * 2;
1067 pcm
= PER_CHAR_METRIC (font
, x_2byte_buffer
+ i
);
1068 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1069 : gref
== 2 ? lowest
1070 : (highest
+ lowest
) / 2)
1071 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
1072 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
1073 : (pcm
->ascent
+ pcm
->descent
) / 2));
1074 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
1077 if (bottom
< lowest
)
1079 y_offset
= bottom
+ pcm
->descent
;
1080 x_offset
= (cmpcharp
->col_offset
[gidx
]
1081 * FONT_WIDTH (f
->output_data
.x
->font
));
1083 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1084 left
+ x_offset
, top
+ baseline
- y_offset
,
1085 x_2byte_buffer
+ i
, 1);
1088 if (require_clipping
)
1089 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
1091 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
1092 which often is not up to date yet. */
1093 if (!just_foreground
)
1095 if (left
== orig_left
)
1096 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
1097 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1099 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
1100 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1106 /* Show rectangles to indicate that we found no font. */
1107 int limit
= cmpcharp
? 1 : len
;
1109 for (i
= 0; i
< limit
; i
++)
1110 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1111 left
+ glyph_width
* i
, top
,
1112 glyph_width
- 1, line_height
- 1);
1114 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1116 /* Show ??? to indicate that we found a font of
1117 inappropriate size. */
1118 int limit
= cmpcharp
? 1 : len
;
1120 for (i
= 0; i
< limit
; i
++)
1122 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1123 left
+ glyph_width
* i
, top
+ line_height
- 1,
1124 left
+ glyph_width
* i
+ 1, top
+ line_height
- 1);
1125 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1126 left
+ glyph_width
* i
, top
+ line_height
- 3,
1127 left
+ glyph_width
* i
, top
+ line_height
- 1);
1131 /* We should probably check for XA_UNDERLINE_POSITION and
1132 XA_UNDERLINE_THICKNESS properties on the font, but let's
1133 just get the thing working, and come back to that. */
1135 /* Setting underline position based on the metric of the
1136 current font results in shaky underline if it strides
1137 over different fonts. So, we set the position based only
1138 on the default font of this frame. */
1139 int underline_position
= f
->output_data
.x
->font_baseline
+ 1;
1141 if (underline_position
>= line_height
)
1142 underline_position
= line_height
- 1;
1144 if (face
->underline
)
1145 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1147 left
, top
+ underline_position
, run_width
, 1);
1155 return (left
- orig_left
);
1160 /* This is the old single-face code. */
1163 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
1166 register GLYPH
*gp
; /* Points to first GLYPH. */
1167 register int n
; /* Number of glyphs to display. */
1172 Window window
= FRAME_X_WINDOW (f
);
1173 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
1174 : (hl
? f
->output_data
.x
->reverse_gc
1175 : f
->output_data
.x
->normal_gc
));
1177 if (sizeof (GLYPH
) == sizeof (XChar2b
))
1178 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1179 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
1180 else if (sizeof (GLYPH
) == sizeof (unsigned char))
1181 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1182 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
1184 /* What size of glyph ARE you using? And does X have a function to
1190 /* Output some text at the nominal frame cursor position.
1191 Advance the cursor over the text.
1192 Output LEN glyphs at START.
1194 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
1195 controls the pixel values used for foreground and background. */
1198 XTwrite_glyphs (start
, len
)
1199 register GLYPH
*start
;
1202 register int temp_length
;
1213 /* If not within an update,
1214 output at the frame's visible cursor. */
1215 curs_x
= FRAME_CURSOR_X (f
);
1216 curs_y
= FRAME_CURSOR_Y (f
);
1220 CHAR_TO_PIXEL_COL (f
, curs_x
),
1221 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1222 start
, len
, highlight
, 0, NULL
);
1224 /* If we drew on top of the cursor, note that it is turned off. */
1225 if (curs_y
== f
->phys_cursor_y
1226 && curs_x
<= f
->phys_cursor_x
1227 && curs_x
+ len
> f
->phys_cursor_x
)
1228 f
->phys_cursor_on
= 0;
1231 if (curs_x
>= FRAME_CURSOR_X_LIMIT (f
))
1232 curs_x
= FRAME_CURSOR_X_LIMIT (f
) - 1;
1234 if (updating_frame
== 0)
1235 x_display_cursor (f
, 1, curs_x
, FRAME_CURSOR_Y (f
));
1241 /* Clear to the end of the line.
1242 Erase the current text line from the nominal cursor position (inclusive)
1243 to column FIRST_UNUSED (exclusive). The idea is that everything
1244 from FIRST_UNUSED onward is already erased. */
1247 XTclear_end_of_line (first_unused
)
1248 register int first_unused
;
1250 struct frame
*f
= updating_frame
;
1256 if (curs_y
< 0 || curs_y
>= f
->height
)
1258 if (first_unused
<= 0)
1261 if (first_unused
>= FRAME_WINDOW_WIDTH (f
))
1262 first_unused
= FRAME_WINDOW_WIDTH (f
);
1264 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1270 /* Notice if the cursor will be cleared by this operation. */
1271 if (curs_y
== f
->phys_cursor_y
1272 && curs_x
<= f
->phys_cursor_x
1273 && f
->phys_cursor_x
< first_unused
)
1274 f
->phys_cursor_on
= 0;
1276 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1277 CHAR_TO_PIXEL_COL (f
, curs_x
),
1278 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1279 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
1280 f
->output_data
.x
->line_height
, False
);
1282 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
1292 struct frame
*f
= updating_frame
;
1297 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1298 curs_x
= 0; /* Nominal cursor position is top left. */
1303 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
1305 /* We have to clear the scroll bars, too. If we have changed
1306 colors or something like that, then they should be notified. */
1307 x_scroll_bar_clear (f
);
1309 XFlush (FRAME_X_DISPLAY (f
));
1314 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
1315 always contain the right glyphs to use.
1317 It also needs to be changed to look at the details of the font and
1318 see whether there is really overlap, and do nothing when there is
1319 not. This can use font_char_overlap_left and font_char_overlap_right,
1320 but just how to use them is not clear. */
1322 /* Erase the character (if any) at the position just before X, Y in frame F,
1323 then redraw it and the character before it.
1324 This is necessary when we erase starting at X,
1325 in case the character after X overlaps into the one before X.
1326 Call this function with input blocked. */
1329 redraw_previous_char (f
, x
, y
, highlight_flag
)
1334 /* Erase the character before the new ones, in case
1335 what was here before overlaps it.
1336 Reoutput that character, and the previous character
1337 (in case the previous character overlaps it). */
1340 int start_x
= x
- 2;
1343 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1344 CHAR_TO_PIXEL_COL (f
, x
- 1),
1345 CHAR_TO_PIXEL_ROW (f
, y
),
1346 FONT_WIDTH (f
->output_data
.x
->font
),
1347 f
->output_data
.x
->line_height
, False
);
1349 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
1350 CHAR_TO_PIXEL_ROW (f
, y
),
1351 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
1352 x
- start_x
, highlight_flag
, 1, NULL
);
1356 /* Erase the character (if any) at the position X, Y in frame F,
1357 then redraw it and the character after it.
1358 This is necessary when we erase endng at X,
1359 in case the character after X overlaps into the one before X.
1360 Call this function with input blocked. */
1363 redraw_following_char (f
, x
, y
, highlight_flag
)
1368 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
1369 /* Erase the character after the new ones, in case
1370 what was here before overlaps it.
1371 Reoutput that character, and the following character
1372 (in case the following character overlaps it). */
1374 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1379 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1380 CHAR_TO_PIXEL_COL (f
, x
),
1381 CHAR_TO_PIXEL_ROW (f
, y
),
1382 FONT_WIDTH (f
->output_data
.x
->font
),
1383 f
->output_data
.x
->line_height
, False
);
1385 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1386 CHAR_TO_PIXEL_ROW (f
, y
),
1387 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1388 end_x
- x
, highlight_flag
, 1, NULL
);
1393 #if 0 /* Not in use yet */
1395 /* Return 1 if character C in font F extends past its left edge. */
1398 font_char_overlap_left (font
, c
)
1404 /* Find the bounding-box info for C. */
1405 if (font
->per_char
== 0)
1406 s
= &font
->max_bounds
;
1409 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1412 /* Decode char into row number (byte 1) and code within row (byte 2). */
1415 if (!(within
>= font
->min_char_or_byte2
1416 && within
<= font
->max_char_or_byte2
1417 && row
>= font
->min_byte1
1418 && row
<= font
->max_byte1
))
1420 /* If char is out of range, try the font's default char instead. */
1421 c
= font
->default_char
;
1422 row
= c
>> (BITS_PER_INT
- 8);
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
))
1429 /* Still out of range means this char does not overlap. */
1432 /* We found the info for this char. */
1433 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1437 return (s
&& s
->lbearing
< 0);
1440 /* Return 1 if character C in font F extends past its right edge. */
1443 font_char_overlap_right (font
, c
)
1449 /* Find the bounding-box info for C. */
1450 if (font
->per_char
== 0)
1451 s
= &font
->max_bounds
;
1454 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1457 /* Decode char into row number (byte 1) and code within row (byte 2). */
1460 if (!(within
>= font
->min_char_or_byte2
1461 && within
<= font
->max_char_or_byte2
1462 && row
>= font
->min_byte1
1463 && row
<= font
->max_byte1
))
1465 /* If char is out of range, try the font's default char instead. */
1466 c
= font
->default_char
;
1467 row
= c
>> (BITS_PER_INT
- 8);
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
))
1474 /* Still out of range means this char does not overlap. */
1477 /* We found the info for this char. */
1478 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1482 return (s
&& s
->rbearing
>= s
->width
);
1486 /* Invert the middle quarter of the frame for .15 sec. */
1488 /* We use the select system call to do the waiting, so we have to make sure
1489 it's available. If it isn't, we just won't do visual bells. */
1490 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1492 /* Subtract the `struct timeval' values X and Y,
1493 storing the result in RESULT.
1494 Return 1 if the difference is negative, otherwise 0. */
1497 timeval_subtract (result
, x
, y
)
1498 struct timeval
*result
, x
, y
;
1500 /* Perform the carry for the later subtraction by updating y.
1501 This is safer because on some systems
1502 the tv_sec member is unsigned. */
1503 if (x
.tv_usec
< y
.tv_usec
)
1505 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1506 y
.tv_usec
-= 1000000 * nsec
;
1509 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1511 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1512 y
.tv_usec
+= 1000000 * nsec
;
1516 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1517 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1518 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1520 /* Return indication of whether the result should be considered negative. */
1521 return x
.tv_sec
< y
.tv_sec
;
1533 /* Create a GC that will use the GXxor function to flip foreground pixels
1534 into background pixels. */
1538 values
.function
= GXxor
;
1539 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1540 ^ f
->output_data
.x
->background_pixel
);
1542 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1543 GCFunction
| GCForeground
, &values
);
1547 /* Get the height not including a menu bar widget. */
1548 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
1549 /* Height of each line to flash. */
1550 int flash_height
= FRAME_LINE_HEIGHT (f
);
1551 /* These will be the left and right margins of the rectangles. */
1552 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1553 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
1557 /* Don't flash the area between a scroll bar and the frame
1558 edge it is next to. */
1559 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
1561 case vertical_scroll_bar_left
:
1562 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1565 case vertical_scroll_bar_right
:
1566 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1570 width
= flash_right
- flash_left
;
1572 /* If window is tall, flash top and bottom line. */
1573 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1575 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1576 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1577 width
, flash_height
);
1578 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1580 (height
- flash_height
1581 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1582 width
, flash_height
);
1585 /* If it is short, flash it all. */
1586 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1587 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1588 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1590 XFlush (FRAME_X_DISPLAY (f
));
1593 struct timeval wakeup
, now
;
1595 EMACS_GET_TIME (wakeup
);
1597 /* Compute time to wait until, propagating carry from usecs. */
1598 wakeup
.tv_usec
+= 150000;
1599 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1600 wakeup
.tv_usec
%= 1000000;
1602 /* Keep waiting until past the time wakeup. */
1605 struct timeval timeout
;
1607 EMACS_GET_TIME (timeout
);
1609 /* In effect, timeout = wakeup - timeout.
1610 Break if result would be negative. */
1611 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1614 /* Try to wait that long--but we might wake up sooner. */
1615 select (0, NULL
, NULL
, NULL
, &timeout
);
1619 /* If window is tall, flash top and bottom line. */
1620 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1622 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1623 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1624 width
, flash_height
);
1625 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1627 (height
- flash_height
1628 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1629 width
, flash_height
);
1632 /* If it is short, flash it all. */
1633 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1634 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1635 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1637 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1638 XFlush (FRAME_X_DISPLAY (f
));
1648 /* Make audible bell. */
1650 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1655 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1658 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1660 XTflash (selected_frame
);
1666 XFlush (FRAME_X_DISPLAY (selected_frame
));
1671 /* Insert and delete character.
1672 These are not supposed to be used because we are supposed to turn
1673 off the feature of using them. */
1676 XTinsert_glyphs (start
, len
)
1677 register char *start
;
1690 /* Specify how many text lines, from the top of the window,
1691 should be affected by insert-lines and delete-lines operations.
1692 This, and those operations, are used only within an update
1693 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1696 XTset_terminal_window (n
)
1699 if (updating_frame
== 0)
1702 if ((n
<= 0) || (n
> updating_frame
->height
))
1703 flexlines
= updating_frame
->height
;
1708 /* These variables need not be per frame
1709 because redisplay is done on a frame-by-frame basis
1710 and the line dance for one frame is finished before
1711 anything is done for anoter frame. */
1713 /* Array of line numbers from cached insert/delete operations.
1714 line_dance[i] is the old position of the line that we want
1715 to move to line i, or -1 if we want a blank line there. */
1716 static int *line_dance
;
1718 /* Allocated length of that array. */
1719 static int line_dance_len
;
1721 /* Flag indicating whether we've done any work. */
1722 static int line_dance_in_progress
;
1724 /* Perform an insert-lines or delete-lines operation,
1725 inserting N lines or deleting -N lines at vertical position VPOS. */
1727 XTins_del_lines (vpos
, n
)
1730 register int fence
, i
;
1732 if (vpos
>= flexlines
)
1735 if (!line_dance_in_progress
)
1737 int ht
= updating_frame
->height
;
1738 if (ht
> line_dance_len
)
1740 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1741 line_dance_len
= ht
;
1743 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1744 line_dance_in_progress
= 1;
1748 if (n
> flexlines
- vpos
)
1749 n
= flexlines
- vpos
;
1751 for (i
= flexlines
; --i
>= fence
;)
1752 line_dance
[i
] = line_dance
[i
-n
];
1753 for (i
= fence
; --i
>= vpos
;)
1759 if (n
> flexlines
- vpos
)
1760 n
= flexlines
- vpos
;
1761 fence
= flexlines
- n
;
1762 for (i
= vpos
; i
< fence
; ++i
)
1763 line_dance
[i
] = line_dance
[i
+ n
];
1764 for (i
= fence
; i
< flexlines
; ++i
)
1769 /* Here's where we actually move the pixels around.
1770 Must be called with input blocked. */
1774 register int i
, j
, distance
;
1775 register struct frame
*f
;
1779 /* Must check this flag first. If it's not set, then not only is the
1780 array uninitialized, but we might not even have a frame. */
1781 if (!line_dance_in_progress
)
1789 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1791 x_update_cursor (updating_frame
, 0);
1793 for (i
= 0; i
< ht
; ++i
)
1794 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1796 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1797 && line_dance
[j
]-j
== distance
); ++j
);
1798 /* Copy [i,j) upward from [i+distance,j+distance) */
1799 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1800 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1801 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1802 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1803 (j
-i
) * f
->output_data
.x
->line_height
,
1804 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1808 for (i
= ht
; --i
>=0; )
1809 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1811 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1812 && line_dance
[j
]-j
== distance
););
1813 /* Copy (j,i] downward from (j+distance, i+distance] */
1814 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1815 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1816 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1817 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1818 (i
-j
) * f
->output_data
.x
->line_height
,
1819 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1823 for (i
= 0; i
< ht
; ++i
)
1824 if (line_dance
[i
] == -1)
1826 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1828 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1829 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1830 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1831 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1834 line_dance_in_progress
= 0;
1837 /* Support routines for exposure events. */
1838 static void clear_cursor ();
1840 /* Output into a rectangle of an X-window (for frame F)
1841 the characters in f->phys_lines that overlap that rectangle.
1842 TOP and LEFT are the position of the upper left corner of the rectangle.
1843 ROWS and COLS are the size of the rectangle.
1844 Call this function with input blocked. */
1847 dumprectangle (f
, left
, top
, cols
, rows
)
1849 register int left
, top
, cols
, rows
;
1851 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1852 int cursor_cleared
= 0;
1856 if (FRAME_GARBAGED_P (f
))
1859 /* Express rectangle as four edges, instead of position-and-size. */
1860 bottom
= top
+ rows
;
1861 right
= left
+ cols
;
1863 /* Convert rectangle edges in pixels to edges in chars.
1864 Round down for left and top, up for right and bottom. */
1865 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1866 left
= PIXEL_TO_CHAR_COL (f
, left
);
1867 bottom
+= (f
->output_data
.x
->line_height
- 1);
1868 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1869 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1870 right
= PIXEL_TO_CHAR_COL (f
, right
);
1872 /* Clip the rectangle to what can be visible. */
1877 if (right
> FRAME_WINDOW_WIDTH (f
))
1878 right
= FRAME_WINDOW_WIDTH (f
);
1879 if (bottom
> f
->height
)
1882 /* Get size in chars of the rectangle. */
1883 cols
= right
- left
;
1884 rows
= bottom
- top
;
1886 /* If rectangle has zero area, return. */
1887 if (rows
<= 0) return;
1888 if (cols
<= 0) return;
1890 /* Turn off the cursor if it is in the rectangle.
1891 We will turn it back on afterward. */
1892 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1893 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1899 /* Display the text in the rectangle, one text line at a time. */
1901 for (y
= top
; y
< bottom
; y
++)
1903 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1905 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1908 while (*line
& GLYPH_MASK_PADDING
)
1910 /* We must display the whole glyph of a wide-column
1917 CHAR_TO_PIXEL_COL (f
, left
),
1918 CHAR_TO_PIXEL_ROW (f
, y
),
1919 line
, min (cols
, active_frame
->used
[y
] - left
),
1920 active_frame
->highlight
[y
], 0, NULL
);
1923 /* Turn the cursor on if we turned it off. */
1926 x_update_cursor (f
, 1);
1933 /* We used to only do this if Vx_no_window_manager was non-nil, but
1934 the ICCCM (section 4.1.6) says that the window's border pixmap
1935 and border pixel are window attributes which are "private to the
1936 client", so we can always change it to whatever we want. */
1938 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1939 f
->output_data
.x
->border_pixel
);
1941 x_update_cursor (f
, 1);
1945 frame_unhighlight (f
)
1948 /* We used to only do this if Vx_no_window_manager was non-nil, but
1949 the ICCCM (section 4.1.6) says that the window's border pixmap
1950 and border pixel are window attributes which are "private to the
1951 client", so we can always change it to whatever we want. */
1953 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1954 f
->output_data
.x
->border_tile
);
1956 x_update_cursor (f
, 1);
1959 static void XTframe_rehighlight ();
1960 static void x_frame_rehighlight ();
1962 /* The focus has changed. Update the frames as necessary to reflect
1963 the new situation. Note that we can't change the selected frame
1964 here, because the Lisp code we are interrupting might become confused.
1965 Each event gets marked with the frame in which it occurred, so the
1966 Lisp code can tell when the switch took place by examining the events. */
1969 x_new_focus_frame (dpyinfo
, frame
)
1970 struct x_display_info
*dpyinfo
;
1971 struct frame
*frame
;
1973 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1974 int events_enqueued
= 0;
1976 if (frame
!= dpyinfo
->x_focus_frame
)
1978 /* Set this before calling other routines, so that they see
1979 the correct value of x_focus_frame. */
1980 dpyinfo
->x_focus_frame
= frame
;
1982 if (old_focus
&& old_focus
->auto_lower
)
1983 x_lower_frame (old_focus
);
1986 selected_frame
= frame
;
1987 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1989 Fselect_window (selected_frame
->selected_window
);
1990 choose_minibuf_frame ();
1993 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1994 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1996 pending_autoraise_frame
= 0;
1999 x_frame_rehighlight (dpyinfo
);
2002 /* Handle an event saying the mouse has moved out of an Emacs frame. */
2005 x_mouse_leave (dpyinfo
)
2006 struct x_display_info
*dpyinfo
;
2008 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
2011 /* The focus has changed, or we have redirected a frame's focus to
2012 another frame (this happens when a frame uses a surrogate
2013 minibuffer frame). Shift the highlight as appropriate.
2015 The FRAME argument doesn't necessarily have anything to do with which
2016 frame is being highlighted or unhighlighted; we only use it to find
2017 the appropriate X display info. */
2019 XTframe_rehighlight (frame
)
2020 struct frame
*frame
;
2022 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
2026 x_frame_rehighlight (dpyinfo
)
2027 struct x_display_info
*dpyinfo
;
2029 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
2031 if (dpyinfo
->x_focus_frame
)
2033 dpyinfo
->x_highlight_frame
2034 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
2035 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
2036 : dpyinfo
->x_focus_frame
);
2037 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
2039 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
2040 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
2044 dpyinfo
->x_highlight_frame
= 0;
2046 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
2049 frame_unhighlight (old_highlight
);
2050 if (dpyinfo
->x_highlight_frame
)
2051 frame_highlight (dpyinfo
->x_highlight_frame
);
2055 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
2057 /* Initialize mode_switch_bit and modifier_meaning. */
2059 x_find_modifier_meanings (dpyinfo
)
2060 struct x_display_info
*dpyinfo
;
2062 int min_code
, max_code
;
2065 XModifierKeymap
*mods
;
2067 dpyinfo
->meta_mod_mask
= 0;
2068 dpyinfo
->shift_lock_mask
= 0;
2069 dpyinfo
->alt_mod_mask
= 0;
2070 dpyinfo
->super_mod_mask
= 0;
2071 dpyinfo
->hyper_mod_mask
= 0;
2074 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
2076 min_code
= dpyinfo
->display
->min_keycode
;
2077 max_code
= dpyinfo
->display
->max_keycode
;
2080 syms
= XGetKeyboardMapping (dpyinfo
->display
,
2081 min_code
, max_code
- min_code
+ 1,
2083 mods
= XGetModifierMapping (dpyinfo
->display
);
2085 /* Scan the modifier table to see which modifier bits the Meta and
2086 Alt keysyms are on. */
2088 int row
, col
; /* The row and column in the modifier table. */
2090 for (row
= 3; row
< 8; row
++)
2091 for (col
= 0; col
< mods
->max_keypermod
; col
++)
2094 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
2096 /* Zeroes are used for filler. Skip them. */
2100 /* Are any of this keycode's keysyms a meta key? */
2104 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
2106 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
2112 dpyinfo
->meta_mod_mask
|= (1 << row
);
2117 dpyinfo
->alt_mod_mask
|= (1 << row
);
2122 dpyinfo
->hyper_mod_mask
|= (1 << row
);
2127 dpyinfo
->super_mod_mask
|= (1 << row
);
2131 /* Ignore this if it's not on the lock modifier. */
2132 if ((1 << row
) == LockMask
)
2133 dpyinfo
->shift_lock_mask
= LockMask
;
2141 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
2142 if (! dpyinfo
->meta_mod_mask
)
2144 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
2145 dpyinfo
->alt_mod_mask
= 0;
2148 /* If some keys are both alt and meta,
2149 make them just meta, not alt. */
2150 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
2152 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
2155 XFree ((char *) syms
);
2156 XFreeModifiermap (mods
);
2159 /* Convert between the modifier bits X uses and the modifier bits
2162 x_x_to_emacs_modifiers (dpyinfo
, state
)
2163 struct x_display_info
*dpyinfo
;
2166 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
2167 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
2168 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
2169 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
2170 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
2171 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
2175 x_emacs_to_x_modifiers (dpyinfo
, state
)
2176 struct x_display_info
*dpyinfo
;
2179 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
2180 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
2181 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
2182 | ((state
& shift_modifier
) ? ShiftMask
: 0)
2183 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
2184 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
2187 /* Convert a keysym to its name. */
2190 x_get_keysym_name (keysym
)
2196 value
= XKeysymToString (keysym
);
2202 /* Mouse clicks and mouse movement. Rah. */
2204 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
2205 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
2206 that the glyph at X, Y occupies, if BOUNDS != 0.
2207 If NOCLIP is nonzero, do not force the value into range. */
2210 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2212 register int pix_x
, pix_y
;
2213 register int *x
, *y
;
2217 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
2218 even for negative values. */
2220 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
2222 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
2224 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
2225 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
2229 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
2230 bounds
->height
= f
->output_data
.x
->line_height
;
2231 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
2232 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
2239 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
2240 pix_x
= FRAME_WINDOW_WIDTH (f
);
2244 else if (pix_y
> f
->height
)
2253 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2256 register int *pix_x
, *pix_y
;
2258 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
2259 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
2262 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2264 If the event is a button press, then note that we have grabbed
2268 construct_mouse_click (result
, event
, f
)
2269 struct input_event
*result
;
2270 XButtonEvent
*event
;
2273 /* Make the event type no_event; we'll change that when we decide
2275 result
->kind
= mouse_click
;
2276 result
->code
= event
->button
- Button1
;
2277 result
->timestamp
= event
->time
;
2278 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2280 | (event
->type
== ButtonRelease
2288 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2289 XSETFASTINT (result
->x
, column
);
2290 XSETFASTINT (result
->y
, row
);
2292 XSETINT (result
->x
, event
->x
);
2293 XSETINT (result
->y
, event
->y
);
2294 XSETFRAME (result
->frame_or_window
, f
);
2298 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2301 construct_menu_click (result
, event
, f
)
2302 struct input_event
*result
;
2303 XButtonEvent
*event
;
2306 /* Make the event type no_event; we'll change that when we decide
2308 result
->kind
= mouse_click
;
2309 result
->code
= event
->button
- Button1
;
2310 result
->timestamp
= event
->time
;
2311 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2313 | (event
->type
== ButtonRelease
2317 XSETINT (result
->x
, event
->x
);
2318 XSETINT (result
->y
, -1);
2319 XSETFRAME (result
->frame_or_window
, f
);
2322 /* Function to report a mouse movement to the mainstream Emacs code.
2323 The input handler calls this.
2325 We have received a mouse movement event, which is given in *event.
2326 If the mouse is over a different glyph than it was last time, tell
2327 the mainstream emacs code by setting mouse_moved. If not, ask for
2328 another motion event, so we can check again the next time it moves. */
2331 note_mouse_movement (frame
, event
)
2333 XMotionEvent
*event
;
2335 last_mouse_movement_time
= event
->time
;
2337 if (event
->window
!= FRAME_X_WINDOW (frame
))
2339 frame
->mouse_moved
= 1;
2340 last_mouse_scroll_bar
= Qnil
;
2342 note_mouse_highlight (frame
, -1, -1);
2345 /* Has the mouse moved off the glyph it was on at the last sighting? */
2346 else if (event
->x
< last_mouse_glyph
.x
2347 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2348 || event
->y
< last_mouse_glyph
.y
2349 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2351 frame
->mouse_moved
= 1;
2352 last_mouse_scroll_bar
= Qnil
;
2354 note_mouse_highlight (frame
, event
->x
, event
->y
);
2358 /* This is used for debugging, to turn off note_mouse_highlight. */
2359 static int disable_mouse_highlight
;
2361 /* Take proper action when the mouse has moved to position X, Y on frame F
2362 as regards highlighting characters that have mouse-face properties.
2363 Also dehighlighting chars where the mouse was before.
2364 X and Y can be negative or out of range. */
2367 note_mouse_highlight (f
, x
, y
)
2371 int row
, column
, portion
;
2372 XRectangle new_glyph
;
2376 if (disable_mouse_highlight
)
2379 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2380 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2381 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2383 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
2388 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2392 /* Find out which glyph the mouse is on. */
2393 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2394 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
2396 /* Which window is that in? */
2397 window
= window_from_coordinates (f
, column
, row
, &portion
);
2398 w
= XWINDOW (window
);
2400 /* If we were displaying active text in another window, clear that. */
2401 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
2402 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2404 /* Are we in a window whose display is up to date?
2405 And verify the buffer's text has not changed. */
2406 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2407 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2408 && EQ (w
->window_end_valid
, w
->buffer
)
2409 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
2410 && (XFASTINT (w
->last_overlay_modified
)
2411 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
2413 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2416 /* Find which buffer position the mouse corresponds to. */
2417 for (i
= column
; i
>= 0; i
--)
2421 /* Is it outside the displayed active region (if any)? */
2423 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2424 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
2425 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2426 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2427 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2428 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2429 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2430 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2431 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2433 Lisp_Object mouse_face
, overlay
, position
;
2434 Lisp_Object
*overlay_vec
;
2435 int len
, noverlays
, ignor1
;
2436 struct buffer
*obuf
;
2439 /* If we get an out-of-range value, return now; avoid an error. */
2440 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2443 /* Make the window's buffer temporarily current for
2444 overlays_at and compute_char_face. */
2445 obuf
= current_buffer
;
2446 current_buffer
= XBUFFER (w
->buffer
);
2452 /* Yes. Clear the display of the old active region, if any. */
2453 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2455 /* Is this char mouse-active? */
2456 XSETINT (position
, pos
);
2459 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2461 /* Put all the overlays we want in a vector in overlay_vec.
2462 Store the length in len. */
2463 noverlays
= overlays_at (pos
, 1, &overlay_vec
, &len
,
2465 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2467 /* Find the highest priority overlay that has a mouse-face prop. */
2469 for (i
= 0; i
< noverlays
; i
++)
2471 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2472 if (!NILP (mouse_face
))
2474 overlay
= overlay_vec
[i
];
2479 /* If no overlay applies, get a text property. */
2481 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2483 /* Handle the overlay case. */
2484 if (! NILP (overlay
))
2486 /* Find the range of text around this char that
2487 should be active. */
2488 Lisp_Object before
, after
;
2491 before
= Foverlay_start (overlay
);
2492 after
= Foverlay_end (overlay
);
2493 /* Record this as the current active region. */
2494 fast_find_position (window
, XFASTINT (before
),
2495 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2496 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2497 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2498 = !fast_find_position (window
, XFASTINT (after
),
2499 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2500 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2501 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2502 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2503 = compute_char_face (f
, w
, pos
, 0, 0,
2504 &ignore
, pos
+ 1, 1);
2506 /* Display it as active. */
2507 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2509 /* Handle the text property case. */
2510 else if (! NILP (mouse_face
))
2512 /* Find the range of text around this char that
2513 should be active. */
2514 Lisp_Object before
, after
, beginning
, end
;
2517 beginning
= Fmarker_position (w
->start
);
2518 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2519 - XFASTINT (w
->window_end_pos
)));
2521 = Fprevious_single_property_change (make_number (pos
+ 1),
2523 w
->buffer
, beginning
);
2525 = Fnext_single_property_change (position
, Qmouse_face
,
2527 /* Record this as the current active region. */
2528 fast_find_position (window
, XFASTINT (before
),
2529 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2530 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2531 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2532 = !fast_find_position (window
, XFASTINT (after
),
2533 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2534 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2535 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2536 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2537 = compute_char_face (f
, w
, pos
, 0, 0,
2538 &ignore
, pos
+ 1, 1);
2540 /* Display it as active. */
2541 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2545 current_buffer
= obuf
;
2550 /* Find the row and column of position POS in window WINDOW.
2551 Store them in *COLUMNP and *ROWP.
2552 This assumes display in WINDOW is up to date.
2553 If POS is above start of WINDOW, return coords
2554 of start of first screen line.
2555 If POS is after end of WINDOW, return coords of end of last screen line.
2557 Value is 1 if POS is in range, 0 if it was off screen. */
2560 fast_find_position (window
, pos
, columnp
, rowp
)
2563 int *columnp
, *rowp
;
2565 struct window
*w
= XWINDOW (window
);
2566 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2569 int left
= WINDOW_LEFT_MARGIN (w
);
2570 int top
= XFASTINT (w
->top
);
2571 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2572 int width
= window_internal_width (w
);
2575 int maybe_next_line
= 0;
2577 /* Find the right row. */
2582 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2583 if (linestart
> pos
)
2585 /* If the position sought is the end of the buffer,
2586 don't include the blank lines at the bottom of the window. */
2587 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2589 maybe_next_line
= 1;
2596 /* Find the right column with in it. */
2597 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2599 for (i
= 0; i
< width
; i
++)
2601 if (charstarts
[left
+ i
] == pos
)
2604 *columnp
= i
+ left
;
2607 else if (charstarts
[left
+ i
] > pos
)
2609 else if (charstarts
[left
+ i
] > 0)
2613 /* If we're looking for the end of the buffer,
2614 and we didn't find it in the line we scanned,
2615 use the start of the following line. */
2616 if (maybe_next_line
)
2627 /* Display the active region described by mouse_face_*
2628 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2631 show_mouse_face (dpyinfo
, hl
)
2632 struct x_display_info
*dpyinfo
;
2635 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2636 int width
= window_internal_width (w
);
2637 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2640 int old_curs_x
= curs_x
;
2641 int old_curs_y
= curs_y
;
2643 /* Set these variables temporarily
2644 so that if we have to turn the cursor off and on again
2645 we will put it back at the same place. */
2646 curs_x
= f
->phys_cursor_x
;
2647 curs_y
= f
->phys_cursor_y
;
2648 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2649 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2651 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2652 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2653 : WINDOW_LEFT_MARGIN (w
));
2654 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2655 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2656 : WINDOW_LEFT_MARGIN (w
) + width
);
2657 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2659 /* If the cursor's in the text we are about to rewrite,
2660 turn the cursor off. */
2662 && curs_x
>= column
- 1
2663 && curs_x
<= endcolumn
)
2665 x_update_cursor (f
, 0);
2670 CHAR_TO_PIXEL_COL (f
, column
),
2671 CHAR_TO_PIXEL_ROW (f
, i
),
2672 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2674 /* Highlight with mouse face if hl > 0. */
2675 hl
> 0 ? 3 : 0, 0, NULL
);
2678 /* If we turned the cursor off, turn it back on. */
2680 x_display_cursor (f
, 1, curs_x
, curs_y
);
2682 curs_x
= old_curs_x
;
2683 curs_y
= old_curs_y
;
2685 /* Change the mouse cursor according to the value of HL. */
2687 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2688 f
->output_data
.x
->cross_cursor
);
2690 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2691 f
->output_data
.x
->text_cursor
);
2694 /* Clear out the mouse-highlighted active region.
2695 Redraw it unhighlighted first. */
2698 clear_mouse_face (dpyinfo
)
2699 struct x_display_info
*dpyinfo
;
2701 if (! NILP (dpyinfo
->mouse_face_window
))
2702 show_mouse_face (dpyinfo
, 0);
2704 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2705 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2706 dpyinfo
->mouse_face_window
= Qnil
;
2709 /* Just discard the mouse face information for frame F, if any.
2710 This is used when the size of F is changed. */
2713 cancel_mouse_face (f
)
2717 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2719 window
= dpyinfo
->mouse_face_window
;
2720 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2722 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2723 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2724 dpyinfo
->mouse_face_window
= Qnil
;
2728 static struct scroll_bar
*x_window_to_scroll_bar ();
2729 static void x_scroll_bar_report_motion ();
2731 /* Return the current position of the mouse.
2732 *fp should be a frame which indicates which display to ask about.
2734 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2735 and *part to the frame, window, and scroll bar part that the mouse
2736 is over. Set *x and *y to the portion and whole of the mouse's
2737 position on the scroll bar.
2739 If the mouse movement started elsewhere, set *fp to the frame the
2740 mouse is on, *bar_window to nil, and *x and *y to the character cell
2743 Set *time to the server timestamp for the time at which the mouse
2744 was at this position.
2746 Don't store anything if we don't have a valid set of values to report.
2748 This clears the mouse_moved flag, so we can wait for the next mouse
2752 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2755 Lisp_Object
*bar_window
;
2756 enum scroll_bar_part
*part
;
2758 unsigned long *time
;
2764 if (! NILP (last_mouse_scroll_bar
) && insist
== 0)
2765 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2771 Window dummy_window
;
2774 Lisp_Object frame
, tail
;
2776 /* Clear the mouse-moved flag for every frame on this display. */
2777 FOR_EACH_FRAME (tail
, frame
)
2778 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2779 XFRAME (frame
)->mouse_moved
= 0;
2781 last_mouse_scroll_bar
= Qnil
;
2783 /* Figure out which root window we're on. */
2784 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2785 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2787 /* The root window which contains the pointer. */
2790 /* Trash which we can't trust if the pointer is on
2791 a different screen. */
2794 /* The position on that root window. */
2797 /* More trash we can't trust. */
2800 /* Modifier keys and pointer buttons, about which
2802 (unsigned int *) &dummy
);
2804 /* Now we have a position on the root; find the innermost window
2805 containing the pointer. */
2809 int parent_x
, parent_y
;
2814 /* XTranslateCoordinates can get errors if the window
2815 structure is changing at the same time this function
2816 is running. So at least we must not crash from them. */
2818 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
2820 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2821 && FRAME_LIVE_P (last_mouse_frame
))
2823 /* If mouse was grabbed on a frame, give coords for that frame
2824 even if the mouse is now outside it. */
2825 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2827 /* From-window, to-window. */
2828 root
, FRAME_X_WINDOW (last_mouse_frame
),
2830 /* From-position, to-position. */
2831 root_x
, root_y
, &win_x
, &win_y
,
2835 f1
= last_mouse_frame
;
2841 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2843 /* From-window, to-window. */
2846 /* From-position, to-position. */
2847 root_x
, root_y
, &win_x
, &win_y
,
2852 if (child
== None
|| child
== win
)
2860 /* Now we know that:
2861 win is the innermost window containing the pointer
2862 (XTC says it has no child containing the pointer),
2863 win_x and win_y are the pointer's position in it
2864 (XTC did this the last time through), and
2865 parent_x and parent_y are the pointer's position in win's parent.
2866 (They are what win_x and win_y were when win was child.
2867 If win is the root window, it has no parent, and
2868 parent_{x,y} are invalid, but that's okay, because we'll
2869 never use them in that case.) */
2871 /* Is win one of our frames? */
2872 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2875 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2878 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
2880 /* If not, is it one of our scroll bars? */
2883 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2887 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2893 if (f1
== 0 && insist
> 0)
2894 f1
= selected_frame
;
2898 int ignore1
, ignore2
;
2900 /* Ok, we found a frame. Store all the values. */
2902 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2904 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2910 XSETINT (*x
, win_x
);
2911 XSETINT (*y
, win_y
);
2912 *time
= last_mouse_movement_time
;
2920 /* Scroll bar support. */
2922 /* Given an X window ID, find the struct scroll_bar which manages it.
2923 This can be called in GC, so we have to make sure to strip off mark
2925 static struct scroll_bar
*
2926 x_window_to_scroll_bar (window_id
)
2929 Lisp_Object tail
, frame
;
2931 for (tail
= Vframe_list
;
2932 XGCTYPE (tail
) == Lisp_Cons
;
2933 tail
= XCONS (tail
)->cdr
)
2935 Lisp_Object frame
, bar
, condemned
;
2937 frame
= XCONS (tail
)->car
;
2938 /* All elements of Vframe_list should be frames. */
2939 if (! GC_FRAMEP (frame
))
2942 /* Scan this frame's scroll bar list for a scroll bar with the
2944 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2945 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2946 /* This trick allows us to search both the ordinary and
2947 condemned scroll bar lists with one loop. */
2948 ! GC_NILP (bar
) || (bar
= condemned
,
2951 bar
= XSCROLL_BAR (bar
)->next
)
2952 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2953 return XSCROLL_BAR (bar
);
2959 /* Open a new X window to serve as a scroll bar, and return the
2960 scroll bar vector for it. */
2961 static struct scroll_bar
*
2962 x_scroll_bar_create (window
, top
, left
, width
, height
)
2963 struct window
*window
;
2964 int top
, left
, width
, height
;
2966 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2967 struct scroll_bar
*bar
2968 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2973 XSetWindowAttributes a
;
2975 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2976 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2977 | ButtonMotionMask
| PointerMotionHintMask
2979 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2981 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2986 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2987 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2988 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2989 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2990 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2991 sb_widget
= XtCreateManagedWidget ("box",
2993 f
->output_data
.x
->edit_widget
, al
, ac
);
2994 SET_SCROLL_BAR_X_WINDOW
2995 (bar
, sb_widget
->core
.window
);
2997 SET_SCROLL_BAR_X_WINDOW
2999 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
3001 /* Position and size of scroll bar. */
3002 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, top
,
3003 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2, height
,
3005 /* Border width, depth, class, and visual. */
3006 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
3012 XSETWINDOW (bar
->window
, window
);
3013 XSETINT (bar
->top
, top
);
3014 XSETINT (bar
->left
, left
);
3015 XSETINT (bar
->width
, width
);
3016 XSETINT (bar
->height
, height
);
3017 XSETINT (bar
->start
, 0);
3018 XSETINT (bar
->end
, 0);
3019 bar
->dragging
= Qnil
;
3021 /* Add bar to its frame's list of scroll bars. */
3022 bar
->next
= FRAME_SCROLL_BARS (f
);
3024 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3025 if (! NILP (bar
->next
))
3026 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3028 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3035 /* Draw BAR's handle in the proper position.
3036 If the handle is already drawn from START to END, don't bother
3037 redrawing it, unless REBUILD is non-zero; in that case, always
3038 redraw it. (REBUILD is handy for drawing the handle after expose
3041 Normally, we want to constrain the start and end of the handle to
3042 fit inside its rectangle, but if the user is dragging the scroll bar
3043 handle, we want to let them drag it down all the way, so that the
3044 bar's top is as far down as it goes; otherwise, there's no way to
3045 move to the very end of the buffer. */
3047 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
3048 struct scroll_bar
*bar
;
3052 int dragging
= ! NILP (bar
->dragging
);
3053 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3054 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3055 GC gc
= f
->output_data
.x
->normal_gc
;
3057 /* If the display is already accurate, do nothing. */
3059 && start
== XINT (bar
->start
)
3060 && end
== XINT (bar
->end
))
3066 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
3067 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3068 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3070 /* Make sure the values are reasonable, and try to preserve
3071 the distance between start and end. */
3073 int length
= end
- start
;
3077 else if (start
> top_range
)
3079 end
= start
+ length
;
3083 else if (end
> top_range
&& ! dragging
)
3087 /* Store the adjusted setting in the scroll bar. */
3088 XSETINT (bar
->start
, start
);
3089 XSETINT (bar
->end
, end
);
3091 /* Clip the end position, just for display. */
3092 if (end
> top_range
)
3095 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
3096 below top positions, to make sure the handle is always at least
3097 that many pixels tall. */
3098 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3100 /* Draw the empty space above the handle. Note that we can't clear
3101 zero-height areas; that means "clear to end of window." */
3103 XClearArea (FRAME_X_DISPLAY (f
), w
,
3105 /* x, y, width, height, and exposures. */
3106 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3107 VERTICAL_SCROLL_BAR_TOP_BORDER
,
3108 inside_width
, start
,
3111 /* Draw the handle itself. */
3112 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3114 /* x, y, width, height */
3115 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3116 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
3117 inside_width
, end
- start
);
3120 /* Draw the empty space below the handle. Note that we can't
3121 clear zero-height areas; that means "clear to end of window." */
3122 if (end
< inside_height
)
3123 XClearArea (FRAME_X_DISPLAY (f
), w
,
3125 /* x, y, width, height, and exposures. */
3126 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3127 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
3128 inside_width
, inside_height
- end
,
3136 /* Move a scroll bar around on the screen, to accommodate changing
3137 window configurations. */
3139 x_scroll_bar_move (bar
, top
, left
, width
, height
)
3140 struct scroll_bar
*bar
;
3141 int top
, left
, width
, height
;
3143 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3144 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3150 unsigned int mask
= 0;
3152 wc
.x
= left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3155 wc
.width
= width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
3158 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
3159 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
3160 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
3161 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
3164 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
3168 XSETINT (bar
->left
, left
);
3169 XSETINT (bar
->top
, top
);
3170 XSETINT (bar
->width
, width
);
3171 XSETINT (bar
->height
, height
);
3176 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
3179 x_scroll_bar_remove (bar
)
3180 struct scroll_bar
*bar
;
3182 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3186 /* Destroy the window. */
3187 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3189 /* Disassociate this scroll bar from its window. */
3190 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3195 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3196 that we are displaying PORTION characters out of a total of WHOLE
3197 characters, starting at POSITION. If WINDOW has no scroll bar,
3200 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
3201 struct window
*window
;
3202 int portion
, whole
, position
;
3204 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3205 int top
= XINT (window
->top
);
3206 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
3207 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
3209 /* Where should this scroll bar be, pixelwise? */
3210 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
3211 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
3213 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3214 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3215 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3216 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
3218 struct scroll_bar
*bar
;
3220 /* Does the scroll bar exist yet? */
3221 if (NILP (window
->vertical_scroll_bar
))
3222 bar
= x_scroll_bar_create (window
,
3223 pixel_top
, pixel_left
,
3224 pixel_width
, pixel_height
);
3227 /* It may just need to be moved and resized. */
3228 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3229 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
3232 /* Set the scroll bar's current state, unless we're currently being
3234 if (NILP (bar
->dragging
))
3236 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
3239 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
3242 int start
= ((double) position
* top_range
) / whole
;
3243 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
3245 x_scroll_bar_set_handle (bar
, start
, end
, 0);
3249 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
3253 /* The following three hooks are used when we're doing a thorough
3254 redisplay of the frame. We don't explicitly know which scroll bars
3255 are going to be deleted, because keeping track of when windows go
3256 away is a real pain - "Can you say set-window-configuration, boys
3257 and girls?" Instead, we just assert at the beginning of redisplay
3258 that *all* scroll bars are to be removed, and then save a scroll bar
3259 from the fiery pit when we actually redisplay its window. */
3261 /* Arrange for all scroll bars on FRAME to be removed at the next call
3262 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3263 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
3265 XTcondemn_scroll_bars (frame
)
3268 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3269 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3272 bar
= FRAME_SCROLL_BARS (frame
);
3273 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3274 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3275 XSCROLL_BAR (bar
)->prev
= Qnil
;
3276 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3277 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3278 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3282 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
3283 Note that WINDOW isn't necessarily condemned at all. */
3285 XTredeem_scroll_bar (window
)
3286 struct window
*window
;
3288 struct scroll_bar
*bar
;
3290 /* We can't redeem this window's scroll bar if it doesn't have one. */
3291 if (NILP (window
->vertical_scroll_bar
))
3294 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3296 /* Unlink it from the condemned list. */
3298 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3300 if (NILP (bar
->prev
))
3302 /* If the prev pointer is nil, it must be the first in one of
3304 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3305 /* It's not condemned. Everything's fine. */
3307 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3308 window
->vertical_scroll_bar
))
3309 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3311 /* If its prev pointer is nil, it must be at the front of
3312 one or the other! */
3316 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3318 if (! NILP (bar
->next
))
3319 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3321 bar
->next
= FRAME_SCROLL_BARS (f
);
3323 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3324 if (! NILP (bar
->next
))
3325 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3329 /* Remove all scroll bars on FRAME that haven't been saved since the
3330 last call to `*condemn_scroll_bars_hook'. */
3332 XTjudge_scroll_bars (f
)
3335 Lisp_Object bar
, next
;
3337 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3339 /* Clear out the condemned list now so we won't try to process any
3340 more events on the hapless scroll bars. */
3341 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3343 for (; ! NILP (bar
); bar
= next
)
3345 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3347 x_scroll_bar_remove (b
);
3350 b
->next
= b
->prev
= Qnil
;
3353 /* Now there should be no references to the condemned scroll bars,
3354 and they should get garbage-collected. */
3358 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3360 This may be called from a signal handler, so we have to ignore GC
3363 x_scroll_bar_expose (bar
, event
)
3364 struct scroll_bar
*bar
;
3367 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3368 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3369 GC gc
= f
->output_data
.x
->normal_gc
;
3370 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3374 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3376 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3377 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3379 /* x, y, width, height */
3381 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
3382 XINT (bar
->height
) - 1);
3387 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3388 is set to something other than no_event, it is enqueued.
3390 This may be called from a signal handler, so we have to ignore GC
3393 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3394 struct scroll_bar
*bar
;
3396 struct input_event
*emacs_event
;
3398 if (! GC_WINDOWP (bar
->window
))
3401 emacs_event
->kind
= scroll_bar_click
;
3402 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3403 emacs_event
->modifiers
3404 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
3405 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
3406 event
->xbutton
.state
)
3407 | (event
->type
== ButtonRelease
3410 emacs_event
->frame_or_window
= bar
->window
;
3411 emacs_event
->timestamp
= event
->xbutton
.time
;
3413 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3415 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3417 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3418 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3421 if (y
> top_range
) y
= top_range
;
3423 if (y
< XINT (bar
->start
))
3424 emacs_event
->part
= scroll_bar_above_handle
;
3425 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3426 emacs_event
->part
= scroll_bar_handle
;
3428 emacs_event
->part
= scroll_bar_below_handle
;
3430 /* Just because the user has clicked on the handle doesn't mean
3431 they want to drag it. Lisp code needs to be able to decide
3432 whether or not we're dragging. */
3434 /* If the user has just clicked on the handle, record where they're
3436 if (event
->type
== ButtonPress
3437 && emacs_event
->part
== scroll_bar_handle
)
3438 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
3441 /* If the user has released the handle, set it to its final position. */
3442 if (event
->type
== ButtonRelease
3443 && ! NILP (bar
->dragging
))
3445 int new_start
= y
- XINT (bar
->dragging
);
3446 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3448 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3449 bar
->dragging
= Qnil
;
3452 /* Same deal here as the other #if 0. */
3454 /* Clicks on the handle are always reported as occurring at the top of
3456 if (emacs_event
->part
== scroll_bar_handle
)
3457 emacs_event
->x
= bar
->start
;
3459 XSETINT (emacs_event
->x
, y
);
3461 XSETINT (emacs_event
->x
, y
);
3464 XSETINT (emacs_event
->y
, top_range
);
3468 /* Handle some mouse motion while someone is dragging the scroll bar.
3470 This may be called from a signal handler, so we have to ignore GC
3473 x_scroll_bar_note_movement (bar
, event
)
3474 struct scroll_bar
*bar
;
3477 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
3479 last_mouse_movement_time
= event
->xmotion
.time
;
3482 XSETVECTOR (last_mouse_scroll_bar
, bar
);
3484 /* If we're dragging the bar, display it. */
3485 if (! GC_NILP (bar
->dragging
))
3487 /* Where should the handle be now? */
3488 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3490 if (new_start
!= XINT (bar
->start
))
3492 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3494 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3499 /* Return information to the user about the current position of the mouse
3500 on the scroll bar. */
3502 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3504 Lisp_Object
*bar_window
;
3505 enum scroll_bar_part
*part
;
3507 unsigned long *time
;
3509 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3510 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3511 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3513 Window dummy_window
;
3515 unsigned int dummy_mask
;
3519 /* Get the mouse's position relative to the scroll bar window, and
3521 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3523 /* Root, child, root x and root y. */
3524 &dummy_window
, &dummy_window
,
3525 &dummy_coord
, &dummy_coord
,
3527 /* Position relative to scroll bar. */
3530 /* Mouse buttons and modifier keys. */
3536 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3538 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3540 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3542 if (! NILP (bar
->dragging
))
3543 win_y
-= XINT (bar
->dragging
);
3547 if (win_y
> top_range
)
3551 *bar_window
= bar
->window
;
3553 if (! NILP (bar
->dragging
))
3554 *part
= scroll_bar_handle
;
3555 else if (win_y
< XINT (bar
->start
))
3556 *part
= scroll_bar_above_handle
;
3557 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3558 *part
= scroll_bar_handle
;
3560 *part
= scroll_bar_below_handle
;
3562 XSETINT (*x
, win_y
);
3563 XSETINT (*y
, top_range
);
3566 last_mouse_scroll_bar
= Qnil
;
3569 *time
= last_mouse_movement_time
;
3575 /* The screen has been cleared so we may have changed foreground or
3576 background colors, and the scroll bars may need to be redrawn.
3577 Clear out the scroll bars, and ask for expose events, so we can
3581 x_scroll_bar_clear (f
)
3586 /* We can have scroll bars even if this is 0,
3587 if we just turned off scroll bar mode.
3588 But in that case we should not clear them. */
3589 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3590 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3591 bar
= XSCROLL_BAR (bar
)->next
)
3592 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3596 /* This processes Expose events from the menubar specific X event
3597 loop in xmenu.c. This allows to redisplay the frame if necessary
3598 when handling menubar or popup items. */
3601 process_expose_from_menu (event
)
3605 struct x_display_info
*dpyinfo
;
3609 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3610 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3613 if (f
->async_visible
== 0)
3615 f
->async_visible
= 1;
3616 f
->async_iconified
= 0;
3617 f
->output_data
.x
->has_been_visible
= 1;
3618 SET_FRAME_GARBAGED (f
);
3622 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3623 event
.xexpose
.x
, event
.xexpose
.y
,
3624 event
.xexpose
.width
, event
.xexpose
.height
);
3629 struct scroll_bar
*bar
3630 = x_window_to_scroll_bar (event
.xexpose
.window
);
3633 x_scroll_bar_expose (bar
, &event
);
3639 /* Define a queue to save up SelectionRequest events for later handling. */
3641 struct selection_event_queue
3644 struct selection_event_queue
*next
;
3647 static struct selection_event_queue
*queue
;
3649 /* Nonzero means queue up certain events--don't process them yet. */
3650 static int x_queue_selection_requests
;
3652 /* Queue up an X event *EVENT, to be processed later. */
3655 x_queue_event (f
, event
)
3659 struct selection_event_queue
*queue_tmp
3660 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3662 if (queue_tmp
!= NULL
)
3664 queue_tmp
->event
= *event
;
3665 queue_tmp
->next
= queue
;
3670 /* Take all the queued events and put them back
3671 so that they get processed afresh. */
3674 x_unqueue_events (display
)
3677 while (queue
!= NULL
)
3679 struct selection_event_queue
*queue_tmp
= queue
;
3680 XPutBackEvent (display
, &queue_tmp
->event
);
3681 queue
= queue_tmp
->next
;
3682 free ((char *)queue_tmp
);
3686 /* Start queuing SelectionRequest events. */
3689 x_start_queuing_selection_requests (display
)
3692 x_queue_selection_requests
++;
3695 /* Stop queuing SelectionRequest events. */
3698 x_stop_queuing_selection_requests (display
)
3701 x_queue_selection_requests
--;
3702 x_unqueue_events (display
);
3705 /* The main X event-reading loop - XTread_socket. */
3707 /* Timestamp of enter window event. This is only used by XTread_socket,
3708 but we have to put it out here, since static variables within functions
3709 sometimes don't work. */
3710 static Time enter_timestamp
;
3712 /* This holds the state XLookupString needs to implement dead keys
3713 and other tricks known as "compose processing". _X Window System_
3714 says that a portable program can't use this, but Stephen Gildea assures
3715 me that letting the compiler initialize it to zeros will work okay.
3717 This must be defined outside of XTread_socket, for the same reasons
3718 given for enter_timestamp, above. */
3719 static XComposeStatus compose_status
;
3721 /* Record the last 100 characters stored
3722 to help debug the loss-of-chars-during-GC problem. */
3723 static int temp_index
;
3724 static short temp_buffer
[100];
3726 /* Set this to nonzero to fake an "X I/O error"
3727 on a particular display. */
3728 struct x_display_info
*XTread_socket_fake_io_error
;
3730 /* When we find no input here, we occasionally do a no-op command
3731 to verify that the X server is still running and we can still talk with it.
3732 We try all the open displays, one by one.
3733 This variable is used for cycling thru the displays. */
3734 static struct x_display_info
*next_noop_dpyinfo
;
3736 #define SET_SAVED_MENU_EVENT(size) { \
3737 if (f->output_data.x->saved_menu_event == 0) \
3738 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
3739 bcopy (&event, f->output_data.x->saved_menu_event, size); \
3740 if (numchars >= 1) \
3742 bufp->kind = menu_bar_activate_event; \
3743 XSETFRAME (bufp->frame_or_window, f); \
3749 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
3750 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
3752 /* Read events coming from the X server.
3753 This routine is called by the SIGIO handler.
3754 We return as soon as there are no more events to be read.
3756 Events representing keys are stored in buffer BUFP,
3757 which can hold up to NUMCHARS characters.
3758 We return the number of characters stored into the buffer,
3759 thus pretending to be `read'.
3761 EXPECTED is nonzero if the caller knows input is available. */
3764 XTread_socket (sd
, bufp
, numchars
, expected
)
3766 /* register */ struct input_event
*bufp
;
3767 /* register */ int numchars
;
3773 int items_pending
; /* How many items are in the X queue. */
3776 int event_found
= 0;
3779 struct x_display_info
*dpyinfo
;
3781 Status status_return
;
3784 if (interrupt_input_blocked
)
3786 interrupt_input_pending
= 1;
3790 interrupt_input_pending
= 0;
3793 /* So people can tell when we have read the available input. */
3794 input_signal_count
++;
3797 abort (); /* Don't think this happens. */
3799 /* Find the display we are supposed to read input for.
3800 It's the one communicating on descriptor SD. */
3801 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3803 #if 0 /* This ought to be unnecessary; let's verify it. */
3805 /* If available, Xlib uses FIOSNBIO to make the socket
3806 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3807 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3808 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3809 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3810 #endif /* ! defined (FIOSNBIO) */
3813 #if 0 /* This code can't be made to work, with multiple displays,
3814 and appears not to be used on any system any more.
3815 Also keyboard.c doesn't turn O_NDELAY on and off
3816 for X connections. */
3819 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3821 extern int read_alarm_should_throw
;
3822 read_alarm_should_throw
= 1;
3823 XPeekEvent (dpyinfo
->display
, &event
);
3824 read_alarm_should_throw
= 0;
3826 #endif /* HAVE_SELECT */
3830 /* For debugging, this gives a way to fake an I/O error. */
3831 if (dpyinfo
== XTread_socket_fake_io_error
)
3833 XTread_socket_fake_io_error
= 0;
3834 x_io_error_quitter (dpyinfo
->display
);
3837 while (XPending (dpyinfo
->display
) != 0)
3839 #ifdef USE_X_TOOLKIT
3840 /* needed to raise Motif submenus */
3841 XtAppNextEvent (Xt_app_con
, &event
);
3843 XNextEvent (dpyinfo
->display
, &event
);
3847 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
3848 event
.xclient
.window
);
3849 /* The necessity of the following line took me
3850 a full work-day to decipher from the docs!! */
3851 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
3861 if (event
.xclient
.message_type
3862 == dpyinfo
->Xatom_wm_protocols
3863 && event
.xclient
.format
== 32)
3865 if (event
.xclient
.data
.l
[0]
3866 == dpyinfo
->Xatom_wm_take_focus
)
3868 /* Use x_any_window_to_frame because this
3869 could be the shell widget window
3870 if the frame has no title bar. */
3871 f
= x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3873 /* Not quite sure this is needed -pd */
3874 if (f
&& FRAME_XIC (f
))
3875 XSetICFocus (FRAME_XIC (f
));
3877 /* Since we set WM_TAKE_FOCUS, we must call
3878 XSetInputFocus explicitly. But not if f is null,
3879 since that might be an event for a deleted frame. */
3882 Display
*d
= event
.xclient
.display
;
3883 /* Catch and ignore errors, in case window has been
3884 iconified by a window manager such as GWM. */
3885 int count
= x_catch_errors (d
);
3886 XSetInputFocus (d
, event
.xclient
.window
,
3887 RevertToPointerRoot
,
3888 event
.xclient
.data
.l
[1]);
3889 /* This is needed to detect the error
3890 if there is an error. */
3892 x_uncatch_errors (d
, count
);
3894 /* Not certain about handling scroll bars here */
3896 else if (event
.xclient
.data
.l
[0]
3897 == dpyinfo
->Xatom_wm_save_yourself
)
3899 /* Save state modify the WM_COMMAND property to
3900 something which can reinstate us. This notifies
3901 the session manager, who's looking for such a
3902 PropertyNotify. Can restart processing when
3903 a keyboard or mouse event arrives. */
3906 f
= x_top_window_to_frame (dpyinfo
,
3907 event
.xclient
.window
);
3909 /* This is just so we only give real data once
3910 for a single Emacs process. */
3911 if (f
== selected_frame
)
3912 XSetCommand (FRAME_X_DISPLAY (f
),
3913 event
.xclient
.window
,
3914 initial_argv
, initial_argc
);
3916 XSetCommand (FRAME_X_DISPLAY (f
),
3917 event
.xclient
.window
,
3921 else if (event
.xclient
.data
.l
[0]
3922 == dpyinfo
->Xatom_wm_delete_window
)
3925 = x_any_window_to_frame (dpyinfo
,
3926 event
.xclient
.window
);
3933 bufp
->kind
= delete_window_event
;
3934 XSETFRAME (bufp
->frame_or_window
, f
);
3942 else if (event
.xclient
.message_type
3943 == dpyinfo
->Xatom_wm_configure_denied
)
3946 else if (event
.xclient
.message_type
3947 == dpyinfo
->Xatom_wm_window_moved
)
3951 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3953 new_x
= event
.xclient
.data
.s
[0];
3954 new_y
= event
.xclient
.data
.s
[1];
3958 f
->output_data
.x
->left_pos
= new_x
;
3959 f
->output_data
.x
->top_pos
= new_y
;
3963 else if (event
.xclient
.message_type
3964 == dpyinfo
->Xatom_editres
)
3967 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3968 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3971 #endif /* HACK_EDITRES */
3975 case SelectionNotify
:
3976 #ifdef USE_X_TOOLKIT
3977 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3979 #endif /* not USE_X_TOOLKIT */
3980 x_handle_selection_notify (&event
.xselection
);
3983 case SelectionClear
: /* Someone has grabbed ownership. */
3984 #ifdef USE_X_TOOLKIT
3985 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3987 #endif /* USE_X_TOOLKIT */
3989 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3994 bufp
->kind
= selection_clear_event
;
3995 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3996 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3997 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3998 bufp
->frame_or_window
= Qnil
;
4006 case SelectionRequest
: /* Someone wants our selection. */
4007 #ifdef USE_X_TOOLKIT
4008 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
4010 #endif /* USE_X_TOOLKIT */
4011 if (x_queue_selection_requests
)
4012 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
4016 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
4021 bufp
->kind
= selection_request_event
;
4022 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
4023 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
4024 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
4025 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
4026 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
4027 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
4028 bufp
->frame_or_window
= Qnil
;
4036 case PropertyNotify
:
4037 #ifdef USE_X_TOOLKIT
4038 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
4040 #endif /* not USE_X_TOOLKIT */
4041 x_handle_property_notify (&event
.xproperty
);
4044 case ReparentNotify
:
4045 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
4049 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
4050 x_real_positions (f
, &x
, &y
);
4051 f
->output_data
.x
->left_pos
= x
;
4052 f
->output_data
.x
->top_pos
= y
;
4057 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
4060 if (f
->async_visible
== 0)
4062 f
->async_visible
= 1;
4063 f
->async_iconified
= 0;
4064 f
->output_data
.x
->has_been_visible
= 1;
4065 SET_FRAME_GARBAGED (f
);
4068 dumprectangle (x_window_to_frame (dpyinfo
,
4069 event
.xexpose
.window
),
4070 event
.xexpose
.x
, event
.xexpose
.y
,
4071 event
.xexpose
.width
, event
.xexpose
.height
);
4075 struct scroll_bar
*bar
4076 = x_window_to_scroll_bar (event
.xexpose
.window
);
4079 x_scroll_bar_expose (bar
, &event
);
4080 #ifdef USE_X_TOOLKIT
4083 #endif /* USE_X_TOOLKIT */
4087 case GraphicsExpose
: /* This occurs when an XCopyArea's
4088 source area was obscured or not
4090 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
4094 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
4095 event
.xgraphicsexpose
.width
,
4096 event
.xgraphicsexpose
.height
);
4098 #ifdef USE_X_TOOLKIT
4101 #endif /* USE_X_TOOLKIT */
4104 case NoExpose
: /* This occurs when an XCopyArea's
4105 source area was completely
4110 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
4111 if (f
) /* F may no longer exist if
4112 the frame was deleted. */
4114 /* While a frame is unmapped, display generation is
4115 disabled; you don't want to spend time updating a
4116 display that won't ever be seen. */
4117 f
->async_visible
= 0;
4118 /* We can't distinguish, from the event, whether the window
4119 has become iconified or invisible. So assume, if it
4120 was previously visible, than now it is iconified.
4121 But x_make_frame_invisible clears both
4122 the visible flag and the iconified flag;
4123 and that way, we know the window is not iconified now. */
4124 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
4126 f
->async_iconified
= 1;
4128 bufp
->kind
= iconify_event
;
4129 XSETFRAME (bufp
->frame_or_window
, f
);
4138 /* We use x_top_window_to_frame because map events can come
4139 for subwindows and they don't mean that the frame is visible. */
4140 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
4143 f
->async_visible
= 1;
4144 f
->async_iconified
= 0;
4145 f
->output_data
.x
->has_been_visible
= 1;
4147 /* wait_reading_process_input will notice this and update
4148 the frame's display structures. */
4149 SET_FRAME_GARBAGED (f
);
4153 bufp
->kind
= deiconify_event
;
4154 XSETFRAME (bufp
->frame_or_window
, f
);
4159 else if (! NILP (Vframe_list
)
4160 && ! NILP (XCONS (Vframe_list
)->cdr
))
4161 /* Force a redisplay sooner or later
4162 to update the frame titles
4163 in case this is the second frame. */
4164 record_asynch_buffer_change ();
4168 /* Turn off processing if we become fully obscured. */
4169 case VisibilityNotify
:
4173 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
4177 KeySym keysym
, orig_keysym
;
4178 /* al%imercury@uunet.uu.net says that making this 81 instead of
4179 80 fixed a bug whereby meta chars made his Emacs hang. */
4180 unsigned char copy_buffer
[81];
4183 #if 0 /* This was how we made f10 work in Motif.
4184 The drawback is, you can't type at Emacs when the
4185 the mouse is in the menu bar. So it is better to
4186 turn off f10 in Motif and let Emacs handle it. */
4188 if (lw_window_is_in_menubar (event
.xkey
.window
,
4189 f
->output_data
.x
->menubar_widget
4192 SET_SAVED_KEY_EVENT
;
4195 #endif /* USE_MOTIF */
4199 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
4200 extra_keyboard_modifiers
);
4201 modifiers
= event
.xkey
.state
;
4203 /* This will have to go some day... */
4205 /* make_lispy_event turns chars into control chars.
4206 Don't do it here because XLookupString is too eager. */
4207 event
.xkey
.state
&= ~ControlMask
;
4208 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
4209 | dpyinfo
->super_mod_mask
4210 | dpyinfo
->hyper_mod_mask
4211 | dpyinfo
->alt_mod_mask
);
4213 /* In case Meta is ComposeCharacter,
4214 clear its status. According to Markus Ehrnsperger
4215 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
4216 this enables ComposeCharacter to work whether or
4217 not it is combined with Meta. */
4218 if (modifiers
& dpyinfo
->meta_mod_mask
)
4219 bzero (&compose_status
, sizeof (compose_status
));
4224 /* The necessity of the following line took me
4225 a full work-day to decipher from the docs!! */
4226 if (XFilterEvent (&event
, None
))
4228 nbytes
= XmbLookupString (FRAME_XIC (f
),
4229 &event
.xkey
, copy_buffer
,
4234 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4235 80, &keysym
, &compose_status
);
4237 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4238 80, &keysym
, &compose_status
);
4241 orig_keysym
= keysym
;
4245 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
4246 || keysym
== XK_Delete
4247 #ifdef XK_ISO_Left_Tab
4248 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
4250 || (keysym
>= XK_Kanji
&& keysym
<= XK_Eisu_toggle
)
4251 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
4252 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
4254 /* This recognizes the "extended function keys".
4255 It seems there's no cleaner way.
4256 Test IsModifierKey to avoid handling mode_switch
4258 || ((unsigned) (keysym
) >= XK_Select
4259 && (unsigned)(keysym
) < XK_KP_Space
)
4261 #ifdef XK_dead_circumflex
4262 || orig_keysym
== XK_dead_circumflex
4264 #ifdef XK_dead_grave
4265 || orig_keysym
== XK_dead_grave
4267 #ifdef XK_dead_tilde
4268 || orig_keysym
== XK_dead_tilde
4270 #ifdef XK_dead_diaeresis
4271 || orig_keysym
== XK_dead_diaeresis
4273 #ifdef XK_dead_macron
4274 || orig_keysym
== XK_dead_macron
4276 #ifdef XK_dead_degree
4277 || orig_keysym
== XK_dead_degree
4279 #ifdef XK_dead_acute
4280 || orig_keysym
== XK_dead_acute
4282 #ifdef XK_dead_cedilla
4283 || orig_keysym
== XK_dead_cedilla
4285 #ifdef XK_dead_breve
4286 || orig_keysym
== XK_dead_breve
4288 #ifdef XK_dead_ogonek
4289 || orig_keysym
== XK_dead_ogonek
4291 #ifdef XK_dead_caron
4292 || orig_keysym
== XK_dead_caron
4294 #ifdef XK_dead_doubleacute
4295 || orig_keysym
== XK_dead_doubleacute
4297 #ifdef XK_dead_abovedot
4298 || orig_keysym
== XK_dead_abovedot
4300 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
4301 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
4302 /* Any "vendor-specific" key is ok. */
4303 || (orig_keysym
& (1 << 28)))
4304 && ! (IsModifierKey (orig_keysym
)
4306 #ifdef XK_Mode_switch
4307 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
4310 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
4312 #endif /* not HAVE_X11R5 */
4315 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4317 temp_buffer
[temp_index
++] = keysym
;
4318 bufp
->kind
= non_ascii_keystroke
;
4319 bufp
->code
= keysym
;
4320 XSETFRAME (bufp
->frame_or_window
, f
);
4322 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4324 bufp
->timestamp
= event
.xkey
.time
;
4329 else if (numchars
> nbytes
)
4333 for (i
= 0; i
< nbytes
; i
++)
4335 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4337 temp_buffer
[temp_index
++] = copy_buffer
[i
];
4338 bufp
->kind
= ascii_keystroke
;
4339 bufp
->code
= copy_buffer
[i
];
4340 XSETFRAME (bufp
->frame_or_window
, f
);
4342 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4344 bufp
->timestamp
= event
.xkey
.time
;
4359 /* Here's a possible interpretation of the whole
4360 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
4361 FocusIn event, you have to get a FocusOut event before you
4362 relinquish the focus. If you haven't received a FocusIn event,
4363 then a mere LeaveNotify is enough to free you. */
4366 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4368 if (event
.xcrossing
.focus
) /* Entered Window */
4370 /* Avoid nasty pop/raise loops. */
4371 if (f
&& (!(f
->auto_raise
)
4373 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4375 x_new_focus_frame (dpyinfo
, f
);
4376 enter_timestamp
= event
.xcrossing
.time
;
4379 else if (f
== dpyinfo
->x_focus_frame
)
4380 x_new_focus_frame (dpyinfo
, 0);
4381 /* EnterNotify counts as mouse movement,
4382 so update things that depend on mouse position. */
4384 note_mouse_movement (f
, &event
.xmotion
);
4388 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4389 if (event
.xfocus
.detail
!= NotifyPointer
)
4390 dpyinfo
->x_focus_event_frame
= f
;
4392 x_new_focus_frame (dpyinfo
, f
);
4395 if (f
&& FRAME_XIC (f
))
4396 XSetICFocus (FRAME_XIC (f
));
4402 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4405 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4406 /* If we move outside the frame,
4407 then we're certainly no longer on any text in the frame. */
4408 clear_mouse_face (dpyinfo
);
4410 if (event
.xcrossing
.focus
)
4411 x_mouse_leave (dpyinfo
);
4414 if (f
== dpyinfo
->x_focus_event_frame
)
4415 dpyinfo
->x_focus_event_frame
= 0;
4416 if (f
== dpyinfo
->x_focus_frame
)
4417 x_new_focus_frame (dpyinfo
, 0);
4423 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4424 if (event
.xfocus
.detail
!= NotifyPointer
4425 && f
== dpyinfo
->x_focus_event_frame
)
4426 dpyinfo
->x_focus_event_frame
= 0;
4427 if (f
&& f
== dpyinfo
->x_focus_frame
)
4428 x_new_focus_frame (dpyinfo
, 0);
4431 if (f
&& FRAME_XIC (f
))
4432 XUnsetICFocus (FRAME_XIC (f
));
4439 if (dpyinfo
->grabbed
&& last_mouse_frame
4440 && FRAME_LIVE_P (last_mouse_frame
))
4441 f
= last_mouse_frame
;
4443 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
4445 note_mouse_movement (f
, &event
.xmotion
);
4448 struct scroll_bar
*bar
4449 = x_window_to_scroll_bar (event
.xmotion
.window
);
4452 x_scroll_bar_note_movement (bar
, &event
);
4454 /* If we move outside the frame,
4455 then we're certainly no longer on any text in the frame. */
4456 clear_mouse_face (dpyinfo
);
4461 case ConfigureNotify
:
4462 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
4465 #ifndef USE_X_TOOLKIT
4466 /* In the toolkit version, change_frame_size
4467 is called by the code that handles resizing
4468 of the EmacsFrame widget. */
4470 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4471 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4473 /* Even if the number of character rows and columns has
4474 not changed, the font size may have changed, so we need
4475 to check the pixel dimensions as well. */
4476 if (columns
!= f
->width
4477 || rows
!= f
->height
4478 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
4479 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
4481 change_frame_size (f
, rows
, columns
, 0, 1);
4482 SET_FRAME_GARBAGED (f
);
4483 cancel_mouse_face (f
);
4487 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
4488 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
4490 /* What we have now is the position of Emacs's own window.
4491 Convert that to the position of the window manager window. */
4492 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
4493 &f
->output_data
.x
->top_pos
);
4495 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4497 /* Since the WM decorations come below top_pos now,
4498 we must put them below top_pos in the future. */
4499 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4500 x_wm_set_size_hint (f
, (long) 0, 0);
4503 /* Some window managers pass (0,0) as the location of
4504 the window, and the Motif event handler stores it
4505 in the emacs widget, which messes up Motif menus. */
4506 if (event
.xconfigure
.x
== 0 && event
.xconfigure
.y
== 0)
4508 event
.xconfigure
.x
= f
->output_data
.x
->widget
->core
.x
;
4509 event
.xconfigure
.y
= f
->output_data
.x
->widget
->core
.y
;
4518 /* If we decide we want to generate an event to be seen
4519 by the rest of Emacs, we put it here. */
4520 struct input_event emacs_event
;
4521 emacs_event
.kind
= no_event
;
4523 bzero (&compose_status
, sizeof (compose_status
));
4525 if (dpyinfo
->grabbed
&& last_mouse_frame
4526 && FRAME_LIVE_P (last_mouse_frame
))
4527 f
= last_mouse_frame
;
4529 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4533 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4534 construct_mouse_click (&emacs_event
, &event
, f
);
4538 struct scroll_bar
*bar
4539 = x_window_to_scroll_bar (event
.xbutton
.window
);
4542 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4545 if (event
.type
== ButtonPress
)
4547 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4548 last_mouse_frame
= f
;
4552 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4555 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4557 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4563 #ifdef USE_X_TOOLKIT
4564 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4565 /* For a down-event in the menu bar,
4566 don't pass it to Xt right now.
4567 Instead, save it away
4568 and we will pass it to Xt from kbd_buffer_get_event.
4569 That way, we can run some Lisp code first. */
4570 if (f
&& event
.type
== ButtonPress
4571 /* Verify the event is really within the menu bar
4572 and not just sent to it due to grabbing. */
4573 && event
.xbutton
.x
>= 0
4574 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4575 && event
.xbutton
.y
>= 0
4576 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4577 && event
.xbutton
.same_screen
)
4579 SET_SAVED_BUTTON_EVENT
;
4580 XSETFRAME (last_mouse_press_frame
, f
);
4582 else if (event
.type
== ButtonPress
)
4584 last_mouse_press_frame
= Qnil
;
4587 #ifdef USE_MOTIF /* This should do not harm for Lucid,
4588 but I am trying to be cautious. */
4589 else if (event
.type
== ButtonRelease
)
4591 if (!NILP (last_mouse_press_frame
))
4593 f
= XFRAME (last_mouse_press_frame
);
4594 if (f
->output_data
.x
)
4596 SET_SAVED_BUTTON_EVENT
;
4602 #endif /* USE_MOTIF */
4605 #endif /* USE_X_TOOLKIT */
4609 case CirculateNotify
:
4611 case CirculateRequest
:
4615 /* Someone has changed the keyboard mapping - update the
4617 switch (event
.xmapping
.request
)
4619 case MappingModifier
:
4620 x_find_modifier_meanings (dpyinfo
);
4621 /* This is meant to fall through. */
4622 case MappingKeyboard
:
4623 XRefreshKeyboardMapping (&event
.xmapping
);
4629 #ifdef USE_X_TOOLKIT
4631 XtDispatchEvent (&event
);
4633 #endif /* USE_X_TOOLKIT */
4639 /* On some systems, an X bug causes Emacs to get no more events
4640 when the window is destroyed. Detect that. (1994.) */
4643 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4644 One XNOOP in 100 loops will make Emacs terminate.
4645 B. Bretthauer, 1994 */
4647 if (x_noop_count
>= 100)
4651 if (next_noop_dpyinfo
== 0)
4652 next_noop_dpyinfo
= x_display_list
;
4654 XNoOp (next_noop_dpyinfo
->display
);
4656 /* Each time we get here, cycle through the displays now open. */
4657 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4661 /* If the focus was just given to an autoraising frame,
4663 /* ??? This ought to be able to handle more than one such frame. */
4664 if (pending_autoraise_frame
)
4666 x_raise_frame (pending_autoraise_frame
);
4667 pending_autoraise_frame
= 0;
4674 /* Drawing the cursor. */
4677 /* Draw a hollow box cursor on frame F at X, Y.
4678 Don't change the inside of the box. */
4681 x_draw_box (f
, x
, y
)
4685 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4686 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4687 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4688 int height
= f
->output_data
.x
->line_height
;
4689 int c
= FAST_GLYPH_CHAR (f
->phys_cursor_glyph
);
4690 int charset
= CHAR_CHARSET (c
);
4693 unsigned long mask
= GCForeground
;
4695 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
4697 /* cursor_gc's foreground color is typically the same as the normal
4698 background color, which can cause the cursor box to be invisible. */
4699 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
4700 XChangeGC (FRAME_X_DISPLAY (f
),
4701 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4704 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
4705 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), mask
, &xgcv
);
4707 /* If cursor is on a multi-column character, multiply WIDTH by columns. */
4708 width
*= (charset
== CHARSET_COMPOSITION
4709 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4710 : CHARSET_WIDTH (charset
));
4711 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4712 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4713 left
, top
, width
- 1, height
- 1);
4716 /* Clear the cursor of frame F to background color,
4717 and mark the cursor as not shown.
4718 This is used when the text where the cursor is
4719 is about to be rewritten. */
4727 if (! FRAME_VISIBLE_P (f
)
4728 || ! f
->phys_cursor_on
)
4731 x_update_cursor (f
, 0);
4732 f
->phys_cursor_on
= 0;
4735 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4736 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4740 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4747 CHAR_TO_PIXEL_COL (f
, column
),
4748 CHAR_TO_PIXEL_ROW (f
, row
),
4749 &glyph
, 1, highlight
, 0, NULL
);
4753 x_display_bar_cursor (f
, on
, x
, y
)
4758 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4760 /* This is pointless on invisible frames, and dangerous on garbaged
4761 frames; in the latter case, the frame may be in the midst of
4762 changing its size, and x and y may be off the frame. */
4763 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4766 if (! on
&& ! f
->phys_cursor_on
)
4769 /* If there is anything wrong with the current cursor state, remove it. */
4770 if (f
->phys_cursor_on
4772 || f
->phys_cursor_x
!= x
4773 || f
->phys_cursor_y
!= y
4774 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4776 /* Erase the cursor by redrawing the character underneath it. */
4777 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4778 f
->phys_cursor_glyph
,
4779 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4780 f
->phys_cursor_on
= 0;
4783 /* If we now need a cursor in the new place or in the new form, do it so. */
4785 && (! f
->phys_cursor_on
4786 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4788 f
->phys_cursor_glyph
4789 = ((current_glyphs
->enable
[y
]
4790 && x
< current_glyphs
->used
[y
])
4791 ? current_glyphs
->glyphs
[y
][x
]
4793 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4794 f
->output_data
.x
->cursor_gc
,
4795 CHAR_TO_PIXEL_COL (f
, x
),
4796 CHAR_TO_PIXEL_ROW (f
, y
),
4797 max (f
->output_data
.x
->cursor_width
, 1),
4798 f
->output_data
.x
->line_height
);
4800 f
->phys_cursor_x
= x
;
4801 f
->phys_cursor_y
= y
;
4802 f
->phys_cursor_on
= 1;
4804 f
->output_data
.x
->current_cursor
= bar_cursor
;
4807 if (updating_frame
!= f
)
4808 XFlush (FRAME_X_DISPLAY (f
));
4812 /* Turn the displayed cursor of frame F on or off according to ON.
4813 If ON is nonzero, where to put the cursor is specified by X and Y. */
4816 x_display_box_cursor (f
, on
, x
, y
)
4821 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4823 /* This is pointless on invisible frames, and dangerous on garbaged
4824 frames; in the latter case, the frame may be in the midst of
4825 changing its size, and x and y may be off the frame. */
4826 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4829 /* If cursor is off and we want it off, return quickly. */
4830 if (!on
&& ! f
->phys_cursor_on
)
4833 /* If cursor is currently being shown and we don't want it to be
4834 or it is in the wrong place,
4835 or we want a hollow box and it's not so, (pout!)
4837 if (f
->phys_cursor_on
4839 || f
->phys_cursor_x
!= x
4840 || f
->phys_cursor_y
!= y
4841 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4842 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4844 int mouse_face_here
= 0;
4845 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4847 /* If the cursor is in the mouse face area, redisplay that when
4848 we clear the cursor. */
4849 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4851 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4852 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4853 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4855 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4856 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4857 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4858 /* Don't redraw the cursor's spot in mouse face
4859 if it is at the end of a line (on a newline).
4860 The cursor appears there, but mouse highlighting does not. */
4861 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4862 mouse_face_here
= 1;
4864 /* If the font is not as tall as a whole line,
4865 we must explicitly clear the line's whole height. */
4866 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4867 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4868 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4869 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4870 FONT_WIDTH (f
->output_data
.x
->font
),
4871 f
->output_data
.x
->line_height
, False
);
4872 /* Erase the cursor by redrawing the character underneath it. */
4873 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4874 f
->phys_cursor_glyph
,
4877 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4878 f
->phys_cursor_on
= 0;
4881 /* If we want to show a cursor,
4882 or we want a box cursor and it's not so,
4883 write it in the right place. */
4885 && (! f
->phys_cursor_on
4886 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4887 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4889 f
->phys_cursor_glyph
4890 = ((current_glyphs
->enable
[y
]
4891 && x
< current_glyphs
->used
[y
])
4892 ? current_glyphs
->glyphs
[y
][x
]
4894 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4896 x_draw_box (f
, x
, y
);
4897 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4901 x_draw_single_glyph (f
, y
, x
,
4902 f
->phys_cursor_glyph
, 2);
4903 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4906 f
->phys_cursor_x
= x
;
4907 f
->phys_cursor_y
= y
;
4908 f
->phys_cursor_on
= 1;
4911 if (updating_frame
!= f
)
4912 XFlush (FRAME_X_DISPLAY (f
));
4915 /* Display the cursor on frame F, or clear it, according to ON.
4916 Also set the frame's cursor position to X and Y. */
4919 x_display_cursor (f
, on
, x
, y
)
4926 if ((unsigned) x
>= FRAME_CURSOR_X_LIMIT (f
)
4927 || (unsigned) y
>= FRAME_HEIGHT (f
))
4930 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4931 x_display_box_cursor (f
, on
, x
, y
);
4932 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4933 x_display_bar_cursor (f
, on
, x
, y
);
4935 /* Those are the only two we have implemented! */
4941 /* Display the cursor on frame F, or clear it, according to ON.
4942 Don't change the cursor's position. */
4945 x_update_cursor (f
, on
)
4951 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4952 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4953 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4954 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4956 /* Those are the only two we have implemented! */
4964 /* Refresh bitmap kitchen sink icon for frame F
4965 when we get an expose event for it. */
4971 /* Normally, the window manager handles this function. */
4974 /* Make the x-window of frame F use the gnu icon bitmap. */
4977 x_bitmap_icon (f
, file
)
4981 int mask
, bitmap_id
;
4984 if (FRAME_X_WINDOW (f
) == 0)
4987 /* Free up our existing icon bitmap if any. */
4988 if (f
->output_data
.x
->icon_bitmap
> 0)
4989 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4990 f
->output_data
.x
->icon_bitmap
= 0;
4993 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4996 /* Create the GNU bitmap if necessary. */
4997 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4998 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4999 = x_create_bitmap_from_data (f
, gnu_bits
,
5000 gnu_width
, gnu_height
);
5002 /* The first time we create the GNU bitmap,
5003 this increments the refcount one extra time.
5004 As a result, the GNU bitmap is never freed.
5005 That way, we don't have to worry about allocating it again. */
5006 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
5008 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
5011 x_wm_set_icon_pixmap (f
, bitmap_id
);
5012 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
5018 /* Make the x-window of frame F use a rectangle with text.
5019 Use ICON_NAME as the text. */
5022 x_text_icon (f
, icon_name
)
5026 if (FRAME_X_WINDOW (f
) == 0)
5032 text
.value
= (unsigned char *) icon_name
;
5033 text
.encoding
= XA_STRING
;
5035 text
.nitems
= strlen (icon_name
);
5036 #ifdef USE_X_TOOLKIT
5037 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5039 #else /* not USE_X_TOOLKIT */
5040 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
5041 #endif /* not USE_X_TOOLKIT */
5043 #else /* not HAVE_X11R4 */
5044 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
5045 #endif /* not HAVE_X11R4 */
5047 if (f
->output_data
.x
->icon_bitmap
> 0)
5048 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
5049 f
->output_data
.x
->icon_bitmap
= 0;
5050 x_wm_set_icon_pixmap (f
, 0);
5055 #define X_ERROR_MESSAGE_SIZE 200
5057 /* If non-nil, this should be a string.
5058 It means catch X errors and store the error message in this string. */
5060 static Lisp_Object x_error_message_string
;
5062 /* An X error handler which stores the error message in
5063 x_error_message_string. This is called from x_error_handler if
5064 x_catch_errors is in effect. */
5067 x_error_catcher (display
, error
)
5071 XGetErrorText (display
, error
->error_code
,
5072 XSTRING (x_error_message_string
)->data
,
5073 X_ERROR_MESSAGE_SIZE
);
5076 /* Begin trapping X errors for display DPY. Actually we trap X errors
5077 for all displays, but DPY should be the display you are actually
5080 After calling this function, X protocol errors no longer cause
5081 Emacs to exit; instead, they are recorded in the string
5082 stored in x_error_message_string.
5084 Calling x_check_errors signals an Emacs error if an X error has
5085 occurred since the last call to x_catch_errors or x_check_errors.
5087 Calling x_uncatch_errors resumes the normal error handling. */
5089 void x_check_errors ();
5090 static Lisp_Object
x_catch_errors_unwind ();
5093 x_catch_errors (dpy
)
5096 int count
= specpdl_ptr
- specpdl
;
5098 /* Make sure any errors from previous requests have been dealt with. */
5101 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
5103 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
5104 XSTRING (x_error_message_string
)->data
[0] = 0;
5109 /* Unbind the binding that we made to check for X errors. */
5112 x_catch_errors_unwind (old_val
)
5113 Lisp_Object old_val
;
5115 x_error_message_string
= old_val
;
5119 /* If any X protocol errors have arrived since the last call to
5120 x_catch_errors or x_check_errors, signal an Emacs error using
5121 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5124 x_check_errors (dpy
, format
)
5128 /* Make sure to catch any errors incurred so far. */
5131 if (XSTRING (x_error_message_string
)->data
[0])
5132 error (format
, XSTRING (x_error_message_string
)->data
);
5135 /* Nonzero if we had any X protocol errors
5136 since we did x_catch_errors on DPY. */
5139 x_had_errors_p (dpy
)
5142 /* Make sure to catch any errors incurred so far. */
5145 return XSTRING (x_error_message_string
)->data
[0] != 0;
5148 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
5151 x_clear_errors (dpy
)
5154 XSTRING (x_error_message_string
)->data
[0] = 0;
5157 /* Stop catching X protocol errors and let them make Emacs die.
5158 DPY should be the display that was passed to x_catch_errors.
5159 COUNT should be the value that was returned by
5160 the corresponding call to x_catch_errors. */
5163 x_uncatch_errors (dpy
, count
)
5167 unbind_to (count
, Qnil
);
5171 static unsigned int x_wire_count
;
5174 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5179 /* Handle SIGPIPE, which can happen when the connection to a server
5180 simply goes away. SIGPIPE is handled by x_connection_signal.
5181 Don't need to do anything, because the write which caused the
5182 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
5183 which will do the appropriate cleanup for us. */
5186 x_connection_signal (signalnum
) /* If we don't have an argument, */
5187 int signalnum
; /* some compilers complain in signal calls. */
5190 /* USG systems forget handlers when they are used;
5191 must reestablish each time */
5192 signal (signalnum
, x_connection_signal
);
5196 /* Handling X errors. */
5198 /* Handle the loss of connection to display DISPLAY. */
5201 x_connection_closed (display
, error_message
)
5203 char *error_message
;
5205 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
5206 Lisp_Object frame
, tail
;
5208 /* Indicate that this display is dead. */
5210 #ifdef USE_X_TOOLKIT
5211 XtCloseDisplay (display
);
5214 dpyinfo
->display
= 0;
5216 /* First delete frames whose minibuffers are on frames
5217 that are on the dead display. */
5218 FOR_EACH_FRAME (tail
, frame
)
5220 Lisp_Object minibuf_frame
;
5222 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
5223 if (FRAME_X_P (XFRAME (frame
))
5224 && FRAME_X_P (XFRAME (minibuf_frame
))
5225 && ! EQ (frame
, minibuf_frame
)
5226 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
5227 Fdelete_frame (frame
, Qt
);
5230 /* Now delete all remaining frames on the dead display.
5231 We are now sure none of these is used as the minibuffer
5232 for another frame that we need to delete. */
5233 FOR_EACH_FRAME (tail
, frame
)
5234 if (FRAME_X_P (XFRAME (frame
))
5235 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
5237 /* Set this to t so that Fdelete_frame won't get confused
5238 trying to find a replacement. */
5239 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
5240 Fdelete_frame (frame
, Qt
);
5244 x_delete_display (dpyinfo
);
5246 if (x_display_list
== 0)
5248 fprintf (stderr
, "%s\n", error_message
);
5249 shut_down_emacs (0, 0, Qnil
);
5253 /* Ordinary stack unwind doesn't deal with these. */
5255 sigunblock (sigmask (SIGIO
));
5257 sigunblock (sigmask (SIGALRM
));
5258 TOTALLY_UNBLOCK_INPUT
;
5260 clear_waiting_for_input ();
5261 error ("%s", error_message
);
5264 /* This is the usual handler for X protocol errors.
5265 It kills all frames on the display that we got the error for.
5266 If that was the only one, it prints an error message and kills Emacs. */
5269 x_error_quitter (display
, error
)
5273 char buf
[256], buf1
[356];
5275 /* Note that there is no real way portable across R3/R4 to get the
5276 original error handler. */
5278 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
5279 sprintf (buf1
, "X protocol error: %s on protocol request %d",
5280 buf
, error
->request_code
);
5281 x_connection_closed (display
, buf1
);
5284 /* This is the first-level handler for X protocol errors.
5285 It calls x_error_quitter or x_error_catcher. */
5288 x_error_handler (display
, error
)
5292 char buf
[256], buf1
[356];
5294 if (! NILP (x_error_message_string
))
5295 x_error_catcher (display
, error
);
5297 x_error_quitter (display
, error
);
5300 /* This is the handler for X IO errors, always.
5301 It kills all frames on the display that we lost touch with.
5302 If that was the only one, it prints an error message and kills Emacs. */
5305 x_io_error_quitter (display
)
5310 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
5311 x_connection_closed (display
, buf
);
5314 /* Changing the font of the frame. */
5316 /* Give frame F the font named FONTNAME as its default font, and
5317 return the full name of that font. FONTNAME may be a wildcard
5318 pattern; in that case, we choose some font that fits the pattern.
5319 The return value shows which font we chose. */
5322 x_new_font (f
, fontname
)
5324 register char *fontname
;
5326 struct font_info
*fontp
5327 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
5332 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
5333 f
->output_data
.x
->font_baseline
5334 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
5335 f
->output_data
.x
->fontset
= -1;
5337 /* Compute the scroll bar width in character columns. */
5338 if (f
->scroll_bar_pixel_width
> 0)
5340 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5341 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
5345 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5346 f
->scroll_bar_cols
= (14 + wid
- 1) / wid
;
5349 /* Now make the frame display the given font. */
5350 if (FRAME_X_WINDOW (f
) != 0)
5352 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
5353 f
->output_data
.x
->font
->fid
);
5354 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
5355 f
->output_data
.x
->font
->fid
);
5356 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
5357 f
->output_data
.x
->font
->fid
);
5359 frame_update_line_height (f
);
5360 x_set_window_size (f
, 0, f
->width
, f
->height
);
5363 /* If we are setting a new frame's font for the first time,
5364 there are no faces yet, so this font's height is the line height. */
5365 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
5367 return build_string (fontp
->full_name
);
5370 /* Give frame F the fontset named FONTSETNAME as its default font, and
5371 return the full name of that fontset. FONTSETNAME may be a wildcard
5372 pattern; in that case, we choose some fontset that fits the pattern.
5373 The return value shows which fontset we chose. */
5376 x_new_fontset (f
, fontsetname
)
5380 int fontset
= fs_query_fontset (f
, fontsetname
);
5381 struct fontset_info
*fontsetp
;
5387 if (f
->output_data
.x
->fontset
== fontset
)
5388 /* This fontset is already set in frame F. There's nothing more
5390 return build_string (fontsetname
);
5392 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
5394 if (!fontsetp
->fontname
[CHARSET_ASCII
])
5395 /* This fontset doesn't contain ASCII font. */
5398 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
5400 if (!STRINGP (result
))
5401 /* Can't load ASCII font. */
5404 /* Since x_new_font doesn't update any fontset information, do it now. */
5405 f
->output_data
.x
->fontset
= fontset
;
5406 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
5407 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
5409 return build_string (fontsetname
);
5412 /* Calculate the absolute position in frame F
5413 from its current recorded position values and gravity. */
5416 x_calc_absolute_position (f
)
5420 int win_x
= 0, win_y
= 0;
5421 int flags
= f
->output_data
.x
->size_hint_flags
;
5424 /* We have nothing to do if the current position
5425 is already for the top-left corner. */
5426 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5429 #ifdef USE_X_TOOLKIT
5430 this_window
= XtWindow (f
->output_data
.x
->widget
);
5432 this_window
= FRAME_X_WINDOW (f
);
5435 /* Find the position of the outside upper-left corner of
5436 the inner window, with respect to the outer window.
5437 But do this only if we will need the results. */
5438 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
5443 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
5446 x_clear_errors (FRAME_X_DISPLAY (f
));
5447 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
5449 /* From-window, to-window. */
5451 f
->output_data
.x
->parent_desc
,
5453 /* From-position, to-position. */
5454 0, 0, &win_x
, &win_y
,
5458 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
5460 Window newroot
, newparent
= 0xdeadbeef;
5461 Window
*newchildren
;
5464 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
5465 &newparent
, &newchildren
, &nchildren
))
5468 XFree (newchildren
);
5470 f
->output_data
.x
->parent_desc
= newparent
;
5476 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
5480 /* Treat negative positions as relative to the leftmost bottommost
5481 position that fits on the screen. */
5482 if (flags
& XNegative
)
5483 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5484 - 2 * f
->output_data
.x
->border_width
- win_x
5486 + f
->output_data
.x
->left_pos
);
5488 if (flags
& YNegative
)
5489 /* We used to subtract f->output_data.x->menubar_height here
5490 in the toolkit case, but PIXEL_HEIGHT already includes that. */
5491 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5492 - 2 * f
->output_data
.x
->border_width
- win_y
5494 + f
->output_data
.x
->top_pos
);
5496 /* The left_pos and top_pos
5497 are now relative to the top and left screen edges,
5498 so the flags should correspond. */
5499 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5502 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5503 to really change the position, and 0 when calling from
5504 x_make_frame_visible (in that case, XOFF and YOFF are the current
5505 position values). It is -1 when calling from x_set_frame_parameters,
5506 which means, do adjust for borders but don't change the gravity. */
5509 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5511 register int xoff
, yoff
;
5514 int modified_top
, modified_left
;
5516 if (change_gravity
> 0)
5518 f
->output_data
.x
->top_pos
= yoff
;
5519 f
->output_data
.x
->left_pos
= xoff
;
5520 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5522 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5524 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5525 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5527 x_calc_absolute_position (f
);
5530 x_wm_set_size_hint (f
, (long) 0, 0);
5532 modified_left
= f
->output_data
.x
->left_pos
;
5533 modified_top
= f
->output_data
.x
->top_pos
;
5534 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
5535 this seems to be unnecessary and incorrect. rms, 4/17/97. */
5536 /* It is a mystery why we need to add the border_width here
5537 when the frame is already visible, but experiment says we do. */
5538 if (change_gravity
!= 0)
5540 modified_left
+= f
->output_data
.x
->border_width
;
5541 modified_top
+= f
->output_data
.x
->border_width
;
5545 #ifdef USE_X_TOOLKIT
5546 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5547 modified_left
, modified_top
);
5548 #else /* not USE_X_TOOLKIT */
5549 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5550 modified_left
, modified_top
);
5551 #endif /* not USE_X_TOOLKIT */
5555 /* Call this to change the size of frame F's x-window.
5556 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5557 for this size change and subsequent size changes.
5558 Otherwise we leave the window gravity unchanged. */
5561 x_set_window_size (f
, change_gravity
, cols
, rows
)
5566 int pixelwidth
, pixelheight
;
5568 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5572 #ifdef USE_X_TOOLKIT
5574 /* The x and y position of the widget is clobbered by the
5575 call to XtSetValues within EmacsFrameSetCharSize.
5576 This is a real kludge, but I don't understand Xt so I can't
5577 figure out a correct fix. Can anyone else tell me? -- rms. */
5578 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5579 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5580 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5581 f
->output_data
.x
->widget
->core
.x
= xpos
;
5582 f
->output_data
.x
->widget
->core
.y
= ypos
;
5585 #else /* not USE_X_TOOLKIT */
5587 check_frame_size (f
, &rows
, &cols
);
5588 f
->output_data
.x
->vertical_scroll_bar_extra
5589 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5591 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5592 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5593 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5594 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5595 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5597 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5598 x_wm_set_size_hint (f
, (long) 0, 0);
5600 XSync (FRAME_X_DISPLAY (f
), False
);
5601 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5602 pixelwidth
, pixelheight
);
5604 /* Now, strictly speaking, we can't be sure that this is accurate,
5605 but the window manager will get around to dealing with the size
5606 change request eventually, and we'll hear how it went when the
5607 ConfigureNotify event gets here.
5609 We could just not bother storing any of this information here,
5610 and let the ConfigureNotify event set everything up, but that
5611 might be kind of confusing to the lisp code, since size changes
5612 wouldn't be reported in the frame parameters until some random
5613 point in the future when the ConfigureNotify event arrives. */
5614 change_frame_size (f
, rows
, cols
, 0, 0);
5615 PIXEL_WIDTH (f
) = pixelwidth
;
5616 PIXEL_HEIGHT (f
) = pixelheight
;
5618 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5619 receive in the ConfigureNotify event; if we get what we asked
5620 for, then the event won't cause the screen to become garbaged, so
5621 we have to make sure to do it here. */
5622 SET_FRAME_GARBAGED (f
);
5624 XFlush (FRAME_X_DISPLAY (f
));
5626 #endif /* not USE_X_TOOLKIT */
5628 /* If cursor was outside the new size, mark it as off. */
5629 if (f
->phys_cursor_y
>= rows
5630 || f
->phys_cursor_x
>= cols
)
5632 f
->phys_cursor_x
= 0;
5633 f
->phys_cursor_y
= 0;
5634 f
->phys_cursor_on
= 0;
5637 /* Clear out any recollection of where the mouse highlighting was,
5638 since it might be in a place that's outside the new frame size.
5639 Actually checking whether it is outside is a pain in the neck,
5640 so don't try--just let the highlighting be done afresh with new size. */
5641 cancel_mouse_face (f
);
5646 /* Mouse warping. */
5649 x_set_mouse_position (f
, x
, y
)
5655 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5656 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5658 if (pix_x
< 0) pix_x
= 0;
5659 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5661 if (pix_y
< 0) pix_y
= 0;
5662 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5666 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5667 0, 0, 0, 0, pix_x
, pix_y
);
5671 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5674 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5680 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5681 0, 0, 0, 0, pix_x
, pix_y
);
5685 /* focus shifting, raising and lowering. */
5688 x_focus_on_frame (f
)
5691 #if 0 /* This proves to be unpleasant. */
5695 /* I don't think that the ICCCM allows programs to do things like this
5696 without the interaction of the window manager. Whatever you end up
5697 doing with this code, do it to x_unfocus_frame too. */
5698 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5699 RevertToPointerRoot
, CurrentTime
);
5708 /* Look at the remarks in x_focus_on_frame. */
5709 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5710 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5711 RevertToPointerRoot
, CurrentTime
);
5715 /* Raise frame F. */
5721 if (f
->async_visible
)
5724 #ifdef USE_X_TOOLKIT
5725 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5726 #else /* not USE_X_TOOLKIT */
5727 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5728 #endif /* not USE_X_TOOLKIT */
5729 XFlush (FRAME_X_DISPLAY (f
));
5734 /* Lower frame F. */
5740 if (f
->async_visible
)
5743 #ifdef USE_X_TOOLKIT
5744 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5745 #else /* not USE_X_TOOLKIT */
5746 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5747 #endif /* not USE_X_TOOLKIT */
5748 XFlush (FRAME_X_DISPLAY (f
));
5754 XTframe_raise_lower (f
, raise_flag
)
5764 /* Change of visibility. */
5766 /* This tries to wait until the frame is really visible.
5767 However, if the window manager asks the user where to position
5768 the frame, this will return before the user finishes doing that.
5769 The frame will not actually be visible at that time,
5770 but it will become visible later when the window manager
5771 finishes with it. */
5774 x_make_frame_visible (f
)
5779 int starting_flags
= f
->output_data
.x
->size_hint_flags
;
5780 int original_top
, original_left
;
5784 type
= x_icon_type (f
);
5786 x_bitmap_icon (f
, type
);
5788 if (! FRAME_VISIBLE_P (f
))
5790 /* We test FRAME_GARBAGED_P here to make sure we don't
5791 call x_set_offset a second time
5792 if we get to x_make_frame_visible a second time
5793 before the window gets really visible. */
5794 if (! FRAME_ICONIFIED_P (f
)
5795 && ! f
->output_data
.x
->asked_for_visible
)
5796 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5798 f
->output_data
.x
->asked_for_visible
= 1;
5800 if (! EQ (Vx_no_window_manager
, Qt
))
5801 x_wm_set_window_state (f
, NormalState
);
5802 #ifdef USE_X_TOOLKIT
5803 /* This was XtPopup, but that did nothing for an iconified frame. */
5804 XtMapWidget (f
->output_data
.x
->widget
);
5805 #else /* not USE_X_TOOLKIT */
5806 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5807 #endif /* not USE_X_TOOLKIT */
5808 #if 0 /* This seems to bring back scroll bars in the wrong places
5809 if the window configuration has changed. They seem
5810 to come back ok without this. */
5811 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5812 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5816 XFlush (FRAME_X_DISPLAY (f
));
5818 /* Synchronize to ensure Emacs knows the frame is visible
5819 before we do anything else. We do this loop with input not blocked
5820 so that incoming events are handled. */
5823 int count
= input_signal_count
;
5824 /* This must be before UNBLOCK_INPUT
5825 since events that arrive in response to the actions above
5826 will set it when they are handled. */
5827 int previously_visible
= f
->output_data
.x
->has_been_visible
;
5829 original_left
= f
->output_data
.x
->left_pos
;
5830 original_top
= f
->output_data
.x
->top_pos
;
5832 /* This must come after we set COUNT. */
5835 /* Arriving X events are processed here. */
5837 /* Now move the window back to where it was "supposed to be".
5838 But don't do it if the gravity is negative.
5839 When the gravity is negative, this uses a position
5840 that is 3 pixels too low. Perhaps that's really the border width.
5842 Don't do this if the window has never been visible before,
5843 because the window manager may choose the position
5844 and we don't want to override it. */
5846 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
5847 && f
->output_data
.x
->win_gravity
== NorthWestGravity
5848 && previously_visible
)
5852 #ifdef USE_X_TOOLKIT
5853 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5854 original_left
, original_top
);
5855 #else /* not USE_X_TOOLKIT */
5856 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5857 original_left
, original_top
);
5858 #endif /* not USE_X_TOOLKIT */
5862 XSETFRAME (frame
, f
);
5867 /* Once we have handled input events,
5868 we should have received the MapNotify if one is coming.
5869 So if we have not got it yet, stop looping.
5870 Some window managers make their own decisions
5871 about visibility. */
5872 if (input_signal_count
!= count
)
5874 /* Machines that do polling rather than SIGIO have been observed
5875 to go into a busy-wait here. So we'll fake an alarm signal
5876 to let the handler know that there's something to be read.
5877 We used to raise a real alarm, but it seems that the handler
5878 isn't always enabled here. This is probably a bug. */
5879 if (input_polling_used ())
5881 /* It could be confusing if a real alarm arrives while processing
5882 the fake one. Turn it off and let the handler reset it. */
5884 input_poll_signal (0);
5886 /* Once we have handled input events,
5887 we should have received the MapNotify if one is coming.
5888 So if we have not got it yet, stop looping.
5889 Some window managers make their own decisions
5890 about visibility. */
5891 if (input_signal_count
!= count
)
5894 FRAME_SAMPLE_VISIBILITY (f
);
5898 /* Change from mapped state to withdrawn state. */
5900 /* Make the frame visible (mapped and not iconified). */
5903 x_make_frame_invisible (f
)
5909 #ifdef USE_X_TOOLKIT
5910 /* Use the frame's outermost window, not the one we normally draw on. */
5911 window
= XtWindow (f
->output_data
.x
->widget
);
5912 #else /* not USE_X_TOOLKIT */
5913 window
= FRAME_X_WINDOW (f
);
5914 #endif /* not USE_X_TOOLKIT */
5916 /* Don't keep the highlight on an invisible frame. */
5917 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5918 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5920 #if 0/* This might add unreliability; I don't trust it -- rms. */
5921 if (! f
->async_visible
&& ! f
->async_iconified
)
5927 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5928 that the current position of the window is user-specified, rather than
5929 program-specified, so that when the window is mapped again, it will be
5930 placed at the same location, without forcing the user to position it
5931 by hand again (they have already done that once for this window.) */
5932 x_wm_set_size_hint (f
, (long) 0, 1);
5936 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5937 DefaultScreen (FRAME_X_DISPLAY (f
))))
5939 UNBLOCK_INPUT_RESIGNAL
;
5940 error ("Can't notify window manager of window withdrawal");
5942 #else /* ! defined (HAVE_X11R4) */
5944 /* Tell the window manager what we're going to do. */
5945 if (! EQ (Vx_no_window_manager
, Qt
))
5949 unmap
.xunmap
.type
= UnmapNotify
;
5950 unmap
.xunmap
.window
= window
;
5951 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5952 unmap
.xunmap
.from_configure
= False
;
5953 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5954 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5956 SubstructureRedirectMask
|SubstructureNotifyMask
,
5959 UNBLOCK_INPUT_RESIGNAL
;
5960 error ("Can't notify window manager of withdrawal");
5964 /* Unmap the window ourselves. Cheeky! */
5965 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5966 #endif /* ! defined (HAVE_X11R4) */
5968 /* We can't distinguish this from iconification
5969 just by the event that we get from the server.
5970 So we can't win using the usual strategy of letting
5971 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5972 and synchronize with the server to make sure we agree. */
5974 FRAME_ICONIFIED_P (f
) = 0;
5975 f
->async_visible
= 0;
5976 f
->async_iconified
= 0;
5983 /* Change window state from mapped to iconified. */
5993 /* Don't keep the highlight on an invisible frame. */
5994 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5995 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5997 if (f
->async_iconified
)
6002 FRAME_SAMPLE_VISIBILITY (f
);
6004 type
= x_icon_type (f
);
6006 x_bitmap_icon (f
, type
);
6008 #ifdef USE_X_TOOLKIT
6010 if (! FRAME_VISIBLE_P (f
))
6012 if (! EQ (Vx_no_window_manager
, Qt
))
6013 x_wm_set_window_state (f
, IconicState
);
6014 /* This was XtPopup, but that did nothing for an iconified frame. */
6015 XtMapWidget (f
->output_data
.x
->widget
);
6016 /* The server won't give us any event to indicate
6017 that an invisible frame was changed to an icon,
6018 so we have to record it here. */
6021 f
->async_iconified
= 1;
6022 f
->async_visible
= 0;
6027 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
6028 XtWindow (f
->output_data
.x
->widget
),
6029 DefaultScreen (FRAME_X_DISPLAY (f
)));
6033 error ("Can't notify window manager of iconification");
6035 f
->async_iconified
= 1;
6036 f
->async_visible
= 0;
6040 XFlush (FRAME_X_DISPLAY (f
));
6042 #else /* not USE_X_TOOLKIT */
6044 /* Make sure the X server knows where the window should be positioned,
6045 in case the user deiconifies with the window manager. */
6046 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
6047 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
6049 /* Since we don't know which revision of X we're running, we'll use both
6050 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
6052 /* X11R4: send a ClientMessage to the window manager using the
6053 WM_CHANGE_STATE type. */
6057 message
.xclient
.window
= FRAME_X_WINDOW (f
);
6058 message
.xclient
.type
= ClientMessage
;
6059 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
6060 message
.xclient
.format
= 32;
6061 message
.xclient
.data
.l
[0] = IconicState
;
6063 if (! XSendEvent (FRAME_X_DISPLAY (f
),
6064 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
6066 SubstructureRedirectMask
| SubstructureNotifyMask
,
6069 UNBLOCK_INPUT_RESIGNAL
;
6070 error ("Can't notify window manager of iconification");
6074 /* X11R3: set the initial_state field of the window manager hints to
6076 x_wm_set_window_state (f
, IconicState
);
6078 if (!FRAME_VISIBLE_P (f
))
6080 /* If the frame was withdrawn, before, we must map it. */
6081 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
6084 f
->async_iconified
= 1;
6085 f
->async_visible
= 0;
6087 XFlush (FRAME_X_DISPLAY (f
));
6089 #endif /* not USE_X_TOOLKIT */
6092 /* Destroy the X window of frame F. */
6095 x_destroy_window (f
)
6098 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6102 /* If a display connection is dead, don't try sending more
6103 commands to the X server. */
6104 if (dpyinfo
->display
!= 0)
6106 if (f
->output_data
.x
->icon_desc
!= 0)
6107 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
6111 XDestroyIC (FRAME_XIC (f
));
6112 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
6113 /* This line causes crashes on Solaris with Openwin,
6114 due to an apparent bug in XCloseIM.
6115 X11R6 seems not to have the bug. */
6116 XCloseIM (FRAME_XIM (f
));
6120 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
6121 #ifdef USE_X_TOOLKIT
6122 XtDestroyWidget (f
->output_data
.x
->widget
);
6123 free_frame_menubar (f
);
6124 #endif /* USE_X_TOOLKIT */
6126 free_frame_faces (f
);
6127 XFlush (FRAME_X_DISPLAY (f
));
6130 if (f
->output_data
.x
->saved_menu_event
)
6131 free (f
->output_data
.x
->saved_menu_event
);
6133 xfree (f
->output_data
.x
);
6134 f
->output_data
.x
= 0;
6135 if (f
== dpyinfo
->x_focus_frame
)
6136 dpyinfo
->x_focus_frame
= 0;
6137 if (f
== dpyinfo
->x_focus_event_frame
)
6138 dpyinfo
->x_focus_event_frame
= 0;
6139 if (f
== dpyinfo
->x_highlight_frame
)
6140 dpyinfo
->x_highlight_frame
= 0;
6142 dpyinfo
->reference_count
--;
6144 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6146 dpyinfo
->mouse_face_beg_row
6147 = dpyinfo
->mouse_face_beg_col
= -1;
6148 dpyinfo
->mouse_face_end_row
6149 = dpyinfo
->mouse_face_end_col
= -1;
6150 dpyinfo
->mouse_face_window
= Qnil
;
6151 dpyinfo
->mouse_face_deferred_gc
= 0;
6152 dpyinfo
->mouse_face_mouse_frame
= 0;
6158 /* Setting window manager hints. */
6160 /* Set the normal size hints for the window manager, for frame F.
6161 FLAGS is the flags word to use--or 0 meaning preserve the flags
6162 that the window now has.
6163 If USER_POSITION is nonzero, we set the USPosition
6164 flag (this is useful when FLAGS is 0). */
6167 x_wm_set_size_hint (f
, flags
, user_position
)
6172 XSizeHints size_hints
;
6174 #ifdef USE_X_TOOLKIT
6177 Dimension widget_width
, widget_height
;
6178 Window window
= XtWindow (f
->output_data
.x
->widget
);
6179 #else /* not USE_X_TOOLKIT */
6180 Window window
= FRAME_X_WINDOW (f
);
6181 #endif /* not USE_X_TOOLKIT */
6183 /* Setting PMaxSize caused various problems. */
6184 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6186 flexlines
= f
->height
;
6188 size_hints
.x
= f
->output_data
.x
->left_pos
;
6189 size_hints
.y
= f
->output_data
.x
->top_pos
;
6191 #ifdef USE_X_TOOLKIT
6192 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6193 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6194 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
6195 size_hints
.height
= widget_height
;
6196 size_hints
.width
= widget_width
;
6197 #else /* not USE_X_TOOLKIT */
6198 size_hints
.height
= PIXEL_HEIGHT (f
);
6199 size_hints
.width
= PIXEL_WIDTH (f
);
6200 #endif /* not USE_X_TOOLKIT */
6202 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
6203 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
6204 size_hints
.max_width
6205 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6206 size_hints
.max_height
6207 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6209 /* Calculate the base and minimum sizes.
6211 (When we use the X toolkit, we don't do it here.
6212 Instead we copy the values that the widgets are using, below.) */
6213 #ifndef USE_X_TOOLKIT
6215 int base_width
, base_height
;
6216 int min_rows
= 0, min_cols
= 0;
6218 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6219 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6221 check_frame_size (f
, &min_rows
, &min_cols
);
6223 /* The window manager uses the base width hints to calculate the
6224 current number of rows and columns in the frame while
6225 resizing; min_width and min_height aren't useful for this
6226 purpose, since they might not give the dimensions for a
6227 zero-row, zero-column frame.
6229 We use the base_width and base_height members if we have
6230 them; otherwise, we set the min_width and min_height members
6231 to the size for a zero x zero frame. */
6234 size_hints
.flags
|= PBaseSize
;
6235 size_hints
.base_width
= base_width
;
6236 size_hints
.base_height
= base_height
;
6237 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6238 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6240 size_hints
.min_width
= base_width
;
6241 size_hints
.min_height
= base_height
;
6245 /* If we don't need the old flags, we don't need the old hint at all. */
6248 size_hints
.flags
|= flags
;
6251 #endif /* not USE_X_TOOLKIT */
6254 XSizeHints hints
; /* Sometimes I hate X Windows... */
6255 long supplied_return
;
6259 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
6262 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
6265 #ifdef USE_X_TOOLKIT
6266 size_hints
.base_height
= hints
.base_height
;
6267 size_hints
.base_width
= hints
.base_width
;
6268 size_hints
.min_height
= hints
.min_height
;
6269 size_hints
.min_width
= hints
.min_width
;
6273 size_hints
.flags
|= flags
;
6278 if (hints
.flags
& PSize
)
6279 size_hints
.flags
|= PSize
;
6280 if (hints
.flags
& PPosition
)
6281 size_hints
.flags
|= PPosition
;
6282 if (hints
.flags
& USPosition
)
6283 size_hints
.flags
|= USPosition
;
6284 if (hints
.flags
& USSize
)
6285 size_hints
.flags
|= USSize
;
6292 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
6293 size_hints
.flags
|= PWinGravity
;
6297 size_hints
.flags
&= ~ PPosition
;
6298 size_hints
.flags
|= USPosition
;
6300 #endif /* PWinGravity */
6303 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6305 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6309 /* Used for IconicState or NormalState */
6311 x_wm_set_window_state (f
, state
)
6315 #ifdef USE_X_TOOLKIT
6318 XtSetArg (al
[0], XtNinitialState
, state
);
6319 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6320 #else /* not USE_X_TOOLKIT */
6321 Window window
= FRAME_X_WINDOW (f
);
6323 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6324 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6326 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6327 #endif /* not USE_X_TOOLKIT */
6331 x_wm_set_icon_pixmap (f
, pixmap_id
)
6337 #ifdef USE_X_TOOLKIT
6338 Window window
= XtWindow (f
->output_data
.x
->widget
);
6340 Window window
= FRAME_X_WINDOW (f
);
6345 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6346 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6350 /* It seems there is no way to turn off use of an icon pixmap.
6351 The following line does it, only if no icon has yet been created,
6352 for some window managers. But with mwm it crashes.
6353 Some people say it should clear the IconPixmapHint bit in this case,
6354 but that doesn't work, and the X consortium said it isn't the
6355 right thing at all. Since there is no way to win,
6356 best to explicitly give up. */
6358 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6364 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6368 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6369 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6372 #else /* not USE_X_TOOLKIT */
6374 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6375 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6377 #endif /* not USE_X_TOOLKIT */
6381 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6385 #ifdef USE_X_TOOLKIT
6386 Window window
= XtWindow (f
->output_data
.x
->widget
);
6388 Window window
= FRAME_X_WINDOW (f
);
6391 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6392 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6393 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6395 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6399 /* Interface to fontset handler. */
6401 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6403 x_get_font_info (f
, font_idx
)
6407 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
6411 /* Return a list of names of available fonts matching PATTERN on frame
6412 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6413 to be listed. Frame F NULL means we have not yet created any
6414 frame on X, and consult the first display in x_display_list.
6415 MAXNAMES sets a limit on how many fonts to match. */
6418 x_list_fonts (f
, pattern
, size
, maxnames
)
6420 Lisp_Object pattern
;
6424 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
, tem
, second_best
;
6425 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
6427 patterns
= Fassoc (pattern
, Valternate_fontname_alist
);
6428 if (NILP (patterns
))
6429 patterns
= Fcons (pattern
, Qnil
);
6431 /* We try at least 10 fonts because X server will return auto-scaled
6432 fonts at the head. */
6433 if (maxnames
< 10) maxnames
= 10;
6435 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
6440 pattern
= XCONS (patterns
)->car
;
6441 /* See if we cached the result for this particular query.
6442 The cache is an alist of the form:
6443 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
6445 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
6446 key
= Fcons (pattern
, make_number (maxnames
)),
6447 !NILP (list
= Fassoc (key
, tem
))))
6449 list
= Fcdr_safe (list
);
6450 /* We have a cashed list. Don't have to get the list again. */
6454 /* At first, put PATTERN in the cache. */
6456 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, maxnames
, &num_fonts
);
6463 /* Make a list of all the fonts we got back.
6464 Store that in the font cache for the display. */
6465 for (i
= 0; i
< num_fonts
; i
++)
6468 int average_width
= -1, dashes
= 0, width
= 0;
6470 /* Count the number of dashes in NAMES[I]. If there are
6471 14 dashes, and the field value following 12th dash
6472 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
6473 is usually too ugly to be used for editing. Let's
6479 if (dashes
== 7) /* PIXEL_SIZE field */
6481 else if (dashes
== 12) /* AVERAGE_WIDTH field */
6482 average_width
= atoi (p
);
6484 if (dashes
< 14 || average_width
!= 0)
6486 tem
= build_string (names
[i
]);
6487 if (NILP (Fassoc (tem
, list
)))
6489 if (STRINGP (Vx_pixel_size_width_font_regexp
)
6490 && ((fast_c_string_match_ignore_case
6491 (Vx_pixel_size_width_font_regexp
, names
[i
]))
6493 /* We can set the value of PIXEL_SIZE to the
6494 width of this font. */
6495 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
6497 /* For the moment, width is not known. */
6498 list
= Fcons (Fcons (tem
, Qnil
), list
);
6502 XFreeFontNames (names
);
6505 /* Now store the result in the cache. */
6507 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
6508 = Fcons (Fcons (key
, list
),
6509 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6512 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6514 newlist
= second_best
= Qnil
;
6515 /* Make a list of the fonts that have the right width. */
6516 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
6520 tem
= XCONS (list
)->car
;
6522 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
6526 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6530 if (!INTEGERP (XCONS (tem
)->cdr
))
6532 /* Since we have not yet known the size of this font, we
6533 must try slow function call XLoadQueryFont. */
6534 XFontStruct
*thisinfo
;
6537 thisinfo
= XLoadQueryFont (dpy
,
6538 XSTRING (XCONS (tem
)->car
)->data
);
6544 = (thisinfo
->min_bounds
.width
== 0
6546 : make_number (thisinfo
->max_bounds
.width
));
6547 XFreeFont (dpy
, thisinfo
);
6550 /* For unknown reason, the previous call of XListFont had
6551 retruned a font which can't be opened. Record the size
6552 as 0 not to try to open it again. */
6553 XCONS (tem
)->cdr
= make_number (0);
6556 found_size
= XINT (XCONS (tem
)->cdr
);
6557 if (found_size
== size
)
6558 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6559 else if (found_size
> 0)
6561 if (NILP (second_best
))
6563 else if (found_size
< size
)
6565 if (XINT (XCONS (second_best
)->cdr
) > size
6566 || XINT (XCONS (second_best
)->cdr
) < found_size
)
6571 if (XINT (XCONS (second_best
)->cdr
) > size
6572 && XINT (XCONS (second_best
)->cdr
) > found_size
)
6577 if (!NILP (newlist
))
6579 else if (!NILP (second_best
))
6581 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6589 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6590 pointer to the structure font_info while allocating it dynamically.
6591 If SIZE is 0, load any size of font.
6592 If loading is failed, return NULL. */
6595 x_load_font (f
, fontname
, size
)
6597 register char *fontname
;
6600 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6601 Lisp_Object font_names
;
6603 /* Get a list of all the fonts that match this name. Once we
6604 have a list of matching fonts, we compare them against the fonts
6605 we already have by comparing names. */
6606 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 256);
6608 if (!NILP (font_names
))
6613 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6614 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
6615 if (!strcmp (dpyinfo
->font_table
[i
].name
,
6616 XSTRING (XCONS (tail
)->car
)->data
)
6617 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6618 XSTRING (XCONS (tail
)->car
)->data
))
6619 return (dpyinfo
->font_table
+ i
);
6622 /* Load the font and add it to the table. */
6626 struct font_info
*fontp
;
6627 unsigned long value
;
6629 /* If we have found fonts by x_list_font, load one of them. If
6630 not, we still try to load a font by the name given as FONTNAME
6631 because XListFonts (called in x_list_font) of some X server has
6632 a bug of not finding a font even if the font surely exists and
6633 is loadable by XLoadQueryFont. */
6634 if (!NILP (font_names
))
6635 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
6638 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
6643 /* Do we need to create the table? */
6644 if (dpyinfo
->font_table_size
== 0)
6646 dpyinfo
->font_table_size
= 16;
6648 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
6649 * sizeof (struct font_info
));
6651 /* Do we need to grow the table? */
6652 else if (dpyinfo
->n_fonts
6653 >= dpyinfo
->font_table_size
)
6655 dpyinfo
->font_table_size
*= 2;
6657 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
6658 (dpyinfo
->font_table_size
6659 * sizeof (struct font_info
)));
6662 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
6664 /* Now fill in the slots of *FONTP. */
6667 fontp
->font_idx
= dpyinfo
->n_fonts
;
6668 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
6669 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
6671 /* Try to get the full name of FONT. Put it in FULL_NAME. */
6673 if (XGetFontProperty (font
, XA_FONT
, &value
))
6675 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
6679 /* Count the number of dashes in the "full name".
6680 If it is too few, this isn't really the font's full name,
6682 In X11R4, the fonts did not come with their canonical names
6693 full_name
= (char *) xmalloc (p
- name
+ 1);
6694 bcopy (name
, full_name
, p
- name
+ 1);
6701 fontp
->full_name
= full_name
;
6703 fontp
->full_name
= fontp
->name
;
6705 fontp
->size
= font
->max_bounds
.width
;
6706 fontp
->height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6708 if (NILP (font_names
))
6710 /* We come here because of a bug of XListFonts mentioned at
6711 the head of this block. Let's store this information in
6712 the cache for x_list_fonts. */
6713 Lisp_Object lispy_name
= build_string (fontname
);
6714 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
6716 XCONS (dpyinfo
->name_list_element
)->cdr
6717 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
6718 Fcons (Fcons (lispy_full_name
,
6719 make_number (fontp
->size
)),
6721 XCONS (dpyinfo
->name_list_element
)->cdr
);
6723 XCONS (dpyinfo
->name_list_element
)->cdr
6724 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
6725 Fcons (Fcons (lispy_full_name
,
6726 make_number (fontp
->size
)),
6728 XCONS (dpyinfo
->name_list_element
)->cdr
);
6731 /* The slot `encoding' specifies how to map a character
6732 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6733 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
6734 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
6735 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
6736 2:0xA020..0xFF7F). For the moment, we don't know which charset
6737 uses this font. So, we set informatoin in fontp->encoding[1]
6738 which is never used by any charset. If mapping can't be
6739 decided, set FONT_ENCODING_NOT_DECIDED. */
6741 = (font
->max_byte1
== 0
6743 ? (font
->min_char_or_byte2
< 0x80
6744 ? (font
->max_char_or_byte2
< 0x80
6745 ? 0 /* 0x20..0x7F */
6746 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6747 : 1) /* 0xA0..0xFF */
6749 : (font
->min_byte1
< 0x80
6750 ? (font
->max_byte1
< 0x80
6751 ? (font
->min_char_or_byte2
< 0x80
6752 ? (font
->max_char_or_byte2
< 0x80
6753 ? 0 /* 0x2020..0x7F7F */
6754 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6755 : 3) /* 0x20A0..0x7FFF */
6756 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6757 : (font
->min_char_or_byte2
< 0x80
6758 ? (font
->max_char_or_byte2
< 0x80
6759 ? 2 /* 0xA020..0xFF7F */
6760 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6761 : 1))); /* 0xA0A0..0xFFFF */
6763 fontp
->baseline_offset
6764 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6765 ? (long) value
: 0);
6766 fontp
->relative_compose
6767 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6768 ? (long) value
: 0);
6769 fontp
->default_ascent
6770 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6771 ? (long) value
: 0);
6780 /* Return a pointer to struct font_info of a font named FONTNAME for frame F.
6781 If no such font is loaded, return NULL. */
6783 x_query_font (f
, fontname
)
6785 register char *fontname
;
6787 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6790 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6791 if (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6792 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
))
6793 return (dpyinfo
->font_table
+ i
);
6797 /* Find a CCL program for a font specified by FONTP, and set the memer
6798 `encoder' of the structure. */
6801 x_find_ccl_program (fontp
)
6802 struct font_info
*fontp
;
6804 extern Lisp_Object Vfont_ccl_encoder_alist
, Vccl_program_table
;
6805 extern Lisp_Object Qccl_program_idx
;
6806 extern Lisp_Object
resolve_symbol_ccl_program ();
6807 Lisp_Object list
, elt
, ccl_prog
, ccl_id
;
6809 for (list
= Vfont_ccl_encoder_alist
; CONSP (list
); list
= XCONS (list
)->cdr
)
6811 elt
= XCONS (list
)->car
;
6813 && STRINGP (XCONS (elt
)->car
)
6814 && (fast_c_string_match_ignore_case (XCONS (elt
)->car
, fontp
->name
)
6817 if (SYMBOLP (XCONS (elt
)->cdr
) &&
6818 (!NILP (ccl_id
= Fget (XCONS (elt
)->cdr
, Qccl_program_idx
))))
6820 ccl_prog
= XVECTOR (Vccl_program_table
)->contents
[XUINT (ccl_id
)];
6821 if (!CONSP (ccl_prog
)) continue;
6822 ccl_prog
= XCONS (ccl_prog
)->cdr
;
6826 ccl_prog
= XCONS (elt
)->cdr
;
6827 if (!VECTORP (ccl_prog
)) continue;
6831 = (struct ccl_program
*) xmalloc (sizeof (struct ccl_program
));
6832 setup_ccl_program (fontp
->font_encoder
,
6833 resolve_symbol_ccl_program (ccl_prog
));
6840 /* Initialization. */
6842 #ifdef USE_X_TOOLKIT
6843 static XrmOptionDescRec emacs_options
[] = {
6844 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6845 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6847 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6848 XrmoptionSepArg
, NULL
},
6849 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6851 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6852 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6853 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6854 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6855 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6856 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6857 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6859 #endif /* USE_X_TOOLKIT */
6861 static int x_initialized
;
6864 /* Test whether two display-name strings agree up to the dot that separates
6865 the screen number from the server number. */
6867 same_x_server (name1
, name2
)
6868 char *name1
, *name2
;
6871 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
6875 if (seen_colon
&& *name1
== '.')
6879 && (*name1
== '.' || *name1
== '\0')
6880 && (*name2
== '.' || *name2
== '\0'));
6884 struct x_display_info
*
6885 x_term_init (display_name
, xrm_option
, resource_name
)
6886 Lisp_Object display_name
;
6888 char *resource_name
;
6894 struct x_display_info
*dpyinfo
;
6906 setlocale (LC_ALL
, "");
6907 /* In case we just overrode what init_lread did, redo it. */
6908 setlocale (LC_NUMERIC
, "C");
6909 setlocale (LC_TIME
, "C");
6912 #ifdef USE_X_TOOLKIT
6913 /* weiner@footloose.sps.mot.com reports that this causes
6915 X protocol error: BadAtom (invalid Atom parameter)
6916 on protocol request 18skiloaf.
6917 So let's not use it until R6. */
6919 XtSetLanguageProc (NULL
, NULL
, NULL
);
6930 argv
[argc
++] = "-xrm";
6931 argv
[argc
++] = xrm_option
;
6933 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
6934 resource_name
, EMACS_CLASS
,
6935 emacs_options
, XtNumber (emacs_options
),
6939 /* I think this is to compensate for XtSetLanguageProc. */
6940 setlocale (LC_NUMERIC
, "C");
6941 setlocale (LC_TIME
, "C");
6945 #else /* not USE_X_TOOLKIT */
6947 XSetLocaleModifiers ("");
6949 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
6950 #endif /* not USE_X_TOOLKIT */
6952 /* Detect failure. */
6959 /* We have definitely succeeded. Record the new connection. */
6961 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
6965 struct x_display_info
*share
;
6968 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
6969 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
6970 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
6971 XSTRING (display_name
)->data
))
6974 dpyinfo
->kboard
= share
->kboard
;
6977 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
6978 init_kboard (dpyinfo
->kboard
);
6979 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
6981 char *vendor
= ServerVendor (dpy
);
6982 dpyinfo
->kboard
->Vsystem_key_alist
6983 = call1 (Qvendor_specific_keysyms
,
6984 build_string (vendor
? vendor
: ""));
6987 dpyinfo
->kboard
->next_kboard
= all_kboards
;
6988 all_kboards
= dpyinfo
->kboard
;
6989 /* Don't let the initial kboard remain current longer than necessary.
6990 That would cause problems if a file loaded on startup tries to
6991 prompt in the minibuffer. */
6992 if (current_kboard
== initial_kboard
)
6993 current_kboard
= dpyinfo
->kboard
;
6995 dpyinfo
->kboard
->reference_count
++;
6999 /* Put this display on the chain. */
7000 dpyinfo
->next
= x_display_list
;
7001 x_display_list
= dpyinfo
;
7003 /* Put it on x_display_name_list as well, to keep them parallel. */
7004 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
7005 x_display_name_list
);
7006 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
7008 dpyinfo
->display
= dpy
;
7011 XSetAfterFunction (x_current_display
, x_trace_wire
);
7015 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name
))
7016 + STRING_BYTES (XSTRING (Vsystem_name
))
7018 sprintf (dpyinfo
->x_id_name
, "%s@%s",
7019 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
7021 /* Figure out which modifier bits mean what. */
7022 x_find_modifier_meanings (dpyinfo
);
7024 /* Get the scroll bar cursor. */
7025 dpyinfo
->vertical_scroll_bar_cursor
7026 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
7028 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
7029 resource_name
, EMACS_CLASS
);
7030 #ifdef HAVE_XRMSETDATABASE
7031 XrmSetDatabase (dpyinfo
->display
, xrdb
);
7033 dpyinfo
->display
->db
= xrdb
;
7035 /* Put the rdb where we can find it in a way that works on
7037 dpyinfo
->xrdb
= xrdb
;
7039 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
7040 DefaultScreen (dpyinfo
->display
));
7041 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
7042 &dpyinfo
->n_planes
);
7043 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
7044 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
7045 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
7046 dpyinfo
->grabbed
= 0;
7047 dpyinfo
->reference_count
= 0;
7048 dpyinfo
->icon_bitmap_id
= -1;
7049 dpyinfo
->n_fonts
= 0;
7050 dpyinfo
->font_table_size
= 0;
7051 dpyinfo
->bitmaps
= 0;
7052 dpyinfo
->bitmaps_size
= 0;
7053 dpyinfo
->bitmaps_last
= 0;
7054 dpyinfo
->scratch_cursor_gc
= 0;
7055 dpyinfo
->mouse_face_mouse_frame
= 0;
7056 dpyinfo
->mouse_face_deferred_gc
= 0;
7057 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
7058 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
7059 dpyinfo
->mouse_face_face_id
= 0;
7060 dpyinfo
->mouse_face_window
= Qnil
;
7061 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
7062 dpyinfo
->mouse_face_defer
= 0;
7063 dpyinfo
->x_focus_frame
= 0;
7064 dpyinfo
->x_focus_event_frame
= 0;
7065 dpyinfo
->x_highlight_frame
= 0;
7067 dpyinfo
->Xatom_wm_protocols
7068 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
7069 dpyinfo
->Xatom_wm_take_focus
7070 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
7071 dpyinfo
->Xatom_wm_save_yourself
7072 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
7073 dpyinfo
->Xatom_wm_delete_window
7074 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
7075 dpyinfo
->Xatom_wm_change_state
7076 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
7077 dpyinfo
->Xatom_wm_configure_denied
7078 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
7079 dpyinfo
->Xatom_wm_window_moved
7080 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
7081 dpyinfo
->Xatom_editres
7082 = XInternAtom (dpyinfo
->display
, "Editres", False
);
7083 dpyinfo
->Xatom_CLIPBOARD
7084 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
7085 dpyinfo
->Xatom_TIMESTAMP
7086 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
7088 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
7089 dpyinfo
->Xatom_COMPOUND_TEXT
7090 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
7091 dpyinfo
->Xatom_DELETE
7092 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
7093 dpyinfo
->Xatom_MULTIPLE
7094 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
7096 = XInternAtom (dpyinfo
->display
, "INCR", False
);
7097 dpyinfo
->Xatom_EMACS_TMP
7098 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
7099 dpyinfo
->Xatom_TARGETS
7100 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
7102 = XInternAtom (dpyinfo
->display
, "NULL", False
);
7103 dpyinfo
->Xatom_ATOM_PAIR
7104 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
7105 /* For properties of font. */
7106 dpyinfo
->Xatom_PIXEL_SIZE
7107 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
7108 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
7109 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
7110 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
7111 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
7112 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
7113 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
7115 dpyinfo
->cut_buffers_initialized
= 0;
7117 connection
= ConnectionNumber (dpyinfo
->display
);
7118 dpyinfo
->connection
= connection
;
7123 null_bits
[0] = 0x00;
7126 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
7127 null_bits
, 1, 1, (long) 0, (long) 0,
7132 /* This is only needed for distinguishing keyboard and process input. */
7133 if (connection
!= 0)
7134 add_keyboard_wait_descriptor (connection
);
7137 #ifndef F_SETOWN_BUG
7139 #ifdef F_SETOWN_SOCK_NEG
7140 /* stdin is a socket here */
7141 fcntl (connection
, F_SETOWN
, -getpid ());
7142 #else /* ! defined (F_SETOWN_SOCK_NEG) */
7143 fcntl (connection
, F_SETOWN
, getpid ());
7144 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
7145 #endif /* ! defined (F_SETOWN) */
7146 #endif /* F_SETOWN_BUG */
7149 if (interrupt_input
)
7150 init_sigio (connection
);
7151 #endif /* ! defined (SIGIO) */
7154 #ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
7155 /* Make sure that we have a valid font for dialog boxes
7156 so that Xt does not crash. */
7158 Display
*dpy
= dpyinfo
->display
;
7163 d
.addr
= (XPointer
)&dpy
;
7164 d
.size
= sizeof (Display
*);
7165 fr
.addr
= XtDefaultFont
;
7166 fr
.size
= sizeof (XtDefaultFont
);
7167 to
.size
= sizeof (Font
*);
7168 to
.addr
= (XPointer
)&font
;
7169 count
= x_catch_errors (dpy
);
7170 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
7172 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
7173 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
7174 x_uncatch_errors (dpy
, count
);
7185 /* Get rid of display DPYINFO, assuming all frames are already gone,
7186 and without sending any more commands to the X server. */
7189 x_delete_display (dpyinfo
)
7190 struct x_display_info
*dpyinfo
;
7192 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
7194 /* Discard this display from x_display_name_list and x_display_list.
7195 We can't use Fdelq because that can quit. */
7196 if (! NILP (x_display_name_list
)
7197 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
7198 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
7203 tail
= x_display_name_list
;
7204 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
7206 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
7207 dpyinfo
->name_list_element
))
7209 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
7212 tail
= XCONS (tail
)->cdr
;
7216 if (x_display_list
== dpyinfo
)
7217 x_display_list
= dpyinfo
->next
;
7220 struct x_display_info
*tail
;
7222 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
7223 if (tail
->next
== dpyinfo
)
7224 tail
->next
= tail
->next
->next
;
7227 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
7228 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
7229 XrmDestroyDatabase (dpyinfo
->xrdb
);
7233 if (--dpyinfo
->kboard
->reference_count
== 0)
7234 delete_kboard (dpyinfo
->kboard
);
7236 xfree (dpyinfo
->font_table
);
7237 xfree (dpyinfo
->x_id_name
);
7241 /* Set up use of X before we make the first connection. */
7246 clear_frame_hook
= XTclear_frame
;
7247 clear_end_of_line_hook
= XTclear_end_of_line
;
7248 ins_del_lines_hook
= XTins_del_lines
;
7249 change_line_highlight_hook
= XTchange_line_highlight
;
7250 insert_glyphs_hook
= XTinsert_glyphs
;
7251 write_glyphs_hook
= XTwrite_glyphs
;
7252 delete_glyphs_hook
= XTdelete_glyphs
;
7253 ring_bell_hook
= XTring_bell
;
7254 reset_terminal_modes_hook
= XTreset_terminal_modes
;
7255 set_terminal_modes_hook
= XTset_terminal_modes
;
7256 update_begin_hook
= XTupdate_begin
;
7257 update_end_hook
= XTupdate_end
;
7258 set_terminal_window_hook
= XTset_terminal_window
;
7259 read_socket_hook
= XTread_socket
;
7260 frame_up_to_date_hook
= XTframe_up_to_date
;
7261 cursor_to_hook
= XTcursor_to
;
7262 reassert_line_highlight_hook
= XTreassert_line_highlight
;
7263 mouse_position_hook
= XTmouse_position
;
7264 frame_rehighlight_hook
= XTframe_rehighlight
;
7265 frame_raise_lower_hook
= XTframe_raise_lower
;
7266 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
7267 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
7268 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
7269 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
7271 scroll_region_ok
= 1; /* we'll scroll partial frames */
7272 char_ins_del_ok
= 0; /* just as fast to write the line */
7273 line_ins_del_ok
= 1; /* we'll just blt 'em */
7274 fast_clear_end_of_line
= 1; /* X does this well */
7275 memory_below_frame
= 0; /* we don't remember what scrolls
7281 /* Try to use interrupt input; if we can't, then start polling. */
7282 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
7284 #ifdef USE_X_TOOLKIT
7285 XtToolkitInitialize ();
7286 Xt_app_con
= XtCreateApplicationContext ();
7287 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
7290 /* Note that there is no real way portable across R3/R4 to get the
7291 original error handler. */
7292 XSetErrorHandler (x_error_handler
);
7293 XSetIOErrorHandler (x_io_error_quitter
);
7295 /* Disable Window Change signals; they are handled by X events. */
7297 signal (SIGWINCH
, SIG_DFL
);
7298 #endif /* ! defined (SIGWINCH) */
7300 signal (SIGPIPE
, x_connection_signal
);
7306 staticpro (&x_error_message_string
);
7307 x_error_message_string
= Qnil
;
7309 staticpro (&x_display_name_list
);
7310 x_display_name_list
= Qnil
;
7312 staticpro (&last_mouse_scroll_bar
);
7313 last_mouse_scroll_bar
= Qnil
;
7315 staticpro (&Qvendor_specific_keysyms
);
7316 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
7318 staticpro (&last_mouse_press_frame
);
7319 last_mouse_press_frame
= Qnil
;
7322 #endif /* not HAVE_X_WINDOWS */