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 void 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. */
560 int ch
, first_ch
, charset
;
561 /* HIGHEST and LOWEST are used while drawing a composite
562 character. The meanings are described later. */
565 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
566 cf
= (cmpcharp
? cmpcharp
->face_work
: FAST_GLYPH_FACE (g
));
567 ch
= FAST_GLYPH_CHAR (g
);
568 if (gidx
== 0) first_ch
= ch
;
569 charset
= CHAR_CHARSET (ch
);
570 if (charset
== CHARSET_COMPOSITION
)
572 /* We must draw components of the composite character on the
574 cmpcharp
= cmpchar_table
[COMPOSITE_CHAR_ID (ch
)];
576 /* Set the face in the slot for work. */
577 cmpcharp
->face_work
= cf
;
579 /* We don't need the return value ... */
580 dumpglyphs (f
, left
, top
, cmpcharp
->glyph
, cmpcharp
->glyph_len
,
581 hl
, just_foreground
, cmpcharp
);
582 /* ... because the width of just drawn text can be
583 calculated as follows. */
584 left
+= FONT_WIDTH (f
->output_data
.x
->font
) * cmpcharp
->width
;
587 while (gp
&& (*gp
& GLYPH_MASK_PADDING
)) ++gp
, --n
;
592 /* Find the run of consecutive glyphs which can be drawn with
593 the same GC (i.e. the same charset and the same face-code).
594 Extract their character codes into BUF.
595 If CMPCHARP is not NULL, face-code is not checked because we
596 use only the face specified in `cmpcharp->face_work'. */
600 int this_charset
, c1
, c2
;
603 GLYPH_FOLLOW_ALIASES (tbase
, tlen
, g
);
604 ch
= FAST_GLYPH_CHAR (g
);
605 SPLIT_CHAR (ch
, this_charset
, c1
, c2
);
606 if (this_charset
!= charset
607 || (cmpcharp
== NULL
&& FAST_GLYPH_FACE (g
) != cf
))
611 cp
->byte1
= c1
, cp
->byte2
= c2
;
613 cp
->byte1
= 0, cp
->byte2
= c1
;
616 while (gp
&& (*gp
& GLYPH_MASK_PADDING
))
620 /* LEN gets the length of the run. */
622 /* Now output this run of chars, with the font and pixel values
623 determined by the face code CF. */
625 struct face
*face
= FRAME_DEFAULT_FACE (f
);
626 XFontStruct
*font
= NULL
;
629 int line_height
= f
->output_data
.x
->line_height
;
630 /* Pixel width of each glyph in this run. */
632 = (FONT_WIDTH (f
->output_data
.x
->font
)
633 * (cmpcharp
? cmpcharp
->width
: CHARSET_WIDTH (charset
)));
634 /* Overall pixel width of this run. */
636 = (FONT_WIDTH (f
->output_data
.x
->font
)
637 * (cmpcharp
? cmpcharp
->width
: len
* CHARSET_WIDTH (charset
)));
638 /* A flag to tell if we have already filled background. We
639 fill background in advance in the following cases:
640 1) A face has stipple.
641 2) A height of font is shorter than LINE_HEIGHT.
642 3) Drawing a composite character.
643 4) Font has non-zero _MULE_BASELINE_OFFSET property.
644 After filling background, we draw glyphs by XDrawString16. */
645 int background_filled
;
646 /* Baseline position of a character, offset from TOP. */
648 /* The property value of `_MULE_RELATIVE_COMPOSE' and
649 `_MULE_DEFAULT_ASCENT'. */
650 int relative_compose
= 0, default_ascent
= 0;
651 /* 1 if we find no font or a font of inappropriate size. */
652 int require_clipping
;
654 /* HL = 3 means use a mouse face previously chosen. */
656 cf
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
;
658 /* First look at the face of the text itself. */
661 /* It's possible for the display table to specify
662 a face code that is out of range. Use 0 in that case. */
663 if (cf
< 0 || cf
>= FRAME_N_COMPUTED_FACES (f
)
664 || FRAME_COMPUTED_FACES (f
) [cf
] == 0)
668 face
= FRAME_MODE_LINE_FACE (f
);
670 face
= intern_face (f
, FRAME_COMPUTED_FACES (f
) [cf
]);
671 if (FACE_STIPPLE (face
))
675 /* Then comes the distinction between modeline and normal text. */
680 face
= FRAME_MODE_LINE_FACE (f
);
681 if (FACE_STIPPLE (face
))
685 #define FACE_DEFAULT (~0)
687 /* Setting appropriate font and gc for this charset. */
688 if (charset
!= CHARSET_ASCII
)
691 int fontset
= FACE_FONTSET (face
);
692 struct font_info
*fontp
;
694 if ((fontset
< 0 && (fontset
= FRAME_FONTSET (f
)) < 0)
695 || !(fontp
= fs_load_font (f
, FRAME_X_FONT_TABLE (f
),
696 charset
, NULL
, fontset
)))
699 font
= (XFontStruct
*) (fontp
->font
);
700 gc
= FACE_NON_ASCII_GC (face
);
701 XSetFont (FRAME_X_DISPLAY (f
), gc
, font
->fid
);
703 = (font
->max_byte1
!= 0
704 ? (line_height
+ font
->ascent
- font
->descent
) / 2
705 : f
->output_data
.x
->font_baseline
- fontp
->baseline_offset
);
706 if (cmpcharp
&& cmpcharp
->cmp_rule
== NULL
)
708 relative_compose
= fontp
->relative_compose
;
709 default_ascent
= fontp
->default_ascent
;
712 /* We have to change code points in the following cases. */
713 if (fontp
->font_encoder
)
715 /* This font requires CCL program to calculate code
716 point of characters. */
717 struct ccl_program
*ccl
= fontp
->font_encoder
;
719 if (CHARSET_DIMENSION (charset
) == 1)
720 for (cp
= buf
; cp
< buf
+ len
; cp
++)
722 ccl
->reg
[0] = charset
;
723 ccl
->reg
[1] = cp
->byte2
;
724 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
725 cp
->byte2
= ccl
->reg
[1];
728 for (cp
= buf
; cp
< buf
+ len
; cp
++)
730 ccl
->reg
[0] = charset
;
731 ccl
->reg
[1] = cp
->byte1
, ccl
->reg
[2] = cp
->byte2
;
732 ccl_driver (ccl
, NULL
, NULL
, 0, 0, NULL
);
733 cp
->byte1
= ccl
->reg
[1], cp
->byte2
= ccl
->reg
[2];
736 else if (fontp
->encoding
[charset
])
738 int enc
= fontp
->encoding
[charset
];
740 if ((enc
== 1 || enc
== 2) && CHARSET_DIMENSION (charset
) == 2)
741 for (cp
= buf
; cp
< buf
+ len
; cp
++)
743 if (enc
== 1 || enc
== 3)
744 for (cp
= buf
; cp
< buf
+ len
; cp
++)
750 font
= FACE_FONT (face
);
751 if (font
== (XFontStruct
*) FACE_DEFAULT
)
752 font
= f
->output_data
.x
->font
;
753 baseline
= FONT_BASE (font
);
758 /* Now override that if the cursor's on this character. */
761 /* The cursor overrides stippling. */
764 if (font
== f
->output_data
.x
->font
765 && face
->background
== f
->output_data
.x
->background_pixel
766 && face
->foreground
== f
->output_data
.x
->foreground_pixel
)
768 gc
= f
->output_data
.x
->cursor_gc
;
770 /* Cursor on non-default face: must merge. */
776 xgcv
.background
= f
->output_data
.x
->cursor_pixel
;
777 xgcv
.foreground
= face
->background
;
778 /* If the glyph would be invisible,
779 try a different foreground. */
780 if (xgcv
.foreground
== xgcv
.background
)
781 xgcv
.foreground
= face
->foreground
;
782 if (xgcv
.foreground
== xgcv
.background
)
783 xgcv
.foreground
= f
->output_data
.x
->cursor_foreground_pixel
;
784 if (xgcv
.foreground
== xgcv
.background
)
785 xgcv
.foreground
= face
->foreground
;
786 /* Make sure the cursor is distinct from text in this face. */
787 if (xgcv
.background
== face
->background
788 && xgcv
.foreground
== face
->foreground
)
790 xgcv
.background
= face
->foreground
;
791 xgcv
.foreground
= face
->background
;
794 xgcv
.font
= font
->fid
;
796 xgcv
.font
= FACE_FONT (face
)->fid
;
797 xgcv
.graphics_exposures
= 0;
798 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
799 if (FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
)
800 XChangeGC (FRAME_X_DISPLAY (f
),
801 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
,
804 FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
805 = XCreateGC (FRAME_X_DISPLAY (f
), window
, mask
, &xgcv
);
806 gc
= FRAME_X_DISPLAY_INFO (f
)->scratch_cursor_gc
;
808 /* If this code is restored, it must also reset to the default stipple
810 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
811 XSetStipple (FRAME_X_DISPLAY (f
), gc
, face
->stipple
);
817 require_clipping
= (!NILP (Vclip_large_size_font
)
818 && (font
->ascent
> baseline
819 || font
->descent
> line_height
- baseline
821 && FONT_WIDTH (font
) > glyph_width
)));
823 if (font
&& (just_foreground
|| (cmpcharp
&& gidx
> 0)))
824 background_filled
= 1;
827 /* Turn stipple on. */
828 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillOpaqueStippled
);
830 /* Draw stipple or background color on background. */
831 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
832 left
, top
, run_width
, line_height
);
834 /* Turn stipple off. */
835 XSetFillStyle (FRAME_X_DISPLAY (f
), gc
, FillSolid
);
837 background_filled
= 1;
840 || FONT_HEIGHT (font
) < line_height
841 || FONT_WIDTH (font
) < glyph_width
844 /* Fill a area for the current run in background pixle of GC. */
846 unsigned long mask
= GCForeground
| GCBackground
;
847 unsigned long fore
, back
;
849 /* The current code at first exchange foreground and
850 background of GC, fill the area, then recover the
851 original foreground and background of GC.
852 Aren't there any more smart ways? */
854 XGetGCValues (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
855 fore
= xgcv
.foreground
, back
= xgcv
.background
;
856 xgcv
.foreground
= back
, xgcv
.background
= fore
;
857 XChangeGC (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
858 XFillRectangle (FRAME_X_DISPLAY (f
), window
, gc
,
859 left
, top
, run_width
, line_height
);
860 xgcv
.foreground
= fore
, xgcv
.background
= back
;
861 XChangeGC (FRAME_X_DISPLAY (f
), gc
, mask
, &xgcv
);
863 background_filled
= 1;
865 /* To assure not to fill background while drawing
866 remaining components. */
870 background_filled
= 0;
874 if (require_clipping
)
876 Region region
; /* Region used for setting clip mask to GC. */
877 XPoint x
[4]; /* Data used for creating REGION. */
879 x
[0].x
= x
[3].x
= left
, x
[1].x
= x
[2].x
= left
+ glyph_width
;
880 x
[0].y
= x
[1].y
= top
, x
[2].y
= x
[3].y
= top
+ line_height
;
881 region
= XPolygonRegion (x
, 4, EvenOddRule
);
882 XSetRegion (FRAME_X_DISPLAY (f
), gc
, region
);
883 XDestroyRegion (region
);
888 if (require_clipping
)
889 for (i
= 0; i
< len
; i
++)
892 XSetClipOrigin (FRAME_X_DISPLAY (f
), gc
,
894 if (background_filled
)
895 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
896 left
+ glyph_width
* i
,
897 top
+ baseline
, buf
+ i
, 1);
899 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
900 left
+ glyph_width
* i
,
901 top
+ baseline
, buf
+ i
, 1);
905 if (background_filled
)
906 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
907 left
, top
+ baseline
, buf
, len
);
909 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, gc
,
910 left
, top
+ baseline
, buf
, len
);
915 XCharStruct
*pcm
; /* Pointer to per char metric info. */
917 if ((cmpcharp
->cmp_rule
|| relative_compose
)
920 /* This is the first character. Initialize variables.
921 HIGHEST is the highest position of glyphs ever
922 written, LOWEST the lowest position. */
926 && CHAR_TABLE_P (Vuse_default_ascent
)
927 && !NILP (Faref (Vuse_default_ascent
, first_ch
)))
929 highest
= default_ascent
;
934 pcm
= PER_CHAR_METRIC (font
, buf
);
935 highest
= pcm
->ascent
+ 1;
936 lowest
= - pcm
->descent
;
939 if (cmpcharp
->cmp_rule
)
940 x_offset
= (cmpcharp
->col_offset
[0]
941 * FONT_WIDTH (f
->output_data
.x
->font
));
942 /* Draw the first character at the normal position. */
943 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
944 left
+ x_offset
, top
+ baseline
, buf
, 1);
951 for (; i
< len
; i
++, gidx
++)
953 int x_offset
= 0, y_offset
= 0;
955 if (relative_compose
)
957 pcm
= PER_CHAR_METRIC (font
, buf
+ i
);
958 if (- pcm
->descent
>= relative_compose
)
960 /* Draw above the current glyphs. */
961 y_offset
= highest
+ pcm
->descent
;
962 highest
+= pcm
->ascent
+ pcm
->descent
;
964 else if (pcm
->ascent
<= 0)
966 /* Draw beneath the current glyphs. */
967 y_offset
= lowest
- pcm
->ascent
;
968 lowest
-= pcm
->ascent
+ pcm
->descent
;
971 else if (cmpcharp
->cmp_rule
)
973 int gref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) / 9;
974 int nref
= (cmpcharp
->cmp_rule
[gidx
] - 0xA0) % 9;
977 /* Re-encode GREF and NREF so that they specify
978 only Y-axis information:
979 0:top, 1:base, 2:bottom, 3:center */
980 gref
= gref
/ 3 + (gref
== 4) * 2;
981 nref
= nref
/ 3 + (nref
== 4) * 2;
983 pcm
= PER_CHAR_METRIC (font
, buf
+ i
);
984 bottom
= ((gref
== 0 ? highest
: gref
== 1 ? 0
986 : (highest
+ lowest
) / 2)
987 - (nref
== 0 ? pcm
->ascent
+ pcm
->descent
988 : nref
== 1 ? pcm
->descent
: nref
== 2 ? 0
989 : (pcm
->ascent
+ pcm
->descent
) / 2));
990 top
= bottom
+ (pcm
->ascent
+ pcm
->descent
);
995 y_offset
= bottom
+ pcm
->descent
;
996 x_offset
= (cmpcharp
->col_offset
[gidx
]
997 * FONT_WIDTH (f
->output_data
.x
->font
));
999 XDrawString16 (FRAME_X_DISPLAY (f
), window
, gc
,
1000 left
+ x_offset
, top
+ baseline
- y_offset
,
1004 if (require_clipping
)
1005 XSetClipMask (FRAME_X_DISPLAY (f
), gc
, None
);
1007 #if 0 /* Doesn't work, because it uses FRAME_CURRENT_GLYPHS,
1008 which often is not up to date yet. */
1009 if (!just_foreground
)
1011 if (left
== orig_left
)
1012 redraw_previous_char (f
, PIXEL_TO_CHAR_COL (f
, left
),
1013 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1015 redraw_following_char (f
, PIXEL_TO_CHAR_COL (f
, left
+ len
* FONT_WIDTH (font
)),
1016 PIXEL_TO_CHAR_ROW (f
, top
), hl
== 1);
1020 if (!font
|| require_clipping
&& !NILP (Vhighlight_wrong_size_font
))
1022 /* Show rectangles to show that we found no font or a font
1023 of inappropriate size. */
1027 (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1028 left
, top
, run_width
- 1, line_height
- 1);
1030 for (i
= 0; i
< len
; i
++)
1031 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1032 left
+ glyph_width
* i
, top
,
1033 glyph_width
-1, line_height
- 1);
1036 /* We should probably check for XA_UNDERLINE_POSITION and
1037 XA_UNDERLINE_THICKNESS properties on the font, but let's
1038 just get the thing working, and come back to that. */
1040 /* Setting underline position based on the metric of the
1041 current font results in shaky underline if it strides
1042 over different fonts. So, we set the position based only
1043 on the default font of this frame. */
1044 int underline_position
= f
->output_data
.x
->font_baseline
+ 1;
1046 if (underline_position
>= line_height
)
1047 underline_position
= line_height
- 1;
1049 if (face
->underline
)
1050 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1052 left
, top
+ underline_position
, run_width
, 1);
1060 return (left
- orig_left
);
1065 /* This is the old single-face code. */
1068 dumpglyphs (f
, left
, top
, gp
, n
, hl
, font
)
1071 register GLYPH
*gp
; /* Points to first GLYPH. */
1072 register int n
; /* Number of glyphs to display. */
1077 Window window
= FRAME_X_WINDOW (f
);
1078 GC drawing_gc
= (hl
== 2 ? f
->output_data
.x
->cursor_gc
1079 : (hl
? f
->output_data
.x
->reverse_gc
1080 : f
->output_data
.x
->normal_gc
));
1082 if (sizeof (GLYPH
) == sizeof (XChar2b
))
1083 XDrawImageString16 (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1084 left
, top
+ FONT_BASE (font
), (XChar2b
*) gp
, n
);
1085 else if (sizeof (GLYPH
) == sizeof (unsigned char))
1086 XDrawImageString (FRAME_X_DISPLAY (f
), window
, drawing_gc
,
1087 left
, top
+ FONT_BASE (font
), (char *) gp
, n
);
1089 /* What size of glyph ARE you using? And does X have a function to
1095 /* Output some text at the nominal frame cursor position.
1096 Advance the cursor over the text.
1097 Output LEN glyphs at START.
1099 `highlight', set up by XTreassert_line_highlight or XTchange_line_highlight,
1100 controls the pixel values used for foreground and background. */
1103 XTwrite_glyphs (start
, len
)
1104 register GLYPH
*start
;
1107 register int temp_length
;
1118 /* If not within an update,
1119 output at the frame's visible cursor. */
1120 curs_x
= f
->cursor_x
;
1121 curs_y
= f
->cursor_y
;
1125 CHAR_TO_PIXEL_COL (f
, curs_x
),
1126 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1127 start
, len
, highlight
, 0, NULL
);
1129 /* If we drew on top of the cursor, note that it is turned off. */
1130 if (curs_y
== f
->phys_cursor_y
1131 && curs_x
<= f
->phys_cursor_x
1132 && curs_x
+ len
> f
->phys_cursor_x
)
1133 f
->phys_cursor_on
= 0;
1135 if (updating_frame
== 0)
1136 x_display_cursor (f
, 1, FRAME_CURSOR_X (f
) + len
, FRAME_CURSOR_Y (f
));
1143 /* Clear to the end of the line.
1144 Erase the current text line from the nominal cursor position (inclusive)
1145 to column FIRST_UNUSED (exclusive). The idea is that everything
1146 from FIRST_UNUSED onward is already erased. */
1149 XTclear_end_of_line (first_unused
)
1150 register int first_unused
;
1152 struct frame
*f
= updating_frame
;
1158 if (curs_y
< 0 || curs_y
>= f
->height
)
1160 if (first_unused
<= 0)
1163 if (first_unused
>= FRAME_WINDOW_WIDTH (f
))
1164 first_unused
= FRAME_WINDOW_WIDTH (f
);
1166 first_unused
+= FRAME_LEFT_SCROLL_BAR_WIDTH (f
);
1172 /* Notice if the cursor will be cleared by this operation. */
1173 if (curs_y
== f
->phys_cursor_y
1174 && curs_x
<= f
->phys_cursor_x
1175 && f
->phys_cursor_x
< first_unused
)
1176 f
->phys_cursor_on
= 0;
1178 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1179 CHAR_TO_PIXEL_COL (f
, curs_x
),
1180 CHAR_TO_PIXEL_ROW (f
, curs_y
),
1181 FONT_WIDTH (f
->output_data
.x
->font
) * (first_unused
- curs_x
),
1182 f
->output_data
.x
->line_height
, False
);
1184 redraw_previous_char (f
, curs_x
, curs_y
, highlight
);
1194 struct frame
*f
= updating_frame
;
1199 f
->phys_cursor_on
= 0; /* Cursor not visible. */
1200 curs_x
= 0; /* Nominal cursor position is top left. */
1205 XClearWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
1207 /* We have to clear the scroll bars, too. If we have changed
1208 colors or something like that, then they should be notified. */
1209 x_scroll_bar_clear (f
);
1211 XFlush (FRAME_X_DISPLAY (f
));
1216 /* This currently does not work because FRAME_CURRENT_GLYPHS doesn't
1217 always contain the right glyphs to use.
1219 It also needs to be changed to look at the details of the font and
1220 see whether there is really overlap, and do nothing when there is
1221 not. This can use font_char_overlap_left and font_char_overlap_right,
1222 but just how to use them is not clear. */
1224 /* Erase the character (if any) at the position just before X, Y in frame F,
1225 then redraw it and the character before it.
1226 This is necessary when we erase starting at X,
1227 in case the character after X overlaps into the one before X.
1228 Call this function with input blocked. */
1231 redraw_previous_char (f
, x
, y
, highlight_flag
)
1236 /* Erase the character before the new ones, in case
1237 what was here before overlaps it.
1238 Reoutput that character, and the previous character
1239 (in case the previous character overlaps it). */
1242 int start_x
= x
- 2;
1245 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1246 CHAR_TO_PIXEL_COL (f
, x
- 1),
1247 CHAR_TO_PIXEL_ROW (f
, y
),
1248 FONT_WIDTH (f
->output_data
.x
->font
),
1249 f
->output_data
.x
->line_height
, False
);
1251 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, start_x
),
1252 CHAR_TO_PIXEL_ROW (f
, y
),
1253 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][start_x
],
1254 x
- start_x
, highlight_flag
, 1, NULL
);
1258 /* Erase the character (if any) at the position X, Y in frame F,
1259 then redraw it and the character after it.
1260 This is necessary when we erase endng at X,
1261 in case the character after X overlaps into the one before X.
1262 Call this function with input blocked. */
1265 redraw_following_char (f
, x
, y
, highlight_flag
)
1270 int limit
= FRAME_CURRENT_GLYPHS (f
)->used
[y
];
1271 /* Erase the character after the new ones, in case
1272 what was here before overlaps it.
1273 Reoutput that character, and the following character
1274 (in case the following character overlaps it). */
1276 && FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
] != SPACEGLYPH
)
1281 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1282 CHAR_TO_PIXEL_COL (f
, x
),
1283 CHAR_TO_PIXEL_ROW (f
, y
),
1284 FONT_WIDTH (f
->output_data
.x
->font
),
1285 f
->output_data
.x
->line_height
, False
);
1287 dumpglyphs (f
, CHAR_TO_PIXEL_COL (f
, x
),
1288 CHAR_TO_PIXEL_ROW (f
, y
),
1289 &FRAME_CURRENT_GLYPHS (f
)->glyphs
[y
][x
],
1290 end_x
- x
, highlight_flag
, 1, NULL
);
1295 #if 0 /* Not in use yet */
1297 /* Return 1 if character C in font F extends past its left edge. */
1300 font_char_overlap_left (font
, c
)
1306 /* Find the bounding-box info for C. */
1307 if (font
->per_char
== 0)
1308 s
= &font
->max_bounds
;
1311 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1314 /* Decode char into row number (byte 1) and code within row (byte 2). */
1317 if (!(within
>= font
->min_char_or_byte2
1318 && within
<= font
->max_char_or_byte2
1319 && row
>= font
->min_byte1
1320 && row
<= font
->max_byte1
))
1322 /* If char is out of range, try the font's default char instead. */
1323 c
= font
->default_char
;
1324 row
= c
>> (BITS_PER_INT
- 8);
1327 if (!(within
>= font
->min_char_or_byte2
1328 && within
<= font
->max_char_or_byte2
1329 && row
>= font
->min_byte1
1330 && row
<= font
->max_byte1
))
1331 /* Still out of range means this char does not overlap. */
1334 /* We found the info for this char. */
1335 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1339 return (s
&& s
->lbearing
< 0);
1342 /* Return 1 if character C in font F extends past its right edge. */
1345 font_char_overlap_right (font
, c
)
1351 /* Find the bounding-box info for C. */
1352 if (font
->per_char
== 0)
1353 s
= &font
->max_bounds
;
1356 int rowlen
= font
->max_char_or_byte2
- font
->min_char_or_byte2
+ 1;
1359 /* Decode char into row number (byte 1) and code within row (byte 2). */
1362 if (!(within
>= font
->min_char_or_byte2
1363 && within
<= font
->max_char_or_byte2
1364 && row
>= font
->min_byte1
1365 && row
<= font
->max_byte1
))
1367 /* If char is out of range, try the font's default char instead. */
1368 c
= font
->default_char
;
1369 row
= c
>> (BITS_PER_INT
- 8);
1372 if (!(within
>= font
->min_char_or_byte2
1373 && within
<= font
->max_char_or_byte2
1374 && row
>= font
->min_byte1
1375 && row
<= font
->max_byte1
))
1376 /* Still out of range means this char does not overlap. */
1379 /* We found the info for this char. */
1380 s
= (font
->per_char
+ (within
- font
->min_char_or_byte2
)
1384 return (s
&& s
->rbearing
>= s
->width
);
1388 /* Invert the middle quarter of the frame for .15 sec. */
1390 /* We use the select system call to do the waiting, so we have to make sure
1391 it's available. If it isn't, we just won't do visual bells. */
1392 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1394 /* Subtract the `struct timeval' values X and Y,
1395 storing the result in RESULT.
1396 Return 1 if the difference is negative, otherwise 0. */
1399 timeval_subtract (result
, x
, y
)
1400 struct timeval
*result
, x
, y
;
1402 /* Perform the carry for the later subtraction by updating y.
1403 This is safer because on some systems
1404 the tv_sec member is unsigned. */
1405 if (x
.tv_usec
< y
.tv_usec
)
1407 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000 + 1;
1408 y
.tv_usec
-= 1000000 * nsec
;
1411 if (x
.tv_usec
- y
.tv_usec
> 1000000)
1413 int nsec
= (y
.tv_usec
- x
.tv_usec
) / 1000000;
1414 y
.tv_usec
+= 1000000 * nsec
;
1418 /* Compute the time remaining to wait. tv_usec is certainly positive. */
1419 result
->tv_sec
= x
.tv_sec
- y
.tv_sec
;
1420 result
->tv_usec
= x
.tv_usec
- y
.tv_usec
;
1422 /* Return indication of whether the result should be considered negative. */
1423 return x
.tv_sec
< y
.tv_sec
;
1434 /* Create a GC that will use the GXxor function to flip foreground pixels
1435 into background pixels. */
1439 values
.function
= GXxor
;
1440 values
.foreground
= (f
->output_data
.x
->foreground_pixel
1441 ^ f
->output_data
.x
->background_pixel
);
1443 gc
= XCreateGC (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1444 GCFunction
| GCForeground
, &values
);
1448 /* Get the height not including a menu bar widget. */
1449 int height
= CHAR_TO_PIXEL_HEIGHT (f
, FRAME_HEIGHT (f
));
1450 /* Height of each line to flash. */
1451 int flash_height
= FRAME_LINE_HEIGHT (f
);
1452 /* These will be the left and right margins of the rectangles. */
1453 int flash_left
= FRAME_INTERNAL_BORDER_WIDTH (f
);
1454 int flash_right
= PIXEL_WIDTH (f
) - FRAME_INTERNAL_BORDER_WIDTH (f
);
1458 /* Don't flash the area between a scroll bar and the frame
1459 edge it is next to. */
1460 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f
))
1462 case vertical_scroll_bar_left
:
1463 flash_left
+= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1466 case vertical_scroll_bar_right
:
1467 flash_right
-= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
1471 width
= flash_right
- flash_left
;
1473 /* If window is tall, flash top and bottom line. */
1474 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1476 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1477 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1478 width
, flash_height
);
1479 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1481 (height
- flash_height
1482 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1483 width
, flash_height
);
1486 /* If it is short, flash it all. */
1487 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1488 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1489 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1491 XFlush (FRAME_X_DISPLAY (f
));
1494 struct timeval wakeup
, now
;
1496 EMACS_GET_TIME (wakeup
);
1498 /* Compute time to wait until, propagating carry from usecs. */
1499 wakeup
.tv_usec
+= 150000;
1500 wakeup
.tv_sec
+= (wakeup
.tv_usec
/ 1000000);
1501 wakeup
.tv_usec
%= 1000000;
1503 /* Keep waiting until past the time wakeup. */
1506 struct timeval timeout
;
1508 EMACS_GET_TIME (timeout
);
1510 /* In effect, timeout = wakeup - timeout.
1511 Break if result would be negative. */
1512 if (timeval_subtract (&timeout
, wakeup
, timeout
))
1515 /* Try to wait that long--but we might wake up sooner. */
1516 select (0, NULL
, NULL
, NULL
, &timeout
);
1520 /* If window is tall, flash top and bottom line. */
1521 if (height
> 3 * FRAME_LINE_HEIGHT (f
))
1523 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1524 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1525 width
, flash_height
);
1526 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1528 (height
- flash_height
1529 - FRAME_INTERNAL_BORDER_WIDTH (f
)),
1530 width
, flash_height
);
1533 /* If it is short, flash it all. */
1534 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), gc
,
1535 flash_left
, FRAME_INTERNAL_BORDER_WIDTH (f
),
1536 width
, height
- 2 * FRAME_INTERNAL_BORDER_WIDTH (f
));
1538 XFreeGC (FRAME_X_DISPLAY (f
), gc
);
1539 XFlush (FRAME_X_DISPLAY (f
));
1549 /* Make audible bell. */
1551 #define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
1555 if (FRAME_X_DISPLAY (selected_frame
) == 0)
1558 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
1560 XTflash (selected_frame
);
1566 XFlush (FRAME_X_DISPLAY (selected_frame
));
1571 /* Insert and delete character.
1572 These are not supposed to be used because we are supposed to turn
1573 off the feature of using them. */
1576 XTinsert_glyphs (start
, len
)
1577 register char *start
;
1590 /* Specify how many text lines, from the top of the window,
1591 should be affected by insert-lines and delete-lines operations.
1592 This, and those operations, are used only within an update
1593 that is bounded by calls to XTupdate_begin and XTupdate_end. */
1596 XTset_terminal_window (n
)
1599 if (updating_frame
== 0)
1602 if ((n
<= 0) || (n
> updating_frame
->height
))
1603 flexlines
= updating_frame
->height
;
1608 /* These variables need not be per frame
1609 because redisplay is done on a frame-by-frame basis
1610 and the line dance for one frame is finished before
1611 anything is done for anoter frame. */
1613 /* Array of line numbers from cached insert/delete operations.
1614 line_dance[i] is the old position of the line that we want
1615 to move to line i, or -1 if we want a blank line there. */
1616 static int *line_dance
;
1618 /* Allocated length of that array. */
1619 static int line_dance_len
;
1621 /* Flag indicating whether we've done any work. */
1622 static int line_dance_in_progress
;
1624 /* Perform an insert-lines or delete-lines operation,
1625 inserting N lines or deleting -N lines at vertical position VPOS. */
1626 XTins_del_lines (vpos
, n
)
1629 register int fence
, i
;
1631 if (vpos
>= flexlines
)
1634 if (!line_dance_in_progress
)
1636 int ht
= updating_frame
->height
;
1637 if (ht
> line_dance_len
)
1639 line_dance
= (int *)xrealloc (line_dance
, ht
* sizeof (int));
1640 line_dance_len
= ht
;
1642 for (i
= 0; i
< ht
; ++i
) line_dance
[i
] = i
;
1643 line_dance_in_progress
= 1;
1647 if (n
> flexlines
- vpos
)
1648 n
= flexlines
- vpos
;
1650 for (i
= flexlines
; --i
>= fence
;)
1651 line_dance
[i
] = line_dance
[i
-n
];
1652 for (i
= fence
; --i
>= vpos
;)
1658 if (n
> flexlines
- vpos
)
1659 n
= flexlines
- vpos
;
1660 fence
= flexlines
- n
;
1661 for (i
= vpos
; i
< fence
; ++i
)
1662 line_dance
[i
] = line_dance
[i
+ n
];
1663 for (i
= fence
; i
< flexlines
; ++i
)
1668 /* Here's where we actually move the pixels around.
1669 Must be called with input blocked. */
1673 register int i
, j
, distance
;
1674 register struct frame
*f
;
1678 /* Must check this flag first. If it's not set, then not only is the
1679 array uninitialized, but we might not even have a frame. */
1680 if (!line_dance_in_progress
)
1688 intborder
= CHAR_TO_PIXEL_COL (f
, FRAME_LEFT_SCROLL_BAR_WIDTH (f
));
1690 x_update_cursor (updating_frame
, 0);
1692 for (i
= 0; i
< ht
; ++i
)
1693 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) > 0)
1695 for (j
= i
; (j
< ht
&& line_dance
[j
] != -1
1696 && line_dance
[j
]-j
== distance
); ++j
);
1697 /* Copy [i,j) upward from [i+distance,j+distance) */
1698 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1699 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1700 intborder
, CHAR_TO_PIXEL_ROW (f
, i
+distance
),
1701 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1702 (j
-i
) * f
->output_data
.x
->line_height
,
1703 intborder
, CHAR_TO_PIXEL_ROW (f
, i
));
1707 for (i
= ht
; --i
>=0; )
1708 if (line_dance
[i
] != -1 && (distance
= line_dance
[i
]-i
) < 0)
1710 for (j
= i
; (--j
>= 0 && line_dance
[j
] != -1
1711 && line_dance
[j
]-j
== distance
););
1712 /* Copy (j,i] downward from (j+distance, i+distance] */
1713 XCopyArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1714 FRAME_X_WINDOW (f
), f
->output_data
.x
->normal_gc
,
1715 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1+distance
),
1716 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1717 (i
-j
) * f
->output_data
.x
->line_height
,
1718 intborder
, CHAR_TO_PIXEL_ROW (f
, j
+1));
1722 for (i
= 0; i
< ht
; ++i
)
1723 if (line_dance
[i
] == -1)
1725 for (j
= i
; j
< ht
&& line_dance
[j
] == -1; ++j
);
1727 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1728 intborder
, CHAR_TO_PIXEL_ROW (f
, i
),
1729 FRAME_WINDOW_WIDTH (f
) * FONT_WIDTH (f
->output_data
.x
->font
),
1730 (j
-i
) * f
->output_data
.x
->line_height
, False
);
1733 line_dance_in_progress
= 0;
1736 /* Support routines for exposure events. */
1737 static void clear_cursor ();
1739 /* Output into a rectangle of an X-window (for frame F)
1740 the characters in f->phys_lines that overlap that rectangle.
1741 TOP and LEFT are the position of the upper left corner of the rectangle.
1742 ROWS and COLS are the size of the rectangle.
1743 Call this function with input blocked. */
1746 dumprectangle (f
, left
, top
, cols
, rows
)
1748 register int left
, top
, cols
, rows
;
1750 register struct frame_glyphs
*active_frame
= FRAME_CURRENT_GLYPHS (f
);
1751 int cursor_cleared
= 0;
1755 if (FRAME_GARBAGED_P (f
))
1758 /* Express rectangle as four edges, instead of position-and-size. */
1759 bottom
= top
+ rows
;
1760 right
= left
+ cols
;
1762 /* Convert rectangle edges in pixels to edges in chars.
1763 Round down for left and top, up for right and bottom. */
1764 top
= PIXEL_TO_CHAR_ROW (f
, top
);
1765 left
= PIXEL_TO_CHAR_COL (f
, left
);
1766 bottom
+= (f
->output_data
.x
->line_height
- 1);
1767 right
+= (FONT_WIDTH (f
->output_data
.x
->font
) - 1);
1768 bottom
= PIXEL_TO_CHAR_ROW (f
, bottom
);
1769 right
= PIXEL_TO_CHAR_COL (f
, right
);
1771 /* Clip the rectangle to what can be visible. */
1776 if (right
> FRAME_WINDOW_WIDTH (f
))
1777 right
= FRAME_WINDOW_WIDTH (f
);
1778 if (bottom
> f
->height
)
1781 /* Get size in chars of the rectangle. */
1782 cols
= right
- left
;
1783 rows
= bottom
- top
;
1785 /* If rectangle has zero area, return. */
1786 if (rows
<= 0) return;
1787 if (cols
<= 0) return;
1789 /* Turn off the cursor if it is in the rectangle.
1790 We will turn it back on afterward. */
1791 if ((f
->phys_cursor_x
>= left
) && (f
->phys_cursor_x
< right
)
1792 && (f
->phys_cursor_y
>= top
) && (f
->phys_cursor_y
< bottom
))
1798 /* Display the text in the rectangle, one text line at a time. */
1800 for (y
= top
; y
< bottom
; y
++)
1802 GLYPH
*line
= &active_frame
->glyphs
[y
][left
];
1804 if (! active_frame
->enable
[y
] || left
> active_frame
->used
[y
])
1807 while (*line
& GLYPH_MASK_PADDING
)
1809 /* We must display the whole glyph of a wide-column
1816 CHAR_TO_PIXEL_COL (f
, left
),
1817 CHAR_TO_PIXEL_ROW (f
, y
),
1818 line
, min (cols
, active_frame
->used
[y
] - left
),
1819 active_frame
->highlight
[y
], 0, NULL
);
1822 /* Turn the cursor on if we turned it off. */
1825 x_update_cursor (f
, 1);
1832 /* We used to only do this if Vx_no_window_manager was non-nil, but
1833 the ICCCM (section 4.1.6) says that the window's border pixmap
1834 and border pixel are window attributes which are "private to the
1835 client", so we can always change it to whatever we want. */
1837 XSetWindowBorder (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1838 f
->output_data
.x
->border_pixel
);
1840 x_update_cursor (f
, 1);
1844 frame_unhighlight (f
)
1847 /* We used to only do this if Vx_no_window_manager was non-nil, but
1848 the ICCCM (section 4.1.6) says that the window's border pixmap
1849 and border pixel are window attributes which are "private to the
1850 client", so we can always change it to whatever we want. */
1852 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
1853 f
->output_data
.x
->border_tile
);
1855 x_update_cursor (f
, 1);
1858 static void XTframe_rehighlight ();
1859 static void x_frame_rehighlight ();
1861 /* The focus has changed. Update the frames as necessary to reflect
1862 the new situation. Note that we can't change the selected frame
1863 here, because the Lisp code we are interrupting might become confused.
1864 Each event gets marked with the frame in which it occurred, so the
1865 Lisp code can tell when the switch took place by examining the events. */
1868 x_new_focus_frame (dpyinfo
, frame
)
1869 struct x_display_info
*dpyinfo
;
1870 struct frame
*frame
;
1872 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
1873 int events_enqueued
= 0;
1875 if (frame
!= dpyinfo
->x_focus_frame
)
1877 /* Set this before calling other routines, so that they see
1878 the correct value of x_focus_frame. */
1879 dpyinfo
->x_focus_frame
= frame
;
1881 if (old_focus
&& old_focus
->auto_lower
)
1882 x_lower_frame (old_focus
);
1885 selected_frame
= frame
;
1886 XSETFRAME (XWINDOW (selected_frame
->selected_window
)->frame
,
1888 Fselect_window (selected_frame
->selected_window
);
1889 choose_minibuf_frame ();
1892 if (dpyinfo
->x_focus_frame
&& dpyinfo
->x_focus_frame
->auto_raise
)
1893 pending_autoraise_frame
= dpyinfo
->x_focus_frame
;
1895 pending_autoraise_frame
= 0;
1898 x_frame_rehighlight (dpyinfo
);
1901 /* Handle an event saying the mouse has moved out of an Emacs frame. */
1904 x_mouse_leave (dpyinfo
)
1905 struct x_display_info
*dpyinfo
;
1907 x_new_focus_frame (dpyinfo
, dpyinfo
->x_focus_event_frame
);
1910 /* The focus has changed, or we have redirected a frame's focus to
1911 another frame (this happens when a frame uses a surrogate
1912 minibuffer frame). Shift the highlight as appropriate.
1914 The FRAME argument doesn't necessarily have anything to do with which
1915 frame is being highlighted or unhighlighted; we only use it to find
1916 the appropriate X display info. */
1918 XTframe_rehighlight (frame
)
1919 struct frame
*frame
;
1921 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame
));
1925 x_frame_rehighlight (dpyinfo
)
1926 struct x_display_info
*dpyinfo
;
1928 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1930 if (dpyinfo
->x_focus_frame
)
1932 dpyinfo
->x_highlight_frame
1933 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
)))
1934 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
))
1935 : dpyinfo
->x_focus_frame
);
1936 if (! FRAME_LIVE_P (dpyinfo
->x_highlight_frame
))
1938 FRAME_FOCUS_FRAME (dpyinfo
->x_focus_frame
) = Qnil
;
1939 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1943 dpyinfo
->x_highlight_frame
= 0;
1945 if (dpyinfo
->x_highlight_frame
!= old_highlight
)
1948 frame_unhighlight (old_highlight
);
1949 if (dpyinfo
->x_highlight_frame
)
1950 frame_highlight (dpyinfo
->x_highlight_frame
);
1954 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
1956 /* Initialize mode_switch_bit and modifier_meaning. */
1958 x_find_modifier_meanings (dpyinfo
)
1959 struct x_display_info
*dpyinfo
;
1961 int min_code
, max_code
;
1964 XModifierKeymap
*mods
;
1966 dpyinfo
->meta_mod_mask
= 0;
1967 dpyinfo
->shift_lock_mask
= 0;
1968 dpyinfo
->alt_mod_mask
= 0;
1969 dpyinfo
->super_mod_mask
= 0;
1970 dpyinfo
->hyper_mod_mask
= 0;
1973 XDisplayKeycodes (dpyinfo
->display
, &min_code
, &max_code
);
1975 min_code
= dpyinfo
->display
->min_keycode
;
1976 max_code
= dpyinfo
->display
->max_keycode
;
1979 syms
= XGetKeyboardMapping (dpyinfo
->display
,
1980 min_code
, max_code
- min_code
+ 1,
1982 mods
= XGetModifierMapping (dpyinfo
->display
);
1984 /* Scan the modifier table to see which modifier bits the Meta and
1985 Alt keysyms are on. */
1987 int row
, col
; /* The row and column in the modifier table. */
1989 for (row
= 3; row
< 8; row
++)
1990 for (col
= 0; col
< mods
->max_keypermod
; col
++)
1993 = mods
->modifiermap
[(row
* mods
->max_keypermod
) + col
];
1995 /* Zeroes are used for filler. Skip them. */
1999 /* Are any of this keycode's keysyms a meta key? */
2003 for (code_col
= 0; code_col
< syms_per_code
; code_col
++)
2005 int sym
= syms
[((code
- min_code
) * syms_per_code
) + code_col
];
2011 dpyinfo
->meta_mod_mask
|= (1 << row
);
2016 dpyinfo
->alt_mod_mask
|= (1 << row
);
2021 dpyinfo
->hyper_mod_mask
|= (1 << row
);
2026 dpyinfo
->super_mod_mask
|= (1 << row
);
2030 /* Ignore this if it's not on the lock modifier. */
2031 if ((1 << row
) == LockMask
)
2032 dpyinfo
->shift_lock_mask
= LockMask
;
2040 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
2041 if (! dpyinfo
->meta_mod_mask
)
2043 dpyinfo
->meta_mod_mask
= dpyinfo
->alt_mod_mask
;
2044 dpyinfo
->alt_mod_mask
= 0;
2047 /* If some keys are both alt and meta,
2048 make them just meta, not alt. */
2049 if (dpyinfo
->alt_mod_mask
& dpyinfo
->meta_mod_mask
)
2051 dpyinfo
->alt_mod_mask
&= ~dpyinfo
->meta_mod_mask
;
2054 XFree ((char *) syms
);
2055 XFreeModifiermap (mods
);
2058 /* Convert between the modifier bits X uses and the modifier bits
2061 x_x_to_emacs_modifiers (dpyinfo
, state
)
2062 struct x_display_info
*dpyinfo
;
2065 return ( ((state
& (ShiftMask
| dpyinfo
->shift_lock_mask
)) ? shift_modifier
: 0)
2066 | ((state
& ControlMask
) ? ctrl_modifier
: 0)
2067 | ((state
& dpyinfo
->meta_mod_mask
) ? meta_modifier
: 0)
2068 | ((state
& dpyinfo
->alt_mod_mask
) ? alt_modifier
: 0)
2069 | ((state
& dpyinfo
->super_mod_mask
) ? super_modifier
: 0)
2070 | ((state
& dpyinfo
->hyper_mod_mask
) ? hyper_modifier
: 0));
2074 x_emacs_to_x_modifiers (dpyinfo
, state
)
2075 struct x_display_info
*dpyinfo
;
2078 return ( ((state
& alt_modifier
) ? dpyinfo
->alt_mod_mask
: 0)
2079 | ((state
& super_modifier
) ? dpyinfo
->super_mod_mask
: 0)
2080 | ((state
& hyper_modifier
) ? dpyinfo
->hyper_mod_mask
: 0)
2081 | ((state
& shift_modifier
) ? ShiftMask
: 0)
2082 | ((state
& ctrl_modifier
) ? ControlMask
: 0)
2083 | ((state
& meta_modifier
) ? dpyinfo
->meta_mod_mask
: 0));
2086 /* Convert a keysym to its name. */
2089 x_get_keysym_name (keysym
)
2095 value
= XKeysymToString (keysym
);
2101 /* Mouse clicks and mouse movement. Rah. */
2103 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
2104 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
2105 that the glyph at X, Y occupies, if BOUNDS != 0.
2106 If NOCLIP is nonzero, do not force the value into range. */
2109 pixel_to_glyph_coords (f
, pix_x
, pix_y
, x
, y
, bounds
, noclip
)
2111 register int pix_x
, pix_y
;
2112 register int *x
, *y
;
2116 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
2117 even for negative values. */
2119 pix_x
-= FONT_WIDTH ((f
)->output_data
.x
->font
) - 1;
2121 pix_y
-= (f
)->output_data
.x
->line_height
- 1;
2123 pix_x
= PIXEL_TO_CHAR_COL (f
, pix_x
);
2124 pix_y
= PIXEL_TO_CHAR_ROW (f
, pix_y
);
2128 bounds
->width
= FONT_WIDTH (f
->output_data
.x
->font
);
2129 bounds
->height
= f
->output_data
.x
->line_height
;
2130 bounds
->x
= CHAR_TO_PIXEL_COL (f
, pix_x
);
2131 bounds
->y
= CHAR_TO_PIXEL_ROW (f
, pix_y
);
2138 else if (pix_x
> FRAME_WINDOW_WIDTH (f
))
2139 pix_x
= FRAME_WINDOW_WIDTH (f
);
2143 else if (pix_y
> f
->height
)
2152 glyph_to_pixel_coords (f
, x
, y
, pix_x
, pix_y
)
2155 register int *pix_x
, *pix_y
;
2157 *pix_x
= CHAR_TO_PIXEL_COL (f
, x
);
2158 *pix_y
= CHAR_TO_PIXEL_ROW (f
, y
);
2161 /* Prepare a mouse-event in *RESULT for placement in the input queue.
2163 If the event is a button press, then note that we have grabbed
2167 construct_mouse_click (result
, event
, f
)
2168 struct input_event
*result
;
2169 XButtonEvent
*event
;
2172 /* Make the event type no_event; we'll change that when we decide
2174 result
->kind
= mouse_click
;
2175 result
->code
= event
->button
- Button1
;
2176 result
->timestamp
= event
->time
;
2177 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2179 | (event
->type
== ButtonRelease
2187 pixel_to_glyph_coords (f
, event
->x
, event
->y
, &column
, &row
, NULL
, 0);
2188 XSETFASTINT (result
->x
, column
);
2189 XSETFASTINT (result
->y
, row
);
2191 XSETINT (result
->x
, event
->x
);
2192 XSETINT (result
->y
, event
->y
);
2193 XSETFRAME (result
->frame_or_window
, f
);
2197 /* Prepare a menu-event in *RESULT for placement in the input queue. */
2200 construct_menu_click (result
, event
, f
)
2201 struct input_event
*result
;
2202 XButtonEvent
*event
;
2205 /* Make the event type no_event; we'll change that when we decide
2207 result
->kind
= mouse_click
;
2208 XSETINT (result
->code
, event
->button
- Button1
);
2209 result
->timestamp
= event
->time
;
2210 result
->modifiers
= (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
2212 | (event
->type
== ButtonRelease
2216 XSETINT (result
->x
, event
->x
);
2217 XSETINT (result
->y
, -1);
2218 XSETFRAME (result
->frame_or_window
, f
);
2221 /* Function to report a mouse movement to the mainstream Emacs code.
2222 The input handler calls this.
2224 We have received a mouse movement event, which is given in *event.
2225 If the mouse is over a different glyph than it was last time, tell
2226 the mainstream emacs code by setting mouse_moved. If not, ask for
2227 another motion event, so we can check again the next time it moves. */
2230 note_mouse_movement (frame
, event
)
2232 XMotionEvent
*event
;
2234 last_mouse_movement_time
= event
->time
;
2236 if (event
->window
!= FRAME_X_WINDOW (frame
))
2238 frame
->mouse_moved
= 1;
2239 last_mouse_scroll_bar
= Qnil
;
2241 note_mouse_highlight (frame
, -1, -1);
2244 /* Has the mouse moved off the glyph it was on at the last sighting? */
2245 else if (event
->x
< last_mouse_glyph
.x
2246 || event
->x
>= last_mouse_glyph
.x
+ last_mouse_glyph
.width
2247 || event
->y
< last_mouse_glyph
.y
2248 || event
->y
>= last_mouse_glyph
.y
+ last_mouse_glyph
.height
)
2250 frame
->mouse_moved
= 1;
2251 last_mouse_scroll_bar
= Qnil
;
2253 note_mouse_highlight (frame
, event
->x
, event
->y
);
2257 /* This is used for debugging, to turn off note_mouse_highlight. */
2258 static int disable_mouse_highlight
;
2260 /* Take proper action when the mouse has moved to position X, Y on frame F
2261 as regards highlighting characters that have mouse-face properties.
2262 Also dehighlighting chars where the mouse was before.
2263 X and Y can be negative or out of range. */
2266 note_mouse_highlight (f
, x
, y
)
2270 int row
, column
, portion
;
2271 XRectangle new_glyph
;
2275 if (disable_mouse_highlight
)
2278 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_x
= x
;
2279 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_y
= y
;
2280 FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
= f
;
2282 if (FRAME_X_DISPLAY_INFO (f
)->mouse_face_defer
)
2287 FRAME_X_DISPLAY_INFO (f
)->mouse_face_deferred_gc
= 1;
2291 /* Find out which glyph the mouse is on. */
2292 pixel_to_glyph_coords (f
, x
, y
, &column
, &row
,
2293 &new_glyph
, FRAME_X_DISPLAY_INFO (f
)->grabbed
);
2295 /* Which window is that in? */
2296 window
= window_from_coordinates (f
, column
, row
, &portion
);
2297 w
= XWINDOW (window
);
2299 /* If we were displaying active text in another window, clear that. */
2300 if (! EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
))
2301 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2303 /* Are we in a window whose display is up to date?
2304 And verify the buffer's text has not changed. */
2305 if (WINDOWP (window
) && portion
== 0 && row
>= 0 && column
>= 0
2306 && row
< FRAME_HEIGHT (f
) && column
< FRAME_WIDTH (f
)
2307 && EQ (w
->window_end_valid
, w
->buffer
)
2308 && w
->last_modified
== BUF_MODIFF (XBUFFER (w
->buffer
))
2309 && w
->last_overlay_modified
== BUF_OVERLAY_MODIFF (XBUFFER (w
->buffer
)))
2311 int *ptr
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[row
];
2314 /* Find which buffer position the mouse corresponds to. */
2315 for (i
= column
; i
>= 0; i
--)
2319 /* Is it outside the displayed active region (if any)? */
2321 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2322 else if (! (EQ (window
, FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
)
2323 && row
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2324 && row
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2325 && (row
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2326 || column
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
)
2327 && (row
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2328 || column
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2329 || FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
)))
2331 Lisp_Object mouse_face
, overlay
, position
;
2332 Lisp_Object
*overlay_vec
;
2333 int len
, noverlays
, ignor1
;
2334 struct buffer
*obuf
;
2337 /* If we get an out-of-range value, return now; avoid an error. */
2338 if (pos
> BUF_Z (XBUFFER (w
->buffer
)))
2341 /* Make the window's buffer temporarily current for
2342 overlays_at and compute_char_face. */
2343 obuf
= current_buffer
;
2344 current_buffer
= XBUFFER (w
->buffer
);
2350 /* Yes. Clear the display of the old active region, if any. */
2351 clear_mouse_face (FRAME_X_DISPLAY_INFO (f
));
2353 /* Is this char mouse-active? */
2354 XSETINT (position
, pos
);
2357 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
2359 /* Put all the overlays we want in a vector in overlay_vec.
2360 Store the length in len. */
2361 noverlays
= overlays_at (XINT (pos
), 1, &overlay_vec
, &len
,
2363 noverlays
= sort_overlays (overlay_vec
, noverlays
, w
);
2365 /* Find the highest priority overlay that has a mouse-face prop. */
2367 for (i
= 0; i
< noverlays
; i
++)
2369 mouse_face
= Foverlay_get (overlay_vec
[i
], Qmouse_face
);
2370 if (!NILP (mouse_face
))
2372 overlay
= overlay_vec
[i
];
2377 /* If no overlay applies, get a text property. */
2379 mouse_face
= Fget_text_property (position
, Qmouse_face
, w
->buffer
);
2381 /* Handle the overlay case. */
2382 if (! NILP (overlay
))
2384 /* Find the range of text around this char that
2385 should be active. */
2386 Lisp_Object before
, after
;
2389 before
= Foverlay_start (overlay
);
2390 after
= Foverlay_end (overlay
);
2391 /* Record this as the current active region. */
2392 fast_find_position (window
, XFASTINT (before
),
2393 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2394 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2395 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2396 = !fast_find_position (window
, XFASTINT (after
),
2397 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2398 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2399 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2400 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2401 = compute_char_face (f
, w
, pos
, 0, 0,
2402 &ignore
, pos
+ 1, 1);
2404 /* Display it as active. */
2405 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2407 /* Handle the text property case. */
2408 else if (! NILP (mouse_face
))
2410 /* Find the range of text around this char that
2411 should be active. */
2412 Lisp_Object before
, after
, beginning
, end
;
2415 beginning
= Fmarker_position (w
->start
);
2416 XSETINT (end
, (BUF_Z (XBUFFER (w
->buffer
))
2417 - XFASTINT (w
->window_end_pos
)));
2419 = Fprevious_single_property_change (make_number (pos
+ 1),
2421 w
->buffer
, beginning
);
2423 = Fnext_single_property_change (position
, Qmouse_face
,
2425 /* Record this as the current active region. */
2426 fast_find_position (window
, XFASTINT (before
),
2427 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
,
2428 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
);
2429 FRAME_X_DISPLAY_INFO (f
)->mouse_face_past_end
2430 = !fast_find_position (window
, XFASTINT (after
),
2431 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
,
2432 &FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
);
2433 FRAME_X_DISPLAY_INFO (f
)->mouse_face_window
= window
;
2434 FRAME_X_DISPLAY_INFO (f
)->mouse_face_face_id
2435 = compute_char_face (f
, w
, pos
, 0, 0,
2436 &ignore
, pos
+ 1, 1);
2438 /* Display it as active. */
2439 show_mouse_face (FRAME_X_DISPLAY_INFO (f
), 1);
2443 current_buffer
= obuf
;
2448 /* Find the row and column of position POS in window WINDOW.
2449 Store them in *COLUMNP and *ROWP.
2450 This assumes display in WINDOW is up to date.
2451 If POS is above start of WINDOW, return coords
2452 of start of first screen line.
2453 If POS is after end of WINDOW, return coords of end of last screen line.
2455 Value is 1 if POS is in range, 0 if it was off screen. */
2458 fast_find_position (window
, pos
, columnp
, rowp
)
2461 int *columnp
, *rowp
;
2463 struct window
*w
= XWINDOW (window
);
2464 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2467 int left
= WINDOW_LEFT_MARGIN (w
);
2469 int height
= XFASTINT (w
->height
) - ! MINI_WINDOW_P (w
);
2470 int width
= window_internal_width (w
);
2473 int maybe_next_line
= 0;
2475 /* Find the right row. */
2480 int linestart
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ i
][left
];
2481 if (linestart
> pos
)
2483 /* If the position sought is the end of the buffer,
2484 don't include the blank lines at the bottom of the window. */
2485 if (linestart
== pos
&& pos
== BUF_ZV (XBUFFER (w
->buffer
)))
2487 maybe_next_line
= 1;
2494 /* Find the right column with in it. */
2495 charstarts
= FRAME_CURRENT_GLYPHS (f
)->charstarts
[top
+ row
];
2497 for (i
= 0; i
< width
; i
++)
2499 if (charstarts
[left
+ i
] == pos
)
2502 *columnp
= i
+ left
;
2505 else if (charstarts
[left
+ i
] > pos
)
2507 else if (charstarts
[left
+ i
] > 0)
2511 /* If we're looking for the end of the buffer,
2512 and we didn't find it in the line we scanned,
2513 use the start of the following line. */
2514 if (maybe_next_line
)
2525 /* Display the active region described by mouse_face_*
2526 in its mouse-face if HL > 0, in its normal face if HL = 0. */
2529 show_mouse_face (dpyinfo
, hl
)
2530 struct x_display_info
*dpyinfo
;
2533 struct window
*w
= XWINDOW (dpyinfo
->mouse_face_window
);
2534 int width
= window_internal_width (w
);
2535 FRAME_PTR f
= XFRAME (WINDOW_FRAME (w
));
2538 int old_curs_x
= curs_x
;
2539 int old_curs_y
= curs_y
;
2541 /* Set these variables temporarily
2542 so that if we have to turn the cursor off and on again
2543 we will put it back at the same place. */
2544 curs_x
= f
->phys_cursor_x
;
2545 curs_y
= f
->phys_cursor_y
;
2546 for (i
= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
;
2547 i
<= FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
; i
++)
2549 int column
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
2550 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
2551 : WINDOW_LEFT_MARGIN (w
));
2552 int endcolumn
= (i
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
2553 ? FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
2554 : WINDOW_LEFT_MARGIN (w
) + width
);
2555 endcolumn
= min (endcolumn
, FRAME_CURRENT_GLYPHS (f
)->used
[i
]);
2557 /* If the cursor's in the text we are about to rewrite,
2558 turn the cursor off. */
2560 && curs_x
>= column
- 1
2561 && curs_x
<= endcolumn
)
2563 x_update_cursor (f
, 0);
2568 CHAR_TO_PIXEL_COL (f
, column
),
2569 CHAR_TO_PIXEL_ROW (f
, i
),
2570 FRAME_CURRENT_GLYPHS (f
)->glyphs
[i
] + column
,
2572 /* Highlight with mouse face if hl > 0. */
2573 hl
> 0 ? 3 : 0, 0, NULL
);
2576 /* If we turned the cursor off, turn it back on. */
2578 x_display_cursor (f
, 1, curs_x
, curs_y
);
2580 curs_x
= old_curs_x
;
2581 curs_y
= old_curs_y
;
2583 /* Change the mouse cursor according to the value of HL. */
2585 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2586 f
->output_data
.x
->cross_cursor
);
2588 XDefineCursor (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2589 f
->output_data
.x
->text_cursor
);
2592 /* Clear out the mouse-highlighted active region.
2593 Redraw it unhighlighted first. */
2596 clear_mouse_face (dpyinfo
)
2597 struct x_display_info
*dpyinfo
;
2599 if (! NILP (dpyinfo
->mouse_face_window
))
2600 show_mouse_face (dpyinfo
, 0);
2602 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2603 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2604 dpyinfo
->mouse_face_window
= Qnil
;
2607 /* Just discard the mouse face information for frame F, if any.
2608 This is used when the size of F is changed. */
2610 cancel_mouse_face (f
)
2614 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
2616 window
= dpyinfo
->mouse_face_window
;
2617 if (! NILP (window
) && XFRAME (XWINDOW (window
)->frame
) == f
)
2619 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
2620 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
2621 dpyinfo
->mouse_face_window
= Qnil
;
2625 static struct scroll_bar
*x_window_to_scroll_bar ();
2626 static void x_scroll_bar_report_motion ();
2628 /* Return the current position of the mouse.
2629 *fp should be a frame which indicates which display to ask about.
2631 If the mouse movement started in a scroll bar, set *fp, *bar_window,
2632 and *part to the frame, window, and scroll bar part that the mouse
2633 is over. Set *x and *y to the portion and whole of the mouse's
2634 position on the scroll bar.
2636 If the mouse movement started elsewhere, set *fp to the frame the
2637 mouse is on, *bar_window to nil, and *x and *y to the character cell
2640 Set *time to the server timestamp for the time at which the mouse
2641 was at this position.
2643 Don't store anything if we don't have a valid set of values to report.
2645 This clears the mouse_moved flag, so we can wait for the next mouse
2649 XTmouse_position (fp
, insist
, bar_window
, part
, x
, y
, time
)
2652 Lisp_Object
*bar_window
;
2653 enum scroll_bar_part
*part
;
2655 unsigned long *time
;
2661 if (! NILP (last_mouse_scroll_bar
))
2662 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
);
2668 Window dummy_window
;
2671 Lisp_Object frame
, tail
;
2673 /* Clear the mouse-moved flag for every frame on this display. */
2674 FOR_EACH_FRAME (tail
, frame
)
2675 if (FRAME_X_DISPLAY (XFRAME (frame
)) == FRAME_X_DISPLAY (*fp
))
2676 XFRAME (frame
)->mouse_moved
= 0;
2678 last_mouse_scroll_bar
= Qnil
;
2680 /* Figure out which root window we're on. */
2681 XQueryPointer (FRAME_X_DISPLAY (*fp
),
2682 DefaultRootWindow (FRAME_X_DISPLAY (*fp
)),
2684 /* The root window which contains the pointer. */
2687 /* Trash which we can't trust if the pointer is on
2688 a different screen. */
2691 /* The position on that root window. */
2694 /* More trash we can't trust. */
2697 /* Modifier keys and pointer buttons, about which
2699 (unsigned int *) &dummy
);
2701 /* Now we have a position on the root; find the innermost window
2702 containing the pointer. */
2706 int parent_x
, parent_y
;
2710 /* XTranslateCoordinates can get errors if the window
2711 structure is changing at the same time this function
2712 is running. So at least we must not crash from them. */
2714 x_catch_errors (FRAME_X_DISPLAY (*fp
));
2716 if (FRAME_X_DISPLAY_INFO (*fp
)->grabbed
&& last_mouse_frame
2717 && FRAME_LIVE_P (last_mouse_frame
))
2719 /* If mouse was grabbed on a frame, give coords for that frame
2720 even if the mouse is now outside it. */
2721 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2723 /* From-window, to-window. */
2724 root
, FRAME_X_WINDOW (last_mouse_frame
),
2726 /* From-position, to-position. */
2727 root_x
, root_y
, &win_x
, &win_y
,
2731 f1
= last_mouse_frame
;
2737 XTranslateCoordinates (FRAME_X_DISPLAY (*fp
),
2739 /* From-window, to-window. */
2742 /* From-position, to-position. */
2743 root_x
, root_y
, &win_x
, &win_y
,
2748 if (child
== None
|| child
== win
)
2756 /* Now we know that:
2757 win is the innermost window containing the pointer
2758 (XTC says it has no child containing the pointer),
2759 win_x and win_y are the pointer's position in it
2760 (XTC did this the last time through), and
2761 parent_x and parent_y are the pointer's position in win's parent.
2762 (They are what win_x and win_y were when win was child.
2763 If win is the root window, it has no parent, and
2764 parent_{x,y} are invalid, but that's okay, because we'll
2765 never use them in that case.) */
2767 /* Is win one of our frames? */
2768 f1
= x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp
), win
);
2771 if (x_had_errors_p (FRAME_X_DISPLAY (*fp
)))
2774 x_uncatch_errors (FRAME_X_DISPLAY (*fp
));
2776 /* If not, is it one of our scroll bars? */
2779 struct scroll_bar
*bar
= x_window_to_scroll_bar (win
);
2783 f1
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2789 if (f1
== 0 && insist
)
2790 f1
= selected_frame
;
2794 int ignore1
, ignore2
;
2796 /* Ok, we found a frame. Store all the values. */
2798 pixel_to_glyph_coords (f1
, win_x
, win_y
, &ignore1
, &ignore2
,
2800 FRAME_X_DISPLAY_INFO (f1
)->grabbed
2806 XSETINT (*x
, win_x
);
2807 XSETINT (*y
, win_y
);
2808 *time
= last_mouse_movement_time
;
2816 /* Scroll bar support. */
2818 /* Given an X window ID, find the struct scroll_bar which manages it.
2819 This can be called in GC, so we have to make sure to strip off mark
2821 static struct scroll_bar
*
2822 x_window_to_scroll_bar (window_id
)
2825 Lisp_Object tail
, frame
;
2827 for (tail
= Vframe_list
;
2828 XGCTYPE (tail
) == Lisp_Cons
;
2829 tail
= XCONS (tail
)->cdr
)
2831 Lisp_Object frame
, bar
, condemned
;
2833 frame
= XCONS (tail
)->car
;
2834 /* All elements of Vframe_list should be frames. */
2835 if (! GC_FRAMEP (frame
))
2838 /* Scan this frame's scroll bar list for a scroll bar with the
2840 condemned
= FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame
));
2841 for (bar
= FRAME_SCROLL_BARS (XFRAME (frame
));
2842 /* This trick allows us to search both the ordinary and
2843 condemned scroll bar lists with one loop. */
2844 ! GC_NILP (bar
) || (bar
= condemned
,
2847 bar
= XSCROLL_BAR (bar
)->next
)
2848 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)) == window_id
)
2849 return XSCROLL_BAR (bar
);
2855 /* Open a new X window to serve as a scroll bar, and return the
2856 scroll bar vector for it. */
2857 static struct scroll_bar
*
2858 x_scroll_bar_create (window
, top
, left
, width
, height
)
2859 struct window
*window
;
2860 int top
, left
, width
, height
;
2862 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
2863 struct scroll_bar
*bar
2864 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE
), Qnil
));
2869 XSetWindowAttributes a
;
2871 a
.background_pixel
= f
->output_data
.x
->background_pixel
;
2872 a
.event_mask
= (ButtonPressMask
| ButtonReleaseMask
2873 | ButtonMotionMask
| PointerMotionHintMask
2875 a
.cursor
= FRAME_X_DISPLAY_INFO (f
)->vertical_scroll_bar_cursor
;
2877 mask
= (CWBackPixel
| CWEventMask
| CWCursor
);
2882 XtSetArg (al
[ac
], XtNx
, left
); ac
++;
2883 XtSetArg (al
[ac
], XtNy
, top
); ac
++;
2884 XtSetArg (al
[ac
], XtNwidth
, width
); ac
++;
2885 XtSetArg (al
[ac
], XtNheight
, height
); ac
++;
2886 XtSetArg (al
[ac
], XtNborderWidth
, 0); ac
++;
2887 sb_widget
= XtCreateManagedWidget ("box",
2889 f
->output_data
.x
->edit_widget
, al
, ac
);
2890 SET_SCROLL_BAR_X_WINDOW
2891 (bar
, sb_widget
->core
.window
);
2893 SET_SCROLL_BAR_X_WINDOW
2895 XCreateWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
2897 /* Position and size of scroll bar. */
2898 left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
, top
,
2899 width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2, height
,
2901 /* Border width, depth, class, and visual. */
2902 0, CopyFromParent
, CopyFromParent
, CopyFromParent
,
2908 XSETWINDOW (bar
->window
, window
);
2909 XSETINT (bar
->top
, top
);
2910 XSETINT (bar
->left
, left
);
2911 XSETINT (bar
->width
, width
);
2912 XSETINT (bar
->height
, height
);
2913 XSETINT (bar
->start
, 0);
2914 XSETINT (bar
->end
, 0);
2915 bar
->dragging
= Qnil
;
2917 /* Add bar to its frame's list of scroll bars. */
2918 bar
->next
= FRAME_SCROLL_BARS (f
);
2920 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
2921 if (! NILP (bar
->next
))
2922 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
2924 XMapRaised (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
2931 /* Draw BAR's handle in the proper position.
2932 If the handle is already drawn from START to END, don't bother
2933 redrawing it, unless REBUILD is non-zero; in that case, always
2934 redraw it. (REBUILD is handy for drawing the handle after expose
2937 Normally, we want to constrain the start and end of the handle to
2938 fit inside its rectangle, but if the user is dragging the scroll bar
2939 handle, we want to let them drag it down all the way, so that the
2940 bar's top is as far down as it goes; otherwise, there's no way to
2941 move to the very end of the buffer. */
2943 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2944 struct scroll_bar
*bar
;
2948 int dragging
= ! NILP (bar
->dragging
);
2949 Window w
= SCROLL_BAR_X_WINDOW (bar
);
2950 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2951 GC gc
= f
->output_data
.x
->normal_gc
;
2953 /* If the display is already accurate, do nothing. */
2955 && start
== XINT (bar
->start
)
2956 && end
== XINT (bar
->end
))
2962 int inside_width
= VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f
, XINT (bar
->width
));
2963 int inside_height
= VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
2964 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
2966 /* Make sure the values are reasonable, and try to preserve
2967 the distance between start and end. */
2969 int length
= end
- start
;
2973 else if (start
> top_range
)
2975 end
= start
+ length
;
2979 else if (end
> top_range
&& ! dragging
)
2983 /* Store the adjusted setting in the scroll bar. */
2984 XSETINT (bar
->start
, start
);
2985 XSETINT (bar
->end
, end
);
2987 /* Clip the end position, just for display. */
2988 if (end
> top_range
)
2991 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
2992 below top positions, to make sure the handle is always at least
2993 that many pixels tall. */
2994 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2996 /* Draw the empty space above the handle. Note that we can't clear
2997 zero-height areas; that means "clear to end of window." */
2999 XClearArea (FRAME_X_DISPLAY (f
), w
,
3001 /* x, y, width, height, and exposures. */
3002 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3003 VERTICAL_SCROLL_BAR_TOP_BORDER
,
3004 inside_width
, start
,
3007 /* Draw the handle itself. */
3008 XFillRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3010 /* x, y, width, height */
3011 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3012 VERTICAL_SCROLL_BAR_TOP_BORDER
+ start
,
3013 inside_width
, end
- start
);
3016 /* Draw the empty space below the handle. Note that we can't
3017 clear zero-height areas; that means "clear to end of window." */
3018 if (end
< inside_height
)
3019 XClearArea (FRAME_X_DISPLAY (f
), w
,
3021 /* x, y, width, height, and exposures. */
3022 VERTICAL_SCROLL_BAR_LEFT_BORDER
,
3023 VERTICAL_SCROLL_BAR_TOP_BORDER
+ end
,
3024 inside_width
, inside_height
- end
,
3032 /* Move a scroll bar around on the screen, to accommodate changing
3033 window configurations. */
3035 x_scroll_bar_move (bar
, top
, left
, width
, height
)
3036 struct scroll_bar
*bar
;
3037 int top
, left
, width
, height
;
3039 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3040 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3046 unsigned int mask
= 0;
3048 wc
.x
= left
+ VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3051 wc
.width
= width
- VERTICAL_SCROLL_BAR_WIDTH_TRIM
* 2;
3054 if (left
!= XINT (bar
->left
)) mask
|= CWX
;
3055 if (top
!= XINT (bar
->top
)) mask
|= CWY
;
3056 if (width
!= XINT (bar
->width
)) mask
|= CWWidth
;
3057 if (height
!= XINT (bar
->height
)) mask
|= CWHeight
;
3060 XConfigureWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
),
3064 XSETINT (bar
->left
, left
);
3065 XSETINT (bar
->top
, top
);
3066 XSETINT (bar
->width
, width
);
3067 XSETINT (bar
->height
, height
);
3072 /* Destroy the X window for BAR, and set its Emacs window's scroll bar
3075 x_scroll_bar_remove (bar
)
3076 struct scroll_bar
*bar
;
3078 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3082 /* Destroy the window. */
3083 XDestroyWindow (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (bar
));
3085 /* Disassociate this scroll bar from its window. */
3086 XWINDOW (bar
->window
)->vertical_scroll_bar
= Qnil
;
3091 /* Set the handle of the vertical scroll bar for WINDOW to indicate
3092 that we are displaying PORTION characters out of a total of WHOLE
3093 characters, starting at POSITION. If WINDOW has no scroll bar,
3096 XTset_vertical_scroll_bar (window
, portion
, whole
, position
)
3097 struct window
*window
;
3098 int portion
, whole
, position
;
3100 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3101 int top
= XINT (window
->top
);
3102 int left
= WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window
);
3103 int height
= WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window
);
3105 /* Where should this scroll bar be, pixelwise? */
3106 int pixel_top
= CHAR_TO_PIXEL_ROW (f
, top
);
3107 int pixel_left
= CHAR_TO_PIXEL_COL (f
, left
);
3109 = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
3110 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
3111 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
3112 int pixel_height
= VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f
, height
);
3114 struct scroll_bar
*bar
;
3116 /* Does the scroll bar exist yet? */
3117 if (NILP (window
->vertical_scroll_bar
))
3118 bar
= x_scroll_bar_create (window
,
3119 pixel_top
, pixel_left
,
3120 pixel_width
, pixel_height
);
3123 /* It may just need to be moved and resized. */
3124 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3125 x_scroll_bar_move (bar
, pixel_top
, pixel_left
, pixel_width
, pixel_height
);
3128 /* Set the scroll bar's current state, unless we're currently being
3130 if (NILP (bar
->dragging
))
3132 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, pixel_height
);
3135 x_scroll_bar_set_handle (bar
, 0, top_range
, 0);
3138 int start
= ((double) position
* top_range
) / whole
;
3139 int end
= ((double) (position
+ portion
) * top_range
) / whole
;
3141 x_scroll_bar_set_handle (bar
, start
, end
, 0);
3145 XSETVECTOR (window
->vertical_scroll_bar
, bar
);
3149 /* The following three hooks are used when we're doing a thorough
3150 redisplay of the frame. We don't explicitly know which scroll bars
3151 are going to be deleted, because keeping track of when windows go
3152 away is a real pain - "Can you say set-window-configuration, boys
3153 and girls?" Instead, we just assert at the beginning of redisplay
3154 that *all* scroll bars are to be removed, and then save a scroll bar
3155 from the fiery pit when we actually redisplay its window. */
3157 /* Arrange for all scroll bars on FRAME to be removed at the next call
3158 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
3159 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
3161 XTcondemn_scroll_bars (frame
)
3164 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
3165 while (! NILP (FRAME_SCROLL_BARS (frame
)))
3168 bar
= FRAME_SCROLL_BARS (frame
);
3169 FRAME_SCROLL_BARS (frame
) = XSCROLL_BAR (bar
)->next
;
3170 XSCROLL_BAR (bar
)->next
= FRAME_CONDEMNED_SCROLL_BARS (frame
);
3171 XSCROLL_BAR (bar
)->prev
= Qnil
;
3172 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame
)))
3173 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame
))->prev
= bar
;
3174 FRAME_CONDEMNED_SCROLL_BARS (frame
) = bar
;
3178 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
3179 Note that WINDOW isn't necessarily condemned at all. */
3181 XTredeem_scroll_bar (window
)
3182 struct window
*window
;
3184 struct scroll_bar
*bar
;
3186 /* We can't redeem this window's scroll bar if it doesn't have one. */
3187 if (NILP (window
->vertical_scroll_bar
))
3190 bar
= XSCROLL_BAR (window
->vertical_scroll_bar
);
3192 /* Unlink it from the condemned list. */
3194 FRAME_PTR f
= XFRAME (WINDOW_FRAME (window
));
3196 if (NILP (bar
->prev
))
3198 /* If the prev pointer is nil, it must be the first in one of
3200 if (EQ (FRAME_SCROLL_BARS (f
), window
->vertical_scroll_bar
))
3201 /* It's not condemned. Everything's fine. */
3203 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f
),
3204 window
->vertical_scroll_bar
))
3205 FRAME_CONDEMNED_SCROLL_BARS (f
) = bar
->next
;
3207 /* If its prev pointer is nil, it must be at the front of
3208 one or the other! */
3212 XSCROLL_BAR (bar
->prev
)->next
= bar
->next
;
3214 if (! NILP (bar
->next
))
3215 XSCROLL_BAR (bar
->next
)->prev
= bar
->prev
;
3217 bar
->next
= FRAME_SCROLL_BARS (f
);
3219 XSETVECTOR (FRAME_SCROLL_BARS (f
), bar
);
3220 if (! NILP (bar
->next
))
3221 XSETVECTOR (XSCROLL_BAR (bar
->next
)->prev
, bar
);
3225 /* Remove all scroll bars on FRAME that haven't been saved since the
3226 last call to `*condemn_scroll_bars_hook'. */
3228 XTjudge_scroll_bars (f
)
3231 Lisp_Object bar
, next
;
3233 bar
= FRAME_CONDEMNED_SCROLL_BARS (f
);
3235 /* Clear out the condemned list now so we won't try to process any
3236 more events on the hapless scroll bars. */
3237 FRAME_CONDEMNED_SCROLL_BARS (f
) = Qnil
;
3239 for (; ! NILP (bar
); bar
= next
)
3241 struct scroll_bar
*b
= XSCROLL_BAR (bar
);
3243 x_scroll_bar_remove (b
);
3246 b
->next
= b
->prev
= Qnil
;
3249 /* Now there should be no references to the condemned scroll bars,
3250 and they should get garbage-collected. */
3254 /* Handle an Expose or GraphicsExpose event on a scroll bar.
3256 This may be called from a signal handler, so we have to ignore GC
3259 x_scroll_bar_expose (bar
, event
)
3260 struct scroll_bar
*bar
;
3263 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3264 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3265 GC gc
= f
->output_data
.x
->normal_gc
;
3266 int width_trim
= VERTICAL_SCROLL_BAR_WIDTH_TRIM
;
3270 x_scroll_bar_set_handle (bar
, XINT (bar
->start
), XINT (bar
->end
), 1);
3272 /* Draw a one-pixel border just inside the edges of the scroll bar. */
3273 XDrawRectangle (FRAME_X_DISPLAY (f
), w
, gc
,
3275 /* x, y, width, height */
3277 XINT (bar
->width
) - 1 - width_trim
- width_trim
,
3278 XINT (bar
->height
) - 1);
3283 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
3284 is set to something other than no_event, it is enqueued.
3286 This may be called from a signal handler, so we have to ignore GC
3289 x_scroll_bar_handle_click (bar
, event
, emacs_event
)
3290 struct scroll_bar
*bar
;
3292 struct input_event
*emacs_event
;
3294 if (! GC_WINDOWP (bar
->window
))
3297 emacs_event
->kind
= scroll_bar_click
;
3298 emacs_event
->code
= event
->xbutton
.button
- Button1
;
3299 emacs_event
->modifiers
3300 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
3301 (XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)))),
3302 event
->xbutton
.state
)
3303 | (event
->type
== ButtonRelease
3306 emacs_event
->frame_or_window
= bar
->window
;
3307 emacs_event
->timestamp
= event
->xbutton
.time
;
3309 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3311 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3313 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3314 int y
= event
->xbutton
.y
- VERTICAL_SCROLL_BAR_TOP_BORDER
;
3317 if (y
> top_range
) y
= top_range
;
3319 if (y
< XINT (bar
->start
))
3320 emacs_event
->part
= scroll_bar_above_handle
;
3321 else if (y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3322 emacs_event
->part
= scroll_bar_handle
;
3324 emacs_event
->part
= scroll_bar_below_handle
;
3326 /* Just because the user has clicked on the handle doesn't mean
3327 they want to drag it. Lisp code needs to be able to decide
3328 whether or not we're dragging. */
3330 /* If the user has just clicked on the handle, record where they're
3332 if (event
->type
== ButtonPress
3333 && emacs_event
->part
== scroll_bar_handle
)
3334 XSETINT (bar
->dragging
, y
- XINT (bar
->start
));
3337 /* If the user has released the handle, set it to its final position. */
3338 if (event
->type
== ButtonRelease
3339 && ! NILP (bar
->dragging
))
3341 int new_start
= y
- XINT (bar
->dragging
);
3342 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3344 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3345 bar
->dragging
= Qnil
;
3348 /* Same deal here as the other #if 0. */
3350 /* Clicks on the handle are always reported as occurring at the top of
3352 if (emacs_event
->part
== scroll_bar_handle
)
3353 emacs_event
->x
= bar
->start
;
3355 XSETINT (emacs_event
->x
, y
);
3357 XSETINT (emacs_event
->x
, y
);
3360 XSETINT (emacs_event
->y
, top_range
);
3364 /* Handle some mouse motion while someone is dragging the scroll bar.
3366 This may be called from a signal handler, so we have to ignore GC
3369 x_scroll_bar_note_movement (bar
, event
)
3370 struct scroll_bar
*bar
;
3373 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
3375 last_mouse_movement_time
= event
->xmotion
.time
;
3378 XSETVECTOR (last_mouse_scroll_bar
, bar
);
3380 /* If we're dragging the bar, display it. */
3381 if (! GC_NILP (bar
->dragging
))
3383 /* Where should the handle be now? */
3384 int new_start
= event
->xmotion
.y
- XINT (bar
->dragging
);
3386 if (new_start
!= XINT (bar
->start
))
3388 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
3390 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
3395 /* Return information to the user about the current position of the mouse
3396 on the scroll bar. */
3398 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
3400 Lisp_Object
*bar_window
;
3401 enum scroll_bar_part
*part
;
3403 unsigned long *time
;
3405 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
3406 Window w
= SCROLL_BAR_X_WINDOW (bar
);
3407 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
3409 Window dummy_window
;
3411 unsigned int dummy_mask
;
3415 /* Get the mouse's position relative to the scroll bar window, and
3417 if (! XQueryPointer (FRAME_X_DISPLAY (f
), w
,
3419 /* Root, child, root x and root y. */
3420 &dummy_window
, &dummy_window
,
3421 &dummy_coord
, &dummy_coord
,
3423 /* Position relative to scroll bar. */
3426 /* Mouse buttons and modifier keys. */
3432 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f
, XINT (bar
->height
));
3434 = VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
3436 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
3438 if (! NILP (bar
->dragging
))
3439 win_y
-= XINT (bar
->dragging
);
3443 if (win_y
> top_range
)
3447 *bar_window
= bar
->window
;
3449 if (! NILP (bar
->dragging
))
3450 *part
= scroll_bar_handle
;
3451 else if (win_y
< XINT (bar
->start
))
3452 *part
= scroll_bar_above_handle
;
3453 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
3454 *part
= scroll_bar_handle
;
3456 *part
= scroll_bar_below_handle
;
3458 XSETINT (*x
, win_y
);
3459 XSETINT (*y
, top_range
);
3462 last_mouse_scroll_bar
= Qnil
;
3465 *time
= last_mouse_movement_time
;
3471 /* The screen has been cleared so we may have changed foreground or
3472 background colors, and the scroll bars may need to be redrawn.
3473 Clear out the scroll bars, and ask for expose events, so we can
3476 x_scroll_bar_clear (f
)
3481 /* We can have scroll bars even if this is 0,
3482 if we just turned off scroll bar mode.
3483 But in that case we should not clear them. */
3484 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
3485 for (bar
= FRAME_SCROLL_BARS (f
); VECTORP (bar
);
3486 bar
= XSCROLL_BAR (bar
)->next
)
3487 XClearArea (FRAME_X_DISPLAY (f
), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar
)),
3491 /* This processes Expose events from the menubar specific X event
3492 loop in xmenu.c. This allows to redisplay the frame if necessary
3493 when handling menubar or popup items. */
3496 process_expose_from_menu (event
)
3500 struct x_display_info
*dpyinfo
;
3504 dpyinfo
= x_display_info_for_display (event
.xexpose
.display
);
3505 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3508 if (f
->async_visible
== 0)
3510 f
->async_visible
= 1;
3511 f
->async_iconified
= 0;
3512 SET_FRAME_GARBAGED (f
);
3516 dumprectangle (x_window_to_frame (dpyinfo
, event
.xexpose
.window
),
3517 event
.xexpose
.x
, event
.xexpose
.y
,
3518 event
.xexpose
.width
, event
.xexpose
.height
);
3523 struct scroll_bar
*bar
3524 = x_window_to_scroll_bar (event
.xexpose
.window
);
3527 x_scroll_bar_expose (bar
, &event
);
3533 /* Define a queue to save up SelectionRequest events for later handling. */
3535 struct selection_event_queue
3538 struct selection_event_queue
*next
;
3541 static struct selection_event_queue
*queue
;
3543 /* Nonzero means queue up certain events--don't process them yet. */
3544 static int x_queue_selection_requests
;
3546 /* Queue up an X event *EVENT, to be processed later. */
3549 x_queue_event (f
, event
)
3553 struct selection_event_queue
*queue_tmp
3554 = (struct selection_event_queue
*) malloc (sizeof (struct selection_event_queue
));
3556 if (queue_tmp
!= NULL
)
3558 queue_tmp
->event
= *event
;
3559 queue_tmp
->next
= queue
;
3564 /* Take all the queued events and put them back
3565 so that they get processed afresh. */
3568 x_unqueue_events (display
)
3571 while (queue
!= NULL
)
3573 struct selection_event_queue
*queue_tmp
= queue
;
3574 XPutBackEvent (display
, &queue_tmp
->event
);
3575 queue
= queue_tmp
->next
;
3576 free ((char *)queue_tmp
);
3580 /* Start queuing SelectionRequest events. */
3583 x_start_queuing_selection_requests (display
)
3586 x_queue_selection_requests
++;
3589 /* Stop queuing SelectionRequest events. */
3592 x_stop_queuing_selection_requests (display
)
3595 x_queue_selection_requests
--;
3596 x_unqueue_events (display
);
3599 /* The main X event-reading loop - XTread_socket. */
3601 /* Timestamp of enter window event. This is only used by XTread_socket,
3602 but we have to put it out here, since static variables within functions
3603 sometimes don't work. */
3604 static Time enter_timestamp
;
3606 /* This holds the state XLookupString needs to implement dead keys
3607 and other tricks known as "compose processing". _X Window System_
3608 says that a portable program can't use this, but Stephen Gildea assures
3609 me that letting the compiler initialize it to zeros will work okay.
3611 This must be defined outside of XTread_socket, for the same reasons
3612 given for enter_timestamp, above. */
3613 static XComposeStatus compose_status
;
3615 /* Record the last 100 characters stored
3616 to help debug the loss-of-chars-during-GC problem. */
3617 static int temp_index
;
3618 static short temp_buffer
[100];
3620 /* Set this to nonzero to fake an "X I/O error"
3621 on a particular display. */
3622 struct x_display_info
*XTread_socket_fake_io_error
;
3624 /* When we find no input here, we occasionally do a no-op command
3625 to verify that the X server is still running and we can still talk with it.
3626 We try all the open displays, one by one.
3627 This variable is used for cycling thru the displays. */
3628 static struct x_display_info
*next_noop_dpyinfo
;
3630 #define SET_SAVED_MENU_EVENT(size) { \
3631 if (f->output_data.x->saved_menu_event == 0) \
3632 f->output_data.x->saved_menu_event = (XEvent*)xmalloc (sizeof (XEvent)); \
3633 bcopy (&event, f->output_data.x->saved_menu_event, size); \
3634 if (numchars >= 1) \
3636 bufp->kind = menu_bar_activate_event; \
3637 XSETFRAME (bufp->frame_or_window, f); \
3643 #define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
3644 #define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
3646 /* Read events coming from the X server.
3647 This routine is called by the SIGIO handler.
3648 We return as soon as there are no more events to be read.
3650 Events representing keys are stored in buffer BUFP,
3651 which can hold up to NUMCHARS characters.
3652 We return the number of characters stored into the buffer,
3653 thus pretending to be `read'.
3655 EXPECTED is nonzero if the caller knows input is available. */
3658 XTread_socket (sd
, bufp
, numchars
, expected
)
3660 /* register */ struct input_event
*bufp
;
3661 /* register */ int numchars
;
3667 int items_pending
; /* How many items are in the X queue. */
3670 int event_found
= 0;
3673 struct x_display_info
*dpyinfo
;
3675 Status status_return
;
3678 if (interrupt_input_blocked
)
3680 interrupt_input_pending
= 1;
3684 interrupt_input_pending
= 0;
3687 /* So people can tell when we have read the available input. */
3688 input_signal_count
++;
3691 abort (); /* Don't think this happens. */
3693 /* Find the display we are supposed to read input for.
3694 It's the one communicating on descriptor SD. */
3695 for (dpyinfo
= x_display_list
; dpyinfo
; dpyinfo
= dpyinfo
->next
)
3697 #if 0 /* This ought to be unnecessary; let's verify it. */
3699 /* If available, Xlib uses FIOSNBIO to make the socket
3700 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
3701 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
3702 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
3703 fcntl (dpyinfo
->connection
, F_SETFL
, 0);
3704 #endif /* ! defined (FIOSNBIO) */
3707 #if 0 /* This code can't be made to work, with multiple displays,
3708 and appears not to be used on any system any more.
3709 Also keyboard.c doesn't turn O_NDELAY on and off
3710 for X connections. */
3713 if (! (fcntl (dpyinfo
->connection
, F_GETFL
, 0) & O_NDELAY
))
3715 extern int read_alarm_should_throw
;
3716 read_alarm_should_throw
= 1;
3717 XPeekEvent (dpyinfo
->display
, &event
);
3718 read_alarm_should_throw
= 0;
3720 #endif /* HAVE_SELECT */
3724 /* For debugging, this gives a way to fake an I/O error. */
3725 if (dpyinfo
== XTread_socket_fake_io_error
)
3727 XTread_socket_fake_io_error
= 0;
3728 x_io_error_quitter (dpyinfo
->display
);
3731 while (XPending (dpyinfo
->display
) != 0)
3733 #ifdef USE_X_TOOLKIT
3734 /* needed to raise Motif submenus */
3735 XtAppNextEvent (Xt_app_con
, &event
);
3737 XNextEvent (dpyinfo
->display
, &event
);
3741 struct frame
*f1
= x_any_window_to_frame (dpyinfo
,
3742 &event
.xclient
.window
);
3743 /* The necessity of the following line took me
3744 a full work-day to decipher from the docs!! */
3745 if (f1
!= 0 && FRAME_XIC (f1
) && XFilterEvent (&event
, None
))
3755 if (event
.xclient
.message_type
3756 == dpyinfo
->Xatom_wm_protocols
3757 && event
.xclient
.format
== 32)
3759 if (event
.xclient
.data
.l
[0]
3760 == dpyinfo
->Xatom_wm_take_focus
)
3762 f
= x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3763 /* Since we set WM_TAKE_FOCUS, we must call
3764 XSetInputFocus explicitly. But not if f is null,
3765 since that might be an event for a deleted frame. */
3767 /* Not quite sure this is needed -pd */
3769 XSetICFocus (FRAME_XIC (f
));
3772 XSetInputFocus (event
.xclient
.display
,
3773 event
.xclient
.window
,
3774 RevertToPointerRoot
,
3775 event
.xclient
.data
.l
[1]);
3776 /* Not certain about handling scroll bars here */
3778 else if (event
.xclient
.data
.l
[0]
3779 == dpyinfo
->Xatom_wm_save_yourself
)
3781 /* Save state modify the WM_COMMAND property to
3782 something which can reinstate us. This notifies
3783 the session manager, who's looking for such a
3784 PropertyNotify. Can restart processing when
3785 a keyboard or mouse event arrives. */
3788 f
= x_top_window_to_frame (dpyinfo
,
3789 event
.xclient
.window
);
3791 /* This is just so we only give real data once
3792 for a single Emacs process. */
3793 if (f
== selected_frame
)
3794 XSetCommand (FRAME_X_DISPLAY (f
),
3795 event
.xclient
.window
,
3796 initial_argv
, initial_argc
);
3798 XSetCommand (FRAME_X_DISPLAY (f
),
3799 event
.xclient
.window
,
3803 else if (event
.xclient
.data
.l
[0]
3804 == dpyinfo
->Xatom_wm_delete_window
)
3807 = x_any_window_to_frame (dpyinfo
,
3808 event
.xclient
.window
);
3815 bufp
->kind
= delete_window_event
;
3816 XSETFRAME (bufp
->frame_or_window
, f
);
3824 else if (event
.xclient
.message_type
3825 == dpyinfo
->Xatom_wm_configure_denied
)
3828 else if (event
.xclient
.message_type
3829 == dpyinfo
->Xatom_wm_window_moved
)
3833 = x_window_to_frame (dpyinfo
, event
.xclient
.window
);
3835 new_x
= event
.xclient
.data
.s
[0];
3836 new_y
= event
.xclient
.data
.s
[1];
3840 f
->output_data
.x
->left_pos
= new_x
;
3841 f
->output_data
.x
->top_pos
= new_y
;
3845 else if (event
.xclient
.message_type
3846 == dpyinfo
->Xatom_editres
)
3849 = x_any_window_to_frame (dpyinfo
, event
.xclient
.window
);
3850 _XEditResCheckMessages (f
->output_data
.x
->widget
, NULL
,
3853 #endif /* HACK_EDITRES */
3857 case SelectionNotify
:
3858 #ifdef USE_X_TOOLKIT
3859 if (! x_window_to_frame (dpyinfo
, event
.xselection
.requestor
))
3861 #endif /* not USE_X_TOOLKIT */
3862 x_handle_selection_notify (&event
);
3865 case SelectionClear
: /* Someone has grabbed ownership. */
3866 #ifdef USE_X_TOOLKIT
3867 if (! x_window_to_frame (dpyinfo
, event
.xselectionclear
.window
))
3869 #endif /* USE_X_TOOLKIT */
3871 XSelectionClearEvent
*eventp
= (XSelectionClearEvent
*) &event
;
3876 bufp
->kind
= selection_clear_event
;
3877 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3878 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3879 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3880 bufp
->frame_or_window
= Qnil
;
3888 case SelectionRequest
: /* Someone wants our selection. */
3889 #ifdef USE_X_TOOLKIT
3890 if (!x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
))
3892 #endif /* USE_X_TOOLKIT */
3893 if (x_queue_selection_requests
)
3894 x_queue_event (x_window_to_frame (dpyinfo
, event
.xselectionrequest
.owner
),
3898 XSelectionRequestEvent
*eventp
= (XSelectionRequestEvent
*) &event
;
3903 bufp
->kind
= selection_request_event
;
3904 SELECTION_EVENT_DISPLAY (bufp
) = eventp
->display
;
3905 SELECTION_EVENT_REQUESTOR (bufp
) = eventp
->requestor
;
3906 SELECTION_EVENT_SELECTION (bufp
) = eventp
->selection
;
3907 SELECTION_EVENT_TARGET (bufp
) = eventp
->target
;
3908 SELECTION_EVENT_PROPERTY (bufp
) = eventp
->property
;
3909 SELECTION_EVENT_TIME (bufp
) = eventp
->time
;
3910 bufp
->frame_or_window
= Qnil
;
3918 case PropertyNotify
:
3919 #ifdef USE_X_TOOLKIT
3920 if (!x_any_window_to_frame (dpyinfo
, event
.xproperty
.window
))
3922 #endif /* not USE_X_TOOLKIT */
3923 x_handle_property_notify (&event
);
3926 case ReparentNotify
:
3927 f
= x_top_window_to_frame (dpyinfo
, event
.xreparent
.window
);
3931 f
->output_data
.x
->parent_desc
= event
.xreparent
.parent
;
3932 x_real_positions (f
, &x
, &y
);
3933 f
->output_data
.x
->left_pos
= x
;
3934 f
->output_data
.x
->top_pos
= y
;
3939 f
= x_window_to_frame (dpyinfo
, event
.xexpose
.window
);
3942 if (f
->async_visible
== 0)
3944 f
->async_visible
= 1;
3945 f
->async_iconified
= 0;
3946 SET_FRAME_GARBAGED (f
);
3949 dumprectangle (x_window_to_frame (dpyinfo
,
3950 event
.xexpose
.window
),
3951 event
.xexpose
.x
, event
.xexpose
.y
,
3952 event
.xexpose
.width
, event
.xexpose
.height
);
3956 struct scroll_bar
*bar
3957 = x_window_to_scroll_bar (event
.xexpose
.window
);
3960 x_scroll_bar_expose (bar
, &event
);
3961 #ifdef USE_X_TOOLKIT
3964 #endif /* USE_X_TOOLKIT */
3968 case GraphicsExpose
: /* This occurs when an XCopyArea's
3969 source area was obscured or not
3971 f
= x_window_to_frame (dpyinfo
, event
.xgraphicsexpose
.drawable
);
3975 event
.xgraphicsexpose
.x
, event
.xgraphicsexpose
.y
,
3976 event
.xgraphicsexpose
.width
,
3977 event
.xgraphicsexpose
.height
);
3979 #ifdef USE_X_TOOLKIT
3982 #endif /* USE_X_TOOLKIT */
3985 case NoExpose
: /* This occurs when an XCopyArea's
3986 source area was completely
3991 f
= x_top_window_to_frame (dpyinfo
, event
.xunmap
.window
);
3992 if (f
) /* F may no longer exist if
3993 the frame was deleted. */
3995 /* While a frame is unmapped, display generation is
3996 disabled; you don't want to spend time updating a
3997 display that won't ever be seen. */
3998 f
->async_visible
= 0;
3999 /* We can't distinguish, from the event, whether the window
4000 has become iconified or invisible. So assume, if it
4001 was previously visible, than now it is iconified.
4002 We depend on x_make_frame_invisible to mark it invisible. */
4003 if (FRAME_VISIBLE_P (f
) || FRAME_ICONIFIED_P (f
))
4004 f
->async_iconified
= 1;
4006 bufp
->kind
= iconify_event
;
4007 XSETFRAME (bufp
->frame_or_window
, f
);
4015 /* We use x_top_window_to_frame because map events can come
4016 for subwindows and they don't mean that the frame is visible. */
4017 f
= x_top_window_to_frame (dpyinfo
, event
.xmap
.window
);
4020 f
->async_visible
= 1;
4021 f
->async_iconified
= 0;
4023 /* wait_reading_process_input will notice this and update
4024 the frame's display structures. */
4025 SET_FRAME_GARBAGED (f
);
4029 bufp
->kind
= deiconify_event
;
4030 XSETFRAME (bufp
->frame_or_window
, f
);
4035 else if (! NILP(Vframe_list
)
4036 && ! NILP (XCONS (Vframe_list
)->cdr
))
4037 /* Force a redisplay sooner or later
4038 to update the frame titles
4039 in case this is the second frame. */
4040 record_asynch_buffer_change ();
4044 /* Turn off processing if we become fully obscured. */
4045 case VisibilityNotify
:
4049 f
= x_any_window_to_frame (dpyinfo
, event
.xkey
.window
);
4053 KeySym keysym
, orig_keysym
;
4054 /* al%imercury@uunet.uu.net says that making this 81 instead of
4055 80 fixed a bug whereby meta chars made his Emacs hang. */
4056 unsigned char copy_buffer
[81];
4059 #if 0 /* This was how we made f10 work in Motif.
4060 The drawback is, you can't type at Emacs when the
4061 the mouse is in the menu bar. So it is better to
4062 turn off f10 in Motif and let Emacs handle it. */
4064 if (lw_window_is_in_menubar (event
.xkey
.window
,
4065 f
->output_data
.x
->menubar_widget
4068 SET_SAVED_KEY_EVENT
;
4071 #endif /* USE_MOTIF */
4075 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f
),
4076 extra_keyboard_modifiers
);
4077 modifiers
= event
.xkey
.state
;
4079 /* This will have to go some day... */
4081 /* make_lispy_event turns chars into control chars.
4082 Don't do it here because XLookupString is too eager. */
4083 event
.xkey
.state
&= ~ControlMask
;
4084 event
.xkey
.state
&= ~(dpyinfo
->meta_mod_mask
4085 | dpyinfo
->super_mod_mask
4086 | dpyinfo
->hyper_mod_mask
4087 | dpyinfo
->alt_mod_mask
);
4089 /* In case Meta is ComposeCharacter,
4090 clear its status. According to Markus Ehrnsperger
4091 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
4092 this enables ComposeCharacter to work whether or
4093 not it is combined with Meta. */
4094 if (modifiers
& dpyinfo
->meta_mod_mask
)
4095 bzero (&compose_status
, sizeof (compose_status
));
4100 nbytes
= XmbLookupString (FRAME_XIC (f
),
4101 &event
.xkey
, copy_buffer
,
4106 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4107 80, &keysym
, &compose_status
);
4109 nbytes
= XLookupString (&event
.xkey
, copy_buffer
,
4110 80, &keysym
, &compose_status
);
4113 orig_keysym
= keysym
;
4117 if (((keysym
>= XK_BackSpace
&& keysym
<= XK_Escape
)
4118 || keysym
== XK_Delete
4119 #ifdef XK_ISO_Left_Tab
4120 || (keysym
>= XK_ISO_Left_Tab
&& keysym
<= XK_ISO_Enter
)
4122 || IsCursorKey (keysym
) /* 0xff50 <= x < 0xff60 */
4123 || IsMiscFunctionKey (keysym
) /* 0xff60 <= x < VARIES */
4125 /* This recognizes the "extended function keys".
4126 It seems there's no cleaner way.
4127 Test IsModifierKey to avoid handling mode_switch
4129 || ((unsigned) (keysym
) >= XK_Select
4130 && (unsigned)(keysym
) < XK_KP_Space
)
4132 #ifdef XK_dead_circumflex
4133 || orig_keysym
== XK_dead_circumflex
4135 #ifdef XK_dead_grave
4136 || orig_keysym
== XK_dead_grave
4138 #ifdef XK_dead_tilde
4139 || orig_keysym
== XK_dead_tilde
4141 #ifdef XK_dead_diaeresis
4142 || orig_keysym
== XK_dead_diaeresis
4144 #ifdef XK_dead_macron
4145 || orig_keysym
== XK_dead_macron
4147 #ifdef XK_dead_degree
4148 || orig_keysym
== XK_dead_degree
4150 #ifdef XK_dead_acute
4151 || orig_keysym
== XK_dead_acute
4153 #ifdef XK_dead_cedilla
4154 || orig_keysym
== XK_dead_cedilla
4156 #ifdef XK_dead_breve
4157 || orig_keysym
== XK_dead_breve
4159 #ifdef XK_dead_ogonek
4160 || orig_keysym
== XK_dead_ogonek
4162 #ifdef XK_dead_caron
4163 || orig_keysym
== XK_dead_caron
4165 #ifdef XK_dead_doubleacute
4166 || orig_keysym
== XK_dead_doubleacute
4168 #ifdef XK_dead_abovedot
4169 || orig_keysym
== XK_dead_abovedot
4171 || IsKeypadKey (keysym
) /* 0xff80 <= x < 0xffbe */
4172 || IsFunctionKey (keysym
) /* 0xffbe <= x < 0xffe1 */
4173 /* Any "vendor-specific" key is ok. */
4174 || (orig_keysym
& (1 << 28)))
4175 && ! (IsModifierKey (orig_keysym
)
4177 #ifdef XK_Mode_switch
4178 || ((unsigned)(orig_keysym
) == XK_Mode_switch
)
4181 || ((unsigned)(orig_keysym
) == XK_Num_Lock
)
4183 #endif /* not HAVE_X11R5 */
4186 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4188 temp_buffer
[temp_index
++] = keysym
;
4189 bufp
->kind
= non_ascii_keystroke
;
4190 bufp
->code
= keysym
;
4191 XSETFRAME (bufp
->frame_or_window
, f
);
4193 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4195 bufp
->timestamp
= event
.xkey
.time
;
4200 else if (numchars
> nbytes
)
4204 for (i
= 0; i
< nbytes
; i
++)
4206 if (temp_index
== sizeof temp_buffer
/ sizeof (short))
4208 temp_buffer
[temp_index
++] = copy_buffer
[i
];
4209 bufp
->kind
= ascii_keystroke
;
4210 bufp
->code
= copy_buffer
[i
];
4211 XSETFRAME (bufp
->frame_or_window
, f
);
4213 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f
),
4215 bufp
->timestamp
= event
.xkey
.time
;
4230 /* Here's a possible interpretation of the whole
4231 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If you get a
4232 FocusIn event, you have to get a FocusOut event before you
4233 relinquish the focus. If you haven't received a FocusIn event,
4234 then a mere LeaveNotify is enough to free you. */
4237 f
= x_any_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4239 if (event
.xcrossing
.focus
) /* Entered Window */
4241 /* Avoid nasty pop/raise loops. */
4242 if (f
&& (!(f
->auto_raise
)
4244 || (event
.xcrossing
.time
- enter_timestamp
) > 500))
4246 x_new_focus_frame (dpyinfo
, f
);
4247 enter_timestamp
= event
.xcrossing
.time
;
4250 else if (f
== dpyinfo
->x_focus_frame
)
4251 x_new_focus_frame (dpyinfo
, 0);
4252 /* EnterNotify counts as mouse movement,
4253 so update things that depend on mouse position. */
4255 note_mouse_movement (f
, &event
.xmotion
);
4259 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4260 if (event
.xfocus
.detail
!= NotifyPointer
)
4261 dpyinfo
->x_focus_event_frame
= f
;
4263 x_new_focus_frame (dpyinfo
, f
);
4266 if (f
&& FRAME_XIC (f
))
4267 XSetICFocus (FRAME_XIC (f
));
4273 f
= x_top_window_to_frame (dpyinfo
, event
.xcrossing
.window
);
4276 if (f
== dpyinfo
->mouse_face_mouse_frame
)
4277 /* If we move outside the frame,
4278 then we're certainly no longer on any text in the frame. */
4279 clear_mouse_face (dpyinfo
);
4281 if (event
.xcrossing
.focus
)
4282 x_mouse_leave (dpyinfo
);
4285 if (f
== dpyinfo
->x_focus_event_frame
)
4286 dpyinfo
->x_focus_event_frame
= 0;
4287 if (f
== dpyinfo
->x_focus_frame
)
4288 x_new_focus_frame (dpyinfo
, 0);
4294 f
= x_any_window_to_frame (dpyinfo
, event
.xfocus
.window
);
4295 if (event
.xfocus
.detail
!= NotifyPointer
4296 && f
== dpyinfo
->x_focus_event_frame
)
4297 dpyinfo
->x_focus_event_frame
= 0;
4298 if (f
&& f
== dpyinfo
->x_focus_frame
)
4299 x_new_focus_frame (dpyinfo
, 0);
4302 if (f
&& FRAME_XIC (f
))
4303 XUnsetICFocus (FRAME_XIC (f
));
4310 if (dpyinfo
->grabbed
&& last_mouse_frame
4311 && FRAME_LIVE_P (last_mouse_frame
))
4312 f
= last_mouse_frame
;
4314 f
= x_window_to_frame (dpyinfo
, event
.xmotion
.window
);
4316 note_mouse_movement (f
, &event
.xmotion
);
4319 struct scroll_bar
*bar
4320 = x_window_to_scroll_bar (event
.xmotion
.window
);
4323 x_scroll_bar_note_movement (bar
, &event
);
4325 /* If we move outside the frame,
4326 then we're certainly no longer on any text in the frame. */
4327 clear_mouse_face (dpyinfo
);
4332 case ConfigureNotify
:
4333 f
= x_any_window_to_frame (dpyinfo
, event
.xconfigure
.window
);
4335 #ifdef USE_X_TOOLKIT
4336 && (event
.xconfigure
.window
== XtWindow (f
->output_data
.x
->widget
))
4340 #ifndef USE_X_TOOLKIT
4341 /* In the toolkit version, change_frame_size
4342 is called by the code that handles resizing
4343 of the EmacsFrame widget. */
4345 int rows
= PIXEL_TO_CHAR_HEIGHT (f
, event
.xconfigure
.height
);
4346 int columns
= PIXEL_TO_CHAR_WIDTH (f
, event
.xconfigure
.width
);
4348 /* Even if the number of character rows and columns has
4349 not changed, the font size may have changed, so we need
4350 to check the pixel dimensions as well. */
4351 if (columns
!= f
->width
4352 || rows
!= f
->height
4353 || event
.xconfigure
.width
!= f
->output_data
.x
->pixel_width
4354 || event
.xconfigure
.height
!= f
->output_data
.x
->pixel_height
)
4356 change_frame_size (f
, rows
, columns
, 0, 1);
4357 SET_FRAME_GARBAGED (f
);
4358 cancel_mouse_face (f
);
4362 /* Formerly, in the USE_X_TOOLKIT version,
4363 we did not test send_event here. */
4365 #ifndef USE_X_TOOLKIT
4366 && ! event
.xconfigure
.send_event
4373 /* Find the position of the outside upper-left corner of
4374 the window, in the root coordinate system. Don't
4375 refer to the parent window here; we may be processing
4376 this event after the window manager has changed our
4377 parent, but before we have reached the ReparentNotify. */
4378 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
4380 /* From-window, to-window. */
4381 event
.xconfigure
.window
,
4382 FRAME_X_DISPLAY_INFO (f
)->root_window
,
4384 /* From-position, to-position. */
4385 -event
.xconfigure
.border_width
,
4386 -event
.xconfigure
.border_width
,
4391 event
.xconfigure
.x
= win_x
;
4392 event
.xconfigure
.y
= win_y
;
4395 f
->output_data
.x
->pixel_width
= event
.xconfigure
.width
;
4396 f
->output_data
.x
->pixel_height
= event
.xconfigure
.height
;
4397 f
->output_data
.x
->left_pos
= event
.xconfigure
.x
;
4398 f
->output_data
.x
->top_pos
= event
.xconfigure
.y
;
4400 /* What we have now is the position of Emacs's own window.
4401 Convert that to the position of the window manager window. */
4404 x_real_positions (f
, &x
, &y
);
4405 f
->output_data
.x
->left_pos
= x
;
4406 f
->output_data
.x
->top_pos
= y
;
4407 /* Formerly we did not do this in the USE_X_TOOLKIT
4408 version. Let's try making them the same. */
4409 /* #ifndef USE_X_TOOLKIT */
4410 if (y
!= event
.xconfigure
.y
)
4412 /* Since the WM decorations come below top_pos now,
4413 we must put them below top_pos in the future. */
4414 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
4415 x_wm_set_size_hint (f
, (long) 0, 0);
4425 /* If we decide we want to generate an event to be seen
4426 by the rest of Emacs, we put it here. */
4427 struct input_event emacs_event
;
4428 emacs_event
.kind
= no_event
;
4430 bzero (&compose_status
, sizeof (compose_status
));
4432 if (dpyinfo
->grabbed
&& last_mouse_frame
4433 && FRAME_LIVE_P (last_mouse_frame
))
4434 f
= last_mouse_frame
;
4436 f
= x_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4440 if (!dpyinfo
->x_focus_frame
|| f
== dpyinfo
->x_focus_frame
)
4441 construct_mouse_click (&emacs_event
, &event
, f
);
4445 struct scroll_bar
*bar
4446 = x_window_to_scroll_bar (event
.xbutton
.window
);
4449 x_scroll_bar_handle_click (bar
, &event
, &emacs_event
);
4452 if (event
.type
== ButtonPress
)
4454 dpyinfo
->grabbed
|= (1 << event
.xbutton
.button
);
4455 last_mouse_frame
= f
;
4459 dpyinfo
->grabbed
&= ~(1 << event
.xbutton
.button
);
4462 if (numchars
>= 1 && emacs_event
.kind
!= no_event
)
4464 bcopy (&emacs_event
, bufp
, sizeof (struct input_event
));
4470 #ifdef USE_X_TOOLKIT
4471 f
= x_menubar_window_to_frame (dpyinfo
, event
.xbutton
.window
);
4472 /* For a down-event in the menu bar,
4473 don't pass it to Xt right now.
4474 Instead, save it away
4475 and we will pass it to Xt from kbd_buffer_get_event.
4476 That way, we can run some Lisp code first. */
4477 if (f
&& event
.type
== ButtonPress
4478 /* Verify the event is really within the menu bar
4479 and not just sent to it due to grabbing. */
4480 && event
.xbutton
.x
>= 0
4481 && event
.xbutton
.x
< f
->output_data
.x
->pixel_width
4482 && event
.xbutton
.y
>= 0
4483 && event
.xbutton
.y
< f
->output_data
.x
->menubar_height
4484 && event
.xbutton
.same_screen
)
4486 SET_SAVED_BUTTON_EVENT
;
4487 XSETFRAME (last_mouse_press_frame
, f
);
4489 else if (event
.type
== ButtonPress
)
4491 last_mouse_press_frame
= Qnil
;
4494 #ifdef USE_MOTIF /* This should do not harm for Lucid,
4495 but I am trying to be cautious. */
4496 else if (event
.type
== ButtonRelease
)
4498 if (!NILP (last_mouse_press_frame
))
4500 f
= XFRAME (last_mouse_press_frame
);
4501 if (f
->output_data
.x
)
4503 SET_SAVED_BUTTON_EVENT
;
4509 #endif /* USE_MOTIF */
4512 #endif /* USE_X_TOOLKIT */
4516 case CirculateNotify
:
4518 case CirculateRequest
:
4522 /* Someone has changed the keyboard mapping - update the
4524 switch (event
.xmapping
.request
)
4526 case MappingModifier
:
4527 x_find_modifier_meanings (dpyinfo
);
4528 /* This is meant to fall through. */
4529 case MappingKeyboard
:
4530 XRefreshKeyboardMapping (&event
.xmapping
);
4536 #ifdef USE_X_TOOLKIT
4538 XtDispatchEvent (&event
);
4540 #endif /* USE_X_TOOLKIT */
4546 /* On some systems, an X bug causes Emacs to get no more events
4547 when the window is destroyed. Detect that. (1994.) */
4550 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
4551 One XNOOP in 100 loops will make Emacs terminate.
4552 B. Bretthauer, 1994 */
4554 if (x_noop_count
>= 100)
4558 if (next_noop_dpyinfo
== 0)
4559 next_noop_dpyinfo
= x_display_list
;
4561 XNoOp (next_noop_dpyinfo
->display
);
4563 /* Each time we get here, cycle through the displays now open. */
4564 next_noop_dpyinfo
= next_noop_dpyinfo
->next
;
4568 /* If the focus was just given to an autoraising frame,
4570 /* ??? This ought to be able to handle more than one such frame. */
4571 if (pending_autoraise_frame
)
4573 x_raise_frame (pending_autoraise_frame
);
4574 pending_autoraise_frame
= 0;
4581 /* Drawing the cursor. */
4584 /* Draw a hollow box cursor on frame F at X, Y.
4585 Don't change the inside of the box. */
4588 x_draw_box (f
, x
, y
)
4592 int left
= CHAR_TO_PIXEL_COL (f
, x
);
4593 int top
= CHAR_TO_PIXEL_ROW (f
, y
);
4594 int width
= FONT_WIDTH (f
->output_data
.x
->font
);
4595 int height
= f
->output_data
.x
->line_height
;
4596 int c
= FAST_GLYPH_CHAR (f
->phys_cursor_glyph
);
4597 int charset
= CHAR_CHARSET (c
);
4599 /* If cursor is on a multi-column character, multiply WIDTH by columns. */
4600 width
*= (charset
== CHARSET_COMPOSITION
4601 ? cmpchar_table
[COMPOSITE_CHAR_ID (c
)]->width
4602 : CHARSET_WIDTH (charset
));
4603 XDrawRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4604 f
->output_data
.x
->cursor_gc
,
4605 left
, top
, width
- 1, height
- 1);
4608 /* Clear the cursor of frame F to background color,
4609 and mark the cursor as not shown.
4610 This is used when the text where the cursor is
4611 is about to be rewritten. */
4619 if (! FRAME_VISIBLE_P (f
)
4620 || ! f
->phys_cursor_on
)
4623 x_update_cursor (f
, 0);
4624 f
->phys_cursor_on
= 0;
4627 /* Redraw the glyph at ROW, COLUMN on frame F, in the style
4628 HIGHLIGHT. HIGHLIGHT is as defined for dumpglyphs. Return the
4632 x_draw_single_glyph (f
, row
, column
, glyph
, highlight
)
4639 CHAR_TO_PIXEL_COL (f
, column
),
4640 CHAR_TO_PIXEL_ROW (f
, row
),
4641 &glyph
, 1, highlight
, 0, NULL
);
4645 x_display_bar_cursor (f
, on
, x
, y
)
4650 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4652 /* This is pointless on invisible frames, and dangerous on garbaged
4653 frames; in the latter case, the frame may be in the midst of
4654 changing its size, and x and y may be off the frame. */
4655 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4658 if (! on
&& ! f
->phys_cursor_on
)
4661 /* If there is anything wrong with the current cursor state, remove it. */
4662 if (f
->phys_cursor_on
4664 || f
->phys_cursor_x
!= x
4665 || f
->phys_cursor_y
!= y
4666 || f
->output_data
.x
->current_cursor
!= bar_cursor
))
4668 /* Erase the cursor by redrawing the character underneath it. */
4669 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4670 f
->phys_cursor_glyph
,
4671 current_glyphs
->highlight
[f
->phys_cursor_y
]);
4672 f
->phys_cursor_on
= 0;
4675 /* If we now need a cursor in the new place or in the new form, do it so. */
4677 && (! f
->phys_cursor_on
4678 || (f
->output_data
.x
->current_cursor
!= bar_cursor
)))
4680 f
->phys_cursor_glyph
4681 = ((current_glyphs
->enable
[y
]
4682 && x
< current_glyphs
->used
[y
])
4683 ? current_glyphs
->glyphs
[y
][x
]
4685 XFillRectangle (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4686 f
->output_data
.x
->cursor_gc
,
4687 CHAR_TO_PIXEL_COL (f
, x
),
4688 CHAR_TO_PIXEL_ROW (f
, y
),
4689 max (f
->output_data
.x
->cursor_width
, 1),
4690 f
->output_data
.x
->line_height
);
4692 f
->phys_cursor_x
= x
;
4693 f
->phys_cursor_y
= y
;
4694 f
->phys_cursor_on
= 1;
4696 f
->output_data
.x
->current_cursor
= bar_cursor
;
4699 if (updating_frame
!= f
)
4700 XFlush (FRAME_X_DISPLAY (f
));
4704 /* Turn the displayed cursor of frame F on or off according to ON.
4705 If ON is nonzero, where to put the cursor is specified by X and Y. */
4708 x_display_box_cursor (f
, on
, x
, y
)
4713 struct frame_glyphs
*current_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4715 /* This is pointless on invisible frames, and dangerous on garbaged
4716 frames; in the latter case, the frame may be in the midst of
4717 changing its size, and x and y may be off the frame. */
4718 if (! FRAME_VISIBLE_P (f
) || FRAME_GARBAGED_P (f
))
4721 /* If cursor is off and we want it off, return quickly. */
4722 if (!on
&& ! f
->phys_cursor_on
)
4725 /* If cursor is currently being shown and we don't want it to be
4726 or it is in the wrong place,
4727 or we want a hollow box and it's not so, (pout!)
4729 if (f
->phys_cursor_on
4731 || f
->phys_cursor_x
!= x
4732 || f
->phys_cursor_y
!= y
4733 || (f
->output_data
.x
->current_cursor
!= hollow_box_cursor
4734 && (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
))))
4736 int mouse_face_here
= 0;
4737 struct frame_glyphs
*active_glyphs
= FRAME_CURRENT_GLYPHS (f
);
4739 /* If the cursor is in the mouse face area, redisplay that when
4740 we clear the cursor. */
4741 if (f
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_mouse_frame
4743 (f
->phys_cursor_y
> FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4744 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_row
4745 && f
->phys_cursor_x
>= FRAME_X_DISPLAY_INFO (f
)->mouse_face_beg_col
))
4747 (f
->phys_cursor_y
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4748 || (f
->phys_cursor_y
== FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_row
4749 && f
->phys_cursor_x
< FRAME_X_DISPLAY_INFO (f
)->mouse_face_end_col
))
4750 /* Don't redraw the cursor's spot in mouse face
4751 if it is at the end of a line (on a newline).
4752 The cursor appears there, but mouse highlighting does not. */
4753 && active_glyphs
->used
[f
->phys_cursor_y
] > f
->phys_cursor_x
)
4754 mouse_face_here
= 1;
4756 /* If the font is not as tall as a whole line,
4757 we must explicitly clear the line's whole height. */
4758 if (FONT_HEIGHT (f
->output_data
.x
->font
) != f
->output_data
.x
->line_height
)
4759 XClearArea (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
4760 CHAR_TO_PIXEL_COL (f
, f
->phys_cursor_x
),
4761 CHAR_TO_PIXEL_ROW (f
, f
->phys_cursor_y
),
4762 FONT_WIDTH (f
->output_data
.x
->font
),
4763 f
->output_data
.x
->line_height
, False
);
4764 /* Erase the cursor by redrawing the character underneath it. */
4765 x_draw_single_glyph (f
, f
->phys_cursor_y
, f
->phys_cursor_x
,
4766 f
->phys_cursor_glyph
,
4769 : current_glyphs
->highlight
[f
->phys_cursor_y
]));
4770 f
->phys_cursor_on
= 0;
4773 /* If we want to show a cursor,
4774 or we want a box cursor and it's not so,
4775 write it in the right place. */
4777 && (! f
->phys_cursor_on
4778 || (f
->output_data
.x
->current_cursor
!= filled_box_cursor
4779 && f
== FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)))
4781 f
->phys_cursor_glyph
4782 = ((current_glyphs
->enable
[y
]
4783 && x
< current_glyphs
->used
[y
])
4784 ? current_glyphs
->glyphs
[y
][x
]
4786 if (f
!= FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
)
4788 x_draw_box (f
, x
, y
);
4789 f
->output_data
.x
->current_cursor
= hollow_box_cursor
;
4793 x_draw_single_glyph (f
, y
, x
,
4794 f
->phys_cursor_glyph
, 2);
4795 f
->output_data
.x
->current_cursor
= filled_box_cursor
;
4798 f
->phys_cursor_x
= x
;
4799 f
->phys_cursor_y
= y
;
4800 f
->phys_cursor_on
= 1;
4803 if (updating_frame
!= f
)
4804 XFlush (FRAME_X_DISPLAY (f
));
4807 /* Display the cursor on frame F, or clear it, according to ON.
4808 Also set the frame's cursor position to X and Y. */
4810 x_display_cursor (f
, on
, x
, y
)
4817 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4818 x_display_box_cursor (f
, on
, x
, y
);
4819 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4820 x_display_bar_cursor (f
, on
, x
, y
);
4822 /* Those are the only two we have implemented! */
4828 /* Display the cursor on frame F, or clear it, according to ON.
4829 Don't change the cursor's position. */
4831 x_update_cursor (f
, on
)
4837 if (FRAME_DESIRED_CURSOR (f
) == filled_box_cursor
)
4838 x_display_box_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4839 else if (FRAME_DESIRED_CURSOR (f
) == bar_cursor
)
4840 x_display_bar_cursor (f
, on
, f
->phys_cursor_x
, f
->phys_cursor_y
);
4842 /* Those are the only two we have implemented! */
4850 /* Refresh bitmap kitchen sink icon for frame F
4851 when we get an expose event for it. */
4856 /* Normally, the window manager handles this function. */
4859 /* Make the x-window of frame F use the gnu icon bitmap. */
4862 x_bitmap_icon (f
, file
)
4866 int mask
, bitmap_id
;
4869 if (FRAME_X_WINDOW (f
) == 0)
4872 /* Free up our existing icon bitmap if any. */
4873 if (f
->output_data
.x
->icon_bitmap
> 0)
4874 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4875 f
->output_data
.x
->icon_bitmap
= 0;
4878 bitmap_id
= x_create_bitmap_from_file (f
, file
);
4881 /* Create the GNU bitmap if necessary. */
4882 if (FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
< 0)
4883 FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
4884 = x_create_bitmap_from_data (f
, gnu_bits
,
4885 gnu_width
, gnu_height
);
4887 /* The first time we create the GNU bitmap,
4888 this increments the refcount one extra time.
4889 As a result, the GNU bitmap is never freed.
4890 That way, we don't have to worry about allocating it again. */
4891 x_reference_bitmap (f
, FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
);
4893 bitmap_id
= FRAME_X_DISPLAY_INFO (f
)->icon_bitmap_id
;
4896 x_wm_set_icon_pixmap (f
, bitmap_id
);
4897 f
->output_data
.x
->icon_bitmap
= bitmap_id
;
4903 /* Make the x-window of frame F use a rectangle with text.
4904 Use ICON_NAME as the text. */
4907 x_text_icon (f
, icon_name
)
4911 if (FRAME_X_WINDOW (f
) == 0)
4917 text
.value
= (unsigned char *) icon_name
;
4918 text
.encoding
= XA_STRING
;
4920 text
.nitems
= strlen (icon_name
);
4921 #ifdef USE_X_TOOLKIT
4922 XSetWMIconName (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
4924 #else /* not USE_X_TOOLKIT */
4925 XSetWMIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), &text
);
4926 #endif /* not USE_X_TOOLKIT */
4928 #else /* not HAVE_X11R4 */
4929 XSetIconName (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
), icon_name
);
4930 #endif /* not HAVE_X11R4 */
4932 if (f
->output_data
.x
->icon_bitmap
> 0)
4933 x_destroy_bitmap (f
, f
->output_data
.x
->icon_bitmap
);
4934 f
->output_data
.x
->icon_bitmap
= 0;
4935 x_wm_set_icon_pixmap (f
, 0);
4940 /* Handling X errors. */
4942 /* Handle the loss of connection to display DISPLAY. */
4945 x_connection_closed (display
, error_message
)
4947 char *error_message
;
4949 struct x_display_info
*dpyinfo
= x_display_info_for_display (display
);
4950 Lisp_Object frame
, tail
;
4952 /* Indicate that this display is dead. */
4954 #ifdef USE_X_TOOLKIT
4955 XtCloseDisplay (display
);
4958 dpyinfo
->display
= 0;
4960 /* First delete frames whose minibuffers are on frames
4961 that are on the dead display. */
4962 FOR_EACH_FRAME (tail
, frame
)
4964 Lisp_Object minibuf_frame
;
4966 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame
))));
4967 if (FRAME_X_P (XFRAME (frame
))
4968 && FRAME_X_P (XFRAME (minibuf_frame
))
4969 && ! EQ (frame
, minibuf_frame
)
4970 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame
)) == dpyinfo
)
4971 Fdelete_frame (frame
, Qt
);
4974 /* Now delete all remaining frames on the dead display.
4975 We are now sure none of these is used as the minibuffer
4976 for another frame that we need to delete. */
4977 FOR_EACH_FRAME (tail
, frame
)
4978 if (FRAME_X_P (XFRAME (frame
))
4979 && FRAME_X_DISPLAY_INFO (XFRAME (frame
)) == dpyinfo
)
4981 /* Set this to t so that Fdelete_frame won't get confused
4982 trying to find a replacement. */
4983 FRAME_KBOARD (XFRAME (frame
))->Vdefault_minibuffer_frame
= Qt
;
4984 Fdelete_frame (frame
, Qt
);
4988 x_delete_display (dpyinfo
);
4990 if (x_display_list
== 0)
4992 fprintf (stderr
, "%s\n", error_message
);
4993 shut_down_emacs (0, 0, Qnil
);
4997 /* Ordinary stack unwind doesn't deal with these. */
4999 sigunblock (sigmask (SIGIO
));
5001 sigunblock (sigmask (SIGALRM
));
5002 TOTALLY_UNBLOCK_INPUT
;
5004 clear_waiting_for_input ();
5005 error ("%s", error_message
);
5008 /* This is the usual handler for X protocol errors.
5009 It kills all frames on the display that we got the error for.
5010 If that was the only one, it prints an error message and kills Emacs. */
5013 x_error_quitter (display
, error
)
5017 char buf
[256], buf1
[356];
5019 /* Note that there is no real way portable across R3/R4 to get the
5020 original error handler. */
5022 XGetErrorText (display
, error
->error_code
, buf
, sizeof (buf
));
5023 sprintf (buf1
, "X protocol error: %s on protocol request %d",
5024 buf
, error
->request_code
);
5025 x_connection_closed (display
, buf1
);
5028 /* This is the handler for X IO errors, always.
5029 It kills all frames on the display that we lost touch with.
5030 If that was the only one, it prints an error message and kills Emacs. */
5033 x_io_error_quitter (display
)
5038 sprintf (buf
, "Connection lost to X server `%s'", DisplayString (display
));
5039 x_connection_closed (display
, buf
);
5042 /* Handle SIGPIPE, which can happen when the connection to a server
5043 simply goes away. SIGPIPE is handled by x_connection_signal.
5044 Don't need to do anything, because the write which caused the
5045 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
5046 which will do the appropriate cleanup for us. */
5049 x_connection_signal (signalnum
) /* If we don't have an argument, */
5050 int signalnum
; /* some compilers complain in signal calls. */
5053 /* USG systems forget handlers when they are used;
5054 must reestablish each time */
5055 signal (signalnum
, x_connection_signal
);
5059 /* A buffer for storing X error messages. */
5060 static char *x_caught_error_message
;
5061 #define X_CAUGHT_ERROR_MESSAGE_SIZE 200
5063 /* An X error handler which stores the error message in
5064 x_caught_error_message. This is what's installed when
5065 x_catch_errors is in effect. */
5068 x_error_catcher (display
, error
)
5072 XGetErrorText (display
, error
->error_code
,
5073 x_caught_error_message
, X_CAUGHT_ERROR_MESSAGE_SIZE
);
5077 /* Begin trapping X errors for display DPY. Actually we trap X errors
5078 for all displays, but DPY should be the display you are actually
5081 After calling this function, X protocol errors no longer cause
5082 Emacs to exit; instead, they are recorded in x_cfc_error_message.
5084 Calling x_check_errors signals an Emacs error if an X error has
5085 occurred since the last call to x_catch_errors or x_check_errors.
5087 Calling x_uncatch_errors resumes the normal error handling. */
5089 void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
5092 x_catch_errors (dpy
)
5095 /* Make sure any errors from previous requests have been dealt with. */
5098 /* Set up the error buffer. */
5099 x_caught_error_message
5100 = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE
);
5101 x_caught_error_message
[0] = '\0';
5103 /* Install our little error handler. */
5104 XSetErrorHandler (x_error_catcher
);
5107 /* If any X protocol errors have arrived since the last call to
5108 x_catch_errors or x_check_errors, signal an Emacs error using
5109 sprintf (a buffer, FORMAT, the x error message text) as the text. */
5112 x_check_errors (dpy
, format
)
5116 /* Make sure to catch any errors incurred so far. */
5119 if (x_caught_error_message
[0])
5121 char buf
[X_CAUGHT_ERROR_MESSAGE_SIZE
+ 56];
5123 sprintf (buf
, format
, x_caught_error_message
);
5124 x_uncatch_errors (dpy
);
5129 /* Nonzero if we had any X protocol errors since we did x_catch_errors. */
5132 x_had_errors_p (dpy
)
5135 /* Make sure to catch any errors incurred so far. */
5138 return x_caught_error_message
[0] != 0;
5141 /* Stop catching X protocol errors and let them make Emacs die. */
5144 x_uncatch_errors (dpy
)
5147 xfree (x_caught_error_message
);
5148 x_caught_error_message
= 0;
5149 XSetErrorHandler (x_error_quitter
);
5153 static unsigned int x_wire_count
;
5156 fprintf (stderr
, "Lib call: %d\n", ++x_wire_count
);
5161 /* Changing the font of the frame. */
5163 /* Give frame F the font named FONTNAME as its default font, and
5164 return the full name of that font. FONTNAME may be a wildcard
5165 pattern; in that case, we choose some font that fits the pattern.
5166 The return value shows which font we chose. */
5169 x_new_font (f
, fontname
)
5171 register char *fontname
;
5173 struct font_info
*fontp
5174 = fs_load_font (f
, FRAME_X_FONT_TABLE (f
), CHARSET_ASCII
, fontname
, -1);
5179 f
->output_data
.x
->font
= (XFontStruct
*) (fontp
->font
);
5180 f
->output_data
.x
->font_baseline
5181 = (f
->output_data
.x
->font
->ascent
+ fontp
->baseline_offset
);
5182 f
->output_data
.x
->fontset
= -1;
5184 /* Compute the scroll bar width in character columns. */
5185 if (f
->scroll_bar_pixel_width
> 0)
5187 int wid
= FONT_WIDTH (f
->output_data
.x
->font
);
5188 f
->scroll_bar_cols
= (f
->scroll_bar_pixel_width
+ wid
-1) / wid
;
5191 f
->scroll_bar_cols
= 2;
5193 /* Now make the frame display the given font. */
5194 if (FRAME_X_WINDOW (f
) != 0)
5196 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->normal_gc
,
5197 f
->output_data
.x
->font
->fid
);
5198 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->reverse_gc
,
5199 f
->output_data
.x
->font
->fid
);
5200 XSetFont (FRAME_X_DISPLAY (f
), f
->output_data
.x
->cursor_gc
,
5201 f
->output_data
.x
->font
->fid
);
5203 frame_update_line_height (f
);
5204 x_set_window_size (f
, 0, f
->width
, f
->height
);
5207 /* If we are setting a new frame's font for the first time,
5208 there are no faces yet, so this font's height is the line height. */
5209 f
->output_data
.x
->line_height
= FONT_HEIGHT (f
->output_data
.x
->font
);
5211 return build_string (fontp
->full_name
);
5214 /* Give frame F the fontset named FONTSETNAME as its default font, and
5215 return the full name of that fontset. FONTSETNAME may be a wildcard
5216 pattern; in that case, we choose some fontset that fits the pattern.
5217 The return value shows which fontset we chose. */
5220 x_new_fontset (f
, fontsetname
)
5224 int fontset
= fs_query_fontset (f
, fontsetname
);
5225 struct fontset_info
*fontsetp
;
5231 fontsetp
= FRAME_FONTSET_DATA (f
)->fontset_table
[fontset
];
5233 if (!fontsetp
->fontname
[CHARSET_ASCII
])
5234 /* This fontset doesn't contain ASCII font. */
5237 result
= x_new_font (f
, fontsetp
->fontname
[CHARSET_ASCII
]);
5239 if (!STRINGP (result
))
5240 /* Can't load ASCII font. */
5243 /* Since x_new_font doesn't update any fontset information, do it now. */
5244 f
->output_data
.x
->fontset
= fontset
;
5245 fs_load_font (f
, FRAME_X_FONT_TABLE (f
),
5246 CHARSET_ASCII
, XSTRING (result
)->data
, fontset
);
5248 return build_string (fontsetname
);
5251 /* Calculate the absolute position in frame F
5252 from its current recorded position values and gravity. */
5254 x_calc_absolute_position (f
)
5258 int win_x
= 0, win_y
= 0;
5259 int flags
= f
->output_data
.x
->size_hint_flags
;
5262 #ifdef USE_X_TOOLKIT
5263 this_window
= XtWindow (f
->output_data
.x
->widget
);
5265 this_window
= FRAME_X_WINDOW (f
);
5268 /* Find the position of the outside upper-left corner of
5269 the inner window, with respect to the outer window. */
5270 if (f
->output_data
.x
->parent_desc
!= FRAME_X_DISPLAY_INFO (f
)->root_window
)
5273 XTranslateCoordinates (FRAME_X_DISPLAY (f
),
5275 /* From-window, to-window. */
5277 f
->output_data
.x
->parent_desc
,
5279 /* From-position, to-position. */
5280 0, 0, &win_x
, &win_y
,
5287 /* Treat negative positions as relative to the leftmost bottommost
5288 position that fits on the screen. */
5289 if (flags
& XNegative
)
5290 f
->output_data
.x
->left_pos
= (FRAME_X_DISPLAY_INFO (f
)->width
5291 - 2 * f
->output_data
.x
->border_width
- win_x
5293 + f
->output_data
.x
->left_pos
);
5295 if (flags
& YNegative
)
5296 /* We used to subtract f->output_data.x->menubar_height here
5297 in the toolkit case, but PIXEL_HEIGHT already includes that. */
5298 f
->output_data
.x
->top_pos
= (FRAME_X_DISPLAY_INFO (f
)->height
5299 - 2 * f
->output_data
.x
->border_width
- win_y
5301 + f
->output_data
.x
->top_pos
);
5303 /* The left_pos and top_pos
5304 are now relative to the top and left screen edges,
5305 so the flags should correspond. */
5306 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5309 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5310 to really change the position, and 0 when calling from
5311 x_make_frame_visible (in that case, XOFF and YOFF are the current
5312 position values). It is -1 when calling from x_set_frame_parameters,
5313 which means, do adjust for borders but don't change the gravity. */
5315 x_set_offset (f
, xoff
, yoff
, change_gravity
)
5317 register int xoff
, yoff
;
5320 int modified_top
, modified_left
;
5322 if (change_gravity
> 0)
5324 f
->output_data
.x
->top_pos
= yoff
;
5325 f
->output_data
.x
->left_pos
= xoff
;
5326 f
->output_data
.x
->size_hint_flags
&= ~ (XNegative
| YNegative
);
5328 f
->output_data
.x
->size_hint_flags
|= XNegative
;
5330 f
->output_data
.x
->size_hint_flags
|= YNegative
;
5331 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5333 x_calc_absolute_position (f
);
5336 x_wm_set_size_hint (f
, (long) 0, 0);
5338 /* It is a mystery why we need to add the border_width here
5339 when the frame is already visible, but experiment says we do. */
5340 modified_left
= f
->output_data
.x
->left_pos
;
5341 modified_top
= f
->output_data
.x
->top_pos
;
5342 if (change_gravity
!= 0)
5344 modified_left
+= f
->output_data
.x
->border_width
;
5345 modified_top
+= f
->output_data
.x
->border_width
;
5348 #ifdef USE_X_TOOLKIT
5349 XMoveWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
),
5350 modified_left
, modified_top
);
5351 #else /* not USE_X_TOOLKIT */
5352 XMoveWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5353 modified_left
, modified_top
);
5354 #endif /* not USE_X_TOOLKIT */
5358 /* Call this to change the size of frame F's x-window.
5359 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5360 for this size change and subsequent size changes.
5361 Otherwise we leave the window gravity unchanged. */
5363 x_set_window_size (f
, change_gravity
, cols
, rows
)
5368 int pixelwidth
, pixelheight
;
5370 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5374 #ifdef USE_X_TOOLKIT
5376 /* The x and y position of the widget is clobbered by the
5377 call to XtSetValues within EmacsFrameSetCharSize.
5378 This is a real kludge, but I don't understand Xt so I can't
5379 figure out a correct fix. Can anyone else tell me? -- rms. */
5380 int xpos
= f
->output_data
.x
->widget
->core
.x
;
5381 int ypos
= f
->output_data
.x
->widget
->core
.y
;
5382 EmacsFrameSetCharSize (f
->output_data
.x
->edit_widget
, cols
, rows
);
5383 f
->output_data
.x
->widget
->core
.x
= xpos
;
5384 f
->output_data
.x
->widget
->core
.y
= ypos
;
5387 #else /* not USE_X_TOOLKIT */
5389 check_frame_size (f
, &rows
, &cols
);
5390 f
->output_data
.x
->vertical_scroll_bar_extra
5391 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f
)
5393 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f
) > 0
5394 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f
)
5395 : (FRAME_SCROLL_BAR_COLS (f
) * FONT_WIDTH (f
->output_data
.x
->font
)));
5396 pixelwidth
= CHAR_TO_PIXEL_WIDTH (f
, cols
);
5397 pixelheight
= CHAR_TO_PIXEL_HEIGHT (f
, rows
);
5399 f
->output_data
.x
->win_gravity
= NorthWestGravity
;
5400 x_wm_set_size_hint (f
, (long) 0, 0);
5402 XSync (FRAME_X_DISPLAY (f
), False
);
5403 XResizeWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5404 pixelwidth
, pixelheight
);
5406 /* Now, strictly speaking, we can't be sure that this is accurate,
5407 but the window manager will get around to dealing with the size
5408 change request eventually, and we'll hear how it went when the
5409 ConfigureNotify event gets here.
5411 We could just not bother storing any of this information here,
5412 and let the ConfigureNotify event set everything up, but that
5413 might be kind of confusing to the lisp code, since size changes
5414 wouldn't be reported in the frame parameters until some random
5415 point in the future when the ConfigureNotify event arrives. */
5416 change_frame_size (f
, rows
, cols
, 0, 0);
5417 PIXEL_WIDTH (f
) = pixelwidth
;
5418 PIXEL_HEIGHT (f
) = pixelheight
;
5420 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5421 receive in the ConfigureNotify event; if we get what we asked
5422 for, then the event won't cause the screen to become garbaged, so
5423 we have to make sure to do it here. */
5424 SET_FRAME_GARBAGED (f
);
5426 XFlush (FRAME_X_DISPLAY (f
));
5428 #endif /* not USE_X_TOOLKIT */
5430 /* If cursor was outside the new size, mark it as off. */
5431 if (f
->phys_cursor_y
>= rows
5432 || f
->phys_cursor_x
>= cols
)
5434 f
->phys_cursor_x
= 0;
5435 f
->phys_cursor_y
= 0;
5436 f
->phys_cursor_on
= 0;
5439 /* Clear out any recollection of where the mouse highlighting was,
5440 since it might be in a place that's outside the new frame size.
5441 Actually checking whether it is outside is a pain in the neck,
5442 so don't try--just let the highlighting be done afresh with new size. */
5443 cancel_mouse_face (f
);
5448 /* Mouse warping. */
5451 x_set_mouse_position (f
, x
, y
)
5457 pix_x
= CHAR_TO_PIXEL_COL (f
, x
) + FONT_WIDTH (f
->output_data
.x
->font
) / 2;
5458 pix_y
= CHAR_TO_PIXEL_ROW (f
, y
) + f
->output_data
.x
->line_height
/ 2;
5460 if (pix_x
< 0) pix_x
= 0;
5461 if (pix_x
> PIXEL_WIDTH (f
)) pix_x
= PIXEL_WIDTH (f
);
5463 if (pix_y
< 0) pix_y
= 0;
5464 if (pix_y
> PIXEL_HEIGHT (f
)) pix_y
= PIXEL_HEIGHT (f
);
5468 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5469 0, 0, 0, 0, pix_x
, pix_y
);
5473 /* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
5476 x_set_mouse_pixel_position (f
, pix_x
, pix_y
)
5482 XWarpPointer (FRAME_X_DISPLAY (f
), None
, FRAME_X_WINDOW (f
),
5483 0, 0, 0, 0, pix_x
, pix_y
);
5487 /* focus shifting, raising and lowering. */
5489 x_focus_on_frame (f
)
5492 #if 0 /* This proves to be unpleasant. */
5496 /* I don't think that the ICCCM allows programs to do things like this
5497 without the interaction of the window manager. Whatever you end up
5498 doing with this code, do it to x_unfocus_frame too. */
5499 XSetInputFocus (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
),
5500 RevertToPointerRoot
, CurrentTime
);
5508 /* Look at the remarks in x_focus_on_frame. */
5509 if (FRAME_X_DISPLAY_INFO (f
)->x_focus_frame
== f
)
5510 XSetInputFocus (FRAME_X_DISPLAY (f
), PointerRoot
,
5511 RevertToPointerRoot
, CurrentTime
);
5515 /* Raise frame F. */
5520 if (f
->async_visible
)
5523 #ifdef USE_X_TOOLKIT
5524 XRaiseWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5525 #else /* not USE_X_TOOLKIT */
5526 XRaiseWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5527 #endif /* not USE_X_TOOLKIT */
5528 XFlush (FRAME_X_DISPLAY (f
));
5533 /* Lower frame F. */
5538 if (f
->async_visible
)
5541 #ifdef USE_X_TOOLKIT
5542 XLowerWindow (FRAME_X_DISPLAY (f
), XtWindow (f
->output_data
.x
->widget
));
5543 #else /* not USE_X_TOOLKIT */
5544 XLowerWindow (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5545 #endif /* not USE_X_TOOLKIT */
5546 XFlush (FRAME_X_DISPLAY (f
));
5552 XTframe_raise_lower (f
, raise_flag
)
5562 /* Change of visibility. */
5564 /* This tries to wait until the frame is really visible.
5565 However, if the window manager asks the user where to position
5566 the frame, this will return before the user finishes doing that.
5567 The frame will not actually be visible at that time,
5568 but it will become visible later when the window manager
5569 finishes with it. */
5571 x_make_frame_visible (f
)
5579 type
= x_icon_type (f
);
5581 x_bitmap_icon (f
, type
);
5583 if (! FRAME_VISIBLE_P (f
))
5585 /* We test FRAME_GARBAGED_P here to make sure we don't
5586 call x_set_offset a second time
5587 if we get to x_make_frame_visible a second time
5588 before the window gets really visible. */
5589 if (! FRAME_ICONIFIED_P (f
)
5590 && ! f
->output_data
.x
->asked_for_visible
)
5591 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5593 f
->output_data
.x
->asked_for_visible
= 1;
5595 if (! EQ (Vx_no_window_manager
, Qt
))
5596 x_wm_set_window_state (f
, NormalState
);
5597 #ifdef USE_X_TOOLKIT
5598 /* This was XtPopup, but that did nothing for an iconified frame. */
5599 XtMapWidget (f
->output_data
.x
->widget
);
5600 #else /* not USE_X_TOOLKIT */
5601 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5602 #endif /* not USE_X_TOOLKIT */
5603 #if 0 /* This seems to bring back scroll bars in the wrong places
5604 if the window configuration has changed. They seem
5605 to come back ok without this. */
5606 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f
))
5607 XMapSubwindows (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5611 XFlush (FRAME_X_DISPLAY (f
));
5613 /* Synchronize to ensure Emacs knows the frame is visible
5614 before we do anything else. We do this loop with input not blocked
5615 so that incoming events are handled. */
5618 int count
= input_signal_count
;
5620 /* This must come after we set COUNT. */
5623 XSETFRAME (frame
, f
);
5628 /* Once we have handled input events,
5629 we should have received the MapNotify if one is coming.
5630 So if we have not got it yet, stop looping.
5631 Some window managers make their own decisions
5632 about visibility. */
5633 if (input_signal_count
!= count
)
5635 /* Machines that do polling rather than SIGIO have been observed
5636 to go into a busy-wait here. So we'll fake an alarm signal
5637 to let the handler know that there's something to be read.
5638 We used to raise a real alarm, but it seems that the handler
5639 isn't always enabled here. This is probably a bug. */
5640 if (input_polling_used ())
5642 /* It could be confusing if a real alarm arrives while processing
5643 the fake one. Turn it off and let the handler reset it. */
5645 input_poll_signal ();
5647 /* Once we have handled input events,
5648 we should have received the MapNotify if one is coming.
5649 So if we have not got it yet, stop looping.
5650 Some window managers make their own decisions
5651 about visibility. */
5652 if (input_signal_count
!= count
)
5655 FRAME_SAMPLE_VISIBILITY (f
);
5659 /* Change from mapped state to withdrawn state. */
5661 /* Make the frame visible (mapped and not iconified). */
5663 x_make_frame_invisible (f
)
5669 #ifdef USE_X_TOOLKIT
5670 /* Use the frame's outermost window, not the one we normally draw on. */
5671 window
= XtWindow (f
->output_data
.x
->widget
);
5672 #else /* not USE_X_TOOLKIT */
5673 window
= FRAME_X_WINDOW (f
);
5674 #endif /* not USE_X_TOOLKIT */
5676 /* Don't keep the highlight on an invisible frame. */
5677 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5678 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5680 #if 0/* This might add unreliability; I don't trust it -- rms. */
5681 if (! f
->async_visible
&& ! f
->async_iconified
)
5687 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
5688 that the current position of the window is user-specified, rather than
5689 program-specified, so that when the window is mapped again, it will be
5690 placed at the same location, without forcing the user to position it
5691 by hand again (they have already done that once for this window.) */
5692 x_wm_set_size_hint (f
, (long) 0, 1);
5696 if (! XWithdrawWindow (FRAME_X_DISPLAY (f
), window
,
5697 DefaultScreen (FRAME_X_DISPLAY (f
))))
5699 UNBLOCK_INPUT_RESIGNAL
;
5700 error ("Can't notify window manager of window withdrawal");
5702 #else /* ! defined (HAVE_X11R4) */
5704 /* Tell the window manager what we're going to do. */
5705 if (! EQ (Vx_no_window_manager
, Qt
))
5709 unmap
.xunmap
.type
= UnmapNotify
;
5710 unmap
.xunmap
.window
= window
;
5711 unmap
.xunmap
.event
= DefaultRootWindow (FRAME_X_DISPLAY (f
));
5712 unmap
.xunmap
.from_configure
= False
;
5713 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5714 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5716 SubstructureRedirectMask
|SubstructureNotifyMask
,
5719 UNBLOCK_INPUT_RESIGNAL
;
5720 error ("Can't notify window manager of withdrawal");
5724 /* Unmap the window ourselves. Cheeky! */
5725 XUnmapWindow (FRAME_X_DISPLAY (f
), window
);
5726 #endif /* ! defined (HAVE_X11R4) */
5728 /* We can't distinguish this from iconification
5729 just by the event that we get from the server.
5730 So we can't win using the usual strategy of letting
5731 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5732 and synchronize with the server to make sure we agree. */
5734 FRAME_ICONIFIED_P (f
) = 0;
5735 f
->async_visible
= 0;
5736 f
->async_iconified
= 0;
5743 /* Change window state from mapped to iconified. */
5752 /* Don't keep the highlight on an invisible frame. */
5753 if (FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
== f
)
5754 FRAME_X_DISPLAY_INFO (f
)->x_highlight_frame
= 0;
5756 if (f
->async_iconified
)
5761 FRAME_SAMPLE_VISIBILITY (f
);
5763 type
= x_icon_type (f
);
5765 x_bitmap_icon (f
, type
);
5767 #ifdef USE_X_TOOLKIT
5769 if (! FRAME_VISIBLE_P (f
))
5771 if (! EQ (Vx_no_window_manager
, Qt
))
5772 x_wm_set_window_state (f
, IconicState
);
5773 /* This was XtPopup, but that did nothing for an iconified frame. */
5774 XtMapWidget (f
->output_data
.x
->widget
);
5775 /* The server won't give us any event to indicate
5776 that an invisible frame was changed to an icon,
5777 so we have to record it here. */
5780 f
->async_iconified
= 1;
5781 f
->async_visible
= 0;
5786 result
= XIconifyWindow (FRAME_X_DISPLAY (f
),
5787 XtWindow (f
->output_data
.x
->widget
),
5788 DefaultScreen (FRAME_X_DISPLAY (f
)));
5792 error ("Can't notify window manager of iconification");
5794 f
->async_iconified
= 1;
5795 f
->async_visible
= 0;
5799 XFlush (FRAME_X_DISPLAY (f
));
5801 #else /* not USE_X_TOOLKIT */
5803 /* Make sure the X server knows where the window should be positioned,
5804 in case the user deiconifies with the window manager. */
5805 if (! FRAME_VISIBLE_P (f
) && !FRAME_ICONIFIED_P (f
))
5806 x_set_offset (f
, f
->output_data
.x
->left_pos
, f
->output_data
.x
->top_pos
, 0);
5808 /* Since we don't know which revision of X we're running, we'll use both
5809 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
5811 /* X11R4: send a ClientMessage to the window manager using the
5812 WM_CHANGE_STATE type. */
5816 message
.xclient
.window
= FRAME_X_WINDOW (f
);
5817 message
.xclient
.type
= ClientMessage
;
5818 message
.xclient
.message_type
= FRAME_X_DISPLAY_INFO (f
)->Xatom_wm_change_state
;
5819 message
.xclient
.format
= 32;
5820 message
.xclient
.data
.l
[0] = IconicState
;
5822 if (! XSendEvent (FRAME_X_DISPLAY (f
),
5823 DefaultRootWindow (FRAME_X_DISPLAY (f
)),
5825 SubstructureRedirectMask
| SubstructureNotifyMask
,
5828 UNBLOCK_INPUT_RESIGNAL
;
5829 error ("Can't notify window manager of iconification");
5833 /* X11R3: set the initial_state field of the window manager hints to
5835 x_wm_set_window_state (f
, IconicState
);
5837 if (!FRAME_VISIBLE_P (f
))
5839 /* If the frame was withdrawn, before, we must map it. */
5840 XMapRaised (FRAME_X_DISPLAY (f
), FRAME_X_WINDOW (f
));
5843 f
->async_iconified
= 1;
5844 f
->async_visible
= 0;
5846 XFlush (FRAME_X_DISPLAY (f
));
5848 #endif /* not USE_X_TOOLKIT */
5851 /* Destroy the X window of frame F. */
5853 x_destroy_window (f
)
5856 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
5860 /* If a display connection is dead, don't try sending more
5861 commands to the X server. */
5862 if (dpyinfo
->display
!= 0)
5864 if (f
->output_data
.x
->icon_desc
!= 0)
5865 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->icon_desc
);
5869 XDestroyIC (FRAME_XIC (f
));
5870 #if ! defined (SOLARIS2) || defined (HAVE_X11R6)
5871 /* This line causes crashes on Solaris with Openwin,
5872 due to an apparent bug in XCloseIM.
5873 X11R6 seems not to have the bug. */
5874 XCloseIM (FRAME_XIM (f
));
5878 XDestroyWindow (FRAME_X_DISPLAY (f
), f
->output_data
.x
->window_desc
);
5879 #ifdef USE_X_TOOLKIT
5880 XtDestroyWidget (f
->output_data
.x
->widget
);
5881 free_frame_menubar (f
);
5882 #endif /* USE_X_TOOLKIT */
5884 free_frame_faces (f
);
5885 XFlush (FRAME_X_DISPLAY (f
));
5888 xfree (f
->output_data
.x
);
5889 f
->output_data
.x
= 0;
5890 if (f
== dpyinfo
->x_focus_frame
)
5891 dpyinfo
->x_focus_frame
= 0;
5892 if (f
== dpyinfo
->x_focus_event_frame
)
5893 dpyinfo
->x_focus_event_frame
= 0;
5894 if (f
== dpyinfo
->x_highlight_frame
)
5895 dpyinfo
->x_highlight_frame
= 0;
5897 dpyinfo
->reference_count
--;
5899 if (f
== dpyinfo
->mouse_face_mouse_frame
)
5901 dpyinfo
->mouse_face_beg_row
5902 = dpyinfo
->mouse_face_beg_col
= -1;
5903 dpyinfo
->mouse_face_end_row
5904 = dpyinfo
->mouse_face_end_col
= -1;
5905 dpyinfo
->mouse_face_window
= Qnil
;
5911 /* Setting window manager hints. */
5913 /* Set the normal size hints for the window manager, for frame F.
5914 FLAGS is the flags word to use--or 0 meaning preserve the flags
5915 that the window now has.
5916 If USER_POSITION is nonzero, we set the USPosition
5917 flag (this is useful when FLAGS is 0). */
5919 x_wm_set_size_hint (f
, flags
, user_position
)
5924 XSizeHints size_hints
;
5926 #ifdef USE_X_TOOLKIT
5929 Dimension widget_width
, widget_height
;
5930 Window window
= XtWindow (f
->output_data
.x
->widget
);
5931 #else /* not USE_X_TOOLKIT */
5932 Window window
= FRAME_X_WINDOW (f
);
5933 #endif /* not USE_X_TOOLKIT */
5935 /* Setting PMaxSize caused various problems. */
5936 size_hints
.flags
= PResizeInc
| PMinSize
/* | PMaxSize */;
5938 flexlines
= f
->height
;
5940 size_hints
.x
= f
->output_data
.x
->left_pos
;
5941 size_hints
.y
= f
->output_data
.x
->top_pos
;
5943 #ifdef USE_X_TOOLKIT
5944 XtSetArg (al
[ac
], XtNwidth
, &widget_width
); ac
++;
5945 XtSetArg (al
[ac
], XtNheight
, &widget_height
); ac
++;
5946 XtGetValues (f
->output_data
.x
->widget
, al
, ac
);
5947 size_hints
.height
= widget_height
;
5948 size_hints
.width
= widget_width
;
5949 #else /* not USE_X_TOOLKIT */
5950 size_hints
.height
= PIXEL_HEIGHT (f
);
5951 size_hints
.width
= PIXEL_WIDTH (f
);
5952 #endif /* not USE_X_TOOLKIT */
5954 size_hints
.width_inc
= FONT_WIDTH (f
->output_data
.x
->font
);
5955 size_hints
.height_inc
= f
->output_data
.x
->line_height
;
5956 size_hints
.max_width
5957 = FRAME_X_DISPLAY_INFO (f
)->width
- CHAR_TO_PIXEL_WIDTH (f
, 0);
5958 size_hints
.max_height
5959 = FRAME_X_DISPLAY_INFO (f
)->height
- CHAR_TO_PIXEL_HEIGHT (f
, 0);
5961 /* Calculate the base and minimum sizes.
5963 (When we use the X toolkit, we don't do it here.
5964 Instead we copy the values that the widgets are using, below.) */
5965 #ifndef USE_X_TOOLKIT
5967 int base_width
, base_height
;
5968 int min_rows
= 0, min_cols
= 0;
5970 base_width
= CHAR_TO_PIXEL_WIDTH (f
, 0);
5971 base_height
= CHAR_TO_PIXEL_HEIGHT (f
, 0);
5973 check_frame_size (f
, &min_rows
, &min_cols
);
5975 /* The window manager uses the base width hints to calculate the
5976 current number of rows and columns in the frame while
5977 resizing; min_width and min_height aren't useful for this
5978 purpose, since they might not give the dimensions for a
5979 zero-row, zero-column frame.
5981 We use the base_width and base_height members if we have
5982 them; otherwise, we set the min_width and min_height members
5983 to the size for a zero x zero frame. */
5986 size_hints
.flags
|= PBaseSize
;
5987 size_hints
.base_width
= base_width
;
5988 size_hints
.base_height
= base_height
;
5989 size_hints
.min_width
= base_width
+ min_cols
* size_hints
.width_inc
;
5990 size_hints
.min_height
= base_height
+ min_rows
* size_hints
.height_inc
;
5992 size_hints
.min_width
= base_width
;
5993 size_hints
.min_height
= base_height
;
5997 /* If we don't need the old flags, we don't need the old hint at all. */
6000 size_hints
.flags
|= flags
;
6003 #endif /* not USE_X_TOOLKIT */
6006 XSizeHints hints
; /* Sometimes I hate X Windows... */
6007 long supplied_return
;
6011 value
= XGetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
,
6014 value
= XGetNormalHints (FRAME_X_DISPLAY (f
), window
, &hints
);
6017 #ifdef USE_X_TOOLKIT
6018 size_hints
.base_height
= hints
.base_height
;
6019 size_hints
.base_width
= hints
.base_width
;
6020 size_hints
.min_height
= hints
.min_height
;
6021 size_hints
.min_width
= hints
.min_width
;
6025 size_hints
.flags
|= flags
;
6030 if (hints
.flags
& PSize
)
6031 size_hints
.flags
|= PSize
;
6032 if (hints
.flags
& PPosition
)
6033 size_hints
.flags
|= PPosition
;
6034 if (hints
.flags
& USPosition
)
6035 size_hints
.flags
|= USPosition
;
6036 if (hints
.flags
& USSize
)
6037 size_hints
.flags
|= USSize
;
6044 size_hints
.win_gravity
= f
->output_data
.x
->win_gravity
;
6045 size_hints
.flags
|= PWinGravity
;
6049 size_hints
.flags
&= ~ PPosition
;
6050 size_hints
.flags
|= USPosition
;
6052 #endif /* PWinGravity */
6055 XSetWMNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6057 XSetNormalHints (FRAME_X_DISPLAY (f
), window
, &size_hints
);
6061 /* Used for IconicState or NormalState */
6062 x_wm_set_window_state (f
, state
)
6066 #ifdef USE_X_TOOLKIT
6069 XtSetArg (al
[0], XtNinitialState
, state
);
6070 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6071 #else /* not USE_X_TOOLKIT */
6072 Window window
= FRAME_X_WINDOW (f
);
6074 f
->output_data
.x
->wm_hints
.flags
|= StateHint
;
6075 f
->output_data
.x
->wm_hints
.initial_state
= state
;
6077 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6078 #endif /* not USE_X_TOOLKIT */
6081 x_wm_set_icon_pixmap (f
, pixmap_id
)
6087 #ifdef USE_X_TOOLKIT
6088 Window window
= XtWindow (f
->output_data
.x
->widget
);
6090 Window window
= FRAME_X_WINDOW (f
);
6095 icon_pixmap
= x_bitmap_pixmap (f
, pixmap_id
);
6096 f
->output_data
.x
->wm_hints
.icon_pixmap
= icon_pixmap
;
6100 /* It seems there is no way to turn off use of an icon pixmap.
6101 The following line does it, only if no icon has yet been created,
6102 for some window managers. But with mwm it crashes.
6103 Some people say it should clear the IconPixmapHint bit in this case,
6104 but that doesn't work, and the X consortium said it isn't the
6105 right thing at all. Since there is no way to win,
6106 best to explicitly give up. */
6108 f
->output_data
.x
->wm_hints
.icon_pixmap
= None
;
6114 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
6118 XtSetArg (al
[0], XtNiconPixmap
, icon_pixmap
);
6119 XtSetValues (f
->output_data
.x
->widget
, al
, 1);
6122 #else /* not USE_X_TOOLKIT */
6124 f
->output_data
.x
->wm_hints
.flags
|= IconPixmapHint
;
6125 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6127 #endif /* not USE_X_TOOLKIT */
6130 x_wm_set_icon_position (f
, icon_x
, icon_y
)
6134 #ifdef USE_X_TOOLKIT
6135 Window window
= XtWindow (f
->output_data
.x
->widget
);
6137 Window window
= FRAME_X_WINDOW (f
);
6140 f
->output_data
.x
->wm_hints
.flags
|= IconPositionHint
;
6141 f
->output_data
.x
->wm_hints
.icon_x
= icon_x
;
6142 f
->output_data
.x
->wm_hints
.icon_y
= icon_y
;
6144 XSetWMHints (FRAME_X_DISPLAY (f
), window
, &f
->output_data
.x
->wm_hints
);
6148 /* Interface to fontset handler. */
6150 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
6152 x_get_font_info (f
, font_idx
)
6156 return (FRAME_X_FONT_TABLE (f
) + font_idx
);
6160 /* Return a list of names of available fonts matching PATTERN on frame
6161 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
6162 to be listed. Frame F NULL means we have not yet created any
6163 frame on X, and consult the first display in x_display_list.
6164 MAXNAMES sets a limit on how many fonts to match. */
6167 x_list_fonts (f
, pattern
, size
, maxnames
)
6169 Lisp_Object pattern
;
6173 Lisp_Object list
, patterns
= Qnil
, newlist
= Qnil
, key
, tem
, second_best
;
6174 Display
*dpy
= f
!= NULL
? FRAME_X_DISPLAY (f
) : x_display_list
->display
;
6176 for (list
= Valternative_fontname_alist
; CONSP (list
);
6177 list
= XCONS (list
)->cdr
)
6179 tem
= XCONS (list
)->car
;
6181 && STRINGP (XCONS (tem
)->car
)
6182 && !NILP (Fstring_equal (XCONS (tem
)->car
, pattern
)))
6184 patterns
= XCONS (tem
)->cdr
;
6189 for (patterns
= Fcons (pattern
, patterns
); CONSP (patterns
);
6190 patterns
= XCONS (patterns
)->cdr
, pattern
= XCONS (patterns
)->car
)
6195 /* See if we cached the result for this particular query. */
6196 if (f
&& (tem
= XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
,
6197 key
= Fcons (pattern
, make_number (maxnames
)),
6198 !NILP (list
= Fassoc (key
, tem
))))
6200 list
= Fcdr_safe (list
);
6201 /* We have a cashed list. Don't have to get the list again. */
6205 /* At first, put PATTERN in the cache. */
6207 names
= XListFonts (dpy
, XSTRING (pattern
)->data
, maxnames
, &num_fonts
);
6214 /* Make a list of all the fonts we got back.
6215 Store that in the font cache for the display. */
6216 for (i
= 0; i
< num_fonts
; i
++)
6219 int average_width
= -1, dashes
= 0, width
= 0;
6221 /* Count the number of dashes in NAMES[I]. If there are
6222 14 dashes, and the field value following 12th dash
6223 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
6224 is usually too ugly to be used for editing. Let's
6230 if (dashes
== 7) /* PIXEL_SIZE field */
6232 else if (dashes
== 12) /* AVERAGE_WIDTH field */
6233 average_width
= atoi (p
);
6235 if (dashes
< 14 || average_width
!= 0)
6237 tem
= build_string (names
[i
]);
6238 if (NILP (Fassoc (tem
, list
)))
6240 if (STRINGP (Vx_pixel_size_width_font_regexp
)
6241 && (fast_string_match_ignore_case
6242 (Vx_pixel_size_width_font_regexp
, names
[i
])
6244 /* We can set the value of PIXEL_SIZE to the
6245 width of this font. */
6246 list
= Fcons (Fcons (tem
, make_number (width
)), list
);
6248 /* For the moment, width is not known. */
6249 list
= Fcons (Fcons (tem
, Qnil
), list
);
6253 XFreeFontNames (names
);
6256 /* Now store the result in the cache. */
6258 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
6259 = Fcons (Fcons (key
, list
),
6260 XCONS (FRAME_X_DISPLAY_INFO (f
)->name_list_element
)->cdr
);
6263 if (NILP (list
)) continue; /* Try the remaining alternatives. */
6265 newlist
= second_best
= Qnil
;
6266 /* Make a list of the fonts that have the right width. */
6267 for (; CONSP (list
); list
= XCONS (list
)->cdr
)
6269 tem
= XCONS (list
)->car
;
6271 if (!CONSP (tem
) || NILP (XCONS (tem
)->car
))
6275 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6279 if (!INTEGERP (XCONS (tem
)->cdr
))
6281 /* Since we have not yet known the size of this font, we
6282 must try slow function call XLoadQueryFont. */
6283 XFontStruct
*thisinfo
;
6286 thisinfo
= XLoadQueryFont (dpy
,
6287 XSTRING (XCONS (tem
)->car
)->data
);
6292 XCONS (tem
)->cdr
= make_number (thisinfo
->max_bounds
.width
);
6293 XFreeFont (dpy
, thisinfo
);
6296 /* For unknown reason, the previous call of XListFont had
6297 retruned a font which can't be opened. Record the size
6298 as 0 not to try to open it again. */
6299 XCONS (tem
)->cdr
= make_number (0);
6301 if (XINT (XCONS (tem
)->cdr
) == size
)
6302 newlist
= Fcons (XCONS (tem
)->car
, newlist
);
6303 else if (NILP (second_best
))
6305 else if (XINT (XCONS (tem
)->cdr
) < size
)
6307 if (XINT (XCONS (second_best
)->cdr
) > size
6308 || XINT (XCONS (second_best
)->cdr
) < XINT (XCONS (tem
)->cdr
))
6313 if (XINT (XCONS (second_best
)->cdr
) > size
6314 && XINT (XCONS (second_best
)->cdr
) > XINT (XCONS (tem
)->cdr
))
6318 if (!NILP (newlist
))
6320 else if (!NILP (second_best
))
6322 newlist
= Fcons (XCONS (second_best
)->car
, Qnil
);
6330 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6331 pointer to the structure font_info while allocating it dynamically.
6332 If SIZE is 0, load any size of font.
6333 If loading is failed, return NULL. */
6336 x_load_font (f
, fontname
, size
)
6338 register char *fontname
;
6341 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6342 Lisp_Object font_names
;
6344 /* Get a list of all the fonts that match this name. Once we
6345 have a list of matching fonts, we compare them against the fonts
6346 we already have by comparing names. */
6347 font_names
= x_list_fonts (f
, build_string (fontname
), size
, 256);
6349 if (!NILP (font_names
))
6354 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6355 for (tail
= font_names
; CONSP (tail
); tail
= XCONS (tail
)->cdr
)
6356 if (!strcmp (dpyinfo
->font_table
[i
].name
,
6357 XSTRING (XCONS (tail
)->car
)->data
)
6358 || !strcmp (dpyinfo
->font_table
[i
].full_name
,
6359 XSTRING (XCONS (tail
)->car
)->data
))
6360 return (dpyinfo
->font_table
+ i
);
6363 /* Load the font and add it to the table. */
6367 struct font_info
*fontp
;
6368 unsigned long value
;
6370 if (!NILP (font_names
))
6371 fontname
= XSTRING (XCONS (font_names
)->car
)->data
;
6374 font
= (XFontStruct
*) XLoadQueryFont (FRAME_X_DISPLAY (f
), fontname
);
6379 /* Do we need to create the table? */
6380 if (dpyinfo
->font_table_size
== 0)
6382 dpyinfo
->font_table_size
= 16;
6384 = (struct font_info
*) xmalloc (dpyinfo
->font_table_size
6385 * sizeof (struct font_info
));
6387 /* Do we need to grow the table? */
6388 else if (dpyinfo
->n_fonts
6389 >= dpyinfo
->font_table_size
)
6391 dpyinfo
->font_table_size
*= 2;
6393 = (struct font_info
*) xrealloc (dpyinfo
->font_table
,
6394 (dpyinfo
->font_table_size
6395 * sizeof (struct font_info
)));
6398 fontp
= dpyinfo
->font_table
+ dpyinfo
->n_fonts
;
6400 /* Now fill in the slots of *FONTP. */
6403 fontp
->font_idx
= dpyinfo
->n_fonts
;
6404 fontp
->name
= (char *) xmalloc (strlen (fontname
) + 1);
6405 bcopy (fontname
, fontp
->name
, strlen (fontname
) + 1);
6407 /* Try to get the full name of FONT. Put it in FULL_NAME. */
6409 if (XGetFontProperty (font
, XA_FONT
, &value
))
6411 char *name
= (char *) XGetAtomName (FRAME_X_DISPLAY (f
), (Atom
) value
);
6415 /* Count the number of dashes in the "full name".
6416 If it is too few, this isn't really the font's full name,
6418 In X11R4, the fonts did not come with their canonical names
6429 full_name
= (char *) xmalloc (p
- name
+ 1);
6430 bcopy (name
, full_name
, p
- name
+ 1);
6437 fontp
->full_name
= full_name
;
6439 fontp
->full_name
= fontp
->name
;
6441 fontp
->size
= font
->max_bounds
.width
;
6442 fontp
->height
= font
->ascent
+ font
->descent
;
6444 /* The slot `encoding' specifies how to map a character
6445 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6446 the font code-points (0x20..0x7F, 0xA0..0xFF, 0x2020..0x7F7F,
6447 0xA0A0..0xFFFF, 0x20A0..0x7FFF, or 0xA020..0xFF7F). For the
6448 moment, we don't know which charset uses this font. So, we set
6449 informatoin in fontp->encoding[1] which is never used by any
6450 charset. If mapping can't be decided, set -1. */
6452 = (font
->max_byte1
== 0
6454 ? (font
->min_char_or_byte2
< 0x80
6455 ? (font
->max_char_or_byte2
< 0x80
6456 ? 0 /* 0x20..0x7F */
6457 : -1) /* 0x20..0xFF (can't decide) */
6458 : 1) /* 0xA0..0xFF */
6460 : (font
->min_byte1
< 0x80
6461 ? (font
->max_byte1
< 0x80
6462 ? (font
->min_char_or_byte2
< 0x80
6463 ? (font
->max_char_or_byte2
< 0x80
6464 ? 0 /* 0x2020..0x7F7F */
6465 : -1) /* 0x2020..0x7FFF (can't decide) */
6466 : 3) /* 0x20A0..0x7FFF */
6467 : -1) /* 0x20??..0xA0?? (can't decide) */
6468 : (font
->min_char_or_byte2
< 0x80
6469 ? (font
->max_char_or_byte2
< 0x80
6470 ? 2 /* 0xA020..0xFF7F */
6471 : -1) /* 0xA020..0xFFFF (can't decide) */
6472 : 1))); /* 0xA0A0..0xFFFF */
6474 fontp
->baseline_offset
6475 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_BASELINE_OFFSET
, &value
)
6476 ? (long) value
: 0);
6477 fontp
->relative_compose
6478 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
, &value
)
6479 ? (long) value
: 0);
6480 fontp
->default_ascent
6481 = (XGetFontProperty (font
, dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
, &value
)
6482 ? (long) value
: 0);
6491 /* Return a pointer to struct font_info of a font named FONTNAME for frame F.
6492 If no such font is loaded, return NULL. */
6494 x_query_font (f
, fontname
)
6496 register char *fontname
;
6498 struct x_display_info
*dpyinfo
= FRAME_X_DISPLAY_INFO (f
);
6501 for (i
= 0; i
< dpyinfo
->n_fonts
; i
++)
6502 if (!strcmp (dpyinfo
->font_table
[i
].name
, fontname
)
6503 || !strcmp (dpyinfo
->font_table
[i
].full_name
, fontname
))
6504 return (dpyinfo
->font_table
+ i
);
6509 /* Initialization. */
6511 #ifdef USE_X_TOOLKIT
6512 static XrmOptionDescRec emacs_options
[] = {
6513 {"-geometry", ".geometry", XrmoptionSepArg
, NULL
},
6514 {"-iconic", ".iconic", XrmoptionNoArg
, (XtPointer
) "yes"},
6516 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
6517 XrmoptionSepArg
, NULL
},
6518 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg
, NULL
},
6520 {"-T", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6521 {"-wn", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6522 {"-title", "*EmacsShell.title", XrmoptionSepArg
, (XtPointer
) NULL
},
6523 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6524 {"-in", "*EmacsShell.iconName", XrmoptionSepArg
, (XtPointer
) NULL
},
6525 {"-mc", "*pointerColor", XrmoptionSepArg
, (XtPointer
) NULL
},
6526 {"-cr", "*cursorColor", XrmoptionSepArg
, (XtPointer
) NULL
}
6528 #endif /* USE_X_TOOLKIT */
6530 static int x_initialized
;
6533 /* Test whether two display-name strings agree up to the dot that separates
6534 the screen number from the server number. */
6536 same_x_server (name1
, name2
)
6537 char *name1
, *name2
;
6540 for (; *name1
!= '\0' && *name1
== *name2
; name1
++, name2
++)
6544 if (seen_colon
&& *name1
== '.')
6548 && (*name1
== '.' || *name1
== '\0')
6549 && (*name2
== '.' || *name2
== '\0'));
6553 struct x_display_info
*
6554 x_term_init (display_name
, xrm_option
, resource_name
)
6555 Lisp_Object display_name
;
6557 char *resource_name
;
6563 struct x_display_info
*dpyinfo
;
6575 setlocale (LC_ALL
, "");
6576 /* In case we just overrode what init_lread did, redo it. */
6577 setlocale (LC_NUMERIC
, "C");
6578 setlocale (LC_TIME
, "C");
6581 #ifdef USE_X_TOOLKIT
6582 /* weiner@footloose.sps.mot.com reports that this causes
6584 X protocol error: BadAtom (invalid Atom parameter)
6585 on protocol request 18skiloaf.
6586 So let's not use it until R6. */
6588 XtSetLanguageProc (NULL
, NULL
, NULL
);
6599 argv
[argc
++] = "-xrm";
6600 argv
[argc
++] = xrm_option
;
6602 dpy
= XtOpenDisplay (Xt_app_con
, XSTRING (display_name
)->data
,
6603 resource_name
, EMACS_CLASS
,
6604 emacs_options
, XtNumber (emacs_options
),
6608 /* I think this is to compensate for XtSetLanguageProc. */
6609 setlocale (LC_NUMERIC
, "C");
6610 setlocale (LC_TIME
, "C");
6614 #else /* not USE_X_TOOLKIT */
6616 XSetLocaleModifiers ("");
6618 dpy
= XOpenDisplay (XSTRING (display_name
)->data
);
6619 #endif /* not USE_X_TOOLKIT */
6621 /* Detect failure. */
6628 /* We have definitely succeeded. Record the new connection. */
6630 dpyinfo
= (struct x_display_info
*) xmalloc (sizeof (struct x_display_info
));
6634 struct x_display_info
*share
;
6637 for (share
= x_display_list
, tail
= x_display_name_list
; share
;
6638 share
= share
->next
, tail
= XCONS (tail
)->cdr
)
6639 if (same_x_server (XSTRING (XCONS (XCONS (tail
)->car
)->car
)->data
,
6640 XSTRING (display_name
)->data
))
6643 dpyinfo
->kboard
= share
->kboard
;
6646 dpyinfo
->kboard
= (KBOARD
*) xmalloc (sizeof (KBOARD
));
6647 init_kboard (dpyinfo
->kboard
);
6648 if (!EQ (XSYMBOL (Qvendor_specific_keysyms
)->function
, Qunbound
))
6650 char *vendor
= ServerVendor (dpy
);
6651 dpyinfo
->kboard
->Vsystem_key_alist
6652 = call1 (Qvendor_specific_keysyms
,
6653 build_string (vendor
? vendor
: ""));
6656 dpyinfo
->kboard
->next_kboard
= all_kboards
;
6657 all_kboards
= dpyinfo
->kboard
;
6658 /* Don't let the initial kboard remain current longer than necessary.
6659 That would cause problems if a file loaded on startup tries to
6660 prompt in the minibuffer. */
6661 if (current_kboard
== initial_kboard
)
6662 current_kboard
= dpyinfo
->kboard
;
6664 dpyinfo
->kboard
->reference_count
++;
6668 /* Put this display on the chain. */
6669 dpyinfo
->next
= x_display_list
;
6670 x_display_list
= dpyinfo
;
6672 /* Put it on x_display_name_list as well, to keep them parallel. */
6673 x_display_name_list
= Fcons (Fcons (display_name
, Qnil
),
6674 x_display_name_list
);
6675 dpyinfo
->name_list_element
= XCONS (x_display_name_list
)->car
;
6677 dpyinfo
->display
= dpy
;
6680 XSetAfterFunction (x_current_display
, x_trace_wire
);
6684 = (char *) xmalloc (XSTRING (Vinvocation_name
)->size
6685 + XSTRING (Vsystem_name
)->size
6687 sprintf (dpyinfo
->x_id_name
, "%s@%s",
6688 XSTRING (Vinvocation_name
)->data
, XSTRING (Vsystem_name
)->data
);
6690 /* Figure out which modifier bits mean what. */
6691 x_find_modifier_meanings (dpyinfo
);
6693 /* Get the scroll bar cursor. */
6694 dpyinfo
->vertical_scroll_bar_cursor
6695 = XCreateFontCursor (dpyinfo
->display
, XC_sb_v_double_arrow
);
6697 xrdb
= x_load_resources (dpyinfo
->display
, xrm_option
,
6698 resource_name
, EMACS_CLASS
);
6699 #ifdef HAVE_XRMSETDATABASE
6700 XrmSetDatabase (dpyinfo
->display
, xrdb
);
6702 dpyinfo
->display
->db
= xrdb
;
6704 /* Put the rdb where we can find it in a way that works on
6706 dpyinfo
->xrdb
= xrdb
;
6708 dpyinfo
->screen
= ScreenOfDisplay (dpyinfo
->display
,
6709 DefaultScreen (dpyinfo
->display
));
6710 dpyinfo
->visual
= select_visual (dpyinfo
->display
, dpyinfo
->screen
,
6711 &dpyinfo
->n_planes
);
6712 dpyinfo
->height
= HeightOfScreen (dpyinfo
->screen
);
6713 dpyinfo
->width
= WidthOfScreen (dpyinfo
->screen
);
6714 dpyinfo
->root_window
= RootWindowOfScreen (dpyinfo
->screen
);
6715 dpyinfo
->grabbed
= 0;
6716 dpyinfo
->reference_count
= 0;
6717 dpyinfo
->icon_bitmap_id
= -1;
6718 dpyinfo
->n_fonts
= 0;
6719 dpyinfo
->font_table_size
= 0;
6720 dpyinfo
->bitmaps
= 0;
6721 dpyinfo
->bitmaps_size
= 0;
6722 dpyinfo
->bitmaps_last
= 0;
6723 dpyinfo
->scratch_cursor_gc
= 0;
6724 dpyinfo
->mouse_face_mouse_frame
= 0;
6725 dpyinfo
->mouse_face_deferred_gc
= 0;
6726 dpyinfo
->mouse_face_beg_row
= dpyinfo
->mouse_face_beg_col
= -1;
6727 dpyinfo
->mouse_face_end_row
= dpyinfo
->mouse_face_end_col
= -1;
6728 dpyinfo
->mouse_face_face_id
= 0;
6729 dpyinfo
->mouse_face_window
= Qnil
;
6730 dpyinfo
->mouse_face_mouse_x
= dpyinfo
->mouse_face_mouse_y
= 0;
6731 dpyinfo
->mouse_face_defer
= 0;
6732 dpyinfo
->x_focus_frame
= 0;
6733 dpyinfo
->x_focus_event_frame
= 0;
6734 dpyinfo
->x_highlight_frame
= 0;
6736 dpyinfo
->Xatom_wm_protocols
6737 = XInternAtom (dpyinfo
->display
, "WM_PROTOCOLS", False
);
6738 dpyinfo
->Xatom_wm_take_focus
6739 = XInternAtom (dpyinfo
->display
, "WM_TAKE_FOCUS", False
);
6740 dpyinfo
->Xatom_wm_save_yourself
6741 = XInternAtom (dpyinfo
->display
, "WM_SAVE_YOURSELF", False
);
6742 dpyinfo
->Xatom_wm_delete_window
6743 = XInternAtom (dpyinfo
->display
, "WM_DELETE_WINDOW", False
);
6744 dpyinfo
->Xatom_wm_change_state
6745 = XInternAtom (dpyinfo
->display
, "WM_CHANGE_STATE", False
);
6746 dpyinfo
->Xatom_wm_configure_denied
6747 = XInternAtom (dpyinfo
->display
, "WM_CONFIGURE_DENIED", False
);
6748 dpyinfo
->Xatom_wm_window_moved
6749 = XInternAtom (dpyinfo
->display
, "WM_MOVED", False
);
6750 dpyinfo
->Xatom_editres
6751 = XInternAtom (dpyinfo
->display
, "Editres", False
);
6752 dpyinfo
->Xatom_CLIPBOARD
6753 = XInternAtom (dpyinfo
->display
, "CLIPBOARD", False
);
6754 dpyinfo
->Xatom_TIMESTAMP
6755 = XInternAtom (dpyinfo
->display
, "TIMESTAMP", False
);
6757 = XInternAtom (dpyinfo
->display
, "TEXT", False
);
6758 dpyinfo
->Xatom_COMPOUND_TEXT
6759 = XInternAtom (dpyinfo
->display
, "COMPOUND_TEXT", False
);
6760 dpyinfo
->Xatom_DELETE
6761 = XInternAtom (dpyinfo
->display
, "DELETE", False
);
6762 dpyinfo
->Xatom_MULTIPLE
6763 = XInternAtom (dpyinfo
->display
, "MULTIPLE", False
);
6765 = XInternAtom (dpyinfo
->display
, "INCR", False
);
6766 dpyinfo
->Xatom_EMACS_TMP
6767 = XInternAtom (dpyinfo
->display
, "_EMACS_TMP_", False
);
6768 dpyinfo
->Xatom_TARGETS
6769 = XInternAtom (dpyinfo
->display
, "TARGETS", False
);
6771 = XInternAtom (dpyinfo
->display
, "NULL", False
);
6772 dpyinfo
->Xatom_ATOM_PAIR
6773 = XInternAtom (dpyinfo
->display
, "ATOM_PAIR", False
);
6774 /* For properties of font. */
6775 dpyinfo
->Xatom_PIXEL_SIZE
6776 = XInternAtom (dpyinfo
->display
, "PIXEL_SIZE", False
);
6777 dpyinfo
->Xatom_MULE_BASELINE_OFFSET
6778 = XInternAtom (dpyinfo
->display
, "_MULE_BASELINE_OFFSET", False
);
6779 dpyinfo
->Xatom_MULE_RELATIVE_COMPOSE
6780 = XInternAtom (dpyinfo
->display
, "_MULE_RELATIVE_COMPOSE", False
);
6781 dpyinfo
->Xatom_MULE_DEFAULT_ASCENT
6782 = XInternAtom (dpyinfo
->display
, "_MULE_DEFAULT_ASCENT", False
);
6784 dpyinfo
->cut_buffers_initialized
= 0;
6786 connection
= ConnectionNumber (dpyinfo
->display
);
6787 dpyinfo
->connection
= connection
;
6790 char null_bits
[] = { 0x00 };
6793 = XCreatePixmapFromBitmapData (dpyinfo
->display
, dpyinfo
->root_window
,
6794 null_bits
, 1, 1, (long) 0, (long) 0,
6799 /* This is only needed for distinguishing keyboard and process input. */
6800 if (connection
!= 0)
6801 add_keyboard_wait_descriptor (connection
);
6804 #ifndef F_SETOWN_BUG
6806 #ifdef F_SETOWN_SOCK_NEG
6807 /* stdin is a socket here */
6808 fcntl (connection
, F_SETOWN
, -getpid ());
6809 #else /* ! defined (F_SETOWN_SOCK_NEG) */
6810 fcntl (connection
, F_SETOWN
, getpid ());
6811 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
6812 #endif /* ! defined (F_SETOWN) */
6813 #endif /* F_SETOWN_BUG */
6816 if (interrupt_input
)
6817 init_sigio (connection
);
6818 #endif /* ! defined (SIGIO) */
6821 /* Make sure that we have a valid font for dialog boxes
6822 so that Xt does not crash. */
6824 Display
*dpy
= dpyinfo
->display
;
6828 d
.addr
= (XPointer
)&dpy
;
6829 d
.size
= sizeof (Display
*);
6830 fr
.addr
= XtDefaultFont
;
6831 fr
.size
= sizeof (XtDefaultFont
);
6832 to
.size
= sizeof (Font
*);
6833 to
.addr
= (XPointer
)&font
;
6834 x_catch_errors (dpy
);
6835 if (!XtCallConverter (dpy
, XtCvtStringToFont
, &d
, 1, &fr
, &to
, NULL
))
6837 if (x_had_errors_p (dpy
) || !XQueryFont (dpy
, font
))
6838 XrmPutLineResource (&xrdb
, "Emacs.dialog.*.font: 9x15");
6839 x_uncatch_errors (dpy
);
6849 /* Get rid of display DPYINFO, assuming all frames are already gone,
6850 and without sending any more commands to the X server. */
6853 x_delete_display (dpyinfo
)
6854 struct x_display_info
*dpyinfo
;
6856 delete_keyboard_wait_descriptor (dpyinfo
->connection
);
6858 /* Discard this display from x_display_name_list and x_display_list.
6859 We can't use Fdelq because that can quit. */
6860 if (! NILP (x_display_name_list
)
6861 && EQ (XCONS (x_display_name_list
)->car
, dpyinfo
->name_list_element
))
6862 x_display_name_list
= XCONS (x_display_name_list
)->cdr
;
6867 tail
= x_display_name_list
;
6868 while (CONSP (tail
) && CONSP (XCONS (tail
)->cdr
))
6870 if (EQ (XCONS (XCONS (tail
)->cdr
)->car
,
6871 dpyinfo
->name_list_element
))
6873 XCONS (tail
)->cdr
= XCONS (XCONS (tail
)->cdr
)->cdr
;
6876 tail
= XCONS (tail
)->cdr
;
6880 if (x_display_list
== dpyinfo
)
6881 x_display_list
= dpyinfo
->next
;
6884 struct x_display_info
*tail
;
6886 for (tail
= x_display_list
; tail
; tail
= tail
->next
)
6887 if (tail
->next
== dpyinfo
)
6888 tail
->next
= tail
->next
->next
;
6891 #ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
6892 #ifndef AIX /* On AIX, XCloseDisplay calls this. */
6893 XrmDestroyDatabase (dpyinfo
->xrdb
);
6897 if (--dpyinfo
->kboard
->reference_count
== 0)
6898 delete_kboard (dpyinfo
->kboard
);
6900 xfree (dpyinfo
->font_table
);
6901 xfree (dpyinfo
->x_id_name
);
6905 /* Set up use of X before we make the first connection. */
6909 clear_frame_hook
= XTclear_frame
;
6910 clear_end_of_line_hook
= XTclear_end_of_line
;
6911 ins_del_lines_hook
= XTins_del_lines
;
6912 change_line_highlight_hook
= XTchange_line_highlight
;
6913 insert_glyphs_hook
= XTinsert_glyphs
;
6914 write_glyphs_hook
= XTwrite_glyphs
;
6915 delete_glyphs_hook
= XTdelete_glyphs
;
6916 ring_bell_hook
= XTring_bell
;
6917 reset_terminal_modes_hook
= XTreset_terminal_modes
;
6918 set_terminal_modes_hook
= XTset_terminal_modes
;
6919 update_begin_hook
= XTupdate_begin
;
6920 update_end_hook
= XTupdate_end
;
6921 set_terminal_window_hook
= XTset_terminal_window
;
6922 read_socket_hook
= XTread_socket
;
6923 frame_up_to_date_hook
= XTframe_up_to_date
;
6924 cursor_to_hook
= XTcursor_to
;
6925 reassert_line_highlight_hook
= XTreassert_line_highlight
;
6926 mouse_position_hook
= XTmouse_position
;
6927 frame_rehighlight_hook
= XTframe_rehighlight
;
6928 frame_raise_lower_hook
= XTframe_raise_lower
;
6929 set_vertical_scroll_bar_hook
= XTset_vertical_scroll_bar
;
6930 condemn_scroll_bars_hook
= XTcondemn_scroll_bars
;
6931 redeem_scroll_bar_hook
= XTredeem_scroll_bar
;
6932 judge_scroll_bars_hook
= XTjudge_scroll_bars
;
6934 scroll_region_ok
= 1; /* we'll scroll partial frames */
6935 char_ins_del_ok
= 0; /* just as fast to write the line */
6936 line_ins_del_ok
= 1; /* we'll just blt 'em */
6937 fast_clear_end_of_line
= 1; /* X does this well */
6938 memory_below_frame
= 0; /* we don't remember what scrolls
6944 /* Try to use interrupt input; if we can't, then start polling. */
6945 Fset_input_mode (Qt
, Qnil
, Qt
, Qnil
);
6947 #ifdef USE_X_TOOLKIT
6948 XtToolkitInitialize ();
6949 Xt_app_con
= XtCreateApplicationContext ();
6950 XtAppSetFallbackResources (Xt_app_con
, Xt_default_resources
);
6953 /* Note that there is no real way portable across R3/R4 to get the
6954 original error handler. */
6955 XSetErrorHandler (x_error_quitter
);
6956 XSetIOErrorHandler (x_io_error_quitter
);
6958 /* Disable Window Change signals; they are handled by X events. */
6960 signal (SIGWINCH
, SIG_DFL
);
6961 #endif /* ! defined (SIGWINCH) */
6963 signal (SIGPIPE
, x_connection_signal
);
6969 staticpro (&x_display_name_list
);
6970 x_display_name_list
= Qnil
;
6972 staticpro (&last_mouse_scroll_bar
);
6973 last_mouse_scroll_bar
= Qnil
;
6975 staticpro (&Qvendor_specific_keysyms
);
6976 Qvendor_specific_keysyms
= intern ("vendor-specific-keysyms");
6978 staticpro (&last_mouse_press_frame
);
6979 last_mouse_press_frame
= Qnil
;
6982 #endif /* not HAVE_X_WINDOWS */