1 /* X Communication module for terminals which understand the X protocol.
2 Copyright (C) 1989, 93, 94, 95, 1996 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. */
32 /* Need syssignal.h for various externs and definitions that may be required
33 by some configurations for calls to signal later in this source file. */
34 #include "syssignal.h"
39 #include "blockinput.h"
41 /* This may include sys/types.h, and that somehow loses
42 if this is not done before the other system files. */
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"
91 #include <X11/Shell.h>
95 extern void free_frame_menubar ();
96 extern FRAME_PTR
x_menubar_window_to_frame ();
97 #if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
99 extern void _XEditResCheckMessages ();
100 #endif /* not NO_EDITRES */
101 #endif /* USE_X_TOOLKIT */
103 #ifndef USE_X_TOOLKIT
104 #define x_any_window_to_frame x_window_to_frame
105 #define x_top_window_to_frame x_window_to_frame
110 #ifndef XtNinitialState
111 #define XtNinitialState "initialState"
115 #ifdef HAVE_SETLOCALE
116 /* So we can do setlocale. */
121 /* memmove will be defined as a macro in Xfuncs.h unless
122 <string.h> is included beforehand. The declaration for memmove in
123 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
128 #define min(a,b) ((a)<(b) ? (a) : (b))
131 #define max(a,b) ((a)>(b) ? (a) : (b))
134 /* This is a chain of structures for all the X displays currently in use. */
135 struct x_display_info
*x_display_list
;
137 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
138 one for each element of x_display_list and in the same order.
139 NAME is the name of the frame.
140 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
141 Lisp_Object x_display_name_list
;
143 /* Frame being updated by update_frame. This is declared in term.c.
144 This is set by update_begin and looked at by all the
145 XT functions. It is zero while not inside an update.
146 In that case, the XT functions assume that `selected_frame'
147 is the frame to apply to. */
148 extern struct frame
*updating_frame
;
150 extern waiting_for_input
;
152 /* This is a frame waiting to be autoraised, within XTread_socket. */
153 struct frame
*pending_autoraise_frame
;
156 /* The application context for Xt use. */
157 XtAppContext Xt_app_con
;
159 static String Xt_default_resources
[] =
165 /* During an update, maximum vpos for ins/del line operations to affect. */
167 static int flexlines
;
169 /* During an update, nonzero if chars output now should be highlighted. */
171 static int highlight
;
173 /* Nominal cursor position -- where to draw output.
174 During an update, these are different from the cursor-box position. */
181 Formerly, we used PointerMotionHintMask (in STANDARD_EVENT_MASK)
182 so that we would have to call XQueryPointer after each MotionNotify
183 event to ask for another such event. However, this made mouse tracking
184 slow, and there was a bug that made it eventually stop.
186 Simply asking for MotionNotify all the time seems to work better.
188 In order to avoid asking for motion events and then throwing most
189 of them away or busy-polling the server for mouse positions, we ask
190 the server for pointer motion hints. This means that we get only
191 one event per group of mouse movements. "Groups" are delimited by
192 other kinds of events (focus changes and button clicks, for
193 example), or by XQueryPointer calls; when one of these happens, we
194 get another MotionNotify event the next time the mouse moves. This
195 is at least as efficient as getting motion events when mouse
196 tracking is on, and I suspect only negligibly worse when tracking
199 /* Where the mouse was last time we reported a mouse event. */
200 static FRAME_PTR last_mouse_frame
;
201 static XRectangle last_mouse_glyph
;
203 static Lisp_Object last_mouse_press_frame
;
205 /* The scroll bar in which the last X motion event occurred.
207 If the last X motion event occurred in a scroll bar, we set this
208 so XTmouse_position can know whether to report a scroll bar motion or
211 If the last X motion event didn't occur in a scroll bar, we set this
212 to Qnil, to tell XTmouse_position to return an ordinary motion event. */
213 static Lisp_Object last_mouse_scroll_bar
;
215 /* This is a hack. We would really prefer that XTmouse_position would
216 return the time associated with the position it returns, but there
217 doesn't seem to be any way to wrest the timestamp from the server
218 along with the position query. So, we just keep track of the time
219 of the last movement we received, and return that in hopes that
220 it's somewhat accurate. */
221 static Time last_mouse_movement_time
;
223 /* Incremented by XTread_socket whenever it really tries to read events. */
225 static int volatile input_signal_count
;
227 static int input_signal_count
;
230 /* Used locally within XTread_socket. */
231 static int x_noop_count
;
233 /* Initial values of argv and argc. */
234 extern char **initial_argv
;
235 extern int initial_argc
;
237 extern Lisp_Object Vcommand_line_args
, Vsystem_name
;
239 /* Tells if a window manager is present or not. */
241 extern Lisp_Object Vx_no_window_manager
;
243 extern Lisp_Object Qface
, Qmouse_face
;
247 /* A mask of extra modifier bits to put into every keyboard char. */
248 extern int extra_keyboard_modifiers
;
250 static Lisp_Object Qvendor_specific_keysyms
;
252 extern XrmDatabase
x_load_resources ();
254 extern Lisp_Object
x_icon_type ();
256 void x_delete_display ();
258 static void redraw_previous_char ();
259 static void redraw_following_char ();
260 static unsigned int x_x_to_emacs_modifiers ();
262 static int fast_find_position ();
263 static void note_mouse_highlight ();
264 static void clear_mouse_face ();
265 static void show_mouse_face ();
266 static void do_line_dance ();
268 static int XTcursor_to ();
269 static int XTclear_end_of_line ();
270 static int x_io_error_quitter ();
271 int x_catch_errors ();
272 void x_uncatch_errors ();
275 /* This is a function useful for recording debugging information
276 about the sequence of occurrences in this file. */
284 struct record event_record
[100];
286 int event_record_index
;
288 record_event (locus
, type
)
292 if (event_record_index
== sizeof (event_record
) / sizeof (struct record
))
293 event_record_index
= 0;
295 event_record
[event_record_index
].locus
= locus
;
296 event_record
[event_record_index
].type
= type
;
297 event_record_index
++;
302 /* Return the struct x_display_info corresponding to DPY. */
304 struct x_display_info
*
305 x_display_info_for_display (dpy
)
308 struct x_display_info
*dpyinfo
;
310 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
311 if (dpyinfo
->display
== dpy
)
317 /* Starting and ending updates.
319 These hooks are called by update_frame at the beginning and end
320 of a frame update. We record in `updating_frame' the identity
321 of the frame being updated, so that the XT... functions do not
322 need to take a frame as argument. Most of the XT... functions
323 should never be called except during an update, the only exceptions
324 being XTcursor_to, XTwrite_glyphs and XTreassert_line_highlight. */
335 flexlines
= f
->height
;
340 curs_x
= FRAME_CURSOR_X (f
);
341 curs_y
= FRAME_CURSOR_Y (f
);
343 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
345 /* Don't do highlighting for mouse motion during the update. */
346 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 1;
348 /* If the frame needs to be redrawn,
349 simply forget about any prior mouse highlighting. */
350 if (FRAME_GARBAGED_P (f
))
351 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= Qnil
;
353 if (!NILP (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
355 int firstline
, lastline
, i
;
356 struct window
*w
= XWINDOW (FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
);
358 /* Find the first, and the last+1, lines affected by redisplay. */
359 for (firstline
= 0; firstline
< f
->height
; firstline
++)
360 if (FRAME_DESIRED_GLYPHS (f
)->enable
[firstline
])
363 lastline
= f
->height
;
364 for (i
= f
->height
- 1; i
>= 0; i
--)
366 if (FRAME_DESIRED_GLYPHS (f
)->enable
[i
])
372 /* Can we tell that this update does not affect the window
373 where the mouse highlight is? If so, no need to turn off.
374 Likewise, don't do anything if the frame is garbaged;
375 in that case, the FRAME_CURRENT_GLYPHS that we would use
376 are all wrong, and we will redisplay that line anyway. */
377 if (! (firstline
> (XFASTINT (w
->top
) + window_internal_height (w
))
378 || lastline
< XFASTINT (w
->top
)))
379 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
395 x_display_cursor (f
, 1, curs_x
, curs_y
);
397 FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
= 0;
399 /* This fails in the case of having updated only the echo area
400 if we have switched buffers. In that case, FRAME_CURRENT_GLYPHS
401 has no relation to the current contents, and its charstarts
402 have no relation to the contents of the window-buffer.
403 I don't know a clean way to check
404 for that case. window_end_valid isn't set up yet. */
405 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
406 note_mouse_highlight (f
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
407 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
410 XFlush (FRAME_X_DISPLAY (f
));
414 /* This is called after a redisplay on frame F. */
417 XTframe_up_to_date (f
)
421 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
422 || f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
)
424 note_mouse_highlight (FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
,
425 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
,
426 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
);
427 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 0;
432 /* External interface to control of standout mode.
433 Call this when about to modify line at position VPOS
434 and not change whether it is highlighted. */
436 XTreassert_line_highlight (new, vpos
)
442 /* Call this when about to modify line at position VPOS
443 and change whether it is highlighted. */
446 XTchange_line_highlight (new_highlight
, vpos
, first_unused_hpos
)
447 int new_highlight
, vpos
, first_unused_hpos
;
449 highlight
= new_highlight
;
450 XTcursor_to (vpos
, 0);
451 XTclear_end_of_line (FRAME_WINDOW_WIDTH (updating_frame
));
454 /* This is used when starting Emacs and when restarting after suspend.
455 When starting Emacs, no X window is mapped. And nothing must be done
456 to Emacs's own window if it is suspended (though that rarely happens). */
459 XTset_terminal_modes ()
463 /* This is called when exiting or suspending Emacs.
464 Exiting will make the X-windows go away, and suspending
465 requires no action. */
468 XTreset_terminal_modes ()
470 /* XTclear_frame (); */
473 /* Set the nominal cursor position of the frame.
474 This is where display update commands will take effect.
475 This does not affect the place where the cursor-box is displayed. */
478 XTcursor_to (row
, col
)
479 register int row
, col
;
487 if (updating_frame
== 0)
490 x_display_cursor (selected_frame
, 1, curs_x
, curs_y
);
491 XFlush (FRAME_X_DISPLAY (selected_frame
));
497 /* Return a pointer to per char metric information in FONT of a
498 character pointed by B (*XChar2b). */
500 #define PER_CHAR_METRIC(font, b) \
502 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
503 + (((font)->min_byte1 || (font)->max_byte1) \
504 ? (((b)->byte1 - (font)->min_byte1) \
505 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
507 : &((font)->max_bounds))
509 /* Display a sequence of N glyphs found at GP.
510 WINDOW is the x-window to output to. LEFT and TOP are starting coords.
511 HL is 1 if this text is highlighted, 2 if the cursor is on it,
512 3 if should appear in its mouse-face.
513 JUST_FOREGROUND if 1 means draw only the foreground;
514 don't alter the background.
516 CMPCHARP if non NULL is a pointer to the struct cmpchar_info, which
517 means drawing glyphs on the same column. This is set to non NULL
518 only when recursively called within dumpglyphs to draw a composite
519 character specified by CMPCHAR.
521 FONT is the default font to use (for glyphs whose font-code is 0).
523 Since the display generation code is responsible for calling
524 compute_char_face and compute_glyph_face on everything it puts in
525 the display structure, we can assume that the face code on each
526 glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
527 to which we can actually apply intern_face.
528 Call this function with input blocked.
530 Return overall pixel width of the drawn glyphs. */
533 /* This is the multi-face code. */
536 dumpglyphs (f
, left
, top
, gp
, n
, hl
, just_foreground
, cmpcharp
)
539 register GLYPH
*gp
; /* Points to first GLYPH. */
540 register int n
; /* Number of glyphs to display. */
543 struct cmpchar_info
*cmpcharp
;
545 /* Holds characters to be displayed. */
546 XChar2b
*buf
= (XChar2b
*) alloca (FRAME_WINDOW_WIDTH (f
) * sizeof (*buf
));
547 register XChar2b
*cp
; /* Steps through buf[]. */
548 register int tlen
= GLYPH_TABLE_LENGTH
;
549 register Lisp_Object
*tbase
= GLYPH_TABLE_BASE
;
550 Window window
= FRAME_X_WINDOW (f
);
551 int orig_left
= left
;
557 /* Get the face-code of the next GLYPH. */
561 Lisp_Object first_ch
;
562 /* HIGHEST and LOWEST are used while drawing a composite
563 character. The meanings are described later. */
566 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
567 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
568 ch
= FAST_GLYPH_CHAR (g
);
569 if (gidx
== 0) XSETFASTINT (first_ch
, ch
);
570 charset
= CHAR_CHARSET (ch
);
571 if (charset
== CHARSET_COMPOSITION
)
573 /* We must draw components of the composite character on the
575 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
577 /* Set the face in the slot for work. */
578 cmpcharp
->face_work
= cf
;
580 /* We don't need the return value ... */
581 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
582 hl
, just_foreground
, cmpcharp
);
583 /* ... because the width of just drawn text can be
584 calculated as follows. */
585 left
+= FONT_WIDTH (f
->output_data
.x
->font
) * cmpcharp
->width
;
588 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
593 /* Find the run of consecutive glyphs which can be drawn with
594 the same GC (i.e. the same charset and the same face-code).
595 Extract their character codes into BUF.
596 If CMPCHARP is not NULL, face-code is not checked because we
597 use only the face specified in `cmpcharp->face_work'. */
601 int this_charset
, c1
, c2
;
604 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
605 ch
= FAST_GLYPH_CHAR (g
);
606 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
607 if (this_charset
!= charset
608 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
612 cp
->byte1
= c1
, cp
->byte2
= c2
;
614 cp
->byte1
= 0, cp
->byte2
= c1
;
617 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
621 /* LEN gets the length of the run. */
623 /* Now output this run of chars, with the font and pixel values
624 determined by the face code CF. */
626 struct face
*face
= FRAME_DEFAULT_FACE (f
);
627 XFontStruct
*font
= NULL
;
630 int line_height
= f
->output_data
.x
->line_height
;
631 /* Pixel width of each glyph in this run. */
633 = (FONT_WIDTH (f
->output_data
.x
->font
)
634 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
635 /* Overall pixel width of this run. */
637 = (FONT_WIDTH (f
->output_data
.x
->font
)
638 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
639 /* A flag to tell if we have already filled background. We
640 fill background in advance in the following cases:
641 1) A face has stipple.
642 2) A height of font is shorter than LINE_HEIGHT.
643 3) Drawing a composite character.
644 4) Font has non-zero _MULE_BASELINE_OFFSET property.
645 After filling background, we draw glyphs by XDrawString16. */
646 int background_filled
;
647 /* Baseline position of a character, offset from TOP. */
649 /* The property value of `_MULE_RELATIVE_COMPOSE' and
650 `_MULE_DEFAULT_ASCENT'. */
651 int relative_compose
= 0, default_ascent
= 0;
652 /* 1 if we find no font or a font of inappropriate size. */
653 int require_clipping
;
655 /* HL = 3 means use a mouse face previously chosen. */
657 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
659 /* First look at the face of the text itself. */
662 /* It's possible for the display table to specify
663 a face code that is out of range. Use 0 in that case. */
664 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
665 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
669 face
= FRAME_MODE_LINE_FACE (f
);
671 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
672 if (FACE_STIPPLE (face
))
676 /* Then comes the distinction between modeline and normal text. */
681 face
= FRAME_MODE_LINE_FACE (f
);
682 if (FACE_STIPPLE (face
))
686 #define FACE_DEFAULT (~0)
688 /* Setting appropriate font and gc for this charset. */
689 if (charset
!= CHARSET_ASCII
)
692 int fontset
= FACE_FONTSET (face
);
693 struct font_info
*fontp
;
695 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
696 || !(fontp
= FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
697 charset
, NULL
, fontset
)))
700 font
= (XFontStruct
*) (fontp
->font
);
701 gc
= FACE_NON_ASCII_GC (face
);
702 XSetFont (FRAME_X_DISPLAY (f
), gc
, font
->fid
);
704 = (font
->max_byte1
!= 0
705 ? (line_height
+ font
->ascent
- font
->descent
) / 2
706 : f
->output_data
.x
->font_baseline
- fontp
->baseline_offset
);
707 if (FONT_HEIGHT (font
) <= line_height
708 && (font
->ascent
> baseline
709 || font
->descent
> line_height
- baseline
))
710 /* Adjust baseline for this font to show the whole
712 baseline
= line_height
- font
->descent
;
714 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
716 relative_compose
= fontp
->relative_compose
;
717 default_ascent
= fontp
->default_ascent
;
720 /* We have to change code points in the following cases. */
721 if (fontp
->font_encoder
)
723 /* This font requires CCL program to calculate code
724 point of characters. */
725 struct ccl_program
*ccl
= fontp
->font_encoder
;
727 if (CHARSET_DIMENSION (charset
) == 1)
728 for (cp
= buf
; cp
< buf
+ len
; cp
++)
730 ccl
->reg
[0] = charset
;
731 ccl
->reg
[1] = cp
->byte2
;
732 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
733 cp
->byte2
= ccl
->reg
[1];
736 for (cp
= buf
; cp
< buf
+ len
; cp
++)
738 ccl
->reg
[0] = charset
;
739 ccl
->reg
[1] = cp
->byte1
, ccl
->reg
[2] = cp
->byte2
;
740 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
741 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
744 else if (fontp
->encoding
[charset
])
746 int enc
= fontp
->encoding
[charset
];
748 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
749 for (cp
= buf
; cp
< buf
+ len
; cp
++)
751 if (enc
== 1 || enc
== 3)
752 for (cp
= buf
; cp
< buf
+ len
; cp
++)
759 if (charset
== CHARSET_ASCII
|| charset
== charset_latin_iso8859_1
)
761 font
= FACE_FONT (face
);
762 if (font
== (XFontStruct
*) FACE_DEFAULT
)
763 font
= f
->output_data
.x
->font
;
764 baseline
= FONT_BASE (f
->output_data
.x
->font
);
765 if (charset
== charset_latin_iso8859_1
)
767 if (font
->max_char_or_byte2
< 0x80)
768 /* This font can't display Latin1 characters. */
772 for (cp
= buf
; cp
< buf
+ len
; cp
++)
780 /* Now override that if the cursor's on this character. */
783 /* The cursor overrides stippling. */
786 if (font
== f
->output_data
.x
->font
787 && face
->background
== f
->output_data
.x
->background_pixel
788 && face
->foreground
== f
->output_data
.x
->foreground_pixel
791 gc
= f
->output_data
.x
->cursor_gc
;
793 /* Cursor on non-default face: must merge. */
799 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
800 xgcv
.foreground
= face
->background
;
801 /* If the glyph would be invisible,
802 try a different foreground. */
803 if (xgcv
.foreground
== xgcv
.background
)
804 xgcv
.foreground
= face
->foreground
;
805 if (xgcv
.foreground
== xgcv
.background
)
806 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
807 if (xgcv
.foreground
== xgcv
.background
)
808 xgcv
.foreground
= face
->foreground
;
809 /* Make sure the cursor is distinct from text in this face. */
810 if (xgcv
.background
== face
->background
811 && xgcv
.foreground
== face
->foreground
)
813 xgcv
.background
= face
->foreground
;
814 xgcv
.foreground
= face
->background
;
817 xgcv
.font
= font
->fid
;
819 xgcv
.font
= FACE_FONT (face
)->fid
;
820 xgcv
.graphics_exposures
= 0;
821 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
822 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
823 XChangeGC (FRAME_X_DISPLAY (f
),
824 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
827 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
828 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
829 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
831 /* If this code is restored, it must also reset to the default stipple
833 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
834 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
840 require_clipping
= (!NILP (Vclip_large_size_font
)
841 && (font
->ascent
> baseline
842 || font
->descent
> line_height
- baseline
844 && FONT_WIDTH (font
) > glyph_width
)));
846 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
847 background_filled
= 1;
850 /* Turn stipple on. */
851 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
853 /* Draw stipple or background color on background. */
854 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
855 left
, top
, run_width
, line_height
);
857 /* Turn stipple off. */
858 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
860 background_filled
= 1;
863 || FONT_HEIGHT (font
) < line_height
864 || FONT_WIDTH (font
) < glyph_width
867 /* Fill a area for the current run in background pixle of GC. */
869 unsigned long mask
= GCForeground
| GCBackground
| GCFillStyle
;
871 /* The current code at first set foreground to background,
872 fill the area, then recover the original foreground.
873 Aren't there any smarter ways? */
875 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
876 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.background
);
877 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
878 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
879 left
, top
, run_width
, line_height
);
880 XSetForeground (FRAME_X_DISPLAY (f
), gc
, xgcv
.foreground
);
882 background_filled
= 1;
884 /* To assure not to fill background while drawing
885 remaining components. */
889 background_filled
= 0;
893 if (require_clipping
)
895 Region region
; /* Region used for setting clip mask to GC. */
896 XPoint x
[4]; /* Data used for creating REGION. */
898 x
[0].x
= x
[3].x
= left
, x
[1].x
= x
[2].x
= left
+ glyph_width
;
899 x
[0].y
= x
[1].y
= top
, x
[2].y
= x
[3].y
= top
+ line_height
;
900 region
= XPolygonRegion (x
, 4, EvenOddRule
);
901 XSetRegion (FRAME_X_DISPLAY (f
), gc
, region
);
902 XDestroyRegion (region
);
907 if (require_clipping
|| FONT_WIDTH (font
) != glyph_width
)
908 for (i
= 0; i
< len
; i
++)
910 if (require_clipping
&& i
> 0)
911 XSetClipOrigin (FRAME_X_DISPLAY (f
), gc
,
913 if (background_filled
)
914 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
915 left
+ glyph_width
* i
,
916 top
+ baseline
, buf
+ i
, 1);
918 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
919 left
+ glyph_width
* i
,
920 top
+ baseline
, buf
+ i
, 1);
924 if (background_filled
)
925 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
926 left
, top
+ baseline
, buf
, len
);
928 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
929 left
, top
+ baseline
, buf
, len
);
934 XCharStruct
*pcm
; /* Pointer to per char metric info. */
936 if ((cmpcharp
->cmp_rule
|| relative_compose
)
939 /* This is the first character. Initialize variables.
940 HIGHEST is the highest position of glyphs ever
941 written, LOWEST the lowest position. */
945 && CHAR_TABLE_P (Vuse_default_ascent
)
946 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
948 highest
= default_ascent
;
953 pcm
= PER_CHAR_METRIC (font
, buf
);
954 highest
= pcm
->ascent
+ 1;
955 lowest
= - pcm
->descent
;
958 if (cmpcharp
->cmp_rule
)
959 x_offset
= (cmpcharp
->col_offset
[0]
960 * FONT_WIDTH (f
->output_data
.x
->font
));
961 /* Draw the first character at the normal position. */
962 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
963 left
+ x_offset
, top
+ baseline
, buf
, 1);
970 for (; i
< len
; i
++, gidx
++)
972 int x_offset
= 0, y_offset
= 0;
974 if (relative_compose
)
976 pcm
= PER_CHAR_METRIC (font
, buf
+ i
);
977 if (- pcm
->descent
>= relative_compose
)
979 /* Draw above the current glyphs. */
980 y_offset
= highest
+ pcm
->descent
;
981 highest
+= pcm
->ascent
+ pcm
->descent
;
983 else if (pcm
->ascent
<= 0)
985 /* Draw beneath the current glyphs. */
986 y_offset
= lowest
- pcm
->ascent
;
987 lowest
-= pcm
->ascent
+ pcm
->descent
;
990 else if (cmpcharp
->cmp_rule
)
992 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
993 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
996 /* Re-encode GREF and NREF so that they specify
997 only Y-axis information:
998 0:top, 1:base, 2:bottom, 3:center */
999 gref
= gref
/ 3 + (gref
== 4) * 2;
1000 nref
= nref
/ 3 + (nref
== 4) * 2;
1002 pcm
= PER_CHAR_METRIC (font
, buf
+ i
);
1003 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
1004 : gref
== 2 ? lowest
1005 : (highest
+ lowest
) / 2)
1006 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
1007 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
1008 : (pcm
->ascent
+ pcm
->descent
) / 2));
1009 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
1012 if (bottom
< lowest
)
1014 y_offset
= bottom
+ pcm
->descent
;
1015 x_offset
= (cmpcharp
->col_offset
[gidx
]
1016 * FONT_WIDTH (f
->output_data
.x
->font
));
1018 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1019 left
+ x_offset
, top
+ baseline
- y_offset
,
1023 if (require_clipping
)
1024 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
1026 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
1027 which often is not up to date yet. */
1028 if (!just_foreground
)
1030 if (left
== orig_left
)
1031 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
1032 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1034 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
1035 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1041 /* Show rectangles to indicate that we found no font. */
1042 int limit
= cmpcharp
? 1 : len
;
1044 for (i
= 0; i
< limit
; i
++)
1045 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1046 left
+ glyph_width
* i
, top
,
1047 glyph_width
- 1, line_height
- 1);
1049 else if (require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1051 /* Show ??? to indicate that we found a font of
1052 inappropriate size. */
1053 int limit
= cmpcharp
? 1 : len
;
1055 for (i
= 0; i
< limit
; i
++)
1057 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1058 left
+ glyph_width
* i
, top
+ line_height
- 1,
1059 left
+ glyph_width
* i
+ 1, top
+ line_height
- 1);
1060 XDrawLine (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1061 left
+ glyph_width
* i
, top
+ line_height
- 3,
1062 left
+ glyph_width
* i
, top
+ line_height
- 1);
1066 /* We should probably check for XA_UNDERLINE_POSITION and
1067 XA_UNDERLINE_THICKNESS properties on the font, but let's
1068 just get the thing working, and come back to that. */
1070 /* Setting underline position based on the metric of the
1071 current font results in shaky underline if it strides
1072 over different fonts. So, we set the position based only
1073 on the default font of this frame. */
1074 int underline_position
= f
->output_data
.x
->font_baseline
+ 1;
1076 if (underline_position
>= line_height
)
1077 underline_position
= line_height
- 1;
1079 if (face
->underline
)
1080 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1082 left
, top
+ underline_position
, run_width
, 1);
1090 return (left
- orig_left
);
1095 /* This is the old single-face code. */
1098 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
1101 register GLYPH
*gp
; /* Points to first GLYPH. */
1102 register int n
; /* Number of glyphs to display. */
1107 Window window
= FRAME_X_WINDOW (f
);
1108 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
1109 : (hl
? f
->output_data
.x
->reverse_gc
1110 : f
->output_data
.x
->normal_gc
));
1112 if (sizeof (GLYPH
) == sizeof (XChar2b
))
1113 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1114 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
1115 else if (sizeof (GLYPH
) == sizeof (unsigned char))
1116 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1117 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
1119 /* What size of glyph ARE you using? And does X have a function to
1125 /* Output some text at the nominal frame cursor position.
1126 Advance the cursor over the text.
1127 Output LEN glyphs at START.
1129 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
1130 controls the pixel values used for foreground and background. */
1133 XTwrite_glyphs (start
, len
)
1134 register GLYPH
*start
;
1137 register int temp_length
;
1148 /* If not within an update,
1149 output at the frame's visible cursor. */
1150 curs_x
= f
->cursor_x
;
1151 curs_y
= f
->cursor_y
;
1155 CHAR_TO_PIXEL_COL (f
, curs_x
),
1156 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1157 start
, len
, highlight
, 0, NULL
);
1159 /* If we drew on top of the cursor, note that it is turned off. */
1160 if (curs_y
== f
->phys_cursor_y
1161 && curs_x
<= f
->phys_cursor_x
1162 && curs_x
+ len
> f
->phys_cursor_x
)
1163 f
->phys_cursor_on
= 0;
1165 if (updating_frame
== 0)
1166 x_display_cursor (f
, 1, FRAME_CURSOR_X (f
) + len
, FRAME_CURSOR_Y (f
));
1173 /* Clear to the end of the line.
1174 Erase the current text line from the nominal cursor position (inclusive)
1175 to column FIRST_UNUSED (exclusive). The idea is that everything
1176 from FIRST_UNUSED onward is already erased. */
1179 XTclear_end_of_line (first_unused
)
1180 register int first_unused
;
1182 struct frame
*f
= updating_frame
;
1188 if (curs_y
< 0 || curs_y
>= f
->height
)
1190 if (first_unused
<= 0)
1193 if (first_unused
>= FRAME_WINDOW_WIDTH (f
))
1194 first_unused
= FRAME_WINDOW_WIDTH (f
);
1196 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1202 /* Notice if the cursor will be cleared by this operation. */
1203 if (curs_y
== f
->phys_cursor_y
1204 && curs_x
<= f
->phys_cursor_x
1205 && f
->phys_cursor_x
< first_unused
)
1206 f
->phys_cursor_on
= 0;
1208 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1209 CHAR_TO_PIXEL_COL (f
, curs_x
),
1210 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1211 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
1212 f
->output_data
.x
->line_height
, False
);
1214 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
1224 struct frame
*f
= updating_frame
;
1229 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1230 curs_x
= 0; /* Nominal cursor position is top left. */
1235 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
1237 /* We have to clear the scroll bars, too. If we have changed
1238 colors or something like that, then they should be notified. */
1239 x_scroll_bar_clear (f
);
1241 XFlush (FRAME_X_DISPLAY (f
));
1246 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
1247 always contain the right glyphs to use.
1249 It also needs to be changed to look at the details of the font and
1250 see whether there is really overlap, and do nothing when there is
1251 not. This can use font_char_overlap_left and font_char_overlap_right,
1252 but just how to use them is not clear. */
1254 /* Erase the character (if any) at the position just before X, Y in frame F,
1255 then redraw it and the character before it.
1256 This is necessary when we erase starting at X,
1257 in case the character after X overlaps into the one before X.
1258 Call this function with input blocked. */
1261 redraw_previous_char (f
, x
, y
, highlight_flag
)
1266 /* Erase the character before the new ones, in case
1267 what was here before overlaps it.
1268 Reoutput that character, and the previous character
1269 (in case the previous character overlaps it). */
1272 int start_x
= x
- 2;
1275 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1276 CHAR_TO_PIXEL_COL (f
, x
- 1),
1277 CHAR_TO_PIXEL_ROW (f
, y
),
1278 FONT_WIDTH (f
->output_data
.x
->font
),
1279 f
->output_data
.x
->line_height
, False
);
1281 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
1282 CHAR_TO_PIXEL_ROW (f
, y
),
1283 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
1284 x
- start_x
, highlight_flag
, 1, NULL
);
1288 /* Erase the character (if any) at the position X, Y in frame F,
1289 then redraw it and the character after it.
1290 This is necessary when we erase endng at X,
1291 in case the character after X overlaps into the one before X.
1292 Call this function with input blocked. */
1295 redraw_following_char (f
, x
, y
, highlight_flag
)
1300 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
1301 /* Erase the character after the new ones, in case
1302 what was here before overlaps it.
1303 Reoutput that character, and the following character
1304 (in case the following character overlaps it). */
1306 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1311 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1312 CHAR_TO_PIXEL_COL (f
, x
),
1313 CHAR_TO_PIXEL_ROW (f
, y
),
1314 FONT_WIDTH (f
->output_data
.x
->font
),
1315 f
->output_data
.x
->line_height
, False
);
1317 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1318 CHAR_TO_PIXEL_ROW (f
, y
),
1319 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1320 end_x
- x
, highlight_flag
, 1, NULL
);
1325 #if 0 /* Not in use yet */
1327 /* Return 1 if character C in font F extends past its left edge. */
1330 font_char_overlap_left (font
, c
)
1336 /* Find the bounding-box info for C. */
1337 if (font
->per_char
== 0)
1338 s
= &font
->max_bounds
;
1341 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1344 /* Decode char into row number (byte 1) and code within row (byte 2). */
1347 if (!(within
>= font
->min_char_or_byte2
1348 && within
<= font
->max_char_or_byte2
1349 && row
>= font
->min_byte1
1350 && row
<= font
->max_byte1
))
1352 /* If char is out of range, try the font's default char instead. */
1353 c
= font
->default_char
;
1354 row
= c
>> (BITS_PER_INT
- 8);
1357 if (!(within
>= font
->min_char_or_byte2
1358 && within
<= font
->max_char_or_byte2
1359 && row
>= font
->min_byte1
1360 && row
<= font
->max_byte1
))
1361 /* Still out of range means this char does not overlap. */
1364 /* We found the info for this char. */
1365 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1369 return (s
&& s
->lbearing
< 0);
1372 /* Return 1 if character C in font F extends past its right edge. */
1375 font_char_overlap_right (font
, c
)
1381 /* Find the bounding-box info for C. */
1382 if (font
->per_char
== 0)
1383 s
= &font
->max_bounds
;
1386 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1389 /* Decode char into row number (byte 1) and code within row (byte 2). */
1392 if (!(within
>= font
->min_char_or_byte2
1393 && within
<= font
->max_char_or_byte2
1394 && row
>= font
->min_byte1
1395 && row
<= font
->max_byte1
))
1397 /* If char is out of range, try the font's default char instead. */
1398 c
= font
->default_char
;
1399 row
= c
>> (BITS_PER_INT
- 8);
1402 if (!(within
>= font
->min_char_or_byte2
1403 && within
<= font
->max_char_or_byte2
1404 && row
>= font
->min_byte1
1405 && row
<= font
->max_byte1
))
1406 /* Still out of range means this char does not overlap. */
1409 /* We found the info for this char. */
1410 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1414 return (s
&& s
->rbearing
>= s
->width
);
1418 /* Invert the middle quarter of the frame for .15 sec. */
1420 /* We use the select system call to do the waiting, so we have to make sure
1421 it's available. If it isn't, we just won't do visual bells. */
1422 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1424 /* Subtract the `struct timeval' values X and Y,
1425 storing the result in RESULT.
1426 Return 1 if the difference is negative, otherwise 0. */
1429 timeval_subtract (result
, x
, y
)
1430 struct timeval
*result
, x
, y
;
1432 /* Perform the carry for the later subtraction by updating y.
1433 This is safer because on some systems
1434 the tv_sec member is unsigned. */
1435 if (x
.tv_usec
< y
.tv_usec
)
1437 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1438 y
.tv_usec
-= 1000000 * nsec
;
1441 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1443 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1444 y
.tv_usec
+= 1000000 * nsec
;
1448 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1449 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1450 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1452 /* Return indication of whether the result should be considered negative. */
1453 return x
.tv_sec
< y
.tv_sec
;
1464 /* Create a GC that will use the GXxor function to flip foreground pixels
1465 into background pixels. */
1469 values
.function
= GXxor
;
1470 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1471 ^ f
->output_data
.x
->background_pixel
);
1473 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1474 GCFunction
| GCForeground
, &values
);
1478 /* Get the height not including a menu bar widget. */
1479 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
1480 /* Height of each line to flash. */
1481 int flash_height
= FRAME_LINE_HEIGHT (f
);
1482 /* These will be the left and right margins of the rectangles. */
1483 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1484 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
1488 /* Don't flash the area between a scroll bar and the frame
1489 edge it is next to. */
1490 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
1492 case vertical_scroll_bar_left
:
1493 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1496 case vertical_scroll_bar_right
:
1497 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1501 width
= flash_right
- flash_left
;
1503 /* If window is tall, flash top and bottom line. */
1504 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1506 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1507 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1508 width
, flash_height
);
1509 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1511 (height
- flash_height
1512 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1513 width
, flash_height
);
1516 /* If it is short, flash it all. */
1517 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1518 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1519 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1521 XFlush (FRAME_X_DISPLAY (f
));
1524 struct timeval wakeup
, now
;
1526 EMACS_GET_TIME (wakeup
);
1528 /* Compute time to wait until, propagating carry from usecs. */
1529 wakeup
.tv_usec
+= 150000;
1530 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1531 wakeup
.tv_usec
%= 1000000;
1533 /* Keep waiting until past the time wakeup. */
1536 struct timeval timeout
;
1538 EMACS_GET_TIME (timeout
);
1540 /* In effect, timeout = wakeup - timeout.
1541 Break if result would be negative. */
1542 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1545 /* Try to wait that long--but we might wake up sooner. */
1546 select (0, NULL
, NULL
, NULL
, &timeout
);
1550 /* If window is tall, flash top and bottom line. */
1551 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1553 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1554 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1555 width
, flash_height
);
1556 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1558 (height
- flash_height
1559 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1560 width
, flash_height
);
1563 /* If it is short, flash it all. */
1564 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1565 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1566 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1568 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1569 XFlush (FRAME_X_DISPLAY (f
));
1579 /* Make audible bell. */
1581 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1585 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1588 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1590 XTflash (selected_frame
);
1596 XFlush (FRAME_X_DISPLAY (selected_frame
));
1601 /* Insert and delete character.
1602 These are not supposed to be used because we are supposed to turn
1603 off the feature of using them. */
1606 XTinsert_glyphs (start
, len
)
1607 register char *start
;
1620 /* Specify how many text lines, from the top of the window,
1621 should be affected by insert-lines and delete-lines operations.
1622 This, and those operations, are used only within an update
1623 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1626 XTset_terminal_window (n
)
1629 if (updating_frame
== 0)
1632 if ((n
<= 0) || (n
> updating_frame
->height
))
1633 flexlines
= updating_frame
->height
;
1638 /* These variables need not be per frame
1639 because redisplay is done on a frame-by-frame basis
1640 and the line dance for one frame is finished before
1641 anything is done for anoter frame. */
1643 /* Array of line numbers from cached insert/delete operations.
1644 line_dance[i] is the old position of the line that we want
1645 to move to line i, or -1 if we want a blank line there. */
1646 static int *line_dance
;
1648 /* Allocated length of that array. */
1649 static int line_dance_len
;
1651 /* Flag indicating whether we've done any work. */
1652 static int line_dance_in_progress
;
1654 /* Perform an insert-lines or delete-lines operation,
1655 inserting N lines or deleting -N lines at vertical position VPOS. */
1656 XTins_del_lines (vpos
, n
)
1659 register int fence
, i
;
1661 if (vpos
>= flexlines
)
1664 if (!line_dance_in_progress
)
1666 int ht
= updating_frame
->height
;
1667 if (ht
> line_dance_len
)
1669 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1670 line_dance_len
= ht
;
1672 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1673 line_dance_in_progress
= 1;
1677 if (n
> flexlines
- vpos
)
1678 n
= flexlines
- vpos
;
1680 for (i
= flexlines
; --i
>= fence
;)
1681 line_dance
[i
] = line_dance
[i
-n
];
1682 for (i
= fence
; --i
>= vpos
;)
1688 if (n
> flexlines
- vpos
)
1689 n
= flexlines
- vpos
;
1690 fence
= flexlines
- n
;
1691 for (i
= vpos
; i
< fence
; ++i
)
1692 line_dance
[i
] = line_dance
[i
+ n
];
1693 for (i
= fence
; i
< flexlines
; ++i
)
1698 /* Here's where we actually move the pixels around.
1699 Must be called with input blocked. */
1703 register int i
, j
, distance
;
1704 register struct frame
*f
;
1708 /* Must check this flag first. If it's not set, then not only is the
1709 array uninitialized, but we might not even have a frame. */
1710 if (!line_dance_in_progress
)
1718 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1720 x_update_cursor (updating_frame
, 0);
1722 for (i
= 0; i
< ht
; ++i
)
1723 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1725 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1726 && line_dance
[j
]-j
== distance
); ++j
);
1727 /* Copy [i,j) upward from [i+distance,j+distance) */
1728 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1729 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1730 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1731 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1732 (j
-i
) * f
->output_data
.x
->line_height
,
1733 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1737 for (i
= ht
; --i
>=0; )
1738 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1740 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1741 && line_dance
[j
]-j
== distance
););
1742 /* Copy (j,i] downward from (j+distance, i+distance] */
1743 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1744 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1745 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1746 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1747 (i
-j
) * f
->output_data
.x
->line_height
,
1748 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1752 for (i
= 0; i
< ht
; ++i
)
1753 if (line_dance
[i
] == -1)
1755 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1757 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1758 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1759 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1760 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1763 line_dance_in_progress
= 0;
1766 /* Support routines for exposure events. */
1767 static void clear_cursor ();
1769 /* Output into a rectangle of an X-window (for frame F)
1770 the characters in f->phys_lines that overlap that rectangle.
1771 TOP and LEFT are the position of the upper left corner of the rectangle.
1772 ROWS and COLS are the size of the rectangle.
1773 Call this function with input blocked. */
1776 dumprectangle (f
, left
, top
, cols
, rows
)
1778 register int left
, top
, cols
, rows
;
1780 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1781 int cursor_cleared
= 0;
1785 if (FRAME_GARBAGED_P (f
))
1788 /* Express rectangle as four edges, instead of position-and-size. */
1789 bottom
= top
+ rows
;
1790 right
= left
+ cols
;
1792 /* Convert rectangle edges in pixels to edges in chars.
1793 Round down for left and top, up for right and bottom. */
1794 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1795 left
= PIXEL_TO_CHAR_COL (f
, left
);
1796 bottom
+= (f
->output_data
.x
->line_height
- 1);
1797 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1798 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1799 right
= PIXEL_TO_CHAR_COL (f
, right
);
1801 /* Clip the rectangle to what can be visible. */
1806 if (right
> FRAME_WINDOW_WIDTH (f
))
1807 right
= FRAME_WINDOW_WIDTH (f
);
1808 if (bottom
> f
->height
)
1811 /* Get size in chars of the rectangle. */
1812 cols
= right
- left
;
1813 rows
= bottom
- top
;
1815 /* If rectangle has zero area, return. */
1816 if (rows
<= 0) return;
1817 if (cols
<= 0) return;
1819 /* Turn off the cursor if it is in the rectangle.
1820 We will turn it back on afterward. */
1821 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1822 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1828 /* Display the text in the rectangle, one text line at a time. */
1830 for (y
= top
; y
< bottom
; y
++)
1832 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1834 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1837 while (*line
& GLYPH_MASK_PADDING
)
1839 /* We must display the whole glyph of a wide-column
1846 CHAR_TO_PIXEL_COL (f
, left
),
1847 CHAR_TO_PIXEL_ROW (f
, y
),
1848 line
, min (cols
, active_frame
->used
[y
] - left
),
1849 active_frame
->highlight
[y
], 0, NULL
);
1852 /* Turn the cursor on if we turned it off. */
1855 x_update_cursor (f
, 1);
1862 /* We used to only do this if Vx_no_window_manager was non-nil, but
1863 the ICCCM (section 4.1.6) says that the window's border pixmap
1864 and border pixel are window attributes which are "private to the
1865 client", so we can always change it to whatever we want. */
1867 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1868 f
->output_data
.x
->border_pixel
);
1870 x_update_cursor (f
, 1);
1874 frame_unhighlight (f
)
1877 /* We used to only do this if Vx_no_window_manager was non-nil, but
1878 the ICCCM (section 4.1.6) says that the window's border pixmap
1879 and border pixel are window attributes which are "private to the
1880 client", so we can always change it to whatever we want. */
1882 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1883 f
->output_data
.x
->border_tile
);
1885 x_update_cursor (f
, 1);
1888 static void XTframe_rehighlight ();
1889 static void x_frame_rehighlight ();
1891 /* The focus has changed. Update the frames as necessary to reflect
1892 the new situation. Note that we can't change the selected frame
1893 here, because the Lisp code we are interrupting might become confused.
1894 Each event gets marked with the frame in which it occurred, so the
1895 Lisp code can tell when the switch took place by examining the events. */
1898 x_new_focus_frame (dpyinfo
, frame
)
1899 struct x_display_info
*dpyinfo
;
1900 struct frame
*frame
;
1902 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1903 int events_enqueued
= 0;
1905 if (frame
!= dpyinfo
->x_focus_frame
)
1907 /* Set this before calling other routines, so that they see
1908 the correct value of x_focus_frame. */
1909 dpyinfo
->x_focus_frame
= frame
;
1911 if (old_focus
&& old_focus
->auto_lower
)
1912 x_lower_frame (old_focus
);
1915 selected_frame
= frame
;
1916 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1918 Fselect_window (selected_frame
->selected_window
);
1919 choose_minibuf_frame ();
1922 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1923 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1925 pending_autoraise_frame
= 0;
1928 x_frame_rehighlight (dpyinfo
);
1931 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1934 x_mouse_leave (dpyinfo
)
1935 struct x_display_info
*dpyinfo
;
1937 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1940 /* The focus has changed, or we have redirected a frame's focus to
1941 another frame (this happens when a frame uses a surrogate
1942 minibuffer frame). Shift the highlight as appropriate.
1944 The FRAME argument doesn't necessarily have anything to do with which
1945 frame is being highlighted or unhighlighted; we only use it to find
1946 the appropriate X display info. */
1948 XTframe_rehighlight (frame
)
1949 struct frame
*frame
;
1951 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1955 x_frame_rehighlight (dpyinfo
)
1956 struct x_display_info
*dpyinfo
;
1958 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1960 if (dpyinfo
->x_focus_frame
)
1962 dpyinfo
->x_highlight_frame
1963 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1964 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1965 : dpyinfo
->x_focus_frame
);
1966 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1968 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1969 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1973 dpyinfo
->x_highlight_frame
= 0;
1975 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1978 frame_unhighlight (old_highlight
);
1979 if (dpyinfo
->x_highlight_frame
)
1980 frame_highlight (dpyinfo
->x_highlight_frame
);
1984 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1986 /* Initialize mode_switch_bit and modifier_meaning. */
1988 x_find_modifier_meanings (dpyinfo
)
1989 struct x_display_info
*dpyinfo
;
1991 int min_code
, max_code
;
1994 XModifierKeymap
*mods
;
1996 dpyinfo
->meta_mod_mask
= 0;
1997 dpyinfo
->shift_lock_mask
= 0;
1998 dpyinfo
->alt_mod_mask
= 0;
1999 dpyinfo
->super_mod_mask
= 0;
2000 dpyinfo
->hyper_mod_mask
= 0;
2003 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
2005 min_code
= dpyinfo
->display
->min_keycode
;
2006 max_code
= dpyinfo
->display
->max_keycode
;
2009 syms
= XGetKeyboardMapping (dpyinfo
->display
,
2010 min_code
, max_code
- min_code
+ 1,
2012 mods
= XGetModifierMapping (dpyinfo
->display
);
2014 /* Scan the modifier table to see which modifier bits the Meta and
2015 Alt keysyms are on. */
2017 int row
, col
; /* The row and column in the modifier table. */
2019 for (row
= 3; row
< 8; row
++)
2020 for (col
= 0; col
< mods
->max_keypermod
; col
++)
2023 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
2025 /* Zeroes are used for filler. Skip them. */
2029 /* Are any of this keycode's keysyms a meta key? */
2033 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
2035 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
2041 dpyinfo
->meta_mod_mask
|= (1 << row
);
2046 dpyinfo
->alt_mod_mask
|= (1 << row
);
2051 dpyinfo
->hyper_mod_mask
|= (1 << row
);
2056 dpyinfo
->super_mod_mask
|= (1 << row
);
2060 /* Ignore this if it's not on the lock modifier. */
2061 if ((1 << row
) == LockMask
)
2062 dpyinfo
->shift_lock_mask
= LockMask
;
2070 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
2071 if (! dpyinfo
->meta_mod_mask
)
2073 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
2074 dpyinfo
->alt_mod_mask
= 0;
2077 /* If some keys are both alt and meta,
2078 make them just meta, not alt. */
2079 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
2081 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
2084 XFree ((char *) syms
);
2085 XFreeModifiermap (mods
);
2088 /* Convert between the modifier bits X uses and the modifier bits
2091 x_x_to_emacs_modifiers (dpyinfo
, state
)
2092 struct x_display_info
*dpyinfo
;
2095 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
2096 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
2097 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
2098 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
2099 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
2100 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
2104 x_emacs_to_x_modifiers (dpyinfo
, state
)
2105 struct x_display_info
*dpyinfo
;
2108 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
2109 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
2110 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
2111 | ((state
& shift_modifier
) ? ShiftMask
: 0)
2112 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
2113 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
2116 /* Convert a keysym to its name. */
2119 x_get_keysym_name (keysym
)
2125 value
= XKeysymToString (keysym
);
2131 /* Mouse clicks and mouse movement. Rah. */
2133 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
2134 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
2135 that the glyph at X, Y occupies, if BOUNDS != 0.
2136 If NOCLIP is nonzero, do not force the value into range. */
2139 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2141 register int pix_x
, pix_y
;
2142 register int *x
, *y
;
2146 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
2147 even for negative values. */
2149 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
2151 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
2153 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
2154 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
2158 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
2159 bounds
->height
= f
->output_data
.x
->line_height
;
2160 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
2161 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
2168 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
2169 pix_x
= FRAME_WINDOW_WIDTH (f
);
2173 else if (pix_y
> f
->height
)
2182 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2185 register int *pix_x
, *pix_y
;
2187 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
2188 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
2191 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2193 If the event is a button press, then note that we have grabbed
2197 construct_mouse_click (result
, event
, f
)
2198 struct input_event
*result
;
2199 XButtonEvent
*event
;
2202 /* Make the event type no_event; we'll change that when we decide
2204 result
->kind
= mouse_click
;
2205 result
->code
= event
->button
- Button1
;
2206 result
->timestamp
= event
->time
;
2207 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2209 | (event
->type
== ButtonRelease
2217 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2218 XSETFASTINT (result
->x
, column
);
2219 XSETFASTINT (result
->y
, row
);
2221 XSETINT (result
->x
, event
->x
);
2222 XSETINT (result
->y
, event
->y
);
2223 XSETFRAME (result
->frame_or_window
, f
);
2227 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2230 construct_menu_click (result
, event
, f
)
2231 struct input_event
*result
;
2232 XButtonEvent
*event
;
2235 /* Make the event type no_event; we'll change that when we decide
2237 result
->kind
= mouse_click
;
2238 result
->code
= event
->button
- Button1
;
2239 result
->timestamp
= event
->time
;
2240 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2242 | (event
->type
== ButtonRelease
2246 XSETINT (result
->x
, event
->x
);
2247 XSETINT (result
->y
, -1);
2248 XSETFRAME (result
->frame_or_window
, f
);
2251 /* Function to report a mouse movement to the mainstream Emacs code.
2252 The input handler calls this.
2254 We have received a mouse movement event, which is given in *event.
2255 If the mouse is over a different glyph than it was last time, tell
2256 the mainstream emacs code by setting mouse_moved. If not, ask for
2257 another motion event, so we can check again the next time it moves. */
2260 note_mouse_movement (frame
, event
)
2262 XMotionEvent
*event
;
2264 last_mouse_movement_time
= event
->time
;
2266 if (event
->window
!= FRAME_X_WINDOW (frame
))
2268 frame
->mouse_moved
= 1;
2269 last_mouse_scroll_bar
= Qnil
;
2271 note_mouse_highlight (frame
, -1, -1);
2274 /* Has the mouse moved off the glyph it was on at the last sighting? */
2275 else if (event
->x
< last_mouse_glyph
.x
2276 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2277 || event
->y
< last_mouse_glyph
.y
2278 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2280 frame
->mouse_moved
= 1;
2281 last_mouse_scroll_bar
= Qnil
;
2283 note_mouse_highlight (frame
, event
->x
, event
->y
);
2287 /* This is used for debugging, to turn off note_mouse_highlight. */
2288 static int disable_mouse_highlight
;
2290 /* Take proper action when the mouse has moved to position X, Y on frame F
2291 as regards highlighting characters that have mouse-face properties.
2292 Also dehighlighting chars where the mouse was before.
2293 X and Y can be negative or out of range. */
2296 note_mouse_highlight (f
, x
, y
)
2300 int row
, column
, portion
;
2301 XRectangle new_glyph
;
2305 if (disable_mouse_highlight
)
2308 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2309 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2310 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2312 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
2317 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2321 /* Find out which glyph the mouse is on. */
2322 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2323 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
2325 /* Which window is that in? */
2326 window
= window_from_coordinates (f
, column
, row
, &portion
);
2327 w
= XWINDOW (window
);
2329 /* If we were displaying active text in another window, clear that. */
2330 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
2331 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2333 /* Are we in a window whose display is up to date?
2334 And verify the buffer's text has not changed. */
2335 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2336 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2337 && EQ (w
->window_end_valid
, w
->buffer
)
2338 && XFASTINT (w
->last_modified
) == BUF_MODIFF (XBUFFER (w
->buffer
))
2339 && (XFASTINT (w
->last_overlay_modified
)
2340 == BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
))))
2342 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2345 /* Find which buffer position the mouse corresponds to. */
2346 for (i
= column
; i
>= 0; i
--)
2350 /* Is it outside the displayed active region (if any)? */
2352 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2353 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
2354 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2355 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2356 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2357 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2358 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2359 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2360 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2362 Lisp_Object mouse_face
, overlay
, position
;
2363 Lisp_Object
*overlay_vec
;
2364 int len
, noverlays
, ignor1
;
2365 struct buffer
*obuf
;
2368 /* If we get an out-of-range value, return now; avoid an error. */
2369 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2372 /* Make the window's buffer temporarily current for
2373 overlays_at and compute_char_face. */
2374 obuf
= current_buffer
;
2375 current_buffer
= XBUFFER (w
->buffer
);
2381 /* Yes. Clear the display of the old active region, if any. */
2382 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2384 /* Is this char mouse-active? */
2385 XSETINT (position
, pos
);
2388 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2390 /* Put all the overlays we want in a vector in overlay_vec.
2391 Store the length in len. */
2392 noverlays
= overlays_at (pos
, 1, &overlay_vec
, &len
,
2394 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2396 /* Find the highest priority overlay that has a mouse-face prop. */
2398 for (i
= 0; i
< noverlays
; i
++)
2400 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2401 if (!NILP (mouse_face
))
2403 overlay
= overlay_vec
[i
];
2408 /* If no overlay applies, get a text property. */
2410 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2412 /* Handle the overlay case. */
2413 if (! NILP (overlay
))
2415 /* Find the range of text around this char that
2416 should be active. */
2417 Lisp_Object before
, after
;
2420 before
= Foverlay_start (overlay
);
2421 after
= Foverlay_end (overlay
);
2422 /* Record this as the current active region. */
2423 fast_find_position (window
, XFASTINT (before
),
2424 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2425 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2426 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2427 = !fast_find_position (window
, XFASTINT (after
),
2428 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2429 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2430 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2431 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2432 = compute_char_face (f
, w
, pos
, 0, 0,
2433 &ignore
, pos
+ 1, 1);
2435 /* Display it as active. */
2436 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2438 /* Handle the text property case. */
2439 else if (! NILP (mouse_face
))
2441 /* Find the range of text around this char that
2442 should be active. */
2443 Lisp_Object before
, after
, beginning
, end
;
2446 beginning
= Fmarker_position (w
->start
);
2447 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2448 - XFASTINT (w
->window_end_pos
)));
2450 = Fprevious_single_property_change (make_number (pos
+ 1),
2452 w
->buffer
, beginning
);
2454 = Fnext_single_property_change (position
, Qmouse_face
,
2456 /* Record this as the current active region. */
2457 fast_find_position (window
, XFASTINT (before
),
2458 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2459 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2460 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2461 = !fast_find_position (window
, XFASTINT (after
),
2462 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2463 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2464 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2465 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2466 = compute_char_face (f
, w
, pos
, 0, 0,
2467 &ignore
, pos
+ 1, 1);
2469 /* Display it as active. */
2470 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2474 current_buffer
= obuf
;
2479 /* Find the row and column of position POS in window WINDOW.
2480 Store them in *COLUMNP and *ROWP.
2481 This assumes display in WINDOW is up to date.
2482 If POS is above start of WINDOW, return coords
2483 of start of first screen line.
2484 If POS is after end of WINDOW, return coords of end of last screen line.
2486 Value is 1 if POS is in range, 0 if it was off screen. */
2489 fast_find_position (window
, pos
, columnp
, rowp
)
2492 int *columnp
, *rowp
;
2494 struct window
*w
= XWINDOW (window
);
2495 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2498 int left
= WINDOW_LEFT_MARGIN (w
);
2499 int top
= XFASTINT (w
->top
);
2500 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2501 int width
= window_internal_width (w
);
2504 int maybe_next_line
= 0;
2506 /* Find the right row. */
2511 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2512 if (linestart
> pos
)
2514 /* If the position sought is the end of the buffer,
2515 don't include the blank lines at the bottom of the window. */
2516 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2518 maybe_next_line
= 1;
2525 /* Find the right column with in it. */
2526 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2528 for (i
= 0; i
< width
; i
++)
2530 if (charstarts
[left
+ i
] == pos
)
2533 *columnp
= i
+ left
;
2536 else if (charstarts
[left
+ i
] > pos
)
2538 else if (charstarts
[left
+ i
] > 0)
2542 /* If we're looking for the end of the buffer,
2543 and we didn't find it in the line we scanned,
2544 use the start of the following line. */
2545 if (maybe_next_line
)
2556 /* Display the active region described by mouse_face_*
2557 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2560 show_mouse_face (dpyinfo
, hl
)
2561 struct x_display_info
*dpyinfo
;
2564 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2565 int width
= window_internal_width (w
);
2566 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2569 int old_curs_x
= curs_x
;
2570 int old_curs_y
= curs_y
;
2572 /* Set these variables temporarily
2573 so that if we have to turn the cursor off and on again
2574 we will put it back at the same place. */
2575 curs_x
= f
->phys_cursor_x
;
2576 curs_y
= f
->phys_cursor_y
;
2577 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2578 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2580 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2581 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2582 : WINDOW_LEFT_MARGIN (w
));
2583 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2584 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2585 : WINDOW_LEFT_MARGIN (w
) + width
);
2586 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2588 /* If the cursor's in the text we are about to rewrite,
2589 turn the cursor off. */
2591 && curs_x
>= column
- 1
2592 && curs_x
<= endcolumn
)
2594 x_update_cursor (f
, 0);
2599 CHAR_TO_PIXEL_COL (f
, column
),
2600 CHAR_TO_PIXEL_ROW (f
, i
),
2601 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2603 /* Highlight with mouse face if hl > 0. */
2604 hl
> 0 ? 3 : 0, 0, NULL
);
2607 /* If we turned the cursor off, turn it back on. */
2609 x_display_cursor (f
, 1, curs_x
, curs_y
);
2611 curs_x
= old_curs_x
;
2612 curs_y
= old_curs_y
;
2614 /* Change the mouse cursor according to the value of HL. */
2616 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2617 f
->output_data
.x
->cross_cursor
);
2619 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2620 f
->output_data
.x
->text_cursor
);
2623 /* Clear out the mouse-highlighted active region.
2624 Redraw it unhighlighted first. */
2627 clear_mouse_face (dpyinfo
)
2628 struct x_display_info
*dpyinfo
;
2630 if (! NILP (dpyinfo
->mouse_face_window
))
2631 show_mouse_face (dpyinfo
, 0);
2633 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2634 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2635 dpyinfo
->mouse_face_window
= Qnil
;
2638 /* Just discard the mouse face information for frame F, if any.
2639 This is used when the size of F is changed. */
2641 cancel_mouse_face (f
)
2645 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2647 window
= dpyinfo
->mouse_face_window
;
2648 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2650 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2651 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2652 dpyinfo
->mouse_face_window
= Qnil
;
2656 static struct scroll_bar
*x_window_to_scroll_bar ();
2657 static void x_scroll_bar_report_motion ();
2659 /* Return the current position of the mouse.
2660 *fp should be a frame which indicates which display to ask about.
2662 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2663 and *part to the frame, window, and scroll bar part that the mouse
2664 is over. Set *x and *y to the portion and whole of the mouse's
2665 position on the scroll bar.
2667 If the mouse movement started elsewhere, set *fp to the frame the
2668 mouse is on, *bar_window to nil, and *x and *y to the character cell
2671 Set *time to the server timestamp for the time at which the mouse
2672 was at this position.
2674 Don't store anything if we don't have a valid set of values to report.
2676 This clears the mouse_moved flag, so we can wait for the next mouse
2680 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2683 Lisp_Object
*bar_window
;
2684 enum scroll_bar_part
*part
;
2686 unsigned long *time
;
2692 if (! NILP (last_mouse_scroll_bar
))
2693 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2699 Window dummy_window
;
2702 Lisp_Object frame
, tail
;
2704 /* Clear the mouse-moved flag for every frame on this display. */
2705 FOR_EACH_FRAME (tail
, frame
)
2706 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2707 XFRAME (frame
)->mouse_moved
= 0;
2709 last_mouse_scroll_bar
= Qnil
;
2711 /* Figure out which root window we're on. */
2712 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2713 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2715 /* The root window which contains the pointer. */
2718 /* Trash which we can't trust if the pointer is on
2719 a different screen. */
2722 /* The position on that root window. */
2725 /* More trash we can't trust. */
2728 /* Modifier keys and pointer buttons, about which
2730 (unsigned int *) &dummy
);
2732 /* Now we have a position on the root; find the innermost window
2733 containing the pointer. */
2737 int parent_x
, parent_y
;
2742 /* XTranslateCoordinates can get errors if the window
2743 structure is changing at the same time this function
2744 is running. So at least we must not crash from them. */
2746 count
= x_catch_errors (FRAME_X_DISPLAY (*fp
));
2748 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2749 && FRAME_LIVE_P (last_mouse_frame
))
2751 /* If mouse was grabbed on a frame, give coords for that frame
2752 even if the mouse is now outside it. */
2753 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2755 /* From-window, to-window. */
2756 root
, FRAME_X_WINDOW (last_mouse_frame
),
2758 /* From-position, to-position. */
2759 root_x
, root_y
, &win_x
, &win_y
,
2763 f1
= last_mouse_frame
;
2769 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2771 /* From-window, to-window. */
2774 /* From-position, to-position. */
2775 root_x
, root_y
, &win_x
, &win_y
,
2780 if (child
== None
|| child
== win
)
2788 /* Now we know that:
2789 win is the innermost window containing the pointer
2790 (XTC says it has no child containing the pointer),
2791 win_x and win_y are the pointer's position in it
2792 (XTC did this the last time through), and
2793 parent_x and parent_y are the pointer's position in win's parent.
2794 (They are what win_x and win_y were when win was child.
2795 If win is the root window, it has no parent, and
2796 parent_{x,y} are invalid, but that's okay, because we'll
2797 never use them in that case.) */
2799 /* Is win one of our frames? */
2800 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2803 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2806 x_uncatch_errors (FRAME_X_DISPLAY (*fp
), count
);
2808 /* If not, is it one of our scroll bars? */
2811 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2815 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2821 if (f1
== 0 && insist
)
2822 f1
= selected_frame
;
2826 int ignore1
, ignore2
;
2828 /* Ok, we found a frame. Store all the values. */
2830 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2832 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2838 XSETINT (*x
, win_x
);
2839 XSETINT (*y
, win_y
);
2840 *time
= last_mouse_movement_time
;
2848 /* Scroll bar support. */
2850 /* Given an X window ID, find the struct scroll_bar which manages it.
2851 This can be called in GC, so we have to make sure to strip off mark
2853 static struct scroll_bar
*
2854 x_window_to_scroll_bar (window_id
)
2857 Lisp_Object tail
, frame
;
2859 for (tail
= Vframe_list
;
2860 XGCTYPE (tail
) == Lisp_Cons
;
2861 tail
= XCONS (tail
)->cdr
)
2863 Lisp_Object frame
, bar
, condemned
;
2865 frame
= XCONS (tail
)->car
;
2866 /* All elements of Vframe_list should be frames. */
2867 if (! GC_FRAMEP (frame
))
2870 /* Scan this frame's scroll bar list for a scroll bar with the
2872 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2873 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2874 /* This trick allows us to search both the ordinary and
2875 condemned scroll bar lists with one loop. */
2876 ! GC_NILP (bar
) || (bar
= condemned
,
2879 bar
= XSCROLL_BAR (bar
)->next
)
2880 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2881 return XSCROLL_BAR (bar
);
2887 /* Open a new X window to serve as a scroll bar, and return the
2888 scroll bar vector for it. */
2889 static struct scroll_bar
*
2890 x_scroll_bar_create (window
, top
, left
, width
, height
)
2891 struct window
*window
;
2892 int top
, left
, width
, height
;
2894 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2895 struct scroll_bar
*bar
2896 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2901 XSetWindowAttributes a
;
2903 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2904 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2905 | ButtonMotionMask
| PointerMotionHintMask
2907 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2909 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2914 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2915 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2916 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2917 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2918 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2919 sb_widget
= XtCreateManagedWidget ("box",
2921 f
->output_data
.x
->edit_widget
, al
, ac
);
2922 SET_SCROLL_BAR_X_WINDOW
2923 (bar
, sb_widget
->core
.window
);
2925 SET_SCROLL_BAR_X_WINDOW
2927 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2929 /* Position and size of scroll bar. */
2930 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, top
,
2931 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2, height
,
2933 /* Border width, depth, class, and visual. */
2934 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2940 XSETWINDOW (bar
->window
, window
);
2941 XSETINT (bar
->top
, top
);
2942 XSETINT (bar
->left
, left
);
2943 XSETINT (bar
->width
, width
);
2944 XSETINT (bar
->height
, height
);
2945 XSETINT (bar
->start
, 0);
2946 XSETINT (bar
->end
, 0);
2947 bar
->dragging
= Qnil
;
2949 /* Add bar to its frame's list of scroll bars. */
2950 bar
->next
= FRAME_SCROLL_BARS (f
);
2952 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2953 if (! NILP (bar
->next
))
2954 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2956 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2963 /* Draw BAR's handle in the proper position.
2964 If the handle is already drawn from START to END, don't bother
2965 redrawing it, unless REBUILD is non-zero; in that case, always
2966 redraw it. (REBUILD is handy for drawing the handle after expose
2969 Normally, we want to constrain the start and end of the handle to
2970 fit inside its rectangle, but if the user is dragging the scroll bar
2971 handle, we want to let them drag it down all the way, so that the
2972 bar's top is as far down as it goes; otherwise, there's no way to
2973 move to the very end of the buffer. */
2975 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2976 struct scroll_bar
*bar
;
2980 int dragging
= ! NILP (bar
->dragging
);
2981 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2982 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2983 GC gc
= f
->output_data
.x
->normal_gc
;
2985 /* If the display is already accurate, do nothing. */
2987 && start
== XINT (bar
->start
)
2988 && end
== XINT (bar
->end
))
2994 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
2995 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
2996 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
2998 /* Make sure the values are reasonable, and try to preserve
2999 the distance between start and end. */
3001 int length
= end
- start
;
3005 else if (start
> top_range
)
3007 end
= start
+ length
;
3011 else if (end
> top_range
&& ! dragging
)
3015 /* Store the adjusted setting in the scroll bar. */
3016 XSETINT (bar
->start
, start
);
3017 XSETINT (bar
->end
, end
);
3019 /* Clip the end position, just for display. */
3020 if (end
> top_range
)
3023 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
3024 below top positions, to make sure the handle is always at least
3025 that many pixels tall. */
3026 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
3028 /* Draw the empty space above the handle. Note that we can't clear
3029 zero-height areas; that means "clear to end of window." */
3031 XClearArea (FRAME_X_DISPLAY (f
), w
,
3033 /* x, y, width, height, and exposures. */
3034 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3035 VERTICAL_SCROLL_BAR_TOP_BORDER
,
3036 inside_width
, start
,
3039 /* Draw the handle itself. */
3040 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3042 /* x, y, width, height */
3043 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3044 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
3045 inside_width
, end
- start
);
3048 /* Draw the empty space below the handle. Note that we can't
3049 clear zero-height areas; that means "clear to end of window." */
3050 if (end
< inside_height
)
3051 XClearArea (FRAME_X_DISPLAY (f
), w
,
3053 /* x, y, width, height, and exposures. */
3054 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3055 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
3056 inside_width
, inside_height
- end
,
3064 /* Move a scroll bar around on the screen, to accommodate changing
3065 window configurations. */
3067 x_scroll_bar_move (bar
, top
, left
, width
, height
)
3068 struct scroll_bar
*bar
;
3069 int top
, left
, width
, height
;
3071 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3072 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3078 unsigned int mask
= 0;
3080 wc
.x
= left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3083 wc
.width
= width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
3086 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
3087 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
3088 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
3089 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
3092 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
3096 XSETINT (bar
->left
, left
);
3097 XSETINT (bar
->top
, top
);
3098 XSETINT (bar
->width
, width
);
3099 XSETINT (bar
->height
, height
);
3104 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
3107 x_scroll_bar_remove (bar
)
3108 struct scroll_bar
*bar
;
3110 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3114 /* Destroy the window. */
3115 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3117 /* Disassociate this scroll bar from its window. */
3118 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3123 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3124 that we are displaying PORTION characters out of a total of WHOLE
3125 characters, starting at POSITION. If WINDOW has no scroll bar,
3128 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
3129 struct window
*window
;
3130 int portion
, whole
, position
;
3132 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3133 int top
= XINT (window
->top
);
3134 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
3135 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
3137 /* Where should this scroll bar be, pixelwise? */
3138 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
3139 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
3141 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3142 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3143 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3144 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
3146 struct scroll_bar
*bar
;
3148 /* Does the scroll bar exist yet? */
3149 if (NILP (window
->vertical_scroll_bar
))
3150 bar
= x_scroll_bar_create (window
,
3151 pixel_top
, pixel_left
,
3152 pixel_width
, pixel_height
);
3155 /* It may just need to be moved and resized. */
3156 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3157 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
3160 /* Set the scroll bar's current state, unless we're currently being
3162 if (NILP (bar
->dragging
))
3164 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
3167 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
3170 int start
= ((double) position
* top_range
) / whole
;
3171 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
3173 x_scroll_bar_set_handle (bar
, start
, end
, 0);
3177 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
3181 /* The following three hooks are used when we're doing a thorough
3182 redisplay of the frame. We don't explicitly know which scroll bars
3183 are going to be deleted, because keeping track of when windows go
3184 away is a real pain - "Can you say set-window-configuration, boys
3185 and girls?" Instead, we just assert at the beginning of redisplay
3186 that *all* scroll bars are to be removed, and then save a scroll bar
3187 from the fiery pit when we actually redisplay its window. */
3189 /* Arrange for all scroll bars on FRAME to be removed at the next call
3190 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3191 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
3193 XTcondemn_scroll_bars (frame
)
3196 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3197 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3200 bar
= FRAME_SCROLL_BARS (frame
);
3201 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3202 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3203 XSCROLL_BAR (bar
)->prev
= Qnil
;
3204 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3205 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3206 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3210 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
3211 Note that WINDOW isn't necessarily condemned at all. */
3213 XTredeem_scroll_bar (window
)
3214 struct window
*window
;
3216 struct scroll_bar
*bar
;
3218 /* We can't redeem this window's scroll bar if it doesn't have one. */
3219 if (NILP (window
->vertical_scroll_bar
))
3222 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3224 /* Unlink it from the condemned list. */
3226 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3228 if (NILP (bar
->prev
))
3230 /* If the prev pointer is nil, it must be the first in one of
3232 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3233 /* It's not condemned. Everything's fine. */
3235 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3236 window
->vertical_scroll_bar
))
3237 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3239 /* If its prev pointer is nil, it must be at the front of
3240 one or the other! */
3244 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3246 if (! NILP (bar
->next
))
3247 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3249 bar
->next
= FRAME_SCROLL_BARS (f
);
3251 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3252 if (! NILP (bar
->next
))
3253 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3257 /* Remove all scroll bars on FRAME that haven't been saved since the
3258 last call to `*condemn_scroll_bars_hook'. */
3260 XTjudge_scroll_bars (f
)
3263 Lisp_Object bar
, next
;
3265 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3267 /* Clear out the condemned list now so we won't try to process any
3268 more events on the hapless scroll bars. */
3269 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3271 for (; ! NILP (bar
); bar
= next
)
3273 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3275 x_scroll_bar_remove (b
);
3278 b
->next
= b
->prev
= Qnil
;
3281 /* Now there should be no references to the condemned scroll bars,
3282 and they should get garbage-collected. */
3286 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3288 This may be called from a signal handler, so we have to ignore GC
3291 x_scroll_bar_expose (bar
, event
)
3292 struct scroll_bar
*bar
;
3295 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3296 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3297 GC gc
= f
->output_data
.x
->normal_gc
;
3298 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3302 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3304 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3305 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3307 /* x, y, width, height */
3309 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
3310 XINT (bar
->height
) - 1);
3315 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3316 is set to something other than no_event, it is enqueued.
3318 This may be called from a signal handler, so we have to ignore GC
3321 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3322 struct scroll_bar
*bar
;
3324 struct input_event
*emacs_event
;
3326 if (! GC_WINDOWP (bar
->window
))
3329 emacs_event
->kind
= scroll_bar_click
;
3330 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3331 emacs_event
->modifiers
3332 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
3333 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
3334 event
->xbutton
.state
)
3335 | (event
->type
== ButtonRelease
3338 emacs_event
->frame_or_window
= bar
->window
;
3339 emacs_event
->timestamp
= event
->xbutton
.time
;
3341 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3343 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3345 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3346 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3349 if (y
> top_range
) y
= top_range
;
3351 if (y
< XINT (bar
->start
))
3352 emacs_event
->part
= scroll_bar_above_handle
;
3353 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3354 emacs_event
->part
= scroll_bar_handle
;
3356 emacs_event
->part
= scroll_bar_below_handle
;
3358 /* Just because the user has clicked on the handle doesn't mean
3359 they want to drag it. Lisp code needs to be able to decide
3360 whether or not we're dragging. */
3362 /* If the user has just clicked on the handle, record where they're
3364 if (event
->type
== ButtonPress
3365 && emacs_event
->part
== scroll_bar_handle
)
3366 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
3369 /* If the user has released the handle, set it to its final position. */
3370 if (event
->type
== ButtonRelease
3371 && ! NILP (bar
->dragging
))
3373 int new_start
= y
- XINT (bar
->dragging
);
3374 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3376 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3377 bar
->dragging
= Qnil
;
3380 /* Same deal here as the other #if 0. */
3382 /* Clicks on the handle are always reported as occurring at the top of
3384 if (emacs_event
->part
== scroll_bar_handle
)
3385 emacs_event
->x
= bar
->start
;
3387 XSETINT (emacs_event
->x
, y
);
3389 XSETINT (emacs_event
->x
, y
);
3392 XSETINT (emacs_event
->y
, top_range
);
3396 /* Handle some mouse motion while someone is dragging the scroll bar.
3398 This may be called from a signal handler, so we have to ignore GC
3401 x_scroll_bar_note_movement (bar
, event
)
3402 struct scroll_bar
*bar
;
3405 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
3407 last_mouse_movement_time
= event
->xmotion
.time
;
3410 XSETVECTOR (last_mouse_scroll_bar
, bar
);
3412 /* If we're dragging the bar, display it. */
3413 if (! GC_NILP (bar
->dragging
))
3415 /* Where should the handle be now? */
3416 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3418 if (new_start
!= XINT (bar
->start
))
3420 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3422 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3427 /* Return information to the user about the current position of the mouse
3428 on the scroll bar. */
3430 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3432 Lisp_Object
*bar_window
;
3433 enum scroll_bar_part
*part
;
3435 unsigned long *time
;
3437 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3438 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3439 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3441 Window dummy_window
;
3443 unsigned int dummy_mask
;
3447 /* Get the mouse's position relative to the scroll bar window, and
3449 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3451 /* Root, child, root x and root y. */
3452 &dummy_window
, &dummy_window
,
3453 &dummy_coord
, &dummy_coord
,
3455 /* Position relative to scroll bar. */
3458 /* Mouse buttons and modifier keys. */
3464 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3466 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3468 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3470 if (! NILP (bar
->dragging
))
3471 win_y
-= XINT (bar
->dragging
);
3475 if (win_y
> top_range
)
3479 *bar_window
= bar
->window
;
3481 if (! NILP (bar
->dragging
))
3482 *part
= scroll_bar_handle
;
3483 else if (win_y
< XINT (bar
->start
))
3484 *part
= scroll_bar_above_handle
;
3485 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3486 *part
= scroll_bar_handle
;
3488 *part
= scroll_bar_below_handle
;
3490 XSETINT (*x
, win_y
);
3491 XSETINT (*y
, top_range
);
3494 last_mouse_scroll_bar
= Qnil
;
3497 *time
= last_mouse_movement_time
;
3503 /* The screen has been cleared so we may have changed foreground or
3504 background colors, and the scroll bars may need to be redrawn.
3505 Clear out the scroll bars, and ask for expose events, so we can
3508 x_scroll_bar_clear (f
)
3513 /* We can have scroll bars even if this is 0,
3514 if we just turned off scroll bar mode.
3515 But in that case we should not clear them. */
3516 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3517 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3518 bar
= XSCROLL_BAR (bar
)->next
)
3519 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3523 /* This processes Expose events from the menubar specific X event
3524 loop in xmenu.c. This allows to redisplay the frame if necessary
3525 when handling menubar or popup items. */
3528 process_expose_from_menu (event
)
3532 struct x_display_info
*dpyinfo
;
3536 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3537 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3540 if (f
->async_visible
== 0)
3542 f
->async_visible
= 1;
3543 f
->async_iconified
= 0;
3544 f
->output_data
.x
->has_been_visible
= 1;
3545 SET_FRAME_GARBAGED (f
);
3549 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3550 event
.xexpose
.x
, event
.xexpose
.y
,
3551 event
.xexpose
.width
, event
.xexpose
.height
);
3556 struct scroll_bar
*bar
3557 = x_window_to_scroll_bar (event
.xexpose
.window
);
3560 x_scroll_bar_expose (bar
, &event
);
3566 /* Define a queue to save up SelectionRequest events for later handling. */
3568 struct selection_event_queue
3571 struct selection_event_queue
*next
;
3574 static struct selection_event_queue
*queue
;
3576 /* Nonzero means queue up certain events--don't process them yet. */
3577 static int x_queue_selection_requests
;
3579 /* Queue up an X event *EVENT, to be processed later. */
3582 x_queue_event (f
, event
)
3586 struct selection_event_queue
*queue_tmp
3587 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3589 if (queue_tmp
!= NULL
)
3591 queue_tmp
->event
= *event
;
3592 queue_tmp
->next
= queue
;
3597 /* Take all the queued events and put them back
3598 so that they get processed afresh. */
3601 x_unqueue_events (display
)
3604 while (queue
!= NULL
)
3606 struct selection_event_queue
*queue_tmp
= queue
;
3607 XPutBackEvent (display
, &queue_tmp
->event
);
3608 queue
= queue_tmp
->next
;
3609 free ((char *)queue_tmp
);
3613 /* Start queuing SelectionRequest events. */
3616 x_start_queuing_selection_requests (display
)
3619 x_queue_selection_requests
++;
3622 /* Stop queuing SelectionRequest events. */
3625 x_stop_queuing_selection_requests (display
)
3628 x_queue_selection_requests
--;
3629 x_unqueue_events (display
);
3632 /* The main X event-reading loop - XTread_socket. */
3634 /* Timestamp of enter window event. This is only used by XTread_socket,
3635 but we have to put it out here, since static variables within functions
3636 sometimes don't work. */
3637 static Time enter_timestamp
;
3639 /* This holds the state XLookupString needs to implement dead keys
3640 and other tricks known as "compose processing". _X Window System_
3641 says that a portable program can't use this, but Stephen Gildea assures
3642 me that letting the compiler initialize it to zeros will work okay.
3644 This must be defined outside of XTread_socket, for the same reasons
3645 given for enter_timestamp, above. */
3646 static XComposeStatus compose_status
;
3648 /* Record the last 100 characters stored
3649 to help debug the loss-of-chars-during-GC problem. */
3650 static int temp_index
;
3651 static short temp_buffer
[100];
3653 /* Set this to nonzero to fake an "X I/O error"
3654 on a particular display. */
3655 struct x_display_info
*XTread_socket_fake_io_error
;
3657 /* When we find no input here, we occasionally do a no-op command
3658 to verify that the X server is still running and we can still talk with it.
3659 We try all the open displays, one by one.
3660 This variable is used for cycling thru the displays. */
3661 static struct x_display_info
*next_noop_dpyinfo
;
3663 #define SET_SAVED_MENU_EVENT(size) { \
3664 if (f->output_data.x->saved_menu_event == 0) \
3665 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
3666 bcopy (&event, f->output_data.x->saved_menu_event, size); \
3667 if (numchars >= 1) \
3669 bufp->kind = menu_bar_activate_event; \
3670 XSETFRAME (bufp->frame_or_window, f); \
3676 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
3677 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
3679 /* Read events coming from the X server.
3680 This routine is called by the SIGIO handler.
3681 We return as soon as there are no more events to be read.
3683 Events representing keys are stored in buffer BUFP,
3684 which can hold up to NUMCHARS characters.
3685 We return the number of characters stored into the buffer,
3686 thus pretending to be `read'.
3688 EXPECTED is nonzero if the caller knows input is available. */
3691 XTread_socket (sd
, bufp
, numchars
, expected
)
3693 /* register */ struct input_event
*bufp
;
3694 /* register */ int numchars
;
3700 int items_pending
; /* How many items are in the X queue. */
3703 int event_found
= 0;
3706 struct x_display_info
*dpyinfo
;
3708 Status status_return
;
3711 if (interrupt_input_blocked
)
3713 interrupt_input_pending
= 1;
3717 interrupt_input_pending
= 0;
3720 /* So people can tell when we have read the available input. */
3721 input_signal_count
++;
3724 abort (); /* Don't think this happens. */
3726 /* Find the display we are supposed to read input for.
3727 It's the one communicating on descriptor SD. */
3728 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3730 #if 0 /* This ought to be unnecessary; let's verify it. */
3732 /* If available, Xlib uses FIOSNBIO to make the socket
3733 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3734 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3735 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3736 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3737 #endif /* ! defined (FIOSNBIO) */
3740 #if 0 /* This code can't be made to work, with multiple displays,
3741 and appears not to be used on any system any more.
3742 Also keyboard.c doesn't turn O_NDELAY on and off
3743 for X connections. */
3746 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3748 extern int read_alarm_should_throw
;
3749 read_alarm_should_throw
= 1;
3750 XPeekEvent (dpyinfo
->display
, &event
);
3751 read_alarm_should_throw
= 0;
3753 #endif /* HAVE_SELECT */
3757 /* For debugging, this gives a way to fake an I/O error. */
3758 if (dpyinfo
== XTread_socket_fake_io_error
)
3760 XTread_socket_fake_io_error
= 0;
3761 x_io_error_quitter (dpyinfo
->display
);
3764 while (XPending (dpyinfo
->display
) != 0)
3766 #ifdef USE_X_TOOLKIT
3767 /* needed to raise Motif submenus */
3768 XtAppNextEvent (Xt_app_con
, &event
);
3770 XNextEvent (dpyinfo
->display
, &event
);
3774 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
3775 &event
.xclient
.window
);
3776 /* The necessity of the following line took me
3777 a full work-day to decipher from the docs!! */
3778 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
3788 if (event
.xclient
.message_type
3789 == dpyinfo
->Xatom_wm_protocols
3790 && event
.xclient
.format
== 32)
3792 if (event
.xclient
.data
.l
[0]
3793 == dpyinfo
->Xatom_wm_take_focus
)
3795 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3796 /* Since we set WM_TAKE_FOCUS, we must call
3797 XSetInputFocus explicitly. But not if f is null,
3798 since that might be an event for a deleted frame. */
3800 /* Not quite sure this is needed -pd */
3802 XSetICFocus (FRAME_XIC (f
));
3805 XSetInputFocus (event
.xclient
.display
,
3806 event
.xclient
.window
,
3807 RevertToPointerRoot
,
3808 event
.xclient
.data
.l
[1]);
3809 /* Not certain about handling scroll bars here */
3811 else if (event
.xclient
.data
.l
[0]
3812 == dpyinfo
->Xatom_wm_save_yourself
)
3814 /* Save state modify the WM_COMMAND property to
3815 something which can reinstate us. This notifies
3816 the session manager, who's looking for such a
3817 PropertyNotify. Can restart processing when
3818 a keyboard or mouse event arrives. */
3821 f
= x_top_window_to_frame (dpyinfo
,
3822 event
.xclient
.window
);
3824 /* This is just so we only give real data once
3825 for a single Emacs process. */
3826 if (f
== selected_frame
)
3827 XSetCommand (FRAME_X_DISPLAY (f
),
3828 event
.xclient
.window
,
3829 initial_argv
, initial_argc
);
3831 XSetCommand (FRAME_X_DISPLAY (f
),
3832 event
.xclient
.window
,
3836 else if (event
.xclient
.data
.l
[0]
3837 == dpyinfo
->Xatom_wm_delete_window
)
3840 = x_any_window_to_frame (dpyinfo
,
3841 event
.xclient
.window
);
3848 bufp
->kind
= delete_window_event
;
3849 XSETFRAME (bufp
->frame_or_window
, f
);
3857 else if (event
.xclient
.message_type
3858 == dpyinfo
->Xatom_wm_configure_denied
)
3861 else if (event
.xclient
.message_type
3862 == dpyinfo
->Xatom_wm_window_moved
)
3866 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3868 new_x
= event
.xclient
.data
.s
[0];
3869 new_y
= event
.xclient
.data
.s
[1];
3873 f
->output_data
.x
->left_pos
= new_x
;
3874 f
->output_data
.x
->top_pos
= new_y
;
3878 else if (event
.xclient
.message_type
3879 == dpyinfo
->Xatom_editres
)
3882 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3883 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3886 #endif /* HACK_EDITRES */
3890 case SelectionNotify
:
3891 #ifdef USE_X_TOOLKIT
3892 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3894 #endif /* not USE_X_TOOLKIT */
3895 x_handle_selection_notify (&event
);
3898 case SelectionClear
: /* Someone has grabbed ownership. */
3899 #ifdef USE_X_TOOLKIT
3900 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3902 #endif /* USE_X_TOOLKIT */
3904 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3909 bufp
->kind
= selection_clear_event
;
3910 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3911 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3912 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3913 bufp
->frame_or_window
= Qnil
;
3921 case SelectionRequest
: /* Someone wants our selection. */
3922 #ifdef USE_X_TOOLKIT
3923 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3925 #endif /* USE_X_TOOLKIT */
3926 if (x_queue_selection_requests
)
3927 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3931 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3936 bufp
->kind
= selection_request_event
;
3937 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3938 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3939 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3940 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3941 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3942 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3943 bufp
->frame_or_window
= Qnil
;
3951 case PropertyNotify
:
3952 #ifdef USE_X_TOOLKIT
3953 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3955 #endif /* not USE_X_TOOLKIT */
3956 x_handle_property_notify (&event
);
3959 case ReparentNotify
:
3960 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3964 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3965 x_real_positions (f
, &x
, &y
);
3966 f
->output_data
.x
->left_pos
= x
;
3967 f
->output_data
.x
->top_pos
= y
;
3972 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3975 if (f
->async_visible
== 0)
3977 f
->async_visible
= 1;
3978 f
->async_iconified
= 0;
3979 f
->output_data
.x
->has_been_visible
= 1;
3980 SET_FRAME_GARBAGED (f
);
3983 dumprectangle (x_window_to_frame (dpyinfo
,
3984 event
.xexpose
.window
),
3985 event
.xexpose
.x
, event
.xexpose
.y
,
3986 event
.xexpose
.width
, event
.xexpose
.height
);
3990 struct scroll_bar
*bar
3991 = x_window_to_scroll_bar (event
.xexpose
.window
);
3994 x_scroll_bar_expose (bar
, &event
);
3995 #ifdef USE_X_TOOLKIT
3998 #endif /* USE_X_TOOLKIT */
4002 case GraphicsExpose
: /* This occurs when an XCopyArea's
4003 source area was obscured or not
4005 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
4009 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
4010 event
.xgraphicsexpose
.width
,
4011 event
.xgraphicsexpose
.height
);
4013 #ifdef USE_X_TOOLKIT
4016 #endif /* USE_X_TOOLKIT */
4019 case NoExpose
: /* This occurs when an XCopyArea's
4020 source area was completely
4025 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
4026 if (f
) /* F may no longer exist if
4027 the frame was deleted. */
4029 /* While a frame is unmapped, display generation is
4030 disabled; you don't want to spend time updating a
4031 display that won't ever be seen. */
4032 f
->async_visible
= 0;
4033 /* We can't distinguish, from the event, whether the window
4034 has become iconified or invisible. So assume, if it
4035 was previously visible, than now it is iconified.
4036 But x_make_frame_invisible clears both
4037 the visible flag and the iconified flag;
4038 and that way, we know the window is not iconified now. */
4039 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
4041 f
->async_iconified
= 1;
4043 bufp
->kind
= iconify_event
;
4044 XSETFRAME (bufp
->frame_or_window
, f
);
4053 /* We use x_top_window_to_frame because map events can come
4054 for subwindows and they don't mean that the frame is visible. */
4055 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
4058 f
->async_visible
= 1;
4059 f
->async_iconified
= 0;
4060 f
->output_data
.x
->has_been_visible
= 1;
4062 /* wait_reading_process_input will notice this and update
4063 the frame's display structures. */
4064 SET_FRAME_GARBAGED (f
);
4068 bufp
->kind
= deiconify_event
;
4069 XSETFRAME (bufp
->frame_or_window
, f
);
4074 else if (! NILP (Vframe_list
)
4075 && ! NILP (XCONS (Vframe_list
)->cdr
))
4076 /* Force a redisplay sooner or later
4077 to update the frame titles
4078 in case this is the second frame. */
4079 record_asynch_buffer_change ();
4083 /* Turn off processing if we become fully obscured. */
4084 case VisibilityNotify
:
4088 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
4092 KeySym keysym
, orig_keysym
;
4093 /* al%imercury@uunet.uu.net says that making this 81 instead of
4094 80 fixed a bug whereby meta chars made his Emacs hang. */
4095 unsigned char copy_buffer
[81];
4098 #if 0 /* This was how we made f10 work in Motif.
4099 The drawback is, you can't type at Emacs when the
4100 the mouse is in the menu bar. So it is better to
4101 turn off f10 in Motif and let Emacs handle it. */
4103 if (lw_window_is_in_menubar (event
.xkey
.window
,
4104 f
->output_data
.x
->menubar_widget
4107 SET_SAVED_KEY_EVENT
;
4110 #endif /* USE_MOTIF */
4114 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
4115 extra_keyboard_modifiers
);
4116 modifiers
= event
.xkey
.state
;
4118 /* This will have to go some day... */
4120 /* make_lispy_event turns chars into control chars.
4121 Don't do it here because XLookupString is too eager. */
4122 event
.xkey
.state
&= ~ControlMask
;
4123 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
4124 | dpyinfo
->super_mod_mask
4125 | dpyinfo
->hyper_mod_mask
4126 | dpyinfo
->alt_mod_mask
);
4128 /* In case Meta is ComposeCharacter,
4129 clear its status. According to Markus Ehrnsperger
4130 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
4131 this enables ComposeCharacter to work whether or
4132 not it is combined with Meta. */
4133 if (modifiers
& dpyinfo
->meta_mod_mask
)
4134 bzero (&compose_status
, sizeof (compose_status
));
4139 /* The necessity of the following line took me
4140 a full work-day to decipher from the docs!! */
4141 if (XFilterEvent (&event
, None
))
4143 nbytes
= XmbLookupString (FRAME_XIC (f
),
4144 &event
.xkey
, copy_buffer
,
4149 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4150 80, &keysym
, &compose_status
);
4152 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4153 80, &keysym
, &compose_status
);
4156 orig_keysym
= keysym
;
4160 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
4161 || keysym
== XK_Delete
4162 #ifdef XK_ISO_Left_Tab
4163 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
4165 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
4166 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
4168 /* This recognizes the "extended function keys".
4169 It seems there's no cleaner way.
4170 Test IsModifierKey to avoid handling mode_switch
4172 || ((unsigned) (keysym
) >= XK_Select
4173 && (unsigned)(keysym
) < XK_KP_Space
)
4175 #ifdef XK_dead_circumflex
4176 || orig_keysym
== XK_dead_circumflex
4178 #ifdef XK_dead_grave
4179 || orig_keysym
== XK_dead_grave
4181 #ifdef XK_dead_tilde
4182 || orig_keysym
== XK_dead_tilde
4184 #ifdef XK_dead_diaeresis
4185 || orig_keysym
== XK_dead_diaeresis
4187 #ifdef XK_dead_macron
4188 || orig_keysym
== XK_dead_macron
4190 #ifdef XK_dead_degree
4191 || orig_keysym
== XK_dead_degree
4193 #ifdef XK_dead_acute
4194 || orig_keysym
== XK_dead_acute
4196 #ifdef XK_dead_cedilla
4197 || orig_keysym
== XK_dead_cedilla
4199 #ifdef XK_dead_breve
4200 || orig_keysym
== XK_dead_breve
4202 #ifdef XK_dead_ogonek
4203 || orig_keysym
== XK_dead_ogonek
4205 #ifdef XK_dead_caron
4206 || orig_keysym
== XK_dead_caron
4208 #ifdef XK_dead_doubleacute
4209 || orig_keysym
== XK_dead_doubleacute
4211 #ifdef XK_dead_abovedot
4212 || orig_keysym
== XK_dead_abovedot
4214 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
4215 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
4216 /* Any "vendor-specific" key is ok. */
4217 || (orig_keysym
& (1 << 28)))
4218 && ! (IsModifierKey (orig_keysym
)
4220 #ifdef XK_Mode_switch
4221 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
4224 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
4226 #endif /* not HAVE_X11R5 */
4229 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4231 temp_buffer
[temp_index
++] = keysym
;
4232 bufp
->kind
= non_ascii_keystroke
;
4233 bufp
->code
= keysym
;
4234 XSETFRAME (bufp
->frame_or_window
, f
);
4236 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4238 bufp
->timestamp
= event
.xkey
.time
;
4243 else if (numchars
> nbytes
)
4247 for (i
= 0; i
< nbytes
; i
++)
4249 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4251 temp_buffer
[temp_index
++] = copy_buffer
[i
];
4252 bufp
->kind
= ascii_keystroke
;
4253 bufp
->code
= copy_buffer
[i
];
4254 XSETFRAME (bufp
->frame_or_window
, f
);
4256 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4258 bufp
->timestamp
= event
.xkey
.time
;
4273 /* Here's a possible interpretation of the whole
4274 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
4275 FocusIn event, you have to get a FocusOut event before you
4276 relinquish the focus. If you haven't received a FocusIn event,
4277 then a mere LeaveNotify is enough to free you. */
4280 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4282 if (event
.xcrossing
.focus
) /* Entered Window */
4284 /* Avoid nasty pop/raise loops. */
4285 if (f
&& (!(f
->auto_raise
)
4287 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4289 x_new_focus_frame (dpyinfo
, f
);
4290 enter_timestamp
= event
.xcrossing
.time
;
4293 else if (f
== dpyinfo
->x_focus_frame
)
4294 x_new_focus_frame (dpyinfo
, 0);
4295 /* EnterNotify counts as mouse movement,
4296 so update things that depend on mouse position. */
4298 note_mouse_movement (f
, &event
.xmotion
);
4302 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4303 if (event
.xfocus
.detail
!= NotifyPointer
)
4304 dpyinfo
->x_focus_event_frame
= f
;
4306 x_new_focus_frame (dpyinfo
, f
);
4309 if (f
&& FRAME_XIC (f
))
4310 XSetICFocus (FRAME_XIC (f
));
4316 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4319 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4320 /* If we move outside the frame,
4321 then we're certainly no longer on any text in the frame. */
4322 clear_mouse_face (dpyinfo
);
4324 if (event
.xcrossing
.focus
)
4325 x_mouse_leave (dpyinfo
);
4328 if (f
== dpyinfo
->x_focus_event_frame
)
4329 dpyinfo
->x_focus_event_frame
= 0;
4330 if (f
== dpyinfo
->x_focus_frame
)
4331 x_new_focus_frame (dpyinfo
, 0);
4337 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4338 if (event
.xfocus
.detail
!= NotifyPointer
4339 && f
== dpyinfo
->x_focus_event_frame
)
4340 dpyinfo
->x_focus_event_frame
= 0;
4341 if (f
&& f
== dpyinfo
->x_focus_frame
)
4342 x_new_focus_frame (dpyinfo
, 0);
4345 if (f
&& FRAME_XIC (f
))
4346 XUnsetICFocus (FRAME_XIC (f
));
4353 if (dpyinfo
->grabbed
&& last_mouse_frame
4354 && FRAME_LIVE_P (last_mouse_frame
))
4355 f
= last_mouse_frame
;
4357 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
4359 note_mouse_movement (f
, &event
.xmotion
);
4362 struct scroll_bar
*bar
4363 = x_window_to_scroll_bar (event
.xmotion
.window
);
4366 x_scroll_bar_note_movement (bar
, &event
);
4368 /* If we move outside the frame,
4369 then we're certainly no longer on any text in the frame. */
4370 clear_mouse_face (dpyinfo
);
4375 case ConfigureNotify
:
4376 f
= x_top_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
4379 #ifndef USE_X_TOOLKIT
4380 /* In the toolkit version, change_frame_size
4381 is called by the code that handles resizing
4382 of the EmacsFrame widget. */
4384 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4385 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4387 /* Even if the number of character rows and columns has
4388 not changed, the font size may have changed, so we need
4389 to check the pixel dimensions as well. */
4390 if (columns
!= f
->width
4391 || rows
!= f
->height
4392 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
4393 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
4395 change_frame_size (f
, rows
, columns
, 0, 1);
4396 SET_FRAME_GARBAGED (f
);
4397 cancel_mouse_face (f
);
4401 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
4402 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
4404 /* What we have now is the position of Emacs's own window.
4405 Convert that to the position of the window manager window. */
4406 x_real_positions (f
, &f
->output_data
.x
->left_pos
,
4407 &f
->output_data
.x
->top_pos
);
4409 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
4411 /* Since the WM decorations come below top_pos now,
4412 we must put them below top_pos in the future. */
4413 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4414 x_wm_set_size_hint (f
, (long) 0, 0);
4422 /* If we decide we want to generate an event to be seen
4423 by the rest of Emacs, we put it here. */
4424 struct input_event emacs_event
;
4425 emacs_event
.kind
= no_event
;
4427 bzero (&compose_status
, sizeof (compose_status
));
4429 if (dpyinfo
->grabbed
&& last_mouse_frame
4430 && FRAME_LIVE_P (last_mouse_frame
))
4431 f
= last_mouse_frame
;
4433 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4437 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4438 construct_mouse_click (&emacs_event
, &event
, f
);
4442 struct scroll_bar
*bar
4443 = x_window_to_scroll_bar (event
.xbutton
.window
);
4446 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4449 if (event
.type
== ButtonPress
)
4451 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4452 last_mouse_frame
= f
;
4456 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4459 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4461 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4467 #ifdef USE_X_TOOLKIT
4468 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4469 /* For a down-event in the menu bar,
4470 don't pass it to Xt right now.
4471 Instead, save it away
4472 and we will pass it to Xt from kbd_buffer_get_event.
4473 That way, we can run some Lisp code first. */
4474 if (f
&& event
.type
== ButtonPress
4475 /* Verify the event is really within the menu bar
4476 and not just sent to it due to grabbing. */
4477 && event
.xbutton
.x
>= 0
4478 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4479 && event
.xbutton
.y
>= 0
4480 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4481 && event
.xbutton
.same_screen
)
4483 SET_SAVED_BUTTON_EVENT
;
4484 XSETFRAME (last_mouse_press_frame
, f
);
4486 else if (event
.type
== ButtonPress
)
4488 last_mouse_press_frame
= Qnil
;
4491 #ifdef USE_MOTIF /* This should do not harm for Lucid,
4492 but I am trying to be cautious. */
4493 else if (event
.type
== ButtonRelease
)
4495 if (!NILP (last_mouse_press_frame
))
4497 f
= XFRAME (last_mouse_press_frame
);
4498 if (f
->output_data
.x
)
4500 SET_SAVED_BUTTON_EVENT
;
4506 #endif /* USE_MOTIF */
4509 #endif /* USE_X_TOOLKIT */
4513 case CirculateNotify
:
4515 case CirculateRequest
:
4519 /* Someone has changed the keyboard mapping - update the
4521 switch (event
.xmapping
.request
)
4523 case MappingModifier
:
4524 x_find_modifier_meanings (dpyinfo
);
4525 /* This is meant to fall through. */
4526 case MappingKeyboard
:
4527 XRefreshKeyboardMapping (&event
.xmapping
);
4533 #ifdef USE_X_TOOLKIT
4535 XtDispatchEvent (&event
);
4537 #endif /* USE_X_TOOLKIT */
4543 /* On some systems, an X bug causes Emacs to get no more events
4544 when the window is destroyed. Detect that. (1994.) */
4547 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4548 One XNOOP in 100 loops will make Emacs terminate.
4549 B. Bretthauer, 1994 */
4551 if (x_noop_count
>= 100)
4555 if (next_noop_dpyinfo
== 0)
4556 next_noop_dpyinfo
= x_display_list
;
4558 XNoOp (next_noop_dpyinfo
->display
);
4560 /* Each time we get here, cycle through the displays now open. */
4561 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4565 /* If the focus was just given to an autoraising frame,
4567 /* ??? This ought to be able to handle more than one such frame. */
4568 if (pending_autoraise_frame
)
4570 x_raise_frame (pending_autoraise_frame
);
4571 pending_autoraise_frame
= 0;
4578 /* Drawing the cursor. */
4581 /* Draw a hollow box cursor on frame F at X, Y.
4582 Don't change the inside of the box. */
4585 x_draw_box (f
, x
, y
)
4589 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4590 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4591 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4592 int height
= f
->output_data
.x
->line_height
;
4593 int c
= FAST_GLYPH_CHAR (f
->phys_cursor_glyph
);
4594 int charset
= CHAR_CHARSET (c
);
4597 unsigned long mask
= GCForeground
;
4599 xgcv
.foreground
= f
->output_data
.x
->cursor_pixel
;
4601 /* cursor_gc's foreground color is typically the same as the normal
4602 background color, which can cause the cursor box to be invisible. */
4603 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
4604 XChangeGC (FRAME_X_DISPLAY (f
),
4605 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4608 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
4609 = XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), mask
, &xgcv
);
4611 /* If cursor is on a multi-column character, multiply WIDTH by columns. */
4612 width
*= (charset
== CHARSET_COMPOSITION
4613 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4614 : CHARSET_WIDTH (charset
));
4615 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4616 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
4617 left
, top
, width
- 1, height
- 1);
4620 /* Clear the cursor of frame F to background color,
4621 and mark the cursor as not shown.
4622 This is used when the text where the cursor is
4623 is about to be rewritten. */
4631 if (! FRAME_VISIBLE_P (f
)
4632 || ! f
->phys_cursor_on
)
4635 x_update_cursor (f
, 0);
4636 f
->phys_cursor_on
= 0;
4639 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4640 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4644 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4651 CHAR_TO_PIXEL_COL (f
, column
),
4652 CHAR_TO_PIXEL_ROW (f
, row
),
4653 &glyph
, 1, highlight
, 0, NULL
);
4657 x_display_bar_cursor (f
, on
, x
, y
)
4662 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4664 /* This is pointless on invisible frames, and dangerous on garbaged
4665 frames; in the latter case, the frame may be in the midst of
4666 changing its size, and x and y may be off the frame. */
4667 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4670 if (! on
&& ! f
->phys_cursor_on
)
4673 /* If there is anything wrong with the current cursor state, remove it. */
4674 if (f
->phys_cursor_on
4676 || f
->phys_cursor_x
!= x
4677 || f
->phys_cursor_y
!= y
4678 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4680 /* Erase the cursor by redrawing the character underneath it. */
4681 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4682 f
->phys_cursor_glyph
,
4683 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4684 f
->phys_cursor_on
= 0;
4687 /* If we now need a cursor in the new place or in the new form, do it so. */
4689 && (! f
->phys_cursor_on
4690 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4692 f
->phys_cursor_glyph
4693 = ((current_glyphs
->enable
[y
]
4694 && x
< current_glyphs
->used
[y
])
4695 ? current_glyphs
->glyphs
[y
][x
]
4697 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4698 f
->output_data
.x
->cursor_gc
,
4699 CHAR_TO_PIXEL_COL (f
, x
),
4700 CHAR_TO_PIXEL_ROW (f
, y
),
4701 max (f
->output_data
.x
->cursor_width
, 1),
4702 f
->output_data
.x
->line_height
);
4704 f
->phys_cursor_x
= x
;
4705 f
->phys_cursor_y
= y
;
4706 f
->phys_cursor_on
= 1;
4708 f
->output_data
.x
->current_cursor
= bar_cursor
;
4711 if (updating_frame
!= f
)
4712 XFlush (FRAME_X_DISPLAY (f
));
4716 /* Turn the displayed cursor of frame F on or off according to ON.
4717 If ON is nonzero, where to put the cursor is specified by X and Y. */
4720 x_display_box_cursor (f
, on
, x
, y
)
4725 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4727 /* This is pointless on invisible frames, and dangerous on garbaged
4728 frames; in the latter case, the frame may be in the midst of
4729 changing its size, and x and y may be off the frame. */
4730 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4733 /* If cursor is off and we want it off, return quickly. */
4734 if (!on
&& ! f
->phys_cursor_on
)
4737 /* If cursor is currently being shown and we don't want it to be
4738 or it is in the wrong place,
4739 or we want a hollow box and it's not so, (pout!)
4741 if (f
->phys_cursor_on
4743 || f
->phys_cursor_x
!= x
4744 || f
->phys_cursor_y
!= y
4745 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4746 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4748 int mouse_face_here
= 0;
4749 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4751 /* If the cursor is in the mouse face area, redisplay that when
4752 we clear the cursor. */
4753 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4755 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4756 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4757 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4759 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4760 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4761 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4762 /* Don't redraw the cursor's spot in mouse face
4763 if it is at the end of a line (on a newline).
4764 The cursor appears there, but mouse highlighting does not. */
4765 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4766 mouse_face_here
= 1;
4768 /* If the font is not as tall as a whole line,
4769 we must explicitly clear the line's whole height. */
4770 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4771 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4772 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4773 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4774 FONT_WIDTH (f
->output_data
.x
->font
),
4775 f
->output_data
.x
->line_height
, False
);
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
,
4781 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4782 f
->phys_cursor_on
= 0;
4785 /* If we want to show a cursor,
4786 or we want a box cursor and it's not so,
4787 write it in the right place. */
4789 && (! f
->phys_cursor_on
4790 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4791 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4793 f
->phys_cursor_glyph
4794 = ((current_glyphs
->enable
[y
]
4795 && x
< current_glyphs
->used
[y
])
4796 ? current_glyphs
->glyphs
[y
][x
]
4798 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4800 x_draw_box (f
, x
, y
);
4801 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4805 x_draw_single_glyph (f
, y
, x
,
4806 f
->phys_cursor_glyph
, 2);
4807 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4810 f
->phys_cursor_x
= x
;
4811 f
->phys_cursor_y
= y
;
4812 f
->phys_cursor_on
= 1;
4815 if (updating_frame
!= f
)
4816 XFlush (FRAME_X_DISPLAY (f
));
4819 /* Display the cursor on frame F, or clear it, according to ON.
4820 Also set the frame's cursor position to X and Y. */
4822 x_display_cursor (f
, on
, x
, y
)
4829 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4830 x_display_box_cursor (f
, on
, x
, y
);
4831 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4832 x_display_bar_cursor (f
, on
, x
, y
);
4834 /* Those are the only two we have implemented! */
4840 /* Display the cursor on frame F, or clear it, according to ON.
4841 Don't change the cursor's position. */
4843 x_update_cursor (f
, on
)
4849 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4850 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4851 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4852 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4854 /* Those are the only two we have implemented! */
4862 /* Refresh bitmap kitchen sink icon for frame F
4863 when we get an expose event for it. */
4868 /* Normally, the window manager handles this function. */
4871 /* Make the x-window of frame F use the gnu icon bitmap. */
4874 x_bitmap_icon (f
, file
)
4878 int mask
, bitmap_id
;
4881 if (FRAME_X_WINDOW (f
) == 0)
4884 /* Free up our existing icon bitmap if any. */
4885 if (f
->output_data
.x
->icon_bitmap
> 0)
4886 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4887 f
->output_data
.x
->icon_bitmap
= 0;
4890 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4893 /* Create the GNU bitmap if necessary. */
4894 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4895 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4896 = x_create_bitmap_from_data (f
, gnu_bits
,
4897 gnu_width
, gnu_height
);
4899 /* The first time we create the GNU bitmap,
4900 this increments the refcount one extra time.
4901 As a result, the GNU bitmap is never freed.
4902 That way, we don't have to worry about allocating it again. */
4903 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4905 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4908 x_wm_set_icon_pixmap (f
, bitmap_id
);
4909 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4915 /* Make the x-window of frame F use a rectangle with text.
4916 Use ICON_NAME as the text. */
4919 x_text_icon (f
, icon_name
)
4923 if (FRAME_X_WINDOW (f
) == 0)
4929 text
.value
= (unsigned char *) icon_name
;
4930 text
.encoding
= XA_STRING
;
4932 text
.nitems
= strlen (icon_name
);
4933 #ifdef USE_X_TOOLKIT
4934 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4936 #else /* not USE_X_TOOLKIT */
4937 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4938 #endif /* not USE_X_TOOLKIT */
4940 #else /* not HAVE_X11R4 */
4941 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4942 #endif /* not HAVE_X11R4 */
4944 if (f
->output_data
.x
->icon_bitmap
> 0)
4945 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4946 f
->output_data
.x
->icon_bitmap
= 0;
4947 x_wm_set_icon_pixmap (f
, 0);
4952 #define X_ERROR_MESSAGE_SIZE 200
4954 /* If non-nil, this should be a string.
4955 It means catch X errors and store the error message in this string. */
4957 static Lisp_Object x_error_message_string
;
4959 /* An X error handler which stores the error message in
4960 x_error_message_string. This is called from x_error_handler if
4961 x_catch_errors is in effect. */
4964 x_error_catcher (display
, error
)
4968 XGetErrorText (display
, error
->error_code
,
4969 XSTRING (x_error_message_string
)->data
,
4970 X_ERROR_MESSAGE_SIZE
);
4973 /* Begin trapping X errors for display DPY. Actually we trap X errors
4974 for all displays, but DPY should be the display you are actually
4977 After calling this function, X protocol errors no longer cause
4978 Emacs to exit; instead, they are recorded in the string
4979 stored in x_error_message_string.
4981 Calling x_check_errors signals an Emacs error if an X error has
4982 occurred since the last call to x_catch_errors or x_check_errors.
4984 Calling x_uncatch_errors resumes the normal error handling. */
4986 void x_check_errors ();
4987 static Lisp_Object
x_catch_errors_unwind ();
4990 x_catch_errors (dpy
)
4993 int count
= specpdl_ptr
- specpdl
;
4995 /* Make sure any errors from previous requests have been dealt with. */
4998 record_unwind_protect (x_catch_errors_unwind
, x_error_message_string
);
5000 x_error_message_string
= make_uninit_string (X_ERROR_MESSAGE_SIZE
);
5001 XSTRING (x_error_message_string
)->data
[0] = 0;
5006 /* Unbind the binding that we made to check for X errors. */
5009 x_catch_errors_unwind (old_val
)
5010 Lisp_Object old_val
;
5012 x_error_message_string
= old_val
;
5016 /* If any X protocol errors have arrived since the last call to
5017 x_catch_errors or x_check_errors, signal an Emacs error using
5018 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5021 x_check_errors (dpy
, format
)
5025 /* Make sure to catch any errors incurred so far. */
5028 if (XSTRING (x_error_message_string
)->data
[0])
5029 error (format
, XSTRING (x_error_message_string
)->data
);
5032 /* Nonzero if we had any X protocol errors
5033 since we did x_catch_errors on DPY. */
5036 x_had_errors_p (dpy
)
5039 /* Make sure to catch any errors incurred so far. */
5042 return XSTRING (x_error_message_string
)->data
[0] != 0;
5045 /* Forget about any errors we have had, since we did x_catch_errors on DPY. */
5048 x_clear_errors (dpy
)
5051 XSTRING (x_error_message_string
)->data
[0] = 0;
5054 /* Stop catching X protocol errors and let them make Emacs die.
5055 DPY should be the display that was passed to x_catch_errors.
5056 COUNT should be the value that was returned by
5057 the corresponding call to x_catch_errors. */
5060 x_uncatch_errors (dpy
, count
)
5064 unbind_to (count
, Qnil
);
5068 static unsigned int x_wire_count
;
5071 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5076 /* Handle SIGPIPE, which can happen when the connection to a server
5077 simply goes away. SIGPIPE is handled by x_connection_signal.
5078 Don't need to do anything, because the write which caused the
5079 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
5080 which will do the appropriate cleanup for us. */
5083 x_connection_signal (signalnum
) /* If we don't have an argument, */
5084 int signalnum
; /* some compilers complain in signal calls. */
5087 /* USG systems forget handlers when they are used;
5088 must reestablish each time */
5089 signal (signalnum
, x_connection_signal
);
5093 /* Handling X errors. */
5095 /* Handle the loss of connection to display DISPLAY. */
5098 x_connection_closed (display
, error_message
)
5100 char *error_message
;
5102 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
5103 Lisp_Object frame
, tail
;
5105 /* Indicate that this display is dead. */
5107 #ifdef USE_X_TOOLKIT
5108 XtCloseDisplay (display
);
5111 dpyinfo
->display
= 0;
5113 /* First delete frames whose minibuffers are on frames
5114 that are on the dead display. */
5115 FOR_EACH_FRAME (tail
, frame
)
5117 Lisp_Object minibuf_frame
;
5119 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
5120 if (FRAME_X_P (XFRAME (frame
))
5121 && FRAME_X_P (XFRAME (minibuf_frame
))
5122 && ! EQ (frame
, minibuf_frame
)
5123 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
5124 Fdelete_frame (frame
, Qt
);
5127 /* Now delete all remaining frames on the dead display.
5128 We are now sure none of these is used as the minibuffer
5129 for another frame that we need to delete. */
5130 FOR_EACH_FRAME (tail
, frame
)
5131 if (FRAME_X_P (XFRAME (frame
))
5132 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
5134 /* Set this to t so that Fdelete_frame won't get confused
5135 trying to find a replacement. */
5136 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
5137 Fdelete_frame (frame
, Qt
);
5141 x_delete_display (dpyinfo
);
5143 if (x_display_list
== 0)
5145 fprintf (stderr
, "%s\n", error_message
);
5146 shut_down_emacs (0, 0, Qnil
);
5150 /* Ordinary stack unwind doesn't deal with these. */
5152 sigunblock (sigmask (SIGIO
));
5154 sigunblock (sigmask (SIGALRM
));
5155 TOTALLY_UNBLOCK_INPUT
;
5157 clear_waiting_for_input ();
5158 error ("%s", error_message
);
5161 /* This is the usual handler for X protocol errors.
5162 It kills all frames on the display that we got the error for.
5163 If that was the only one, it prints an error message and kills Emacs. */
5166 x_error_quitter (display
, error
)
5170 char buf
[256], buf1
[356];
5172 /* Note that there is no real way portable across R3/R4 to get the
5173 original error handler. */
5175 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
5176 sprintf (buf1
, "X protocol error: %s on protocol request %d",
5177 buf
, error
->request_code
);
5178 x_connection_closed (display
, buf1
);
5181 /* This is the first-level handler for X protocol errors.
5182 It calls x_error_quitter or x_error_catcher. */
5185 x_error_handler (display
, error
)
5189 char buf
[256], buf1
[356];
5191 if (! NILP (x_error_message_string
))
5192 x_error_catcher (display
, error
);
5194 x_error_quitter (display
, error
);
5197 /* This is the handler for X IO errors, always.
5198 It kills all frames on the display that we lost touch with.
5199 If that was the only one, it prints an error message and kills Emacs. */
5202 x_io_error_quitter (display
)
5207 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
5208 x_connection_closed (display
, buf
);
5211 /* Changing the font of the frame. */
5213 /* Give frame F the font named FONTNAME as its default font, and
5214 return the full name of that font. FONTNAME may be a wildcard
5215 pattern; in that case, we choose some font that fits the pattern.
5216 The return value shows which font we chose. */
5219 x_new_font (f
, fontname
)
5221 register char *fontname
;
5223 struct font_info
*fontp
5224 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
5229 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
5230 f
->output_data
.x
->font_baseline
5231 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
5232 f
->output_data
.x
->fontset
= -1;
5234 /* Compute the scroll bar width in character columns. */
5235 if (f
->scroll_bar_pixel_width
> 0)
5237 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5238 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
5241 f
->scroll_bar_cols
= 2;
5243 /* Now make the frame display the given font. */
5244 if (FRAME_X_WINDOW (f
) != 0)
5246 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
5247 f
->output_data
.x
->font
->fid
);
5248 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
5249 f
->output_data
.x
->font
->fid
);
5250 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
5251 f
->output_data
.x
->font
->fid
);
5253 frame_update_line_height (f
);
5254 x_set_window_size (f
, 0, f
->width
, f
->height
);
5257 /* If we are setting a new frame's font for the first time,
5258 there are no faces yet, so this font's height is the line height. */
5259 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
5261 return build_string (fontp
->full_name
);
5264 /* Give frame F the fontset named FONTSETNAME as its default font, and
5265 return the full name of that fontset. FONTSETNAME may be a wildcard
5266 pattern; in that case, we choose some fontset that fits the pattern.
5267 The return value shows which fontset we chose. */
5270 x_new_fontset (f
, fontsetname
)
5274 int fontset
= fs_query_fontset (f
, fontsetname
);
5275 struct fontset_info
*fontsetp
;
5281 if (f
->output_data
.x
->fontset
== fontset
)
5282 /* This fontset is already set in frame F. There's nothing more
5284 return build_string (fontsetname
);
5286 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
5288 if (!fontsetp
->fontname
[CHARSET_ASCII
])
5289 /* This fontset doesn't contain ASCII font. */
5292 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
5294 if (!STRINGP (result
))
5295 /* Can't load ASCII font. */
5298 /* Since x_new_font doesn't update any fontset information, do it now. */
5299 f
->output_data
.x
->fontset
= fontset
;
5300 FS_LOAD_FONT (f
, FRAME_X_FONT_TABLE (f
),
5301 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
5303 return build_string (fontsetname
);
5306 /* Calculate the absolute position in frame F
5307 from its current recorded position values and gravity. */
5309 x_calc_absolute_position (f
)
5313 int win_x
= 0, win_y
= 0;
5314 int flags
= f
->output_data
.x
->size_hint_flags
;
5317 /* We have nothing to do if the current position
5318 is already for the top-left corner. */
5319 if (! ((flags
& XNegative
) || (flags
& YNegative
)))
5322 #ifdef USE_X_TOOLKIT
5323 this_window
= XtWindow (f
->output_data
.x
->widget
);
5325 this_window
= FRAME_X_WINDOW (f
);
5328 /* Find the position of the outside upper-left corner of
5329 the inner window, with respect to the outer window.
5330 But do this only if we will need the results. */
5331 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
5336 count
= x_catch_errors (FRAME_X_DISPLAY (f
));
5339 x_clear_errors (FRAME_X_DISPLAY (f
));
5340 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
5342 /* From-window, to-window. */
5344 f
->output_data
.x
->parent_desc
,
5346 /* From-position, to-position. */
5347 0, 0, &win_x
, &win_y
,
5351 if (x_had_errors_p (FRAME_X_DISPLAY (f
)))
5353 Window newroot
, newparent
= 0xdeadbeef;
5354 Window
*newchildren
;
5357 if (! XQueryTree (FRAME_X_DISPLAY (f
), this_window
, &newroot
,
5358 &newparent
, &newchildren
, &nchildren
))
5361 XFree (newchildren
);
5363 f
->output_data
.x
->parent_desc
= newparent
;
5369 x_uncatch_errors (FRAME_X_DISPLAY (f
), count
);
5373 /* Treat negative positions as relative to the leftmost bottommost
5374 position that fits on the screen. */
5375 if (flags
& XNegative
)
5376 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5377 - 2 * f
->output_data
.x
->border_width
- win_x
5379 + f
->output_data
.x
->left_pos
);
5381 if (flags
& YNegative
)
5382 /* We used to subtract f->output_data.x->menubar_height here
5383 in the toolkit case, but PIXEL_HEIGHT already includes that. */
5384 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5385 - 2 * f
->output_data
.x
->border_width
- win_y
5387 + f
->output_data
.x
->top_pos
);
5389 /* The left_pos and top_pos
5390 are now relative to the top and left screen edges,
5391 so the flags should correspond. */
5392 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5395 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5396 to really change the position, and 0 when calling from
5397 x_make_frame_visible (in that case, XOFF and YOFF are the current
5398 position values). It is -1 when calling from x_set_frame_parameters,
5399 which means, do adjust for borders but don't change the gravity. */
5401 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5403 register int xoff
, yoff
;
5406 int modified_top
, modified_left
;
5408 if (change_gravity
> 0)
5410 f
->output_data
.x
->top_pos
= yoff
;
5411 f
->output_data
.x
->left_pos
= xoff
;
5412 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5414 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5416 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5417 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5419 x_calc_absolute_position (f
);
5422 x_wm_set_size_hint (f
, (long) 0, 0);
5424 modified_left
= f
->output_data
.x
->left_pos
;
5425 modified_top
= f
->output_data
.x
->top_pos
;
5426 #if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
5427 this seems to be unnecessary and incorrect. rms, 4/17/97. */
5428 /* It is a mystery why we need to add the border_width here
5429 when the frame is already visible, but experiment says we do. */
5430 if (change_gravity
!= 0)
5432 modified_left
+= f
->output_data
.x
->border_width
;
5433 modified_top
+= f
->output_data
.x
->border_width
;
5437 #ifdef USE_X_TOOLKIT
5438 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5439 modified_left
, modified_top
);
5440 #else /* not USE_X_TOOLKIT */
5441 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5442 modified_left
, modified_top
);
5443 #endif /* not USE_X_TOOLKIT */
5447 /* Call this to change the size of frame F's x-window.
5448 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5449 for this size change and subsequent size changes.
5450 Otherwise we leave the window gravity unchanged. */
5452 x_set_window_size (f
, change_gravity
, cols
, rows
)
5457 int pixelwidth
, pixelheight
;
5459 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5463 #ifdef USE_X_TOOLKIT
5465 /* The x and y position of the widget is clobbered by the
5466 call to XtSetValues within EmacsFrameSetCharSize.
5467 This is a real kludge, but I don't understand Xt so I can't
5468 figure out a correct fix. Can anyone else tell me? -- rms. */
5469 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5470 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5471 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5472 f
->output_data
.x
->widget
->core
.x
= xpos
;
5473 f
->output_data
.x
->widget
->core
.y
= ypos
;
5476 #else /* not USE_X_TOOLKIT */
5478 check_frame_size (f
, &rows
, &cols
);
5479 f
->output_data
.x
->vertical_scroll_bar_extra
5480 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5482 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5483 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5484 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5485 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5486 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5488 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5489 x_wm_set_size_hint (f
, (long) 0, 0);
5491 XSync (FRAME_X_DISPLAY (f
), False
);
5492 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5493 pixelwidth
, pixelheight
);
5495 /* Now, strictly speaking, we can't be sure that this is accurate,
5496 but the window manager will get around to dealing with the size
5497 change request eventually, and we'll hear how it went when the
5498 ConfigureNotify event gets here.
5500 We could just not bother storing any of this information here,
5501 and let the ConfigureNotify event set everything up, but that
5502 might be kind of confusing to the lisp code, since size changes
5503 wouldn't be reported in the frame parameters until some random
5504 point in the future when the ConfigureNotify event arrives. */
5505 change_frame_size (f
, rows
, cols
, 0, 0);
5506 PIXEL_WIDTH (f
) = pixelwidth
;
5507 PIXEL_HEIGHT (f
) = pixelheight
;
5509 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5510 receive in the ConfigureNotify event; if we get what we asked
5511 for, then the event won't cause the screen to become garbaged, so
5512 we have to make sure to do it here. */
5513 SET_FRAME_GARBAGED (f
);
5515 XFlush (FRAME_X_DISPLAY (f
));
5517 #endif /* not USE_X_TOOLKIT */
5519 /* If cursor was outside the new size, mark it as off. */
5520 if (f
->phys_cursor_y
>= rows
5521 || f
->phys_cursor_x
>= cols
)
5523 f
->phys_cursor_x
= 0;
5524 f
->phys_cursor_y
= 0;
5525 f
->phys_cursor_on
= 0;
5528 /* Clear out any recollection of where the mouse highlighting was,
5529 since it might be in a place that's outside the new frame size.
5530 Actually checking whether it is outside is a pain in the neck,
5531 so don't try--just let the highlighting be done afresh with new size. */
5532 cancel_mouse_face (f
);
5537 /* Mouse warping. */
5540 x_set_mouse_position (f
, x
, y
)
5546 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5547 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5549 if (pix_x
< 0) pix_x
= 0;
5550 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5552 if (pix_y
< 0) pix_y
= 0;
5553 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5557 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5558 0, 0, 0, 0, pix_x
, pix_y
);
5562 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5565 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5571 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5572 0, 0, 0, 0, pix_x
, pix_y
);
5576 /* focus shifting, raising and lowering. */
5578 x_focus_on_frame (f
)
5581 #if 0 /* This proves to be unpleasant. */
5585 /* I don't think that the ICCCM allows programs to do things like this
5586 without the interaction of the window manager. Whatever you end up
5587 doing with this code, do it to x_unfocus_frame too. */
5588 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5589 RevertToPointerRoot
, CurrentTime
);
5597 /* Look at the remarks in x_focus_on_frame. */
5598 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5599 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5600 RevertToPointerRoot
, CurrentTime
);
5604 /* Raise frame F. */
5609 if (f
->async_visible
)
5612 #ifdef USE_X_TOOLKIT
5613 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5614 #else /* not USE_X_TOOLKIT */
5615 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5616 #endif /* not USE_X_TOOLKIT */
5617 XFlush (FRAME_X_DISPLAY (f
));
5622 /* Lower frame F. */
5627 if (f
->async_visible
)
5630 #ifdef USE_X_TOOLKIT
5631 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5632 #else /* not USE_X_TOOLKIT */
5633 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5634 #endif /* not USE_X_TOOLKIT */
5635 XFlush (FRAME_X_DISPLAY (f
));
5641 XTframe_raise_lower (f
, raise_flag
)
5651 /* Change of visibility. */
5653 /* This tries to wait until the frame is really visible.
5654 However, if the window manager asks the user where to position
5655 the frame, this will return before the user finishes doing that.
5656 The frame will not actually be visible at that time,
5657 but it will become visible later when the window manager
5658 finishes with it. */
5660 x_make_frame_visible (f
)
5665 int starting_flags
= f
->output_data
.x
->size_hint_flags
;
5666 int original_top
, original_left
;
5670 type
= x_icon_type (f
);
5672 x_bitmap_icon (f
, type
);
5674 if (! FRAME_VISIBLE_P (f
))
5676 /* We test FRAME_GARBAGED_P here to make sure we don't
5677 call x_set_offset a second time
5678 if we get to x_make_frame_visible a second time
5679 before the window gets really visible. */
5680 if (! FRAME_ICONIFIED_P (f
)
5681 && ! f
->output_data
.x
->asked_for_visible
)
5682 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5684 f
->output_data
.x
->asked_for_visible
= 1;
5686 if (! EQ (Vx_no_window_manager
, Qt
))
5687 x_wm_set_window_state (f
, NormalState
);
5688 #ifdef USE_X_TOOLKIT
5689 /* This was XtPopup, but that did nothing for an iconified frame. */
5690 XtMapWidget (f
->output_data
.x
->widget
);
5691 #else /* not USE_X_TOOLKIT */
5692 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5693 #endif /* not USE_X_TOOLKIT */
5694 #if 0 /* This seems to bring back scroll bars in the wrong places
5695 if the window configuration has changed. They seem
5696 to come back ok without this. */
5697 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5698 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5702 XFlush (FRAME_X_DISPLAY (f
));
5704 /* Synchronize to ensure Emacs knows the frame is visible
5705 before we do anything else. We do this loop with input not blocked
5706 so that incoming events are handled. */
5709 int count
= input_signal_count
;
5710 /* This must be before UNBLOCK_INPUT
5711 since events that arrive in response to the actions above
5712 will set it when they are handled. */
5713 int previously_visible
= f
->output_data
.x
->has_been_visible
;
5715 original_left
= f
->output_data
.x
->left_pos
;
5716 original_top
= f
->output_data
.x
->top_pos
;
5718 /* This must come after we set COUNT. */
5721 /* Arriving X events are processed here. */
5723 /* Now move the window back to where it was "supposed to be".
5724 But don't do it if the gravity is negative.
5725 When the gravity is negative, this uses a position
5726 that is 3 pixels too low. Perhaps that's really the border width.
5728 Don't do this if the window has never been visible before,
5729 because the window manager may choose the position
5730 and we don't want to override it. */
5732 if (! FRAME_VISIBLE_P (f
) && ! FRAME_ICONIFIED_P (f
)
5733 && f
->output_data
.x
->win_gravity
== NorthWestGravity
5734 && previously_visible
)
5738 #ifdef USE_X_TOOLKIT
5739 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5740 original_left
, original_top
);
5741 #else /* not USE_X_TOOLKIT */
5742 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5743 original_left
, original_top
);
5744 #endif /* not USE_X_TOOLKIT */
5748 XSETFRAME (frame
, f
);
5753 /* Once we have handled input events,
5754 we should have received the MapNotify if one is coming.
5755 So if we have not got it yet, stop looping.
5756 Some window managers make their own decisions
5757 about visibility. */
5758 if (input_signal_count
!= count
)
5760 /* Machines that do polling rather than SIGIO have been observed
5761 to go into a busy-wait here. So we'll fake an alarm signal
5762 to let the handler know that there's something to be read.
5763 We used to raise a real alarm, but it seems that the handler
5764 isn't always enabled here. This is probably a bug. */
5765 if (input_polling_used ())
5767 /* It could be confusing if a real alarm arrives while processing
5768 the fake one. Turn it off and let the handler reset it. */
5770 input_poll_signal ();
5772 /* Once we have handled input events,
5773 we should have received the MapNotify if one is coming.
5774 So if we have not got it yet, stop looping.
5775 Some window managers make their own decisions
5776 about visibility. */
5777 if (input_signal_count
!= count
)
5780 FRAME_SAMPLE_VISIBILITY (f
);
5784 /* Change from mapped state to withdrawn state. */
5786 /* Make the frame visible (mapped and not iconified). */
5788 x_make_frame_invisible (f
)
5794 #ifdef USE_X_TOOLKIT
5795 /* Use the frame's outermost window, not the one we normally draw on. */
5796 window
= XtWindow (f
->output_data
.x
->widget
);
5797 #else /* not USE_X_TOOLKIT */
5798 window
= FRAME_X_WINDOW (f
);
5799 #endif /* not USE_X_TOOLKIT */
5801 /* Don't keep the highlight on an invisible frame. */
5802 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5803 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5805 #if 0/* This might add unreliability; I don't trust it -- rms. */
5806 if (! f
->async_visible
&& ! f
->async_iconified
)
5812 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5813 that the current position of the window is user-specified, rather than
5814 program-specified, so that when the window is mapped again, it will be
5815 placed at the same location, without forcing the user to position it
5816 by hand again (they have already done that once for this window.) */
5817 x_wm_set_size_hint (f
, (long) 0, 1);
5821 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5822 DefaultScreen (FRAME_X_DISPLAY (f
))))
5824 UNBLOCK_INPUT_RESIGNAL
;
5825 error ("Can't notify window manager of window withdrawal");
5827 #else /* ! defined (HAVE_X11R4) */
5829 /* Tell the window manager what we're going to do. */
5830 if (! EQ (Vx_no_window_manager
, Qt
))
5834 unmap
.xunmap
.type
= UnmapNotify
;
5835 unmap
.xunmap
.window
= window
;
5836 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5837 unmap
.xunmap
.from_configure
= False
;
5838 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5839 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5841 SubstructureRedirectMask
|SubstructureNotifyMask
,
5844 UNBLOCK_INPUT_RESIGNAL
;
5845 error ("Can't notify window manager of withdrawal");
5849 /* Unmap the window ourselves. Cheeky! */
5850 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5851 #endif /* ! defined (HAVE_X11R4) */
5853 /* We can't distinguish this from iconification
5854 just by the event that we get from the server.
5855 So we can't win using the usual strategy of letting
5856 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5857 and synchronize with the server to make sure we agree. */
5859 FRAME_ICONIFIED_P (f
) = 0;
5860 f
->async_visible
= 0;
5861 f
->async_iconified
= 0;
5868 /* Change window state from mapped to iconified. */
5877 /* Don't keep the highlight on an invisible frame. */
5878 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5879 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5881 if (f
->async_iconified
)
5886 FRAME_SAMPLE_VISIBILITY (f
);
5888 type
= x_icon_type (f
);
5890 x_bitmap_icon (f
, type
);
5892 #ifdef USE_X_TOOLKIT
5894 if (! FRAME_VISIBLE_P (f
))
5896 if (! EQ (Vx_no_window_manager
, Qt
))
5897 x_wm_set_window_state (f
, IconicState
);
5898 /* This was XtPopup, but that did nothing for an iconified frame. */
5899 XtMapWidget (f
->output_data
.x
->widget
);
5900 /* The server won't give us any event to indicate
5901 that an invisible frame was changed to an icon,
5902 so we have to record it here. */
5905 f
->async_iconified
= 1;
5906 f
->async_visible
= 0;
5911 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5912 XtWindow (f
->output_data
.x
->widget
),
5913 DefaultScreen (FRAME_X_DISPLAY (f
)));
5917 error ("Can't notify window manager of iconification");
5919 f
->async_iconified
= 1;
5920 f
->async_visible
= 0;
5924 XFlush (FRAME_X_DISPLAY (f
));
5926 #else /* not USE_X_TOOLKIT */
5928 /* Make sure the X server knows where the window should be positioned,
5929 in case the user deiconifies with the window manager. */
5930 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5931 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5933 /* Since we don't know which revision of X we're running, we'll use both
5934 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5936 /* X11R4: send a ClientMessage to the window manager using the
5937 WM_CHANGE_STATE type. */
5941 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5942 message
.xclient
.type
= ClientMessage
;
5943 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5944 message
.xclient
.format
= 32;
5945 message
.xclient
.data
.l
[0] = IconicState
;
5947 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5948 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5950 SubstructureRedirectMask
| SubstructureNotifyMask
,
5953 UNBLOCK_INPUT_RESIGNAL
;
5954 error ("Can't notify window manager of iconification");
5958 /* X11R3: set the initial_state field of the window manager hints to
5960 x_wm_set_window_state (f
, IconicState
);
5962 if (!FRAME_VISIBLE_P (f
))
5964 /* If the frame was withdrawn, before, we must map it. */
5965 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5968 f
->async_iconified
= 1;
5969 f
->async_visible
= 0;
5971 XFlush (FRAME_X_DISPLAY (f
));
5973 #endif /* not USE_X_TOOLKIT */
5976 /* Destroy the X window of frame F. */
5978 x_destroy_window (f
)
5981 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5985 /* If a display connection is dead, don't try sending more
5986 commands to the X server. */
5987 if (dpyinfo
->display
!= 0)
5989 if (f
->output_data
.x
->icon_desc
!= 0)
5990 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5994 XDestroyIC (FRAME_XIC (f
));
5995 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
5996 /* This line causes crashes on Solaris with Openwin,
5997 due to an apparent bug in XCloseIM.
5998 X11R6 seems not to have the bug. */
5999 XCloseIM (FRAME_XIM (f
));
6003 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
6004 #ifdef USE_X_TOOLKIT
6005 XtDestroyWidget (f
->output_data
.x
->widget
);
6006 free_frame_menubar (f
);
6007 #endif /* USE_X_TOOLKIT */
6009 free_frame_faces (f
);
6010 XFlush (FRAME_X_DISPLAY (f
));
6013 if (f
->output_data
.x
->saved_menu_event
)
6014 free (f
->output_data
.x
->saved_menu_event
);
6016 xfree (f
->output_data
.x
);
6017 f
->output_data
.x
= 0;
6018 if (f
== dpyinfo
->x_focus_frame
)
6019 dpyinfo
->x_focus_frame
= 0;
6020 if (f
== dpyinfo
->x_focus_event_frame
)
6021 dpyinfo
->x_focus_event_frame
= 0;
6022 if (f
== dpyinfo
->x_highlight_frame
)
6023 dpyinfo
->x_highlight_frame
= 0;
6025 dpyinfo
->reference_count
--;
6027 if (f
== dpyinfo
->mouse_face_mouse_frame
)
6029 dpyinfo
->mouse_face_beg_row
6030 = dpyinfo
->mouse_face_beg_col
= -1;
6031 dpyinfo
->mouse_face_end_row
6032 = dpyinfo
->mouse_face_end_col
= -1;
6033 dpyinfo
->mouse_face_window
= Qnil
;
6039 /* Setting window manager hints. */
6041 /* Set the normal size hints for the window manager, for frame F.
6042 FLAGS is the flags word to use--or 0 meaning preserve the flags
6043 that the window now has.
6044 If USER_POSITION is nonzero, we set the USPosition
6045 flag (this is useful when FLAGS is 0). */
6047 x_wm_set_size_hint (f
, flags
, user_position
)
6052 XSizeHints size_hints
;
6054 #ifdef USE_X_TOOLKIT
6057 Dimension widget_width
, widget_height
;
6058 Window window
= XtWindow (f
->output_data
.x
->widget
);
6059 #else /* not USE_X_TOOLKIT */
6060 Window window
= FRAME_X_WINDOW (f
);
6061 #endif /* not USE_X_TOOLKIT */
6063 /* Setting PMaxSize caused various problems. */
6064 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
6066 flexlines
= f
->height
;
6068 size_hints
.x
= f
->output_data
.x
->left_pos
;
6069 size_hints
.y
= f
->output_data
.x
->top_pos
;
6071 #ifdef USE_X_TOOLKIT
6072 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
6073 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
6074 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
6075 size_hints
.height
= widget_height
;
6076 size_hints
.width
= widget_width
;
6077 #else /* not USE_X_TOOLKIT */
6078 size_hints
.height
= PIXEL_HEIGHT (f
);
6079 size_hints
.width
= PIXEL_WIDTH (f
);
6080 #endif /* not USE_X_TOOLKIT */
6082 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
6083 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
6084 size_hints
.max_width
6085 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
6086 size_hints
.max_height
6087 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
6089 /* Calculate the base and minimum sizes.
6091 (When we use the X toolkit, we don't do it here.
6092 Instead we copy the values that the widgets are using, below.) */
6093 #ifndef USE_X_TOOLKIT
6095 int base_width
, base_height
;
6096 int min_rows
= 0, min_cols
= 0;
6098 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
6099 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
6101 check_frame_size (f
, &min_rows
, &min_cols
);
6103 /* The window manager uses the base width hints to calculate the
6104 current number of rows and columns in the frame while
6105 resizing; min_width and min_height aren't useful for this
6106 purpose, since they might not give the dimensions for a
6107 zero-row, zero-column frame.
6109 We use the base_width and base_height members if we have
6110 them; otherwise, we set the min_width and min_height members
6111 to the size for a zero x zero frame. */
6114 size_hints
.flags
|= PBaseSize
;
6115 size_hints
.base_width
= base_width
;
6116 size_hints
.base_height
= base_height
;
6117 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
6118 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
6120 size_hints
.min_width
= base_width
;
6121 size_hints
.min_height
= base_height
;
6125 /* If we don't need the old flags, we don't need the old hint at all. */
6128 size_hints
.flags
|= flags
;
6131 #endif /* not USE_X_TOOLKIT */
6134 XSizeHints hints
; /* Sometimes I hate X Windows... */
6135 long supplied_return
;
6139 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
6142 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
6145 #ifdef USE_X_TOOLKIT
6146 size_hints
.base_height
= hints
.base_height
;
6147 size_hints
.base_width
= hints
.base_width
;
6148 size_hints
.min_height
= hints
.min_height
;
6149 size_hints
.min_width
= hints
.min_width
;
6153 size_hints
.flags
|= flags
;
6158 if (hints
.flags
& PSize
)
6159 size_hints
.flags
|= PSize
;
6160 if (hints
.flags
& PPosition
)
6161 size_hints
.flags
|= PPosition
;
6162 if (hints
.flags
& USPosition
)
6163 size_hints
.flags
|= USPosition
;
6164 if (hints
.flags
& USSize
)
6165 size_hints
.flags
|= USSize
;
6172 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
6173 size_hints
.flags
|= PWinGravity
;
6177 size_hints
.flags
&= ~ PPosition
;
6178 size_hints
.flags
|= USPosition
;
6180 #endif /* PWinGravity */
6183 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6185 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6189 /* Used for IconicState or NormalState */
6190 x_wm_set_window_state (f
, state
)
6194 #ifdef USE_X_TOOLKIT
6197 XtSetArg (al
[0], XtNinitialState
, state
);
6198 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6199 #else /* not USE_X_TOOLKIT */
6200 Window window
= FRAME_X_WINDOW (f
);
6202 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6203 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6205 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6206 #endif /* not USE_X_TOOLKIT */
6209 x_wm_set_icon_pixmap (f
, pixmap_id
)
6215 #ifdef USE_X_TOOLKIT
6216 Window window
= XtWindow (f
->output_data
.x
->widget
);
6218 Window window
= FRAME_X_WINDOW (f
);
6223 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6224 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6228 /* It seems there is no way to turn off use of an icon pixmap.
6229 The following line does it, only if no icon has yet been created,
6230 for some window managers. But with mwm it crashes.
6231 Some people say it should clear the IconPixmapHint bit in this case,
6232 but that doesn't work, and the X consortium said it isn't the
6233 right thing at all. Since there is no way to win,
6234 best to explicitly give up. */
6236 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6242 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6246 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6247 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6250 #else /* not USE_X_TOOLKIT */
6252 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6253 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6255 #endif /* not USE_X_TOOLKIT */
6258 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6262 #ifdef USE_X_TOOLKIT
6263 Window window
= XtWindow (f
->output_data
.x
->widget
);
6265 Window window
= FRAME_X_WINDOW (f
);
6268 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6269 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6270 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6272 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6276 /* Interface to fontset handler. */
6278 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6280 x_get_font_info (f
, font_idx
)
6284 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
6288 /* Return a list of names of available fonts matching PATTERN on frame
6289 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6290 to be listed. Frame F NULL means we have not yet created any
6291 frame on X, and consult the first display in x_display_list.
6292 MAXNAMES sets a limit on how many fonts to match. */
6295 x_list_fonts (f
, pattern
, size
, maxnames
)
6297 Lisp_Object pattern
;
6301 Lisp_Object list
= Qnil
, patterns
, newlist
= Qnil
, key
, tem
, second_best
;
6302 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
6304 patterns
= Fassoc (pattern
, Valternative_fontname_alist
);
6305 if (NILP (patterns
))
6306 patterns
= Fcons (pattern
, Qnil
);
6308 for (; CONSP (patterns
); patterns
= XCONS (patterns
)->cdr
)
6313 pattern
= XCONS (patterns
)->car
;
6314 /* See if we cached the result for this particular query. */
6315 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
6316 key
= Fcons (pattern
, make_number (maxnames
)),
6317 !NILP (list
= Fassoc (key
, tem
))))
6319 list
= Fcdr_safe (list
);
6320 /* We have a cashed list. Don't have to get the list again. */
6324 /* At first, put PATTERN in the cache. */
6326 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, maxnames
, &num_fonts
);
6333 /* Make a list of all the fonts we got back.
6334 Store that in the font cache for the display. */
6335 for (i
= 0; i
< num_fonts
; i
++)
6338 int average_width
= -1, dashes
= 0, width
= 0;
6340 /* Count the number of dashes in NAMES[I]. If there are
6341 14 dashes, and the field value following 12th dash
6342 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
6343 is usually too ugly to be used for editing. Let's
6349 if (dashes
== 7) /* PIXEL_SIZE field */
6351 else if (dashes
== 12) /* AVERAGE_WIDTH field */
6352 average_width
= atoi (p
);
6354 if (dashes
< 14 || average_width
!= 0)
6356 tem
= build_string (names
[i
]);
6357 if (NILP (Fassoc (tem
, list
)))
6359 if (STRINGP (Vx_pixel_size_width_font_regexp
)
6360 && ((fast_c_string_match_ignore_case
6361 (Vx_pixel_size_width_font_regexp
, names
[i
]))
6363 /* We can set the value of PIXEL_SIZE to the
6364 width of this font. */
6365 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
6367 /* For the moment, width is not known. */
6368 list
= Fcons (Fcons (tem
, Qnil
), list
);
6372 XFreeFontNames (names
);
6375 /* Now store the result in the cache. */
6377 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
6378 = Fcons (Fcons (key
, list
),
6379 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6382 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6384 newlist
= second_best
= Qnil
;
6385 /* Make a list of the fonts that have the right width. */
6386 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
6388 tem
= XCONS (list
)->car
;
6390 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
6394 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6398 if (!INTEGERP (XCONS (tem
)->cdr
))
6400 /* Since we have not yet known the size of this font, we
6401 must try slow function call XLoadQueryFont. */
6402 XFontStruct
*thisinfo
;
6405 thisinfo
= XLoadQueryFont (dpy
,
6406 XSTRING (XCONS (tem
)->car
)->data
);
6411 XCONS (tem
)->cdr
= make_number (thisinfo
->max_bounds
.width
);
6412 XFreeFont (dpy
, thisinfo
);
6415 /* For unknown reason, the previous call of XListFont had
6416 retruned a font which can't be opened. Record the size
6417 as 0 not to try to open it again. */
6418 XCONS (tem
)->cdr
= make_number (0);
6420 if (XINT (XCONS (tem
)->cdr
) == size
)
6421 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6422 else if (NILP (second_best
))
6424 else if (XINT (XCONS (tem
)->cdr
) < size
)
6426 if (XINT (XCONS (second_best
)->cdr
) > size
6427 || XINT (XCONS (second_best
)->cdr
) < XINT (XCONS (tem
)->cdr
))
6432 if (XINT (XCONS (second_best
)->cdr
) > size
6433 && XINT (XCONS (second_best
)->cdr
) > XINT (XCONS (tem
)->cdr
))
6437 if (!NILP (newlist
))
6439 else if (!NILP (second_best
))
6441 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6449 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6450 pointer to the structure font_info while allocating it dynamically.
6451 If SIZE is 0, load any size of font.
6452 If loading is failed, return NULL. */
6455 x_load_font (f
, fontname
, size
)
6457 register char *fontname
;
6460 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6461 Lisp_Object font_names
;
6463 /* Get a list of all the fonts that match this name. Once we
6464 have a list of matching fonts, we compare them against the fonts
6465 we already have by comparing names. */
6466 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 256);
6468 if (!NILP (font_names
))
6473 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6474 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
6475 if (!strcmp (dpyinfo
->font_table
[i
].name
,
6476 XSTRING (XCONS (tail
)->car
)->data
)
6477 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6478 XSTRING (XCONS (tail
)->car
)->data
))
6479 return (dpyinfo
->font_table
+ i
);
6482 /* Load the font and add it to the table. */
6486 struct font_info
*fontp
;
6487 unsigned long value
;
6489 /* If we have found fonts by x_list_font, load one of them. If
6490 not, we still try to load a font by the name given as FONTNAME
6491 because XListFonts (called in x_list_font) of some X server has
6492 a bug of not finding a font even if the font surely exists and
6493 is loadable by XLoadQueryFont. */
6494 if (!NILP (font_names
))
6495 fontname
= (char *) XSTRING (XCONS (font_names
)->car
)->data
;
6498 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
6503 /* Do we need to create the table? */
6504 if (dpyinfo
->font_table_size
== 0)
6506 dpyinfo
->font_table_size
= 16;
6508 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
6509 * sizeof (struct font_info
));
6511 /* Do we need to grow the table? */
6512 else if (dpyinfo
->n_fonts
6513 >= dpyinfo
->font_table_size
)
6515 dpyinfo
->font_table_size
*= 2;
6517 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
6518 (dpyinfo
->font_table_size
6519 * sizeof (struct font_info
)));
6522 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
6524 /* Now fill in the slots of *FONTP. */
6527 fontp
->font_idx
= dpyinfo
->n_fonts
;
6528 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
6529 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
6531 /* Try to get the full name of FONT. Put it in FULL_NAME. */
6533 if (XGetFontProperty (font
, XA_FONT
, &value
))
6535 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
6539 /* Count the number of dashes in the "full name".
6540 If it is too few, this isn't really the font's full name,
6542 In X11R4, the fonts did not come with their canonical names
6553 full_name
= (char *) xmalloc (p
- name
+ 1);
6554 bcopy (name
, full_name
, p
- name
+ 1);
6561 fontp
->full_name
= full_name
;
6563 fontp
->full_name
= fontp
->name
;
6565 fontp
->size
= font
->max_bounds
.width
;
6566 fontp
->height
= font
->max_bounds
.ascent
+ font
->max_bounds
.descent
;
6568 if (NILP (font_names
))
6570 /* We come here because of a bug of XListFonts mentioned at
6571 the head of this block. Let's store this information in
6572 the cache for x_list_fonts. */
6573 Lisp_Object lispy_name
= build_string (fontname
);
6574 Lisp_Object lispy_full_name
= build_string (fontp
->full_name
);
6576 XCONS (dpyinfo
->name_list_element
)->cdr
6577 = Fcons (Fcons (Fcons (lispy_name
, make_number (256)),
6578 Fcons (Fcons (lispy_full_name
,
6579 make_number (fontp
->size
)),
6581 XCONS (dpyinfo
->name_list_element
)->cdr
);
6583 XCONS (dpyinfo
->name_list_element
)->cdr
6584 = Fcons (Fcons (Fcons (lispy_full_name
, make_number (256)),
6585 Fcons (Fcons (lispy_full_name
,
6586 make_number (fontp
->size
)),
6588 XCONS (dpyinfo
->name_list_element
)->cdr
);
6591 /* The slot `encoding' specifies how to map a character
6592 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6593 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
6594 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
6595 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
6596 2:0xA020..0xFF7F). For the moment, we don't know which charset
6597 uses this font. So, we set informatoin in fontp->encoding[1]
6598 which is never used by any charset. If mapping can't be
6599 decided, set FONT_ENCODING_NOT_DECIDED. */
6601 = (font
->max_byte1
== 0
6603 ? (font
->min_char_or_byte2
< 0x80
6604 ? (font
->max_char_or_byte2
< 0x80
6605 ? 0 /* 0x20..0x7F */
6606 : FONT_ENCODING_NOT_DECIDED
) /* 0x20..0xFF */
6607 : 1) /* 0xA0..0xFF */
6609 : (font
->min_byte1
< 0x80
6610 ? (font
->max_byte1
< 0x80
6611 ? (font
->min_char_or_byte2
< 0x80
6612 ? (font
->max_char_or_byte2
< 0x80
6613 ? 0 /* 0x2020..0x7F7F */
6614 : FONT_ENCODING_NOT_DECIDED
) /* 0x2020..0x7FFF */
6615 : 3) /* 0x20A0..0x7FFF */
6616 : FONT_ENCODING_NOT_DECIDED
) /* 0x20??..0xA0?? */
6617 : (font
->min_char_or_byte2
< 0x80
6618 ? (font
->max_char_or_byte2
< 0x80
6619 ? 2 /* 0xA020..0xFF7F */
6620 : FONT_ENCODING_NOT_DECIDED
) /* 0xA020..0xFFFF */
6621 : 1))); /* 0xA0A0..0xFFFF */
6623 fontp
->baseline_offset
6624 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6625 ? (long) value
: 0);
6626 fontp
->relative_compose
6627 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6628 ? (long) value
: 0);
6629 fontp
->default_ascent
6630 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6631 ? (long) value
: 0);
6640 /* Return a pointer to struct font_info of a font named FONTNAME for frame F.
6641 If no such font is loaded, return NULL. */
6643 x_query_font (f
, fontname
)
6645 register char *fontname
;
6647 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6650 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6651 if (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6652 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
))
6653 return (dpyinfo
->font_table
+ i
);
6658 /* Initialization. */
6660 #ifdef USE_X_TOOLKIT
6661 static XrmOptionDescRec emacs_options
[] = {
6662 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6663 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6665 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6666 XrmoptionSepArg
, NULL
},
6667 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6669 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6670 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6671 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6672 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6673 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6674 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6675 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6677 #endif /* USE_X_TOOLKIT */
6679 static int x_initialized
;
6682 /* Test whether two display-name strings agree up to the dot that separates
6683 the screen number from the server number. */
6685 same_x_server (name1
, name2
)
6686 char *name1
, *name2
;
6689 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
6693 if (seen_colon
&& *name1
== '.')
6697 && (*name1
== '.' || *name1
== '\0')
6698 && (*name2
== '.' || *name2
== '\0'));
6702 struct x_display_info
*
6703 x_term_init (display_name
, xrm_option
, resource_name
)
6704 Lisp_Object display_name
;
6706 char *resource_name
;
6712 struct x_display_info
*dpyinfo
;
6724 setlocale (LC_ALL
, "");
6725 /* In case we just overrode what init_lread did, redo it. */
6726 setlocale (LC_NUMERIC
, "C");
6727 setlocale (LC_TIME
, "C");
6730 #ifdef USE_X_TOOLKIT
6731 /* weiner@footloose.sps.mot.com reports that this causes
6733 X protocol error: BadAtom (invalid Atom parameter)
6734 on protocol request 18skiloaf.
6735 So let's not use it until R6. */
6737 XtSetLanguageProc (NULL
, NULL
, NULL
);
6748 argv
[argc
++] = "-xrm";
6749 argv
[argc
++] = xrm_option
;
6751 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
6752 resource_name
, EMACS_CLASS
,
6753 emacs_options
, XtNumber (emacs_options
),
6757 /* I think this is to compensate for XtSetLanguageProc. */
6758 setlocale (LC_NUMERIC
, "C");
6759 setlocale (LC_TIME
, "C");
6763 #else /* not USE_X_TOOLKIT */
6765 XSetLocaleModifiers ("");
6767 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
6768 #endif /* not USE_X_TOOLKIT */
6770 /* Detect failure. */
6777 /* We have definitely succeeded. Record the new connection. */
6779 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
6783 struct x_display_info
*share
;
6786 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
6787 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
6788 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
6789 XSTRING (display_name
)->data
))
6792 dpyinfo
->kboard
= share
->kboard
;
6795 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
6796 init_kboard (dpyinfo
->kboard
);
6797 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
6799 char *vendor
= ServerVendor (dpy
);
6800 dpyinfo
->kboard
->Vsystem_key_alist
6801 = call1 (Qvendor_specific_keysyms
,
6802 build_string (vendor
? vendor
: ""));
6805 dpyinfo
->kboard
->next_kboard
= all_kboards
;
6806 all_kboards
= dpyinfo
->kboard
;
6807 /* Don't let the initial kboard remain current longer than necessary.
6808 That would cause problems if a file loaded on startup tries to
6809 prompt in the minibuffer. */
6810 if (current_kboard
== initial_kboard
)
6811 current_kboard
= dpyinfo
->kboard
;
6813 dpyinfo
->kboard
->reference_count
++;
6817 /* Put this display on the chain. */
6818 dpyinfo
->next
= x_display_list
;
6819 x_display_list
= dpyinfo
;
6821 /* Put it on x_display_name_list as well, to keep them parallel. */
6822 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6823 x_display_name_list
);
6824 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
6826 dpyinfo
->display
= dpy
;
6829 XSetAfterFunction (x_current_display
, x_trace_wire
);
6833 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6834 + XSTRING (Vsystem_name
)->size
6836 sprintf (dpyinfo
->x_id_name
, "%s@%s",
6837 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6839 /* Figure out which modifier bits mean what. */
6840 x_find_modifier_meanings (dpyinfo
);
6842 /* Get the scroll bar cursor. */
6843 dpyinfo
->vertical_scroll_bar_cursor
6844 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
6846 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
6847 resource_name
, EMACS_CLASS
);
6848 #ifdef HAVE_XRMSETDATABASE
6849 XrmSetDatabase (dpyinfo
->display
, xrdb
);
6851 dpyinfo
->display
->db
= xrdb
;
6853 /* Put the rdb where we can find it in a way that works on
6855 dpyinfo
->xrdb
= xrdb
;
6857 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
6858 DefaultScreen (dpyinfo
->display
));
6859 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
6860 &dpyinfo
->n_planes
);
6861 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6862 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6863 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6864 dpyinfo
->grabbed
= 0;
6865 dpyinfo
->reference_count
= 0;
6866 dpyinfo
->icon_bitmap_id
= -1;
6867 dpyinfo
->n_fonts
= 0;
6868 dpyinfo
->font_table_size
= 0;
6869 dpyinfo
->bitmaps
= 0;
6870 dpyinfo
->bitmaps_size
= 0;
6871 dpyinfo
->bitmaps_last
= 0;
6872 dpyinfo
->scratch_cursor_gc
= 0;
6873 dpyinfo
->mouse_face_mouse_frame
= 0;
6874 dpyinfo
->mouse_face_deferred_gc
= 0;
6875 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6876 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6877 dpyinfo
->mouse_face_face_id
= 0;
6878 dpyinfo
->mouse_face_window
= Qnil
;
6879 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6880 dpyinfo
->mouse_face_defer
= 0;
6881 dpyinfo
->x_focus_frame
= 0;
6882 dpyinfo
->x_focus_event_frame
= 0;
6883 dpyinfo
->x_highlight_frame
= 0;
6885 dpyinfo
->Xatom_wm_protocols
6886 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6887 dpyinfo
->Xatom_wm_take_focus
6888 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6889 dpyinfo
->Xatom_wm_save_yourself
6890 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6891 dpyinfo
->Xatom_wm_delete_window
6892 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6893 dpyinfo
->Xatom_wm_change_state
6894 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6895 dpyinfo
->Xatom_wm_configure_denied
6896 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6897 dpyinfo
->Xatom_wm_window_moved
6898 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6899 dpyinfo
->Xatom_editres
6900 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6901 dpyinfo
->Xatom_CLIPBOARD
6902 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6903 dpyinfo
->Xatom_TIMESTAMP
6904 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6906 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6907 dpyinfo
->Xatom_COMPOUND_TEXT
6908 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
6909 dpyinfo
->Xatom_DELETE
6910 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6911 dpyinfo
->Xatom_MULTIPLE
6912 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6914 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6915 dpyinfo
->Xatom_EMACS_TMP
6916 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6917 dpyinfo
->Xatom_TARGETS
6918 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6920 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6921 dpyinfo
->Xatom_ATOM_PAIR
6922 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6923 /* For properties of font. */
6924 dpyinfo
->Xatom_PIXEL_SIZE
6925 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
6926 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
6927 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
6928 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
6929 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
6930 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
6931 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
6933 dpyinfo
->cut_buffers_initialized
= 0;
6935 connection
= ConnectionNumber (dpyinfo
->display
);
6936 dpyinfo
->connection
= connection
;
6941 null_bits
[0] = 0x00;
6944 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
6945 null_bits
, 1, 1, (long) 0, (long) 0,
6950 /* This is only needed for distinguishing keyboard and process input. */
6951 if (connection
!= 0)
6952 add_keyboard_wait_descriptor (connection
);
6955 #ifndef F_SETOWN_BUG
6957 #ifdef F_SETOWN_SOCK_NEG
6958 /* stdin is a socket here */
6959 fcntl (connection
, F_SETOWN
, -getpid ());
6960 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6961 fcntl (connection
, F_SETOWN
, getpid ());
6962 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6963 #endif /* ! defined (F_SETOWN) */
6964 #endif /* F_SETOWN_BUG */
6967 if (interrupt_input
)
6968 init_sigio (connection
);
6969 #endif /* ! defined (SIGIO) */
6972 /* Make sure that we have a valid font for dialog boxes
6973 so that Xt does not crash. */
6975 Display
*dpy
= dpyinfo
->display
;
6980 d
.addr
= (XPointer
)&dpy
;
6981 d
.size
= sizeof (Display
*);
6982 fr
.addr
= XtDefaultFont
;
6983 fr
.size
= sizeof (XtDefaultFont
);
6984 to
.size
= sizeof (Font
*);
6985 to
.addr
= (XPointer
)&font
;
6986 count
= x_catch_errors (dpy
);
6987 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
6989 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
6990 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
6991 x_uncatch_errors (dpy
, count
);
7001 /* Get rid of display DPYINFO, assuming all frames are already gone,
7002 and without sending any more commands to the X server. */
7005 x_delete_display (dpyinfo
)
7006 struct x_display_info
*dpyinfo
;
7008 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
7010 /* Discard this display from x_display_name_list and x_display_list.
7011 We can't use Fdelq because that can quit. */
7012 if (! NILP (x_display_name_list
)
7013 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
7014 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
7019 tail
= x_display_name_list
;
7020 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
7022 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
7023 dpyinfo
->name_list_element
))
7025 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
7028 tail
= XCONS (tail
)->cdr
;
7032 if (x_display_list
== dpyinfo
)
7033 x_display_list
= dpyinfo
->next
;
7036 struct x_display_info
*tail
;
7038 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
7039 if (tail
->next
== dpyinfo
)
7040 tail
->next
= tail
->next
->next
;
7043 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
7044 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
7045 XrmDestroyDatabase (dpyinfo
->xrdb
);
7049 if (--dpyinfo
->kboard
->reference_count
== 0)
7050 delete_kboard (dpyinfo
->kboard
);
7052 xfree (dpyinfo
->font_table
);
7053 xfree (dpyinfo
->x_id_name
);
7057 /* Set up use of X before we make the first connection. */
7061 clear_frame_hook
= XTclear_frame
;
7062 clear_end_of_line_hook
= XTclear_end_of_line
;
7063 ins_del_lines_hook
= XTins_del_lines
;
7064 change_line_highlight_hook
= XTchange_line_highlight
;
7065 insert_glyphs_hook
= XTinsert_glyphs
;
7066 write_glyphs_hook
= XTwrite_glyphs
;
7067 delete_glyphs_hook
= XTdelete_glyphs
;
7068 ring_bell_hook
= XTring_bell
;
7069 reset_terminal_modes_hook
= XTreset_terminal_modes
;
7070 set_terminal_modes_hook
= XTset_terminal_modes
;
7071 update_begin_hook
= XTupdate_begin
;
7072 update_end_hook
= XTupdate_end
;
7073 set_terminal_window_hook
= XTset_terminal_window
;
7074 read_socket_hook
= XTread_socket
;
7075 frame_up_to_date_hook
= XTframe_up_to_date
;
7076 cursor_to_hook
= XTcursor_to
;
7077 reassert_line_highlight_hook
= XTreassert_line_highlight
;
7078 mouse_position_hook
= XTmouse_position
;
7079 frame_rehighlight_hook
= XTframe_rehighlight
;
7080 frame_raise_lower_hook
= XTframe_raise_lower
;
7081 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
7082 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
7083 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
7084 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
7086 scroll_region_ok
= 1; /* we'll scroll partial frames */
7087 char_ins_del_ok
= 0; /* just as fast to write the line */
7088 line_ins_del_ok
= 1; /* we'll just blt 'em */
7089 fast_clear_end_of_line
= 1; /* X does this well */
7090 memory_below_frame
= 0; /* we don't remember what scrolls
7096 /* Try to use interrupt input; if we can't, then start polling. */
7097 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
7099 #ifdef USE_X_TOOLKIT
7100 XtToolkitInitialize ();
7101 Xt_app_con
= XtCreateApplicationContext ();
7102 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
7105 /* Note that there is no real way portable across R3/R4 to get the
7106 original error handler. */
7107 XSetErrorHandler (x_error_handler
);
7108 XSetIOErrorHandler (x_io_error_quitter
);
7110 /* Disable Window Change signals; they are handled by X events. */
7112 signal (SIGWINCH
, SIG_DFL
);
7113 #endif /* ! defined (SIGWINCH) */
7115 signal (SIGPIPE
, x_connection_signal
);
7121 staticpro (&x_error_message_string
);
7122 x_error_message_string
= Qnil
;
7124 staticpro (&x_display_name_list
);
7125 x_display_name_list
= Qnil
;
7127 staticpro (&last_mouse_scroll_bar
);
7128 last_mouse_scroll_bar
= Qnil
;
7130 staticpro (&Qvendor_specific_keysyms
);
7131 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
7133 staticpro (&last_mouse_press_frame
);
7134 last_mouse_press_frame
= Qnil
;
7137 #endif /* not HAVE_X_WINDOWS */