Exchange mail mangling.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
1c7e22fd 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
06a2c219 3 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
06a2c219 22/* New display code by Gerd Moellmann <gerd@gnu.org>. */
3afe33e7
RS
23/* Xt features made by Fred Pierresteguy. */
24
68c45bf0
PE
25#include <config.h>
26
039440c4 27/* On 4.3 these lose if they come after xterm.h. */
039440c4 28/* Putting these at the beginning seems to be standard for other .c files. */
039440c4
RS
29#include <signal.h>
30
4846819e
RS
31#include <stdio.h>
32
dc6f92b8
JB
33#ifdef HAVE_X_WINDOWS
34
35#include "lisp.h"
9ac0d9e0 36#include "blockinput.h"
dc6f92b8 37
ae79c227
AS
38/* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40#include "syssignal.h"
41
dc6f92b8
JB
42/* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44#include "xterm.h"
f451eb13 45#include <X11/cursorfont.h>
dc6f92b8
JB
46
47/* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49#ifndef makedev
50#include <sys/types.h>
c118dd06 51#endif /* makedev */
dc6f92b8 52
6df54671 53#ifdef BSD_SYSTEM
dc6f92b8 54#include <sys/ioctl.h>
6df54671 55#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 56
2d368234 57#include "systty.h"
3a2712f9 58#include "systime.h"
dc6f92b8 59
b8009dd1 60#ifndef INCLUDED_FCNTL
dc6f92b8 61#include <fcntl.h>
b8009dd1 62#endif
dc6f92b8
JB
63#include <ctype.h>
64#include <errno.h>
65#include <setjmp.h>
66#include <sys/stat.h>
a0a7635f
RS
67/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68/* #include <sys/param.h> */
dc6f92b8 69
dc43ef94 70#include "charset.h"
379b5ac0 71#include "coding.h"
dc43ef94 72#include "ccl.h"
7a13e894 73#include "frame.h"
dc6f92b8 74#include "dispextern.h"
ee569018 75#include "fontset.h"
dc6f92b8
JB
76#include "termhooks.h"
77#include "termopts.h"
78#include "termchar.h"
79#if 0
80#include "sink.h"
81#include "sinkmask.h"
c118dd06 82#endif /* ! 0 */
dc6f92b8 83#include "gnu.h"
dc6f92b8 84#include "disptab.h"
dc6f92b8 85#include "buffer.h"
f451eb13 86#include "window.h"
3b2fa4e6 87#include "keyboard.h"
bde7c500 88#include "intervals.h"
dfcf069d 89#include "process.h"
bffcfca9 90#include "atimer.h"
dc6f92b8 91
d2bd6bc4
RS
92#ifdef USE_X_TOOLKIT
93#include <X11/Shell.h>
94#endif
95
06a2c219
GM
96#ifdef HAVE_SYS_TIME_H
97#include <sys/time.h>
98#endif
99#ifdef HAVE_UNISTD_H
100#include <unistd.h>
101#endif
102
3afe33e7 103#ifdef USE_X_TOOLKIT
06a2c219 104
952291d9
GM
105extern void free_frame_menubar P_ ((struct frame *));
106extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
06a2c219 108
0fdff6bb
RS
109#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110#define HACK_EDITRES
111extern void _XEditResCheckMessages ();
112#endif /* not NO_EDITRES */
06a2c219
GM
113
114/* Include toolkit specific headers for the scroll bar widget. */
115
116#ifdef USE_TOOLKIT_SCROLL_BARS
117#if defined USE_MOTIF
118#include <Xm/Xm.h> /* for LESSTIF_VERSION */
119#include <Xm/ScrollBar.h>
120#include <Xm/ScrollBarP.h>
ec18280f
SM
121#else /* !USE_MOTIF i.e. use Xaw */
122
123#ifdef HAVE_XAW3D
06a2c219 124#include <X11/Xaw3d/Simple.h>
06a2c219
GM
125#include <X11/Xaw3d/Scrollbar.h>
126#define ARROW_SCROLLBAR
127#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
128#else /* !HAVE_XAW3D */
129#include <X11/Xaw/Simple.h>
130#include <X11/Xaw/Scrollbar.h>
131#endif /* !HAVE_XAW3D */
132#ifndef XtNpickTop
133#define XtNpickTop "pickTop"
134#endif /* !XtNpickTop */
135#endif /* !USE_MOTIF */
06a2c219
GM
136#endif /* USE_TOOLKIT_SCROLL_BARS */
137
3afe33e7
RS
138#endif /* USE_X_TOOLKIT */
139
b849c413
RS
140#ifndef USE_X_TOOLKIT
141#define x_any_window_to_frame x_window_to_frame
5627c40e 142#define x_top_window_to_frame x_window_to_frame
b849c413
RS
143#endif
144
546e6d5b 145#ifdef USE_X_TOOLKIT
d067ea8b 146#include "widget.h"
546e6d5b
RS
147#ifndef XtNinitialState
148#define XtNinitialState "initialState"
149#endif
150#endif
151
e4b68333 152#ifndef min
06a2c219 153#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
154#endif
155#ifndef max
06a2c219
GM
156#define max(a,b) ((a) > (b) ? (a) : (b))
157#endif
158
159#define abs(x) ((x) < 0 ? -(x) : (x))
160
161#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
162
163\f
164/* Bitmaps for truncated lines. */
165
166enum bitmap_type
167{
168 NO_BITMAP,
169 LEFT_TRUNCATION_BITMAP,
170 RIGHT_TRUNCATION_BITMAP,
171 OVERLAY_ARROW_BITMAP,
172 CONTINUED_LINE_BITMAP,
173 CONTINUATION_LINE_BITMAP,
174 ZV_LINE_BITMAP
175};
176
177/* Bitmap drawn to indicate lines not displaying text if
178 `indicate-empty-lines' is non-nil. */
179
180#define zv_width 8
181#define zv_height 8
182static unsigned char zv_bits[] = {
183 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
184
185/* An arrow like this: `<-'. */
186
187#define left_width 8
188#define left_height 8
189static unsigned char left_bits[] = {
190 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
191
110859fc
GM
192/* Right truncation arrow bitmap `->'. */
193
194#define right_width 8
195#define right_height 8
196static unsigned char right_bits[] = {
197 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
198
06a2c219
GM
199/* Marker for continued lines. */
200
201#define continued_width 8
202#define continued_height 8
203static unsigned char continued_bits[] = {
110859fc
GM
204 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
205
206/* Marker for continuation lines. */
06a2c219
GM
207
208#define continuation_width 8
209#define continuation_height 8
210static unsigned char continuation_bits[] = {
110859fc 211 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 212
110859fc 213/* Overlay arrow bitmap. */
06a2c219 214
110859fc
GM
215#if 0
216/* A bomb. */
06a2c219
GM
217#define ov_width 8
218#define ov_height 8
219static unsigned char ov_bits[] = {
220 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 221#else
110859fc 222/* A triangular arrow. */
06a2c219
GM
223#define ov_width 8
224#define ov_height 8
225static unsigned char ov_bits[] = {
110859fc
GM
226 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
227
e4b68333 228#endif
06a2c219
GM
229
230extern Lisp_Object Qhelp_echo;
231
69388238 232\f
06a2c219
GM
233/* Non-zero means Emacs uses toolkit scroll bars. */
234
235int x_toolkit_scroll_bars_p;
236
237/* If a string, XTread_socket generates an event to display that string.
238 (The display is done in read_char.) */
239
240static Lisp_Object help_echo;
7cea38bc 241static Lisp_Object help_echo_window;
be010514
GM
242static Lisp_Object help_echo_object;
243static int help_echo_pos;
06a2c219
GM
244
245/* Temporary variable for XTread_socket. */
246
247static Lisp_Object previous_help_echo;
248
249/* Non-zero means that a HELP_EVENT has been generated since Emacs
250 start. */
251
252static int any_help_event_p;
253
254/* Non-zero means draw block and hollow cursor as wide as the glyph
255 under it. For example, if a block cursor is over a tab, it will be
256 drawn as wide as that tab on the display. */
257
258int x_stretch_cursor_p;
259
260/* This is a chain of structures for all the X displays currently in
261 use. */
262
334208b7 263struct x_display_info *x_display_list;
dc6f92b8 264
06a2c219
GM
265/* This is a list of cons cells, each of the form (NAME
266 . FONT-LIST-CACHE), one for each element of x_display_list and in
267 the same order. NAME is the name of the frame. FONT-LIST-CACHE
268 records previous values returned by x-list-fonts. */
269
7a13e894 270Lisp_Object x_display_name_list;
f451eb13 271
987d2ad1 272/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
273 This is set by update_begin and looked at by all the XT functions.
274 It is zero while not inside an update. In that case, the XT
275 functions assume that `selected_frame' is the frame to apply to. */
276
d0386f2a 277extern struct frame *updating_frame;
dc6f92b8 278
dfcf069d 279extern int waiting_for_input;
0e81d8cd 280
06a2c219
GM
281/* This is a frame waiting to be auto-raised, within XTread_socket. */
282
0134a210
RS
283struct frame *pending_autoraise_frame;
284
7f9c7f94
RS
285#ifdef USE_X_TOOLKIT
286/* The application context for Xt use. */
287XtAppContext Xt_app_con;
06a2c219
GM
288static String Xt_default_resources[] = {0};
289#endif /* USE_X_TOOLKIT */
665881ad 290
06a2c219
GM
291/* Nominal cursor position -- where to draw output.
292 HPOS and VPOS are window relative glyph matrix coordinates.
293 X and Y are window relative pixel coordinates. */
dc6f92b8 294
06a2c219 295struct cursor_pos output_cursor;
dc6f92b8 296
bffcfca9
GM
297/* Non-zero means user is interacting with a toolkit scroll bar. */
298
299static int toolkit_scroll_bar_interaction;
dc6f92b8 300
69388238
RS
301/* Mouse movement.
302
06a2c219 303 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
304 so that we would have to call XQueryPointer after each MotionNotify
305 event to ask for another such event. However, this made mouse tracking
306 slow, and there was a bug that made it eventually stop.
307
308 Simply asking for MotionNotify all the time seems to work better.
309
69388238
RS
310 In order to avoid asking for motion events and then throwing most
311 of them away or busy-polling the server for mouse positions, we ask
312 the server for pointer motion hints. This means that we get only
313 one event per group of mouse movements. "Groups" are delimited by
314 other kinds of events (focus changes and button clicks, for
315 example), or by XQueryPointer calls; when one of these happens, we
316 get another MotionNotify event the next time the mouse moves. This
317 is at least as efficient as getting motion events when mouse
318 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 319 is off. */
69388238
RS
320
321/* Where the mouse was last time we reported a mouse event. */
69388238 322
06a2c219
GM
323FRAME_PTR last_mouse_frame;
324static XRectangle last_mouse_glyph;
2237cac9
RS
325static Lisp_Object last_mouse_press_frame;
326
69388238
RS
327/* The scroll bar in which the last X motion event occurred.
328
06a2c219
GM
329 If the last X motion event occurred in a scroll bar, we set this so
330 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
331 an ordinary motion.
332
06a2c219
GM
333 If the last X motion event didn't occur in a scroll bar, we set
334 this to Qnil, to tell XTmouse_position to return an ordinary motion
335 event. */
336
69388238
RS
337static Lisp_Object last_mouse_scroll_bar;
338
69388238
RS
339/* This is a hack. We would really prefer that XTmouse_position would
340 return the time associated with the position it returns, but there
06a2c219 341 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
342 along with the position query. So, we just keep track of the time
343 of the last movement we received, and return that in hopes that
344 it's somewhat accurate. */
06a2c219 345
69388238
RS
346static Time last_mouse_movement_time;
347
06a2c219
GM
348/* Incremented by XTread_socket whenever it really tries to read
349 events. */
350
c0a04927
RS
351#ifdef __STDC__
352static int volatile input_signal_count;
353#else
354static int input_signal_count;
355#endif
356
7a13e894 357/* Used locally within XTread_socket. */
06a2c219 358
7a13e894 359static int x_noop_count;
dc6f92b8 360
7a13e894 361/* Initial values of argv and argc. */
06a2c219 362
7a13e894
RS
363extern char **initial_argv;
364extern int initial_argc;
dc6f92b8 365
7a13e894 366extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 367
06a2c219 368/* Tells if a window manager is present or not. */
7a13e894
RS
369
370extern Lisp_Object Vx_no_window_manager;
dc6f92b8 371
c2df547c 372extern Lisp_Object Qface, Qmouse_face;
b8009dd1 373
dc6f92b8
JB
374extern int errno;
375
dfeccd2d 376/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 377
64bb1782
RS
378extern int extra_keyboard_modifiers;
379
59e755be
KH
380static Lisp_Object Qvendor_specific_keysyms;
381
952291d9
GM
382extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
383extern Lisp_Object x_icon_type P_ ((struct frame *));
c32cdd9a 384
7a13e894 385
06a2c219
GM
386/* Enumeration for overriding/changing the face to use for drawing
387 glyphs in x_draw_glyphs. */
388
389enum draw_glyphs_face
390{
391 DRAW_NORMAL_TEXT,
392 DRAW_INVERSE_VIDEO,
393 DRAW_CURSOR,
394 DRAW_MOUSE_FACE,
395 DRAW_IMAGE_RAISED,
396 DRAW_IMAGE_SUNKEN
397};
398
f04e1297 399static const XColor *x_color_cells P_ ((struct frame *, int *));
71b8321e 400static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
401static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
402void x_delete_display P_ ((struct x_display_info *));
403static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
404 unsigned));
405static int fast_find_position P_ ((struct window *, int, int *, int *,
406 int *, int *));
407static void set_output_cursor P_ ((struct cursor_pos *));
408static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
409 int *, int *, int *));
410static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 411static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
412static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
413static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
414static void show_mouse_face P_ ((struct x_display_info *,
415 enum draw_glyphs_face));
416static int x_io_error_quitter P_ ((Display *));
417int x_catch_errors P_ ((Display *));
418void x_uncatch_errors P_ ((Display *, int));
419void x_lower_frame P_ ((struct frame *));
420void x_scroll_bar_clear P_ ((struct frame *));
421int x_had_errors_p P_ ((Display *));
422void x_wm_set_size_hint P_ ((struct frame *, long, int));
423void x_raise_frame P_ ((struct frame *));
424void x_set_window_size P_ ((struct frame *, int, int, int));
425void x_wm_set_window_state P_ ((struct frame *, int));
426void x_wm_set_icon_pixmap P_ ((struct frame *, int));
427void x_initialize P_ ((void));
428static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
429static int x_compute_min_glyph_bounds P_ ((struct frame *));
430static void x_draw_phys_cursor_glyph P_ ((struct window *,
431 struct glyph_row *,
432 enum draw_glyphs_face));
433static void x_update_end P_ ((struct frame *));
434static void XTframe_up_to_date P_ ((struct frame *));
435static void XTreassert_line_highlight P_ ((int, int));
436static void x_change_line_highlight P_ ((int, int, int, int));
437static void XTset_terminal_modes P_ ((void));
438static void XTreset_terminal_modes P_ ((void));
439static void XTcursor_to P_ ((int, int, int, int));
440static void x_write_glyphs P_ ((struct glyph *, int));
441static void x_clear_end_of_line P_ ((int));
442static void x_clear_frame P_ ((void));
443static void x_clear_cursor P_ ((struct window *));
444static void frame_highlight P_ ((struct frame *));
445static void frame_unhighlight P_ ((struct frame *));
446static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
447static void XTframe_rehighlight P_ ((struct frame *));
448static void x_frame_rehighlight P_ ((struct x_display_info *));
449static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
f02d8aa0 450static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
06a2c219
GM
451static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
452 XRectangle *));
453static void expose_frame P_ ((struct frame *, int, int, int, int));
454static void expose_window_tree P_ ((struct window *, XRectangle *));
455static void expose_window P_ ((struct window *, XRectangle *));
456static void expose_area P_ ((struct window *, struct glyph_row *,
457 XRectangle *, enum glyph_row_area));
458static void expose_line P_ ((struct window *, struct glyph_row *,
459 XRectangle *));
460static void x_update_cursor_in_window_tree P_ ((struct window *, int));
461static void x_update_window_cursor P_ ((struct window *, int));
462static void x_erase_phys_cursor P_ ((struct window *));
463void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
464static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
465 enum bitmap_type));
466
467static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
468 GC, int));
469static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
470static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
471static void note_overwritten_text_cursor P_ ((struct window *, int, int));
472static void x_flush P_ ((struct frame *f));
952291d9
GM
473static void x_update_begin P_ ((struct frame *));
474static void x_update_window_begin P_ ((struct window *));
475static void x_draw_vertical_border P_ ((struct window *));
476static void x_after_update_window_line P_ ((struct glyph_row *));
477static INLINE void take_vertical_position_into_account P_ ((struct it *));
478static void x_produce_stretch_glyph P_ ((struct it *));
479
06a2c219
GM
480
481/* Flush display of frame F, or of all frames if F is null. */
482
483static void
484x_flush (f)
485 struct frame *f;
486{
487 BLOCK_INPUT;
488 if (f == NULL)
489 {
490 Lisp_Object rest, frame;
491 FOR_EACH_FRAME (rest, frame)
492 x_flush (XFRAME (frame));
493 }
494 else if (FRAME_X_P (f))
495 XFlush (FRAME_X_DISPLAY (f));
496 UNBLOCK_INPUT;
497}
498
dc6f92b8 499
06a2c219
GM
500/* Remove calls to XFlush by defining XFlush to an empty replacement.
501 Calls to XFlush should be unnecessary because the X output buffer
502 is flushed automatically as needed by calls to XPending,
503 XNextEvent, or XWindowEvent according to the XFlush man page.
504 XTread_socket calls XPending. Removing XFlush improves
505 performance. */
506
507#define XFlush(DISPLAY) (void) 0
b8009dd1 508
334208b7 509\f
06a2c219
GM
510/***********************************************************************
511 Debugging
512 ***********************************************************************/
513
9382638d 514#if 0
06a2c219
GM
515
516/* This is a function useful for recording debugging information about
517 the sequence of occurrences in this file. */
9382638d
KH
518
519struct record
520{
521 char *locus;
522 int type;
523};
524
525struct record event_record[100];
526
527int event_record_index;
528
529record_event (locus, type)
530 char *locus;
531 int type;
532{
533 if (event_record_index == sizeof (event_record) / sizeof (struct record))
534 event_record_index = 0;
535
536 event_record[event_record_index].locus = locus;
537 event_record[event_record_index].type = type;
538 event_record_index++;
539}
540
541#endif /* 0 */
06a2c219
GM
542
543
9382638d 544\f
334208b7
RS
545/* Return the struct x_display_info corresponding to DPY. */
546
547struct x_display_info *
548x_display_info_for_display (dpy)
549 Display *dpy;
550{
551 struct x_display_info *dpyinfo;
552
553 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
554 if (dpyinfo->display == dpy)
555 return dpyinfo;
16bd92ea 556
334208b7
RS
557 return 0;
558}
f451eb13 559
06a2c219
GM
560
561\f
562/***********************************************************************
563 Starting and ending an update
564 ***********************************************************************/
565
566/* Start an update of frame F. This function is installed as a hook
567 for update_begin, i.e. it is called when update_begin is called.
568 This function is called prior to calls to x_update_window_begin for
569 each window being updated. Currently, there is nothing to do here
570 because all interesting stuff is done on a window basis. */
dc6f92b8 571
dfcf069d 572static void
06a2c219 573x_update_begin (f)
f676886a 574 struct frame *f;
58769bee 575{
06a2c219
GM
576 /* Nothing to do. */
577}
dc6f92b8 578
dc6f92b8 579
06a2c219
GM
580/* Start update of window W. Set the global variable updated_window
581 to the window being updated and set output_cursor to the cursor
582 position of W. */
dc6f92b8 583
06a2c219
GM
584static void
585x_update_window_begin (w)
586 struct window *w;
587{
588 struct frame *f = XFRAME (WINDOW_FRAME (w));
589 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
590
591 updated_window = w;
592 set_output_cursor (&w->cursor);
b8009dd1 593
06a2c219 594 BLOCK_INPUT;
d1bc4182 595
06a2c219 596 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 597 {
514e4681 598 /* Don't do highlighting for mouse motion during the update. */
06a2c219 599 display_info->mouse_face_defer = 1;
37c2c98b 600
06a2c219
GM
601 /* If F needs to be redrawn, simply forget about any prior mouse
602 highlighting. */
9f67f20b 603 if (FRAME_GARBAGED_P (f))
06a2c219
GM
604 display_info->mouse_face_window = Qnil;
605
64f26cf5
GM
606#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
607 their mouse_face_p flag set, which means that they are always
608 unequal to rows in a desired matrix which never have that
609 flag set. So, rows containing mouse-face glyphs are never
610 scrolled, and we don't have to switch the mouse highlight off
611 here to prevent it from being scrolled. */
612
06a2c219
GM
613 /* Can we tell that this update does not affect the window
614 where the mouse highlight is? If so, no need to turn off.
615 Likewise, don't do anything if the frame is garbaged;
616 in that case, the frame's current matrix that we would use
617 is all wrong, and we will redisplay that line anyway. */
618 if (!NILP (display_info->mouse_face_window)
619 && w == XWINDOW (display_info->mouse_face_window))
514e4681 620 {
06a2c219 621 int i;
514e4681 622
06a2c219
GM
623 for (i = 0; i < w->desired_matrix->nrows; ++i)
624 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
625 break;
626
06a2c219
GM
627 if (i < w->desired_matrix->nrows)
628 clear_mouse_face (display_info);
514e4681 629 }
64f26cf5 630#endif /* 0 */
b8009dd1 631 }
6ccf47d1 632
dc6f92b8
JB
633 UNBLOCK_INPUT;
634}
635
06a2c219
GM
636
637/* Draw a vertical window border to the right of window W if W doesn't
638 have vertical scroll bars. */
639
dfcf069d 640static void
06a2c219
GM
641x_draw_vertical_border (w)
642 struct window *w;
58769bee 643{
06a2c219
GM
644 struct frame *f = XFRAME (WINDOW_FRAME (w));
645
646 /* Redraw borders between horizontally adjacent windows. Don't
647 do it for frames with vertical scroll bars because either the
648 right scroll bar of a window, or the left scroll bar of its
649 neighbor will suffice as a border. */
650 if (!WINDOW_RIGHTMOST_P (w)
651 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
652 {
653 int x0, x1, y0, y1;
dc6f92b8 654
06a2c219 655 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 656 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
657 y1 -= 1;
658
659 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
660 f->output_data.x->normal_gc, x1, y0, x1, y1);
661 }
662}
663
664
71b8321e
GM
665/* End update of window W (which is equal to updated_window).
666
667 Draw vertical borders between horizontally adjacent windows, and
668 display W's cursor if CURSOR_ON_P is non-zero.
669
670 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
671 glyphs in mouse-face were overwritten. In that case we have to
672 make sure that the mouse-highlight is properly redrawn.
673
674 W may be a menu bar pseudo-window in case we don't have X toolkit
675 support. Such windows don't have a cursor, so don't display it
676 here. */
06a2c219
GM
677
678static void
71b8321e 679x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
06a2c219 680 struct window *w;
71b8321e 681 int cursor_on_p, mouse_face_overwritten_p;
06a2c219
GM
682{
683 if (!w->pseudo_window_p)
684 {
71b8321e
GM
685 struct x_display_info *dpyinfo
686 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
687
06a2c219 688 BLOCK_INPUT;
71b8321e
GM
689
690 /* If a row with mouse-face was overwritten, arrange for
691 XTframe_up_to_date to redisplay the mouse highlight. */
692 if (mouse_face_overwritten_p)
693 {
694 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
695 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
696 dpyinfo->mouse_face_window = Qnil;
697 }
698
06a2c219
GM
699 if (cursor_on_p)
700 x_display_and_set_cursor (w, 1, output_cursor.hpos,
701 output_cursor.vpos,
702 output_cursor.x, output_cursor.y);
71b8321e 703
06a2c219
GM
704 x_draw_vertical_border (w);
705 UNBLOCK_INPUT;
706 }
707
708 updated_window = NULL;
709}
dc6f92b8 710
dc6f92b8 711
06a2c219
GM
712/* End update of frame F. This function is installed as a hook in
713 update_end. */
714
715static void
716x_update_end (f)
717 struct frame *f;
718{
719 /* Mouse highlight may be displayed again. */
aa8bff2e 720 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 721
06a2c219 722 BLOCK_INPUT;
334208b7 723 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
724 UNBLOCK_INPUT;
725}
b8009dd1 726
06a2c219
GM
727
728/* This function is called from various places in xdisp.c whenever a
729 complete update has been performed. The global variable
730 updated_window is not available here. */
b8009dd1 731
dfcf069d 732static void
b8009dd1 733XTframe_up_to_date (f)
06a2c219 734 struct frame *f;
b8009dd1 735{
06a2c219 736 if (FRAME_X_P (f))
514e4681 737 {
06a2c219 738 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
71b8321e 739
06a2c219
GM
740 if (dpyinfo->mouse_face_deferred_gc
741 || f == dpyinfo->mouse_face_mouse_frame)
742 {
743 BLOCK_INPUT;
744 if (dpyinfo->mouse_face_mouse_frame)
745 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
746 dpyinfo->mouse_face_mouse_x,
747 dpyinfo->mouse_face_mouse_y);
748 dpyinfo->mouse_face_deferred_gc = 0;
749 UNBLOCK_INPUT;
750 }
514e4681 751 }
b8009dd1 752}
06a2c219
GM
753
754
755/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
756 arrow bitmaps, or clear the areas where they would be displayed
757 before DESIRED_ROW is made current. The window being updated is
758 found in updated_window. This function It is called from
759 update_window_line only if it is known that there are differences
760 between bitmaps to be drawn between current row and DESIRED_ROW. */
761
762static void
763x_after_update_window_line (desired_row)
764 struct glyph_row *desired_row;
765{
766 struct window *w = updated_window;
767
768 xassert (w);
769
770 if (!desired_row->mode_line_p && !w->pseudo_window_p)
771 {
772 BLOCK_INPUT;
773 x_draw_row_bitmaps (w, desired_row);
774
775 /* When a window has disappeared, make sure that no rest of
776 full-width rows stays visible in the internal border. */
777 if (windows_or_buffers_changed)
778 {
779 struct frame *f = XFRAME (w->frame);
780 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
781 int height = desired_row->visible_height;
110859fc
GM
782 int x = (window_box_right (w, -1)
783 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
784 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
785
786 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
787 x, y, width, height, False);
788 }
789
790 UNBLOCK_INPUT;
791 }
792}
793
794
795/* Draw the bitmap WHICH in one of the areas to the left or right of
796 window W. ROW is the glyph row for which to display the bitmap; it
797 determines the vertical position at which the bitmap has to be
798 drawn. */
799
800static void
801x_draw_bitmap (w, row, which)
802 struct window *w;
803 struct glyph_row *row;
804 enum bitmap_type which;
805{
806 struct frame *f = XFRAME (WINDOW_FRAME (w));
807 Display *display = FRAME_X_DISPLAY (f);
808 Window window = FRAME_X_WINDOW (f);
809 int x, y, wd, h, dy;
810 unsigned char *bits;
811 Pixmap pixmap;
812 GC gc = f->output_data.x->normal_gc;
813 struct face *face;
814 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
815
816 /* Must clip because of partially visible lines. */
817 x_clip_to_row (w, row, gc, 1);
818
819 switch (which)
820 {
821 case LEFT_TRUNCATION_BITMAP:
822 wd = left_width;
823 h = left_height;
824 bits = left_bits;
825 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
826 - wd
110859fc 827 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
828 break;
829
830 case OVERLAY_ARROW_BITMAP:
831 wd = left_width;
832 h = left_height;
833 bits = ov_bits;
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
835 - wd
110859fc 836 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
837 break;
838
839 case RIGHT_TRUNCATION_BITMAP:
840 wd = right_width;
841 h = right_height;
842 bits = right_bits;
843 x = window_box_right (w, -1);
110859fc 844 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
845 break;
846
847 case CONTINUED_LINE_BITMAP:
848 wd = right_width;
849 h = right_height;
850 bits = continued_bits;
851 x = window_box_right (w, -1);
110859fc 852 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
853 break;
854
855 case CONTINUATION_LINE_BITMAP:
856 wd = continuation_width;
857 h = continuation_height;
858 bits = continuation_bits;
859 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
860 - wd
110859fc 861 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
862 break;
863
864 case ZV_LINE_BITMAP:
865 wd = zv_width;
866 h = zv_height;
867 bits = zv_bits;
868 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
869 - wd
110859fc 870 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
871 break;
872
873 default:
874 abort ();
875 }
876
877 /* Convert to frame coordinates. Set dy to the offset in the row to
878 start drawing the bitmap. */
879 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
880 dy = (row->height - h) / 2;
881
882 /* Draw the bitmap. I believe these small pixmaps can be cached
883 by the server. */
884 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
885 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
886 face->foreground,
887 face->background, depth);
888 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
889 XFreePixmap (display, pixmap);
890 XSetClipMask (display, gc, None);
891}
892
893
894/* Draw flags bitmaps for glyph row ROW on window W. Call this
895 function with input blocked. */
896
897static void
898x_draw_row_bitmaps (w, row)
899 struct window *w;
900 struct glyph_row *row;
901{
902 struct frame *f = XFRAME (w->frame);
903 enum bitmap_type bitmap;
904 struct face *face;
045dee35 905 int header_line_height = -1;
06a2c219
GM
906
907 xassert (interrupt_input_blocked);
908
909 /* If row is completely invisible, because of vscrolling, we
910 don't have to draw anything. */
911 if (row->visible_height <= 0)
912 return;
913
914 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
915 PREPARE_FACE_FOR_DISPLAY (f, face);
916
917 /* Decide which bitmap to draw at the left side. */
918 if (row->overlay_arrow_p)
919 bitmap = OVERLAY_ARROW_BITMAP;
920 else if (row->truncated_on_left_p)
921 bitmap = LEFT_TRUNCATION_BITMAP;
922 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
923 bitmap = CONTINUATION_LINE_BITMAP;
924 else if (row->indicate_empty_line_p)
925 bitmap = ZV_LINE_BITMAP;
926 else
927 bitmap = NO_BITMAP;
928
929 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
930 the flags area. */
931 if (bitmap == NO_BITMAP
110859fc 932 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
933 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
934 {
935 /* If W has a vertical border to its left, don't draw over it. */
936 int border = ((XFASTINT (w->left) > 0
937 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
938 ? 1 : 0);
939 int left = window_box_left (w, -1);
940
045dee35
GM
941 if (header_line_height < 0)
942 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
943
944 /* In case the same realized face is used for bitmap areas and
945 for something displayed in the text (e.g. face `region' on
946 mono-displays, the fill style may have been changed to
947 FillSolid in x_draw_glyph_string_background. */
948 if (face->stipple)
949 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
950 else
951 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
952
06a2c219
GM
953 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
954 face->gc,
955 (left
110859fc 956 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 957 + border),
045dee35 958 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 959 row->y)),
110859fc 960 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 961 row->visible_height);
dcd08bfb
GM
962 if (!face->stipple)
963 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
964 }
965
966 /* Draw the left bitmap. */
967 if (bitmap != NO_BITMAP)
968 x_draw_bitmap (w, row, bitmap);
969
970 /* Decide which bitmap to draw at the right side. */
971 if (row->truncated_on_right_p)
972 bitmap = RIGHT_TRUNCATION_BITMAP;
973 else if (row->continued_p)
974 bitmap = CONTINUED_LINE_BITMAP;
975 else
976 bitmap = NO_BITMAP;
977
978 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
979 the flags area. */
980 if (bitmap == NO_BITMAP
110859fc 981 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
982 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
983 {
984 int right = window_box_right (w, -1);
985
045dee35
GM
986 if (header_line_height < 0)
987 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
988
989 /* In case the same realized face is used for bitmap areas and
990 for something displayed in the text (e.g. face `region' on
991 mono-displays, the fill style may have been changed to
992 FillSolid in x_draw_glyph_string_background. */
993 if (face->stipple)
994 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
995 else
996 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
997 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
998 face->gc,
999 right,
045dee35 1000 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 1001 row->y)),
110859fc 1002 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 1003 row->visible_height);
dcd08bfb
GM
1004 if (!face->stipple)
1005 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
1006 }
1007
1008 /* Draw the right bitmap. */
1009 if (bitmap != NO_BITMAP)
1010 x_draw_bitmap (w, row, bitmap);
1011}
1012
dc6f92b8 1013\f
06a2c219
GM
1014/***********************************************************************
1015 Line Highlighting
1016 ***********************************************************************/
dc6f92b8 1017
06a2c219
GM
1018/* External interface to control of standout mode. Not used for X
1019 frames. Aborts when called. */
1020
1021static void
dc6f92b8
JB
1022XTreassert_line_highlight (new, vpos)
1023 int new, vpos;
1024{
06a2c219 1025 abort ();
dc6f92b8
JB
1026}
1027
06a2c219
GM
1028
1029/* Call this when about to modify line at position VPOS and change
1030 whether it is highlighted. Not used for X frames. Aborts when
1031 called. */
dc6f92b8 1032
dfcf069d 1033static void
06a2c219
GM
1034x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1035 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1036{
06a2c219 1037 abort ();
dc6f92b8
JB
1038}
1039
06a2c219
GM
1040
1041/* This is called when starting Emacs and when restarting after
1042 suspend. When starting Emacs, no X window is mapped. And nothing
1043 must be done to Emacs's own window if it is suspended (though that
1044 rarely happens). */
dc6f92b8 1045
dfcf069d 1046static void
dc6f92b8
JB
1047XTset_terminal_modes ()
1048{
1049}
1050
06a2c219
GM
1051/* This is called when exiting or suspending Emacs. Exiting will make
1052 the X-windows go away, and suspending requires no action. */
dc6f92b8 1053
dfcf069d 1054static void
dc6f92b8
JB
1055XTreset_terminal_modes ()
1056{
dc6f92b8 1057}
06a2c219
GM
1058
1059
dc6f92b8 1060\f
06a2c219
GM
1061/***********************************************************************
1062 Output Cursor
1063 ***********************************************************************/
1064
1065/* Set the global variable output_cursor to CURSOR. All cursor
1066 positions are relative to updated_window. */
dc6f92b8 1067
dfcf069d 1068static void
06a2c219
GM
1069set_output_cursor (cursor)
1070 struct cursor_pos *cursor;
dc6f92b8 1071{
06a2c219
GM
1072 output_cursor.hpos = cursor->hpos;
1073 output_cursor.vpos = cursor->vpos;
1074 output_cursor.x = cursor->x;
1075 output_cursor.y = cursor->y;
1076}
1077
1078
1079/* Set a nominal cursor position.
dc6f92b8 1080
06a2c219
GM
1081 HPOS and VPOS are column/row positions in a window glyph matrix. X
1082 and Y are window text area relative pixel positions.
1083
1084 If this is done during an update, updated_window will contain the
1085 window that is being updated and the position is the future output
1086 cursor position for that window. If updated_window is null, use
1087 selected_window and display the cursor at the given position. */
1088
1089static void
1090XTcursor_to (vpos, hpos, y, x)
1091 int vpos, hpos, y, x;
1092{
1093 struct window *w;
1094
1095 /* If updated_window is not set, work on selected_window. */
1096 if (updated_window)
1097 w = updated_window;
1098 else
1099 w = XWINDOW (selected_window);
dbcb258a 1100
06a2c219
GM
1101 /* Set the output cursor. */
1102 output_cursor.hpos = hpos;
1103 output_cursor.vpos = vpos;
1104 output_cursor.x = x;
1105 output_cursor.y = y;
dc6f92b8 1106
06a2c219
GM
1107 /* If not called as part of an update, really display the cursor.
1108 This will also set the cursor position of W. */
1109 if (updated_window == NULL)
dc6f92b8
JB
1110 {
1111 BLOCK_INPUT;
06a2c219 1112 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1113 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1114 UNBLOCK_INPUT;
1115 }
1116}
dc43ef94 1117
06a2c219
GM
1118
1119\f
1120/***********************************************************************
1121 Display Iterator
1122 ***********************************************************************/
1123
1124/* Function prototypes of this page. */
1125
1126static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1127 struct glyph *,
ee569018
KH
1128 XChar2b *,
1129 int *));
06a2c219
GM
1130static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1131 int, XChar2b *, int));
1132static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1133static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1134static void x_append_glyph P_ ((struct it *));
b4192550 1135static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1136static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1137 int, int, double));
1138static void x_produce_glyphs P_ ((struct it *));
06a2c219 1139static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1140
1141
1142/* Return a pointer to per-char metric information in FONT of a
1143 character pointed by B which is a pointer to an XChar2b. */
1144
1145#define PER_CHAR_METRIC(font, b) \
1146 ((font)->per_char \
1147 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1148 + (((font)->min_byte1 || (font)->max_byte1) \
1149 ? (((b)->byte1 - (font)->min_byte1) \
1150 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1151 : 0)) \
1152 : &((font)->max_bounds))
dc43ef94 1153
dc6f92b8 1154
e2ef8ee6
GM
1155/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1156 is not contained in the font. */
dc43ef94 1157
06a2c219 1158static INLINE XCharStruct *
ee569018 1159x_per_char_metric (font, char2b)
06a2c219
GM
1160 XFontStruct *font;
1161 XChar2b *char2b;
1162{
1163 /* The result metric information. */
1164 XCharStruct *pcm = NULL;
dc6f92b8 1165
06a2c219 1166 xassert (font && char2b);
dc6f92b8 1167
06a2c219 1168 if (font->per_char != NULL)
dc6f92b8 1169 {
06a2c219 1170 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1171 {
06a2c219
GM
1172 /* min_char_or_byte2 specifies the linear character index
1173 corresponding to the first element of the per_char array,
1174 max_char_or_byte2 is the index of the last character. A
1175 character with non-zero CHAR2B->byte1 is not in the font.
1176 A character with byte2 less than min_char_or_byte2 or
1177 greater max_char_or_byte2 is not in the font. */
1178 if (char2b->byte1 == 0
1179 && char2b->byte2 >= font->min_char_or_byte2
1180 && char2b->byte2 <= font->max_char_or_byte2)
1181 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1182 }
06a2c219 1183 else
dc6f92b8 1184 {
06a2c219
GM
1185 /* If either min_byte1 or max_byte1 are nonzero, both
1186 min_char_or_byte2 and max_char_or_byte2 are less than
1187 256, and the 2-byte character index values corresponding
1188 to the per_char array element N (counting from 0) are:
1189
1190 byte1 = N/D + min_byte1
1191 byte2 = N\D + min_char_or_byte2
1192
1193 where:
1194
1195 D = max_char_or_byte2 - min_char_or_byte2 + 1
1196 / = integer division
1197 \ = integer modulus */
1198 if (char2b->byte1 >= font->min_byte1
1199 && char2b->byte1 <= font->max_byte1
1200 && char2b->byte2 >= font->min_char_or_byte2
1201 && char2b->byte2 <= font->max_char_or_byte2)
1202 {
1203 pcm = (font->per_char
1204 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1205 * (char2b->byte1 - font->min_byte1))
1206 + (char2b->byte2 - font->min_char_or_byte2));
1207 }
dc6f92b8 1208 }
06a2c219
GM
1209 }
1210 else
1211 {
1212 /* If the per_char pointer is null, all glyphs between the first
1213 and last character indexes inclusive have the same
1214 information, as given by both min_bounds and max_bounds. */
1215 if (char2b->byte2 >= font->min_char_or_byte2
1216 && char2b->byte2 <= font->max_char_or_byte2)
1217 pcm = &font->max_bounds;
1218 }
dc6f92b8 1219
ee569018 1220 return ((pcm == NULL
3e71d8f2 1221 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1222 ? NULL : pcm);
06a2c219 1223}
b73b6aaf 1224
57b03282 1225
06a2c219
GM
1226/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1227 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1228
06a2c219
GM
1229static INLINE void
1230x_encode_char (c, char2b, font_info)
1231 int c;
1232 XChar2b *char2b;
1233 struct font_info *font_info;
1234{
1235 int charset = CHAR_CHARSET (c);
1236 XFontStruct *font = font_info->font;
1237
1238 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1239 This may be either a program in a special encoder language or a
1240 fixed encoding. */
1241 if (font_info->font_encoder)
1242 {
1243 /* It's a program. */
1244 struct ccl_program *ccl = font_info->font_encoder;
1245
1246 if (CHARSET_DIMENSION (charset) == 1)
1247 {
1248 ccl->reg[0] = charset;
1249 ccl->reg[1] = char2b->byte2;
1250 }
1251 else
1252 {
1253 ccl->reg[0] = charset;
1254 ccl->reg[1] = char2b->byte1;
1255 ccl->reg[2] = char2b->byte2;
1256 }
1257
1258 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1259
1260 /* We assume that MSBs are appropriately set/reset by CCL
1261 program. */
1262 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1263 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1264 else
1265 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1266 }
1267 else if (font_info->encoding[charset])
1268 {
1269 /* Fixed encoding scheme. See fontset.h for the meaning of the
1270 encoding numbers. */
1271 int enc = font_info->encoding[charset];
1272
1273 if ((enc == 1 || enc == 2)
1274 && CHARSET_DIMENSION (charset) == 2)
1275 char2b->byte1 |= 0x80;
1276
1277 if (enc == 1 || enc == 3)
1278 char2b->byte2 |= 0x80;
1279 }
1280}
1281
1282
1283/* Get face and two-byte form of character C in face FACE_ID on frame
1284 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1285 means we want to display multibyte text. Value is a pointer to a
1286 realized face that is ready for display. */
1287
1288static INLINE struct face *
1289x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1290 struct frame *f;
1291 int c, face_id;
1292 XChar2b *char2b;
1293 int multibyte_p;
1294{
1295 struct face *face = FACE_FROM_ID (f, face_id);
1296
1297 if (!multibyte_p)
1298 {
1299 /* Unibyte case. We don't have to encode, but we have to make
1300 sure to use a face suitable for unibyte. */
1301 char2b->byte1 = 0;
1302 char2b->byte2 = c;
ee569018
KH
1303 face_id = FACE_FOR_CHAR (f, face, c);
1304 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1305 }
1306 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1307 {
1308 /* Case of ASCII in a face known to fit ASCII. */
1309 char2b->byte1 = 0;
1310 char2b->byte2 = c;
1311 }
1312 else
1313 {
1314 int c1, c2, charset;
1315
1316 /* Split characters into bytes. If c2 is -1 afterwards, C is
1317 really a one-byte character so that byte1 is zero. */
1318 SPLIT_CHAR (c, charset, c1, c2);
1319 if (c2 > 0)
1320 char2b->byte1 = c1, char2b->byte2 = c2;
1321 else
1322 char2b->byte1 = 0, char2b->byte2 = c1;
1323
06a2c219 1324 /* Maybe encode the character in *CHAR2B. */
ee569018 1325 if (face->font != NULL)
06a2c219
GM
1326 {
1327 struct font_info *font_info
1328 = FONT_INFO_FROM_ID (f, face->font_info_id);
1329 if (font_info)
ee569018 1330 x_encode_char (c, char2b, font_info);
06a2c219
GM
1331 }
1332 }
1333
1334 /* Make sure X resources of the face are allocated. */
1335 xassert (face != NULL);
1336 PREPARE_FACE_FOR_DISPLAY (f, face);
1337
1338 return face;
1339}
1340
1341
1342/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1343 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1344 a pointer to a realized face that is ready for display. */
1345
1346static INLINE struct face *
ee569018 1347x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1348 struct frame *f;
1349 struct glyph *glyph;
1350 XChar2b *char2b;
ee569018 1351 int *two_byte_p;
06a2c219
GM
1352{
1353 struct face *face;
1354
1355 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1356 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1357
ee569018
KH
1358 if (two_byte_p)
1359 *two_byte_p = 0;
1360
06a2c219
GM
1361 if (!glyph->multibyte_p)
1362 {
1363 /* Unibyte case. We don't have to encode, but we have to make
1364 sure to use a face suitable for unibyte. */
1365 char2b->byte1 = 0;
43d120d8 1366 char2b->byte2 = glyph->u.ch;
06a2c219 1367 }
43d120d8
KH
1368 else if (glyph->u.ch < 128
1369 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1370 {
1371 /* Case of ASCII in a face known to fit ASCII. */
1372 char2b->byte1 = 0;
43d120d8 1373 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1374 }
1375 else
1376 {
1377 int c1, c2, charset;
1378
1379 /* Split characters into bytes. If c2 is -1 afterwards, C is
1380 really a one-byte character so that byte1 is zero. */
43d120d8 1381 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1382 if (c2 > 0)
1383 char2b->byte1 = c1, char2b->byte2 = c2;
1384 else
1385 char2b->byte1 = 0, char2b->byte2 = c1;
1386
1387 /* Maybe encode the character in *CHAR2B. */
1388 if (charset != CHARSET_ASCII)
1389 {
1390 struct font_info *font_info
1391 = FONT_INFO_FROM_ID (f, face->font_info_id);
1392 if (font_info)
1393 {
43d120d8 1394 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1395 if (two_byte_p)
1396 *two_byte_p
1397 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1398 }
1399 }
1400 }
1401
1402 /* Make sure X resources of the face are allocated. */
1403 xassert (face != NULL);
1404 PREPARE_FACE_FOR_DISPLAY (f, face);
1405 return face;
1406}
1407
1408
1409/* Store one glyph for IT->char_to_display in IT->glyph_row.
1410 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1411
1412static INLINE void
1413x_append_glyph (it)
1414 struct it *it;
1415{
1416 struct glyph *glyph;
1417 enum glyph_row_area area = it->area;
1418
1419 xassert (it->glyph_row);
1420 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1421
1422 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1423 if (glyph < it->glyph_row->glyphs[area + 1])
1424 {
06a2c219
GM
1425 glyph->charpos = CHARPOS (it->position);
1426 glyph->object = it->object;
88d75730 1427 glyph->pixel_width = it->pixel_width;
06a2c219 1428 glyph->voffset = it->voffset;
88d75730 1429 glyph->type = CHAR_GLYPH;
06a2c219 1430 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1431 glyph->left_box_line_p = it->start_of_box_run_p;
1432 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1433 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1434 || it->phys_descent > it->descent);
88d75730 1435 glyph->padding_p = 0;
ee569018 1436 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1437 glyph->face_id = it->face_id;
1438 glyph->u.ch = it->char_to_display;
06a2c219
GM
1439 ++it->glyph_row->used[area];
1440 }
1441}
1442
b4192550
KH
1443/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1444 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1445
1446static INLINE void
1447x_append_composite_glyph (it)
1448 struct it *it;
1449{
1450 struct glyph *glyph;
1451 enum glyph_row_area area = it->area;
1452
1453 xassert (it->glyph_row);
1454
1455 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1456 if (glyph < it->glyph_row->glyphs[area + 1])
1457 {
b4192550
KH
1458 glyph->charpos = CHARPOS (it->position);
1459 glyph->object = it->object;
88d75730 1460 glyph->pixel_width = it->pixel_width;
b4192550 1461 glyph->voffset = it->voffset;
88d75730 1462 glyph->type = COMPOSITE_GLYPH;
b4192550 1463 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1464 glyph->left_box_line_p = it->start_of_box_run_p;
1465 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1466 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1467 || it->phys_descent > it->descent);
88d75730
GM
1468 glyph->padding_p = 0;
1469 glyph->glyph_not_available_p = 0;
1470 glyph->face_id = it->face_id;
1471 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1472 ++it->glyph_row->used[area];
1473 }
1474}
1475
06a2c219
GM
1476
1477/* Change IT->ascent and IT->height according to the setting of
1478 IT->voffset. */
1479
1480static INLINE void
1481take_vertical_position_into_account (it)
1482 struct it *it;
1483{
1484 if (it->voffset)
1485 {
1486 if (it->voffset < 0)
1487 /* Increase the ascent so that we can display the text higher
1488 in the line. */
1489 it->ascent += abs (it->voffset);
1490 else
1491 /* Increase the descent so that we can display the text lower
1492 in the line. */
1493 it->descent += it->voffset;
1494 }
1495}
1496
1497
1498/* Produce glyphs/get display metrics for the image IT is loaded with.
1499 See the description of struct display_iterator in dispextern.h for
1500 an overview of struct display_iterator. */
1501
1502static void
1503x_produce_image_glyph (it)
1504 struct it *it;
1505{
1506 struct image *img;
1507 struct face *face;
1508
1509 xassert (it->what == IT_IMAGE);
1510
1511 face = FACE_FROM_ID (it->f, it->face_id);
1512 img = IMAGE_FROM_ID (it->f, it->image_id);
1513 xassert (img);
1514
1515 /* Make sure X resources of the face and image are loaded. */
1516 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1517 prepare_image_for_display (it->f, img);
1518
95af8492 1519 it->ascent = it->phys_ascent = image_ascent (img, face);
66ac4b0e 1520 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1521 it->pixel_width = img->width + 2 * img->margin;
1522
1523 it->nglyphs = 1;
1524
1525 if (face->box != FACE_NO_BOX)
1526 {
1527 it->ascent += face->box_line_width;
1528 it->descent += face->box_line_width;
1529
1530 if (it->start_of_box_run_p)
1531 it->pixel_width += face->box_line_width;
1532 if (it->end_of_box_run_p)
1533 it->pixel_width += face->box_line_width;
1534 }
1535
1536 take_vertical_position_into_account (it);
1537
1538 if (it->glyph_row)
1539 {
1540 struct glyph *glyph;
1541 enum glyph_row_area area = it->area;
1542
1543 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1544 if (glyph < it->glyph_row->glyphs[area + 1])
1545 {
06a2c219
GM
1546 glyph->charpos = CHARPOS (it->position);
1547 glyph->object = it->object;
88d75730 1548 glyph->pixel_width = it->pixel_width;
06a2c219 1549 glyph->voffset = it->voffset;
88d75730 1550 glyph->type = IMAGE_GLYPH;
06a2c219 1551 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1552 glyph->left_box_line_p = it->start_of_box_run_p;
1553 glyph->right_box_line_p = it->end_of_box_run_p;
1554 glyph->overlaps_vertically_p = 0;
1555 glyph->padding_p = 0;
1556 glyph->glyph_not_available_p = 0;
1557 glyph->face_id = it->face_id;
1558 glyph->u.img_id = img->id;
06a2c219
GM
1559 ++it->glyph_row->used[area];
1560 }
1561 }
1562}
1563
1564
1565/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1566 of the glyph, WIDTH and HEIGHT are the width and height of the
1567 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1568 ascent of the glyph (0 <= ASCENT <= 1). */
1569
1570static void
1571x_append_stretch_glyph (it, object, width, height, ascent)
1572 struct it *it;
1573 Lisp_Object object;
1574 int width, height;
1575 double ascent;
1576{
1577 struct glyph *glyph;
1578 enum glyph_row_area area = it->area;
1579
1580 xassert (ascent >= 0 && ascent <= 1);
1581
1582 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1583 if (glyph < it->glyph_row->glyphs[area + 1])
1584 {
06a2c219
GM
1585 glyph->charpos = CHARPOS (it->position);
1586 glyph->object = object;
88d75730 1587 glyph->pixel_width = width;
06a2c219 1588 glyph->voffset = it->voffset;
88d75730 1589 glyph->type = STRETCH_GLYPH;
06a2c219 1590 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1591 glyph->left_box_line_p = it->start_of_box_run_p;
1592 glyph->right_box_line_p = it->end_of_box_run_p;
1593 glyph->overlaps_vertically_p = 0;
1594 glyph->padding_p = 0;
1595 glyph->glyph_not_available_p = 0;
1596 glyph->face_id = it->face_id;
1597 glyph->u.stretch.ascent = height * ascent;
1598 glyph->u.stretch.height = height;
06a2c219
GM
1599 ++it->glyph_row->used[area];
1600 }
1601}
1602
1603
1604/* Produce a stretch glyph for iterator IT. IT->object is the value
1605 of the glyph property displayed. The value must be a list
1606 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1607 being recognized:
1608
1609 1. `:width WIDTH' specifies that the space should be WIDTH *
1610 canonical char width wide. WIDTH may be an integer or floating
1611 point number.
1612
1613 2. `:relative-width FACTOR' specifies that the width of the stretch
1614 should be computed from the width of the first character having the
1615 `glyph' property, and should be FACTOR times that width.
1616
1617 3. `:align-to HPOS' specifies that the space should be wide enough
1618 to reach HPOS, a value in canonical character units.
1619
1620 Exactly one of the above pairs must be present.
1621
1622 4. `:height HEIGHT' specifies that the height of the stretch produced
1623 should be HEIGHT, measured in canonical character units.
1624
1625 5. `:relative-height FACTOR' specifies that the height of the the
1626 stretch should be FACTOR times the height of the characters having
1627 the glyph property.
1628
1629 Either none or exactly one of 4 or 5 must be present.
1630
1631 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1632 of the stretch should be used for the ascent of the stretch.
1633 ASCENT must be in the range 0 <= ASCENT <= 100. */
1634
1635#define NUMVAL(X) \
1636 ((INTEGERP (X) || FLOATP (X)) \
1637 ? XFLOATINT (X) \
1638 : - 1)
1639
1640
1641static void
1642x_produce_stretch_glyph (it)
1643 struct it *it;
1644{
1645 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1646#if GLYPH_DEBUG
1647 extern Lisp_Object Qspace;
1648#endif
1649 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1650 extern Lisp_Object QCrelative_width, QCrelative_height;
1651 extern Lisp_Object QCalign_to;
1652 Lisp_Object prop, plist;
1653 double width = 0, height = 0, ascent = 0;
1654 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1655 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1656
1657 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1658
1659 /* List should start with `space'. */
1660 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1661 plist = XCDR (it->object);
1662
1663 /* Compute the width of the stretch. */
1664 if (prop = Fplist_get (plist, QCwidth),
1665 NUMVAL (prop) > 0)
1666 /* Absolute width `:width WIDTH' specified and valid. */
1667 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1668 else if (prop = Fplist_get (plist, QCrelative_width),
1669 NUMVAL (prop) > 0)
1670 {
1671 /* Relative width `:relative-width FACTOR' specified and valid.
1672 Compute the width of the characters having the `glyph'
1673 property. */
1674 struct it it2;
1675 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1676
1677 it2 = *it;
1678 if (it->multibyte_p)
1679 {
1680 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1681 - IT_BYTEPOS (*it));
1682 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1683 }
1684 else
1685 it2.c = *p, it2.len = 1;
1686
1687 it2.glyph_row = NULL;
1688 it2.what = IT_CHARACTER;
1689 x_produce_glyphs (&it2);
1690 width = NUMVAL (prop) * it2.pixel_width;
1691 }
1692 else if (prop = Fplist_get (plist, QCalign_to),
1693 NUMVAL (prop) > 0)
1694 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1695 else
1696 /* Nothing specified -> width defaults to canonical char width. */
1697 width = CANON_X_UNIT (it->f);
1698
1699 /* Compute height. */
1700 if (prop = Fplist_get (plist, QCheight),
1701 NUMVAL (prop) > 0)
1702 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1703 else if (prop = Fplist_get (plist, QCrelative_height),
1704 NUMVAL (prop) > 0)
1705 height = FONT_HEIGHT (font) * NUMVAL (prop);
1706 else
1707 height = FONT_HEIGHT (font);
1708
1709 /* Compute percentage of height used for ascent. If
1710 `:ascent ASCENT' is present and valid, use that. Otherwise,
1711 derive the ascent from the font in use. */
1712 if (prop = Fplist_get (plist, QCascent),
1713 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1714 ascent = NUMVAL (prop) / 100.0;
1715 else
1716 ascent = (double) font->ascent / FONT_HEIGHT (font);
1717
1718 if (width <= 0)
1719 width = 1;
1720 if (height <= 0)
1721 height = 1;
1722
1723 if (it->glyph_row)
1724 {
1725 Lisp_Object object = it->stack[it->sp - 1].string;
1726 if (!STRINGP (object))
1727 object = it->w->buffer;
1728 x_append_stretch_glyph (it, object, width, height, ascent);
1729 }
1730
1731 it->pixel_width = width;
66ac4b0e
GM
1732 it->ascent = it->phys_ascent = height * ascent;
1733 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1734 it->nglyphs = 1;
1735
1736 if (face->box != FACE_NO_BOX)
1737 {
1738 it->ascent += face->box_line_width;
1739 it->descent += face->box_line_width;
1740
1741 if (it->start_of_box_run_p)
1742 it->pixel_width += face->box_line_width;
1743 if (it->end_of_box_run_p)
1744 it->pixel_width += face->box_line_width;
1745 }
1746
1747 take_vertical_position_into_account (it);
1748}
1749
b4192550
KH
1750/* Return proper value to be used as baseline offset of font that has
1751 ASCENT and DESCENT to draw characters by the font at the vertical
1752 center of the line of frame F.
1753
1754 Here, out task is to find the value of BOFF in the following figure;
1755
1756 -------------------------+-----------+-
1757 -+-+---------+-+ | |
1758 | | | | | |
1759 | | | | F_ASCENT F_HEIGHT
1760 | | | ASCENT | |
1761 HEIGHT | | | | |
1762 | | |-|-+------+-----------|------- baseline
1763 | | | | BOFF | |
1764 | |---------|-+-+ | |
1765 | | | DESCENT | |
1766 -+-+---------+-+ F_DESCENT |
1767 -------------------------+-----------+-
1768
1769 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1770 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1771 DESCENT = FONT->descent
1772 HEIGHT = FONT_HEIGHT (FONT)
1773 F_DESCENT = (F->output_data.x->font->descent
1774 - F->output_data.x->baseline_offset)
1775 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1776*/
1777
458f45fa
KH
1778#define VCENTER_BASELINE_OFFSET(FONT, F) \
1779 ((FONT)->descent \
1780 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1781 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1782 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1783
1784/* Produce glyphs/get display metrics for the display element IT is
1785 loaded with. See the description of struct display_iterator in
1786 dispextern.h for an overview of struct display_iterator. */
1787
1788static void
1789x_produce_glyphs (it)
1790 struct it *it;
1791{
ee569018
KH
1792 it->glyph_not_available_p = 0;
1793
06a2c219
GM
1794 if (it->what == IT_CHARACTER)
1795 {
1796 XChar2b char2b;
1797 XFontStruct *font;
ee569018 1798 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1799 XCharStruct *pcm;
06a2c219 1800 int font_not_found_p;
b4192550
KH
1801 struct font_info *font_info;
1802 int boff; /* baseline offset */
a4249304
KH
1803 /* We may change it->multibyte_p upon unibyte<->multibyte
1804 conversion. So, save the current value now and restore it
1805 later.
1806
1807 Note: It seems that we don't have to record multibyte_p in
1808 struct glyph because the character code itself tells if or
1809 not the character is multibyte. Thus, in the future, we must
1810 consider eliminating the field `multibyte_p' in the struct
1811 glyph.
1812 */
1813 int saved_multibyte_p = it->multibyte_p;
06a2c219 1814
ee569018
KH
1815 /* Maybe translate single-byte characters to multibyte, or the
1816 other way. */
06a2c219 1817 it->char_to_display = it->c;
ee569018 1818 if (!ASCII_BYTE_P (it->c))
06a2c219 1819 {
ee569018
KH
1820 if (unibyte_display_via_language_environment
1821 && SINGLE_BYTE_CHAR_P (it->c)
1822 && (it->c >= 0240
1823 || !NILP (Vnonascii_translation_table)))
1824 {
1825 it->char_to_display = unibyte_char_to_multibyte (it->c);
a4249304 1826 it->multibyte_p = 1;
ee569018
KH
1827 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1828 face = FACE_FROM_ID (it->f, it->face_id);
1829 }
1830 else if (!SINGLE_BYTE_CHAR_P (it->c)
1831 && !it->multibyte_p)
1832 {
1833 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
a4249304 1834 it->multibyte_p = 0;
ee569018
KH
1835 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1836 face = FACE_FROM_ID (it->f, it->face_id);
1837 }
06a2c219
GM
1838 }
1839
ee569018
KH
1840 /* Get font to use. Encode IT->char_to_display. */
1841 x_get_char_face_and_encoding (it->f, it->char_to_display,
1842 it->face_id, &char2b,
1843 it->multibyte_p);
06a2c219
GM
1844 font = face->font;
1845
1846 /* When no suitable font found, use the default font. */
1847 font_not_found_p = font == NULL;
1848 if (font_not_found_p)
b4192550
KH
1849 {
1850 font = FRAME_FONT (it->f);
1851 boff = it->f->output_data.x->baseline_offset;
1852 font_info = NULL;
1853 }
1854 else
1855 {
1856 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1857 boff = font_info->baseline_offset;
1858 if (font_info->vertical_centering)
1859 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1860 }
06a2c219
GM
1861
1862 if (it->char_to_display >= ' '
1863 && (!it->multibyte_p || it->char_to_display < 128))
1864 {
1865 /* Either unibyte or ASCII. */
1866 int stretched_p;
1867
1868 it->nglyphs = 1;
06a2c219
GM
1869
1870 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1871 it->ascent = font->ascent + boff;
1872 it->descent = font->descent - boff;
474848ac
GM
1873
1874 if (pcm)
1875 {
1876 it->phys_ascent = pcm->ascent + boff;
1877 it->phys_descent = pcm->descent - boff;
1878 it->pixel_width = pcm->width;
1879 }
1880 else
1881 {
1882 it->glyph_not_available_p = 1;
1883 it->phys_ascent = font->ascent + boff;
1884 it->phys_descent = font->descent - boff;
1885 it->pixel_width = FONT_WIDTH (font);
1886 }
06a2c219
GM
1887
1888 /* If this is a space inside a region of text with
1889 `space-width' property, change its width. */
1890 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1891 if (stretched_p)
1892 it->pixel_width *= XFLOATINT (it->space_width);
1893
1894 /* If face has a box, add the box thickness to the character
1895 height. If character has a box line to the left and/or
1896 right, add the box line width to the character's width. */
1897 if (face->box != FACE_NO_BOX)
1898 {
1899 int thick = face->box_line_width;
1900
1901 it->ascent += thick;
1902 it->descent += thick;
1903
1904 if (it->start_of_box_run_p)
1905 it->pixel_width += thick;
1906 if (it->end_of_box_run_p)
1907 it->pixel_width += thick;
1908 }
1909
1910 /* If face has an overline, add the height of the overline
1911 (1 pixel) and a 1 pixel margin to the character height. */
1912 if (face->overline_p)
1913 it->ascent += 2;
1914
1915 take_vertical_position_into_account (it);
1916
1917 /* If we have to actually produce glyphs, do it. */
1918 if (it->glyph_row)
1919 {
1920 if (stretched_p)
1921 {
1922 /* Translate a space with a `space-width' property
1923 into a stretch glyph. */
1924 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1925 x_append_stretch_glyph (it, it->object, it->pixel_width,
1926 it->ascent + it->descent, ascent);
1927 }
1928 else
1929 x_append_glyph (it);
1930
1931 /* If characters with lbearing or rbearing are displayed
1932 in this line, record that fact in a flag of the
1933 glyph row. This is used to optimize X output code. */
1c7e22fd 1934 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1935 it->glyph_row->contains_overlapping_glyphs_p = 1;
1936 }
1937 }
1938 else if (it->char_to_display == '\n')
1939 {
1940 /* A newline has no width but we need the height of the line. */
1941 it->pixel_width = 0;
1942 it->nglyphs = 0;
b4192550
KH
1943 it->ascent = it->phys_ascent = font->ascent + boff;
1944 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1945
1946 if (face->box != FACE_NO_BOX)
1947 {
1948 int thick = face->box_line_width;
1949 it->ascent += thick;
1950 it->descent += thick;
1951 }
1952 }
1953 else if (it->char_to_display == '\t')
1954 {
1955 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1956 int x = it->current_x + it->continuation_lines_width;
06a2c219 1957 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2a32b5ea
GM
1958
1959 /* If the distance from the current position to the next tab
1960 stop is less than a canonical character width, use the
1961 tab stop after that. */
1962 if (next_tab_x - x < CANON_X_UNIT (it->f))
1963 next_tab_x += tab_width;
06a2c219
GM
1964
1965 it->pixel_width = next_tab_x - x;
1966 it->nglyphs = 1;
b4192550
KH
1967 it->ascent = it->phys_ascent = font->ascent + boff;
1968 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1969
1970 if (it->glyph_row)
1971 {
1972 double ascent = (double) it->ascent / (it->ascent + it->descent);
1973 x_append_stretch_glyph (it, it->object, it->pixel_width,
1974 it->ascent + it->descent, ascent);
1975 }
1976 }
1977 else
1978 {
1979 /* A multi-byte character. Assume that the display width of the
1980 character is the width of the character multiplied by the
b4192550 1981 width of the font. */
06a2c219 1982
b4192550
KH
1983 /* If we found a font, this font should give us the right
1984 metrics. If we didn't find a font, use the frame's
1985 default font and calculate the width of the character
1986 from the charset width; this is what old redisplay code
1987 did. */
1988 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1989 if (font_not_found_p || !pcm)
1990 {
1991 int charset = CHAR_CHARSET (it->char_to_display);
1992
1993 it->glyph_not_available_p = 1;
1994 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1995 * CHARSET_WIDTH (charset));
1996 it->phys_ascent = font->ascent + boff;
1997 it->phys_descent = font->descent - boff;
1998 }
1999 else
2000 {
2001 it->pixel_width = pcm->width;
2002 it->phys_ascent = pcm->ascent + boff;
2003 it->phys_descent = pcm->descent - boff;
2004 if (it->glyph_row
2005 && (pcm->lbearing < 0
2006 || pcm->rbearing > pcm->width))
2007 it->glyph_row->contains_overlapping_glyphs_p = 1;
2008 }
b4192550
KH
2009 it->nglyphs = 1;
2010 it->ascent = font->ascent + boff;
2011 it->descent = font->descent - boff;
06a2c219
GM
2012 if (face->box != FACE_NO_BOX)
2013 {
2014 int thick = face->box_line_width;
2015 it->ascent += thick;
2016 it->descent += thick;
2017
2018 if (it->start_of_box_run_p)
2019 it->pixel_width += thick;
2020 if (it->end_of_box_run_p)
2021 it->pixel_width += thick;
2022 }
2023
2024 /* If face has an overline, add the height of the overline
2025 (1 pixel) and a 1 pixel margin to the character height. */
2026 if (face->overline_p)
2027 it->ascent += 2;
2028
2029 take_vertical_position_into_account (it);
2030
2031 if (it->glyph_row)
2032 x_append_glyph (it);
2033 }
a4249304 2034 it->multibyte_p = saved_multibyte_p;
06a2c219 2035 }
b4192550
KH
2036 else if (it->what == IT_COMPOSITION)
2037 {
2038 /* Note: A composition is represented as one glyph in the
2039 glyph matrix. There are no padding glyphs. */
2040 XChar2b char2b;
2041 XFontStruct *font;
ee569018 2042 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2043 XCharStruct *pcm;
2044 int font_not_found_p;
2045 struct font_info *font_info;
2046 int boff; /* baseline offset */
2047 struct composition *cmp = composition_table[it->cmp_id];
2048
2049 /* Maybe translate single-byte characters to multibyte. */
2050 it->char_to_display = it->c;
2051 if (unibyte_display_via_language_environment
2052 && SINGLE_BYTE_CHAR_P (it->c)
2053 && (it->c >= 0240
2054 || (it->c >= 0200
2055 && !NILP (Vnonascii_translation_table))))
2056 {
2057 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2058 }
2059
2060 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2061 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2062 face = FACE_FROM_ID (it->f, it->face_id);
2063 x_get_char_face_and_encoding (it->f, it->char_to_display,
2064 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2065 font = face->font;
2066
2067 /* When no suitable font found, use the default font. */
2068 font_not_found_p = font == NULL;
2069 if (font_not_found_p)
2070 {
2071 font = FRAME_FONT (it->f);
2072 boff = it->f->output_data.x->baseline_offset;
2073 font_info = NULL;
2074 }
2075 else
2076 {
2077 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2078 boff = font_info->baseline_offset;
2079 if (font_info->vertical_centering)
2080 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2081 }
2082
2083 /* There are no padding glyphs, so there is only one glyph to
2084 produce for the composition. Important is that pixel_width,
2085 ascent and descent are the values of what is drawn by
2086 draw_glyphs (i.e. the values of the overall glyphs composed). */
2087 it->nglyphs = 1;
2088
2089 /* If we have not yet calculated pixel size data of glyphs of
2090 the composition for the current face font, calculate them
2091 now. Theoretically, we have to check all fonts for the
2092 glyphs, but that requires much time and memory space. So,
2093 here we check only the font of the first glyph. This leads
2094 to incorrect display very rarely, and C-l (recenter) can
2095 correct the display anyway. */
2096 if (cmp->font != (void *) font)
2097 {
2098 /* Ascent and descent of the font of the first character of
2099 this composition (adjusted by baseline offset). Ascent
2100 and descent of overall glyphs should not be less than
2101 them respectively. */
2102 int font_ascent = font->ascent + boff;
2103 int font_descent = font->descent - boff;
2104 /* Bounding box of the overall glyphs. */
2105 int leftmost, rightmost, lowest, highest;
329bed06 2106 int i, width, ascent, descent;
b4192550
KH
2107
2108 cmp->font = (void *) font;
2109
2110 /* Initialize the bounding box. */
2111 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2112 if (pcm)
2113 {
2114 width = pcm->width;
2115 ascent = pcm->ascent;
2116 descent = pcm->descent;
2117 }
2118 else
2119 {
2120 width = FONT_WIDTH (font);
2121 ascent = font->ascent;
2122 descent = font->descent;
2123 }
2124
2125 rightmost = width;
2126 lowest = - descent + boff;
2127 highest = ascent + boff;
b4192550 2128 leftmost = 0;
329bed06 2129
b4192550
KH
2130 if (font_info
2131 && font_info->default_ascent
2132 && CHAR_TABLE_P (Vuse_default_ascent)
2133 && !NILP (Faref (Vuse_default_ascent,
2134 make_number (it->char_to_display))))
2135 highest = font_info->default_ascent + boff;
2136
2137 /* Draw the first glyph at the normal position. It may be
2138 shifted to right later if some other glyphs are drawn at
2139 the left. */
2140 cmp->offsets[0] = 0;
2141 cmp->offsets[1] = boff;
2142
2143 /* Set cmp->offsets for the remaining glyphs. */
2144 for (i = 1; i < cmp->glyph_len; i++)
2145 {
2146 int left, right, btm, top;
2147 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2148 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2149
2150 face = FACE_FROM_ID (it->f, face_id);
2151 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2152 it->multibyte_p);
b4192550
KH
2153 font = face->font;
2154 if (font == NULL)
2155 {
2156 font = FRAME_FONT (it->f);
2157 boff = it->f->output_data.x->baseline_offset;
2158 font_info = NULL;
2159 }
2160 else
2161 {
2162 font_info
2163 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2164 boff = font_info->baseline_offset;
2165 if (font_info->vertical_centering)
2166 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2167 }
2168
2169 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2170 if (pcm)
2171 {
2172 width = pcm->width;
2173 ascent = pcm->ascent;
2174 descent = pcm->descent;
2175 }
2176 else
2177 {
2178 width = FONT_WIDTH (font);
2179 ascent = font->ascent;
2180 descent = font->descent;
2181 }
b4192550
KH
2182
2183 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2184 {
2185 /* Relative composition with or without
2186 alternate chars. */
329bed06
GM
2187 left = (leftmost + rightmost - width) / 2;
2188 btm = - descent + boff;
b4192550
KH
2189 if (font_info && font_info->relative_compose
2190 && (! CHAR_TABLE_P (Vignore_relative_composition)
2191 || NILP (Faref (Vignore_relative_composition,
2192 make_number (ch)))))
2193 {
2194
329bed06 2195 if (- descent >= font_info->relative_compose)
b4192550
KH
2196 /* One extra pixel between two glyphs. */
2197 btm = highest + 1;
329bed06 2198 else if (ascent <= 0)
b4192550 2199 /* One extra pixel between two glyphs. */
329bed06 2200 btm = lowest - 1 - ascent - descent;
b4192550
KH
2201 }
2202 }
2203 else
2204 {
2205 /* A composition rule is specified by an integer
2206 value that encodes global and new reference
2207 points (GREF and NREF). GREF and NREF are
2208 specified by numbers as below:
2209
2210 0---1---2 -- ascent
2211 | |
2212 | |
2213 | |
2214 9--10--11 -- center
2215 | |
2216 ---3---4---5--- baseline
2217 | |
2218 6---7---8 -- descent
2219 */
2220 int rule = COMPOSITION_RULE (cmp, i);
2221 int gref, nref, grefx, grefy, nrefx, nrefy;
2222
2223 COMPOSITION_DECODE_RULE (rule, gref, nref);
2224 grefx = gref % 3, nrefx = nref % 3;
2225 grefy = gref / 3, nrefy = nref / 3;
2226
2227 left = (leftmost
2228 + grefx * (rightmost - leftmost) / 2
329bed06 2229 - nrefx * width / 2);
b4192550
KH
2230 btm = ((grefy == 0 ? highest
2231 : grefy == 1 ? 0
2232 : grefy == 2 ? lowest
2233 : (highest + lowest) / 2)
329bed06
GM
2234 - (nrefy == 0 ? ascent + descent
2235 : nrefy == 1 ? descent - boff
b4192550 2236 : nrefy == 2 ? 0
329bed06 2237 : (ascent + descent) / 2));
b4192550
KH
2238 }
2239
2240 cmp->offsets[i * 2] = left;
329bed06 2241 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2242
2243 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2244 right = left + width;
2245 top = btm + descent + ascent;
b4192550
KH
2246 if (left < leftmost)
2247 leftmost = left;
2248 if (right > rightmost)
2249 rightmost = right;
2250 if (top > highest)
2251 highest = top;
2252 if (btm < lowest)
2253 lowest = btm;
2254 }
2255
2256 /* If there are glyphs whose x-offsets are negative,
2257 shift all glyphs to the right and make all x-offsets
2258 non-negative. */
2259 if (leftmost < 0)
2260 {
2261 for (i = 0; i < cmp->glyph_len; i++)
2262 cmp->offsets[i * 2] -= leftmost;
2263 rightmost -= leftmost;
2264 }
2265
2266 cmp->pixel_width = rightmost;
2267 cmp->ascent = highest;
2268 cmp->descent = - lowest;
2269 if (cmp->ascent < font_ascent)
2270 cmp->ascent = font_ascent;
2271 if (cmp->descent < font_descent)
2272 cmp->descent = font_descent;
2273 }
2274
2275 it->pixel_width = cmp->pixel_width;
2276 it->ascent = it->phys_ascent = cmp->ascent;
2277 it->descent = it->phys_descent = cmp->descent;
2278
2279 if (face->box != FACE_NO_BOX)
2280 {
2281 int thick = face->box_line_width;
2282 it->ascent += thick;
2283 it->descent += thick;
2284
2285 if (it->start_of_box_run_p)
2286 it->pixel_width += thick;
2287 if (it->end_of_box_run_p)
2288 it->pixel_width += thick;
2289 }
2290
2291 /* If face has an overline, add the height of the overline
2292 (1 pixel) and a 1 pixel margin to the character height. */
2293 if (face->overline_p)
2294 it->ascent += 2;
2295
2296 take_vertical_position_into_account (it);
2297
2298 if (it->glyph_row)
2299 x_append_composite_glyph (it);
2300 }
06a2c219
GM
2301 else if (it->what == IT_IMAGE)
2302 x_produce_image_glyph (it);
2303 else if (it->what == IT_STRETCH)
2304 x_produce_stretch_glyph (it);
2305
3017fdd1
GM
2306 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2307 because this isn't true for images with `:ascent 100'. */
2308 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2309 if (it->area == TEXT_AREA)
2310 it->current_x += it->pixel_width;
66ac4b0e 2311
d365f5bb
GM
2312 it->descent += it->extra_line_spacing;
2313
06a2c219
GM
2314 it->max_ascent = max (it->max_ascent, it->ascent);
2315 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2316 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2317 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2318}
2319
2320
2321/* Estimate the pixel height of the mode or top line on frame F.
2322 FACE_ID specifies what line's height to estimate. */
2323
2324int
2325x_estimate_mode_line_height (f, face_id)
2326 struct frame *f;
2327 enum face_id face_id;
2328{
2329 int height = 1;
2330
2331 /* This function is called so early when Emacs starts that the face
2332 cache and mode line face are not yet initialized. */
2333 if (FRAME_FACE_CACHE (f))
2334 {
2335 struct face *face = FACE_FROM_ID (f, face_id);
2336 if (face)
2337 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2338 }
2339
2340 return height;
2341}
2342
2343\f
2344/***********************************************************************
2345 Glyph display
2346 ***********************************************************************/
2347
2348/* A sequence of glyphs to be drawn in the same face.
2349
2350 This data structure is not really completely X specific, so it
2351 could possibly, at least partially, be useful for other systems. It
2352 is currently not part of the external redisplay interface because
2353 it's not clear what other systems will need. */
2354
2355struct glyph_string
2356{
2357 /* X-origin of the string. */
2358 int x;
2359
2360 /* Y-origin and y-position of the base line of this string. */
2361 int y, ybase;
2362
2363 /* The width of the string, not including a face extension. */
2364 int width;
2365
2366 /* The width of the string, including a face extension. */
2367 int background_width;
2368
2369 /* The height of this string. This is the height of the line this
2370 string is drawn in, and can be different from the height of the
2371 font the string is drawn in. */
2372 int height;
2373
2374 /* Number of pixels this string overwrites in front of its x-origin.
2375 This number is zero if the string has an lbearing >= 0; it is
2376 -lbearing, if the string has an lbearing < 0. */
2377 int left_overhang;
2378
2379 /* Number of pixels this string overwrites past its right-most
2380 nominal x-position, i.e. x + width. Zero if the string's
2381 rbearing is <= its nominal width, rbearing - width otherwise. */
2382 int right_overhang;
2383
2384 /* The frame on which the glyph string is drawn. */
2385 struct frame *f;
2386
2387 /* The window on which the glyph string is drawn. */
2388 struct window *w;
2389
2390 /* X display and window for convenience. */
2391 Display *display;
2392 Window window;
2393
2394 /* The glyph row for which this string was built. It determines the
2395 y-origin and height of the string. */
2396 struct glyph_row *row;
2397
2398 /* The area within row. */
2399 enum glyph_row_area area;
2400
2401 /* Characters to be drawn, and number of characters. */
2402 XChar2b *char2b;
2403 int nchars;
2404
06a2c219
GM
2405 /* A face-override for drawing cursors, mouse face and similar. */
2406 enum draw_glyphs_face hl;
2407
2408 /* Face in which this string is to be drawn. */
2409 struct face *face;
2410
2411 /* Font in which this string is to be drawn. */
2412 XFontStruct *font;
2413
2414 /* Font info for this string. */
2415 struct font_info *font_info;
2416
b4192550
KH
2417 /* Non-null means this string describes (part of) a composition.
2418 All characters from char2b are drawn composed. */
2419 struct composition *cmp;
06a2c219
GM
2420
2421 /* Index of this glyph string's first character in the glyph
b4192550
KH
2422 definition of CMP. If this is zero, this glyph string describes
2423 the first character of a composition. */
06a2c219
GM
2424 int gidx;
2425
2426 /* 1 means this glyph strings face has to be drawn to the right end
2427 of the window's drawing area. */
2428 unsigned extends_to_end_of_line_p : 1;
2429
2430 /* 1 means the background of this string has been drawn. */
2431 unsigned background_filled_p : 1;
2432
2433 /* 1 means glyph string must be drawn with 16-bit functions. */
2434 unsigned two_byte_p : 1;
2435
2436 /* 1 means that the original font determined for drawing this glyph
2437 string could not be loaded. The member `font' has been set to
2438 the frame's default font in this case. */
2439 unsigned font_not_found_p : 1;
2440
2441 /* 1 means that the face in which this glyph string is drawn has a
2442 stipple pattern. */
2443 unsigned stippled_p : 1;
2444
66ac4b0e
GM
2445 /* 1 means only the foreground of this glyph string must be drawn,
2446 and we should use the physical height of the line this glyph
2447 string appears in as clip rect. */
2448 unsigned for_overlaps_p : 1;
2449
06a2c219
GM
2450 /* The GC to use for drawing this glyph string. */
2451 GC gc;
2452
2453 /* A pointer to the first glyph in the string. This glyph
2454 corresponds to char2b[0]. Needed to draw rectangles if
2455 font_not_found_p is 1. */
2456 struct glyph *first_glyph;
2457
2458 /* Image, if any. */
2459 struct image *img;
2460
2461 struct glyph_string *next, *prev;
2462};
2463
2464
5c187dee 2465#if 0
06a2c219
GM
2466
2467static void
2468x_dump_glyph_string (s)
2469 struct glyph_string *s;
2470{
2471 fprintf (stderr, "glyph string\n");
2472 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2473 s->x, s->y, s->width, s->height);
2474 fprintf (stderr, " ybase = %d\n", s->ybase);
2475 fprintf (stderr, " hl = %d\n", s->hl);
2476 fprintf (stderr, " left overhang = %d, right = %d\n",
2477 s->left_overhang, s->right_overhang);
2478 fprintf (stderr, " nchars = %d\n", s->nchars);
2479 fprintf (stderr, " extends to end of line = %d\n",
2480 s->extends_to_end_of_line_p);
2481 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2482 fprintf (stderr, " bg width = %d\n", s->background_width);
2483}
2484
2485#endif /* GLYPH_DEBUG */
2486
2487
2488
2489static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2490 struct glyph_string **,
2491 struct glyph_string *,
2492 struct glyph_string *));
2493static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2494 struct glyph_string **,
2495 struct glyph_string *,
2496 struct glyph_string *));
2497static void x_append_glyph_string P_ ((struct glyph_string **,
2498 struct glyph_string **,
2499 struct glyph_string *));
2500static int x_left_overwritten P_ ((struct glyph_string *));
2501static int x_left_overwriting P_ ((struct glyph_string *));
2502static int x_right_overwritten P_ ((struct glyph_string *));
2503static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2504static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2505 int));
06a2c219
GM
2506static void x_init_glyph_string P_ ((struct glyph_string *,
2507 XChar2b *, struct window *,
2508 struct glyph_row *,
2509 enum glyph_row_area, int,
2510 enum draw_glyphs_face));
2511static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2512 enum glyph_row_area, int, int,
66ac4b0e 2513 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2514static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2515static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2516static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2517 int));
2518static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2519static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2520static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2521static void x_draw_glyph_string P_ ((struct glyph_string *));
2522static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2523static void x_set_cursor_gc P_ ((struct glyph_string *));
2524static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2525static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2526static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2527 int *, int *));
2528static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2529static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2530 unsigned long *, double, int));
06a2c219 2531static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2532 double, int, unsigned long));
06a2c219
GM
2533static void x_setup_relief_colors P_ ((struct glyph_string *));
2534static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2535static void x_draw_image_relief P_ ((struct glyph_string *));
2536static void x_draw_image_foreground P_ ((struct glyph_string *));
2537static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2538static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2539static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2540 int, int, int));
2541static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2542 int, int, int, int, XRectangle *));
2543static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2544 int, int, int, XRectangle *));
66ac4b0e
GM
2545static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2546 enum glyph_row_area));
209f68d9
GM
2547static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2548 struct glyph_row *,
2549 enum glyph_row_area, int, int));
06a2c219 2550
163dcff3
GM
2551#if GLYPH_DEBUG
2552static void x_check_font P_ ((struct frame *, XFontStruct *));
2553#endif
2554
06a2c219 2555
06a2c219
GM
2556/* Append the list of glyph strings with head H and tail T to the list
2557 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2558
2559static INLINE void
2560x_append_glyph_string_lists (head, tail, h, t)
2561 struct glyph_string **head, **tail;
2562 struct glyph_string *h, *t;
2563{
2564 if (h)
2565 {
2566 if (*head)
2567 (*tail)->next = h;
2568 else
2569 *head = h;
2570 h->prev = *tail;
2571 *tail = t;
2572 }
2573}
2574
2575
2576/* Prepend the list of glyph strings with head H and tail T to the
2577 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2578 result. */
2579
2580static INLINE void
2581x_prepend_glyph_string_lists (head, tail, h, t)
2582 struct glyph_string **head, **tail;
2583 struct glyph_string *h, *t;
2584{
2585 if (h)
2586 {
2587 if (*head)
2588 (*head)->prev = t;
2589 else
2590 *tail = t;
2591 t->next = *head;
2592 *head = h;
2593 }
2594}
2595
2596
2597/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2598 Set *HEAD and *TAIL to the resulting list. */
2599
2600static INLINE void
2601x_append_glyph_string (head, tail, s)
2602 struct glyph_string **head, **tail;
2603 struct glyph_string *s;
2604{
2605 s->next = s->prev = NULL;
2606 x_append_glyph_string_lists (head, tail, s, s);
2607}
2608
2609
2610/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2611 face. */
2612
2613static void
2614x_set_cursor_gc (s)
2615 struct glyph_string *s;
2616{
2617 if (s->font == FRAME_FONT (s->f)
2618 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2619 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2620 && !s->cmp)
06a2c219
GM
2621 s->gc = s->f->output_data.x->cursor_gc;
2622 else
2623 {
2624 /* Cursor on non-default face: must merge. */
2625 XGCValues xgcv;
2626 unsigned long mask;
2627
2628 xgcv.background = s->f->output_data.x->cursor_pixel;
2629 xgcv.foreground = s->face->background;
2630
2631 /* If the glyph would be invisible, try a different foreground. */
2632 if (xgcv.foreground == xgcv.background)
2633 xgcv.foreground = s->face->foreground;
2634 if (xgcv.foreground == xgcv.background)
2635 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2636 if (xgcv.foreground == xgcv.background)
2637 xgcv.foreground = s->face->foreground;
2638
2639 /* Make sure the cursor is distinct from text in this face. */
2640 if (xgcv.background == s->face->background
2641 && xgcv.foreground == s->face->foreground)
2642 {
2643 xgcv.background = s->face->foreground;
2644 xgcv.foreground = s->face->background;
2645 }
2646
2647 IF_DEBUG (x_check_font (s->f, s->font));
2648 xgcv.font = s->font->fid;
2649 xgcv.graphics_exposures = False;
2650 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2651
2652 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2653 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2654 mask, &xgcv);
2655 else
2656 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2657 = XCreateGC (s->display, s->window, mask, &xgcv);
2658
2659 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2660 }
2661}
2662
2663
2664/* Set up S->gc of glyph string S for drawing text in mouse face. */
2665
2666static void
2667x_set_mouse_face_gc (s)
2668 struct glyph_string *s;
2669{
2670 int face_id;
ee569018 2671 struct face *face;
06a2c219
GM
2672
2673 /* What face has to be used for the mouse face? */
2674 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2675 face = FACE_FROM_ID (s->f, face_id);
033e3e18
GM
2676 if (s->first_glyph->type == CHAR_GLYPH)
2677 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2678 else
2679 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2680 s->face = FACE_FROM_ID (s->f, face_id);
2681 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2682
2683 /* If font in this face is same as S->font, use it. */
2684 if (s->font == s->face->font)
2685 s->gc = s->face->gc;
2686 else
2687 {
2688 /* Otherwise construct scratch_cursor_gc with values from FACE
2689 but font FONT. */
2690 XGCValues xgcv;
2691 unsigned long mask;
2692
2693 xgcv.background = s->face->background;
2694 xgcv.foreground = s->face->foreground;
2695 IF_DEBUG (x_check_font (s->f, s->font));
2696 xgcv.font = s->font->fid;
2697 xgcv.graphics_exposures = False;
2698 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2699
2700 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2701 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2702 mask, &xgcv);
2703 else
2704 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2705 = XCreateGC (s->display, s->window, mask, &xgcv);
2706
2707 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2708 }
2709
2710 xassert (s->gc != 0);
2711}
2712
2713
2714/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2715 Faces to use in the mode line have already been computed when the
2716 matrix was built, so there isn't much to do, here. */
2717
2718static INLINE void
2719x_set_mode_line_face_gc (s)
2720 struct glyph_string *s;
2721{
2722 s->gc = s->face->gc;
06a2c219
GM
2723}
2724
2725
2726/* Set S->gc of glyph string S for drawing that glyph string. Set
2727 S->stippled_p to a non-zero value if the face of S has a stipple
2728 pattern. */
2729
2730static INLINE void
2731x_set_glyph_string_gc (s)
2732 struct glyph_string *s;
2733{
209f68d9
GM
2734 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2735
06a2c219
GM
2736 if (s->hl == DRAW_NORMAL_TEXT)
2737 {
2738 s->gc = s->face->gc;
2739 s->stippled_p = s->face->stipple != 0;
2740 }
2741 else if (s->hl == DRAW_INVERSE_VIDEO)
2742 {
2743 x_set_mode_line_face_gc (s);
2744 s->stippled_p = s->face->stipple != 0;
2745 }
2746 else if (s->hl == DRAW_CURSOR)
2747 {
2748 x_set_cursor_gc (s);
2749 s->stippled_p = 0;
2750 }
2751 else if (s->hl == DRAW_MOUSE_FACE)
2752 {
2753 x_set_mouse_face_gc (s);
2754 s->stippled_p = s->face->stipple != 0;
2755 }
2756 else if (s->hl == DRAW_IMAGE_RAISED
2757 || s->hl == DRAW_IMAGE_SUNKEN)
2758 {
2759 s->gc = s->face->gc;
2760 s->stippled_p = s->face->stipple != 0;
2761 }
2762 else
2763 {
2764 s->gc = s->face->gc;
2765 s->stippled_p = s->face->stipple != 0;
2766 }
2767
2768 /* GC must have been set. */
2769 xassert (s->gc != 0);
2770}
2771
2772
2773/* Return in *R the clipping rectangle for glyph string S. */
2774
2775static void
2776x_get_glyph_string_clip_rect (s, r)
2777 struct glyph_string *s;
2778 XRectangle *r;
2779{
2780 if (s->row->full_width_p)
2781 {
2782 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2783 int canon_x = CANON_X_UNIT (s->f);
2784
2785 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2786 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2787
2788 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2789 {
1da3fd71 2790 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2791 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2792 r->x -= width;
2793 }
2794
b9432a85 2795 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2796
06a2c219
GM
2797 /* Unless displaying a mode or menu bar line, which are always
2798 fully visible, clip to the visible part of the row. */
2799 if (s->w->pseudo_window_p)
2800 r->height = s->row->visible_height;
2801 else
2802 r->height = s->height;
2803 }
2804 else
2805 {
2806 /* This is a text line that may be partially visible. */
2807 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2808 r->width = window_box_width (s->w, s->area);
2809 r->height = s->row->visible_height;
2810 }
2811
2812 /* Don't use S->y for clipping because it doesn't take partially
2813 visible lines into account. For example, it can be negative for
2814 partially visible lines at the top of a window. */
2815 if (!s->row->full_width_p
2816 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2817 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2818 else
2819 r->y = max (0, s->row->y);
06a2c219 2820
9ea173e8 2821 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2822 at the top of the window. */
9ea173e8 2823 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2824 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2825
2826 /* If S draws overlapping rows, it's sufficient to use the top and
2827 bottom of the window for clipping because this glyph string
2828 intentionally draws over other lines. */
2829 if (s->for_overlaps_p)
2830 {
045dee35 2831 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2832 r->height = window_text_bottom_y (s->w) - r->y;
2833 }
2834
2835 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2836}
2837
2838
2839/* Set clipping for output of glyph string S. S may be part of a mode
2840 line or menu if we don't have X toolkit support. */
2841
2842static INLINE void
2843x_set_glyph_string_clipping (s)
2844 struct glyph_string *s;
2845{
2846 XRectangle r;
2847 x_get_glyph_string_clip_rect (s, &r);
2848 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2849}
2850
2851
2852/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2853 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2854
2855static INLINE void
2856x_compute_glyph_string_overhangs (s)
2857 struct glyph_string *s;
2858{
b4192550 2859 if (s->cmp == NULL
06a2c219
GM
2860 && s->first_glyph->type == CHAR_GLYPH)
2861 {
2862 XCharStruct cs;
2863 int direction, font_ascent, font_descent;
2864 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2865 &font_ascent, &font_descent, &cs);
2866 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2867 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2868 }
2869}
2870
2871
2872/* Compute overhangs and x-positions for glyph string S and its
2873 predecessors, or successors. X is the starting x-position for S.
2874 BACKWARD_P non-zero means process predecessors. */
2875
2876static void
2877x_compute_overhangs_and_x (s, x, backward_p)
2878 struct glyph_string *s;
2879 int x;
2880 int backward_p;
2881{
2882 if (backward_p)
2883 {
2884 while (s)
2885 {
2886 x_compute_glyph_string_overhangs (s);
2887 x -= s->width;
2888 s->x = x;
2889 s = s->prev;
2890 }
2891 }
2892 else
2893 {
2894 while (s)
2895 {
2896 x_compute_glyph_string_overhangs (s);
2897 s->x = x;
2898 x += s->width;
2899 s = s->next;
2900 }
2901 }
2902}
2903
2904
2905/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2906 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2907 assumed to be zero. */
06a2c219
GM
2908
2909static void
2910x_get_glyph_overhangs (glyph, f, left, right)
2911 struct glyph *glyph;
2912 struct frame *f;
2913 int *left, *right;
2914{
06a2c219
GM
2915 *left = *right = 0;
2916
b4192550 2917 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2918 {
2919 XFontStruct *font;
2920 struct face *face;
2921 struct font_info *font_info;
2922 XChar2b char2b;
ee569018
KH
2923 XCharStruct *pcm;
2924
2925 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2926 font = face->font;
2927 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2928 if (font
2929 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2930 {
06a2c219
GM
2931 if (pcm->rbearing > pcm->width)
2932 *right = pcm->rbearing - pcm->width;
2933 if (pcm->lbearing < 0)
2934 *left = -pcm->lbearing;
2935 }
2936 }
2937}
2938
2939
2940/* Return the index of the first glyph preceding glyph string S that
2941 is overwritten by S because of S's left overhang. Value is -1
2942 if no glyphs are overwritten. */
2943
2944static int
2945x_left_overwritten (s)
2946 struct glyph_string *s;
2947{
2948 int k;
2949
2950 if (s->left_overhang)
2951 {
2952 int x = 0, i;
2953 struct glyph *glyphs = s->row->glyphs[s->area];
2954 int first = s->first_glyph - glyphs;
2955
2956 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2957 x -= glyphs[i].pixel_width;
2958
2959 k = i + 1;
2960 }
2961 else
2962 k = -1;
2963
2964 return k;
2965}
2966
2967
2968/* Return the index of the first glyph preceding glyph string S that
2969 is overwriting S because of its right overhang. Value is -1 if no
2970 glyph in front of S overwrites S. */
2971
2972static int
2973x_left_overwriting (s)
2974 struct glyph_string *s;
2975{
2976 int i, k, x;
2977 struct glyph *glyphs = s->row->glyphs[s->area];
2978 int first = s->first_glyph - glyphs;
2979
2980 k = -1;
2981 x = 0;
2982 for (i = first - 1; i >= 0; --i)
2983 {
2984 int left, right;
2985 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2986 if (x + right > 0)
2987 k = i;
2988 x -= glyphs[i].pixel_width;
2989 }
2990
2991 return k;
2992}
2993
2994
2995/* Return the index of the last glyph following glyph string S that is
2996 not overwritten by S because of S's right overhang. Value is -1 if
2997 no such glyph is found. */
2998
2999static int
3000x_right_overwritten (s)
3001 struct glyph_string *s;
3002{
3003 int k = -1;
3004
3005 if (s->right_overhang)
3006 {
3007 int x = 0, i;
3008 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3009 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3010 int end = s->row->used[s->area];
3011
3012 for (i = first; i < end && s->right_overhang > x; ++i)
3013 x += glyphs[i].pixel_width;
3014
3015 k = i;
3016 }
3017
3018 return k;
3019}
3020
3021
3022/* Return the index of the last glyph following glyph string S that
3023 overwrites S because of its left overhang. Value is negative
3024 if no such glyph is found. */
3025
3026static int
3027x_right_overwriting (s)
3028 struct glyph_string *s;
3029{
3030 int i, k, x;
3031 int end = s->row->used[s->area];
3032 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3033 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3034
3035 k = -1;
3036 x = 0;
3037 for (i = first; i < end; ++i)
3038 {
3039 int left, right;
3040 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3041 if (x - left < 0)
3042 k = i;
3043 x += glyphs[i].pixel_width;
3044 }
3045
3046 return k;
3047}
3048
3049
3050/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3051
3052static INLINE void
3053x_clear_glyph_string_rect (s, x, y, w, h)
3054 struct glyph_string *s;
3055 int x, y, w, h;
3056{
3057 XGCValues xgcv;
3058 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3059 XSetForeground (s->display, s->gc, xgcv.background);
3060 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3061 XSetForeground (s->display, s->gc, xgcv.foreground);
3062}
3063
3064
3065/* Draw the background of glyph_string S. If S->background_filled_p
3066 is non-zero don't draw it. FORCE_P non-zero means draw the
3067 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3068 when a string preceding S draws into the background of S, or S
3069 contains the first component of a composition. */
06a2c219
GM
3070
3071static void
3072x_draw_glyph_string_background (s, force_p)
3073 struct glyph_string *s;
3074 int force_p;
3075{
3076 /* Nothing to do if background has already been drawn or if it
3077 shouldn't be drawn in the first place. */
3078 if (!s->background_filled_p)
3079 {
b4192550 3080 if (s->stippled_p)
06a2c219
GM
3081 {
3082 /* Fill background with a stipple pattern. */
3083 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3084 XFillRectangle (s->display, s->window, s->gc, s->x,
3085 s->y + s->face->box_line_width,
3086 s->background_width,
3087 s->height - 2 * s->face->box_line_width);
3088 XSetFillStyle (s->display, s->gc, FillSolid);
3089 s->background_filled_p = 1;
3090 }
3091 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3092 || s->font_not_found_p
3093 || s->extends_to_end_of_line_p
06a2c219
GM
3094 || force_p)
3095 {
3096 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3097 s->background_width,
3098 s->height - 2 * s->face->box_line_width);
3099 s->background_filled_p = 1;
3100 }
3101 }
3102}
3103
3104
3105/* Draw the foreground of glyph string S. */
3106
3107static void
3108x_draw_glyph_string_foreground (s)
3109 struct glyph_string *s;
3110{
3111 int i, x;
3112
3113 /* If first glyph of S has a left box line, start drawing the text
3114 of S to the right of that box line. */
3115 if (s->face->box != FACE_NO_BOX
3116 && s->first_glyph->left_box_line_p)
3117 x = s->x + s->face->box_line_width;
3118 else
3119 x = s->x;
3120
b4192550
KH
3121 /* Draw characters of S as rectangles if S's font could not be
3122 loaded. */
3123 if (s->font_not_found_p)
06a2c219 3124 {
b4192550 3125 for (i = 0; i < s->nchars; ++i)
06a2c219 3126 {
b4192550
KH
3127 struct glyph *g = s->first_glyph + i;
3128 XDrawRectangle (s->display, s->window,
3129 s->gc, x, s->y, g->pixel_width - 1,
3130 s->height - 1);
3131 x += g->pixel_width;
06a2c219
GM
3132 }
3133 }
3134 else
3135 {
b4192550
KH
3136 char *char1b = (char *) s->char2b;
3137 int boff = s->font_info->baseline_offset;
06a2c219 3138
b4192550
KH
3139 if (s->font_info->vertical_centering)
3140 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3141
3142 /* If we can use 8-bit functions, condense S->char2b. */
3143 if (!s->two_byte_p)
3144 for (i = 0; i < s->nchars; ++i)
3145 char1b[i] = s->char2b[i].byte2;
3146
3147 /* Draw text with XDrawString if background has already been
3148 filled. Otherwise, use XDrawImageString. (Note that
3149 XDrawImageString is usually faster than XDrawString.) Always
3150 use XDrawImageString when drawing the cursor so that there is
3151 no chance that characters under a box cursor are invisible. */
3152 if (s->for_overlaps_p
3153 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3154 {
3155 /* Draw characters with 16-bit or 8-bit functions. */
3156 if (s->two_byte_p)
3157 XDrawString16 (s->display, s->window, s->gc, x,
3158 s->ybase - boff, s->char2b, s->nchars);
3159 else
3160 XDrawString (s->display, s->window, s->gc, x,
3161 s->ybase - boff, char1b, s->nchars);
3162 }
06a2c219
GM
3163 else
3164 {
b4192550
KH
3165 if (s->two_byte_p)
3166 XDrawImageString16 (s->display, s->window, s->gc, x,
3167 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3168 else
b4192550
KH
3169 XDrawImageString (s->display, s->window, s->gc, x,
3170 s->ybase - boff, char1b, s->nchars);
3171 }
3172 }
3173}
06a2c219 3174
b4192550 3175/* Draw the foreground of composite glyph string S. */
06a2c219 3176
b4192550
KH
3177static void
3178x_draw_composite_glyph_string_foreground (s)
3179 struct glyph_string *s;
3180{
3181 int i, x;
06a2c219 3182
b4192550
KH
3183 /* If first glyph of S has a left box line, start drawing the text
3184 of S to the right of that box line. */
3185 if (s->face->box != FACE_NO_BOX
3186 && s->first_glyph->left_box_line_p)
3187 x = s->x + s->face->box_line_width;
3188 else
3189 x = s->x;
06a2c219 3190
b4192550
KH
3191 /* S is a glyph string for a composition. S->gidx is the index of
3192 the first character drawn for glyphs of this composition.
3193 S->gidx == 0 means we are drawing the very first character of
3194 this composition. */
06a2c219 3195
b4192550
KH
3196 /* Draw a rectangle for the composition if the font for the very
3197 first character of the composition could not be loaded. */
3198 if (s->font_not_found_p)
3199 {
3200 if (s->gidx == 0)
3201 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3202 s->width - 1, s->height - 1);
3203 }
3204 else
3205 {
3206 for (i = 0; i < s->nchars; i++, ++s->gidx)
3207 XDrawString16 (s->display, s->window, s->gc,
3208 x + s->cmp->offsets[s->gidx * 2],
3209 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3210 s->char2b + i, 1);
06a2c219
GM
3211 }
3212}
3213
3214
80c32bcc
GM
3215#ifdef USE_X_TOOLKIT
3216
3e71d8f2 3217static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3218
3e71d8f2
GM
3219
3220/* Return the frame on which widget WIDGET is used.. Abort if frame
3221 cannot be determined. */
3222
e851c833 3223static struct frame *
3e71d8f2 3224x_frame_of_widget (widget)
80c32bcc 3225 Widget widget;
80c32bcc 3226{
80c32bcc 3227 struct x_display_info *dpyinfo;
5c187dee 3228 Lisp_Object tail;
3e71d8f2
GM
3229 struct frame *f;
3230
80c32bcc
GM
3231 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3232
3233 /* Find the top-level shell of the widget. Note that this function
3234 can be called when the widget is not yet realized, so XtWindow
3235 (widget) == 0. That's the reason we can't simply use
3236 x_any_window_to_frame. */
3237 while (!XtIsTopLevelShell (widget))
3238 widget = XtParent (widget);
3239
3240 /* Look for a frame with that top-level widget. Allocate the color
3241 on that frame to get the right gamma correction value. */
3242 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3243 if (GC_FRAMEP (XCAR (tail))
3244 && (f = XFRAME (XCAR (tail)),
3245 (f->output_data.nothing != 1
3246 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3247 && f->output_data.x->widget == widget)
3e71d8f2 3248 return f;
80c32bcc
GM
3249
3250 abort ();
3251}
3252
3e71d8f2
GM
3253
3254/* Allocate the color COLOR->pixel on the screen and display of
3255 widget WIDGET in colormap CMAP. If an exact match cannot be
3256 allocated, try the nearest color available. Value is non-zero
3257 if successful. This is called from lwlib. */
3258
3259int
3260x_alloc_nearest_color_for_widget (widget, cmap, color)
3261 Widget widget;
3262 Colormap cmap;
3263 XColor *color;
3264{
3265 struct frame *f = x_frame_of_widget (widget);
3266 return x_alloc_nearest_color (f, cmap, color);
3267}
3268
3269
46d516e5
MB
3270/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3271 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3272 If this produces the same color as PIXEL, try a color where all RGB
3273 values have DELTA added. Return the allocated color in *PIXEL.
3274 DISPLAY is the X display, CMAP is the colormap to operate on.
3275 Value is non-zero if successful. */
3276
3277int
3278x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3279 Widget widget;
3280 Display *display;
3281 Colormap cmap;
3282 unsigned long *pixel;
3283 double factor;
3284 int delta;
3285{
3286 struct frame *f = x_frame_of_widget (widget);
3287 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3288}
3289
3290
80c32bcc
GM
3291#endif /* USE_X_TOOLKIT */
3292
3293
f04e1297
GM
3294/* Value is an array of XColor structures for the contents of the
3295 color map of frame F. Set *NCELLS to the size of the array.
3296 Note that this probably shouldn't be called for large color maps,
3297 say a 24-bit TrueColor map. */
3298
3299static const XColor *
3300x_color_cells (f, ncells)
3301 struct frame *f;
3302 int *ncells;
3303{
3304 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3305
3306 if (dpyinfo->color_cells == NULL)
3307 {
3308 Display *display = FRAME_X_DISPLAY (f);
3309 Screen *screen = FRAME_X_SCREEN (f);
3310 int i;
3311
3312 dpyinfo->ncolor_cells
3313 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3314 dpyinfo->color_cells
3315 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3316 * sizeof *dpyinfo->color_cells);
3317
3318 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3319 dpyinfo->color_cells[i].pixel = i;
3320
3321 XQueryColors (display, FRAME_X_COLORMAP (f),
3322 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3323 }
3324
3325 *ncells = dpyinfo->ncolor_cells;
3326 return dpyinfo->color_cells;
3327}
3328
3329
3330/* On frame F, translate pixel colors to RGB values for the NCOLORS
3331 colors in COLORS. Use cached information, if available. */
3332
3333void
3334x_query_colors (f, colors, ncolors)
3335 struct frame *f;
3336 XColor *colors;
3337 int ncolors;
3338{
3339 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3340
3341 if (dpyinfo->color_cells)
3342 {
3343 int i;
3344 for (i = 0; i < ncolors; ++i)
3345 {
3346 unsigned long pixel = colors[i].pixel;
3347 xassert (pixel < dpyinfo->ncolor_cells);
3348 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3349 colors[i] = dpyinfo->color_cells[pixel];
3350 }
3351 }
3352 else
3353 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3354}
3355
3356
3357/* On frame F, translate pixel color to RGB values for the color in
3358 COLOR. Use cached information, if available. */
3359
3360void
3361x_query_color (f, color)
3362 struct frame *f;
3363 XColor *color;
3364{
3365 x_query_colors (f, color, 1);
3366}
3367
3368
06a2c219
GM
3369/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3370 CMAP. If an exact match can't be allocated, try the nearest color
3371 available. Value is non-zero if successful. Set *COLOR to the
3372 color allocated. */
3373
3374int
80c32bcc
GM
3375x_alloc_nearest_color (f, cmap, color)
3376 struct frame *f;
06a2c219
GM
3377 Colormap cmap;
3378 XColor *color;
3379{
80c32bcc
GM
3380 Display *display = FRAME_X_DISPLAY (f);
3381 Screen *screen = FRAME_X_SCREEN (f);
3382 int rc;
3383
3384 gamma_correct (f, color);
3385 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3386 if (rc == 0)
3387 {
3388 /* If we got to this point, the colormap is full, so we're going
3389 to try to get the next closest color. The algorithm used is
3390 a least-squares matching, which is what X uses for closest
3391 color matching with StaticColor visuals. */
3392 int nearest, i;
3393 unsigned long nearest_delta = ~0;
f04e1297
GM
3394 int ncells;
3395 const XColor *cells = x_color_cells (f, &ncells);
06a2c219
GM
3396
3397 for (nearest = i = 0; i < ncells; ++i)
3398 {
3399 long dred = (color->red >> 8) - (cells[i].red >> 8);
3400 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3401 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3402 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3403
3404 if (delta < nearest_delta)
3405 {
3406 nearest = i;
3407 nearest_delta = delta;
3408 }
3409 }
3410
3411 color->red = cells[nearest].red;
3412 color->green = cells[nearest].green;
3413 color->blue = cells[nearest].blue;
3414 rc = XAllocColor (display, cmap, color);
3415 }
35efe0a1
GM
3416 else
3417 {
3418 /* If allocation succeeded, and the allocated pixel color is not
3419 equal to a cached pixel color recorded earlier, there was a
3420 change in the colormap, so clear the color cache. */
3421 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3422 XColor *cached_color;
3423
3424 if (dpyinfo->color_cells
3425 && (cached_color = &dpyinfo->color_cells[color->pixel],
cae71efe
GM
3426 (cached_color->red != color->red
3427 || cached_color->blue != color->blue
3428 || cached_color->green != color->green)))
35efe0a1
GM
3429 {
3430 xfree (dpyinfo->color_cells);
3431 dpyinfo->color_cells = NULL;
3432 dpyinfo->ncolor_cells = 0;
3433 }
3434 }
06a2c219 3435
d9c545da
GM
3436#ifdef DEBUG_X_COLORS
3437 if (rc)
3438 register_color (color->pixel);
3439#endif /* DEBUG_X_COLORS */
3440
06a2c219
GM
3441 return rc;
3442}
3443
3444
d9c545da
GM
3445/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3446 It's necessary to do this instead of just using PIXEL directly to
3447 get color reference counts right. */
3448
3449unsigned long
3450x_copy_color (f, pixel)
3451 struct frame *f;
3452 unsigned long pixel;
3453{
3454 XColor color;
3455
3456 color.pixel = pixel;
3457 BLOCK_INPUT;
f04e1297 3458 x_query_color (f, &color);
d9c545da
GM
3459 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3460 UNBLOCK_INPUT;
3461#ifdef DEBUG_X_COLORS
3462 register_color (pixel);
3463#endif
3464 return color.pixel;
3465}
3466
3467
3e71d8f2
GM
3468/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3469 It's necessary to do this instead of just using PIXEL directly to
3470 get color reference counts right. */
3471
3472unsigned long
3473x_copy_dpy_color (dpy, cmap, pixel)
3474 Display *dpy;
3475 Colormap cmap;
3476 unsigned long pixel;
3477{
3478 XColor color;
3479
3480 color.pixel = pixel;
3481 BLOCK_INPUT;
3482 XQueryColor (dpy, cmap, &color);
3483 XAllocColor (dpy, cmap, &color);
3484 UNBLOCK_INPUT;
3485#ifdef DEBUG_X_COLORS
3486 register_color (pixel);
3487#endif
3488 return color.pixel;
3489}
3490
3491
6d8b0acd
MB
3492
3493/* Constants used by x_alloc_lighter_color. */
3494
3495/* How much to boost the brightness of 3d highlights for dark colors.
3496 Nominally, highlight colors for `3d' faces are calculated by
3497 brightening an object's color by a constant factor. If
3498 `highlight-color-dark-boost' is a floating point number between 0 and
3499 1, colors darker than `highlight-color-dark-boost-limit' have their
3500 highlight factor increased: a value of 0 means no increase at all,
3501 and greater values yield correspondingly greater increases. */
3502#define HIGHLIGHT_COLOR_DARK_BOOST 0.7
3503
3504/* Brightness beyond which a color won't have its highlight brightness
3505 boosted. See HIGHLIGHT_COLOR_DARK_BOOST.
3506
3507 The `brightness' of a color, for this purpose, is defined to be the
3508 maximum of the color's red, green, or blue components, as returned by
3509 `color-values'.
3510
3511 The value here is set so that the default menu-bar/mode-line color
3512 (grey75) will not have its highlights changed at all. */
3513#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3514
3515
06a2c219
GM
3516/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3517 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3518 If this produces the same color as PIXEL, try a color where all RGB
3519 values have DELTA added. Return the allocated color in *PIXEL.
3520 DISPLAY is the X display, CMAP is the colormap to operate on.
3521 Value is non-zero if successful. */
3522
3523static int
3524x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3525 struct frame *f;
3526 Display *display;
3527 Colormap cmap;
3528 unsigned long *pixel;
68c45bf0 3529 double factor;
06a2c219
GM
3530 int delta;
3531{
3532 XColor color, new;
6d8b0acd 3533 long bright;
06a2c219
GM
3534 int success_p;
3535
3536 /* Get RGB color values. */
3537 color.pixel = *pixel;
f04e1297 3538 x_query_color (f, &color);
06a2c219
GM
3539
3540 /* Change RGB values by specified FACTOR. Avoid overflow! */
3541 xassert (factor >= 0);
3542 new.red = min (0xffff, factor * color.red);
3543 new.green = min (0xffff, factor * color.green);
3544 new.blue = min (0xffff, factor * color.blue);
3545
6d8b0acd
MB
3546 /* Use the maximum component brightness as the overall brightness
3547 (this works quite well in practice). */
3548 bright = color.red;
3549 if (color.green > bright)
3550 bright = color.green;
3551 if (color.blue > bright)
3552 bright = color.blue;
3553
3554 /* We only boost colors that are darker than
3555 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3556 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3557 /* Make an additive adjustment to NEW, because it's dark enough so
3558 that scaling by FACTOR alone isn't enough. */
3559 {
3560 /* How far below the limit this color is (0 - 1, 1 being darker). */
3561 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3562 /* The additive adjustment. */
3563 int min_delta = delta * dimness * HIGHLIGHT_COLOR_DARK_BOOST;
3564
3565 if (factor < 1)
3566 {
3567 min_delta /= 2;
3568 new.red = max (0, new.red - min_delta);
3569 new.green = max (0, new.green - min_delta);
3570 new.blue = max (0, new.blue - min_delta);
3571 }
3572 else
3573 {
3574 new.red = min (0xffff, min_delta + new.red);
3575 new.green = min (0xffff, min_delta + new.green);
3576 new.blue = min (0xffff, min_delta + new.blue);
3577 }
3578 }
3579
06a2c219 3580 /* Try to allocate the color. */
80c32bcc 3581 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3582 if (success_p)
3583 {
3584 if (new.pixel == *pixel)
3585 {
3586 /* If we end up with the same color as before, try adding
3587 delta to the RGB values. */
0d605c67 3588 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3589
3590 new.red = min (0xffff, delta + color.red);
3591 new.green = min (0xffff, delta + color.green);
3592 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3593 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3594 }
3595 else
3596 success_p = 1;
3597 *pixel = new.pixel;
3598 }
3599
3600 return success_p;
3601}
3602
3603
3604/* Set up the foreground color for drawing relief lines of glyph
3605 string S. RELIEF is a pointer to a struct relief containing the GC
3606 with which lines will be drawn. Use a color that is FACTOR or
3607 DELTA lighter or darker than the relief's background which is found
3608 in S->f->output_data.x->relief_background. If such a color cannot
3609 be allocated, use DEFAULT_PIXEL, instead. */
3610
3611static void
3612x_setup_relief_color (f, relief, factor, delta, default_pixel)
3613 struct frame *f;
3614 struct relief *relief;
68c45bf0 3615 double factor;
06a2c219
GM
3616 int delta;
3617 unsigned long default_pixel;
3618{
3619 XGCValues xgcv;
3620 struct x_output *di = f->output_data.x;
3621 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3622 unsigned long pixel;
3623 unsigned long background = di->relief_background;
43bd1b2b 3624 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3625 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3626 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3627
3628 xgcv.graphics_exposures = False;
3629 xgcv.line_width = 1;
3630
3631 /* Free previously allocated color. The color cell will be reused
3632 when it has been freed as many times as it was allocated, so this
3633 doesn't affect faces using the same colors. */
3634 if (relief->gc
3635 && relief->allocated_p)
3636 {
0d605c67 3637 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3638 relief->allocated_p = 0;
3639 }
3640
3641 /* Allocate new color. */
3642 xgcv.foreground = default_pixel;
3643 pixel = background;
dcd08bfb
GM
3644 if (dpyinfo->n_planes != 1
3645 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3646 {
3647 relief->allocated_p = 1;
3648 xgcv.foreground = relief->pixel = pixel;
3649 }
3650
3651 if (relief->gc == 0)
3652 {
dcd08bfb 3653 xgcv.stipple = dpyinfo->gray;
06a2c219 3654 mask |= GCStipple;
dcd08bfb 3655 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3656 }
3657 else
dcd08bfb 3658 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3659}
3660
3661
3662/* Set up colors for the relief lines around glyph string S. */
3663
3664static void
3665x_setup_relief_colors (s)
3666 struct glyph_string *s;
3667{
3668 struct x_output *di = s->f->output_data.x;
3669 unsigned long color;
3670
3671 if (s->face->use_box_color_for_shadows_p)
3672 color = s->face->box_color;
3673 else
3674 {
3675 XGCValues xgcv;
3676
3677 /* Get the background color of the face. */
3678 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3679 color = xgcv.background;
3680 }
3681
3682 if (di->white_relief.gc == 0
3683 || color != di->relief_background)
3684 {
3685 di->relief_background = color;
3686 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3687 WHITE_PIX_DEFAULT (s->f));
3688 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3689 BLACK_PIX_DEFAULT (s->f));
3690 }
3691}
3692
3693
3694/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3695 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3696 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3697 relief. LEFT_P non-zero means draw a relief on the left side of
3698 the rectangle. RIGHT_P non-zero means draw a relief on the right
3699 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3700 when drawing. */
3701
3702static void
3703x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3704 raised_p, left_p, right_p, clip_rect)
3705 struct frame *f;
3706 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3707 XRectangle *clip_rect;
3708{
3709 int i;
3710 GC gc;
3711
3712 if (raised_p)
3713 gc = f->output_data.x->white_relief.gc;
3714 else
3715 gc = f->output_data.x->black_relief.gc;
3716 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3717
3718 /* Top. */
3719 for (i = 0; i < width; ++i)
3720 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3721 left_x + i * left_p, top_y + i,
3722 right_x + 1 - i * right_p, top_y + i);
3723
3724 /* Left. */
3725 if (left_p)
3726 for (i = 0; i < width; ++i)
3727 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3728 left_x + i, top_y + i, left_x + i, bottom_y - i);
3729
3730 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3731 if (raised_p)
3732 gc = f->output_data.x->black_relief.gc;
3733 else
3734 gc = f->output_data.x->white_relief.gc;
3735 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3736
3737 /* Bottom. */
3738 for (i = 0; i < width; ++i)
3739 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3740 left_x + i * left_p, bottom_y - i,
3741 right_x + 1 - i * right_p, bottom_y - i);
3742
3743 /* Right. */
3744 if (right_p)
3745 for (i = 0; i < width; ++i)
3746 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3747 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3748
3749 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3750}
3751
3752
3753/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3754 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3755 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3756 left side of the rectangle. RIGHT_P non-zero means draw a line
3757 on the right side of the rectangle. CLIP_RECT is the clipping
3758 rectangle to use when drawing. */
3759
3760static void
3761x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3762 left_p, right_p, clip_rect)
3763 struct glyph_string *s;
3764 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3765 XRectangle *clip_rect;
3766{
3767 XGCValues xgcv;
3768
3769 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3770 XSetForeground (s->display, s->gc, s->face->box_color);
3771 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3772
3773 /* Top. */
3774 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3775 left_x, top_y, right_x - left_x + 1, width);
06a2c219
GM
3776
3777 /* Left. */
3778 if (left_p)
3779 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3780 left_x, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3781
3782 /* Bottom. */
3783 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3784 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
06a2c219
GM
3785
3786 /* Right. */
3787 if (right_p)
3788 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3789 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3790
3791 XSetForeground (s->display, s->gc, xgcv.foreground);
3792 XSetClipMask (s->display, s->gc, None);
3793}
3794
3795
3796/* Draw a box around glyph string S. */
3797
3798static void
3799x_draw_glyph_string_box (s)
3800 struct glyph_string *s;
3801{
3802 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3803 int left_p, right_p;
3804 struct glyph *last_glyph;
3805 XRectangle clip_rect;
3806
3807 last_x = window_box_right (s->w, s->area);
3808 if (s->row->full_width_p
3809 && !s->w->pseudo_window_p)
3810 {
110859fc 3811 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3812 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3813 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3814 }
3815
3816 /* The glyph that may have a right box line. */
b4192550 3817 last_glyph = (s->cmp || s->img
06a2c219
GM
3818 ? s->first_glyph
3819 : s->first_glyph + s->nchars - 1);
3820
3821 width = s->face->box_line_width;
3822 raised_p = s->face->box == FACE_RAISED_BOX;
3823 left_x = s->x;
3824 right_x = ((s->row->full_width_p
1da3fd71 3825 ? last_x - 1
a7aeb2de 3826 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3827 top_y = s->y;
3828 bottom_y = top_y + s->height - 1;
3829
3830 left_p = (s->first_glyph->left_box_line_p
3831 || (s->hl == DRAW_MOUSE_FACE
3832 && (s->prev == NULL
3833 || s->prev->hl != s->hl)));
3834 right_p = (last_glyph->right_box_line_p
3835 || (s->hl == DRAW_MOUSE_FACE
3836 && (s->next == NULL
3837 || s->next->hl != s->hl)));
3838
3839 x_get_glyph_string_clip_rect (s, &clip_rect);
3840
3841 if (s->face->box == FACE_SIMPLE_BOX)
3842 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3843 left_p, right_p, &clip_rect);
3844 else
3845 {
3846 x_setup_relief_colors (s);
3847 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3848 width, raised_p, left_p, right_p, &clip_rect);
3849 }
3850}
3851
3852
3853/* Draw foreground of image glyph string S. */
3854
3855static void
3856x_draw_image_foreground (s)
3857 struct glyph_string *s;
3858{
3859 int x;
95af8492 3860 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3861
3862 /* If first glyph of S has a left box line, start drawing it to the
3863 right of that line. */
3864 if (s->face->box != FACE_NO_BOX
3865 && s->first_glyph->left_box_line_p)
3866 x = s->x + s->face->box_line_width;
3867 else
3868 x = s->x;
3869
3870 /* If there is a margin around the image, adjust x- and y-position
3871 by that margin. */
3872 if (s->img->margin)
3873 {
3874 x += s->img->margin;
3875 y += s->img->margin;
3876 }
3877
3878 if (s->img->pixmap)
3879 {
3880 if (s->img->mask)
3881 {
3882 /* We can't set both a clip mask and use XSetClipRectangles
3883 because the latter also sets a clip mask. We also can't
3884 trust on the shape extension to be available
3885 (XShapeCombineRegion). So, compute the rectangle to draw
3886 manually. */
3887 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3888 | GCFunction);
3889 XGCValues xgcv;
3890 XRectangle clip_rect, image_rect, r;
3891
3892 xgcv.clip_mask = s->img->mask;
3893 xgcv.clip_x_origin = x;
3894 xgcv.clip_y_origin = y;
3895 xgcv.function = GXcopy;
3896 XChangeGC (s->display, s->gc, mask, &xgcv);
3897
3898 x_get_glyph_string_clip_rect (s, &clip_rect);
3899 image_rect.x = x;
3900 image_rect.y = y;
3901 image_rect.width = s->img->width;
3902 image_rect.height = s->img->height;
3903 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3904 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3905 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3906 }
3907 else
3908 {
49ad1d99
GM
3909 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3910 XGCValues xgcv;
3911 XRectangle clip_rect, image_rect, r;
3912
3913 x_get_glyph_string_clip_rect (s, &clip_rect);
3914 image_rect.x = x;
3915 image_rect.y = y;
3916 image_rect.width = s->img->width;
3917 image_rect.height = s->img->height;
3918 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3919 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3920 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
06a2c219
GM
3921
3922 /* When the image has a mask, we can expect that at
3923 least part of a mouse highlight or a block cursor will
3924 be visible. If the image doesn't have a mask, make
3925 a block cursor visible by drawing a rectangle around
3926 the image. I believe it's looking better if we do
3927 nothing here for mouse-face. */
3928 if (s->hl == DRAW_CURSOR)
3929 XDrawRectangle (s->display, s->window, s->gc, x, y,
3930 s->img->width - 1, s->img->height - 1);
3931 }
3932 }
3933 else
3934 /* Draw a rectangle if image could not be loaded. */
3935 XDrawRectangle (s->display, s->window, s->gc, x, y,
3936 s->img->width - 1, s->img->height - 1);
3937}
3938
3939
3940/* Draw a relief around the image glyph string S. */
3941
3942static void
3943x_draw_image_relief (s)
3944 struct glyph_string *s;
3945{
3946 int x0, y0, x1, y1, thick, raised_p;
3947 XRectangle r;
3948 int x;
95af8492 3949 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3950
3951 /* If first glyph of S has a left box line, start drawing it to the
3952 right of that line. */
3953 if (s->face->box != FACE_NO_BOX
3954 && s->first_glyph->left_box_line_p)
3955 x = s->x + s->face->box_line_width;
3956 else
3957 x = s->x;
3958
3959 /* If there is a margin around the image, adjust x- and y-position
3960 by that margin. */
3961 if (s->img->margin)
3962 {
3963 x += s->img->margin;
3964 y += s->img->margin;
3965 }
3966
3967 if (s->hl == DRAW_IMAGE_SUNKEN
3968 || s->hl == DRAW_IMAGE_RAISED)
3969 {
9ea173e8 3970 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3971 raised_p = s->hl == DRAW_IMAGE_RAISED;
3972 }
3973 else
3974 {
3975 thick = abs (s->img->relief);
3976 raised_p = s->img->relief > 0;
3977 }
3978
3979 x0 = x - thick;
3980 y0 = y - thick;
3981 x1 = x + s->img->width + thick - 1;
3982 y1 = y + s->img->height + thick - 1;
3983
3984 x_setup_relief_colors (s);
3985 x_get_glyph_string_clip_rect (s, &r);
3986 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3987}
3988
3989
3990/* Draw the foreground of image glyph string S to PIXMAP. */
3991
3992static void
3993x_draw_image_foreground_1 (s, pixmap)
3994 struct glyph_string *s;
3995 Pixmap pixmap;
3996{
3997 int x;
95af8492 3998 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3999
4000 /* If first glyph of S has a left box line, start drawing it to the
4001 right of that line. */
4002 if (s->face->box != FACE_NO_BOX
4003 && s->first_glyph->left_box_line_p)
4004 x = s->face->box_line_width;
4005 else
4006 x = 0;
4007
4008 /* If there is a margin around the image, adjust x- and y-position
4009 by that margin. */
4010 if (s->img->margin)
4011 {
4012 x += s->img->margin;
4013 y += s->img->margin;
4014 }
dc43ef94 4015
06a2c219
GM
4016 if (s->img->pixmap)
4017 {
4018 if (s->img->mask)
4019 {
4020 /* We can't set both a clip mask and use XSetClipRectangles
4021 because the latter also sets a clip mask. We also can't
4022 trust on the shape extension to be available
4023 (XShapeCombineRegion). So, compute the rectangle to draw
4024 manually. */
4025 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4026 | GCFunction);
4027 XGCValues xgcv;
4028
4029 xgcv.clip_mask = s->img->mask;
4030 xgcv.clip_x_origin = x;
4031 xgcv.clip_y_origin = y;
4032 xgcv.function = GXcopy;
4033 XChangeGC (s->display, s->gc, mask, &xgcv);
4034
4035 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4036 0, 0, s->img->width, s->img->height, x, y);
4037 XSetClipMask (s->display, s->gc, None);
4038 }
4039 else
4040 {
4041 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4042 0, 0, s->img->width, s->img->height, x, y);
4043
4044 /* When the image has a mask, we can expect that at
4045 least part of a mouse highlight or a block cursor will
4046 be visible. If the image doesn't have a mask, make
4047 a block cursor visible by drawing a rectangle around
4048 the image. I believe it's looking better if we do
4049 nothing here for mouse-face. */
4050 if (s->hl == DRAW_CURSOR)
4051 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4052 s->img->width - 1, s->img->height - 1);
4053 }
4054 }
4055 else
4056 /* Draw a rectangle if image could not be loaded. */
4057 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4058 s->img->width - 1, s->img->height - 1);
4059}
dc43ef94 4060
990ba854 4061
06a2c219
GM
4062/* Draw part of the background of glyph string S. X, Y, W, and H
4063 give the rectangle to draw. */
a9a5b0a5 4064
06a2c219
GM
4065static void
4066x_draw_glyph_string_bg_rect (s, x, y, w, h)
4067 struct glyph_string *s;
4068 int x, y, w, h;
4069{
4070 if (s->stippled_p)
4071 {
4072 /* Fill background with a stipple pattern. */
4073 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4074 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4075 XSetFillStyle (s->display, s->gc, FillSolid);
4076 }
4077 else
4078 x_clear_glyph_string_rect (s, x, y, w, h);
4079}
07e34cb0 4080
b5210ea7 4081
06a2c219 4082/* Draw image glyph string S.
dc43ef94 4083
06a2c219
GM
4084 s->y
4085 s->x +-------------------------
4086 | s->face->box
4087 |
4088 | +-------------------------
4089 | | s->img->margin
4090 | |
4091 | | +-------------------
4092 | | | the image
dc43ef94 4093
06a2c219 4094 */
dc43ef94 4095
06a2c219
GM
4096static void
4097x_draw_image_glyph_string (s)
4098 struct glyph_string *s;
4099{
4100 int x, y;
4101 int box_line_width = s->face->box_line_width;
4102 int margin = s->img->margin;
4103 int height;
4104 Pixmap pixmap = None;
4105
4106 height = s->height - 2 * box_line_width;
4107
4108 /* Fill background with face under the image. Do it only if row is
4109 taller than image or if image has a clip mask to reduce
4110 flickering. */
4111 s->stippled_p = s->face->stipple != 0;
4112 if (height > s->img->height
4113 || margin
4114 || s->img->mask
4115 || s->img->pixmap == 0
4116 || s->width != s->background_width)
4117 {
4118 if (box_line_width && s->first_glyph->left_box_line_p)
4119 x = s->x + box_line_width;
4120 else
4121 x = s->x;
4122
4123 y = s->y + box_line_width;
4124
4125 if (s->img->mask)
4126 {
f9b5db02
GM
4127 /* Create a pixmap as large as the glyph string. Fill it
4128 with the background color. Copy the image to it, using
4129 its mask. Copy the temporary pixmap to the display. */
06a2c219
GM
4130 Screen *screen = FRAME_X_SCREEN (s->f);
4131 int depth = DefaultDepthOfScreen (screen);
4132
4133 /* Create a pixmap as large as the glyph string. */
4134 pixmap = XCreatePixmap (s->display, s->window,
4135 s->background_width,
4136 s->height, depth);
4137
4138 /* Don't clip in the following because we're working on the
4139 pixmap. */
4140 XSetClipMask (s->display, s->gc, None);
4141
4142 /* Fill the pixmap with the background color/stipple. */
4143 if (s->stippled_p)
4144 {
4145 /* Fill background with a stipple pattern. */
4146 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4147 XFillRectangle (s->display, pixmap, s->gc,
4148 0, 0, s->background_width, s->height);
4149 XSetFillStyle (s->display, s->gc, FillSolid);
4150 }
4151 else
4152 {
4153 XGCValues xgcv;
4154 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4155 &xgcv);
4156 XSetForeground (s->display, s->gc, xgcv.background);
4157 XFillRectangle (s->display, pixmap, s->gc,
4158 0, 0, s->background_width, s->height);
4159 XSetForeground (s->display, s->gc, xgcv.foreground);
4160 }
4161 }
4162 else
06a2c219
GM
4163 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4164
4165 s->background_filled_p = 1;
4166 }
dc43ef94 4167
06a2c219
GM
4168 /* Draw the foreground. */
4169 if (pixmap != None)
4170 {
4171 x_draw_image_foreground_1 (s, pixmap);
4172 x_set_glyph_string_clipping (s);
4173 XCopyArea (s->display, pixmap, s->window, s->gc,
4174 0, 0, s->background_width, s->height, s->x, s->y);
4175 XFreePixmap (s->display, pixmap);
4176 }
4177 else
4178 x_draw_image_foreground (s);
b5210ea7 4179
06a2c219
GM
4180 /* If we must draw a relief around the image, do it. */
4181 if (s->img->relief
4182 || s->hl == DRAW_IMAGE_RAISED
4183 || s->hl == DRAW_IMAGE_SUNKEN)
4184 x_draw_image_relief (s);
4185}
8c1a6a84 4186
990ba854 4187
06a2c219 4188/* Draw stretch glyph string S. */
dc43ef94 4189
06a2c219
GM
4190static void
4191x_draw_stretch_glyph_string (s)
4192 struct glyph_string *s;
4193{
4194 xassert (s->first_glyph->type == STRETCH_GLYPH);
4195 s->stippled_p = s->face->stipple != 0;
990ba854 4196
06a2c219
GM
4197 if (s->hl == DRAW_CURSOR
4198 && !x_stretch_cursor_p)
4199 {
4200 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4201 as wide as the stretch glyph. */
4202 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4203
06a2c219
GM
4204 /* Draw cursor. */
4205 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4206
06a2c219
GM
4207 /* Clear rest using the GC of the original non-cursor face. */
4208 if (width < s->background_width)
4209 {
4210 GC gc = s->face->gc;
4211 int x = s->x + width, y = s->y;
4212 int w = s->background_width - width, h = s->height;
4213 XRectangle r;
dc43ef94 4214
06a2c219
GM
4215 x_get_glyph_string_clip_rect (s, &r);
4216 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 4217
06a2c219
GM
4218 if (s->face->stipple)
4219 {
4220 /* Fill background with a stipple pattern. */
4221 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4222 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4223 XSetFillStyle (s->display, gc, FillSolid);
4224 }
4225 else
4226 {
4227 XGCValues xgcv;
4228 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4229 XSetForeground (s->display, gc, xgcv.background);
4230 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4231 XSetForeground (s->display, gc, xgcv.foreground);
4232 }
4233 }
4234 }
4235 else
4236 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4237 s->height);
4238
4239 s->background_filled_p = 1;
4240}
4241
4242
4243/* Draw glyph string S. */
4244
4245static void
4246x_draw_glyph_string (s)
4247 struct glyph_string *s;
4248{
4249 /* If S draws into the background of its successor, draw the
4250 background of the successor first so that S can draw into it.
4251 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4252 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4253 {
4254 xassert (s->next->img == NULL);
4255 x_set_glyph_string_gc (s->next);
4256 x_set_glyph_string_clipping (s->next);
4257 x_draw_glyph_string_background (s->next, 1);
4258 }
97210f4e 4259
06a2c219
GM
4260 /* Set up S->gc, set clipping and draw S. */
4261 x_set_glyph_string_gc (s);
4262 x_set_glyph_string_clipping (s);
4263
4264 switch (s->first_glyph->type)
4265 {
4266 case IMAGE_GLYPH:
4267 x_draw_image_glyph_string (s);
4268 break;
4269
4270 case STRETCH_GLYPH:
4271 x_draw_stretch_glyph_string (s);
4272 break;
4273
4274 case CHAR_GLYPH:
66ac4b0e
GM
4275 if (s->for_overlaps_p)
4276 s->background_filled_p = 1;
4277 else
4278 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4279 x_draw_glyph_string_foreground (s);
4280 break;
4281
b4192550
KH
4282 case COMPOSITE_GLYPH:
4283 if (s->for_overlaps_p || s->gidx > 0)
4284 s->background_filled_p = 1;
4285 else
4286 x_draw_glyph_string_background (s, 1);
4287 x_draw_composite_glyph_string_foreground (s);
4288 break;
4289
06a2c219
GM
4290 default:
4291 abort ();
4292 }
4293
66ac4b0e 4294 if (!s->for_overlaps_p)
06a2c219 4295 {
66ac4b0e
GM
4296 /* Draw underline. */
4297 if (s->face->underline_p)
4298 {
e24e84cc
GM
4299 unsigned long tem, h;
4300 int y;
06a2c219 4301
e24e84cc 4302 /* Get the underline thickness. Default is 1 pixel. */
66ac4b0e
GM
4303 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4304 h = 1;
e24e84cc
GM
4305
4306 /* Get the underline position. This is the recommended
4307 vertical offset in pixels from the baseline to the top of
4308 the underline. This is a signed value according to the
4309 specs, and its default is
4310
4311 ROUND ((maximum descent) / 2), with
4312 ROUND(x) = floor (x + 0.5) */
4313
4314 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4315 y = s->ybase + (long) tem;
4316 else if (s->face->font)
4317 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4318 else
4319 y = s->height - h;
06a2c219 4320
66ac4b0e 4321 if (s->face->underline_defaulted_p)
e24e84cc
GM
4322 XFillRectangle (s->display, s->window, s->gc,
4323 s->x, y, s->width, h);
66ac4b0e
GM
4324 else
4325 {
4326 XGCValues xgcv;
4327 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4328 XSetForeground (s->display, s->gc, s->face->underline_color);
e24e84cc
GM
4329 XFillRectangle (s->display, s->window, s->gc,
4330 s->x, y, s->width, h);
66ac4b0e
GM
4331 XSetForeground (s->display, s->gc, xgcv.foreground);
4332 }
dc6f92b8 4333 }
07e34cb0 4334
66ac4b0e
GM
4335 /* Draw overline. */
4336 if (s->face->overline_p)
06a2c219 4337 {
66ac4b0e
GM
4338 unsigned long dy = 0, h = 1;
4339
4340 if (s->face->overline_color_defaulted_p)
4341 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4342 s->width, h);
4343 else
4344 {
4345 XGCValues xgcv;
4346 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4347 XSetForeground (s->display, s->gc, s->face->overline_color);
4348 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4349 s->width, h);
4350 XSetForeground (s->display, s->gc, xgcv.foreground);
4351 }
06a2c219 4352 }
06a2c219 4353
66ac4b0e
GM
4354 /* Draw strike-through. */
4355 if (s->face->strike_through_p)
06a2c219 4356 {
66ac4b0e
GM
4357 unsigned long h = 1;
4358 unsigned long dy = (s->height - h) / 2;
4359
4360 if (s->face->strike_through_color_defaulted_p)
4361 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4362 s->width, h);
4363 else
4364 {
4365 XGCValues xgcv;
4366 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4367 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4368 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4369 s->width, h);
4370 XSetForeground (s->display, s->gc, xgcv.foreground);
4371 }
06a2c219 4372 }
06a2c219 4373
66ac4b0e
GM
4374 /* Draw relief. */
4375 if (s->face->box != FACE_NO_BOX)
4376 x_draw_glyph_string_box (s);
4377 }
06a2c219
GM
4378
4379 /* Reset clipping. */
4380 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4381}
07e34cb0 4382
06a2c219 4383
b4192550
KH
4384static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4385 struct face **, int));
06a2c219 4386
06a2c219 4387
209f68d9
GM
4388/* Fill glyph string S with composition components specified by S->cmp.
4389
b4192550
KH
4390 FACES is an array of faces for all components of this composition.
4391 S->gidx is the index of the first component for S.
4392 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4393 use its physical height for clipping.
06a2c219 4394
b4192550 4395 Value is the index of a component not in S. */
07e34cb0 4396
b4192550
KH
4397static int
4398x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4399 struct glyph_string *s;
b4192550 4400 struct face **faces;
66ac4b0e 4401 int overlaps_p;
07e34cb0 4402{
b4192550 4403 int i;
06a2c219 4404
b4192550 4405 xassert (s);
06a2c219 4406
b4192550 4407 s->for_overlaps_p = overlaps_p;
06a2c219 4408
b4192550
KH
4409 s->face = faces[s->gidx];
4410 s->font = s->face->font;
4411 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4412
b4192550
KH
4413 /* For all glyphs of this composition, starting at the offset
4414 S->gidx, until we reach the end of the definition or encounter a
4415 glyph that requires the different face, add it to S. */
4416 ++s->nchars;
4417 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4418 ++s->nchars;
06a2c219 4419
b4192550
KH
4420 /* All glyph strings for the same composition has the same width,
4421 i.e. the width set for the first component of the composition. */
06a2c219 4422
06a2c219
GM
4423 s->width = s->first_glyph->pixel_width;
4424
4425 /* If the specified font could not be loaded, use the frame's
4426 default font, but record the fact that we couldn't load it in
4427 the glyph string so that we can draw rectangles for the
4428 characters of the glyph string. */
4429 if (s->font == NULL)
4430 {
4431 s->font_not_found_p = 1;
4432 s->font = FRAME_FONT (s->f);
4433 }
4434
4435 /* Adjust base line for subscript/superscript text. */
4436 s->ybase += s->first_glyph->voffset;
4437
4438 xassert (s->face && s->face->gc);
4439
4440 /* This glyph string must always be drawn with 16-bit functions. */
4441 s->two_byte_p = 1;
b4192550
KH
4442
4443 return s->gidx + s->nchars;
06a2c219
GM
4444}
4445
4446
209f68d9
GM
4447/* Fill glyph string S from a sequence of character glyphs.
4448
06a2c219 4449 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4450 first glyph to consider, END is the index of the last + 1.
4451 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4452 use its physical height for clipping.
66ac4b0e
GM
4453
4454 Value is the index of the first glyph not in S. */
06a2c219
GM
4455
4456static int
66ac4b0e 4457x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4458 struct glyph_string *s;
4459 int face_id;
66ac4b0e 4460 int start, end, overlaps_p;
06a2c219
GM
4461{
4462 struct glyph *glyph, *last;
4463 int voffset;
ee569018 4464 int glyph_not_available_p;
06a2c219 4465
06a2c219
GM
4466 xassert (s->f == XFRAME (s->w->frame));
4467 xassert (s->nchars == 0);
4468 xassert (start >= 0 && end > start);
4469
66ac4b0e 4470 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4471 glyph = s->row->glyphs[s->area] + start;
4472 last = s->row->glyphs[s->area] + end;
4473 voffset = glyph->voffset;
4474
ee569018
KH
4475 glyph_not_available_p = glyph->glyph_not_available_p;
4476
06a2c219
GM
4477 while (glyph < last
4478 && glyph->type == CHAR_GLYPH
4479 && glyph->voffset == voffset
ee569018
KH
4480 /* Same face id implies same font, nowadays. */
4481 && glyph->face_id == face_id
4482 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4483 {
ee569018
KH
4484 int two_byte_p;
4485
06a2c219 4486 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4487 s->char2b + s->nchars,
4488 &two_byte_p);
4489 s->two_byte_p = two_byte_p;
06a2c219
GM
4490 ++s->nchars;
4491 xassert (s->nchars <= end - start);
4492 s->width += glyph->pixel_width;
4493 ++glyph;
4494 }
4495
4496 s->font = s->face->font;
4497 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4498
4499 /* If the specified font could not be loaded, use the frame's font,
4500 but record the fact that we couldn't load it in
4501 S->font_not_found_p so that we can draw rectangles for the
4502 characters of the glyph string. */
ee569018 4503 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4504 {
4505 s->font_not_found_p = 1;
4506 s->font = FRAME_FONT (s->f);
4507 }
4508
4509 /* Adjust base line for subscript/superscript text. */
4510 s->ybase += voffset;
66ac4b0e 4511
06a2c219
GM
4512 xassert (s->face && s->face->gc);
4513 return glyph - s->row->glyphs[s->area];
07e34cb0 4514}
dc6f92b8 4515
06a2c219
GM
4516
4517/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4518
dfcf069d 4519static void
06a2c219
GM
4520x_fill_image_glyph_string (s)
4521 struct glyph_string *s;
4522{
4523 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4524 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4525 xassert (s->img);
43d120d8 4526 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4527 s->font = s->face->font;
4528 s->width = s->first_glyph->pixel_width;
4529
4530 /* Adjust base line for subscript/superscript text. */
4531 s->ybase += s->first_glyph->voffset;
4532}
4533
4534
209f68d9 4535/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4536
209f68d9
GM
4537 ROW is the glyph row in which the glyphs are found, AREA is the
4538 area within the row. START is the index of the first glyph to
4539 consider, END is the index of the last + 1.
4540
4541 Value is the index of the first glyph not in S. */
4542
4543static int
4544x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4545 struct glyph_string *s;
209f68d9
GM
4546 struct glyph_row *row;
4547 enum glyph_row_area area;
4548 int start, end;
06a2c219 4549{
209f68d9
GM
4550 struct glyph *glyph, *last;
4551 int voffset, face_id;
4552
06a2c219 4553 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4554
4555 glyph = s->row->glyphs[s->area] + start;
4556 last = s->row->glyphs[s->area] + end;
4557 face_id = glyph->face_id;
4558 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4559 s->font = s->face->font;
209f68d9
GM
4560 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4561 s->width = glyph->pixel_width;
4562 voffset = glyph->voffset;
4563
4564 for (++glyph;
4565 (glyph < last
4566 && glyph->type == STRETCH_GLYPH
4567 && glyph->voffset == voffset
4568 && glyph->face_id == face_id);
4569 ++glyph)
4570 s->width += glyph->pixel_width;
06a2c219
GM
4571
4572 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4573 s->ybase += voffset;
4574
4575 xassert (s->face && s->face->gc);
4576 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4577}
4578
4579
4580/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4581 of XChar2b structures for S; it can't be allocated in
4582 x_init_glyph_string because it must be allocated via `alloca'. W
4583 is the window on which S is drawn. ROW and AREA are the glyph row
4584 and area within the row from which S is constructed. START is the
4585 index of the first glyph structure covered by S. HL is a
4586 face-override for drawing S. */
4587
4588static void
4589x_init_glyph_string (s, char2b, w, row, area, start, hl)
4590 struct glyph_string *s;
4591 XChar2b *char2b;
4592 struct window *w;
4593 struct glyph_row *row;
4594 enum glyph_row_area area;
4595 int start;
4596 enum draw_glyphs_face hl;
4597{
4598 bzero (s, sizeof *s);
4599 s->w = w;
4600 s->f = XFRAME (w->frame);
4601 s->display = FRAME_X_DISPLAY (s->f);
4602 s->window = FRAME_X_WINDOW (s->f);
4603 s->char2b = char2b;
4604 s->hl = hl;
4605 s->row = row;
4606 s->area = area;
4607 s->first_glyph = row->glyphs[area] + start;
4608 s->height = row->height;
4609 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4610
9ea173e8
GM
4611 /* Display the internal border below the tool-bar window. */
4612 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4613 s->y -= s->f->output_data.x->internal_border_width;
4614
4615 s->ybase = s->y + row->ascent;
4616}
4617
4618
4619/* Set background width of glyph string S. START is the index of the
4620 first glyph following S. LAST_X is the right-most x-position + 1
4621 in the drawing area. */
4622
4623static INLINE void
4624x_set_glyph_string_background_width (s, start, last_x)
4625 struct glyph_string *s;
4626 int start;
4627 int last_x;
4628{
4629 /* If the face of this glyph string has to be drawn to the end of
4630 the drawing area, set S->extends_to_end_of_line_p. */
4631 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4632
4633 if (start == s->row->used[s->area]
4634 && s->hl == DRAW_NORMAL_TEXT
4635 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4636 || s->face->background != default_face->background
4637 || s->face->stipple != default_face->stipple))
4638 s->extends_to_end_of_line_p = 1;
4639
4640 /* If S extends its face to the end of the line, set its
4641 background_width to the distance to the right edge of the drawing
4642 area. */
4643 if (s->extends_to_end_of_line_p)
1da3fd71 4644 s->background_width = last_x - s->x + 1;
06a2c219
GM
4645 else
4646 s->background_width = s->width;
4647}
4648
4649
4650/* Add a glyph string for a stretch glyph to the list of strings
4651 between HEAD and TAIL. START is the index of the stretch glyph in
4652 row area AREA of glyph row ROW. END is the index of the last glyph
4653 in that glyph row area. X is the current output position assigned
4654 to the new glyph string constructed. HL overrides that face of the
4655 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4656 is the right-most x-position of the drawing area. */
4657
8abee2e1
DL
4658/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4659 and below -- keep them on one line. */
4660#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4661 do \
4662 { \
4663 s = (struct glyph_string *) alloca (sizeof *s); \
4664 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4665 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4666 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4667 s->x = (X); \
4668 } \
4669 while (0)
4670
4671
4672/* Add a glyph string for an image glyph to the list of strings
4673 between HEAD and TAIL. START is the index of the image glyph in
4674 row area AREA of glyph row ROW. END is the index of the last glyph
4675 in that glyph row area. X is the current output position assigned
4676 to the new glyph string constructed. HL overrides that face of the
4677 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4678 is the right-most x-position of the drawing area. */
4679
8abee2e1 4680#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4681 do \
4682 { \
4683 s = (struct glyph_string *) alloca (sizeof *s); \
4684 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4685 x_fill_image_glyph_string (s); \
4686 x_append_glyph_string (&HEAD, &TAIL, s); \
4687 ++START; \
4688 s->x = (X); \
4689 } \
4690 while (0)
4691
4692
4693/* Add a glyph string for a sequence of character glyphs to the list
4694 of strings between HEAD and TAIL. START is the index of the first
4695 glyph in row area AREA of glyph row ROW that is part of the new
4696 glyph string. END is the index of the last glyph in that glyph row
4697 area. X is the current output position assigned to the new glyph
4698 string constructed. HL overrides that face of the glyph; e.g. it
4699 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4700 right-most x-position of the drawing area. */
4701
8abee2e1 4702#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4703 do \
4704 { \
3e71d8f2 4705 int c, face_id; \
06a2c219
GM
4706 XChar2b *char2b; \
4707 \
43d120d8 4708 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4709 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4710 \
b4192550
KH
4711 s = (struct glyph_string *) alloca (sizeof *s); \
4712 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4713 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4714 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4715 s->x = (X); \
4716 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4717 OVERLAPS_P); \
06a2c219
GM
4718 } \
4719 while (0)
4720
4721
b4192550
KH
4722/* Add a glyph string for a composite sequence to the list of strings
4723 between HEAD and TAIL. START is the index of the first glyph in
4724 row area AREA of glyph row ROW that is part of the new glyph
4725 string. END is the index of the last glyph in that glyph row area.
4726 X is the current output position assigned to the new glyph string
4727 constructed. HL overrides that face of the glyph; e.g. it is
4728 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4729 x-position of the drawing area. */
4730
6c27ec25 4731#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4732 do { \
43d120d8
KH
4733 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4734 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4735 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4736 struct composition *cmp = composition_table[cmp_id]; \
4737 int glyph_len = cmp->glyph_len; \
4738 XChar2b *char2b; \
4739 struct face **faces; \
4740 struct glyph_string *first_s = NULL; \
4741 int n; \
4742 \
ee569018 4743 base_face = base_face->ascii_face; \
b4192550
KH
4744 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4745 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4746 /* At first, fill in `char2b' and `faces'. */ \
4747 for (n = 0; n < glyph_len; n++) \
4748 { \
43d120d8 4749 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4750 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4751 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4752 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4753 this_face_id, char2b + n, 1); \
b4192550
KH
4754 } \
4755 \
4756 /* Make glyph_strings for each glyph sequence that is drawable by \
4757 the same face, and append them to HEAD/TAIL. */ \
4758 for (n = 0; n < cmp->glyph_len;) \
4759 { \
4760 s = (struct glyph_string *) alloca (sizeof *s); \
4761 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4762 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4763 s->cmp = cmp; \
4764 s->gidx = n; \
b4192550
KH
4765 s->x = (X); \
4766 \
4767 if (n == 0) \
4768 first_s = s; \
4769 \
4770 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4771 } \
4772 \
4773 ++START; \
4774 s = first_s; \
4775 } while (0)
4776
4777
06a2c219
GM
4778/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4779 of AREA of glyph row ROW on window W between indices START and END.
4780 HL overrides the face for drawing glyph strings, e.g. it is
4781 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4782 x-positions of the drawing area.
4783
4784 This is an ugly monster macro construct because we must use alloca
4785 to allocate glyph strings (because x_draw_glyphs can be called
4786 asynchronously). */
4787
8abee2e1 4788#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4789 do \
4790 { \
4791 HEAD = TAIL = NULL; \
4792 while (START < END) \
4793 { \
4794 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4795 switch (first_glyph->type) \
4796 { \
4797 case CHAR_GLYPH: \
4798 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4799 TAIL, HL, X, LAST_X, \
4800 OVERLAPS_P); \
06a2c219
GM
4801 break; \
4802 \
b4192550
KH
4803 case COMPOSITE_GLYPH: \
4804 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4805 HEAD, TAIL, HL, X, LAST_X,\
4806 OVERLAPS_P); \
4807 break; \
4808 \
06a2c219
GM
4809 case STRETCH_GLYPH: \
4810 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4811 HEAD, TAIL, HL, X, LAST_X); \
4812 break; \
4813 \
4814 case IMAGE_GLYPH: \
4815 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4816 TAIL, HL, X, LAST_X); \
4817 break; \
4818 \
4819 default: \
4820 abort (); \
4821 } \
4822 \
4823 x_set_glyph_string_background_width (s, START, LAST_X); \
4824 (X) += s->width; \
4825 } \
4826 } \
4827 while (0)
4828
4829
4830/* Draw glyphs between START and END in AREA of ROW on window W,
4831 starting at x-position X. X is relative to AREA in W. HL is a
4832 face-override with the following meaning:
4833
4834 DRAW_NORMAL_TEXT draw normally
4835 DRAW_CURSOR draw in cursor face
4836 DRAW_MOUSE_FACE draw in mouse face.
4837 DRAW_INVERSE_VIDEO draw in mode line face
4838 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4839 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4840
4841 If REAL_START is non-null, return in *REAL_START the real starting
4842 position for display. This can be different from START in case
4843 overlapping glyphs must be displayed. If REAL_END is non-null,
4844 return in *REAL_END the real end position for display. This can be
4845 different from END in case overlapping glyphs must be displayed.
4846
66ac4b0e
GM
4847 If OVERLAPS_P is non-zero, draw only the foreground of characters
4848 and clip to the physical height of ROW.
4849
06a2c219
GM
4850 Value is the x-position reached, relative to AREA of W. */
4851
4852static int
66ac4b0e
GM
4853x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4854 overlaps_p)
06a2c219
GM
4855 struct window *w;
4856 int x;
4857 struct glyph_row *row;
4858 enum glyph_row_area area;
4859 int start, end;
4860 enum draw_glyphs_face hl;
4861 int *real_start, *real_end;
66ac4b0e 4862 int overlaps_p;
dc6f92b8 4863{
06a2c219
GM
4864 struct glyph_string *head, *tail;
4865 struct glyph_string *s;
4866 int last_x, area_width;
4867 int x_reached;
4868 int i, j;
4869
4870 /* Let's rather be paranoid than getting a SEGV. */
06a2c219 4871 end = min (end, row->used[area]);
a8710abf
GM
4872 start = max (0, start);
4873 start = min (end, start);
06a2c219
GM
4874 if (real_start)
4875 *real_start = start;
4876 if (real_end)
4877 *real_end = end;
4878
4879 /* Translate X to frame coordinates. Set last_x to the right
4880 end of the drawing area. */
4881 if (row->full_width_p)
4882 {
4883 /* X is relative to the left edge of W, without scroll bars
4884 or flag areas. */
4885 struct frame *f = XFRAME (w->frame);
110859fc 4886 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4887 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4888
06a2c219
GM
4889 x += window_left_x;
4890 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4891 last_x = window_left_x + area_width;
4892
4893 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4894 {
110859fc 4895 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4896 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4897 last_x += width;
4898 else
4899 x -= width;
4900 }
dc6f92b8 4901
b9432a85
GM
4902 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4903 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4904 }
4905 else
dc6f92b8 4906 {
06a2c219
GM
4907 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4908 area_width = window_box_width (w, area);
4909 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4910 }
4911
06a2c219
GM
4912 /* Build a doubly-linked list of glyph_string structures between
4913 head and tail from what we have to draw. Note that the macro
4914 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4915 the reason we use a separate variable `i'. */
4916 i = start;
66ac4b0e
GM
4917 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4918 overlaps_p);
06a2c219
GM
4919 if (tail)
4920 x_reached = tail->x + tail->background_width;
4921 else
4922 x_reached = x;
90e65f07 4923
06a2c219
GM
4924 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4925 the row, redraw some glyphs in front or following the glyph
4926 strings built above. */
a8710abf 4927 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4928 {
4929 int dummy_x = 0;
4930 struct glyph_string *h, *t;
4931
4932 /* Compute overhangs for all glyph strings. */
4933 for (s = head; s; s = s->next)
4934 x_compute_glyph_string_overhangs (s);
4935
4936 /* Prepend glyph strings for glyphs in front of the first glyph
4937 string that are overwritten because of the first glyph
4938 string's left overhang. The background of all strings
4939 prepended must be drawn because the first glyph string
4940 draws over it. */
4941 i = x_left_overwritten (head);
4942 if (i >= 0)
4943 {
4944 j = i;
4945 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4946 DRAW_NORMAL_TEXT, dummy_x, last_x,
4947 overlaps_p);
06a2c219
GM
4948 start = i;
4949 if (real_start)
4950 *real_start = start;
4951 x_compute_overhangs_and_x (t, head->x, 1);
4952 x_prepend_glyph_string_lists (&head, &tail, h, t);
4953 }
58769bee 4954
06a2c219
GM
4955 /* Prepend glyph strings for glyphs in front of the first glyph
4956 string that overwrite that glyph string because of their
4957 right overhang. For these strings, only the foreground must
4958 be drawn, because it draws over the glyph string at `head'.
4959 The background must not be drawn because this would overwrite
4960 right overhangs of preceding glyphs for which no glyph
4961 strings exist. */
4962 i = x_left_overwriting (head);
4963 if (i >= 0)
4964 {
4965 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4966 DRAW_NORMAL_TEXT, dummy_x, last_x,
4967 overlaps_p);
06a2c219
GM
4968 for (s = h; s; s = s->next)
4969 s->background_filled_p = 1;
4970 if (real_start)
4971 *real_start = i;
4972 x_compute_overhangs_and_x (t, head->x, 1);
4973 x_prepend_glyph_string_lists (&head, &tail, h, t);
4974 }
dbcb258a 4975
06a2c219
GM
4976 /* Append glyphs strings for glyphs following the last glyph
4977 string tail that are overwritten by tail. The background of
4978 these strings has to be drawn because tail's foreground draws
4979 over it. */
4980 i = x_right_overwritten (tail);
4981 if (i >= 0)
4982 {
4983 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4984 DRAW_NORMAL_TEXT, x, last_x,
4985 overlaps_p);
06a2c219
GM
4986 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4987 x_append_glyph_string_lists (&head, &tail, h, t);
4988 if (real_end)
4989 *real_end = i;
4990 }
dc6f92b8 4991
06a2c219
GM
4992 /* Append glyph strings for glyphs following the last glyph
4993 string tail that overwrite tail. The foreground of such
4994 glyphs has to be drawn because it writes into the background
4995 of tail. The background must not be drawn because it could
4996 paint over the foreground of following glyphs. */
4997 i = x_right_overwriting (tail);
4998 if (i >= 0)
4999 {
5000 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
5001 DRAW_NORMAL_TEXT, x, last_x,
5002 overlaps_p);
06a2c219
GM
5003 for (s = h; s; s = s->next)
5004 s->background_filled_p = 1;
5005 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5006 x_append_glyph_string_lists (&head, &tail, h, t);
5007 if (real_end)
5008 *real_end = i;
5009 }
5010 }
58769bee 5011
06a2c219
GM
5012 /* Draw all strings. */
5013 for (s = head; s; s = s->next)
5014 x_draw_glyph_string (s);
dc6f92b8 5015
06a2c219
GM
5016 /* Value is the x-position up to which drawn, relative to AREA of W.
5017 This doesn't include parts drawn because of overhangs. */
5018 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5019 if (!row->full_width_p)
5020 {
5021 if (area > LEFT_MARGIN_AREA)
5022 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5023 if (area > TEXT_AREA)
5024 x_reached -= window_box_width (w, TEXT_AREA);
5025 }
a8710abf 5026
06a2c219
GM
5027 return x_reached;
5028}
dc6f92b8 5029
dc6f92b8 5030
66ac4b0e
GM
5031/* Fix the display of area AREA of overlapping row ROW in window W. */
5032
5033static void
5034x_fix_overlapping_area (w, row, area)
5035 struct window *w;
5036 struct glyph_row *row;
5037 enum glyph_row_area area;
5038{
5039 int i, x;
5040
5041 BLOCK_INPUT;
5042
5043 if (area == LEFT_MARGIN_AREA)
5044 x = 0;
5045 else if (area == TEXT_AREA)
5046 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5047 else
5048 x = (window_box_width (w, LEFT_MARGIN_AREA)
5049 + window_box_width (w, TEXT_AREA));
5050
5051 for (i = 0; i < row->used[area];)
5052 {
5053 if (row->glyphs[area][i].overlaps_vertically_p)
5054 {
5055 int start = i, start_x = x;
5056
5057 do
5058 {
5059 x += row->glyphs[area][i].pixel_width;
5060 ++i;
5061 }
5062 while (i < row->used[area]
5063 && row->glyphs[area][i].overlaps_vertically_p);
5064
5065 x_draw_glyphs (w, start_x, row, area, start, i,
5066 (row->inverse_p
5067 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5068 NULL, NULL, 1);
5069 }
5070 else
5071 {
5072 x += row->glyphs[area][i].pixel_width;
5073 ++i;
5074 }
5075 }
5076
5077 UNBLOCK_INPUT;
5078}
5079
5080
06a2c219
GM
5081/* Output LEN glyphs starting at START at the nominal cursor position.
5082 Advance the nominal cursor over the text. The global variable
5083 updated_window contains the window being updated, updated_row is
5084 the glyph row being updated, and updated_area is the area of that
5085 row being updated. */
dc6f92b8 5086
06a2c219
GM
5087static void
5088x_write_glyphs (start, len)
5089 struct glyph *start;
5090 int len;
5091{
5092 int x, hpos, real_start, real_end;
d9cdbb3d 5093
06a2c219 5094 xassert (updated_window && updated_row);
dc6f92b8 5095 BLOCK_INPUT;
06a2c219
GM
5096
5097 /* Write glyphs. */
dc6f92b8 5098
06a2c219
GM
5099 hpos = start - updated_row->glyphs[updated_area];
5100 x = x_draw_glyphs (updated_window, output_cursor.x,
5101 updated_row, updated_area,
5102 hpos, hpos + len,
5103 (updated_row->inverse_p
5104 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 5105 &real_start, &real_end, 0);
b30ec466 5106
06a2c219
GM
5107 /* If we drew over the cursor, note that it is not visible any more. */
5108 note_overwritten_text_cursor (updated_window, real_start,
5109 real_end - real_start);
dc6f92b8
JB
5110
5111 UNBLOCK_INPUT;
06a2c219
GM
5112
5113 /* Advance the output cursor. */
5114 output_cursor.hpos += len;
5115 output_cursor.x = x;
dc6f92b8
JB
5116}
5117
0cdd0c9f 5118
06a2c219 5119/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 5120
06a2c219
GM
5121static void
5122x_insert_glyphs (start, len)
5123 struct glyph *start;
5124 register int len;
5125{
5126 struct frame *f;
5127 struct window *w;
5128 int line_height, shift_by_width, shifted_region_width;
5129 struct glyph_row *row;
5130 struct glyph *glyph;
5131 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 5132
06a2c219 5133 xassert (updated_window && updated_row);
0cdd0c9f 5134 BLOCK_INPUT;
06a2c219
GM
5135 w = updated_window;
5136 f = XFRAME (WINDOW_FRAME (w));
5137
5138 /* Get the height of the line we are in. */
5139 row = updated_row;
5140 line_height = row->height;
5141
5142 /* Get the width of the glyphs to insert. */
5143 shift_by_width = 0;
5144 for (glyph = start; glyph < start + len; ++glyph)
5145 shift_by_width += glyph->pixel_width;
5146
5147 /* Get the width of the region to shift right. */
5148 shifted_region_width = (window_box_width (w, updated_area)
5149 - output_cursor.x
5150 - shift_by_width);
5151
5152 /* Shift right. */
5153 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5154 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5155 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5156 f->output_data.x->normal_gc,
5157 frame_x, frame_y,
5158 shifted_region_width, line_height,
5159 frame_x + shift_by_width, frame_y);
5160
5161 /* Write the glyphs. */
5162 hpos = start - row->glyphs[updated_area];
5163 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 5164 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
5165 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5166
5167 /* Advance the output cursor. */
5168 output_cursor.hpos += len;
5169 output_cursor.x += shift_by_width;
0cdd0c9f
RS
5170 UNBLOCK_INPUT;
5171}
0cdd0c9f 5172
0cdd0c9f 5173
06a2c219
GM
5174/* Delete N glyphs at the nominal cursor position. Not implemented
5175 for X frames. */
c83febd7
RS
5176
5177static void
06a2c219
GM
5178x_delete_glyphs (n)
5179 register int n;
c83febd7 5180{
06a2c219 5181 abort ();
c83febd7
RS
5182}
5183
0cdd0c9f 5184
06a2c219
GM
5185/* Erase the current text line from the nominal cursor position
5186 (inclusive) to pixel column TO_X (exclusive). The idea is that
5187 everything from TO_X onward is already erased.
5188
5189 TO_X is a pixel position relative to updated_area of
5190 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 5191
06a2c219
GM
5192static void
5193x_clear_end_of_line (to_x)
5194 int to_x;
5195{
5196 struct frame *f;
5197 struct window *w = updated_window;
5198 int max_x, min_y, max_y;
5199 int from_x, from_y, to_y;
5200
5201 xassert (updated_window && updated_row);
5202 f = XFRAME (w->frame);
5203
5204 if (updated_row->full_width_p)
5205 {
5206 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5207 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5208 && !w->pseudo_window_p)
5209 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 5210 }
06a2c219
GM
5211 else
5212 max_x = window_box_width (w, updated_area);
5213 max_y = window_text_bottom_y (w);
dc6f92b8 5214
06a2c219
GM
5215 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5216 of window. For TO_X > 0, truncate to end of drawing area. */
5217 if (to_x == 0)
5218 return;
5219 else if (to_x < 0)
5220 to_x = max_x;
5221 else
5222 to_x = min (to_x, max_x);
dbc4e1c1 5223
06a2c219
GM
5224 to_y = min (max_y, output_cursor.y + updated_row->height);
5225
5226 /* Notice if the cursor will be cleared by this operation. */
5227 if (!updated_row->full_width_p)
5228 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 5229
06a2c219
GM
5230 from_x = output_cursor.x;
5231
5232 /* Translate to frame coordinates. */
5233 if (updated_row->full_width_p)
5234 {
5235 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5236 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5237 }
0cdd0c9f
RS
5238 else
5239 {
06a2c219
GM
5240 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5241 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5242 }
5243
045dee35 5244 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5245 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5246 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5247
5248 /* Prevent inadvertently clearing to end of the X window. */
5249 if (to_x > from_x && to_y > from_y)
5250 {
5251 BLOCK_INPUT;
5252 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5253 from_x, from_y, to_x - from_x, to_y - from_y,
5254 False);
5255 UNBLOCK_INPUT;
0cdd0c9f 5256 }
0cdd0c9f 5257}
dbc4e1c1 5258
0cdd0c9f 5259
06a2c219 5260/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5261 frame. Otherwise clear the selected frame. */
06a2c219
GM
5262
5263static void
5264x_clear_frame ()
0cdd0c9f 5265{
06a2c219 5266 struct frame *f;
0cdd0c9f 5267
06a2c219
GM
5268 if (updating_frame)
5269 f = updating_frame;
0cdd0c9f 5270 else
b86bd3dd 5271 f = SELECTED_FRAME ();
58769bee 5272
06a2c219
GM
5273 /* Clearing the frame will erase any cursor, so mark them all as no
5274 longer visible. */
5275 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5276 output_cursor.hpos = output_cursor.vpos = 0;
5277 output_cursor.x = -1;
5278
5279 /* We don't set the output cursor here because there will always
5280 follow an explicit cursor_to. */
5281 BLOCK_INPUT;
5282 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5283
5284 /* We have to clear the scroll bars, too. If we have changed
5285 colors or something like that, then they should be notified. */
5286 x_scroll_bar_clear (f);
0cdd0c9f 5287
06a2c219
GM
5288 XFlush (FRAME_X_DISPLAY (f));
5289 UNBLOCK_INPUT;
dc6f92b8 5290}
06a2c219
GM
5291
5292
dc6f92b8 5293\f
dbc4e1c1
JB
5294/* Invert the middle quarter of the frame for .15 sec. */
5295
06a2c219
GM
5296/* We use the select system call to do the waiting, so we have to make
5297 sure it's available. If it isn't, we just won't do visual bells. */
5298
dbc4e1c1
JB
5299#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5300
06a2c219
GM
5301
5302/* Subtract the `struct timeval' values X and Y, storing the result in
5303 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5304
5305static int
5306timeval_subtract (result, x, y)
5307 struct timeval *result, x, y;
5308{
06a2c219
GM
5309 /* Perform the carry for the later subtraction by updating y. This
5310 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5311 if (x.tv_usec < y.tv_usec)
5312 {
5313 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5314 y.tv_usec -= 1000000 * nsec;
5315 y.tv_sec += nsec;
5316 }
06a2c219 5317
dbc4e1c1
JB
5318 if (x.tv_usec - y.tv_usec > 1000000)
5319 {
5320 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5321 y.tv_usec += 1000000 * nsec;
5322 y.tv_sec -= nsec;
5323 }
5324
06a2c219
GM
5325 /* Compute the time remaining to wait. tv_usec is certainly
5326 positive. */
dbc4e1c1
JB
5327 result->tv_sec = x.tv_sec - y.tv_sec;
5328 result->tv_usec = x.tv_usec - y.tv_usec;
5329
06a2c219
GM
5330 /* Return indication of whether the result should be considered
5331 negative. */
dbc4e1c1
JB
5332 return x.tv_sec < y.tv_sec;
5333}
dc6f92b8 5334
dfcf069d 5335void
f676886a
JB
5336XTflash (f)
5337 struct frame *f;
dc6f92b8 5338{
dbc4e1c1 5339 BLOCK_INPUT;
dc6f92b8 5340
dbc4e1c1
JB
5341 {
5342 GC gc;
dc6f92b8 5343
06a2c219
GM
5344 /* Create a GC that will use the GXxor function to flip foreground
5345 pixels into background pixels. */
dbc4e1c1
JB
5346 {
5347 XGCValues values;
dc6f92b8 5348
dbc4e1c1 5349 values.function = GXxor;
7556890b
RS
5350 values.foreground = (f->output_data.x->foreground_pixel
5351 ^ f->output_data.x->background_pixel);
58769bee 5352
334208b7 5353 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5354 GCFunction | GCForeground, &values);
5355 }
dc6f92b8 5356
dbc4e1c1 5357 {
e84e14c3
RS
5358 /* Get the height not including a menu bar widget. */
5359 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5360 /* Height of each line to flash. */
5361 int flash_height = FRAME_LINE_HEIGHT (f);
5362 /* These will be the left and right margins of the rectangles. */
5363 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5364 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5365
5366 int width;
5367
5368 /* Don't flash the area between a scroll bar and the frame
5369 edge it is next to. */
5370 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5371 {
5372 case vertical_scroll_bar_left:
5373 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5374 break;
5375
5376 case vertical_scroll_bar_right:
5377 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5378 break;
06a2c219
GM
5379
5380 default:
5381 break;
e84e14c3
RS
5382 }
5383
5384 width = flash_right - flash_left;
5385
5386 /* If window is tall, flash top and bottom line. */
5387 if (height > 3 * FRAME_LINE_HEIGHT (f))
5388 {
5389 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5390 flash_left,
5391 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5392 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5393 width, flash_height);
5394 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5395 flash_left,
5396 (height - flash_height
5397 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5398 width, flash_height);
5399 }
5400 else
5401 /* If it is short, flash it all. */
5402 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5403 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5404 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5405
06a2c219 5406 x_flush (f);
dc6f92b8 5407
dbc4e1c1 5408 {
06a2c219 5409 struct timeval wakeup;
dc6f92b8 5410
66c30ea1 5411 EMACS_GET_TIME (wakeup);
dc6f92b8 5412
dbc4e1c1
JB
5413 /* Compute time to wait until, propagating carry from usecs. */
5414 wakeup.tv_usec += 150000;
5415 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5416 wakeup.tv_usec %= 1000000;
5417
5418 /* Keep waiting until past the time wakeup. */
5419 while (1)
5420 {
5421 struct timeval timeout;
5422
66c30ea1 5423 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5424
5425 /* In effect, timeout = wakeup - timeout.
5426 Break if result would be negative. */
5427 if (timeval_subtract (&timeout, wakeup, timeout))
5428 break;
5429
5430 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5431 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5432 }
5433 }
58769bee 5434
e84e14c3
RS
5435 /* If window is tall, flash top and bottom line. */
5436 if (height > 3 * FRAME_LINE_HEIGHT (f))
5437 {
5438 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5439 flash_left,
5440 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5441 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5442 width, flash_height);
5443 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5444 flash_left,
5445 (height - flash_height
5446 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5447 width, flash_height);
5448 }
5449 else
5450 /* If it is short, flash it all. */
5451 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5452 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5453 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5454
334208b7 5455 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5456 x_flush (f);
dc6f92b8 5457 }
dbc4e1c1
JB
5458 }
5459
5460 UNBLOCK_INPUT;
dc6f92b8
JB
5461}
5462
06a2c219 5463#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5464
5465
dc6f92b8
JB
5466/* Make audible bell. */
5467
dfcf069d 5468void
dc6f92b8
JB
5469XTring_bell ()
5470{
b86bd3dd
GM
5471 struct frame *f = SELECTED_FRAME ();
5472
5473 if (FRAME_X_DISPLAY (f))
5474 {
dbc4e1c1 5475#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5476 if (visible_bell)
5477 XTflash (f);
5478 else
dbc4e1c1 5479#endif
b86bd3dd
GM
5480 {
5481 BLOCK_INPUT;
5482 XBell (FRAME_X_DISPLAY (f), 0);
5483 XFlush (FRAME_X_DISPLAY (f));
5484 UNBLOCK_INPUT;
5485 }
dc6f92b8
JB
5486 }
5487}
06a2c219 5488
dc6f92b8 5489\f
06a2c219
GM
5490/* Specify how many text lines, from the top of the window,
5491 should be affected by insert-lines and delete-lines operations.
5492 This, and those operations, are used only within an update
5493 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5494
dfcf069d 5495static void
06a2c219
GM
5496XTset_terminal_window (n)
5497 register int n;
dc6f92b8 5498{
06a2c219 5499 /* This function intentionally left blank. */
dc6f92b8
JB
5500}
5501
06a2c219
GM
5502
5503\f
5504/***********************************************************************
5505 Line Dance
5506 ***********************************************************************/
5507
5508/* Perform an insert-lines or delete-lines operation, inserting N
5509 lines or deleting -N lines at vertical position VPOS. */
5510
dfcf069d 5511static void
06a2c219
GM
5512x_ins_del_lines (vpos, n)
5513 int vpos, n;
dc6f92b8
JB
5514{
5515 abort ();
5516}
06a2c219
GM
5517
5518
5519/* Scroll part of the display as described by RUN. */
dc6f92b8 5520
dfcf069d 5521static void
06a2c219
GM
5522x_scroll_run (w, run)
5523 struct window *w;
5524 struct run *run;
dc6f92b8 5525{
06a2c219
GM
5526 struct frame *f = XFRAME (w->frame);
5527 int x, y, width, height, from_y, to_y, bottom_y;
5528
5529 /* Get frame-relative bounding box of the text display area of W,
5530 without mode lines. Include in this box the flags areas to the
5531 left and right of W. */
5532 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5533 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5534 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5535
5536 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5537 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5538 bottom_y = y + height;
dc6f92b8 5539
06a2c219
GM
5540 if (to_y < from_y)
5541 {
5542 /* Scrolling up. Make sure we don't copy part of the mode
5543 line at the bottom. */
5544 if (from_y + run->height > bottom_y)
5545 height = bottom_y - from_y;
5546 else
5547 height = run->height;
5548 }
dc6f92b8 5549 else
06a2c219
GM
5550 {
5551 /* Scolling down. Make sure we don't copy over the mode line.
5552 at the bottom. */
5553 if (to_y + run->height > bottom_y)
5554 height = bottom_y - to_y;
5555 else
5556 height = run->height;
5557 }
7a13e894 5558
06a2c219
GM
5559 BLOCK_INPUT;
5560
5561 /* Cursor off. Will be switched on again in x_update_window_end. */
5562 updated_window = w;
5563 x_clear_cursor (w);
5564
5565 XCopyArea (FRAME_X_DISPLAY (f),
5566 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5567 f->output_data.x->normal_gc,
5568 x, from_y,
5569 width, height,
5570 x, to_y);
5571
5572 UNBLOCK_INPUT;
5573}
dc6f92b8 5574
dc6f92b8 5575
06a2c219
GM
5576\f
5577/***********************************************************************
5578 Exposure Events
5579 ***********************************************************************/
5580
5581/* Redisplay an exposed area of frame F. X and Y are the upper-left
5582 corner of the exposed rectangle. W and H are width and height of
5583 the exposed area. All are pixel values. W or H zero means redraw
5584 the entire frame. */
dc6f92b8 5585
06a2c219
GM
5586static void
5587expose_frame (f, x, y, w, h)
5588 struct frame *f;
5589 int x, y, w, h;
dc6f92b8 5590{
06a2c219 5591 XRectangle r;
dc6f92b8 5592
06a2c219 5593 TRACE ((stderr, "expose_frame "));
dc6f92b8 5594
06a2c219
GM
5595 /* No need to redraw if frame will be redrawn soon. */
5596 if (FRAME_GARBAGED_P (f))
dc6f92b8 5597 {
06a2c219
GM
5598 TRACE ((stderr, " garbaged\n"));
5599 return;
5600 }
5601
5602 /* If basic faces haven't been realized yet, there is no point in
5603 trying to redraw anything. This can happen when we get an expose
5604 event while Emacs is starting, e.g. by moving another window. */
5605 if (FRAME_FACE_CACHE (f) == NULL
5606 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5607 {
5608 TRACE ((stderr, " no faces\n"));
5609 return;
58769bee 5610 }
06a2c219
GM
5611
5612 if (w == 0 || h == 0)
58769bee 5613 {
06a2c219
GM
5614 r.x = r.y = 0;
5615 r.width = CANON_X_UNIT (f) * f->width;
5616 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5617 }
5618 else
5619 {
06a2c219
GM
5620 r.x = x;
5621 r.y = y;
5622 r.width = w;
5623 r.height = h;
5624 }
5625
5626 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5627 expose_window_tree (XWINDOW (f->root_window), &r);
5628
9ea173e8 5629 if (WINDOWP (f->tool_bar_window))
06a2c219 5630 {
9ea173e8 5631 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5632 XRectangle window_rect;
5633 XRectangle intersection_rect;
5634 int window_x, window_y, window_width, window_height;
5635
5636
5637 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5638 window_rect.x = window_x;
5639 window_rect.y = window_y;
5640 window_rect.width = window_width;
5641 window_rect.height = window_height;
5642
5643 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5644 expose_window (w, &intersection_rect);
5645 }
5646
5647#ifndef USE_X_TOOLKIT
5648 if (WINDOWP (f->menu_bar_window))
5649 {
5650 struct window *w = XWINDOW (f->menu_bar_window);
5651 XRectangle window_rect;
5652 XRectangle intersection_rect;
5653 int window_x, window_y, window_width, window_height;
5654
5655
5656 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5657 window_rect.x = window_x;
5658 window_rect.y = window_y;
5659 window_rect.width = window_width;
5660 window_rect.height = window_height;
5661
5662 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5663 expose_window (w, &intersection_rect);
dc6f92b8 5664 }
06a2c219 5665#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5666}
5667
06a2c219
GM
5668
5669/* Redraw (parts) of all windows in the window tree rooted at W that
5670 intersect R. R contains frame pixel coordinates. */
5671
58769bee 5672static void
06a2c219
GM
5673expose_window_tree (w, r)
5674 struct window *w;
5675 XRectangle *r;
dc6f92b8 5676{
06a2c219
GM
5677 while (w)
5678 {
5679 if (!NILP (w->hchild))
5680 expose_window_tree (XWINDOW (w->hchild), r);
5681 else if (!NILP (w->vchild))
5682 expose_window_tree (XWINDOW (w->vchild), r);
5683 else
5684 {
5685 XRectangle window_rect;
5686 XRectangle intersection_rect;
5687 struct frame *f = XFRAME (w->frame);
5688 int window_x, window_y, window_width, window_height;
5689
5690 /* Frame-relative pixel rectangle of W. */
5691 window_box (w, -1, &window_x, &window_y, &window_width,
5692 &window_height);
5693 window_rect.x
5694 = (window_x
110859fc 5695 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5696 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5697 window_rect.y = window_y;
5698 window_rect.width
5699 = (window_width
110859fc 5700 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5701 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5702 window_rect.height
5703 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5704
5705 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5706 expose_window (w, &intersection_rect);
5707 }
58769bee 5708
06a2c219
GM
5709 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5710 }
5711}
58769bee 5712
dc6f92b8 5713
06a2c219
GM
5714/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5715 which intersects rectangle R. R is in window-relative coordinates. */
5716
5717static void
5718expose_area (w, row, r, area)
5719 struct window *w;
5720 struct glyph_row *row;
5721 XRectangle *r;
5722 enum glyph_row_area area;
5723{
5724 int x;
5725 struct glyph *first = row->glyphs[area];
5726 struct glyph *end = row->glyphs[area] + row->used[area];
5727 struct glyph *last;
5728 int first_x;
5729
5730 /* Set x to the window-relative start position for drawing glyphs of
5731 AREA. The first glyph of the text area can be partially visible.
5732 The first glyphs of other areas cannot. */
5733 if (area == LEFT_MARGIN_AREA)
5734 x = 0;
5735 else if (area == TEXT_AREA)
5736 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5737 else
5738 x = (window_box_width (w, LEFT_MARGIN_AREA)
5739 + window_box_width (w, TEXT_AREA));
5740
6fb13182
GM
5741 if (area == TEXT_AREA && row->fill_line_p)
5742 /* If row extends face to end of line write the whole line. */
5743 x_draw_glyphs (w, x, row, area,
5744 0, row->used[area],
06a2c219 5745 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5746 NULL, NULL, 0);
6fb13182
GM
5747 else
5748 {
5749 /* Find the first glyph that must be redrawn. */
5750 while (first < end
5751 && x + first->pixel_width < r->x)
5752 {
5753 x += first->pixel_width;
5754 ++first;
5755 }
5756
5757 /* Find the last one. */
5758 last = first;
5759 first_x = x;
5760 while (last < end
5761 && x < r->x + r->width)
5762 {
5763 x += last->pixel_width;
5764 ++last;
5765 }
5766
5767 /* Repaint. */
5768 if (last > first)
5769 x_draw_glyphs (w, first_x, row, area,
5770 first - row->glyphs[area],
5771 last - row->glyphs[area],
5772 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5773 NULL, NULL, 0);
5774 }
06a2c219
GM
5775}
5776
58769bee 5777
06a2c219
GM
5778/* Redraw the parts of the glyph row ROW on window W intersecting
5779 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5780
06a2c219
GM
5781static void
5782expose_line (w, row, r)
5783 struct window *w;
5784 struct glyph_row *row;
5785 XRectangle *r;
5786{
5787 xassert (row->enabled_p);
5788
5789 if (row->mode_line_p || w->pseudo_window_p)
5790 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5791 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5792 NULL, NULL, 0);
06a2c219
GM
5793 else
5794 {
5795 if (row->used[LEFT_MARGIN_AREA])
5796 expose_area (w, row, r, LEFT_MARGIN_AREA);
5797 if (row->used[TEXT_AREA])
5798 expose_area (w, row, r, TEXT_AREA);
5799 if (row->used[RIGHT_MARGIN_AREA])
5800 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5801 x_draw_row_bitmaps (w, row);
5802 }
5803}
dc6f92b8 5804
58769bee 5805
06a2c219
GM
5806/* Return non-zero if W's cursor intersects rectangle R. */
5807
5808static int
5809x_phys_cursor_in_rect_p (w, r)
5810 struct window *w;
5811 XRectangle *r;
5812{
5813 XRectangle cr, result;
5814 struct glyph *cursor_glyph;
5815
5816 cursor_glyph = get_phys_cursor_glyph (w);
5817 if (cursor_glyph)
5818 {
5819 cr.x = w->phys_cursor.x;
5820 cr.y = w->phys_cursor.y;
5821 cr.width = cursor_glyph->pixel_width;
5822 cr.height = w->phys_cursor_height;
5823 return x_intersect_rectangles (&cr, r, &result);
5824 }
5825 else
5826 return 0;
dc6f92b8 5827}
dc6f92b8 5828
06a2c219
GM
5829
5830/* Redraw a rectangle of window W. R is a rectangle in window
5831 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5832
5833static void
06a2c219
GM
5834expose_window (w, r)
5835 struct window *w;
5836 XRectangle *r;
dc6f92b8 5837{
06a2c219
GM
5838 struct glyph_row *row;
5839 int y;
5840 int yb = window_text_bottom_y (w);
5841 int cursor_cleared_p;
dc6f92b8 5842
80c32bcc
GM
5843 /* If window is not yet fully initialized, do nothing. This can
5844 happen when toolkit scroll bars are used and a window is split.
5845 Reconfiguring the scroll bar will generate an expose for a newly
5846 created window. */
5847 if (w->current_matrix == NULL)
5848 return;
5849
06a2c219
GM
5850 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5851 r->x, r->y, r->width, r->height));
dc6f92b8 5852
06a2c219
GM
5853 /* Convert to window coordinates. */
5854 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5855 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5856
06a2c219
GM
5857 /* Turn off the cursor. */
5858 if (!w->pseudo_window_p
5859 && x_phys_cursor_in_rect_p (w, r))
5860 {
5861 x_clear_cursor (w);
5862 cursor_cleared_p = 1;
5863 }
5864 else
5865 cursor_cleared_p = 0;
5866
5867 /* Find the first row intersecting the rectangle R. */
5868 row = w->current_matrix->rows;
5869 y = 0;
5870 while (row->enabled_p
5871 && y < yb
5872 && y + row->height < r->y)
5873 {
5874 y += row->height;
5875 ++row;
5876 }
5877
dc6f92b8 5878 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5879 while (row->enabled_p
5880 && y < yb
5881 && y < r->y + r->height)
5882 {
5883 expose_line (w, row, r);
5884 y += row->height;
5885 ++row;
5886 }
5887
5888 /* Display the mode line if there is one. */
5889 if (WINDOW_WANTS_MODELINE_P (w)
5890 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5891 row->enabled_p)
5892 && row->y < r->y + r->height)
5893 expose_line (w, row, r);
dc6f92b8 5894
06a2c219 5895 if (!w->pseudo_window_p)
dc6f92b8 5896 {
06a2c219
GM
5897 /* Draw border between windows. */
5898 x_draw_vertical_border (w);
5899
5900 /* Turn the cursor on again. */
5901 if (cursor_cleared_p)
5902 x_update_window_cursor (w, 1);
5903 }
5904}
dc6f92b8 5905
dc6f92b8 5906
06a2c219
GM
5907/* Determine the intersection of two rectangles R1 and R2. Return
5908 the intersection in *RESULT. Value is non-zero if RESULT is not
5909 empty. */
5910
5911static int
5912x_intersect_rectangles (r1, r2, result)
5913 XRectangle *r1, *r2, *result;
5914{
5915 XRectangle *left, *right;
5916 XRectangle *upper, *lower;
5917 int intersection_p = 0;
5918
5919 /* Rearrange so that R1 is the left-most rectangle. */
5920 if (r1->x < r2->x)
5921 left = r1, right = r2;
5922 else
5923 left = r2, right = r1;
5924
5925 /* X0 of the intersection is right.x0, if this is inside R1,
5926 otherwise there is no intersection. */
5927 if (right->x <= left->x + left->width)
5928 {
5929 result->x = right->x;
5930
5931 /* The right end of the intersection is the minimum of the
5932 the right ends of left and right. */
5933 result->width = (min (left->x + left->width, right->x + right->width)
5934 - result->x);
5935
5936 /* Same game for Y. */
5937 if (r1->y < r2->y)
5938 upper = r1, lower = r2;
5939 else
5940 upper = r2, lower = r1;
5941
5942 /* The upper end of the intersection is lower.y0, if this is inside
5943 of upper. Otherwise, there is no intersection. */
5944 if (lower->y <= upper->y + upper->height)
dc43ef94 5945 {
06a2c219
GM
5946 result->y = lower->y;
5947
5948 /* The lower end of the intersection is the minimum of the lower
5949 ends of upper and lower. */
5950 result->height = (min (lower->y + lower->height,
5951 upper->y + upper->height)
5952 - result->y);
5953 intersection_p = 1;
dc43ef94 5954 }
dc6f92b8
JB
5955 }
5956
06a2c219 5957 return intersection_p;
dc6f92b8 5958}
06a2c219
GM
5959
5960
5961
5962
dc6f92b8 5963\f
dc6f92b8 5964static void
334208b7
RS
5965frame_highlight (f)
5966 struct frame *f;
dc6f92b8 5967{
b3e1e05c
JB
5968 /* We used to only do this if Vx_no_window_manager was non-nil, but
5969 the ICCCM (section 4.1.6) says that the window's border pixmap
5970 and border pixel are window attributes which are "private to the
5971 client", so we can always change it to whatever we want. */
5972 BLOCK_INPUT;
334208b7 5973 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5974 f->output_data.x->border_pixel);
b3e1e05c 5975 UNBLOCK_INPUT;
5d46f928 5976 x_update_cursor (f, 1);
dc6f92b8
JB
5977}
5978
5979static void
334208b7
RS
5980frame_unhighlight (f)
5981 struct frame *f;
dc6f92b8 5982{
b3e1e05c
JB
5983 /* We used to only do this if Vx_no_window_manager was non-nil, but
5984 the ICCCM (section 4.1.6) says that the window's border pixmap
5985 and border pixel are window attributes which are "private to the
5986 client", so we can always change it to whatever we want. */
5987 BLOCK_INPUT;
334208b7 5988 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5989 f->output_data.x->border_tile);
b3e1e05c 5990 UNBLOCK_INPUT;
5d46f928 5991 x_update_cursor (f, 1);
dc6f92b8 5992}
dc6f92b8 5993
f676886a
JB
5994/* The focus has changed. Update the frames as necessary to reflect
5995 the new situation. Note that we can't change the selected frame
c5acd733 5996 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5997 Each event gets marked with the frame in which it occurred, so the
c5acd733 5998 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5999
6d4238f3 6000static void
0f941935
KH
6001x_new_focus_frame (dpyinfo, frame)
6002 struct x_display_info *dpyinfo;
f676886a 6003 struct frame *frame;
dc6f92b8 6004{
0f941935 6005 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 6006
0f941935 6007 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 6008 {
58769bee 6009 /* Set this before calling other routines, so that they see
f676886a 6010 the correct value of x_focus_frame. */
0f941935 6011 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
6012
6013 if (old_focus && old_focus->auto_lower)
f676886a 6014 x_lower_frame (old_focus);
dc6f92b8
JB
6015
6016#if 0
f676886a 6017 selected_frame = frame;
e0c1aef2
KH
6018 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6019 selected_frame);
f676886a
JB
6020 Fselect_window (selected_frame->selected_window);
6021 choose_minibuf_frame ();
c118dd06 6022#endif /* ! 0 */
dc6f92b8 6023
0f941935
KH
6024 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6025 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
6026 else
6027 pending_autoraise_frame = 0;
6d4238f3 6028 }
dc6f92b8 6029
0f941935 6030 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
6031}
6032
37c2c98b
RS
6033/* Handle an event saying the mouse has moved out of an Emacs frame. */
6034
6035void
0f941935
KH
6036x_mouse_leave (dpyinfo)
6037 struct x_display_info *dpyinfo;
37c2c98b 6038{
0f941935 6039 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 6040}
6d4238f3 6041
f451eb13
JB
6042/* The focus has changed, or we have redirected a frame's focus to
6043 another frame (this happens when a frame uses a surrogate
06a2c219 6044 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
6045
6046 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 6047 frame is being highlighted or un-highlighted; we only use it to find
0f941935 6048 the appropriate X display info. */
06a2c219 6049
6d4238f3 6050static void
0f941935
KH
6051XTframe_rehighlight (frame)
6052 struct frame *frame;
6d4238f3 6053{
0f941935
KH
6054 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6055}
6d4238f3 6056
0f941935
KH
6057static void
6058x_frame_rehighlight (dpyinfo)
6059 struct x_display_info *dpyinfo;
6060{
6061 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6062
6063 if (dpyinfo->x_focus_frame)
6d4238f3 6064 {
0f941935
KH
6065 dpyinfo->x_highlight_frame
6066 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6067 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6068 : dpyinfo->x_focus_frame);
6069 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 6070 {
0f941935
KH
6071 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6072 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 6073 }
dc6f92b8 6074 }
6d4238f3 6075 else
0f941935 6076 dpyinfo->x_highlight_frame = 0;
dc6f92b8 6077
0f941935 6078 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
6079 {
6080 if (old_highlight)
f676886a 6081 frame_unhighlight (old_highlight);
0f941935
KH
6082 if (dpyinfo->x_highlight_frame)
6083 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 6084 }
dc6f92b8 6085}
06a2c219
GM
6086
6087
dc6f92b8 6088\f
06a2c219 6089/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 6090
28430d3c
JB
6091/* Initialize mode_switch_bit and modifier_meaning. */
6092static void
334208b7
RS
6093x_find_modifier_meanings (dpyinfo)
6094 struct x_display_info *dpyinfo;
28430d3c 6095{
f689eb05 6096 int min_code, max_code;
28430d3c
JB
6097 KeySym *syms;
6098 int syms_per_code;
6099 XModifierKeymap *mods;
6100
334208b7
RS
6101 dpyinfo->meta_mod_mask = 0;
6102 dpyinfo->shift_lock_mask = 0;
6103 dpyinfo->alt_mod_mask = 0;
6104 dpyinfo->super_mod_mask = 0;
6105 dpyinfo->hyper_mod_mask = 0;
58769bee 6106
9658a521 6107#ifdef HAVE_X11R4
334208b7 6108 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 6109#else
4a60f8c5
RS
6110 min_code = dpyinfo->display->min_keycode;
6111 max_code = dpyinfo->display->max_keycode;
9658a521
JB
6112#endif
6113
334208b7 6114 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
6115 min_code, max_code - min_code + 1,
6116 &syms_per_code);
334208b7 6117 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 6118
58769bee 6119 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 6120 Alt keysyms are on. */
28430d3c 6121 {
06a2c219 6122 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
6123
6124 for (row = 3; row < 8; row++)
6125 for (col = 0; col < mods->max_keypermod; col++)
6126 {
0299d313
RS
6127 KeyCode code
6128 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 6129
af92970c
KH
6130 /* Zeroes are used for filler. Skip them. */
6131 if (code == 0)
6132 continue;
6133
28430d3c
JB
6134 /* Are any of this keycode's keysyms a meta key? */
6135 {
6136 int code_col;
6137
6138 for (code_col = 0; code_col < syms_per_code; code_col++)
6139 {
f689eb05 6140 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 6141
f689eb05 6142 switch (sym)
28430d3c 6143 {
f689eb05
JB
6144 case XK_Meta_L:
6145 case XK_Meta_R:
334208b7 6146 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 6147 break;
f689eb05
JB
6148
6149 case XK_Alt_L:
6150 case XK_Alt_R:
334208b7 6151 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
6152 break;
6153
6154 case XK_Hyper_L:
6155 case XK_Hyper_R:
334208b7 6156 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
6157 break;
6158
6159 case XK_Super_L:
6160 case XK_Super_R:
334208b7 6161 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 6162 break;
11edeb03
JB
6163
6164 case XK_Shift_Lock:
6165 /* Ignore this if it's not on the lock modifier. */
6166 if ((1 << row) == LockMask)
334208b7 6167 dpyinfo->shift_lock_mask = LockMask;
11edeb03 6168 break;
28430d3c
JB
6169 }
6170 }
6171 }
6172 }
6173 }
6174
f689eb05 6175 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 6176 if (! dpyinfo->meta_mod_mask)
a3c44b14 6177 {
334208b7
RS
6178 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6179 dpyinfo->alt_mod_mask = 0;
a3c44b14 6180 }
f689eb05 6181
148c4b70
RS
6182 /* If some keys are both alt and meta,
6183 make them just meta, not alt. */
334208b7 6184 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 6185 {
334208b7 6186 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 6187 }
58769bee 6188
28430d3c 6189 XFree ((char *) syms);
f689eb05 6190 XFreeModifiermap (mods);
28430d3c
JB
6191}
6192
dfeccd2d
JB
6193/* Convert between the modifier bits X uses and the modifier bits
6194 Emacs uses. */
06a2c219 6195
7c5283e4 6196static unsigned int
334208b7
RS
6197x_x_to_emacs_modifiers (dpyinfo, state)
6198 struct x_display_info *dpyinfo;
dc6f92b8
JB
6199 unsigned int state;
6200{
334208b7
RS
6201 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6202 | ((state & ControlMask) ? ctrl_modifier : 0)
6203 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6204 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6205 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6206 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
6207}
6208
dfeccd2d 6209static unsigned int
334208b7
RS
6210x_emacs_to_x_modifiers (dpyinfo, state)
6211 struct x_display_info *dpyinfo;
dfeccd2d
JB
6212 unsigned int state;
6213{
334208b7
RS
6214 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6215 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6216 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6217 | ((state & shift_modifier) ? ShiftMask : 0)
6218 | ((state & ctrl_modifier) ? ControlMask : 0)
6219 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6220}
d047c4eb
KH
6221
6222/* Convert a keysym to its name. */
6223
6224char *
6225x_get_keysym_name (keysym)
6226 KeySym keysym;
6227{
6228 char *value;
6229
6230 BLOCK_INPUT;
6231 value = XKeysymToString (keysym);
6232 UNBLOCK_INPUT;
6233
6234 return value;
6235}
06a2c219
GM
6236
6237
e4571a43
JB
6238\f
6239/* Mouse clicks and mouse movement. Rah. */
e4571a43 6240
06a2c219
GM
6241/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6242 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6243 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6244 not force the value into range. */
69388238 6245
c8dba240 6246void
69388238 6247pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6248 FRAME_PTR f;
69388238 6249 register int pix_x, pix_y;
e4571a43
JB
6250 register int *x, *y;
6251 XRectangle *bounds;
69388238 6252 int noclip;
e4571a43 6253{
06a2c219 6254 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6255 even for negative values. */
6256 if (pix_x < 0)
7556890b 6257 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6258 if (pix_y < 0)
7556890b 6259 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6260
e4571a43
JB
6261 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6262 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6263
6264 if (bounds)
6265 {
7556890b
RS
6266 bounds->width = FONT_WIDTH (f->output_data.x->font);
6267 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6268 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6269 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6270 }
6271
69388238
RS
6272 if (!noclip)
6273 {
6274 if (pix_x < 0)
6275 pix_x = 0;
3cbd2e0b
RS
6276 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6277 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6278
6279 if (pix_y < 0)
6280 pix_y = 0;
6281 else if (pix_y > f->height)
6282 pix_y = f->height;
6283 }
e4571a43
JB
6284
6285 *x = pix_x;
6286 *y = pix_y;
6287}
6288
06a2c219
GM
6289
6290/* Given HPOS/VPOS in the current matrix of W, return corresponding
6291 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6292 can't tell the positions because W's display is not up to date,
6293 return 0. */
6294
6295int
6296glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6297 struct window *w;
6298 int hpos, vpos;
6299 int *frame_x, *frame_y;
2b5c9e71 6300{
06a2c219
GM
6301 int success_p;
6302
6303 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6304 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6305
6306 if (display_completed)
6307 {
6308 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6309 struct glyph *glyph = row->glyphs[TEXT_AREA];
6310 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6311
6312 *frame_y = row->y;
6313 *frame_x = row->x;
6314 while (glyph < end)
6315 {
6316 *frame_x += glyph->pixel_width;
6317 ++glyph;
6318 }
6319
6320 success_p = 1;
6321 }
6322 else
6323 {
6324 *frame_y = *frame_x = 0;
6325 success_p = 0;
6326 }
6327
6328 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6329 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6330 return success_p;
2b5c9e71
RS
6331}
6332
06a2c219 6333
dc6f92b8
JB
6334/* Prepare a mouse-event in *RESULT for placement in the input queue.
6335
6336 If the event is a button press, then note that we have grabbed
f451eb13 6337 the mouse. */
dc6f92b8
JB
6338
6339static Lisp_Object
f451eb13 6340construct_mouse_click (result, event, f)
dc6f92b8
JB
6341 struct input_event *result;
6342 XButtonEvent *event;
f676886a 6343 struct frame *f;
dc6f92b8 6344{
f451eb13 6345 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6346 otherwise. */
f451eb13 6347 result->kind = mouse_click;
69388238 6348 result->code = event->button - Button1;
1113d9db 6349 result->timestamp = event->time;
334208b7
RS
6350 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6351 event->state)
f689eb05 6352 | (event->type == ButtonRelease
58769bee 6353 ? up_modifier
f689eb05 6354 : down_modifier));
dc6f92b8 6355
06a2c219
GM
6356 XSETINT (result->x, event->x);
6357 XSETINT (result->y, event->y);
6358 XSETFRAME (result->frame_or_window, f);
0f8aabe9 6359 result->arg = Qnil;
06a2c219 6360 return Qnil;
dc6f92b8 6361}
b849c413 6362
69388238 6363\f
90e65f07
JB
6364/* Function to report a mouse movement to the mainstream Emacs code.
6365 The input handler calls this.
6366
6367 We have received a mouse movement event, which is given in *event.
6368 If the mouse is over a different glyph than it was last time, tell
6369 the mainstream emacs code by setting mouse_moved. If not, ask for
6370 another motion event, so we can check again the next time it moves. */
b8009dd1 6371
06a2c219
GM
6372static XMotionEvent last_mouse_motion_event;
6373static Lisp_Object last_mouse_motion_frame;
6374
90e65f07 6375static void
12ba150f 6376note_mouse_movement (frame, event)
f676886a 6377 FRAME_PTR frame;
90e65f07 6378 XMotionEvent *event;
90e65f07 6379{
e5d77022 6380 last_mouse_movement_time = event->time;
06a2c219
GM
6381 last_mouse_motion_event = *event;
6382 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6383
27f338af
RS
6384 if (event->window != FRAME_X_WINDOW (frame))
6385 {
39d8bb4d 6386 frame->mouse_moved = 1;
27f338af 6387 last_mouse_scroll_bar = Qnil;
27f338af 6388 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6389 }
6390
90e65f07 6391 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6392 else if (event->x < last_mouse_glyph.x
6393 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6394 || event->y < last_mouse_glyph.y
6395 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6396 {
39d8bb4d 6397 frame->mouse_moved = 1;
ab648270 6398 last_mouse_scroll_bar = Qnil;
b8009dd1 6399 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6400 }
6401}
6402
bf1c0ba1 6403/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6404
06a2c219
GM
6405 int disable_mouse_highlight;
6406
6407
6408\f
6409/************************************************************************
6410 Mouse Face
6411 ************************************************************************/
6412
6413/* Find the glyph under window-relative coordinates X/Y in window W.
6414 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6415 strings. Return in *HPOS and *VPOS the row and column number of
6416 the glyph found. Return in *AREA the glyph area containing X.
6417 Value is a pointer to the glyph found or null if X/Y is not on
6418 text, or we can't tell because W's current matrix is not up to
6419 date. */
6420
6421static struct glyph *
6422x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6423 struct window *w;
6424 int x, y;
6425 int *hpos, *vpos, *area;
6426{
6427 struct glyph *glyph, *end;
3e71d8f2 6428 struct glyph_row *row = NULL;
06a2c219
GM
6429 int x0, i, left_area_width;
6430
6431 /* Find row containing Y. Give up if some row is not enabled. */
6432 for (i = 0; i < w->current_matrix->nrows; ++i)
6433 {
6434 row = MATRIX_ROW (w->current_matrix, i);
6435 if (!row->enabled_p)
6436 return NULL;
6437 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6438 break;
6439 }
6440
6441 *vpos = i;
6442 *hpos = 0;
6443
6444 /* Give up if Y is not in the window. */
6445 if (i == w->current_matrix->nrows)
6446 return NULL;
6447
6448 /* Get the glyph area containing X. */
6449 if (w->pseudo_window_p)
6450 {
6451 *area = TEXT_AREA;
6452 x0 = 0;
6453 }
6454 else
6455 {
6456 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6457 if (x < left_area_width)
6458 {
6459 *area = LEFT_MARGIN_AREA;
6460 x0 = 0;
6461 }
6462 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6463 {
6464 *area = TEXT_AREA;
6465 x0 = row->x + left_area_width;
6466 }
6467 else
6468 {
6469 *area = RIGHT_MARGIN_AREA;
6470 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6471 }
6472 }
6473
6474 /* Find glyph containing X. */
6475 glyph = row->glyphs[*area];
6476 end = glyph + row->used[*area];
6477 while (glyph < end)
6478 {
6479 if (x < x0 + glyph->pixel_width)
6480 {
6481 if (w->pseudo_window_p)
6482 break;
6483 else if (BUFFERP (glyph->object))
6484 break;
6485 }
6486
6487 x0 += glyph->pixel_width;
6488 ++glyph;
6489 }
6490
6491 if (glyph == end)
6492 return NULL;
6493
6494 *hpos = glyph - row->glyphs[*area];
6495 return glyph;
6496}
6497
6498
6499/* Convert frame-relative x/y to coordinates relative to window W.
6500 Takes pseudo-windows into account. */
6501
6502static void
6503frame_to_window_pixel_xy (w, x, y)
6504 struct window *w;
6505 int *x, *y;
6506{
6507 if (w->pseudo_window_p)
6508 {
6509 /* A pseudo-window is always full-width, and starts at the
6510 left edge of the frame, plus a frame border. */
6511 struct frame *f = XFRAME (w->frame);
6512 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6513 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6514 }
6515 else
6516 {
6517 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6518 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6519 }
6520}
6521
6522
6523/* Take proper action when mouse has moved to the mode or top line of
6524 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6525 mode line. X is relative to the start of the text display area of
6526 W, so the width of bitmap areas and scroll bars must be subtracted
6527 to get a position relative to the start of the mode line. */
6528
6529static void
6530note_mode_line_highlight (w, x, mode_line_p)
6531 struct window *w;
6532 int x, mode_line_p;
6533{
6534 struct frame *f = XFRAME (w->frame);
6535 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6536 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6537 struct glyph_row *row;
6538
6539 if (mode_line_p)
6540 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6541 else
045dee35 6542 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6543
6544 if (row->enabled_p)
6545 {
6546 struct glyph *glyph, *end;
6547 Lisp_Object help, map;
6548 int x0;
6549
6550 /* Find the glyph under X. */
6551 glyph = row->glyphs[TEXT_AREA];
6552 end = glyph + row->used[TEXT_AREA];
6553 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6554 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6555 while (glyph < end
6556 && x >= x0 + glyph->pixel_width)
6557 {
6558 x0 += glyph->pixel_width;
6559 ++glyph;
6560 }
6561
6562 if (glyph < end
6563 && STRINGP (glyph->object)
6564 && XSTRING (glyph->object)->intervals
6565 && glyph->charpos >= 0
6566 && glyph->charpos < XSTRING (glyph->object)->size)
6567 {
6568 /* If we're on a string with `help-echo' text property,
6569 arrange for the help to be displayed. This is done by
6570 setting the global variable help_echo to the help string. */
6571 help = Fget_text_property (make_number (glyph->charpos),
6572 Qhelp_echo, glyph->object);
b7e80413 6573 if (!NILP (help))
be010514
GM
6574 {
6575 help_echo = help;
7cea38bc 6576 XSETWINDOW (help_echo_window, w);
be010514
GM
6577 help_echo_object = glyph->object;
6578 help_echo_pos = glyph->charpos;
6579 }
06a2c219
GM
6580
6581 /* Change the mouse pointer according to what is under X/Y. */
6582 map = Fget_text_property (make_number (glyph->charpos),
6583 Qlocal_map, glyph->object);
02067692 6584 if (KEYMAPP (map))
06a2c219 6585 cursor = f->output_data.x->nontext_cursor;
be010514
GM
6586 else
6587 {
6588 map = Fget_text_property (make_number (glyph->charpos),
6589 Qkeymap, glyph->object);
02067692 6590 if (KEYMAPP (map))
be010514
GM
6591 cursor = f->output_data.x->nontext_cursor;
6592 }
06a2c219
GM
6593 }
6594 }
6595
6596 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6597}
6598
6599
6600/* Take proper action when the mouse has moved to position X, Y on
6601 frame F as regards highlighting characters that have mouse-face
6602 properties. Also de-highlighting chars where the mouse was before.
27f338af 6603 X and Y can be negative or out of range. */
b8009dd1
RS
6604
6605static void
6606note_mouse_highlight (f, x, y)
06a2c219 6607 struct frame *f;
c32cdd9a 6608 int x, y;
b8009dd1 6609{
06a2c219
GM
6610 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6611 int portion;
b8009dd1
RS
6612 Lisp_Object window;
6613 struct window *w;
6614
06a2c219
GM
6615 /* When a menu is active, don't highlight because this looks odd. */
6616#ifdef USE_X_TOOLKIT
6617 if (popup_activated ())
6618 return;
6619#endif
6620
04fff9c0
GM
6621 if (disable_mouse_highlight
6622 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6623 return;
6624
06a2c219
GM
6625 dpyinfo->mouse_face_mouse_x = x;
6626 dpyinfo->mouse_face_mouse_y = y;
6627 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6628
06a2c219 6629 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6630 return;
6631
514e4681
RS
6632 if (gc_in_progress)
6633 {
06a2c219 6634 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6635 return;
6636 }
6637
b8009dd1 6638 /* Which window is that in? */
06a2c219 6639 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6640
6641 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6642 if (! EQ (window, dpyinfo->mouse_face_window))
6643 clear_mouse_face (dpyinfo);
6644
6645 /* Not on a window -> return. */
6646 if (!WINDOWP (window))
6647 return;
6648
6649 /* Convert to window-relative pixel coordinates. */
6650 w = XWINDOW (window);
6651 frame_to_window_pixel_xy (w, &x, &y);
6652
9ea173e8 6653 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6654 buffer. */
9ea173e8 6655 if (EQ (window, f->tool_bar_window))
06a2c219 6656 {
9ea173e8 6657 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6658 return;
6659 }
6660
6661 if (portion == 1 || portion == 3)
6662 {
6663 /* Mouse is on the mode or top line. */
6664 note_mode_line_highlight (w, x, portion == 1);
6665 return;
6666 }
6667 else
6668 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6669 f->output_data.x->text_cursor);
b8009dd1 6670
0cdd0c9f
RS
6671 /* Are we in a window whose display is up to date?
6672 And verify the buffer's text has not changed. */
06a2c219
GM
6673 if (/* Within text portion of the window. */
6674 portion == 0
0cdd0c9f 6675 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6676 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6677 && (XFASTINT (w->last_overlay_modified)
6678 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6679 {
06a2c219
GM
6680 int hpos, vpos, pos, i, area;
6681 struct glyph *glyph;
b8009dd1 6682
06a2c219
GM
6683 /* Find the glyph under X/Y. */
6684 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6685
6686 /* Clear mouse face if X/Y not over text. */
6687 if (glyph == NULL
6688 || area != TEXT_AREA
6689 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6690 {
06a2c219
GM
6691 clear_mouse_face (dpyinfo);
6692 return;
6693 }
6694
6695 pos = glyph->charpos;
6696 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6697
6698 /* Check for mouse-face and help-echo. */
6699 {
6700 Lisp_Object mouse_face, overlay, position;
6701 Lisp_Object *overlay_vec;
6702 int len, noverlays;
6703 struct buffer *obuf;
6704 int obegv, ozv;
6705
6706 /* If we get an out-of-range value, return now; avoid an error. */
6707 if (pos > BUF_Z (XBUFFER (w->buffer)))
6708 return;
6709
6710 /* Make the window's buffer temporarily current for
6711 overlays_at and compute_char_face. */
6712 obuf = current_buffer;
6713 current_buffer = XBUFFER (w->buffer);
6714 obegv = BEGV;
6715 ozv = ZV;
6716 BEGV = BEG;
6717 ZV = Z;
6718
6719 /* Is this char mouse-active or does it have help-echo? */
6720 XSETINT (position, pos);
6721
6722 /* Put all the overlays we want in a vector in overlay_vec.
6723 Store the length in len. If there are more than 10, make
6724 enough space for all, and try again. */
6725 len = 10;
6726 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6727 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
06a2c219
GM
6728 if (noverlays > len)
6729 {
6730 len = noverlays;
6731 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6732 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
06a2c219 6733 }
f8349001
GM
6734
6735 /* Sort overlays into increasing priority order. */
06a2c219
GM
6736 noverlays = sort_overlays (overlay_vec, noverlays, w);
6737
6738 /* Check mouse-face highlighting. */
6739 if (! (EQ (window, dpyinfo->mouse_face_window)
6740 && vpos >= dpyinfo->mouse_face_beg_row
6741 && vpos <= dpyinfo->mouse_face_end_row
6742 && (vpos > dpyinfo->mouse_face_beg_row
6743 || hpos >= dpyinfo->mouse_face_beg_col)
6744 && (vpos < dpyinfo->mouse_face_end_row
6745 || hpos < dpyinfo->mouse_face_end_col
6746 || dpyinfo->mouse_face_past_end)))
6747 {
6748 /* Clear the display of the old active region, if any. */
6749 clear_mouse_face (dpyinfo);
6750
6751 /* Find the highest priority overlay that has a mouse-face prop. */
6752 overlay = Qnil;
f8349001 6753 for (i = noverlays - 1; i >= 0; --i)
06a2c219
GM
6754 {
6755 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6756 if (!NILP (mouse_face))
6757 {
6758 overlay = overlay_vec[i];
6759 break;
6760 }
6761 }
6762
6763 /* If no overlay applies, get a text property. */
6764 if (NILP (overlay))
6765 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6766
6767 /* Handle the overlay case. */
6768 if (! NILP (overlay))
6769 {
6770 /* Find the range of text around this char that
6771 should be active. */
6772 Lisp_Object before, after;
6773 int ignore;
6774
6775 before = Foverlay_start (overlay);
6776 after = Foverlay_end (overlay);
6777 /* Record this as the current active region. */
6778 fast_find_position (w, XFASTINT (before),
6779 &dpyinfo->mouse_face_beg_col,
6780 &dpyinfo->mouse_face_beg_row,
6781 &dpyinfo->mouse_face_beg_x,
6782 &dpyinfo->mouse_face_beg_y);
6783 dpyinfo->mouse_face_past_end
6784 = !fast_find_position (w, XFASTINT (after),
6785 &dpyinfo->mouse_face_end_col,
6786 &dpyinfo->mouse_face_end_row,
6787 &dpyinfo->mouse_face_end_x,
6788 &dpyinfo->mouse_face_end_y);
6789 dpyinfo->mouse_face_window = window;
6790 dpyinfo->mouse_face_face_id
6791 = face_at_buffer_position (w, pos, 0, 0,
6792 &ignore, pos + 1, 1);
6793
6794 /* Display it as active. */
6795 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6796 }
6797 /* Handle the text property case. */
6798 else if (! NILP (mouse_face))
6799 {
6800 /* Find the range of text around this char that
6801 should be active. */
6802 Lisp_Object before, after, beginning, end;
6803 int ignore;
6804
6805 beginning = Fmarker_position (w->start);
6806 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6807 - XFASTINT (w->window_end_pos)));
6808 before
6809 = Fprevious_single_property_change (make_number (pos + 1),
6810 Qmouse_face,
6811 w->buffer, beginning);
6812 after
6813 = Fnext_single_property_change (position, Qmouse_face,
6814 w->buffer, end);
6815 /* Record this as the current active region. */
6816 fast_find_position (w, XFASTINT (before),
6817 &dpyinfo->mouse_face_beg_col,
6818 &dpyinfo->mouse_face_beg_row,
6819 &dpyinfo->mouse_face_beg_x,
6820 &dpyinfo->mouse_face_beg_y);
6821 dpyinfo->mouse_face_past_end
6822 = !fast_find_position (w, XFASTINT (after),
6823 &dpyinfo->mouse_face_end_col,
6824 &dpyinfo->mouse_face_end_row,
6825 &dpyinfo->mouse_face_end_x,
6826 &dpyinfo->mouse_face_end_y);
6827 dpyinfo->mouse_face_window = window;
6828 dpyinfo->mouse_face_face_id
6829 = face_at_buffer_position (w, pos, 0, 0,
6830 &ignore, pos + 1, 1);
6831
6832 /* Display it as active. */
6833 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6834 }
6835 }
6836
6837 /* Look for a `help-echo' property. */
6838 {
743934db 6839 Lisp_Object help, overlay;
06a2c219
GM
6840
6841 /* Check overlays first. */
f9b5db02 6842 help = overlay = Qnil;
f8349001 6843 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
743934db
GM
6844 {
6845 overlay = overlay_vec[i];
6846 help = Foverlay_get (overlay, Qhelp_echo);
6847 }
be010514
GM
6848
6849 if (!NILP (help))
6850 {
6851 help_echo = help;
7cea38bc 6852 help_echo_window = window;
743934db 6853 help_echo_object = overlay;
be010514
GM
6854 help_echo_pos = pos;
6855 }
6856 else
6857 {
6858 /* Try text properties. */
6859 if ((STRINGP (glyph->object)
06a2c219
GM
6860 && glyph->charpos >= 0
6861 && glyph->charpos < XSTRING (glyph->object)->size)
6862 || (BUFFERP (glyph->object)
6863 && glyph->charpos >= BEGV
be010514
GM
6864 && glyph->charpos < ZV))
6865 help = Fget_text_property (make_number (glyph->charpos),
6866 Qhelp_echo, glyph->object);
06a2c219 6867
be010514
GM
6868 if (!NILP (help))
6869 {
6870 help_echo = help;
7cea38bc 6871 help_echo_window = window;
be010514
GM
6872 help_echo_object = glyph->object;
6873 help_echo_pos = glyph->charpos;
6874 }
6875 }
06a2c219
GM
6876 }
6877
6878 BEGV = obegv;
6879 ZV = ozv;
6880 current_buffer = obuf;
6881 }
6882 }
6883}
6884
6885static void
6886redo_mouse_highlight ()
6887{
6888 if (!NILP (last_mouse_motion_frame)
6889 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6890 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6891 last_mouse_motion_event.x,
6892 last_mouse_motion_event.y);
6893}
6894
6895
6896\f
6897/***********************************************************************
9ea173e8 6898 Tool-bars
06a2c219
GM
6899 ***********************************************************************/
6900
9ea173e8
GM
6901static int x_tool_bar_item P_ ((struct frame *, int, int,
6902 struct glyph **, int *, int *, int *));
06a2c219 6903
9ea173e8 6904/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6905 or -1. */
6906
9ea173e8 6907static int last_tool_bar_item;
06a2c219
GM
6908
6909
9ea173e8
GM
6910/* Get information about the tool-bar item at position X/Y on frame F.
6911 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6912 the current matrix of the tool-bar window of F, or NULL if not
6913 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6914 item in F->current_tool_bar_items. Value is
06a2c219 6915
9ea173e8 6916 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6917 0 if X/Y is on the same item that was highlighted before.
6918 1 otherwise. */
6919
6920static int
9ea173e8 6921x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6922 struct frame *f;
6923 int x, y;
6924 struct glyph **glyph;
6925 int *hpos, *vpos, *prop_idx;
6926{
6927 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6928 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6929 int area;
6930
6931 /* Find the glyph under X/Y. */
6932 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6933 if (*glyph == NULL)
6934 return -1;
6935
9ea173e8
GM
6936 /* Get the start of this tool-bar item's properties in
6937 f->current_tool_bar_items. */
6938 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6939 return -1;
6940
6941 /* Is mouse on the highlighted item? */
9ea173e8 6942 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6943 && *vpos >= dpyinfo->mouse_face_beg_row
6944 && *vpos <= dpyinfo->mouse_face_end_row
6945 && (*vpos > dpyinfo->mouse_face_beg_row
6946 || *hpos >= dpyinfo->mouse_face_beg_col)
6947 && (*vpos < dpyinfo->mouse_face_end_row
6948 || *hpos < dpyinfo->mouse_face_end_col
6949 || dpyinfo->mouse_face_past_end))
6950 return 0;
6951
6952 return 1;
6953}
6954
6955
9ea173e8 6956/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6957 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6958 or ButtonRelase. */
6959
6960static void
9ea173e8 6961x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6962 struct frame *f;
6963 XButtonEvent *button_event;
6964{
6965 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6966 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6967 int hpos, vpos, prop_idx;
6968 struct glyph *glyph;
6969 Lisp_Object enabled_p;
6970 int x = button_event->x;
6971 int y = button_event->y;
6972
9ea173e8 6973 /* If not on the highlighted tool-bar item, return. */
06a2c219 6974 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6975 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6976 return;
6977
6978 /* If item is disabled, do nothing. */
9ea173e8
GM
6979 enabled_p = (XVECTOR (f->current_tool_bar_items)
6980 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6981 if (NILP (enabled_p))
6982 return;
6983
6984 if (button_event->type == ButtonPress)
6985 {
6986 /* Show item in pressed state. */
6987 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6988 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6989 last_tool_bar_item = prop_idx;
06a2c219
GM
6990 }
6991 else
6992 {
6993 Lisp_Object key, frame;
6994 struct input_event event;
6995
6996 /* Show item in released state. */
6997 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6998 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6999
9ea173e8
GM
7000 key = (XVECTOR (f->current_tool_bar_items)
7001 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
7002
7003 XSETFRAME (frame, f);
9ea173e8 7004 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7005 event.frame_or_window = frame;
7006 event.arg = frame;
06a2c219
GM
7007 kbd_buffer_store_event (&event);
7008
9ea173e8 7009 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7010 event.frame_or_window = frame;
7011 event.arg = key;
06a2c219
GM
7012 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7013 button_event->state);
7014 kbd_buffer_store_event (&event);
9ea173e8 7015 last_tool_bar_item = -1;
06a2c219
GM
7016 }
7017}
7018
7019
9ea173e8
GM
7020/* Possibly highlight a tool-bar item on frame F when mouse moves to
7021 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
7022 note_mouse_highlight. */
7023
7024static void
9ea173e8 7025note_tool_bar_highlight (f, x, y)
06a2c219
GM
7026 struct frame *f;
7027 int x, y;
7028{
9ea173e8 7029 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
7030 struct window *w = XWINDOW (window);
7031 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7032 int hpos, vpos;
7033 struct glyph *glyph;
7034 struct glyph_row *row;
5c187dee 7035 int i;
06a2c219
GM
7036 Lisp_Object enabled_p;
7037 int prop_idx;
7038 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 7039 int mouse_down_p, rc;
06a2c219
GM
7040
7041 /* Function note_mouse_highlight is called with negative x(y
7042 values when mouse moves outside of the frame. */
7043 if (x <= 0 || y <= 0)
7044 {
7045 clear_mouse_face (dpyinfo);
7046 return;
7047 }
7048
9ea173e8 7049 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
7050 if (rc < 0)
7051 {
9ea173e8 7052 /* Not on tool-bar item. */
06a2c219
GM
7053 clear_mouse_face (dpyinfo);
7054 return;
7055 }
7056 else if (rc == 0)
9ea173e8 7057 /* On same tool-bar item as before. */
06a2c219 7058 goto set_help_echo;
b8009dd1 7059
06a2c219
GM
7060 clear_mouse_face (dpyinfo);
7061
9ea173e8 7062 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
7063 mouse_down_p = (dpyinfo->grabbed
7064 && f == last_mouse_frame
7065 && FRAME_LIVE_P (f));
7066 if (mouse_down_p
9ea173e8 7067 && last_tool_bar_item != prop_idx)
06a2c219
GM
7068 return;
7069
7070 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7071 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7072
9ea173e8
GM
7073 /* If tool-bar item is not enabled, don't highlight it. */
7074 enabled_p = (XVECTOR (f->current_tool_bar_items)
7075 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
7076 if (!NILP (enabled_p))
7077 {
7078 /* Compute the x-position of the glyph. In front and past the
7079 image is a space. We include this is the highlighted area. */
7080 row = MATRIX_ROW (w->current_matrix, vpos);
7081 for (i = x = 0; i < hpos; ++i)
7082 x += row->glyphs[TEXT_AREA][i].pixel_width;
7083
7084 /* Record this as the current active region. */
7085 dpyinfo->mouse_face_beg_col = hpos;
7086 dpyinfo->mouse_face_beg_row = vpos;
7087 dpyinfo->mouse_face_beg_x = x;
7088 dpyinfo->mouse_face_beg_y = row->y;
7089 dpyinfo->mouse_face_past_end = 0;
7090
7091 dpyinfo->mouse_face_end_col = hpos + 1;
7092 dpyinfo->mouse_face_end_row = vpos;
7093 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7094 dpyinfo->mouse_face_end_y = row->y;
7095 dpyinfo->mouse_face_window = window;
9ea173e8 7096 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
7097
7098 /* Display it as active. */
7099 show_mouse_face (dpyinfo, draw);
7100 dpyinfo->mouse_face_image_state = draw;
b8009dd1 7101 }
06a2c219
GM
7102
7103 set_help_echo:
7104
9ea173e8 7105 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 7106 XTread_socket does the rest. */
7cea38bc 7107 help_echo_object = help_echo_window = Qnil;
be010514 7108 help_echo_pos = -1;
9ea173e8
GM
7109 help_echo = (XVECTOR (f->current_tool_bar_items)
7110 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
b7e80413 7111 if (NILP (help_echo))
9ea173e8
GM
7112 help_echo = (XVECTOR (f->current_tool_bar_items)
7113 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 7114}
4d73d038 7115
06a2c219
GM
7116
7117\f
7118/* Find the glyph matrix position of buffer position POS in window W.
7119 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7120 current glyphs must be up to date. If POS is above window start
7121 return (0, 0, 0, 0). If POS is after end of W, return end of
7122 last line in W. */
b8009dd1
RS
7123
7124static int
06a2c219
GM
7125fast_find_position (w, pos, hpos, vpos, x, y)
7126 struct window *w;
b8009dd1 7127 int pos;
06a2c219 7128 int *hpos, *vpos, *x, *y;
b8009dd1 7129{
b8009dd1 7130 int i;
bf1c0ba1 7131 int lastcol;
06a2c219
GM
7132 int maybe_next_line_p = 0;
7133 int line_start_position;
7134 int yb = window_text_bottom_y (w);
7135 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7136 struct glyph_row *best_row = row;
7137 int row_vpos = 0, best_row_vpos = 0;
7138 int current_x;
7139
7140 while (row->y < yb)
b8009dd1 7141 {
06a2c219
GM
7142 if (row->used[TEXT_AREA])
7143 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7144 else
7145 line_start_position = 0;
7146
7147 if (line_start_position > pos)
b8009dd1 7148 break;
77b68646
RS
7149 /* If the position sought is the end of the buffer,
7150 don't include the blank lines at the bottom of the window. */
06a2c219
GM
7151 else if (line_start_position == pos
7152 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 7153 {
06a2c219 7154 maybe_next_line_p = 1;
77b68646
RS
7155 break;
7156 }
06a2c219
GM
7157 else if (line_start_position > 0)
7158 {
7159 best_row = row;
7160 best_row_vpos = row_vpos;
7161 }
4b0bb6f3
GM
7162
7163 if (row->y + row->height >= yb)
7164 break;
06a2c219
GM
7165
7166 ++row;
7167 ++row_vpos;
b8009dd1 7168 }
06a2c219
GM
7169
7170 /* Find the right column within BEST_ROW. */
7171 lastcol = 0;
7172 current_x = best_row->x;
7173 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 7174 {
06a2c219
GM
7175 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7176 int charpos;
7177
7178 charpos = glyph->charpos;
7179 if (charpos == pos)
bf1c0ba1 7180 {
06a2c219
GM
7181 *hpos = i;
7182 *vpos = best_row_vpos;
7183 *x = current_x;
7184 *y = best_row->y;
bf1c0ba1
RS
7185 return 1;
7186 }
06a2c219 7187 else if (charpos > pos)
4d73d038 7188 break;
06a2c219
GM
7189 else if (charpos > 0)
7190 lastcol = i;
7191
7192 current_x += glyph->pixel_width;
bf1c0ba1 7193 }
b8009dd1 7194
77b68646
RS
7195 /* If we're looking for the end of the buffer,
7196 and we didn't find it in the line we scanned,
7197 use the start of the following line. */
06a2c219 7198 if (maybe_next_line_p)
77b68646 7199 {
06a2c219
GM
7200 ++best_row;
7201 ++best_row_vpos;
7202 lastcol = 0;
7203 current_x = best_row->x;
77b68646
RS
7204 }
7205
06a2c219
GM
7206 *vpos = best_row_vpos;
7207 *hpos = lastcol + 1;
7208 *x = current_x;
7209 *y = best_row->y;
b8009dd1
RS
7210 return 0;
7211}
7212
06a2c219 7213
b8009dd1
RS
7214/* Display the active region described by mouse_face_*
7215 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7216
7217static void
06a2c219 7218show_mouse_face (dpyinfo, draw)
7a13e894 7219 struct x_display_info *dpyinfo;
06a2c219 7220 enum draw_glyphs_face draw;
b8009dd1 7221{
7a13e894 7222 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 7223 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 7224 int i;
06a2c219
GM
7225 int cursor_off_p = 0;
7226 struct cursor_pos saved_cursor;
7227
7228 saved_cursor = output_cursor;
7229
7230 /* If window is in the process of being destroyed, don't bother
7231 to do anything. */
7232 if (w->current_matrix == NULL)
7233 goto set_x_cursor;
7234
7235 /* Recognize when we are called to operate on rows that don't exist
7236 anymore. This can happen when a window is split. */
7237 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7238 goto set_x_cursor;
7239
7240 set_output_cursor (&w->phys_cursor);
7241
7242 /* Note that mouse_face_beg_row etc. are window relative. */
7243 for (i = dpyinfo->mouse_face_beg_row;
7244 i <= dpyinfo->mouse_face_end_row;
7245 i++)
7246 {
7247 int start_hpos, end_hpos, start_x;
7248 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7249
7250 /* Don't do anything if row doesn't have valid contents. */
7251 if (!row->enabled_p)
7252 continue;
7253
7254 /* For all but the first row, the highlight starts at column 0. */
7255 if (i == dpyinfo->mouse_face_beg_row)
7256 {
7257 start_hpos = dpyinfo->mouse_face_beg_col;
7258 start_x = dpyinfo->mouse_face_beg_x;
7259 }
7260 else
7261 {
7262 start_hpos = 0;
7263 start_x = 0;
7264 }
7265
7266 if (i == dpyinfo->mouse_face_end_row)
7267 end_hpos = dpyinfo->mouse_face_end_col;
7268 else
7269 end_hpos = row->used[TEXT_AREA];
7270
7271 /* If the cursor's in the text we are about to rewrite, turn the
7272 cursor off. */
7273 if (!w->pseudo_window_p
7274 && i == output_cursor.vpos
7275 && output_cursor.hpos >= start_hpos - 1
7276 && output_cursor.hpos <= end_hpos)
514e4681 7277 {
06a2c219
GM
7278 x_update_window_cursor (w, 0);
7279 cursor_off_p = 1;
514e4681 7280 }
b8009dd1 7281
06a2c219 7282 if (end_hpos > start_hpos)
64f26cf5
GM
7283 {
7284 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7285 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7286 start_hpos, end_hpos, draw, NULL, NULL, 0);
7287 }
b8009dd1
RS
7288 }
7289
514e4681 7290 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7291 if (cursor_off_p)
7292 x_display_cursor (w, 1,
7293 output_cursor.hpos, output_cursor.vpos,
7294 output_cursor.x, output_cursor.y);
2729a2b5 7295
06a2c219 7296 output_cursor = saved_cursor;
fb3b7de5 7297
06a2c219
GM
7298 set_x_cursor:
7299
7300 /* Change the mouse cursor. */
7301 if (draw == DRAW_NORMAL_TEXT)
7302 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7303 f->output_data.x->text_cursor);
7304 else if (draw == DRAW_MOUSE_FACE)
334208b7 7305 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7306 f->output_data.x->cross_cursor);
27ead1d5 7307 else
334208b7 7308 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7309 f->output_data.x->nontext_cursor);
b8009dd1
RS
7310}
7311
7312/* Clear out the mouse-highlighted active region.
06a2c219 7313 Redraw it un-highlighted first. */
b8009dd1 7314
06a2c219 7315void
7a13e894
RS
7316clear_mouse_face (dpyinfo)
7317 struct x_display_info *dpyinfo;
b8009dd1 7318{
06a2c219
GM
7319 if (tip_frame)
7320 return;
7321
7a13e894 7322 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7323 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7324
7a13e894
RS
7325 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7326 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7327 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7328}
e687d06e 7329
71b8321e
GM
7330
7331/* Clear any mouse-face on window W. This function is part of the
7332 redisplay interface, and is called from try_window_id and similar
7333 functions to ensure the mouse-highlight is off. */
7334
7335static void
7336x_clear_mouse_face (w)
7337 struct window *w;
7338{
7339 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7340 Lisp_Object window;
7341
2e636f9d 7342 BLOCK_INPUT;
71b8321e
GM
7343 XSETWINDOW (window, w);
7344 if (EQ (window, dpyinfo->mouse_face_window))
7345 clear_mouse_face (dpyinfo);
2e636f9d 7346 UNBLOCK_INPUT;
71b8321e
GM
7347}
7348
7349
e687d06e
RS
7350/* Just discard the mouse face information for frame F, if any.
7351 This is used when the size of F is changed. */
7352
dfcf069d 7353void
e687d06e
RS
7354cancel_mouse_face (f)
7355 FRAME_PTR f;
7356{
7357 Lisp_Object window;
7358 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7359
7360 window = dpyinfo->mouse_face_window;
7361 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7362 {
7363 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7364 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7365 dpyinfo->mouse_face_window = Qnil;
7366 }
7367}
b8009dd1 7368\f
ab648270
JB
7369static struct scroll_bar *x_window_to_scroll_bar ();
7370static void x_scroll_bar_report_motion ();
12ba150f 7371
90e65f07 7372/* Return the current position of the mouse.
2d7fc7e8 7373 *fp should be a frame which indicates which display to ask about.
90e65f07 7374
2d7fc7e8 7375 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7376 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7377 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7378 position on the scroll bar.
12ba150f 7379
2d7fc7e8 7380 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7381 mouse is on, *bar_window to nil, and *x and *y to the character cell
7382 the mouse is over.
7383
06a2c219 7384 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7385 was at this position.
7386
a135645a
RS
7387 Don't store anything if we don't have a valid set of values to report.
7388
90e65f07 7389 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7390 movement. */
90e65f07
JB
7391
7392static void
1cf412ec 7393XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7394 FRAME_PTR *fp;
1cf412ec 7395 int insist;
12ba150f 7396 Lisp_Object *bar_window;
ab648270 7397 enum scroll_bar_part *part;
90e65f07 7398 Lisp_Object *x, *y;
e5d77022 7399 unsigned long *time;
90e65f07 7400{
a135645a
RS
7401 FRAME_PTR f1;
7402
90e65f07
JB
7403 BLOCK_INPUT;
7404
8bcee03e 7405 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7406 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7407 else
7408 {
12ba150f
JB
7409 Window root;
7410 int root_x, root_y;
90e65f07 7411
12ba150f
JB
7412 Window dummy_window;
7413 int dummy;
7414
39d8bb4d
KH
7415 Lisp_Object frame, tail;
7416
7417 /* Clear the mouse-moved flag for every frame on this display. */
7418 FOR_EACH_FRAME (tail, frame)
7419 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7420 XFRAME (frame)->mouse_moved = 0;
7421
ab648270 7422 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7423
7424 /* Figure out which root window we're on. */
334208b7
RS
7425 XQueryPointer (FRAME_X_DISPLAY (*fp),
7426 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7427
7428 /* The root window which contains the pointer. */
7429 &root,
7430
7431 /* Trash which we can't trust if the pointer is on
7432 a different screen. */
7433 &dummy_window,
7434
7435 /* The position on that root window. */
58769bee 7436 &root_x, &root_y,
12ba150f
JB
7437
7438 /* More trash we can't trust. */
7439 &dummy, &dummy,
7440
7441 /* Modifier keys and pointer buttons, about which
7442 we don't care. */
7443 (unsigned int *) &dummy);
7444
7445 /* Now we have a position on the root; find the innermost window
7446 containing the pointer. */
7447 {
7448 Window win, child;
7449 int win_x, win_y;
06a2c219 7450 int parent_x = 0, parent_y = 0;
e99db5a1 7451 int count;
12ba150f
JB
7452
7453 win = root;
69388238 7454
2d7fc7e8
RS
7455 /* XTranslateCoordinates can get errors if the window
7456 structure is changing at the same time this function
7457 is running. So at least we must not crash from them. */
7458
e99db5a1 7459 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7460
334208b7 7461 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7462 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7463 {
69388238
RS
7464 /* If mouse was grabbed on a frame, give coords for that frame
7465 even if the mouse is now outside it. */
334208b7 7466 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7467
12ba150f 7468 /* From-window, to-window. */
69388238 7469 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7470
7471 /* From-position, to-position. */
7472 root_x, root_y, &win_x, &win_y,
7473
7474 /* Child of win. */
7475 &child);
69388238
RS
7476 f1 = last_mouse_frame;
7477 }
7478 else
7479 {
7480 while (1)
7481 {
334208b7 7482 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7483
69388238
RS
7484 /* From-window, to-window. */
7485 root, win,
12ba150f 7486
69388238
RS
7487 /* From-position, to-position. */
7488 root_x, root_y, &win_x, &win_y,
7489
7490 /* Child of win. */
7491 &child);
7492
9af3143a 7493 if (child == None || child == win)
69388238
RS
7494 break;
7495
7496 win = child;
7497 parent_x = win_x;
7498 parent_y = win_y;
7499 }
12ba150f 7500
69388238
RS
7501 /* Now we know that:
7502 win is the innermost window containing the pointer
7503 (XTC says it has no child containing the pointer),
7504 win_x and win_y are the pointer's position in it
7505 (XTC did this the last time through), and
7506 parent_x and parent_y are the pointer's position in win's parent.
7507 (They are what win_x and win_y were when win was child.
7508 If win is the root window, it has no parent, and
7509 parent_{x,y} are invalid, but that's okay, because we'll
7510 never use them in that case.) */
7511
7512 /* Is win one of our frames? */
19126e11 7513 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7514 }
58769bee 7515
2d7fc7e8
RS
7516 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7517 f1 = 0;
7518
e99db5a1 7519 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7520
ab648270 7521 /* If not, is it one of our scroll bars? */
a135645a 7522 if (! f1)
12ba150f 7523 {
ab648270 7524 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7525
7526 if (bar)
7527 {
a135645a 7528 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7529 win_x = parent_x;
7530 win_y = parent_y;
7531 }
7532 }
90e65f07 7533
8bcee03e 7534 if (f1 == 0 && insist > 0)
b86bd3dd 7535 f1 = SELECTED_FRAME ();
1cf412ec 7536
a135645a 7537 if (f1)
12ba150f 7538 {
06a2c219
GM
7539 /* Ok, we found a frame. Store all the values.
7540 last_mouse_glyph is a rectangle used to reduce the
7541 generation of mouse events. To not miss any motion
7542 events, we must divide the frame into rectangles of the
7543 size of the smallest character that could be displayed
7544 on it, i.e. into the same rectangles that matrices on
7545 the frame are divided into. */
7546
7547#if OLD_REDISPLAY_CODE
2b5c9e71 7548 int ignore1, ignore2;
2b5c9e71 7549 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7550 &last_mouse_glyph,
1cf412ec
RS
7551 FRAME_X_DISPLAY_INFO (f1)->grabbed
7552 || insist);
06a2c219
GM
7553#else
7554 {
7555 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7556 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7557 int x = win_x;
7558 int y = win_y;
7559
7560 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7561 round down even for negative values. */
7562 if (x < 0)
7563 x -= width - 1;
7564 if (y < 0)
7565 y -= height - 1;
7566
7567 last_mouse_glyph.width = width;
7568 last_mouse_glyph.height = height;
7569 last_mouse_glyph.x = (x + width - 1) / width * width;
7570 last_mouse_glyph.y = (y + height - 1) / height * height;
7571 }
7572#endif
12ba150f
JB
7573
7574 *bar_window = Qnil;
7575 *part = 0;
334208b7 7576 *fp = f1;
e0c1aef2
KH
7577 XSETINT (*x, win_x);
7578 XSETINT (*y, win_y);
12ba150f
JB
7579 *time = last_mouse_movement_time;
7580 }
7581 }
7582 }
90e65f07
JB
7583
7584 UNBLOCK_INPUT;
7585}
f451eb13 7586
06a2c219 7587
06a2c219 7588#ifdef USE_X_TOOLKIT
bffcfca9
GM
7589
7590/* Atimer callback function for TIMER. Called every 0.1s to process
7591 Xt timeouts, if needed. We must avoid calling XtAppPending as
7592 much as possible because that function does an implicit XFlush
7593 that slows us down. */
7594
7595static void
7596x_process_timeouts (timer)
7597 struct atimer *timer;
7598{
7599 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7600 {
7601 BLOCK_INPUT;
7602 while (XtAppPending (Xt_app_con) & XtIMTimer)
7603 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7604 UNBLOCK_INPUT;
7605 }
06a2c219
GM
7606}
7607
bffcfca9 7608#endif /* USE_X_TOOLKIT */
06a2c219
GM
7609
7610\f
7611/* Scroll bar support. */
7612
7613/* Given an X window ID, find the struct scroll_bar which manages it.
7614 This can be called in GC, so we have to make sure to strip off mark
7615 bits. */
bffcfca9 7616
06a2c219
GM
7617static struct scroll_bar *
7618x_window_to_scroll_bar (window_id)
7619 Window window_id;
7620{
7621 Lisp_Object tail;
7622
7623 for (tail = Vframe_list;
7624 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7625 tail = XCDR (tail))
06a2c219
GM
7626 {
7627 Lisp_Object frame, bar, condemned;
7628
8e713be6 7629 frame = XCAR (tail);
06a2c219
GM
7630 /* All elements of Vframe_list should be frames. */
7631 if (! GC_FRAMEP (frame))
7632 abort ();
7633
7634 /* Scan this frame's scroll bar list for a scroll bar with the
7635 right window ID. */
7636 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7637 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7638 /* This trick allows us to search both the ordinary and
7639 condemned scroll bar lists with one loop. */
7640 ! GC_NILP (bar) || (bar = condemned,
7641 condemned = Qnil,
7642 ! GC_NILP (bar));
7643 bar = XSCROLL_BAR (bar)->next)
7644 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7645 return XSCROLL_BAR (bar);
7646 }
7647
7648 return 0;
7649}
7650
7651
7652\f
7653/************************************************************************
7654 Toolkit scroll bars
7655 ************************************************************************/
7656
7657#if USE_TOOLKIT_SCROLL_BARS
7658
7659static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7660static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7661static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7662 struct scroll_bar *));
7663static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7664 int, int, int));
7665
7666
7667/* Id of action hook installed for scroll bars. */
7668
7669static XtActionHookId action_hook_id;
7670
7671/* Lisp window being scrolled. Set when starting to interact with
7672 a toolkit scroll bar, reset to nil when ending the interaction. */
7673
7674static Lisp_Object window_being_scrolled;
7675
7676/* Last scroll bar part sent in xm_scroll_callback. */
7677
7678static int last_scroll_bar_part;
7679
ec18280f
SM
7680/* Whether this is an Xaw with arrow-scrollbars. This should imply
7681 that movements of 1/20 of the screen size are mapped to up/down. */
7682
7683static Boolean xaw3d_arrow_scroll;
7684
7685/* Whether the drag scrolling maintains the mouse at the top of the
7686 thumb. If not, resizing the thumb needs to be done more carefully
7687 to avoid jerkyness. */
7688
7689static Boolean xaw3d_pick_top;
7690
06a2c219
GM
7691
7692/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7693 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7694 the user ends an interaction with the scroll bar, and generates
7695 a `end-scroll' scroll_bar_click' event if so. */
7696
7697static void
7698xt_action_hook (widget, client_data, action_name, event, params,
7699 num_params)
7700 Widget widget;
7701 XtPointer client_data;
7702 String action_name;
7703 XEvent *event;
7704 String *params;
7705 Cardinal *num_params;
7706{
7707 int scroll_bar_p;
7708 char *end_action;
7709
7710#ifdef USE_MOTIF
7711 scroll_bar_p = XmIsScrollBar (widget);
7712 end_action = "Release";
ec18280f 7713#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7714 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7715 end_action = "EndScroll";
ec18280f 7716#endif /* USE_MOTIF */
06a2c219 7717
06a2c219
GM
7718 if (scroll_bar_p
7719 && strcmp (action_name, end_action) == 0
7720 && WINDOWP (window_being_scrolled))
7721 {
7722 struct window *w;
7723
7724 x_send_scroll_bar_event (window_being_scrolled,
7725 scroll_bar_end_scroll, 0, 0);
7726 w = XWINDOW (window_being_scrolled);
7727 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7728 window_being_scrolled = Qnil;
7729 last_scroll_bar_part = -1;
bffcfca9
GM
7730
7731 /* Xt timeouts no longer needed. */
7732 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7733 }
7734}
7735
7736
7737/* Send a client message with message type Xatom_Scrollbar for a
7738 scroll action to the frame of WINDOW. PART is a value identifying
7739 the part of the scroll bar that was clicked on. PORTION is the
7740 amount to scroll of a whole of WHOLE. */
7741
7742static void
7743x_send_scroll_bar_event (window, part, portion, whole)
7744 Lisp_Object window;
7745 int part, portion, whole;
7746{
7747 XEvent event;
7748 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7749 struct frame *f = XFRAME (XWINDOW (window)->frame);
7750
7751 /* Construct a ClientMessage event to send to the frame. */
7752 ev->type = ClientMessage;
7753 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7754 ev->display = FRAME_X_DISPLAY (f);
7755 ev->window = FRAME_X_WINDOW (f);
7756 ev->format = 32;
52e386c2 7757 ev->data.l[0] = (long) XFASTINT (window);
06a2c219
GM
7758 ev->data.l[1] = (long) part;
7759 ev->data.l[2] = (long) 0;
7760 ev->data.l[3] = (long) portion;
7761 ev->data.l[4] = (long) whole;
7762
bffcfca9
GM
7763 /* Make Xt timeouts work while the scroll bar is active. */
7764 toolkit_scroll_bar_interaction = 1;
7765
06a2c219
GM
7766 /* Setting the event mask to zero means that the message will
7767 be sent to the client that created the window, and if that
7768 window no longer exists, no event will be sent. */
7769 BLOCK_INPUT;
7770 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7771 UNBLOCK_INPUT;
7772}
7773
7774
7775/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7776 in *IEVENT. */
7777
7778static void
7779x_scroll_bar_to_input_event (event, ievent)
7780 XEvent *event;
7781 struct input_event *ievent;
7782{
7783 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7784 Lisp_Object window;
7785 struct frame *f;
7786
7787 XSETFASTINT (window, ev->data.l[0]);
7788 f = XFRAME (XWINDOW (window)->frame);
06a2c219
GM
7789
7790 ievent->kind = scroll_bar_click;
7791 ievent->frame_or_window = window;
0f8aabe9 7792 ievent->arg = Qnil;
06a2c219
GM
7793 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7794 ievent->part = ev->data.l[1];
7795 ievent->code = ev->data.l[2];
7796 ievent->x = make_number ((int) ev->data.l[3]);
7797 ievent->y = make_number ((int) ev->data.l[4]);
7798 ievent->modifiers = 0;
7799}
7800
7801
7802#ifdef USE_MOTIF
7803
7804/* Minimum and maximum values used for Motif scroll bars. */
7805
7806#define XM_SB_MIN 1
7807#define XM_SB_MAX 10000000
7808#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7809
7810
7811/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7812 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7813 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7814
7815static void
7816xm_scroll_callback (widget, client_data, call_data)
7817 Widget widget;
7818 XtPointer client_data, call_data;
7819{
7820 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7821 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7822 double percent;
7823 int part = -1, whole = 0, portion = 0;
7824
7825 switch (cs->reason)
7826 {
7827 case XmCR_DECREMENT:
7828 bar->dragging = Qnil;
7829 part = scroll_bar_up_arrow;
7830 break;
7831
7832 case XmCR_INCREMENT:
7833 bar->dragging = Qnil;
7834 part = scroll_bar_down_arrow;
7835 break;
7836
7837 case XmCR_PAGE_DECREMENT:
7838 bar->dragging = Qnil;
7839 part = scroll_bar_above_handle;
7840 break;
7841
7842 case XmCR_PAGE_INCREMENT:
7843 bar->dragging = Qnil;
7844 part = scroll_bar_below_handle;
7845 break;
7846
7847 case XmCR_TO_TOP:
7848 bar->dragging = Qnil;
7849 part = scroll_bar_to_top;
7850 break;
7851
7852 case XmCR_TO_BOTTOM:
7853 bar->dragging = Qnil;
7854 part = scroll_bar_to_bottom;
7855 break;
7856
7857 case XmCR_DRAG:
7858 {
7859 int slider_size;
7860 int dragging_down_p = (INTEGERP (bar->dragging)
7861 && XINT (bar->dragging) <= cs->value);
7862
7863 /* Get the slider size. */
7864 BLOCK_INPUT;
7865 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7866 UNBLOCK_INPUT;
7867
7868 /* At the max position of the scroll bar, do a line-wise
7869 movement. Without doing anything, the LessTif scroll bar
7870 calls us with the same cs->value again and again. If we
7871 want to make sure that we can reach the end of the buffer,
7872 we have to do something.
7873
7874 Implementation note: setting bar->dragging always to
7875 cs->value gives a smoother movement at the max position.
7876 Setting it to nil when doing line-wise movement gives
7877 a better slider behavior. */
7878
7879 if (cs->value + slider_size == XM_SB_MAX
7880 || (dragging_down_p
7881 && last_scroll_bar_part == scroll_bar_down_arrow))
7882 {
7883 part = scroll_bar_down_arrow;
7884 bar->dragging = Qnil;
7885 }
7886 else
7887 {
7888 whole = XM_SB_RANGE;
7889 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7890 part = scroll_bar_handle;
7891 bar->dragging = make_number (cs->value);
7892 }
7893 }
7894 break;
7895
7896 case XmCR_VALUE_CHANGED:
7897 break;
7898 };
7899
7900 if (part >= 0)
7901 {
7902 window_being_scrolled = bar->window;
7903 last_scroll_bar_part = part;
7904 x_send_scroll_bar_event (bar->window, part, portion, whole);
7905 }
7906}
7907
7908
ec18280f 7909#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7910
7911
ec18280f 7912/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7913 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7914 scroll bar struct. CALL_DATA is a pointer to a float saying where
7915 the thumb is. */
7916
7917static void
ec18280f 7918xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7919 Widget widget;
7920 XtPointer client_data, call_data;
7921{
7922 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7923 float top = *(float *) call_data;
7924 float shown;
ec18280f
SM
7925 int whole, portion, height;
7926 int part;
06a2c219
GM
7927
7928 /* Get the size of the thumb, a value between 0 and 1. */
7929 BLOCK_INPUT;
ec18280f 7930 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7931 UNBLOCK_INPUT;
7932
7933 whole = 10000000;
7934 portion = shown < 1 ? top * whole : 0;
06a2c219 7935
ec18280f
SM
7936 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7937 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7938 the bottom, so we force the scrolling whenever we see that we're
7939 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7940 we try to ensure that we always stay two pixels away from the
7941 bottom). */
06a2c219
GM
7942 part = scroll_bar_down_arrow;
7943 else
7944 part = scroll_bar_handle;
7945
7946 window_being_scrolled = bar->window;
7947 bar->dragging = make_number (portion);
7948 last_scroll_bar_part = part;
7949 x_send_scroll_bar_event (bar->window, part, portion, whole);
7950}
7951
7952
ec18280f
SM
7953/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7954 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7955 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7956 the scroll bar. CALL_DATA is an integer specifying the action that
7957 has taken place. It's magnitude is in the range 0..height of the
7958 scroll bar. Negative values mean scroll towards buffer start.
7959 Values < height of scroll bar mean line-wise movement. */
7960
7961static void
ec18280f 7962xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7963 Widget widget;
7964 XtPointer client_data, call_data;
7965{
7966 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7967 int position = (int) call_data;
7968 Dimension height;
7969 int part;
7970
7971 /* Get the height of the scroll bar. */
7972 BLOCK_INPUT;
7973 XtVaGetValues (widget, XtNheight, &height, NULL);
7974 UNBLOCK_INPUT;
7975
ec18280f
SM
7976 if (abs (position) >= height)
7977 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7978
7979 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7980 it maps line-movement to call_data = max(5, height/20). */
7981 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7982 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7983 else
ec18280f 7984 part = scroll_bar_move_ratio;
06a2c219
GM
7985
7986 window_being_scrolled = bar->window;
7987 bar->dragging = Qnil;
7988 last_scroll_bar_part = part;
ec18280f 7989 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7990}
7991
7992
7993#endif /* not USE_MOTIF */
7994
7995
7996/* Create the widget for scroll bar BAR on frame F. Record the widget
7997 and X window of the scroll bar in BAR. */
7998
7999static void
8000x_create_toolkit_scroll_bar (f, bar)
8001 struct frame *f;
8002 struct scroll_bar *bar;
8003{
8004 Window xwindow;
8005 Widget widget;
8006 Arg av[20];
8007 int ac = 0;
8008 char *scroll_bar_name = "verticalScrollBar";
8009 unsigned long pixel;
8010
8011 BLOCK_INPUT;
8012
8013#ifdef USE_MOTIF
8014 /* LessTif 0.85, problems:
8015
8016 1. When the mouse if over the scroll bar, the scroll bar will
8017 get keyboard events. I didn't find a way to turn this off.
8018
8019 2. Do we have to explicitly set the cursor to get an arrow
8020 cursor (see below)? */
8021
8022 /* Set resources. Create the widget. */
8023 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8024 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8025 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8026 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8027 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8028 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8029 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8030
8031 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8032 if (pixel != -1)
8033 {
8034 XtSetArg (av[ac], XmNforeground, pixel);
8035 ++ac;
8036 }
8037
8038 pixel = f->output_data.x->scroll_bar_background_pixel;
8039 if (pixel != -1)
8040 {
8041 XtSetArg (av[ac], XmNbackground, pixel);
8042 ++ac;
8043 }
8044
8045 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8046 scroll_bar_name, av, ac);
8047
8048 /* Add one callback for everything that can happen. */
8049 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8050 (XtPointer) bar);
8051 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8052 (XtPointer) bar);
8053 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8054 (XtPointer) bar);
8055 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8056 (XtPointer) bar);
8057 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8058 (XtPointer) bar);
8059 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8060 (XtPointer) bar);
8061 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8062 (XtPointer) bar);
8063
8064 /* Realize the widget. Only after that is the X window created. */
8065 XtRealizeWidget (widget);
8066
8067 /* Set the cursor to an arrow. I didn't find a resource to do that.
8068 And I'm wondering why it hasn't an arrow cursor by default. */
8069 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8070 f->output_data.x->nontext_cursor);
8071
ec18280f 8072#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
8073
8074 /* Set resources. Create the widget. The background of the
8075 Xaw3d scroll bar widget is a little bit light for my taste.
8076 We don't alter it here to let users change it according
8077 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8078 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8079 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
8080 /* For smoother scrolling with Xaw3d -sm */
8081 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8082 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
8083
8084 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8085 if (pixel != -1)
8086 {
8087 XtSetArg (av[ac], XtNforeground, pixel);
8088 ++ac;
8089 }
8090
8091 pixel = f->output_data.x->scroll_bar_background_pixel;
8092 if (pixel != -1)
8093 {
8094 XtSetArg (av[ac], XtNbackground, pixel);
8095 ++ac;
8096 }
8097
8098 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8099 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
8100
8101 {
8102 char *initial = "";
8103 char *val = initial;
8104 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8105 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8106 if (val == initial)
8107 { /* ARROW_SCROLL */
8108 xaw3d_arrow_scroll = True;
8109 /* Isn't that just a personal preference ? -sm */
8110 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8111 }
8112 }
06a2c219
GM
8113
8114 /* Define callbacks. */
ec18280f
SM
8115 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8116 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
8117 (XtPointer) bar);
8118
8119 /* Realize the widget. Only after that is the X window created. */
8120 XtRealizeWidget (widget);
8121
ec18280f 8122#endif /* !USE_MOTIF */
06a2c219
GM
8123
8124 /* Install an action hook that let's us detect when the user
8125 finishes interacting with a scroll bar. */
8126 if (action_hook_id == 0)
8127 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8128
8129 /* Remember X window and widget in the scroll bar vector. */
8130 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8131 xwindow = XtWindow (widget);
8132 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8133
8134 UNBLOCK_INPUT;
8135}
8136
8137
8138/* Set the thumb size and position of scroll bar BAR. We are currently
8139 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8140
8141static void
8142x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8143 struct scroll_bar *bar;
8144 int portion, position, whole;
f451eb13 8145{
06a2c219 8146 float top, shown;
06a2c219 8147 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 8148
06a2c219
GM
8149 if (whole == 0)
8150 top = 0, shown = 1;
8151 else
f451eb13 8152 {
06a2c219
GM
8153 top = (float) position / whole;
8154 shown = (float) portion / whole;
8155 }
f451eb13 8156
06a2c219 8157 BLOCK_INPUT;
f451eb13 8158
06a2c219
GM
8159#ifdef USE_MOTIF
8160 {
8161 int size, value;
8162 Boolean arrow1_selected, arrow2_selected;
8163 unsigned char flags;
8164 XmScrollBarWidget sb;
8165
ec18280f 8166 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
8167 is the scroll bar's maximum and MIN is the scroll bar's minimum
8168 value. */
8169 size = shown * XM_SB_RANGE;
8170 size = min (size, XM_SB_RANGE);
8171 size = max (size, 1);
8172
8173 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8174 value = top * XM_SB_RANGE;
8175 value = min (value, XM_SB_MAX - size);
8176 value = max (value, XM_SB_MIN);
8177
8178 /* LessTif: Calling XmScrollBarSetValues after an increment or
8179 decrement turns off auto-repeat LessTif-internally. This can
8180 be seen in ScrollBar.c which resets Arrow1Selected and
8181 Arrow2Selected. It also sets internal flags so that LessTif
8182 believes the mouse is in the slider. We either have to change
8183 our code, or work around that by accessing private data. */
8184
8185 sb = (XmScrollBarWidget) widget;
8186 arrow1_selected = sb->scrollBar.arrow1_selected;
8187 arrow2_selected = sb->scrollBar.arrow2_selected;
8188 flags = sb->scrollBar.flags;
8189
8190 if (NILP (bar->dragging))
8191 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8192 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8193 /* This has the negative side effect that the slider value is
ec18280f 8194 not what it would be if we scrolled here using line-wise or
06a2c219
GM
8195 page-wise movement. */
8196 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8197 else
8198 {
8199 /* If currently dragging, only update the slider size.
8200 This reduces flicker effects. */
8201 int old_value, old_size, increment, page_increment;
8202
8203 XmScrollBarGetValues (widget, &old_value, &old_size,
8204 &increment, &page_increment);
8205 XmScrollBarSetValues (widget, old_value,
8206 min (size, XM_SB_RANGE - old_value),
8207 0, 0, False);
8208 }
8209
8210 sb->scrollBar.arrow1_selected = arrow1_selected;
8211 sb->scrollBar.arrow2_selected = arrow2_selected;
8212 sb->scrollBar.flags = flags;
8213 }
ec18280f 8214#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 8215 {
ec18280f
SM
8216 float old_top, old_shown;
8217 Dimension height;
8218 XtVaGetValues (widget,
8219 XtNtopOfThumb, &old_top,
8220 XtNshown, &old_shown,
8221 XtNheight, &height,
8222 NULL);
8223
8224 /* Massage the top+shown values. */
8225 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8226 top = max (0, min (1, top));
8227 else
8228 top = old_top;
8229 /* Keep two pixels available for moving the thumb down. */
8230 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8231
8232 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8233 check that your system's configuration file contains a define
8234 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8235 if (top != old_top || shown != old_shown)
eb393530 8236 {
ec18280f 8237 if (NILP (bar->dragging))
eb393530 8238 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8239 else
8240 {
ec18280f
SM
8241#ifdef HAVE_XAW3D
8242 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8243 int scroll_mode = 0;
ec18280f
SM
8244
8245 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8246 if (xaw3d_arrow_scroll)
8247 {
8248 /* Xaw3d stupidly ignores resize requests while dragging
8249 so we have to make it believe it's not in dragging mode. */
8250 scroll_mode = sb->scrollbar.scroll_mode;
8251 if (scroll_mode == 2)
8252 sb->scrollbar.scroll_mode = 0;
8253 }
8254#endif
8255 /* Try to make the scrolling a tad smoother. */
8256 if (!xaw3d_pick_top)
8257 shown = min (shown, old_shown);
8258
8259 XawScrollbarSetThumb (widget, top, shown);
8260
8261#ifdef HAVE_XAW3D
8262 if (xaw3d_arrow_scroll && scroll_mode == 2)
8263 sb->scrollbar.scroll_mode = scroll_mode;
8264#endif
06a2c219 8265 }
06a2c219
GM
8266 }
8267 }
ec18280f 8268#endif /* !USE_MOTIF */
06a2c219
GM
8269
8270 UNBLOCK_INPUT;
f451eb13
JB
8271}
8272
06a2c219
GM
8273#endif /* USE_TOOLKIT_SCROLL_BARS */
8274
8275
8276\f
8277/************************************************************************
8278 Scroll bars, general
8279 ************************************************************************/
8280
8281/* Create a scroll bar and return the scroll bar vector for it. W is
8282 the Emacs window on which to create the scroll bar. TOP, LEFT,
8283 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8284 scroll bar. */
8285
ab648270 8286static struct scroll_bar *
06a2c219
GM
8287x_scroll_bar_create (w, top, left, width, height)
8288 struct window *w;
f451eb13
JB
8289 int top, left, width, height;
8290{
06a2c219 8291 struct frame *f = XFRAME (w->frame);
334208b7
RS
8292 struct scroll_bar *bar
8293 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8294
8295 BLOCK_INPUT;
8296
06a2c219
GM
8297#if USE_TOOLKIT_SCROLL_BARS
8298 x_create_toolkit_scroll_bar (f, bar);
8299#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8300 {
8301 XSetWindowAttributes a;
8302 unsigned long mask;
5c187dee 8303 Window window;
06a2c219
GM
8304
8305 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8306 if (a.background_pixel == -1)
8307 a.background_pixel = f->output_data.x->background_pixel;
8308
12ba150f 8309 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8310 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8311 | ExposureMask);
7a13e894 8312 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8313
dbc4e1c1 8314 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8315
06a2c219
GM
8316 /* Clear the area of W that will serve as a scroll bar. This is
8317 for the case that a window has been split horizontally. In
8318 this case, no clear_frame is generated to reduce flickering. */
8319 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8320 left, top, width,
8321 window_box_height (w), False);
8322
8323 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8324 /* Position and size of scroll bar. */
8325 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8326 top,
8327 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8328 height,
8329 /* Border width, depth, class, and visual. */
8330 0,
8331 CopyFromParent,
8332 CopyFromParent,
8333 CopyFromParent,
8334 /* Attributes. */
8335 mask, &a);
8336 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8337 }
06a2c219 8338#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8339
06a2c219 8340 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8341 XSETINT (bar->top, top);
8342 XSETINT (bar->left, left);
8343 XSETINT (bar->width, width);
8344 XSETINT (bar->height, height);
8345 XSETINT (bar->start, 0);
8346 XSETINT (bar->end, 0);
12ba150f 8347 bar->dragging = Qnil;
f451eb13
JB
8348
8349 /* Add bar to its frame's list of scroll bars. */
334208b7 8350 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8351 bar->prev = Qnil;
334208b7 8352 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8353 if (!NILP (bar->next))
e0c1aef2 8354 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8355
06a2c219
GM
8356 /* Map the window/widget. */
8357#if USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8358 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8359 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8360 top,
8361 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8362 height, 0);
fa2dfc30 8363 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
06a2c219 8364#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8365 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8366#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8367
8368 UNBLOCK_INPUT;
12ba150f 8369 return bar;
f451eb13
JB
8370}
8371
06a2c219 8372
12ba150f 8373/* Draw BAR's handle in the proper position.
06a2c219 8374
12ba150f
JB
8375 If the handle is already drawn from START to END, don't bother
8376 redrawing it, unless REBUILD is non-zero; in that case, always
8377 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8378 events.)
12ba150f
JB
8379
8380 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8381 fit inside its rectangle, but if the user is dragging the scroll
8382 bar handle, we want to let them drag it down all the way, so that
8383 the bar's top is as far down as it goes; otherwise, there's no way
8384 to move to the very end of the buffer. */
8385
5c187dee
GM
8386#ifndef USE_TOOLKIT_SCROLL_BARS
8387
f451eb13 8388static void
ab648270
JB
8389x_scroll_bar_set_handle (bar, start, end, rebuild)
8390 struct scroll_bar *bar;
f451eb13 8391 int start, end;
12ba150f 8392 int rebuild;
f451eb13 8393{
12ba150f 8394 int dragging = ! NILP (bar->dragging);
ab648270 8395 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8396 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8397 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8398
8399 /* If the display is already accurate, do nothing. */
8400 if (! rebuild
8401 && start == XINT (bar->start)
8402 && end == XINT (bar->end))
8403 return;
8404
f451eb13
JB
8405 BLOCK_INPUT;
8406
8407 {
d9cdbb3d
RS
8408 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8409 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8410 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8411
8412 /* Make sure the values are reasonable, and try to preserve
8413 the distance between start and end. */
12ba150f
JB
8414 {
8415 int length = end - start;
8416
8417 if (start < 0)
8418 start = 0;
8419 else if (start > top_range)
8420 start = top_range;
8421 end = start + length;
8422
8423 if (end < start)
8424 end = start;
8425 else if (end > top_range && ! dragging)
8426 end = top_range;
8427 }
f451eb13 8428
ab648270 8429 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8430 XSETINT (bar->start, start);
8431 XSETINT (bar->end, end);
f451eb13 8432
12ba150f
JB
8433 /* Clip the end position, just for display. */
8434 if (end > top_range)
8435 end = top_range;
f451eb13 8436
ab648270 8437 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8438 below top positions, to make sure the handle is always at least
8439 that many pixels tall. */
ab648270 8440 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8441
12ba150f
JB
8442 /* Draw the empty space above the handle. Note that we can't clear
8443 zero-height areas; that means "clear to end of window." */
8444 if (0 < start)
334208b7 8445 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8446
12ba150f 8447 /* x, y, width, height, and exposures. */
ab648270
JB
8448 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8449 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8450 inside_width, start,
8451 False);
f451eb13 8452
06a2c219
GM
8453 /* Change to proper foreground color if one is specified. */
8454 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8455 XSetForeground (FRAME_X_DISPLAY (f), gc,
8456 f->output_data.x->scroll_bar_foreground_pixel);
8457
12ba150f 8458 /* Draw the handle itself. */
334208b7 8459 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8460
12ba150f 8461 /* x, y, width, height */
ab648270
JB
8462 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8463 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8464 inside_width, end - start);
f451eb13 8465
06a2c219
GM
8466 /* Restore the foreground color of the GC if we changed it above. */
8467 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8468 XSetForeground (FRAME_X_DISPLAY (f), gc,
8469 f->output_data.x->foreground_pixel);
f451eb13 8470
12ba150f
JB
8471 /* Draw the empty space below the handle. Note that we can't
8472 clear zero-height areas; that means "clear to end of window." */
8473 if (end < inside_height)
334208b7 8474 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8475
12ba150f 8476 /* x, y, width, height, and exposures. */
ab648270
JB
8477 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8478 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8479 inside_width, inside_height - end,
8480 False);
f451eb13 8481
f451eb13
JB
8482 }
8483
f451eb13
JB
8484 UNBLOCK_INPUT;
8485}
8486
5c187dee 8487#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8488
06a2c219
GM
8489/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8490 nil. */
58769bee 8491
12ba150f 8492static void
ab648270
JB
8493x_scroll_bar_remove (bar)
8494 struct scroll_bar *bar;
12ba150f 8495{
12ba150f
JB
8496 BLOCK_INPUT;
8497
06a2c219
GM
8498#if USE_TOOLKIT_SCROLL_BARS
8499 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8500#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8501 {
8502 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8503 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8504 }
06a2c219
GM
8505#endif /* not USE_TOOLKIT_SCROLL_BARS */
8506
ab648270
JB
8507 /* Disassociate this scroll bar from its window. */
8508 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8509
8510 UNBLOCK_INPUT;
8511}
8512
06a2c219 8513
12ba150f
JB
8514/* Set the handle of the vertical scroll bar for WINDOW to indicate
8515 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8516 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8517 create one. */
06a2c219 8518
12ba150f 8519static void
06a2c219
GM
8520XTset_vertical_scroll_bar (w, portion, whole, position)
8521 struct window *w;
f451eb13
JB
8522 int portion, whole, position;
8523{
06a2c219 8524 struct frame *f = XFRAME (w->frame);
ab648270 8525 struct scroll_bar *bar;
3c6ede7b 8526 int top, height, left, sb_left, width, sb_width;
06a2c219 8527 int window_x, window_y, window_width, window_height;
06a2c219 8528
3c6ede7b 8529 /* Get window dimensions. */
06a2c219 8530 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8531 top = window_y;
8532 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8533 height = window_height;
06a2c219 8534
3c6ede7b 8535 /* Compute the left edge of the scroll bar area. */
06a2c219 8536 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8537 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8538 else
8539 left = XFASTINT (w->left);
8540 left *= CANON_X_UNIT (f);
8541 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8542
8543 /* Compute the width of the scroll bar which might be less than
8544 the width of the area reserved for the scroll bar. */
8545 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8546 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8547 else
3c6ede7b 8548 sb_width = width;
12ba150f 8549
3c6ede7b
GM
8550 /* Compute the left edge of the scroll bar. */
8551#ifdef USE_TOOLKIT_SCROLL_BARS
8552 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8553 sb_left = left + width - sb_width - (width - sb_width) / 2;
8554 else
8555 sb_left = left + (width - sb_width) / 2;
8556#else
8557 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8558 sb_left = left + width - sb_width;
8559 else
8560 sb_left = left;
8561#endif
8562
ab648270 8563 /* Does the scroll bar exist yet? */
06a2c219 8564 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8565 {
80c32bcc 8566 BLOCK_INPUT;
3c6ede7b
GM
8567 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8568 left, top, width, height, False);
80c32bcc 8569 UNBLOCK_INPUT;
3c6ede7b
GM
8570 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8571 }
f451eb13 8572 else
12ba150f
JB
8573 {
8574 /* It may just need to be moved and resized. */
06a2c219
GM
8575 unsigned int mask = 0;
8576
8577 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8578
8579 BLOCK_INPUT;
8580
3c6ede7b 8581 if (sb_left != XINT (bar->left))
06a2c219 8582 mask |= CWX;
3c6ede7b 8583 if (top != XINT (bar->top))
06a2c219 8584 mask |= CWY;
3c6ede7b 8585 if (sb_width != XINT (bar->width))
06a2c219 8586 mask |= CWWidth;
3c6ede7b 8587 if (height != XINT (bar->height))
06a2c219
GM
8588 mask |= CWHeight;
8589
8590#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8591
8592 /* Since toolkit scroll bars are smaller than the space reserved
8593 for them on the frame, we have to clear "under" them. */
8594 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8595 left, top, width, height, False);
06a2c219
GM
8596
8597 /* Move/size the scroll bar widget. */
8598 if (mask)
8599 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8600 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8601 top,
8602 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8603 height, 0);
06a2c219
GM
8604
8605#else /* not USE_TOOLKIT_SCROLL_BARS */
8606
e1f6572f
RS
8607 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8608 {
8609 /* Clear areas not covered by the scroll bar. This makes sure a
8610 previous mode line display is cleared after C-x 2 C-x 1, for
8611 example. Non-toolkit scroll bars are as wide as the area
8612 reserved for scroll bars - trim at both sides. */
8613 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8614 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8615 height, False);
8616 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8617 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8618 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8619 height, False);
8620 }
06a2c219
GM
8621
8622 /* Move/size the scroll bar window. */
8623 if (mask)
8624 {
8625 XWindowChanges wc;
8626
3c6ede7b
GM
8627 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8628 wc.y = top;
8629 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8630 wc.height = height;
06a2c219
GM
8631 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8632 mask, &wc);
8633 }
8634
8635#endif /* not USE_TOOLKIT_SCROLL_BARS */
8636
8637 /* Remember new settings. */
3c6ede7b
GM
8638 XSETINT (bar->left, sb_left);
8639 XSETINT (bar->top, top);
8640 XSETINT (bar->width, sb_width);
8641 XSETINT (bar->height, height);
06a2c219
GM
8642
8643 UNBLOCK_INPUT;
12ba150f 8644 }
f451eb13 8645
06a2c219
GM
8646#if USE_TOOLKIT_SCROLL_BARS
8647 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8648#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8649 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8650 dragged. */
12ba150f 8651 if (NILP (bar->dragging))
f451eb13 8652 {
92857db0 8653 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8654
12ba150f 8655 if (whole == 0)
ab648270 8656 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8657 else
8658 {
43f868f5
JB
8659 int start = ((double) position * top_range) / whole;
8660 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8661 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8662 }
f451eb13 8663 }
06a2c219 8664#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8665
06a2c219 8666 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8667}
8668
12ba150f 8669
f451eb13 8670/* The following three hooks are used when we're doing a thorough
ab648270 8671 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8672 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8673 away is a real pain - "Can you say set-window-configuration, boys
8674 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8675 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8676 from the fiery pit when we actually redisplay its window. */
f451eb13 8677
ab648270
JB
8678/* Arrange for all scroll bars on FRAME to be removed at the next call
8679 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8680 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8681
58769bee 8682static void
ab648270 8683XTcondemn_scroll_bars (frame)
f451eb13
JB
8684 FRAME_PTR frame;
8685{
f9e24cb9
RS
8686 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8687 while (! NILP (FRAME_SCROLL_BARS (frame)))
8688 {
8689 Lisp_Object bar;
8690 bar = FRAME_SCROLL_BARS (frame);
8691 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8692 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8693 XSCROLL_BAR (bar)->prev = Qnil;
8694 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8695 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8696 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8697 }
f451eb13
JB
8698}
8699
fa2dfc30 8700
06a2c219 8701/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8702 Note that WINDOW isn't necessarily condemned at all. */
fa2dfc30 8703
f451eb13 8704static void
ab648270 8705XTredeem_scroll_bar (window)
12ba150f 8706 struct window *window;
f451eb13 8707{
ab648270 8708 struct scroll_bar *bar;
fa2dfc30 8709 struct frame *f;
12ba150f 8710
ab648270
JB
8711 /* We can't redeem this window's scroll bar if it doesn't have one. */
8712 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8713 abort ();
8714
ab648270 8715 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8716
8717 /* Unlink it from the condemned list. */
fa2dfc30
GM
8718 f = XFRAME (WINDOW_FRAME (window));
8719 if (NILP (bar->prev))
8720 {
8721 /* If the prev pointer is nil, it must be the first in one of
8722 the lists. */
8723 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8724 /* It's not condemned. Everything's fine. */
8725 return;
8726 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8727 window->vertical_scroll_bar))
8728 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8729 else
8730 /* If its prev pointer is nil, it must be at the front of
8731 one or the other! */
8732 abort ();
8733 }
8734 else
8735 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f 8736
fa2dfc30
GM
8737 if (! NILP (bar->next))
8738 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8739
fa2dfc30
GM
8740 bar->next = FRAME_SCROLL_BARS (f);
8741 bar->prev = Qnil;
8742 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8743 if (! NILP (bar->next))
8744 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13
JB
8745}
8746
ab648270
JB
8747/* Remove all scroll bars on FRAME that haven't been saved since the
8748 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8749
f451eb13 8750static void
ab648270 8751XTjudge_scroll_bars (f)
12ba150f 8752 FRAME_PTR f;
f451eb13 8753{
12ba150f 8754 Lisp_Object bar, next;
f451eb13 8755
ab648270 8756 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8757
8758 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8759 more events on the hapless scroll bars. */
8760 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8761
8762 for (; ! NILP (bar); bar = next)
f451eb13 8763 {
ab648270 8764 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8765
ab648270 8766 x_scroll_bar_remove (b);
12ba150f
JB
8767
8768 next = b->next;
8769 b->next = b->prev = Qnil;
f451eb13 8770 }
12ba150f 8771
ab648270 8772 /* Now there should be no references to the condemned scroll bars,
12ba150f 8773 and they should get garbage-collected. */
f451eb13
JB
8774}
8775
8776
06a2c219
GM
8777/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8778 is a no-op when using toolkit scroll bars.
ab648270
JB
8779
8780 This may be called from a signal handler, so we have to ignore GC
8781 mark bits. */
06a2c219 8782
f451eb13 8783static void
ab648270
JB
8784x_scroll_bar_expose (bar, event)
8785 struct scroll_bar *bar;
f451eb13
JB
8786 XEvent *event;
8787{
06a2c219
GM
8788#ifndef USE_TOOLKIT_SCROLL_BARS
8789
ab648270 8790 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8791 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8792 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8793 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8794
f451eb13
JB
8795 BLOCK_INPUT;
8796
ab648270 8797 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8798
06a2c219 8799 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8800 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8801
8802 /* x, y, width, height */
d9cdbb3d 8803 0, 0,
3cbd2e0b 8804 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8805 XINT (bar->height) - 1);
8806
f451eb13 8807 UNBLOCK_INPUT;
06a2c219
GM
8808
8809#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8810}
8811
ab648270
JB
8812/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8813 is set to something other than no_event, it is enqueued.
8814
8815 This may be called from a signal handler, so we have to ignore GC
8816 mark bits. */
06a2c219 8817
5c187dee
GM
8818#ifndef USE_TOOLKIT_SCROLL_BARS
8819
f451eb13 8820static void
ab648270
JB
8821x_scroll_bar_handle_click (bar, event, emacs_event)
8822 struct scroll_bar *bar;
f451eb13
JB
8823 XEvent *event;
8824 struct input_event *emacs_event;
8825{
0299d313 8826 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8827 abort ();
8828
ab648270 8829 emacs_event->kind = scroll_bar_click;
69388238 8830 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8831 emacs_event->modifiers
8832 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8833 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8834 event->xbutton.state)
8835 | (event->type == ButtonRelease
8836 ? up_modifier
8837 : down_modifier));
12ba150f 8838 emacs_event->frame_or_window = bar->window;
0f8aabe9 8839 emacs_event->arg = Qnil;
f451eb13 8840 emacs_event->timestamp = event->xbutton.time;
12ba150f 8841 {
06a2c219 8842#if 0
d9cdbb3d 8843 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8844 int internal_height
d9cdbb3d 8845 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8846#endif
0299d313 8847 int top_range
d9cdbb3d 8848 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8849 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8850
8851 if (y < 0) y = 0;
8852 if (y > top_range) y = top_range;
8853
8854 if (y < XINT (bar->start))
ab648270
JB
8855 emacs_event->part = scroll_bar_above_handle;
8856 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8857 emacs_event->part = scroll_bar_handle;
12ba150f 8858 else
ab648270 8859 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8860
8861 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8862 they want to drag it. Lisp code needs to be able to decide
8863 whether or not we're dragging. */
929787e1 8864#if 0
12ba150f
JB
8865 /* If the user has just clicked on the handle, record where they're
8866 holding it. */
8867 if (event->type == ButtonPress
ab648270 8868 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8869 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8870#endif
12ba150f
JB
8871
8872 /* If the user has released the handle, set it to its final position. */
8873 if (event->type == ButtonRelease
8874 && ! NILP (bar->dragging))
8875 {
8876 int new_start = y - XINT (bar->dragging);
8877 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8878
ab648270 8879 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8880 bar->dragging = Qnil;
8881 }
f451eb13 8882
5116f055
JB
8883 /* Same deal here as the other #if 0. */
8884#if 0
58769bee 8885 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8886 the handle. */
ab648270 8887 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8888 emacs_event->x = bar->start;
8889 else
e0c1aef2 8890 XSETINT (emacs_event->x, y);
5116f055 8891#else
e0c1aef2 8892 XSETINT (emacs_event->x, y);
5116f055 8893#endif
f451eb13 8894
e0c1aef2 8895 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8896 }
8897}
f451eb13 8898
ab648270
JB
8899/* Handle some mouse motion while someone is dragging the scroll bar.
8900
8901 This may be called from a signal handler, so we have to ignore GC
8902 mark bits. */
06a2c219 8903
f451eb13 8904static void
ab648270
JB
8905x_scroll_bar_note_movement (bar, event)
8906 struct scroll_bar *bar;
f451eb13
JB
8907 XEvent *event;
8908{
39d8bb4d
KH
8909 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8910
f451eb13
JB
8911 last_mouse_movement_time = event->xmotion.time;
8912
39d8bb4d 8913 f->mouse_moved = 1;
e0c1aef2 8914 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8915
8916 /* If we're dragging the bar, display it. */
ab648270 8917 if (! GC_NILP (bar->dragging))
f451eb13
JB
8918 {
8919 /* Where should the handle be now? */
12ba150f 8920 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8921
12ba150f 8922 if (new_start != XINT (bar->start))
f451eb13 8923 {
12ba150f 8924 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8925
ab648270 8926 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8927 }
8928 }
f451eb13
JB
8929}
8930
5c187dee
GM
8931#endif /* !USE_TOOLKIT_SCROLL_BARS */
8932
12ba150f 8933/* Return information to the user about the current position of the mouse
ab648270 8934 on the scroll bar. */
06a2c219 8935
12ba150f 8936static void
334208b7
RS
8937x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8938 FRAME_PTR *fp;
12ba150f 8939 Lisp_Object *bar_window;
ab648270 8940 enum scroll_bar_part *part;
12ba150f
JB
8941 Lisp_Object *x, *y;
8942 unsigned long *time;
8943{
ab648270 8944 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8945 Window w = SCROLL_BAR_X_WINDOW (bar);
8946 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8947 int win_x, win_y;
559cb2fb
JB
8948 Window dummy_window;
8949 int dummy_coord;
8950 unsigned int dummy_mask;
12ba150f 8951
cf7cb199
JB
8952 BLOCK_INPUT;
8953
ab648270 8954 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8955 report that. */
334208b7 8956 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8957
559cb2fb
JB
8958 /* Root, child, root x and root y. */
8959 &dummy_window, &dummy_window,
8960 &dummy_coord, &dummy_coord,
12ba150f 8961
559cb2fb
JB
8962 /* Position relative to scroll bar. */
8963 &win_x, &win_y,
12ba150f 8964
559cb2fb
JB
8965 /* Mouse buttons and modifier keys. */
8966 &dummy_mask))
7a13e894 8967 ;
559cb2fb
JB
8968 else
8969 {
06a2c219 8970#if 0
559cb2fb 8971 int inside_height
d9cdbb3d 8972 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8973#endif
559cb2fb 8974 int top_range
d9cdbb3d 8975 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8976
8977 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8978
8979 if (! NILP (bar->dragging))
8980 win_y -= XINT (bar->dragging);
8981
8982 if (win_y < 0)
8983 win_y = 0;
8984 if (win_y > top_range)
8985 win_y = top_range;
8986
334208b7 8987 *fp = f;
7a13e894 8988 *bar_window = bar->window;
559cb2fb
JB
8989
8990 if (! NILP (bar->dragging))
8991 *part = scroll_bar_handle;
8992 else if (win_y < XINT (bar->start))
8993 *part = scroll_bar_above_handle;
8994 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8995 *part = scroll_bar_handle;
8996 else
8997 *part = scroll_bar_below_handle;
12ba150f 8998
e0c1aef2
KH
8999 XSETINT (*x, win_y);
9000 XSETINT (*y, top_range);
12ba150f 9001
39d8bb4d 9002 f->mouse_moved = 0;
559cb2fb
JB
9003 last_mouse_scroll_bar = Qnil;
9004 }
12ba150f 9005
559cb2fb 9006 *time = last_mouse_movement_time;
cf7cb199 9007
cf7cb199 9008 UNBLOCK_INPUT;
12ba150f
JB
9009}
9010
f451eb13 9011
dbc4e1c1 9012/* The screen has been cleared so we may have changed foreground or
ab648270
JB
9013 background colors, and the scroll bars may need to be redrawn.
9014 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
9015 redraw them. */
9016
dfcf069d 9017void
ab648270 9018x_scroll_bar_clear (f)
dbc4e1c1
JB
9019 FRAME_PTR f;
9020{
06a2c219 9021#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
9022 Lisp_Object bar;
9023
b80c363e
RS
9024 /* We can have scroll bars even if this is 0,
9025 if we just turned off scroll bar mode.
9026 But in that case we should not clear them. */
9027 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9028 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9029 bar = XSCROLL_BAR (bar)->next)
9030 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9031 0, 0, 0, 0, True);
06a2c219 9032#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
9033}
9034
06a2c219 9035/* This processes Expose events from the menu-bar specific X event
19126e11 9036 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 9037 when handling menu-bar or pop-up items. */
3afe33e7 9038
06a2c219 9039int
3afe33e7
RS
9040process_expose_from_menu (event)
9041 XEvent event;
9042{
9043 FRAME_PTR f;
19126e11 9044 struct x_display_info *dpyinfo;
06a2c219 9045 int frame_exposed_p = 0;
3afe33e7 9046
f94397b5
KH
9047 BLOCK_INPUT;
9048
19126e11
KH
9049 dpyinfo = x_display_info_for_display (event.xexpose.display);
9050 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
9051 if (f)
9052 {
9053 if (f->async_visible == 0)
9054 {
9055 f->async_visible = 1;
9056 f->async_iconified = 0;
06c488fd 9057 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
9058 SET_FRAME_GARBAGED (f);
9059 }
9060 else
9061 {
06a2c219
GM
9062 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9063 event.xexpose.x, event.xexpose.y,
9064 event.xexpose.width, event.xexpose.height);
9065 frame_exposed_p = 1;
3afe33e7
RS
9066 }
9067 }
9068 else
9069 {
9070 struct scroll_bar *bar
9071 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9072
3afe33e7
RS
9073 if (bar)
9074 x_scroll_bar_expose (bar, &event);
9075 }
f94397b5
KH
9076
9077 UNBLOCK_INPUT;
06a2c219 9078 return frame_exposed_p;
3afe33e7 9079}
09756a85
RS
9080\f
9081/* Define a queue to save up SelectionRequest events for later handling. */
9082
9083struct selection_event_queue
9084 {
9085 XEvent event;
9086 struct selection_event_queue *next;
9087 };
9088
9089static struct selection_event_queue *queue;
9090
9091/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 9092
09756a85
RS
9093static int x_queue_selection_requests;
9094
9095/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 9096
09756a85 9097static void
334208b7
RS
9098x_queue_event (f, event)
9099 FRAME_PTR f;
09756a85
RS
9100 XEvent *event;
9101{
9102 struct selection_event_queue *queue_tmp
06a2c219 9103 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 9104
58769bee 9105 if (queue_tmp != NULL)
09756a85
RS
9106 {
9107 queue_tmp->event = *event;
9108 queue_tmp->next = queue;
9109 queue = queue_tmp;
9110 }
9111}
9112
9113/* Take all the queued events and put them back
9114 so that they get processed afresh. */
9115
9116static void
db3906fd
RS
9117x_unqueue_events (display)
9118 Display *display;
09756a85 9119{
58769bee 9120 while (queue != NULL)
09756a85
RS
9121 {
9122 struct selection_event_queue *queue_tmp = queue;
db3906fd 9123 XPutBackEvent (display, &queue_tmp->event);
09756a85 9124 queue = queue_tmp->next;
06a2c219 9125 xfree ((char *)queue_tmp);
09756a85
RS
9126 }
9127}
9128
9129/* Start queuing SelectionRequest events. */
9130
9131void
db3906fd
RS
9132x_start_queuing_selection_requests (display)
9133 Display *display;
09756a85
RS
9134{
9135 x_queue_selection_requests++;
9136}
9137
9138/* Stop queuing SelectionRequest events. */
9139
9140void
db3906fd
RS
9141x_stop_queuing_selection_requests (display)
9142 Display *display;
09756a85
RS
9143{
9144 x_queue_selection_requests--;
db3906fd 9145 x_unqueue_events (display);
09756a85 9146}
f451eb13
JB
9147\f
9148/* The main X event-reading loop - XTread_socket. */
dc6f92b8 9149
06a2c219 9150/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
9151 but we have to put it out here, since static variables within functions
9152 sometimes don't work. */
06a2c219 9153
dc6f92b8
JB
9154static Time enter_timestamp;
9155
11edeb03 9156/* This holds the state XLookupString needs to implement dead keys
58769bee 9157 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
9158 says that a portable program can't use this, but Stephen Gildea assures
9159 me that letting the compiler initialize it to zeros will work okay.
9160
9161 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
9162 given for enter_time stamp, above. */
9163
11edeb03
JB
9164static XComposeStatus compose_status;
9165
10e6549c
RS
9166/* Record the last 100 characters stored
9167 to help debug the loss-of-chars-during-GC problem. */
06a2c219 9168
2224b905
RS
9169static int temp_index;
9170static short temp_buffer[100];
10e6549c 9171
7a13e894
RS
9172/* Set this to nonzero to fake an "X I/O error"
9173 on a particular display. */
06a2c219 9174
7a13e894
RS
9175struct x_display_info *XTread_socket_fake_io_error;
9176
2224b905
RS
9177/* When we find no input here, we occasionally do a no-op command
9178 to verify that the X server is still running and we can still talk with it.
9179 We try all the open displays, one by one.
9180 This variable is used for cycling thru the displays. */
06a2c219 9181
2224b905
RS
9182static struct x_display_info *next_noop_dpyinfo;
9183
06a2c219
GM
9184#define SET_SAVED_MENU_EVENT(size) \
9185 do \
9186 { \
9187 if (f->output_data.x->saved_menu_event == 0) \
9188 f->output_data.x->saved_menu_event \
9189 = (XEvent *) xmalloc (sizeof (XEvent)); \
9190 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9191 if (numchars >= 1) \
9192 { \
9193 bufp->kind = menu_bar_activate_event; \
9194 XSETFRAME (bufp->frame_or_window, f); \
0f8aabe9 9195 bufp->arg = Qnil; \
06a2c219
GM
9196 bufp++; \
9197 count++; \
9198 numchars--; \
9199 } \
9200 } \
9201 while (0)
9202
8805890a 9203#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 9204#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 9205
dc6f92b8
JB
9206/* Read events coming from the X server.
9207 This routine is called by the SIGIO handler.
9208 We return as soon as there are no more events to be read.
9209
9210 Events representing keys are stored in buffer BUFP,
9211 which can hold up to NUMCHARS characters.
9212 We return the number of characters stored into the buffer,
9213 thus pretending to be `read'.
9214
dc6f92b8
JB
9215 EXPECTED is nonzero if the caller knows input is available. */
9216
7c5283e4 9217int
f66868ba 9218XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 9219 register int sd;
8805890a
KH
9220 /* register */ struct input_event *bufp;
9221 /* register */ int numchars;
dc6f92b8
JB
9222 int expected;
9223{
9224 int count = 0;
9225 int nbytes = 0;
dc6f92b8 9226 XEvent event;
f676886a 9227 struct frame *f;
66f55a9d 9228 int event_found = 0;
334208b7 9229 struct x_display_info *dpyinfo;
379b5ac0 9230 struct coding_system coding;
dc6f92b8 9231
9ac0d9e0 9232 if (interrupt_input_blocked)
dc6f92b8 9233 {
9ac0d9e0 9234 interrupt_input_pending = 1;
dc6f92b8
JB
9235 return -1;
9236 }
9237
9ac0d9e0 9238 interrupt_input_pending = 0;
dc6f92b8 9239 BLOCK_INPUT;
c0a04927
RS
9240
9241 /* So people can tell when we have read the available input. */
9242 input_signal_count++;
9243
dc6f92b8 9244 if (numchars <= 0)
06a2c219 9245 abort (); /* Don't think this happens. */
dc6f92b8 9246
bde5503b
GM
9247 ++handling_signal;
9248
379b5ac0
KH
9249 /* The input should be decoded if it is from XIM. Currently the
9250 locale of XIM is the same as that of the system. So, we can use
9251 Vlocale_coding_system which is initialized properly at Emacs
9252 startup time. */
9253 setup_coding_system (Vlocale_coding_system, &coding);
9254 coding.src_multibyte = 0;
9255 coding.dst_multibyte = 1;
9256 /* The input is converted to events, thus we can't handle
9257 composition. Anyway, there's no XIM that gives us composition
9258 information. */
9259 coding.composing = COMPOSITION_DISABLED;
9260
7a13e894
RS
9261 /* Find the display we are supposed to read input for.
9262 It's the one communicating on descriptor SD. */
9263 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9264 {
9265#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9266#ifdef FIOSNBIO
7a13e894
RS
9267 /* If available, Xlib uses FIOSNBIO to make the socket
9268 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9269 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9270 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9271 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9272#endif /* ! defined (FIOSNBIO) */
7a13e894 9273#endif
dc6f92b8 9274
7a13e894
RS
9275#if 0 /* This code can't be made to work, with multiple displays,
9276 and appears not to be used on any system any more.
9277 Also keyboard.c doesn't turn O_NDELAY on and off
9278 for X connections. */
dc6f92b8
JB
9279#ifndef SIGIO
9280#ifndef HAVE_SELECT
7a13e894
RS
9281 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9282 {
9283 extern int read_alarm_should_throw;
9284 read_alarm_should_throw = 1;
9285 XPeekEvent (dpyinfo->display, &event);
9286 read_alarm_should_throw = 0;
9287 }
c118dd06
JB
9288#endif /* HAVE_SELECT */
9289#endif /* SIGIO */
7a13e894 9290#endif
dc6f92b8 9291
7a13e894
RS
9292 /* For debugging, this gives a way to fake an I/O error. */
9293 if (dpyinfo == XTread_socket_fake_io_error)
9294 {
9295 XTread_socket_fake_io_error = 0;
9296 x_io_error_quitter (dpyinfo->display);
9297 }
dc6f92b8 9298
06a2c219 9299 while (XPending (dpyinfo->display))
dc6f92b8 9300 {
7a13e894 9301 XNextEvent (dpyinfo->display, &event);
06a2c219 9302
531483fb 9303#ifdef HAVE_X_I18N
d1bc4182 9304 {
f2be1146
GM
9305 /* Filter events for the current X input method.
9306 XFilterEvent returns non-zero if the input method has
9307 consumed the event. We pass the frame's X window to
9308 XFilterEvent because that's the one for which the IC
9309 was created. */
f5d11644
GM
9310 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9311 event.xclient.window);
9312 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9313 break;
9314 }
0cd6403b 9315#endif
7a13e894
RS
9316 event_found = 1;
9317
9318 switch (event.type)
9319 {
9320 case ClientMessage:
c047688c 9321 {
7a13e894
RS
9322 if (event.xclient.message_type
9323 == dpyinfo->Xatom_wm_protocols
9324 && event.xclient.format == 32)
c047688c 9325 {
7a13e894
RS
9326 if (event.xclient.data.l[0]
9327 == dpyinfo->Xatom_wm_take_focus)
c047688c 9328 {
8c1a6a84
RS
9329 /* Use x_any_window_to_frame because this
9330 could be the shell widget window
9331 if the frame has no title bar. */
9332 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9333#ifdef HAVE_X_I18N
9334 /* Not quite sure this is needed -pd */
8c1a6a84 9335 if (f && FRAME_XIC (f))
6c183ba5
RS
9336 XSetICFocus (FRAME_XIC (f));
9337#endif
f1da8f06
GM
9338#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9339 instructs the WM to set the input focus automatically for
9340 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9341 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9342 it has set the focus. So, XSetInputFocus below is not
9343 needed.
9344
9345 The call to XSetInputFocus below has also caused trouble. In
9346 cases where the XSetInputFocus done by the WM and the one
9347 below are temporally close (on a fast machine), the call
9348 below can generate additional FocusIn events which confuse
9349 Emacs. */
9350
bf7253f4
RS
9351 /* Since we set WM_TAKE_FOCUS, we must call
9352 XSetInputFocus explicitly. But not if f is null,
9353 since that might be an event for a deleted frame. */
7a13e894 9354 if (f)
bf7253f4
RS
9355 {
9356 Display *d = event.xclient.display;
9357 /* Catch and ignore errors, in case window has been
9358 iconified by a window manager such as GWM. */
9359 int count = x_catch_errors (d);
9360 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9361 /* The ICCCM says this is
9362 the only valid choice. */
9363 RevertToParent,
bf7253f4
RS
9364 event.xclient.data.l[1]);
9365 /* This is needed to detect the error
9366 if there is an error. */
9367 XSync (d, False);
9368 x_uncatch_errors (d, count);
9369 }
7a13e894 9370 /* Not certain about handling scroll bars here */
f1da8f06 9371#endif /* 0 */
c047688c 9372 }
7a13e894
RS
9373 else if (event.xclient.data.l[0]
9374 == dpyinfo->Xatom_wm_save_yourself)
9375 {
9376 /* Save state modify the WM_COMMAND property to
06a2c219 9377 something which can reinstate us. This notifies
7a13e894
RS
9378 the session manager, who's looking for such a
9379 PropertyNotify. Can restart processing when
06a2c219 9380 a keyboard or mouse event arrives. */
7a13e894
RS
9381 if (numchars > 0)
9382 {
19126e11
KH
9383 f = x_top_window_to_frame (dpyinfo,
9384 event.xclient.window);
7a13e894
RS
9385
9386 /* This is just so we only give real data once
9387 for a single Emacs process. */
b86bd3dd 9388 if (f == SELECTED_FRAME ())
7a13e894
RS
9389 XSetCommand (FRAME_X_DISPLAY (f),
9390 event.xclient.window,
9391 initial_argv, initial_argc);
f000f5c5 9392 else if (f)
7a13e894
RS
9393 XSetCommand (FRAME_X_DISPLAY (f),
9394 event.xclient.window,
9395 0, 0);
9396 }
9397 }
9398 else if (event.xclient.data.l[0]
9399 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9400 {
19126e11
KH
9401 struct frame *f
9402 = x_any_window_to_frame (dpyinfo,
9403 event.xclient.window);
1fb20991 9404
7a13e894
RS
9405 if (f)
9406 {
9407 if (numchars == 0)
9408 abort ();
1fb20991 9409
7a13e894
RS
9410 bufp->kind = delete_window_event;
9411 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9412 bufp->arg = Qnil;
7a13e894
RS
9413 bufp++;
9414
9415 count += 1;
9416 numchars -= 1;
9417 }
1fb20991 9418 }
c047688c 9419 }
7a13e894
RS
9420 else if (event.xclient.message_type
9421 == dpyinfo->Xatom_wm_configure_denied)
9422 {
9423 }
9424 else if (event.xclient.message_type
9425 == dpyinfo->Xatom_wm_window_moved)
9426 {
9427 int new_x, new_y;
19126e11
KH
9428 struct frame *f
9429 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9430
7a13e894
RS
9431 new_x = event.xclient.data.s[0];
9432 new_y = event.xclient.data.s[1];
1fb20991 9433
7a13e894
RS
9434 if (f)
9435 {
7556890b
RS
9436 f->output_data.x->left_pos = new_x;
9437 f->output_data.x->top_pos = new_y;
7a13e894 9438 }
1fb20991 9439 }
0fdff6bb 9440#ifdef HACK_EDITRES
7a13e894
RS
9441 else if (event.xclient.message_type
9442 == dpyinfo->Xatom_editres)
9443 {
19126e11
KH
9444 struct frame *f
9445 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9446 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9447 &event, NULL);
7a13e894 9448 }
0fdff6bb 9449#endif /* HACK_EDITRES */
06a2c219
GM
9450 else if ((event.xclient.message_type
9451 == dpyinfo->Xatom_DONE)
9452 || (event.xclient.message_type
9453 == dpyinfo->Xatom_PAGE))
9454 {
9455 /* Ghostview job completed. Kill it. We could
9456 reply with "Next" if we received "Page", but we
9457 currently never do because we are interested in
9458 images, only, which should have 1 page. */
06a2c219
GM
9459 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9460 struct frame *f
9461 = x_window_to_frame (dpyinfo, event.xclient.window);
9462 x_kill_gs_process (pixmap, f);
9463 expose_frame (f, 0, 0, 0, 0);
9464 }
9465#ifdef USE_TOOLKIT_SCROLL_BARS
9466 /* Scroll bar callbacks send a ClientMessage from which
9467 we construct an input_event. */
9468 else if (event.xclient.message_type
9469 == dpyinfo->Xatom_Scrollbar)
9470 {
9471 x_scroll_bar_to_input_event (&event, bufp);
9472 ++bufp, ++count, --numchars;
9473 goto out;
9474 }
9475#endif /* USE_TOOLKIT_SCROLL_BARS */
9476 else
9477 goto OTHER;
7a13e894
RS
9478 }
9479 break;
dc6f92b8 9480
7a13e894 9481 case SelectionNotify:
3afe33e7 9482#ifdef USE_X_TOOLKIT
19126e11 9483 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9484 goto OTHER;
3afe33e7 9485#endif /* not USE_X_TOOLKIT */
dfcf069d 9486 x_handle_selection_notify (&event.xselection);
7a13e894 9487 break;
d56a553a 9488
06a2c219 9489 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9490#ifdef USE_X_TOOLKIT
19126e11 9491 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9492 goto OTHER;
3afe33e7 9493#endif /* USE_X_TOOLKIT */
7a13e894
RS
9494 {
9495 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9496
7a13e894
RS
9497 if (numchars == 0)
9498 abort ();
d56a553a 9499
7a13e894
RS
9500 bufp->kind = selection_clear_event;
9501 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9502 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9503 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9504 bufp->frame_or_window = Qnil;
0f8aabe9 9505 bufp->arg = Qnil;
7a13e894 9506 bufp++;
d56a553a 9507
7a13e894
RS
9508 count += 1;
9509 numchars -= 1;
9510 }
9511 break;
dc6f92b8 9512
06a2c219 9513 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9514#ifdef USE_X_TOOLKIT
19126e11 9515 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9516 goto OTHER;
3afe33e7 9517#endif /* USE_X_TOOLKIT */
7a13e894 9518 if (x_queue_selection_requests)
19126e11 9519 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9520 &event);
9521 else
9522 {
9523 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9524
7a13e894
RS
9525 if (numchars == 0)
9526 abort ();
9527
9528 bufp->kind = selection_request_event;
9529 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9530 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9531 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9532 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9533 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9534 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9535 bufp->frame_or_window = Qnil;
0f8aabe9 9536 bufp->arg = Qnil;
7a13e894
RS
9537 bufp++;
9538
9539 count += 1;
9540 numchars -= 1;
9541 }
9542 break;
9543
9544 case PropertyNotify:
3afe33e7 9545#ifdef USE_X_TOOLKIT
19126e11 9546 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9547 goto OTHER;
3afe33e7 9548#endif /* not USE_X_TOOLKIT */
dfcf069d 9549 x_handle_property_notify (&event.xproperty);
7a13e894 9550 break;
dc6f92b8 9551
7a13e894 9552 case ReparentNotify:
19126e11 9553 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9554 if (f)
9555 {
9556 int x, y;
7556890b 9557 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9558 x_real_positions (f, &x, &y);
7556890b
RS
9559 f->output_data.x->left_pos = x;
9560 f->output_data.x->top_pos = y;
7a13e894
RS
9561 }
9562 break;
3bd330d4 9563
7a13e894 9564 case Expose:
19126e11 9565 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9566 if (f)
dc6f92b8 9567 {
7a13e894
RS
9568 if (f->async_visible == 0)
9569 {
9570 f->async_visible = 1;
9571 f->async_iconified = 0;
06c488fd 9572 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9573 SET_FRAME_GARBAGED (f);
9574 }
9575 else
06a2c219
GM
9576 expose_frame (x_window_to_frame (dpyinfo,
9577 event.xexpose.window),
9578 event.xexpose.x, event.xexpose.y,
9579 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9580 }
9581 else
7a13e894 9582 {
06a2c219
GM
9583#ifdef USE_TOOLKIT_SCROLL_BARS
9584 /* Dispatch event to the widget. */
9585 goto OTHER;
9586#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9587 struct scroll_bar *bar
9588 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9589
7a13e894
RS
9590 if (bar)
9591 x_scroll_bar_expose (bar, &event);
3afe33e7 9592#ifdef USE_X_TOOLKIT
7a13e894
RS
9593 else
9594 goto OTHER;
3afe33e7 9595#endif /* USE_X_TOOLKIT */
06a2c219 9596#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9597 }
9598 break;
dc6f92b8 9599
7a13e894
RS
9600 case GraphicsExpose: /* This occurs when an XCopyArea's
9601 source area was obscured or not
9602 available.*/
19126e11 9603 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9604 if (f)
9605 {
06a2c219
GM
9606 expose_frame (f,
9607 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9608 event.xgraphicsexpose.width,
9609 event.xgraphicsexpose.height);
7a13e894 9610 }
3afe33e7 9611#ifdef USE_X_TOOLKIT
7a13e894
RS
9612 else
9613 goto OTHER;
3afe33e7 9614#endif /* USE_X_TOOLKIT */
7a13e894 9615 break;
dc6f92b8 9616
7a13e894 9617 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9618 source area was completely
9619 available */
7a13e894 9620 break;
dc6f92b8 9621
7a13e894 9622 case UnmapNotify:
06a2c219
GM
9623 /* Redo the mouse-highlight after the tooltip has gone. */
9624 if (event.xmap.window == tip_window)
9625 {
9626 tip_window = 0;
9627 redo_mouse_highlight ();
9628 }
9629
91ea2a7a 9630 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9631 if (f) /* F may no longer exist if
9632 the frame was deleted. */
9633 {
9634 /* While a frame is unmapped, display generation is
9635 disabled; you don't want to spend time updating a
9636 display that won't ever be seen. */
9637 f->async_visible = 0;
9638 /* We can't distinguish, from the event, whether the window
9639 has become iconified or invisible. So assume, if it
9640 was previously visible, than now it is iconified.
1aa6072f
RS
9641 But x_make_frame_invisible clears both
9642 the visible flag and the iconified flag;
9643 and that way, we know the window is not iconified now. */
7a13e894 9644 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9645 {
9646 f->async_iconified = 1;
bddd097c 9647
1aa6072f
RS
9648 bufp->kind = iconify_event;
9649 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9650 bufp->arg = Qnil;
1aa6072f
RS
9651 bufp++;
9652 count++;
9653 numchars--;
9654 }
7a13e894 9655 }
7a13e894 9656 goto OTHER;
dc6f92b8 9657
7a13e894 9658 case MapNotify:
06a2c219
GM
9659 if (event.xmap.window == tip_window)
9660 /* The tooltip has been drawn already. Avoid
9661 the SET_FRAME_GARBAGED below. */
9662 goto OTHER;
9663
9664 /* We use x_top_window_to_frame because map events can
9665 come for sub-windows and they don't mean that the
9666 frame is visible. */
19126e11 9667 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9668 if (f)
9669 {
9670 f->async_visible = 1;
9671 f->async_iconified = 0;
06c488fd 9672 f->output_data.x->has_been_visible = 1;
dc6f92b8 9673
7a13e894
RS
9674 /* wait_reading_process_input will notice this and update
9675 the frame's display structures. */
9676 SET_FRAME_GARBAGED (f);
bddd097c 9677
d806e720
RS
9678 if (f->iconified)
9679 {
9680 bufp->kind = deiconify_event;
9681 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9682 bufp->arg = Qnil;
d806e720
RS
9683 bufp++;
9684 count++;
9685 numchars--;
9686 }
e73ec6fa 9687 else if (! NILP (Vframe_list)
8e713be6 9688 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9689 /* Force a redisplay sooner or later
9690 to update the frame titles
9691 in case this is the second frame. */
9692 record_asynch_buffer_change ();
7a13e894 9693 }
7a13e894 9694 goto OTHER;
dc6f92b8 9695
7a13e894 9696 case KeyPress:
19126e11 9697 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9698
06a2c219
GM
9699#ifdef USE_MOTIF
9700 /* I couldn't find a way to prevent LessTif scroll bars
9701 from consuming key events. */
9702 if (f == 0)
9703 {
9704 Widget widget = XtWindowToWidget (dpyinfo->display,
9705 event.xkey.window);
9706 if (widget && XmIsScrollBar (widget))
9707 {
9708 widget = XtParent (widget);
9709 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9710 }
9711 }
9712#endif /* USE_MOTIF */
9713
7a13e894
RS
9714 if (f != 0)
9715 {
9716 KeySym keysym, orig_keysym;
379b5ac0
KH
9717 /* al%imercury@uunet.uu.net says that making this 81
9718 instead of 80 fixed a bug whereby meta chars made
9719 his Emacs hang.
9720
9721 It seems that some version of XmbLookupString has
9722 a bug of not returning XBufferOverflow in
9723 status_return even if the input is too long to
9724 fit in 81 bytes. So, we must prepare sufficient
9725 bytes for copy_buffer. 513 bytes (256 chars for
9726 two-byte character set) seems to be a faily good
9727 approximation. -- 2000.8.10 handa@etl.go.jp */
9728 unsigned char copy_buffer[513];
9729 unsigned char *copy_bufptr = copy_buffer;
9730 int copy_bufsiz = sizeof (copy_buffer);
7a13e894 9731 int modifiers;
64bb1782 9732
7a13e894
RS
9733 event.xkey.state
9734 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9735 extra_keyboard_modifiers);
9736 modifiers = event.xkey.state;
3a2712f9 9737
7a13e894 9738 /* This will have to go some day... */
752a043f 9739
7a13e894
RS
9740 /* make_lispy_event turns chars into control chars.
9741 Don't do it here because XLookupString is too eager. */
9742 event.xkey.state &= ~ControlMask;
5d46f928
RS
9743 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9744 | dpyinfo->super_mod_mask
9745 | dpyinfo->hyper_mod_mask
9746 | dpyinfo->alt_mod_mask);
9747
1cf4a0d1
RS
9748 /* In case Meta is ComposeCharacter,
9749 clear its status. According to Markus Ehrnsperger
9750 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9751 this enables ComposeCharacter to work whether or
9752 not it is combined with Meta. */
9753 if (modifiers & dpyinfo->meta_mod_mask)
9754 bzero (&compose_status, sizeof (compose_status));
9755
6c183ba5
RS
9756#ifdef HAVE_X_I18N
9757 if (FRAME_XIC (f))
9758 {
f5d11644
GM
9759 Status status_return;
9760
6c183ba5 9761 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9762 &event.xkey, copy_bufptr,
9763 copy_bufsiz, &keysym,
6c183ba5 9764 &status_return);
f5d11644
GM
9765 if (status_return == XBufferOverflow)
9766 {
9767 copy_bufsiz = nbytes + 1;
9768 copy_bufptr = (char *) alloca (copy_bufsiz);
9769 nbytes = XmbLookupString (FRAME_XIC (f),
9770 &event.xkey, copy_bufptr,
9771 copy_bufsiz, &keysym,
9772 &status_return);
9773 }
9774
1decb680
PE
9775 if (status_return == XLookupNone)
9776 break;
9777 else if (status_return == XLookupChars)
fdd9d55e
GM
9778 {
9779 keysym = NoSymbol;
9780 modifiers = 0;
9781 }
1decb680
PE
9782 else if (status_return != XLookupKeySym
9783 && status_return != XLookupBoth)
9784 abort ();
6c183ba5
RS
9785 }
9786 else
379b5ac0
KH
9787 nbytes = XLookupString (&event.xkey, copy_bufptr,
9788 copy_bufsiz, &keysym,
9789 &compose_status);
6c183ba5 9790#else
379b5ac0
KH
9791 nbytes = XLookupString (&event.xkey, copy_bufptr,
9792 copy_bufsiz, &keysym,
9793 &compose_status);
6c183ba5 9794#endif
dc6f92b8 9795
7a13e894 9796 orig_keysym = keysym;
55123275 9797
7a13e894
RS
9798 if (numchars > 1)
9799 {
9800 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9801 || keysym == XK_Delete
1097aea0 9802#ifdef XK_ISO_Left_Tab
441affdb 9803 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9804#endif
852bff8f 9805 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9806 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9807 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9808#ifdef HPUX
7a13e894
RS
9809 /* This recognizes the "extended function keys".
9810 It seems there's no cleaner way.
9811 Test IsModifierKey to avoid handling mode_switch
9812 incorrectly. */
9813 || ((unsigned) (keysym) >= XK_Select
9814 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9815#endif
9816#ifdef XK_dead_circumflex
7a13e894 9817 || orig_keysym == XK_dead_circumflex
69388238
RS
9818#endif
9819#ifdef XK_dead_grave
7a13e894 9820 || orig_keysym == XK_dead_grave
69388238
RS
9821#endif
9822#ifdef XK_dead_tilde
7a13e894 9823 || orig_keysym == XK_dead_tilde
69388238
RS
9824#endif
9825#ifdef XK_dead_diaeresis
7a13e894 9826 || orig_keysym == XK_dead_diaeresis
69388238
RS
9827#endif
9828#ifdef XK_dead_macron
7a13e894 9829 || orig_keysym == XK_dead_macron
69388238
RS
9830#endif
9831#ifdef XK_dead_degree
7a13e894 9832 || orig_keysym == XK_dead_degree
69388238
RS
9833#endif
9834#ifdef XK_dead_acute
7a13e894 9835 || orig_keysym == XK_dead_acute
69388238
RS
9836#endif
9837#ifdef XK_dead_cedilla
7a13e894 9838 || orig_keysym == XK_dead_cedilla
69388238
RS
9839#endif
9840#ifdef XK_dead_breve
7a13e894 9841 || orig_keysym == XK_dead_breve
69388238
RS
9842#endif
9843#ifdef XK_dead_ogonek
7a13e894 9844 || orig_keysym == XK_dead_ogonek
69388238
RS
9845#endif
9846#ifdef XK_dead_caron
7a13e894 9847 || orig_keysym == XK_dead_caron
69388238
RS
9848#endif
9849#ifdef XK_dead_doubleacute
7a13e894 9850 || orig_keysym == XK_dead_doubleacute
69388238
RS
9851#endif
9852#ifdef XK_dead_abovedot
7a13e894 9853 || orig_keysym == XK_dead_abovedot
c34790e0 9854#endif
7a13e894
RS
9855 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9856 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9857 /* Any "vendor-specific" key is ok. */
9858 || (orig_keysym & (1 << 28)))
9859 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9860#ifndef HAVE_X11R5
9861#ifdef XK_Mode_switch
7a13e894 9862 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9863#endif
9864#ifdef XK_Num_Lock
7a13e894 9865 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9866#endif
9867#endif /* not HAVE_X11R5 */
7a13e894 9868 ))
dc6f92b8 9869 {
10e6549c
RS
9870 if (temp_index == sizeof temp_buffer / sizeof (short))
9871 temp_index = 0;
7a13e894
RS
9872 temp_buffer[temp_index++] = keysym;
9873 bufp->kind = non_ascii_keystroke;
9874 bufp->code = keysym;
e0c1aef2 9875 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9876 bufp->arg = Qnil;
334208b7
RS
9877 bufp->modifiers
9878 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9879 modifiers);
1113d9db 9880 bufp->timestamp = event.xkey.time;
dc6f92b8 9881 bufp++;
7a13e894
RS
9882 count++;
9883 numchars--;
dc6f92b8 9884 }
7a13e894
RS
9885 else if (numchars > nbytes)
9886 {
9887 register int i;
379b5ac0
KH
9888 register int c;
9889 unsigned char *p, *pend;
9890 int nchars, len;
7a13e894
RS
9891
9892 for (i = 0; i < nbytes; i++)
9893 {
379b5ac0
KH
9894 if (temp_index == (sizeof temp_buffer
9895 / sizeof (short)))
7a13e894 9896 temp_index = 0;
379b5ac0
KH
9897 temp_buffer[temp_index++] = copy_bufptr[i];
9898 }
9899
9900 if (/* If the event is not from XIM, */
9901 event.xkey.keycode != 0
9902 /* or the current locale doesn't request
9903 decoding of the intup data, ... */
9904 || coding.type == coding_type_raw_text
9905 || coding.type == coding_type_no_conversion)
9906 {
9907 /* ... we can use the input data as is. */
9908 nchars = nbytes;
9909 }
9910 else
9911 {
9912 /* We have to decode the input data. */
9913 int require;
9914 unsigned char *p;
9915
9916 require = decoding_buffer_size (&coding, nbytes);
9917 p = (unsigned char *) alloca (require);
9918 coding.mode |= CODING_MODE_LAST_BLOCK;
9919 decode_coding (&coding, copy_bufptr, p,
9920 nbytes, require);
9921 nbytes = coding.produced;
9922 nchars = coding.produced_char;
9923 copy_bufptr = p;
9924 }
9925
9926 /* Convert the input data to a sequence of
9927 character events. */
9928 for (i = 0; i < nbytes; i += len)
9929 {
9930 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9931 nbytes - i, len);
9932 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9933 ? ascii_keystroke
9934 : multibyte_char_keystroke);
9935 bufp->code = c;
7a13e894 9936 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9937 bufp->arg = Qnil;
7a13e894
RS
9938 bufp->modifiers
9939 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9940 modifiers);
9941 bufp->timestamp = event.xkey.time;
9942 bufp++;
9943 }
9944
379b5ac0
KH
9945 count += nchars;
9946 numchars -= nchars;
1decb680
PE
9947
9948 if (keysym == NoSymbol)
9949 break;
7a13e894
RS
9950 }
9951 else
9952 abort ();
dc6f92b8 9953 }
10e6549c
RS
9954 else
9955 abort ();
dc6f92b8 9956 }
59ddecde
GM
9957#ifdef HAVE_X_I18N
9958 /* Don't dispatch this event since XtDispatchEvent calls
9959 XFilterEvent, and two calls in a row may freeze the
9960 client. */
9961 break;
9962#else
717ca130 9963 goto OTHER;
59ddecde 9964#endif
f451eb13 9965
f5d11644 9966 case KeyRelease:
59ddecde
GM
9967#ifdef HAVE_X_I18N
9968 /* Don't dispatch this event since XtDispatchEvent calls
9969 XFilterEvent, and two calls in a row may freeze the
9970 client. */
9971 break;
9972#else
f5d11644 9973 goto OTHER;
59ddecde 9974#endif
f5d11644 9975
7a13e894 9976 /* Here's a possible interpretation of the whole
06a2c219
GM
9977 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9978 you get a FocusIn event, you have to get a FocusOut
9979 event before you relinquish the focus. If you
9980 haven't received a FocusIn event, then a mere
9981 LeaveNotify is enough to free you. */
f451eb13 9982
7a13e894 9983 case EnterNotify:
06a2c219
GM
9984 {
9985 int from_menu_bar_p = 0;
9986
9987 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9988
9989#ifdef LESSTIF_VERSION
9990 /* When clicking outside of a menu bar popup to close
9991 it, we get a FocusIn/ EnterNotify sequence of
9992 events. The flag event.xcrossing.focus is not set
9993 in the EnterNotify event of that sequence because
9994 the focus is in the menu bar,
9995 event.xcrossing.window is the frame's X window.
9996 Unconditionally setting the focus frame to null in
9997 this case is not the right thing, because no event
9998 follows that could set the focus frame to the right
9999 value.
10000
10001 This could be a LessTif bug, but I wasn't able to
10002 reproduce the behavior in a simple test program.
10003
10004 (gerd, LessTif 0.88.1). */
10005
10006 if (!event.xcrossing.focus
10007 && f
10008 && f->output_data.x->menubar_widget)
10009 {
10010 Window focus;
10011 int revert;
10012
10013 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10014 if (focus == XtWindow (f->output_data.x->menubar_widget))
10015 from_menu_bar_p = 1;
10016 }
10017#endif /* LESSTIF_VERSION */
6d4238f3 10018
06a2c219
GM
10019 if (event.xcrossing.focus || from_menu_bar_p)
10020 {
10021 /* Avoid nasty pop/raise loops. */
10022 if (f && (!(f->auto_raise)
10023 || !(f->auto_lower)
10024 || (event.xcrossing.time - enter_timestamp) > 500))
10025 {
10026 x_new_focus_frame (dpyinfo, f);
10027 enter_timestamp = event.xcrossing.time;
10028 }
10029 }
10030 else if (f == dpyinfo->x_focus_frame)
10031 x_new_focus_frame (dpyinfo, 0);
10032
10033 /* EnterNotify counts as mouse movement,
10034 so update things that depend on mouse position. */
10035 if (f && !f->output_data.x->busy_p)
10036 note_mouse_movement (f, &event.xmotion);
10037 goto OTHER;
10038 }
dc6f92b8 10039
7a13e894 10040 case FocusIn:
19126e11 10041 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10042 if (event.xfocus.detail != NotifyPointer)
0f941935 10043 dpyinfo->x_focus_event_frame = f;
7a13e894 10044 if (f)
eb72635f
GM
10045 {
10046 x_new_focus_frame (dpyinfo, f);
10047
10048 /* Don't stop displaying the initial startup message
10049 for a switch-frame event we don't need. */
10050 if (GC_NILP (Vterminal_frame)
10051 && GC_CONSP (Vframe_list)
10052 && !GC_NILP (XCDR (Vframe_list)))
10053 {
10054 bufp->kind = FOCUS_IN_EVENT;
10055 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10056 bufp->arg = Qnil;
eb72635f
GM
10057 ++bufp, ++count, --numchars;
10058 }
10059 }
f9e24cb9 10060
6c183ba5
RS
10061#ifdef HAVE_X_I18N
10062 if (f && FRAME_XIC (f))
10063 XSetICFocus (FRAME_XIC (f));
10064#endif
10065
7a13e894 10066 goto OTHER;
10c5e63d 10067
7a13e894 10068 case LeaveNotify:
19126e11 10069 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 10070 if (f)
10c5e63d 10071 {
06a2c219
GM
10072 Lisp_Object frame;
10073 int from_menu_bar_p = 0;
10074
7a13e894 10075 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
10076 {
10077 /* If we move outside the frame, then we're
10078 certainly no longer on any text in the frame. */
10079 clear_mouse_face (dpyinfo);
10080 dpyinfo->mouse_face_mouse_frame = 0;
10081 }
10082
10083 /* Generate a nil HELP_EVENT to cancel a help-echo.
10084 Do it only if there's something to cancel.
10085 Otherwise, the startup message is cleared when
10086 the mouse leaves the frame. */
10087 if (any_help_event_p)
10088 {
be010514
GM
10089 Lisp_Object frame;
10090 int n;
10091
06a2c219 10092 XSETFRAME (frame, f);
5ab2570d
GM
10093 n = gen_help_event (bufp, numchars,
10094 Qnil, frame, Qnil, Qnil, 0);
be010514 10095 bufp += n, count += n, numchars -= n;
06a2c219 10096 }
7a13e894 10097
06a2c219
GM
10098#ifdef LESSTIF_VERSION
10099 /* Please see the comment at the start of the
10100 EnterNotify case. */
10101 if (!event.xcrossing.focus
10102 && f->output_data.x->menubar_widget)
10103 {
10104 Window focus;
10105 int revert;
10106 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10107 if (focus == XtWindow (f->output_data.x->menubar_widget))
10108 from_menu_bar_p = 1;
10109 }
10110#endif /* LESSTIF_VERSION */
10111
10112 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 10113 x_mouse_leave (dpyinfo);
10c5e63d 10114 else
7a13e894 10115 {
0f941935
KH
10116 if (f == dpyinfo->x_focus_event_frame)
10117 dpyinfo->x_focus_event_frame = 0;
10118 if (f == dpyinfo->x_focus_frame)
10119 x_new_focus_frame (dpyinfo, 0);
7a13e894 10120 }
10c5e63d 10121 }
7a13e894 10122 goto OTHER;
dc6f92b8 10123
7a13e894 10124 case FocusOut:
19126e11 10125 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10126 if (event.xfocus.detail != NotifyPointer
0f941935
KH
10127 && f == dpyinfo->x_focus_event_frame)
10128 dpyinfo->x_focus_event_frame = 0;
10129 if (f && f == dpyinfo->x_focus_frame)
10130 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 10131
6c183ba5
RS
10132#ifdef HAVE_X_I18N
10133 if (f && FRAME_XIC (f))
10134 XUnsetICFocus (FRAME_XIC (f));
10135#endif
10136
7a13e894 10137 goto OTHER;
dc6f92b8 10138
7a13e894 10139 case MotionNotify:
dc6f92b8 10140 {
06a2c219 10141 previous_help_echo = help_echo;
7cea38bc 10142 help_echo = help_echo_object = help_echo_window = Qnil;
be010514 10143 help_echo_pos = -1;
06a2c219 10144
7a13e894
RS
10145 if (dpyinfo->grabbed && last_mouse_frame
10146 && FRAME_LIVE_P (last_mouse_frame))
10147 f = last_mouse_frame;
10148 else
19126e11 10149 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 10150
7a13e894
RS
10151 if (f)
10152 note_mouse_movement (f, &event.xmotion);
10153 else
10154 {
e88b3c50 10155#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10156 struct scroll_bar *bar
10157 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 10158
7a13e894
RS
10159 if (bar)
10160 x_scroll_bar_note_movement (bar, &event);
e88b3c50 10161#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 10162
06a2c219
GM
10163 /* If we move outside the frame, then we're
10164 certainly no longer on any text in the frame. */
7a13e894
RS
10165 clear_mouse_face (dpyinfo);
10166 }
06a2c219
GM
10167
10168 /* If the contents of the global variable help_echo
10169 has changed, generate a HELP_EVENT. */
b7e80413
SM
10170 if (!NILP (help_echo)
10171 || !NILP (previous_help_echo))
06a2c219
GM
10172 {
10173 Lisp_Object frame;
be010514 10174 int n;
06a2c219
GM
10175
10176 if (f)
10177 XSETFRAME (frame, f);
10178 else
10179 frame = Qnil;
10180
10181 any_help_event_p = 1;
5ab2570d 10182 n = gen_help_event (bufp, numchars, help_echo, frame,
7cea38bc
GM
10183 help_echo_window, help_echo_object,
10184 help_echo_pos);
be010514 10185 bufp += n, count += n, numchars -= n;
06a2c219
GM
10186 }
10187
10188 goto OTHER;
dc6f92b8 10189 }
dc6f92b8 10190
7a13e894 10191 case ConfigureNotify:
9829ddba
RS
10192 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10193 if (f)
af395ec1 10194 {
5c187dee 10195#ifndef USE_X_TOOLKIT
bf1b7b30
KH
10196 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10197 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 10198
2d7fc7e8
RS
10199 /* In the toolkit version, change_frame_size
10200 is called by the code that handles resizing
10201 of the EmacsFrame widget. */
7a13e894 10202
7a13e894
RS
10203 /* Even if the number of character rows and columns has
10204 not changed, the font size may have changed, so we need
10205 to check the pixel dimensions as well. */
10206 if (columns != f->width
10207 || rows != f->height
7556890b
RS
10208 || event.xconfigure.width != f->output_data.x->pixel_width
10209 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 10210 {
7d1e984f 10211 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 10212 SET_FRAME_GARBAGED (f);
e687d06e 10213 cancel_mouse_face (f);
7a13e894 10214 }
2d7fc7e8 10215#endif
af395ec1 10216
7556890b
RS
10217 f->output_data.x->pixel_width = event.xconfigure.width;
10218 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
10219
10220 /* What we have now is the position of Emacs's own window.
10221 Convert that to the position of the window manager window. */
dcb07ae9
RS
10222 x_real_positions (f, &f->output_data.x->left_pos,
10223 &f->output_data.x->top_pos);
10224
f5d11644
GM
10225#ifdef HAVE_X_I18N
10226 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10227 xic_set_statusarea (f);
10228#endif
10229
dcb07ae9
RS
10230 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10231 {
10232 /* Since the WM decorations come below top_pos now,
10233 we must put them below top_pos in the future. */
10234 f->output_data.x->win_gravity = NorthWestGravity;
10235 x_wm_set_size_hint (f, (long) 0, 0);
10236 }
8f08dc93
KH
10237#ifdef USE_MOTIF
10238 /* Some window managers pass (0,0) as the location of
10239 the window, and the Motif event handler stores it
10240 in the emacs widget, which messes up Motif menus. */
10241 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10242 {
10243 event.xconfigure.x = f->output_data.x->widget->core.x;
10244 event.xconfigure.y = f->output_data.x->widget->core.y;
10245 }
06a2c219 10246#endif /* USE_MOTIF */
7a13e894 10247 }
2d7fc7e8 10248 goto OTHER;
dc6f92b8 10249
7a13e894
RS
10250 case ButtonPress:
10251 case ButtonRelease:
10252 {
10253 /* If we decide we want to generate an event to be seen
10254 by the rest of Emacs, we put it here. */
10255 struct input_event emacs_event;
9ea173e8 10256 int tool_bar_p = 0;
06a2c219 10257
7a13e894 10258 emacs_event.kind = no_event;
7a13e894 10259 bzero (&compose_status, sizeof (compose_status));
9b07615b 10260
06a2c219
GM
10261 if (dpyinfo->grabbed
10262 && last_mouse_frame
9f67f20b
RS
10263 && FRAME_LIVE_P (last_mouse_frame))
10264 f = last_mouse_frame;
10265 else
2224b905 10266 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 10267
06a2c219
GM
10268 if (f)
10269 {
9ea173e8
GM
10270 /* Is this in the tool-bar? */
10271 if (WINDOWP (f->tool_bar_window)
10272 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
10273 {
10274 Lisp_Object window;
10275 int p, x, y;
10276
10277 x = event.xbutton.x;
10278 y = event.xbutton.y;
10279
10280 /* Set x and y. */
10281 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 10282 if (EQ (window, f->tool_bar_window))
06a2c219 10283 {
9ea173e8
GM
10284 x_handle_tool_bar_click (f, &event.xbutton);
10285 tool_bar_p = 1;
06a2c219
GM
10286 }
10287 }
10288
9ea173e8 10289 if (!tool_bar_p)
06a2c219
GM
10290 if (!dpyinfo->x_focus_frame
10291 || f == dpyinfo->x_focus_frame)
10292 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
10293 }
10294 else
10295 {
06a2c219 10296#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10297 struct scroll_bar *bar
10298 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 10299
7a13e894
RS
10300 if (bar)
10301 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 10302#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10303 }
10304
10305 if (event.type == ButtonPress)
10306 {
10307 dpyinfo->grabbed |= (1 << event.xbutton.button);
10308 last_mouse_frame = f;
edad46f6
KH
10309 /* Ignore any mouse motion that happened
10310 before this event; any subsequent mouse-movement
10311 Emacs events should reflect only motion after
10312 the ButtonPress. */
a00e91cd
KH
10313 if (f != 0)
10314 f->mouse_moved = 0;
06a2c219 10315
9ea173e8
GM
10316 if (!tool_bar_p)
10317 last_tool_bar_item = -1;
7a13e894 10318 }
3afe33e7
RS
10319 else
10320 {
7a13e894 10321 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10322 }
23faf38f 10323
7a13e894
RS
10324 if (numchars >= 1 && emacs_event.kind != no_event)
10325 {
10326 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10327 bufp++;
10328 count++;
10329 numchars--;
10330 }
3afe33e7
RS
10331
10332#ifdef USE_X_TOOLKIT
2224b905
RS
10333 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10334 /* For a down-event in the menu bar,
10335 don't pass it to Xt right now.
10336 Instead, save it away
10337 and we will pass it to Xt from kbd_buffer_get_event.
10338 That way, we can run some Lisp code first. */
91375f8f
RS
10339 if (f && event.type == ButtonPress
10340 /* Verify the event is really within the menu bar
10341 and not just sent to it due to grabbing. */
10342 && event.xbutton.x >= 0
10343 && event.xbutton.x < f->output_data.x->pixel_width
10344 && event.xbutton.y >= 0
10345 && event.xbutton.y < f->output_data.x->menubar_height
10346 && event.xbutton.same_screen)
2224b905 10347 {
8805890a 10348 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10349 XSETFRAME (last_mouse_press_frame, f);
10350 }
10351 else if (event.type == ButtonPress)
10352 {
10353 last_mouse_press_frame = Qnil;
30e671c3 10354 goto OTHER;
ce89ef46 10355 }
06a2c219 10356
2237cac9
RS
10357#ifdef USE_MOTIF /* This should do not harm for Lucid,
10358 but I am trying to be cautious. */
ce89ef46
RS
10359 else if (event.type == ButtonRelease)
10360 {
2237cac9 10361 if (!NILP (last_mouse_press_frame))
f10ded1c 10362 {
2237cac9
RS
10363 f = XFRAME (last_mouse_press_frame);
10364 if (f->output_data.x)
06a2c219 10365 SET_SAVED_BUTTON_EVENT;
f10ded1c 10366 }
06a2c219 10367 else
30e671c3 10368 goto OTHER;
2224b905 10369 }
2237cac9 10370#endif /* USE_MOTIF */
2224b905
RS
10371 else
10372 goto OTHER;
3afe33e7 10373#endif /* USE_X_TOOLKIT */
7a13e894
RS
10374 }
10375 break;
dc6f92b8 10376
7a13e894 10377 case CirculateNotify:
06a2c219
GM
10378 goto OTHER;
10379
7a13e894 10380 case CirculateRequest:
06a2c219
GM
10381 goto OTHER;
10382
10383 case VisibilityNotify:
10384 goto OTHER;
dc6f92b8 10385
7a13e894
RS
10386 case MappingNotify:
10387 /* Someone has changed the keyboard mapping - update the
10388 local cache. */
10389 switch (event.xmapping.request)
10390 {
10391 case MappingModifier:
10392 x_find_modifier_meanings (dpyinfo);
10393 /* This is meant to fall through. */
10394 case MappingKeyboard:
10395 XRefreshKeyboardMapping (&event.xmapping);
10396 }
7a13e894 10397 goto OTHER;
dc6f92b8 10398
7a13e894 10399 default:
7a13e894 10400 OTHER:
717ca130 10401#ifdef USE_X_TOOLKIT
7a13e894
RS
10402 BLOCK_INPUT;
10403 XtDispatchEvent (&event);
10404 UNBLOCK_INPUT;
3afe33e7 10405#endif /* USE_X_TOOLKIT */
7a13e894
RS
10406 break;
10407 }
dc6f92b8
JB
10408 }
10409 }
10410
06a2c219
GM
10411 out:;
10412
9a5196d0
RS
10413 /* On some systems, an X bug causes Emacs to get no more events
10414 when the window is destroyed. Detect that. (1994.) */
58769bee 10415 if (! event_found)
ef2a22d0 10416 {
ef2a22d0
RS
10417 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10418 One XNOOP in 100 loops will make Emacs terminate.
10419 B. Bretthauer, 1994 */
10420 x_noop_count++;
58769bee 10421 if (x_noop_count >= 100)
ef2a22d0
RS
10422 {
10423 x_noop_count=0;
2224b905
RS
10424
10425 if (next_noop_dpyinfo == 0)
10426 next_noop_dpyinfo = x_display_list;
10427
10428 XNoOp (next_noop_dpyinfo->display);
10429
10430 /* Each time we get here, cycle through the displays now open. */
10431 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10432 }
10433 }
502add23 10434
06a2c219 10435 /* If the focus was just given to an auto-raising frame,
0134a210 10436 raise it now. */
7a13e894 10437 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10438 if (pending_autoraise_frame)
10439 {
10440 x_raise_frame (pending_autoraise_frame);
10441 pending_autoraise_frame = 0;
10442 }
0134a210 10443
dc6f92b8 10444 UNBLOCK_INPUT;
bde5503b 10445 --handling_signal;
dc6f92b8
JB
10446 return count;
10447}
06a2c219
GM
10448
10449
10450
dc6f92b8 10451\f
06a2c219
GM
10452/***********************************************************************
10453 Text Cursor
10454 ***********************************************************************/
10455
10456/* Note if the text cursor of window W has been overwritten by a
10457 drawing operation that outputs N glyphs starting at HPOS in the
10458 line given by output_cursor.vpos. N < 0 means all the rest of the
10459 line after HPOS has been written. */
10460
10461static void
10462note_overwritten_text_cursor (w, hpos, n)
10463 struct window *w;
10464 int hpos, n;
10465{
10466 if (updated_area == TEXT_AREA
10467 && output_cursor.vpos == w->phys_cursor.vpos
10468 && hpos <= w->phys_cursor.hpos
10469 && (n < 0
10470 || hpos + n > w->phys_cursor.hpos))
10471 w->phys_cursor_on_p = 0;
10472}
f451eb13
JB
10473
10474
06a2c219
GM
10475/* Set clipping for output in glyph row ROW. W is the window in which
10476 we operate. GC is the graphics context to set clipping in.
10477 WHOLE_LINE_P non-zero means include the areas used for truncation
10478 mark display and alike in the clipping rectangle.
10479
10480 ROW may be a text row or, e.g., a mode line. Text rows must be
10481 clipped to the interior of the window dedicated to text display,
10482 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10483
10484static void
06a2c219
GM
10485x_clip_to_row (w, row, gc, whole_line_p)
10486 struct window *w;
10487 struct glyph_row *row;
10488 GC gc;
10489 int whole_line_p;
dc6f92b8 10490{
06a2c219
GM
10491 struct frame *f = XFRAME (WINDOW_FRAME (w));
10492 XRectangle clip_rect;
10493 int window_x, window_y, window_width, window_height;
dc6f92b8 10494
06a2c219 10495 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10496
06a2c219
GM
10497 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10498 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10499 clip_rect.y = max (clip_rect.y, window_y);
10500 clip_rect.width = window_width;
10501 clip_rect.height = row->visible_height;
5c1aae96 10502
06a2c219
GM
10503 /* If clipping to the whole line, including trunc marks, extend
10504 the rectangle to the left and increase its width. */
10505 if (whole_line_p)
10506 {
110859fc
GM
10507 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10508 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10509 }
5c1aae96 10510
06a2c219 10511 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10512}
10513
06a2c219
GM
10514
10515/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10516
10517static void
06a2c219
GM
10518x_draw_hollow_cursor (w, row)
10519 struct window *w;
10520 struct glyph_row *row;
dc6f92b8 10521{
06a2c219
GM
10522 struct frame *f = XFRAME (WINDOW_FRAME (w));
10523 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10524 Display *dpy = FRAME_X_DISPLAY (f);
10525 int x, y, wd, h;
10526 XGCValues xgcv;
10527 struct glyph *cursor_glyph;
10528 GC gc;
10529
10530 /* Compute frame-relative coordinates from window-relative
10531 coordinates. */
10532 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10533 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10534 + row->ascent - w->phys_cursor_ascent);
10535 h = row->height - 1;
10536
10537 /* Get the glyph the cursor is on. If we can't tell because
10538 the current matrix is invalid or such, give up. */
10539 cursor_glyph = get_phys_cursor_glyph (w);
10540 if (cursor_glyph == NULL)
dc6f92b8
JB
10541 return;
10542
06a2c219
GM
10543 /* Compute the width of the rectangle to draw. If on a stretch
10544 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10545 rectangle as wide as the glyph, but use a canonical character
10546 width instead. */
10547 wd = cursor_glyph->pixel_width - 1;
10548 if (cursor_glyph->type == STRETCH_GLYPH
10549 && !x_stretch_cursor_p)
10550 wd = min (CANON_X_UNIT (f), wd);
10551
10552 /* The foreground of cursor_gc is typically the same as the normal
10553 background color, which can cause the cursor box to be invisible. */
10554 xgcv.foreground = f->output_data.x->cursor_pixel;
10555 if (dpyinfo->scratch_cursor_gc)
10556 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10557 else
10558 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10559 GCForeground, &xgcv);
10560 gc = dpyinfo->scratch_cursor_gc;
10561
10562 /* Set clipping, draw the rectangle, and reset clipping again. */
10563 x_clip_to_row (w, row, gc, 0);
10564 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10565 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10566}
10567
06a2c219
GM
10568
10569/* Draw a bar cursor on window W in glyph row ROW.
10570
10571 Implementation note: One would like to draw a bar cursor with an
10572 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10573 Unfortunately, I didn't find a font yet that has this property set.
10574 --gerd. */
dc6f92b8
JB
10575
10576static void
f02d8aa0 10577x_draw_bar_cursor (w, row, width)
06a2c219
GM
10578 struct window *w;
10579 struct glyph_row *row;
f02d8aa0 10580 int width;
dc6f92b8 10581{
92f424df
GM
10582 struct frame *f = XFRAME (w->frame);
10583 struct glyph *cursor_glyph;
10584 GC gc;
10585 int x;
10586 unsigned long mask;
10587 XGCValues xgcv;
10588 Display *dpy;
10589 Window window;
06a2c219 10590
92f424df
GM
10591 /* If cursor is out of bounds, don't draw garbage. This can happen
10592 in mini-buffer windows when switching between echo area glyphs
10593 and mini-buffer. */
10594 cursor_glyph = get_phys_cursor_glyph (w);
10595 if (cursor_glyph == NULL)
10596 return;
06a2c219 10597
92f424df
GM
10598 /* If on an image, draw like a normal cursor. That's usually better
10599 visible than drawing a bar, esp. if the image is large so that
10600 the bar might not be in the window. */
10601 if (cursor_glyph->type == IMAGE_GLYPH)
10602 {
10603 struct glyph_row *row;
10604 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10605 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10606 }
10607 else
10608 {
06a2c219
GM
10609 xgcv.background = f->output_data.x->cursor_pixel;
10610 xgcv.foreground = f->output_data.x->cursor_pixel;
10611 xgcv.graphics_exposures = 0;
10612 mask = GCForeground | GCBackground | GCGraphicsExposures;
10613 dpy = FRAME_X_DISPLAY (f);
10614 window = FRAME_X_WINDOW (f);
10615 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
92f424df 10616
06a2c219
GM
10617 if (gc)
10618 XChangeGC (dpy, gc, mask, &xgcv);
10619 else
10620 {
10621 gc = XCreateGC (dpy, window, mask, &xgcv);
10622 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10623 }
92f424df 10624
f02d8aa0
GM
10625 if (width < 0)
10626 width = f->output_data.x->cursor_width;
92f424df 10627
06a2c219
GM
10628 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10629 x_clip_to_row (w, row, gc, 0);
10630 XFillRectangle (dpy, window, gc,
10631 x,
10632 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10633 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10634 row->height);
10635 XSetClipMask (dpy, gc, None);
10636 }
dc6f92b8
JB
10637}
10638
06a2c219
GM
10639
10640/* Clear the cursor of window W to background color, and mark the
10641 cursor as not shown. This is used when the text where the cursor
10642 is is about to be rewritten. */
10643
dc6f92b8 10644static void
06a2c219
GM
10645x_clear_cursor (w)
10646 struct window *w;
dc6f92b8 10647{
06a2c219
GM
10648 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10649 x_update_window_cursor (w, 0);
10650}
90e65f07 10651
dbc4e1c1 10652
06a2c219
GM
10653/* Draw the cursor glyph of window W in glyph row ROW. See the
10654 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10655
06a2c219
GM
10656static void
10657x_draw_phys_cursor_glyph (w, row, hl)
10658 struct window *w;
10659 struct glyph_row *row;
10660 enum draw_glyphs_face hl;
10661{
10662 /* If cursor hpos is out of bounds, don't draw garbage. This can
10663 happen in mini-buffer windows when switching between echo area
10664 glyphs and mini-buffer. */
10665 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10666 {
10667 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10668 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10669 hl, 0, 0, 0);
10670
10671 /* When we erase the cursor, and ROW is overlapped by other
10672 rows, make sure that these overlapping parts of other rows
10673 are redrawn. */
10674 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10675 {
10676 if (row > w->current_matrix->rows
10677 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10678 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10679
10680 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10681 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10682 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10683 }
10684 }
06a2c219 10685}
dbc4e1c1 10686
eea6af04 10687
06a2c219 10688/* Erase the image of a cursor of window W from the screen. */
eea6af04 10689
06a2c219
GM
10690static void
10691x_erase_phys_cursor (w)
10692 struct window *w;
10693{
10694 struct frame *f = XFRAME (w->frame);
10695 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10696 int hpos = w->phys_cursor.hpos;
10697 int vpos = w->phys_cursor.vpos;
10698 int mouse_face_here_p = 0;
10699 struct glyph_matrix *active_glyphs = w->current_matrix;
10700 struct glyph_row *cursor_row;
10701 struct glyph *cursor_glyph;
10702 enum draw_glyphs_face hl;
10703
10704 /* No cursor displayed or row invalidated => nothing to do on the
10705 screen. */
10706 if (w->phys_cursor_type == NO_CURSOR)
10707 goto mark_cursor_off;
10708
10709 /* VPOS >= active_glyphs->nrows means that window has been resized.
10710 Don't bother to erase the cursor. */
10711 if (vpos >= active_glyphs->nrows)
10712 goto mark_cursor_off;
10713
10714 /* If row containing cursor is marked invalid, there is nothing we
10715 can do. */
10716 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10717 if (!cursor_row->enabled_p)
10718 goto mark_cursor_off;
10719
10720 /* This can happen when the new row is shorter than the old one.
10721 In this case, either x_draw_glyphs or clear_end_of_line
10722 should have cleared the cursor. Note that we wouldn't be
10723 able to erase the cursor in this case because we don't have a
10724 cursor glyph at hand. */
10725 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10726 goto mark_cursor_off;
10727
10728 /* If the cursor is in the mouse face area, redisplay that when
10729 we clear the cursor. */
8801a864
KR
10730 if (! NILP (dpyinfo->mouse_face_window)
10731 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10732 && (vpos > dpyinfo->mouse_face_beg_row
10733 || (vpos == dpyinfo->mouse_face_beg_row
10734 && hpos >= dpyinfo->mouse_face_beg_col))
10735 && (vpos < dpyinfo->mouse_face_end_row
10736 || (vpos == dpyinfo->mouse_face_end_row
10737 && hpos < dpyinfo->mouse_face_end_col))
10738 /* Don't redraw the cursor's spot in mouse face if it is at the
10739 end of a line (on a newline). The cursor appears there, but
10740 mouse highlighting does not. */
10741 && cursor_row->used[TEXT_AREA] > hpos)
10742 mouse_face_here_p = 1;
10743
10744 /* Maybe clear the display under the cursor. */
10745 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10746 {
10747 int x;
045dee35 10748 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10749
06a2c219
GM
10750 cursor_glyph = get_phys_cursor_glyph (w);
10751 if (cursor_glyph == NULL)
10752 goto mark_cursor_off;
dbc4e1c1 10753
06a2c219
GM
10754 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10755
10756 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10757 x,
045dee35 10758 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10759 cursor_row->y)),
10760 cursor_glyph->pixel_width,
10761 cursor_row->visible_height,
10762 False);
dbc4e1c1 10763 }
06a2c219
GM
10764
10765 /* Erase the cursor by redrawing the character underneath it. */
10766 if (mouse_face_here_p)
10767 hl = DRAW_MOUSE_FACE;
10768 else if (cursor_row->inverse_p)
10769 hl = DRAW_INVERSE_VIDEO;
10770 else
10771 hl = DRAW_NORMAL_TEXT;
10772 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10773
06a2c219
GM
10774 mark_cursor_off:
10775 w->phys_cursor_on_p = 0;
10776 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10777}
10778
10779
06a2c219
GM
10780/* Display or clear cursor of window W. If ON is zero, clear the
10781 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10782 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10783
06a2c219
GM
10784void
10785x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10786 struct window *w;
10787 int on, hpos, vpos, x, y;
dbc4e1c1 10788{
06a2c219
GM
10789 struct frame *f = XFRAME (w->frame);
10790 int new_cursor_type;
f02d8aa0 10791 int new_cursor_width;
06a2c219
GM
10792 struct glyph_matrix *current_glyphs;
10793 struct glyph_row *glyph_row;
10794 struct glyph *glyph;
dbc4e1c1 10795
49d838ea 10796 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10797 windows and frames; in the latter case, the frame or window may
10798 be in the midst of changing its size, and x and y may be off the
10799 window. */
10800 if (! FRAME_VISIBLE_P (f)
10801 || FRAME_GARBAGED_P (f)
10802 || vpos >= w->current_matrix->nrows
10803 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10804 return;
10805
10806 /* If cursor is off and we want it off, return quickly. */
06a2c219 10807 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10808 return;
10809
06a2c219
GM
10810 current_glyphs = w->current_matrix;
10811 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10812 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10813
10814 /* If cursor row is not enabled, we don't really know where to
10815 display the cursor. */
10816 if (!glyph_row->enabled_p)
10817 {
10818 w->phys_cursor_on_p = 0;
10819 return;
10820 }
10821
10822 xassert (interrupt_input_blocked);
10823
10824 /* Set new_cursor_type to the cursor we want to be displayed. In a
10825 mini-buffer window, we want the cursor only to appear if we are
10826 reading input from this window. For the selected window, we want
10827 the cursor type given by the frame parameter. If explicitly
10828 marked off, draw no cursor. In all other cases, we want a hollow
10829 box cursor. */
f02d8aa0 10830 new_cursor_width = -1;
9b4a7047
GM
10831 if (cursor_in_echo_area
10832 && FRAME_HAS_MINIBUF_P (f)
10833 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10834 {
9b4a7047
GM
10835 if (w == XWINDOW (echo_area_window))
10836 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10837 else
10838 new_cursor_type = HOLLOW_BOX_CURSOR;
10839 }
06a2c219 10840 else
9b4a7047
GM
10841 {
10842 if (w != XWINDOW (selected_window)
10843 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10844 {
e55a0b79
GM
10845 extern int cursor_in_non_selected_windows;
10846
5cefa566
GM
10847 if (MINI_WINDOW_P (w)
10848 || !cursor_in_non_selected_windows
10849 || NILP (XBUFFER (w->buffer)->cursor_type))
9b4a7047
GM
10850 new_cursor_type = NO_CURSOR;
10851 else
10852 new_cursor_type = HOLLOW_BOX_CURSOR;
10853 }
10854 else if (w->cursor_off_p)
10855 new_cursor_type = NO_CURSOR;
10856 else
f02d8aa0
GM
10857 {
10858 struct buffer *b = XBUFFER (w->buffer);
10859
10860 if (EQ (b->cursor_type, Qt))
10861 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10862 else
10863 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10864 &new_cursor_width);
10865 }
9b4a7047 10866 }
06a2c219
GM
10867
10868 /* If cursor is currently being shown and we don't want it to be or
10869 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10870 erase it. */
06a2c219 10871 if (w->phys_cursor_on_p
dc6f92b8 10872 && (!on
06a2c219
GM
10873 || w->phys_cursor.x != x
10874 || w->phys_cursor.y != y
10875 || new_cursor_type != w->phys_cursor_type))
10876 x_erase_phys_cursor (w);
10877
10878 /* If the cursor is now invisible and we want it to be visible,
10879 display it. */
10880 if (on && !w->phys_cursor_on_p)
10881 {
10882 w->phys_cursor_ascent = glyph_row->ascent;
10883 w->phys_cursor_height = glyph_row->height;
10884
10885 /* Set phys_cursor_.* before x_draw_.* is called because some
10886 of them may need the information. */
10887 w->phys_cursor.x = x;
10888 w->phys_cursor.y = glyph_row->y;
10889 w->phys_cursor.hpos = hpos;
10890 w->phys_cursor.vpos = vpos;
10891 w->phys_cursor_type = new_cursor_type;
10892 w->phys_cursor_on_p = 1;
10893
10894 switch (new_cursor_type)
dc6f92b8 10895 {
06a2c219
GM
10896 case HOLLOW_BOX_CURSOR:
10897 x_draw_hollow_cursor (w, glyph_row);
10898 break;
10899
10900 case FILLED_BOX_CURSOR:
10901 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10902 break;
10903
10904 case BAR_CURSOR:
f02d8aa0 10905 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10906 break;
10907
10908 case NO_CURSOR:
10909 break;
dc6f92b8 10910
06a2c219
GM
10911 default:
10912 abort ();
10913 }
59ddecde
GM
10914
10915#ifdef HAVE_X_I18N
10916 if (w == XWINDOW (f->selected_window))
10917 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10918 xic_set_preeditarea (w, x, y);
10919#endif
dc6f92b8
JB
10920 }
10921
06a2c219 10922#ifndef XFlush
f676886a 10923 if (updating_frame != f)
334208b7 10924 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10925#endif
dc6f92b8
JB
10926}
10927
06a2c219
GM
10928
10929/* Display the cursor on window W, or clear it. X and Y are window
10930 relative pixel coordinates. HPOS and VPOS are glyph matrix
10931 positions. If W is not the selected window, display a hollow
10932 cursor. ON non-zero means display the cursor at X, Y which
10933 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10934
dfcf069d 10935void
06a2c219
GM
10936x_display_cursor (w, on, hpos, vpos, x, y)
10937 struct window *w;
10938 int on, hpos, vpos, x, y;
dc6f92b8 10939{
f94397b5 10940 BLOCK_INPUT;
06a2c219 10941 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10942 UNBLOCK_INPUT;
10943}
10944
06a2c219
GM
10945
10946/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10947 Don't change the cursor's position. */
10948
dfcf069d 10949void
06a2c219 10950x_update_cursor (f, on_p)
5d46f928 10951 struct frame *f;
5d46f928 10952{
06a2c219
GM
10953 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10954}
10955
10956
10957/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10958 in the window tree rooted at W. */
10959
10960static void
10961x_update_cursor_in_window_tree (w, on_p)
10962 struct window *w;
10963 int on_p;
10964{
10965 while (w)
10966 {
10967 if (!NILP (w->hchild))
10968 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10969 else if (!NILP (w->vchild))
10970 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10971 else
10972 x_update_window_cursor (w, on_p);
10973
10974 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10975 }
10976}
5d46f928 10977
f94397b5 10978
06a2c219
GM
10979/* Switch the display of W's cursor on or off, according to the value
10980 of ON. */
10981
10982static void
10983x_update_window_cursor (w, on)
10984 struct window *w;
10985 int on;
10986{
16b5d424
GM
10987 /* Don't update cursor in windows whose frame is in the process
10988 of being deleted. */
10989 if (w->current_matrix)
10990 {
10991 BLOCK_INPUT;
10992 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10993 w->phys_cursor.x, w->phys_cursor.y);
10994 UNBLOCK_INPUT;
10995 }
dc6f92b8 10996}
06a2c219
GM
10997
10998
10999
dc6f92b8
JB
11000\f
11001/* Icons. */
11002
f676886a 11003/* Refresh bitmap kitchen sink icon for frame F
06a2c219 11004 when we get an expose event for it. */
dc6f92b8 11005
dfcf069d 11006void
f676886a
JB
11007refreshicon (f)
11008 struct frame *f;
dc6f92b8 11009{
06a2c219 11010 /* Normally, the window manager handles this function. */
dc6f92b8
JB
11011}
11012
dbc4e1c1 11013/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
11014
11015int
990ba854 11016x_bitmap_icon (f, file)
f676886a 11017 struct frame *f;
990ba854 11018 Lisp_Object file;
dc6f92b8 11019{
06a2c219 11020 int bitmap_id;
dc6f92b8 11021
c118dd06 11022 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11023 return 1;
11024
990ba854 11025 /* Free up our existing icon bitmap if any. */
7556890b
RS
11026 if (f->output_data.x->icon_bitmap > 0)
11027 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11028 f->output_data.x->icon_bitmap = 0;
990ba854
RS
11029
11030 if (STRINGP (file))
7f2ae036
RS
11031 bitmap_id = x_create_bitmap_from_file (f, file);
11032 else
11033 {
990ba854 11034 /* Create the GNU bitmap if necessary. */
5bf01b68 11035 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
11036 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11037 = x_create_bitmap_from_data (f, gnu_bits,
11038 gnu_width, gnu_height);
990ba854
RS
11039
11040 /* The first time we create the GNU bitmap,
06a2c219 11041 this increments the ref-count one extra time.
990ba854
RS
11042 As a result, the GNU bitmap is never freed.
11043 That way, we don't have to worry about allocating it again. */
334208b7 11044 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 11045
334208b7 11046 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
11047 }
11048
11049 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 11050 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
11051
11052 return 0;
11053}
11054
11055
1be2d067
KH
11056/* Make the x-window of frame F use a rectangle with text.
11057 Use ICON_NAME as the text. */
dc6f92b8
JB
11058
11059int
f676886a
JB
11060x_text_icon (f, icon_name)
11061 struct frame *f;
dc6f92b8
JB
11062 char *icon_name;
11063{
c118dd06 11064 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11065 return 1;
11066
1be2d067
KH
11067#ifdef HAVE_X11R4
11068 {
11069 XTextProperty text;
11070 text.value = (unsigned char *) icon_name;
11071 text.encoding = XA_STRING;
11072 text.format = 8;
11073 text.nitems = strlen (icon_name);
11074#ifdef USE_X_TOOLKIT
7556890b 11075 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
11076 &text);
11077#else /* not USE_X_TOOLKIT */
11078 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11079#endif /* not USE_X_TOOLKIT */
11080 }
11081#else /* not HAVE_X11R4 */
11082 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11083#endif /* not HAVE_X11R4 */
58769bee 11084
7556890b
RS
11085 if (f->output_data.x->icon_bitmap > 0)
11086 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11087 f->output_data.x->icon_bitmap = 0;
b1c884c3 11088 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
11089
11090 return 0;
11091}
11092\f
e99db5a1
RS
11093#define X_ERROR_MESSAGE_SIZE 200
11094
11095/* If non-nil, this should be a string.
11096 It means catch X errors and store the error message in this string. */
11097
11098static Lisp_Object x_error_message_string;
11099
11100/* An X error handler which stores the error message in
11101 x_error_message_string. This is called from x_error_handler if
11102 x_catch_errors is in effect. */
11103
06a2c219 11104static void
e99db5a1
RS
11105x_error_catcher (display, error)
11106 Display *display;
11107 XErrorEvent *error;
11108{
11109 XGetErrorText (display, error->error_code,
11110 XSTRING (x_error_message_string)->data,
11111 X_ERROR_MESSAGE_SIZE);
11112}
11113
11114/* Begin trapping X errors for display DPY. Actually we trap X errors
11115 for all displays, but DPY should be the display you are actually
11116 operating on.
11117
11118 After calling this function, X protocol errors no longer cause
11119 Emacs to exit; instead, they are recorded in the string
11120 stored in x_error_message_string.
11121
11122 Calling x_check_errors signals an Emacs error if an X error has
11123 occurred since the last call to x_catch_errors or x_check_errors.
11124
11125 Calling x_uncatch_errors resumes the normal error handling. */
11126
11127void x_check_errors ();
11128static Lisp_Object x_catch_errors_unwind ();
11129
11130int
11131x_catch_errors (dpy)
11132 Display *dpy;
11133{
11134 int count = specpdl_ptr - specpdl;
11135
11136 /* Make sure any errors from previous requests have been dealt with. */
11137 XSync (dpy, False);
11138
11139 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11140
11141 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11142 XSTRING (x_error_message_string)->data[0] = 0;
11143
11144 return count;
11145}
11146
11147/* Unbind the binding that we made to check for X errors. */
11148
11149static Lisp_Object
11150x_catch_errors_unwind (old_val)
11151 Lisp_Object old_val;
11152{
11153 x_error_message_string = old_val;
11154 return Qnil;
11155}
11156
11157/* If any X protocol errors have arrived since the last call to
11158 x_catch_errors or x_check_errors, signal an Emacs error using
11159 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11160
11161void
11162x_check_errors (dpy, format)
11163 Display *dpy;
11164 char *format;
11165{
11166 /* Make sure to catch any errors incurred so far. */
11167 XSync (dpy, False);
11168
11169 if (XSTRING (x_error_message_string)->data[0])
11170 error (format, XSTRING (x_error_message_string)->data);
11171}
11172
9829ddba
RS
11173/* Nonzero if we had any X protocol errors
11174 since we did x_catch_errors on DPY. */
e99db5a1
RS
11175
11176int
11177x_had_errors_p (dpy)
11178 Display *dpy;
11179{
11180 /* Make sure to catch any errors incurred so far. */
11181 XSync (dpy, False);
11182
11183 return XSTRING (x_error_message_string)->data[0] != 0;
11184}
11185
9829ddba
RS
11186/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11187
06a2c219 11188void
9829ddba
RS
11189x_clear_errors (dpy)
11190 Display *dpy;
11191{
11192 XSTRING (x_error_message_string)->data[0] = 0;
11193}
11194
e99db5a1
RS
11195/* Stop catching X protocol errors and let them make Emacs die.
11196 DPY should be the display that was passed to x_catch_errors.
11197 COUNT should be the value that was returned by
11198 the corresponding call to x_catch_errors. */
11199
11200void
11201x_uncatch_errors (dpy, count)
11202 Display *dpy;
11203 int count;
11204{
11205 unbind_to (count, Qnil);
11206}
11207
11208#if 0
11209static unsigned int x_wire_count;
11210x_trace_wire ()
11211{
11212 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11213}
11214#endif /* ! 0 */
11215
11216\f
11217/* Handle SIGPIPE, which can happen when the connection to a server
11218 simply goes away. SIGPIPE is handled by x_connection_signal.
11219 Don't need to do anything, because the write which caused the
11220 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 11221 which will do the appropriate cleanup for us. */
e99db5a1
RS
11222
11223static SIGTYPE
11224x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 11225 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
11226{
11227#ifdef USG
11228 /* USG systems forget handlers when they are used;
11229 must reestablish each time */
11230 signal (signalnum, x_connection_signal);
11231#endif /* USG */
11232}
11233\f
4746118a
JB
11234/* Handling X errors. */
11235
7a13e894 11236/* Handle the loss of connection to display DISPLAY. */
16bd92ea 11237
4746118a 11238static SIGTYPE
7a13e894
RS
11239x_connection_closed (display, error_message)
11240 Display *display;
11241 char *error_message;
4746118a 11242{
7a13e894
RS
11243 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11244 Lisp_Object frame, tail;
11245
6186a4a0
RS
11246 /* Indicate that this display is dead. */
11247
2e465cdd 11248#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 11249#ifdef USE_X_TOOLKIT
adabc3a9 11250 XtCloseDisplay (display);
2e465cdd 11251#endif
f613a4c8 11252#endif
adabc3a9 11253
9e80b57d
KR
11254 if (dpyinfo)
11255 dpyinfo->display = 0;
6186a4a0 11256
06a2c219 11257 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
11258 that are on the dead display. */
11259 FOR_EACH_FRAME (tail, frame)
11260 {
11261 Lisp_Object minibuf_frame;
11262 minibuf_frame
11263 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
11264 if (FRAME_X_P (XFRAME (frame))
11265 && FRAME_X_P (XFRAME (minibuf_frame))
11266 && ! EQ (frame, minibuf_frame)
11267 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
11268 Fdelete_frame (frame, Qt);
11269 }
11270
11271 /* Now delete all remaining frames on the dead display.
06a2c219 11272 We are now sure none of these is used as the mini-buffer
7a13e894
RS
11273 for another frame that we need to delete. */
11274 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
11275 if (FRAME_X_P (XFRAME (frame))
11276 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
11277 {
11278 /* Set this to t so that Fdelete_frame won't get confused
11279 trying to find a replacement. */
11280 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11281 Fdelete_frame (frame, Qt);
11282 }
7a13e894 11283
482a1bd2
KH
11284 if (dpyinfo)
11285 x_delete_display (dpyinfo);
7a13e894
RS
11286
11287 if (x_display_list == 0)
11288 {
f8d07b62 11289 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
11290 shut_down_emacs (0, 0, Qnil);
11291 exit (70);
11292 }
12ba150f 11293
7a13e894
RS
11294 /* Ordinary stack unwind doesn't deal with these. */
11295#ifdef SIGIO
11296 sigunblock (sigmask (SIGIO));
11297#endif
11298 sigunblock (sigmask (SIGALRM));
11299 TOTALLY_UNBLOCK_INPUT;
11300
aa4d9a9e 11301 clear_waiting_for_input ();
182334bd 11302 handling_signal = 0;
7a13e894 11303 error ("%s", error_message);
4746118a
JB
11304}
11305
7a13e894
RS
11306/* This is the usual handler for X protocol errors.
11307 It kills all frames on the display that we got the error for.
11308 If that was the only one, it prints an error message and kills Emacs. */
11309
06a2c219 11310static void
c118dd06
JB
11311x_error_quitter (display, error)
11312 Display *display;
11313 XErrorEvent *error;
11314{
7a13e894 11315 char buf[256], buf1[356];
dc6f92b8 11316
58769bee 11317 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 11318 original error handler. */
dc6f92b8 11319
c118dd06 11320 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 11321 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 11322 buf, error->request_code);
7a13e894 11323 x_connection_closed (display, buf1);
dc6f92b8
JB
11324}
11325
e99db5a1
RS
11326/* This is the first-level handler for X protocol errors.
11327 It calls x_error_quitter or x_error_catcher. */
7a13e894 11328
8922af5f 11329static int
e99db5a1 11330x_error_handler (display, error)
8922af5f 11331 Display *display;
e99db5a1 11332 XErrorEvent *error;
8922af5f 11333{
e99db5a1
RS
11334 if (! NILP (x_error_message_string))
11335 x_error_catcher (display, error);
11336 else
11337 x_error_quitter (display, error);
06a2c219 11338 return 0;
f9e24cb9 11339}
c118dd06 11340
e99db5a1
RS
11341/* This is the handler for X IO errors, always.
11342 It kills all frames on the display that we lost touch with.
11343 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 11344
c118dd06 11345static int
e99db5a1 11346x_io_error_quitter (display)
c118dd06 11347 Display *display;
c118dd06 11348{
e99db5a1 11349 char buf[256];
dc6f92b8 11350
e99db5a1
RS
11351 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11352 x_connection_closed (display, buf);
06a2c219 11353 return 0;
dc6f92b8 11354}
dc6f92b8 11355\f
f451eb13
JB
11356/* Changing the font of the frame. */
11357
76bcdf39
RS
11358/* Give frame F the font named FONTNAME as its default font, and
11359 return the full name of that font. FONTNAME may be a wildcard
11360 pattern; in that case, we choose some font that fits the pattern.
11361 The return value shows which font we chose. */
11362
b5cf7a0e 11363Lisp_Object
f676886a
JB
11364x_new_font (f, fontname)
11365 struct frame *f;
dc6f92b8
JB
11366 register char *fontname;
11367{
dc43ef94 11368 struct font_info *fontp
ee569018 11369 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 11370
dc43ef94
KH
11371 if (!fontp)
11372 return Qnil;
2224a5fc 11373
dc43ef94 11374 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11375 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11376 f->output_data.x->fontset = -1;
11377
b2cad826
KH
11378 /* Compute the scroll bar width in character columns. */
11379 if (f->scroll_bar_pixel_width > 0)
11380 {
7556890b 11381 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11382 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11383 }
11384 else
4e61bddf
RS
11385 {
11386 int wid = FONT_WIDTH (f->output_data.x->font);
11387 f->scroll_bar_cols = (14 + wid - 1) / wid;
11388 }
b2cad826 11389
f676886a 11390 /* Now make the frame display the given font. */
c118dd06 11391 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11392 {
7556890b
RS
11393 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11394 f->output_data.x->font->fid);
11395 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11396 f->output_data.x->font->fid);
11397 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11398 f->output_data.x->font->fid);
f676886a 11399
a27f9f86 11400 frame_update_line_height (f);
0134a210 11401 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11402 }
a27f9f86
RS
11403 else
11404 /* If we are setting a new frame's font for the first time,
11405 there are no faces yet, so this font's height is the line height. */
7556890b 11406 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11407
dc43ef94
KH
11408 return build_string (fontp->full_name);
11409}
11410
11411/* Give frame F the fontset named FONTSETNAME as its default font, and
11412 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11413 pattern; in that case, we choose some fontset that fits the pattern.
11414 The return value shows which fontset we chose. */
b5cf7a0e 11415
dc43ef94
KH
11416Lisp_Object
11417x_new_fontset (f, fontsetname)
11418 struct frame *f;
11419 char *fontsetname;
11420{
ee569018 11421 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11422 Lisp_Object result;
b5cf7a0e 11423
dc43ef94
KH
11424 if (fontset < 0)
11425 return Qnil;
b5cf7a0e 11426
2da424f1
KH
11427 if (f->output_data.x->fontset == fontset)
11428 /* This fontset is already set in frame F. There's nothing more
11429 to do. */
ee569018 11430 return fontset_name (fontset);
dc43ef94 11431
ee569018 11432 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11433
11434 if (!STRINGP (result))
11435 /* Can't load ASCII font. */
11436 return Qnil;
11437
11438 /* Since x_new_font doesn't update any fontset information, do it now. */
11439 f->output_data.x->fontset = fontset;
dc43ef94 11440
f5d11644
GM
11441#ifdef HAVE_X_I18N
11442 if (FRAME_XIC (f)
11443 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11444 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11445#endif
11446
dc43ef94 11447 return build_string (fontsetname);
dc6f92b8 11448}
f5d11644
GM
11449
11450\f
11451/***********************************************************************
11452 X Input Methods
11453 ***********************************************************************/
11454
11455#ifdef HAVE_X_I18N
11456
11457#ifdef HAVE_X11R6
11458
11459/* XIM destroy callback function, which is called whenever the
11460 connection to input method XIM dies. CLIENT_DATA contains a
11461 pointer to the x_display_info structure corresponding to XIM. */
11462
11463static void
11464xim_destroy_callback (xim, client_data, call_data)
11465 XIM xim;
11466 XPointer client_data;
11467 XPointer call_data;
11468{
11469 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11470 Lisp_Object frame, tail;
11471
11472 BLOCK_INPUT;
11473
11474 /* No need to call XDestroyIC.. */
11475 FOR_EACH_FRAME (tail, frame)
11476 {
11477 struct frame *f = XFRAME (frame);
11478 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11479 {
11480 FRAME_XIC (f) = NULL;
11481 if (FRAME_XIC_FONTSET (f))
11482 {
11483 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11484 FRAME_XIC_FONTSET (f) = NULL;
11485 }
11486 }
11487 }
11488
11489 /* No need to call XCloseIM. */
11490 dpyinfo->xim = NULL;
11491 XFree (dpyinfo->xim_styles);
11492 UNBLOCK_INPUT;
11493}
11494
11495#endif /* HAVE_X11R6 */
11496
11497/* Open the connection to the XIM server on display DPYINFO.
11498 RESOURCE_NAME is the resource name Emacs uses. */
11499
11500static void
11501xim_open_dpy (dpyinfo, resource_name)
11502 struct x_display_info *dpyinfo;
11503 char *resource_name;
11504{
287f7dd6 11505#ifdef USE_XIM
f5d11644
GM
11506 XIM xim;
11507
11508 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11509 dpyinfo->xim = xim;
11510
11511 if (xim)
11512 {
f5d11644
GM
11513#ifdef HAVE_X11R6
11514 XIMCallback destroy;
11515#endif
11516
11517 /* Get supported styles and XIM values. */
11518 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11519
11520#ifdef HAVE_X11R6
11521 destroy.callback = xim_destroy_callback;
11522 destroy.client_data = (XPointer)dpyinfo;
68642df6 11523 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11524 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11525#endif
11526 }
287f7dd6
GM
11527
11528#else /* not USE_XIM */
11529 dpyinfo->xim = NULL;
11530#endif /* not USE_XIM */
f5d11644
GM
11531}
11532
11533
b9de836c 11534#ifdef HAVE_X11R6_XIM
f5d11644
GM
11535
11536struct xim_inst_t
11537{
11538 struct x_display_info *dpyinfo;
11539 char *resource_name;
11540};
11541
11542/* XIM instantiate callback function, which is called whenever an XIM
11543 server is available. DISPLAY is teh display of the XIM.
11544 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11545 when the callback was registered. */
11546
11547static void
11548xim_instantiate_callback (display, client_data, call_data)
11549 Display *display;
11550 XPointer client_data;
11551 XPointer call_data;
11552{
11553 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11554 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11555
11556 /* We don't support multiple XIM connections. */
11557 if (dpyinfo->xim)
11558 return;
11559
11560 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11561
11562 /* Create XIC for the existing frames on the same display, as long
11563 as they have no XIC. */
11564 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11565 {
11566 Lisp_Object tail, frame;
11567
11568 BLOCK_INPUT;
11569 FOR_EACH_FRAME (tail, frame)
11570 {
11571 struct frame *f = XFRAME (frame);
11572
11573 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11574 if (FRAME_XIC (f) == NULL)
11575 {
11576 create_frame_xic (f);
11577 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11578 xic_set_statusarea (f);
11579 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11580 {
11581 struct window *w = XWINDOW (f->selected_window);
11582 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11583 }
11584 }
11585 }
11586
11587 UNBLOCK_INPUT;
11588 }
11589}
11590
b9de836c 11591#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11592
11593
11594/* Open a connection to the XIM server on display DPYINFO.
11595 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11596 connection only at the first time. On X11R6, open the connection
11597 in the XIM instantiate callback function. */
11598
11599static void
11600xim_initialize (dpyinfo, resource_name)
11601 struct x_display_info *dpyinfo;
11602 char *resource_name;
11603{
287f7dd6 11604#ifdef USE_XIM
b9de836c 11605#ifdef HAVE_X11R6_XIM
f5d11644
GM
11606 struct xim_inst_t *xim_inst;
11607 int len;
11608
11609 dpyinfo->xim = NULL;
11610 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11611 xim_inst->dpyinfo = dpyinfo;
11612 len = strlen (resource_name);
11613 xim_inst->resource_name = (char *) xmalloc (len + 1);
11614 bcopy (resource_name, xim_inst->resource_name, len + 1);
11615 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11616 resource_name, EMACS_CLASS,
11617 xim_instantiate_callback,
2ebb2f8b
DL
11618 /* Fixme: This is XPointer in
11619 XFree86 but (XPointer *) on
11620 Tru64, at least. */
11621 (XPointer) xim_inst);
b9de836c 11622#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11623 dpyinfo->xim = NULL;
11624 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11625#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11626
11627#else /* not USE_XIM */
11628 dpyinfo->xim = NULL;
11629#endif /* not USE_XIM */
f5d11644
GM
11630}
11631
11632
11633/* Close the connection to the XIM server on display DPYINFO. */
11634
11635static void
11636xim_close_dpy (dpyinfo)
11637 struct x_display_info *dpyinfo;
11638{
287f7dd6 11639#ifdef USE_XIM
b9de836c 11640#ifdef HAVE_X11R6_XIM
f5d11644
GM
11641 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11642 NULL, EMACS_CLASS,
11643 xim_instantiate_callback, NULL);
b9de836c 11644#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11645 XCloseIM (dpyinfo->xim);
11646 dpyinfo->xim = NULL;
11647 XFree (dpyinfo->xim_styles);
287f7dd6 11648#endif /* USE_XIM */
f5d11644
GM
11649}
11650
b9de836c 11651#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11652
11653
dc6f92b8 11654\f
2e365682
RS
11655/* Calculate the absolute position in frame F
11656 from its current recorded position values and gravity. */
11657
dfcf069d 11658void
43bca5d5 11659x_calc_absolute_position (f)
f676886a 11660 struct frame *f;
dc6f92b8 11661{
06a2c219 11662 Window child;
6dba1858 11663 int win_x = 0, win_y = 0;
7556890b 11664 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11665 int this_window;
11666
9829ddba
RS
11667 /* We have nothing to do if the current position
11668 is already for the top-left corner. */
11669 if (! ((flags & XNegative) || (flags & YNegative)))
11670 return;
11671
c81412a0 11672#ifdef USE_X_TOOLKIT
7556890b 11673 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11674#else
11675 this_window = FRAME_X_WINDOW (f);
11676#endif
6dba1858
RS
11677
11678 /* Find the position of the outside upper-left corner of
9829ddba
RS
11679 the inner window, with respect to the outer window.
11680 But do this only if we will need the results. */
7556890b 11681 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11682 {
9829ddba
RS
11683 int count;
11684
6dba1858 11685 BLOCK_INPUT;
9829ddba
RS
11686 count = x_catch_errors (FRAME_X_DISPLAY (f));
11687 while (1)
11688 {
11689 x_clear_errors (FRAME_X_DISPLAY (f));
11690 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11691
11692 /* From-window, to-window. */
11693 this_window,
11694 f->output_data.x->parent_desc,
11695
11696 /* From-position, to-position. */
11697 0, 0, &win_x, &win_y,
11698
11699 /* Child of win. */
11700 &child);
11701 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11702 {
11703 Window newroot, newparent = 0xdeadbeef;
11704 Window *newchildren;
2ebb2f8b 11705 unsigned int nchildren;
9829ddba
RS
11706
11707 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11708 &newparent, &newchildren, &nchildren))
11709 break;
58769bee 11710
7c3c78a3 11711 XFree ((char *) newchildren);
6dba1858 11712
9829ddba
RS
11713 f->output_data.x->parent_desc = newparent;
11714 }
11715 else
11716 break;
11717 }
6dba1858 11718
9829ddba 11719 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11720 UNBLOCK_INPUT;
11721 }
11722
11723 /* Treat negative positions as relative to the leftmost bottommost
11724 position that fits on the screen. */
20f55f9a 11725 if (flags & XNegative)
7556890b 11726 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11727 - 2 * f->output_data.x->border_width - win_x
11728 - PIXEL_WIDTH (f)
11729 + f->output_data.x->left_pos);
dc6f92b8 11730
20f55f9a 11731 if (flags & YNegative)
06a2c219
GM
11732 {
11733 int menubar_height = 0;
11734
11735#ifdef USE_X_TOOLKIT
11736 if (f->output_data.x->menubar_widget)
11737 menubar_height
11738 = (f->output_data.x->menubar_widget->core.height
11739 + f->output_data.x->menubar_widget->core.border_width);
11740#endif
11741
11742 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11743 - 2 * f->output_data.x->border_width
11744 - win_y
11745 - PIXEL_HEIGHT (f)
11746 - menubar_height
11747 + f->output_data.x->top_pos);
11748 }
2e365682 11749
3a35ab44
RS
11750 /* The left_pos and top_pos
11751 are now relative to the top and left screen edges,
11752 so the flags should correspond. */
7556890b 11753 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11754}
11755
3a35ab44
RS
11756/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11757 to really change the position, and 0 when calling from
11758 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11759 position values). It is -1 when calling from x_set_frame_parameters,
11760 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11761
dfcf069d 11762void
dc05a16b 11763x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11764 struct frame *f;
dc6f92b8 11765 register int xoff, yoff;
dc05a16b 11766 int change_gravity;
dc6f92b8 11767{
4a4cbdd5
KH
11768 int modified_top, modified_left;
11769
aa3ff7c9 11770 if (change_gravity > 0)
3a35ab44 11771 {
7556890b
RS
11772 f->output_data.x->top_pos = yoff;
11773 f->output_data.x->left_pos = xoff;
11774 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11775 if (xoff < 0)
7556890b 11776 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11777 if (yoff < 0)
7556890b
RS
11778 f->output_data.x->size_hint_flags |= YNegative;
11779 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11780 }
43bca5d5 11781 x_calc_absolute_position (f);
dc6f92b8
JB
11782
11783 BLOCK_INPUT;
c32cdd9a 11784 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11785
7556890b
RS
11786 modified_left = f->output_data.x->left_pos;
11787 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11788#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11789 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11790 /* It is a mystery why we need to add the border_width here
11791 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11792 if (change_gravity != 0)
4a4cbdd5 11793 {
7556890b
RS
11794 modified_left += f->output_data.x->border_width;
11795 modified_top += f->output_data.x->border_width;
4a4cbdd5 11796 }
e73ec6fa 11797#endif
4a4cbdd5 11798
3afe33e7 11799#ifdef USE_X_TOOLKIT
7556890b 11800 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11801 modified_left, modified_top);
3afe33e7 11802#else /* not USE_X_TOOLKIT */
334208b7 11803 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11804 modified_left, modified_top);
3afe33e7 11805#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11806 UNBLOCK_INPUT;
11807}
11808
bc20ebbf
FP
11809/* Call this to change the size of frame F's x-window.
11810 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11811 for this size change and subsequent size changes.
11812 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11813
dfcf069d 11814void
bc20ebbf 11815x_set_window_size (f, change_gravity, cols, rows)
f676886a 11816 struct frame *f;
bc20ebbf 11817 int change_gravity;
b1c884c3 11818 int cols, rows;
dc6f92b8 11819{
06a2c219 11820#ifndef USE_X_TOOLKIT
dc6f92b8 11821 int pixelwidth, pixelheight;
06a2c219 11822#endif
dc6f92b8 11823
80fd1fe2 11824 BLOCK_INPUT;
aee9a898
RS
11825
11826#ifdef USE_X_TOOLKIT
3a20653d
RS
11827 {
11828 /* The x and y position of the widget is clobbered by the
11829 call to XtSetValues within EmacsFrameSetCharSize.
11830 This is a real kludge, but I don't understand Xt so I can't
11831 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11832 int xpos = f->output_data.x->widget->core.x;
11833 int ypos = f->output_data.x->widget->core.y;
11834 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11835 f->output_data.x->widget->core.x = xpos;
11836 f->output_data.x->widget->core.y = ypos;
3a20653d 11837 }
80fd1fe2
FP
11838
11839#else /* not USE_X_TOOLKIT */
11840
b1c884c3 11841 check_frame_size (f, &rows, &cols);
7556890b 11842 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11843 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11844 ? 0
11845 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11846 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11847 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11848 f->output_data.x->flags_areas_extra
110859fc 11849 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11850 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11851 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11852
7556890b 11853 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11854 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11855
334208b7
RS
11856 XSync (FRAME_X_DISPLAY (f), False);
11857 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11858 pixelwidth, pixelheight);
b1c884c3
JB
11859
11860 /* Now, strictly speaking, we can't be sure that this is accurate,
11861 but the window manager will get around to dealing with the size
11862 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11863 ConfigureNotify event gets here.
11864
11865 We could just not bother storing any of this information here,
11866 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11867 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11868 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11869 point in the future when the ConfigureNotify event arrives.
11870
11871 We pass 1 for DELAY since we can't run Lisp code inside of
11872 a BLOCK_INPUT. */
7d1e984f 11873 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11874 PIXEL_WIDTH (f) = pixelwidth;
11875 PIXEL_HEIGHT (f) = pixelheight;
11876
aee9a898
RS
11877 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11878 receive in the ConfigureNotify event; if we get what we asked
11879 for, then the event won't cause the screen to become garbaged, so
11880 we have to make sure to do it here. */
11881 SET_FRAME_GARBAGED (f);
11882
11883 XFlush (FRAME_X_DISPLAY (f));
11884
11885#endif /* not USE_X_TOOLKIT */
11886
4d73d038 11887 /* If cursor was outside the new size, mark it as off. */
06a2c219 11888 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11889
aee9a898
RS
11890 /* Clear out any recollection of where the mouse highlighting was,
11891 since it might be in a place that's outside the new frame size.
11892 Actually checking whether it is outside is a pain in the neck,
11893 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11894 cancel_mouse_face (f);
dbc4e1c1 11895
dc6f92b8
JB
11896 UNBLOCK_INPUT;
11897}
dc6f92b8 11898\f
d047c4eb 11899/* Mouse warping. */
dc6f92b8 11900
9b378208 11901void
f676886a
JB
11902x_set_mouse_position (f, x, y)
11903 struct frame *f;
dc6f92b8
JB
11904 int x, y;
11905{
11906 int pix_x, pix_y;
11907
7556890b
RS
11908 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11909 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11910
11911 if (pix_x < 0) pix_x = 0;
11912 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11913
11914 if (pix_y < 0) pix_y = 0;
11915 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11916
11917 BLOCK_INPUT;
dc6f92b8 11918
334208b7
RS
11919 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11920 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11921 UNBLOCK_INPUT;
11922}
11923
9b378208
RS
11924/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11925
11926void
11927x_set_mouse_pixel_position (f, pix_x, pix_y)
11928 struct frame *f;
11929 int pix_x, pix_y;
11930{
11931 BLOCK_INPUT;
11932
334208b7
RS
11933 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11934 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11935 UNBLOCK_INPUT;
11936}
d047c4eb
KH
11937\f
11938/* focus shifting, raising and lowering. */
9b378208 11939
dfcf069d 11940void
f676886a
JB
11941x_focus_on_frame (f)
11942 struct frame *f;
dc6f92b8 11943{
1fb20991 11944#if 0 /* This proves to be unpleasant. */
f676886a 11945 x_raise_frame (f);
1fb20991 11946#endif
6d4238f3
JB
11947#if 0
11948 /* I don't think that the ICCCM allows programs to do things like this
11949 without the interaction of the window manager. Whatever you end up
f676886a 11950 doing with this code, do it to x_unfocus_frame too. */
334208b7 11951 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11952 RevertToPointerRoot, CurrentTime);
c118dd06 11953#endif /* ! 0 */
dc6f92b8
JB
11954}
11955
dfcf069d 11956void
f676886a
JB
11957x_unfocus_frame (f)
11958 struct frame *f;
dc6f92b8 11959{
6d4238f3 11960#if 0
f676886a 11961 /* Look at the remarks in x_focus_on_frame. */
0f941935 11962 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11963 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11964 RevertToPointerRoot, CurrentTime);
c118dd06 11965#endif /* ! 0 */
dc6f92b8
JB
11966}
11967
f676886a 11968/* Raise frame F. */
dc6f92b8 11969
dfcf069d 11970void
f676886a
JB
11971x_raise_frame (f)
11972 struct frame *f;
dc6f92b8 11973{
3a88c238 11974 if (f->async_visible)
dc6f92b8
JB
11975 {
11976 BLOCK_INPUT;
3afe33e7 11977#ifdef USE_X_TOOLKIT
7556890b 11978 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11979#else /* not USE_X_TOOLKIT */
334208b7 11980 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11981#endif /* not USE_X_TOOLKIT */
334208b7 11982 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11983 UNBLOCK_INPUT;
11984 }
11985}
11986
f676886a 11987/* Lower frame F. */
dc6f92b8 11988
dfcf069d 11989void
f676886a
JB
11990x_lower_frame (f)
11991 struct frame *f;
dc6f92b8 11992{
3a88c238 11993 if (f->async_visible)
dc6f92b8
JB
11994 {
11995 BLOCK_INPUT;
3afe33e7 11996#ifdef USE_X_TOOLKIT
7556890b 11997 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11998#else /* not USE_X_TOOLKIT */
334208b7 11999 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12000#endif /* not USE_X_TOOLKIT */
334208b7 12001 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12002 UNBLOCK_INPUT;
12003 }
12004}
12005
dbc4e1c1 12006static void
6b0442dc 12007XTframe_raise_lower (f, raise_flag)
dbc4e1c1 12008 FRAME_PTR f;
6b0442dc 12009 int raise_flag;
dbc4e1c1 12010{
6b0442dc 12011 if (raise_flag)
dbc4e1c1
JB
12012 x_raise_frame (f);
12013 else
12014 x_lower_frame (f);
12015}
d047c4eb
KH
12016\f
12017/* Change of visibility. */
dc6f92b8 12018
9382638d
KH
12019/* This tries to wait until the frame is really visible.
12020 However, if the window manager asks the user where to position
12021 the frame, this will return before the user finishes doing that.
12022 The frame will not actually be visible at that time,
12023 but it will become visible later when the window manager
12024 finishes with it. */
12025
dfcf069d 12026void
f676886a
JB
12027x_make_frame_visible (f)
12028 struct frame *f;
dc6f92b8 12029{
990ba854 12030 Lisp_Object type;
1aa6072f 12031 int original_top, original_left;
31be9251
GM
12032 int retry_count = 2;
12033
12034 retry:
dc6f92b8 12035
dc6f92b8 12036 BLOCK_INPUT;
dc6f92b8 12037
990ba854
RS
12038 type = x_icon_type (f);
12039 if (!NILP (type))
12040 x_bitmap_icon (f, type);
bdcd49ba 12041
f676886a 12042 if (! FRAME_VISIBLE_P (f))
90e65f07 12043 {
1aa6072f
RS
12044 /* We test FRAME_GARBAGED_P here to make sure we don't
12045 call x_set_offset a second time
12046 if we get to x_make_frame_visible a second time
12047 before the window gets really visible. */
12048 if (! FRAME_ICONIFIED_P (f)
12049 && ! f->output_data.x->asked_for_visible)
12050 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12051
12052 f->output_data.x->asked_for_visible = 1;
12053
90e65f07 12054 if (! EQ (Vx_no_window_manager, Qt))
f676886a 12055 x_wm_set_window_state (f, NormalState);
3afe33e7 12056#ifdef USE_X_TOOLKIT
d7a38a2e 12057 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12058 XtMapWidget (f->output_data.x->widget);
3afe33e7 12059#else /* not USE_X_TOOLKIT */
7f9c7f94 12060 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12061#endif /* not USE_X_TOOLKIT */
0134a210
RS
12062#if 0 /* This seems to bring back scroll bars in the wrong places
12063 if the window configuration has changed. They seem
12064 to come back ok without this. */
ab648270 12065 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 12066 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 12067#endif
90e65f07 12068 }
dc6f92b8 12069
334208b7 12070 XFlush (FRAME_X_DISPLAY (f));
90e65f07 12071
0dacf791
RS
12072 /* Synchronize to ensure Emacs knows the frame is visible
12073 before we do anything else. We do this loop with input not blocked
12074 so that incoming events are handled. */
12075 {
12076 Lisp_Object frame;
12ce2351 12077 int count;
28c01ffe
RS
12078 /* This must be before UNBLOCK_INPUT
12079 since events that arrive in response to the actions above
12080 will set it when they are handled. */
12081 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
12082
12083 original_left = f->output_data.x->left_pos;
12084 original_top = f->output_data.x->top_pos;
c0a04927
RS
12085
12086 /* This must come after we set COUNT. */
12087 UNBLOCK_INPUT;
12088
2745e6c4 12089 /* We unblock here so that arriving X events are processed. */
1aa6072f 12090
dcb07ae9
RS
12091 /* Now move the window back to where it was "supposed to be".
12092 But don't do it if the gravity is negative.
12093 When the gravity is negative, this uses a position
28c01ffe
RS
12094 that is 3 pixels too low. Perhaps that's really the border width.
12095
12096 Don't do this if the window has never been visible before,
12097 because the window manager may choose the position
12098 and we don't want to override it. */
1aa6072f 12099
4d3f5d9a 12100 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 12101 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 12102 && previously_visible)
1aa6072f 12103 {
2745e6c4
RS
12104 Drawable rootw;
12105 int x, y;
12106 unsigned int width, height, border, depth;
06a2c219 12107
1aa6072f 12108 BLOCK_INPUT;
9829ddba 12109
06a2c219
GM
12110 /* On some window managers (such as FVWM) moving an existing
12111 window, even to the same place, causes the window manager
12112 to introduce an offset. This can cause the window to move
12113 to an unexpected location. Check the geometry (a little
12114 slow here) and then verify that the window is in the right
12115 place. If the window is not in the right place, move it
12116 there, and take the potential window manager hit. */
2745e6c4
RS
12117 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12118 &rootw, &x, &y, &width, &height, &border, &depth);
12119
12120 if (original_left != x || original_top != y)
12121 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12122 original_left, original_top);
12123
1aa6072f
RS
12124 UNBLOCK_INPUT;
12125 }
9829ddba 12126
e0c1aef2 12127 XSETFRAME (frame, f);
c0a04927 12128
12ce2351
GM
12129 /* Wait until the frame is visible. Process X events until a
12130 MapNotify event has been seen, or until we think we won't get a
12131 MapNotify at all.. */
12132 for (count = input_signal_count + 10;
12133 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 12134 {
12ce2351 12135 /* Force processing of queued events. */
334208b7 12136 x_sync (f);
12ce2351
GM
12137
12138 /* Machines that do polling rather than SIGIO have been
12139 observed to go into a busy-wait here. So we'll fake an
12140 alarm signal to let the handler know that there's something
12141 to be read. We used to raise a real alarm, but it seems
12142 that the handler isn't always enabled here. This is
12143 probably a bug. */
8b2f8d4e 12144 if (input_polling_used ())
3b2fa4e6 12145 {
12ce2351
GM
12146 /* It could be confusing if a real alarm arrives while
12147 processing the fake one. Turn it off and let the
12148 handler reset it. */
3e71d8f2 12149 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
12150 int old_poll_suppress_count = poll_suppress_count;
12151 poll_suppress_count = 1;
12152 poll_for_input_1 ();
12153 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 12154 }
12ce2351
GM
12155
12156 /* See if a MapNotify event has been processed. */
12157 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 12158 }
31be9251
GM
12159
12160 /* 2000-09-28: In
12161
12162 (let ((f (selected-frame)))
12163 (iconify-frame f)
12164 (raise-frame f))
12165
12166 the frame is not raised with various window managers on
12167 FreeBSD, Linux and Solaris. It turns out that, for some
12168 unknown reason, the call to XtMapWidget is completely ignored.
12169 Mapping the widget a second time works. */
12170
12171 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12172 goto retry;
0dacf791 12173 }
dc6f92b8
JB
12174}
12175
06a2c219 12176/* Change from mapped state to withdrawn state. */
dc6f92b8 12177
d047c4eb
KH
12178/* Make the frame visible (mapped and not iconified). */
12179
dfcf069d 12180void
f676886a
JB
12181x_make_frame_invisible (f)
12182 struct frame *f;
dc6f92b8 12183{
546e6d5b
RS
12184 Window window;
12185
12186#ifdef USE_X_TOOLKIT
12187 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 12188 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
12189#else /* not USE_X_TOOLKIT */
12190 window = FRAME_X_WINDOW (f);
12191#endif /* not USE_X_TOOLKIT */
dc6f92b8 12192
9319ae23 12193 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12194 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12195 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12196
5627c40e 12197#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 12198 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 12199 return;
5627c40e 12200#endif
dc6f92b8
JB
12201
12202 BLOCK_INPUT;
c118dd06 12203
af31d76f
RS
12204 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12205 that the current position of the window is user-specified, rather than
12206 program-specified, so that when the window is mapped again, it will be
12207 placed at the same location, without forcing the user to position it
12208 by hand again (they have already done that once for this window.) */
c32cdd9a 12209 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 12210
c118dd06
JB
12211#ifdef HAVE_X11R4
12212
334208b7
RS
12213 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12214 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
12215 {
12216 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12217 error ("Can't notify window manager of window withdrawal");
c118dd06 12218 }
c118dd06 12219#else /* ! defined (HAVE_X11R4) */
16bd92ea 12220
c118dd06 12221 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
12222 if (! EQ (Vx_no_window_manager, Qt))
12223 {
16bd92ea 12224 XEvent unmap;
dc6f92b8 12225
16bd92ea 12226 unmap.xunmap.type = UnmapNotify;
546e6d5b 12227 unmap.xunmap.window = window;
334208b7 12228 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 12229 unmap.xunmap.from_configure = False;
334208b7
RS
12230 if (! XSendEvent (FRAME_X_DISPLAY (f),
12231 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 12232 False,
06a2c219 12233 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
12234 &unmap))
12235 {
12236 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12237 error ("Can't notify window manager of withdrawal");
16bd92ea 12238 }
dc6f92b8
JB
12239 }
12240
16bd92ea 12241 /* Unmap the window ourselves. Cheeky! */
334208b7 12242 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 12243#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 12244
5627c40e
RS
12245 /* We can't distinguish this from iconification
12246 just by the event that we get from the server.
12247 So we can't win using the usual strategy of letting
12248 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12249 and synchronize with the server to make sure we agree. */
12250 f->visible = 0;
12251 FRAME_ICONIFIED_P (f) = 0;
12252 f->async_visible = 0;
12253 f->async_iconified = 0;
12254
334208b7 12255 x_sync (f);
5627c40e 12256
dc6f92b8
JB
12257 UNBLOCK_INPUT;
12258}
12259
06a2c219 12260/* Change window state from mapped to iconified. */
dc6f92b8 12261
dfcf069d 12262void
f676886a
JB
12263x_iconify_frame (f)
12264 struct frame *f;
dc6f92b8 12265{
3afe33e7 12266 int result;
990ba854 12267 Lisp_Object type;
dc6f92b8 12268
9319ae23 12269 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12270 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12271 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12272
3a88c238 12273 if (f->async_iconified)
dc6f92b8
JB
12274 return;
12275
3afe33e7 12276 BLOCK_INPUT;
546e6d5b 12277
9af3143a
RS
12278 FRAME_SAMPLE_VISIBILITY (f);
12279
990ba854
RS
12280 type = x_icon_type (f);
12281 if (!NILP (type))
12282 x_bitmap_icon (f, type);
bdcd49ba
RS
12283
12284#ifdef USE_X_TOOLKIT
12285
546e6d5b
RS
12286 if (! FRAME_VISIBLE_P (f))
12287 {
12288 if (! EQ (Vx_no_window_manager, Qt))
12289 x_wm_set_window_state (f, IconicState);
12290 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12291 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
12292 /* The server won't give us any event to indicate
12293 that an invisible frame was changed to an icon,
12294 so we have to record it here. */
12295 f->iconified = 1;
1e6bc770 12296 f->visible = 1;
9cf30a30 12297 f->async_iconified = 1;
1e6bc770 12298 f->async_visible = 0;
546e6d5b
RS
12299 UNBLOCK_INPUT;
12300 return;
12301 }
12302
334208b7 12303 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 12304 XtWindow (f->output_data.x->widget),
334208b7 12305 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
12306 UNBLOCK_INPUT;
12307
12308 if (!result)
546e6d5b 12309 error ("Can't notify window manager of iconification");
3afe33e7
RS
12310
12311 f->async_iconified = 1;
1e6bc770
RS
12312 f->async_visible = 0;
12313
8c002a25
KH
12314
12315 BLOCK_INPUT;
334208b7 12316 XFlush (FRAME_X_DISPLAY (f));
8c002a25 12317 UNBLOCK_INPUT;
3afe33e7
RS
12318#else /* not USE_X_TOOLKIT */
12319
fd13dbb2
RS
12320 /* Make sure the X server knows where the window should be positioned,
12321 in case the user deiconifies with the window manager. */
12322 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 12323 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 12324
16bd92ea
JB
12325 /* Since we don't know which revision of X we're running, we'll use both
12326 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12327
12328 /* X11R4: send a ClientMessage to the window manager using the
12329 WM_CHANGE_STATE type. */
12330 {
12331 XEvent message;
58769bee 12332
c118dd06 12333 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 12334 message.xclient.type = ClientMessage;
334208b7 12335 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
12336 message.xclient.format = 32;
12337 message.xclient.data.l[0] = IconicState;
12338
334208b7
RS
12339 if (! XSendEvent (FRAME_X_DISPLAY (f),
12340 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
12341 False,
12342 SubstructureRedirectMask | SubstructureNotifyMask,
12343 &message))
dc6f92b8
JB
12344 {
12345 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12346 error ("Can't notify window manager of iconification");
dc6f92b8 12347 }
16bd92ea 12348 }
dc6f92b8 12349
58769bee 12350 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
12351 IconicState. */
12352 x_wm_set_window_state (f, IconicState);
dc6f92b8 12353
a9c00105
RS
12354 if (!FRAME_VISIBLE_P (f))
12355 {
12356 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 12357 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
12358 }
12359
3a88c238 12360 f->async_iconified = 1;
1e6bc770 12361 f->async_visible = 0;
dc6f92b8 12362
334208b7 12363 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 12364 UNBLOCK_INPUT;
8c002a25 12365#endif /* not USE_X_TOOLKIT */
dc6f92b8 12366}
d047c4eb 12367\f
c0ff3fab 12368/* Destroy the X window of frame F. */
dc6f92b8 12369
dfcf069d 12370void
c0ff3fab 12371x_destroy_window (f)
f676886a 12372 struct frame *f;
dc6f92b8 12373{
7f9c7f94
RS
12374 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12375
dc6f92b8 12376 BLOCK_INPUT;
c0ff3fab 12377
6186a4a0
RS
12378 /* If a display connection is dead, don't try sending more
12379 commands to the X server. */
12380 if (dpyinfo->display != 0)
12381 {
12382 if (f->output_data.x->icon_desc != 0)
12383 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 12384#ifdef HAVE_X_I18N
f5d11644
GM
12385 if (FRAME_XIC (f))
12386 free_frame_xic (f);
31f41daf 12387#endif
6186a4a0 12388 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 12389#ifdef USE_X_TOOLKIT
06a2c219
GM
12390 if (f->output_data.x->widget)
12391 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12392 free_frame_menubar (f);
3afe33e7
RS
12393#endif /* USE_X_TOOLKIT */
12394
3e71d8f2
GM
12395 unload_color (f, f->output_data.x->foreground_pixel);
12396 unload_color (f, f->output_data.x->background_pixel);
12397 unload_color (f, f->output_data.x->cursor_pixel);
12398 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12399 unload_color (f, f->output_data.x->border_pixel);
12400 unload_color (f, f->output_data.x->mouse_pixel);
12401 if (f->output_data.x->scroll_bar_background_pixel != -1)
12402 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12403 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12404 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12405 if (f->output_data.x->white_relief.allocated_p)
12406 unload_color (f, f->output_data.x->white_relief.pixel);
12407 if (f->output_data.x->black_relief.allocated_p)
12408 unload_color (f, f->output_data.x->black_relief.pixel);
12409
6186a4a0
RS
12410 free_frame_faces (f);
12411 XFlush (FRAME_X_DISPLAY (f));
12412 }
dc6f92b8 12413
df89d8a4 12414 if (f->output_data.x->saved_menu_event)
06a2c219 12415 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12416
7556890b
RS
12417 xfree (f->output_data.x);
12418 f->output_data.x = 0;
0f941935
KH
12419 if (f == dpyinfo->x_focus_frame)
12420 dpyinfo->x_focus_frame = 0;
12421 if (f == dpyinfo->x_focus_event_frame)
12422 dpyinfo->x_focus_event_frame = 0;
12423 if (f == dpyinfo->x_highlight_frame)
12424 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12425
7f9c7f94
RS
12426 dpyinfo->reference_count--;
12427
12428 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12429 {
7f9c7f94
RS
12430 dpyinfo->mouse_face_beg_row
12431 = dpyinfo->mouse_face_beg_col = -1;
12432 dpyinfo->mouse_face_end_row
12433 = dpyinfo->mouse_face_end_col = -1;
12434 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12435 dpyinfo->mouse_face_deferred_gc = 0;
12436 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12437 }
0134a210 12438
c0ff3fab 12439 UNBLOCK_INPUT;
dc6f92b8
JB
12440}
12441\f
f451eb13
JB
12442/* Setting window manager hints. */
12443
af31d76f
RS
12444/* Set the normal size hints for the window manager, for frame F.
12445 FLAGS is the flags word to use--or 0 meaning preserve the flags
12446 that the window now has.
12447 If USER_POSITION is nonzero, we set the USPosition
12448 flag (this is useful when FLAGS is 0). */
6dba1858 12449
dfcf069d 12450void
af31d76f 12451x_wm_set_size_hint (f, flags, user_position)
f676886a 12452 struct frame *f;
af31d76f
RS
12453 long flags;
12454 int user_position;
dc6f92b8
JB
12455{
12456 XSizeHints size_hints;
3afe33e7
RS
12457
12458#ifdef USE_X_TOOLKIT
7e4f2521
FP
12459 Arg al[2];
12460 int ac = 0;
12461 Dimension widget_width, widget_height;
7556890b 12462 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12463#else /* not USE_X_TOOLKIT */
c118dd06 12464 Window window = FRAME_X_WINDOW (f);
3afe33e7 12465#endif /* not USE_X_TOOLKIT */
dc6f92b8 12466
b72a58fd
RS
12467 /* Setting PMaxSize caused various problems. */
12468 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12469
7556890b
RS
12470 size_hints.x = f->output_data.x->left_pos;
12471 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12472
7e4f2521
FP
12473#ifdef USE_X_TOOLKIT
12474 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12475 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12476 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12477 size_hints.height = widget_height;
12478 size_hints.width = widget_width;
12479#else /* not USE_X_TOOLKIT */
f676886a
JB
12480 size_hints.height = PIXEL_HEIGHT (f);
12481 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12482#endif /* not USE_X_TOOLKIT */
7553a6b7 12483
7556890b
RS
12484 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12485 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12486 size_hints.max_width
12487 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12488 size_hints.max_height
12489 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12490
d067ea8b
KH
12491 /* Calculate the base and minimum sizes.
12492
12493 (When we use the X toolkit, we don't do it here.
12494 Instead we copy the values that the widgets are using, below.) */
12495#ifndef USE_X_TOOLKIT
b1c884c3 12496 {
b0342f17 12497 int base_width, base_height;
0134a210 12498 int min_rows = 0, min_cols = 0;
b0342f17 12499
f451eb13
JB
12500 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12501 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12502
0134a210 12503 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12504
0134a210
RS
12505 /* The window manager uses the base width hints to calculate the
12506 current number of rows and columns in the frame while
12507 resizing; min_width and min_height aren't useful for this
12508 purpose, since they might not give the dimensions for a
12509 zero-row, zero-column frame.
58769bee 12510
0134a210
RS
12511 We use the base_width and base_height members if we have
12512 them; otherwise, we set the min_width and min_height members
12513 to the size for a zero x zero frame. */
b0342f17
JB
12514
12515#ifdef HAVE_X11R4
0134a210
RS
12516 size_hints.flags |= PBaseSize;
12517 size_hints.base_width = base_width;
12518 size_hints.base_height = base_height;
12519 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12520 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12521#else
0134a210
RS
12522 size_hints.min_width = base_width;
12523 size_hints.min_height = base_height;
b0342f17 12524#endif
b1c884c3 12525 }
dc6f92b8 12526
d067ea8b 12527 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12528 if (flags)
dc6f92b8 12529 {
d067ea8b
KH
12530 size_hints.flags |= flags;
12531 goto no_read;
12532 }
12533#endif /* not USE_X_TOOLKIT */
12534
12535 {
12536 XSizeHints hints; /* Sometimes I hate X Windows... */
12537 long supplied_return;
12538 int value;
af31d76f
RS
12539
12540#ifdef HAVE_X11R4
d067ea8b
KH
12541 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12542 &supplied_return);
af31d76f 12543#else
d067ea8b 12544 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12545#endif
58769bee 12546
d067ea8b
KH
12547#ifdef USE_X_TOOLKIT
12548 size_hints.base_height = hints.base_height;
12549 size_hints.base_width = hints.base_width;
12550 size_hints.min_height = hints.min_height;
12551 size_hints.min_width = hints.min_width;
12552#endif
12553
12554 if (flags)
12555 size_hints.flags |= flags;
12556 else
12557 {
12558 if (value == 0)
12559 hints.flags = 0;
12560 if (hints.flags & PSize)
12561 size_hints.flags |= PSize;
12562 if (hints.flags & PPosition)
12563 size_hints.flags |= PPosition;
12564 if (hints.flags & USPosition)
12565 size_hints.flags |= USPosition;
12566 if (hints.flags & USSize)
12567 size_hints.flags |= USSize;
12568 }
12569 }
12570
06a2c219 12571#ifndef USE_X_TOOLKIT
d067ea8b 12572 no_read:
06a2c219 12573#endif
0134a210 12574
af31d76f 12575#ifdef PWinGravity
7556890b 12576 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12577 size_hints.flags |= PWinGravity;
dc05a16b 12578
af31d76f 12579 if (user_position)
6dba1858 12580 {
af31d76f
RS
12581 size_hints.flags &= ~ PPosition;
12582 size_hints.flags |= USPosition;
6dba1858 12583 }
2554751d 12584#endif /* PWinGravity */
6dba1858 12585
b0342f17 12586#ifdef HAVE_X11R4
334208b7 12587 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12588#else
334208b7 12589 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12590#endif
dc6f92b8
JB
12591}
12592
12593/* Used for IconicState or NormalState */
06a2c219 12594
dfcf069d 12595void
f676886a
JB
12596x_wm_set_window_state (f, state)
12597 struct frame *f;
dc6f92b8
JB
12598 int state;
12599{
3afe33e7 12600#ifdef USE_X_TOOLKIT
546e6d5b
RS
12601 Arg al[1];
12602
12603 XtSetArg (al[0], XtNinitialState, state);
7556890b 12604 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12605#else /* not USE_X_TOOLKIT */
c118dd06 12606 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12607
7556890b
RS
12608 f->output_data.x->wm_hints.flags |= StateHint;
12609 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12610
7556890b 12611 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12612#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12613}
12614
dfcf069d 12615void
7f2ae036 12616x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12617 struct frame *f;
7f2ae036 12618 int pixmap_id;
dc6f92b8 12619{
d2bd6bc4
RS
12620 Pixmap icon_pixmap;
12621
06a2c219 12622#ifndef USE_X_TOOLKIT
c118dd06 12623 Window window = FRAME_X_WINDOW (f);
75231bad 12624#endif
dc6f92b8 12625
7f2ae036 12626 if (pixmap_id > 0)
dbc4e1c1 12627 {
d2bd6bc4 12628 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12629 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12630 }
12631 else
68568555
RS
12632 {
12633 /* It seems there is no way to turn off use of an icon pixmap.
12634 The following line does it, only if no icon has yet been created,
12635 for some window managers. But with mwm it crashes.
12636 Some people say it should clear the IconPixmapHint bit in this case,
12637 but that doesn't work, and the X consortium said it isn't the
12638 right thing at all. Since there is no way to win,
12639 best to explicitly give up. */
12640#if 0
12641 f->output_data.x->wm_hints.icon_pixmap = None;
12642#else
12643 return;
12644#endif
12645 }
b1c884c3 12646
d2bd6bc4
RS
12647#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12648
12649 {
12650 Arg al[1];
12651 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12652 XtSetValues (f->output_data.x->widget, al, 1);
12653 }
12654
12655#else /* not USE_X_TOOLKIT */
12656
7556890b
RS
12657 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12658 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12659
12660#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12661}
12662
dfcf069d 12663void
f676886a
JB
12664x_wm_set_icon_position (f, icon_x, icon_y)
12665 struct frame *f;
dc6f92b8
JB
12666 int icon_x, icon_y;
12667{
75231bad 12668#ifdef USE_X_TOOLKIT
7556890b 12669 Window window = XtWindow (f->output_data.x->widget);
75231bad 12670#else
c118dd06 12671 Window window = FRAME_X_WINDOW (f);
75231bad 12672#endif
dc6f92b8 12673
7556890b
RS
12674 f->output_data.x->wm_hints.flags |= IconPositionHint;
12675 f->output_data.x->wm_hints.icon_x = icon_x;
12676 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12677
7556890b 12678 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12679}
12680
12681\f
06a2c219
GM
12682/***********************************************************************
12683 Fonts
12684 ***********************************************************************/
dc43ef94
KH
12685
12686/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12687
dc43ef94
KH
12688struct font_info *
12689x_get_font_info (f, font_idx)
12690 FRAME_PTR f;
12691 int font_idx;
12692{
12693 return (FRAME_X_FONT_TABLE (f) + font_idx);
12694}
12695
12696
12697/* Return a list of names of available fonts matching PATTERN on frame
12698 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12699 to be listed. Frame F NULL means we have not yet created any
12700 frame on X, and consult the first display in x_display_list.
12701 MAXNAMES sets a limit on how many fonts to match. */
12702
12703Lisp_Object
12704x_list_fonts (f, pattern, size, maxnames)
12705 FRAME_PTR f;
12706 Lisp_Object pattern;
12707 int size;
12708 int maxnames;
12709{
06a2c219
GM
12710 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12711 Lisp_Object tem, second_best;
dc43ef94 12712 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12713 int try_XLoadQueryFont = 0;
53ca4657 12714 int count;
dc43ef94 12715
6b0efe73 12716 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12717 if (NILP (patterns))
12718 patterns = Fcons (pattern, Qnil);
81ba44e5 12719
09c6077f
KH
12720 if (maxnames == 1 && !size)
12721 /* We can return any single font matching PATTERN. */
12722 try_XLoadQueryFont = 1;
9a32686f 12723
8e713be6 12724 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12725 {
dc43ef94 12726 int num_fonts;
3e71d8f2 12727 char **names = NULL;
dc43ef94 12728
8e713be6 12729 pattern = XCAR (patterns);
536f4067
RS
12730 /* See if we cached the result for this particular query.
12731 The cache is an alist of the form:
12732 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12733 */
8e713be6 12734 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12735 key = Fcons (pattern, make_number (maxnames)),
12736 !NILP (list = Fassoc (key, tem))))
12737 {
12738 list = Fcdr_safe (list);
12739 /* We have a cashed list. Don't have to get the list again. */
12740 goto label_cached;
12741 }
12742
12743 /* At first, put PATTERN in the cache. */
09c6077f 12744
dc43ef94 12745 BLOCK_INPUT;
17d85edc
KH
12746 count = x_catch_errors (dpy);
12747
09c6077f
KH
12748 if (try_XLoadQueryFont)
12749 {
12750 XFontStruct *font;
12751 unsigned long value;
12752
12753 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12754 if (x_had_errors_p (dpy))
12755 {
12756 /* This error is perhaps due to insufficient memory on X
12757 server. Let's just ignore it. */
12758 font = NULL;
12759 x_clear_errors (dpy);
12760 }
12761
09c6077f
KH
12762 if (font
12763 && XGetFontProperty (font, XA_FONT, &value))
12764 {
12765 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12766 int len = strlen (name);
01c752b5 12767 char *tmp;
09c6077f 12768
6f6512e8
KH
12769 /* If DXPC (a Differential X Protocol Compressor)
12770 Ver.3.7 is running, XGetAtomName will return null
12771 string. We must avoid such a name. */
12772 if (len == 0)
12773 try_XLoadQueryFont = 0;
12774 else
12775 {
12776 num_fonts = 1;
12777 names = (char **) alloca (sizeof (char *));
12778 /* Some systems only allow alloca assigned to a
12779 simple var. */
12780 tmp = (char *) alloca (len + 1); names[0] = tmp;
12781 bcopy (name, names[0], len + 1);
12782 XFree (name);
12783 }
09c6077f
KH
12784 }
12785 else
12786 try_XLoadQueryFont = 0;
a083fd23
RS
12787
12788 if (font)
12789 XFreeFont (dpy, font);
09c6077f
KH
12790 }
12791
12792 if (!try_XLoadQueryFont)
17d85edc
KH
12793 {
12794 /* We try at least 10 fonts because XListFonts will return
12795 auto-scaled fonts at the head. */
12796 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12797 &num_fonts);
12798 if (x_had_errors_p (dpy))
12799 {
12800 /* This error is perhaps due to insufficient memory on X
12801 server. Let's just ignore it. */
12802 names = NULL;
12803 x_clear_errors (dpy);
12804 }
12805 }
12806
12807 x_uncatch_errors (dpy, count);
dc43ef94
KH
12808 UNBLOCK_INPUT;
12809
12810 if (names)
12811 {
12812 int i;
dc43ef94
KH
12813
12814 /* Make a list of all the fonts we got back.
12815 Store that in the font cache for the display. */
12816 for (i = 0; i < num_fonts; i++)
12817 {
06a2c219 12818 int width = 0;
dc43ef94 12819 char *p = names[i];
06a2c219
GM
12820 int average_width = -1, dashes = 0;
12821
dc43ef94 12822 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12823 14 dashes, and the field value following 12th dash
12824 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12825 is usually too ugly to be used for editing. Let's
12826 ignore it. */
dc43ef94
KH
12827 while (*p)
12828 if (*p++ == '-')
12829 {
12830 dashes++;
12831 if (dashes == 7) /* PIXEL_SIZE field */
12832 width = atoi (p);
12833 else if (dashes == 12) /* AVERAGE_WIDTH field */
12834 average_width = atoi (p);
12835 }
12836 if (dashes < 14 || average_width != 0)
12837 {
12838 tem = build_string (names[i]);
12839 if (NILP (Fassoc (tem, list)))
12840 {
12841 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12842 && ((fast_c_string_match_ignore_case
12843 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12844 >= 0))
12845 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12846 width of this font. */
dc43ef94
KH
12847 list = Fcons (Fcons (tem, make_number (width)), list);
12848 else
12849 /* For the moment, width is not known. */
12850 list = Fcons (Fcons (tem, Qnil), list);
12851 }
12852 }
12853 }
09c6077f
KH
12854 if (!try_XLoadQueryFont)
12855 XFreeFontNames (names);
dc43ef94
KH
12856 }
12857
b5210ea7 12858 /* Now store the result in the cache. */
dc43ef94 12859 if (f != NULL)
8e713be6 12860 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12861 = Fcons (Fcons (key, list),
8e713be6 12862 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12863
b5210ea7
KH
12864 label_cached:
12865 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12866
b5210ea7
KH
12867 newlist = second_best = Qnil;
12868 /* Make a list of the fonts that have the right width. */
8e713be6 12869 for (; CONSP (list); list = XCDR (list))
b5210ea7 12870 {
536f4067
RS
12871 int found_size;
12872
8e713be6 12873 tem = XCAR (list);
dc43ef94 12874
8e713be6 12875 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12876 continue;
12877 if (!size)
12878 {
8e713be6 12879 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12880 continue;
12881 }
dc43ef94 12882
8e713be6 12883 if (!INTEGERP (XCDR (tem)))
dc43ef94 12884 {
b5210ea7
KH
12885 /* Since we have not yet known the size of this font, we
12886 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12887 XFontStruct *thisinfo;
12888
12889 BLOCK_INPUT;
17d85edc 12890 count = x_catch_errors (dpy);
dc43ef94 12891 thisinfo = XLoadQueryFont (dpy,
8e713be6 12892 XSTRING (XCAR (tem))->data);
17d85edc
KH
12893 if (x_had_errors_p (dpy))
12894 {
12895 /* This error is perhaps due to insufficient memory on X
12896 server. Let's just ignore it. */
12897 thisinfo = NULL;
12898 x_clear_errors (dpy);
12899 }
12900 x_uncatch_errors (dpy, count);
dc43ef94
KH
12901 UNBLOCK_INPUT;
12902
12903 if (thisinfo)
12904 {
8e713be6 12905 XCDR (tem)
536f4067
RS
12906 = (thisinfo->min_bounds.width == 0
12907 ? make_number (0)
12908 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12909 XFreeFont (dpy, thisinfo);
12910 }
12911 else
b5210ea7 12912 /* For unknown reason, the previous call of XListFont had
06a2c219 12913 returned a font which can't be opened. Record the size
b5210ea7 12914 as 0 not to try to open it again. */
8e713be6 12915 XCDR (tem) = make_number (0);
dc43ef94 12916 }
536f4067 12917
8e713be6 12918 found_size = XINT (XCDR (tem));
536f4067 12919 if (found_size == size)
8e713be6 12920 newlist = Fcons (XCAR (tem), newlist);
536f4067 12921 else if (found_size > 0)
b5210ea7 12922 {
536f4067 12923 if (NILP (second_best))
b5210ea7 12924 second_best = tem;
536f4067
RS
12925 else if (found_size < size)
12926 {
8e713be6
KR
12927 if (XINT (XCDR (second_best)) > size
12928 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12929 second_best = tem;
12930 }
12931 else
12932 {
8e713be6
KR
12933 if (XINT (XCDR (second_best)) > size
12934 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12935 second_best = tem;
12936 }
b5210ea7
KH
12937 }
12938 }
12939 if (!NILP (newlist))
12940 break;
12941 else if (!NILP (second_best))
12942 {
8e713be6 12943 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12944 break;
dc43ef94 12945 }
dc43ef94
KH
12946 }
12947
12948 return newlist;
12949}
12950
06a2c219
GM
12951
12952#if GLYPH_DEBUG
12953
12954/* Check that FONT is valid on frame F. It is if it can be found in F's
12955 font table. */
12956
12957static void
12958x_check_font (f, font)
12959 struct frame *f;
12960 XFontStruct *font;
12961{
12962 int i;
12963 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12964
12965 xassert (font != NULL);
12966
12967 for (i = 0; i < dpyinfo->n_fonts; i++)
12968 if (dpyinfo->font_table[i].name
12969 && font == dpyinfo->font_table[i].font)
12970 break;
12971
12972 xassert (i < dpyinfo->n_fonts);
12973}
12974
12975#endif /* GLYPH_DEBUG != 0 */
12976
12977/* Set *W to the minimum width, *H to the minimum font height of FONT.
12978 Note: There are (broken) X fonts out there with invalid XFontStruct
12979 min_bounds contents. For example, handa@etl.go.jp reports that
12980 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12981 have font->min_bounds.width == 0. */
12982
12983static INLINE void
12984x_font_min_bounds (font, w, h)
12985 XFontStruct *font;
12986 int *w, *h;
12987{
12988 *h = FONT_HEIGHT (font);
12989 *w = font->min_bounds.width;
12990
12991 /* Try to handle the case where FONT->min_bounds has invalid
12992 contents. Since the only font known to have invalid min_bounds
12993 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12994 if (*w <= 0)
12995 *w = font->max_bounds.width;
12996}
12997
12998
12999/* Compute the smallest character width and smallest font height over
13000 all fonts available on frame F. Set the members smallest_char_width
13001 and smallest_font_height in F's x_display_info structure to
13002 the values computed. Value is non-zero if smallest_font_height or
13003 smallest_char_width become smaller than they were before. */
13004
13005static int
13006x_compute_min_glyph_bounds (f)
13007 struct frame *f;
13008{
13009 int i;
13010 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13011 XFontStruct *font;
13012 int old_width = dpyinfo->smallest_char_width;
13013 int old_height = dpyinfo->smallest_font_height;
13014
13015 dpyinfo->smallest_font_height = 100000;
13016 dpyinfo->smallest_char_width = 100000;
13017
13018 for (i = 0; i < dpyinfo->n_fonts; ++i)
13019 if (dpyinfo->font_table[i].name)
13020 {
13021 struct font_info *fontp = dpyinfo->font_table + i;
13022 int w, h;
13023
13024 font = (XFontStruct *) fontp->font;
13025 xassert (font != (XFontStruct *) ~0);
13026 x_font_min_bounds (font, &w, &h);
13027
13028 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13029 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13030 }
13031
13032 xassert (dpyinfo->smallest_char_width > 0
13033 && dpyinfo->smallest_font_height > 0);
13034
13035 return (dpyinfo->n_fonts == 1
13036 || dpyinfo->smallest_char_width < old_width
13037 || dpyinfo->smallest_font_height < old_height);
13038}
13039
13040
dc43ef94
KH
13041/* Load font named FONTNAME of the size SIZE for frame F, and return a
13042 pointer to the structure font_info while allocating it dynamically.
13043 If SIZE is 0, load any size of font.
13044 If loading is failed, return NULL. */
13045
13046struct font_info *
13047x_load_font (f, fontname, size)
13048 struct frame *f;
13049 register char *fontname;
13050 int size;
13051{
13052 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13053 Lisp_Object font_names;
d645aaa4 13054 int count;
dc43ef94
KH
13055
13056 /* Get a list of all the fonts that match this name. Once we
13057 have a list of matching fonts, we compare them against the fonts
13058 we already have by comparing names. */
09c6077f 13059 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
13060
13061 if (!NILP (font_names))
13062 {
13063 Lisp_Object tail;
13064 int i;
13065
13066 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 13067 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
13068 if (dpyinfo->font_table[i].name
13069 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 13070 XSTRING (XCAR (tail))->data)
06a2c219 13071 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 13072 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
13073 return (dpyinfo->font_table + i);
13074 }
13075
13076 /* Load the font and add it to the table. */
13077 {
13078 char *full_name;
13079 XFontStruct *font;
13080 struct font_info *fontp;
13081 unsigned long value;
06a2c219 13082 int i;
dc43ef94 13083
2da424f1
KH
13084 /* If we have found fonts by x_list_font, load one of them. If
13085 not, we still try to load a font by the name given as FONTNAME
13086 because XListFonts (called in x_list_font) of some X server has
13087 a bug of not finding a font even if the font surely exists and
13088 is loadable by XLoadQueryFont. */
e1d6d5b9 13089 if (size > 0 && !NILP (font_names))
8e713be6 13090 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
13091
13092 BLOCK_INPUT;
d645aaa4 13093 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 13094 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
13095 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13096 {
13097 /* This error is perhaps due to insufficient memory on X
13098 server. Let's just ignore it. */
13099 font = NULL;
13100 x_clear_errors (FRAME_X_DISPLAY (f));
13101 }
13102 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 13103 UNBLOCK_INPUT;
b5210ea7 13104 if (!font)
dc43ef94
KH
13105 return NULL;
13106
06a2c219
GM
13107 /* Find a free slot in the font table. */
13108 for (i = 0; i < dpyinfo->n_fonts; ++i)
13109 if (dpyinfo->font_table[i].name == NULL)
13110 break;
13111
13112 /* If no free slot found, maybe enlarge the font table. */
13113 if (i == dpyinfo->n_fonts
13114 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 13115 {
06a2c219
GM
13116 int sz;
13117 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13118 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 13119 dpyinfo->font_table
06a2c219 13120 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
13121 }
13122
06a2c219
GM
13123 fontp = dpyinfo->font_table + i;
13124 if (i == dpyinfo->n_fonts)
13125 ++dpyinfo->n_fonts;
dc43ef94
KH
13126
13127 /* Now fill in the slots of *FONTP. */
13128 BLOCK_INPUT;
13129 fontp->font = font;
06a2c219 13130 fontp->font_idx = i;
dc43ef94
KH
13131 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13132 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13133
13134 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13135 full_name = 0;
13136 if (XGetFontProperty (font, XA_FONT, &value))
13137 {
13138 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13139 char *p = name;
13140 int dashes = 0;
13141
13142 /* Count the number of dashes in the "full name".
13143 If it is too few, this isn't really the font's full name,
13144 so don't use it.
13145 In X11R4, the fonts did not come with their canonical names
13146 stored in them. */
13147 while (*p)
13148 {
13149 if (*p == '-')
13150 dashes++;
13151 p++;
13152 }
13153
13154 if (dashes >= 13)
13155 {
13156 full_name = (char *) xmalloc (p - name + 1);
13157 bcopy (name, full_name, p - name + 1);
13158 }
13159
13160 XFree (name);
13161 }
13162
13163 if (full_name != 0)
13164 fontp->full_name = full_name;
13165 else
13166 fontp->full_name = fontp->name;
13167
13168 fontp->size = font->max_bounds.width;
d5749adb
KH
13169 fontp->height = FONT_HEIGHT (font);
13170 {
13171 /* For some font, ascent and descent in max_bounds field is
13172 larger than the above value. */
13173 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
13174 if (max_height > fontp->height)
74848a96 13175 fontp->height = max_height;
d5749adb 13176 }
dc43ef94 13177
2da424f1
KH
13178 if (NILP (font_names))
13179 {
13180 /* We come here because of a bug of XListFonts mentioned at
13181 the head of this block. Let's store this information in
13182 the cache for x_list_fonts. */
13183 Lisp_Object lispy_name = build_string (fontname);
13184 Lisp_Object lispy_full_name = build_string (fontp->full_name);
13185
8e713be6 13186 XCDR (dpyinfo->name_list_element)
2da424f1
KH
13187 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
13188 Fcons (Fcons (lispy_full_name,
13189 make_number (fontp->size)),
13190 Qnil)),
8e713be6 13191 XCDR (dpyinfo->name_list_element));
2da424f1 13192 if (full_name)
8e713be6 13193 XCDR (dpyinfo->name_list_element)
2da424f1
KH
13194 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13195 Fcons (Fcons (lispy_full_name,
13196 make_number (fontp->size)),
13197 Qnil)),
8e713be6 13198 XCDR (dpyinfo->name_list_element));
2da424f1
KH
13199 }
13200
dc43ef94
KH
13201 /* The slot `encoding' specifies how to map a character
13202 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
13203 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13204 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 13205 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 13206 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
13207 which is never used by any charset. If mapping can't be
13208 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
13209 fontp->encoding[1]
13210 = (font->max_byte1 == 0
13211 /* 1-byte font */
13212 ? (font->min_char_or_byte2 < 0x80
13213 ? (font->max_char_or_byte2 < 0x80
13214 ? 0 /* 0x20..0x7F */
8ff102bd 13215 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
13216 : 1) /* 0xA0..0xFF */
13217 /* 2-byte font */
13218 : (font->min_byte1 < 0x80
13219 ? (font->max_byte1 < 0x80
13220 ? (font->min_char_or_byte2 < 0x80
13221 ? (font->max_char_or_byte2 < 0x80
13222 ? 0 /* 0x2020..0x7F7F */
8ff102bd 13223 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 13224 : 3) /* 0x20A0..0x7FFF */
8ff102bd 13225 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
13226 : (font->min_char_or_byte2 < 0x80
13227 ? (font->max_char_or_byte2 < 0x80
13228 ? 2 /* 0xA020..0xFF7F */
8ff102bd 13229 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
13230 : 1))); /* 0xA0A0..0xFFFF */
13231
13232 fontp->baseline_offset
13233 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13234 ? (long) value : 0);
13235 fontp->relative_compose
13236 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13237 ? (long) value : 0);
f78798df
KH
13238 fontp->default_ascent
13239 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13240 ? (long) value : 0);
dc43ef94 13241
06a2c219
GM
13242 /* Set global flag fonts_changed_p to non-zero if the font loaded
13243 has a character with a smaller width than any other character
13244 before, or if the font loaded has a smalle>r height than any
13245 other font loaded before. If this happens, it will make a
13246 glyph matrix reallocation necessary. */
13247 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 13248 UNBLOCK_INPUT;
dc43ef94
KH
13249 return fontp;
13250 }
13251}
13252
06a2c219
GM
13253
13254/* Return a pointer to struct font_info of a font named FONTNAME for
13255 frame F. If no such font is loaded, return NULL. */
13256
dc43ef94
KH
13257struct font_info *
13258x_query_font (f, fontname)
13259 struct frame *f;
13260 register char *fontname;
13261{
13262 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13263 int i;
13264
13265 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
13266 if (dpyinfo->font_table[i].name
13267 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13268 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
13269 return (dpyinfo->font_table + i);
13270 return NULL;
13271}
13272
06a2c219
GM
13273
13274/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
13275 `encoder' of the structure. */
13276
13277void
13278x_find_ccl_program (fontp)
13279 struct font_info *fontp;
13280{
a42f54e6 13281 Lisp_Object list, elt;
a6582676 13282
f9b5db02 13283 elt = Qnil;
8e713be6 13284 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 13285 {
8e713be6 13286 elt = XCAR (list);
a6582676 13287 if (CONSP (elt)
8e713be6 13288 && STRINGP (XCAR (elt))
9f2feff6
KH
13289 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13290 >= 0)
13291 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13292 >= 0)))
a42f54e6
KH
13293 break;
13294 }
f9b5db02 13295
a42f54e6
KH
13296 if (! NILP (list))
13297 {
d27f8ca7
KH
13298 struct ccl_program *ccl
13299 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 13300
8e713be6 13301 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
13302 xfree (ccl);
13303 else
13304 fontp->font_encoder = ccl;
a6582676
KH
13305 }
13306}
13307
06a2c219 13308
dc43ef94 13309\f
06a2c219
GM
13310/***********************************************************************
13311 Initialization
13312 ***********************************************************************/
f451eb13 13313
3afe33e7
RS
13314#ifdef USE_X_TOOLKIT
13315static XrmOptionDescRec emacs_options[] = {
13316 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13317 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13318
13319 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13320 XrmoptionSepArg, NULL},
13321 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13322
13323 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13324 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13325 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13326 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13327 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13328 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13329 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13330};
13331#endif /* USE_X_TOOLKIT */
13332
7a13e894
RS
13333static int x_initialized;
13334
29b38361
KH
13335#ifdef MULTI_KBOARD
13336/* Test whether two display-name strings agree up to the dot that separates
13337 the screen number from the server number. */
13338static int
13339same_x_server (name1, name2)
13340 char *name1, *name2;
13341{
13342 int seen_colon = 0;
cf591cc1
RS
13343 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13344 int system_name_length = strlen (system_name);
13345 int length_until_period = 0;
13346
13347 while (system_name[length_until_period] != 0
13348 && system_name[length_until_period] != '.')
13349 length_until_period++;
13350
13351 /* Treat `unix' like an empty host name. */
13352 if (! strncmp (name1, "unix:", 5))
13353 name1 += 4;
13354 if (! strncmp (name2, "unix:", 5))
13355 name2 += 4;
13356 /* Treat this host's name like an empty host name. */
13357 if (! strncmp (name1, system_name, system_name_length)
13358 && name1[system_name_length] == ':')
13359 name1 += system_name_length;
13360 if (! strncmp (name2, system_name, system_name_length)
13361 && name2[system_name_length] == ':')
13362 name2 += system_name_length;
13363 /* Treat this host's domainless name like an empty host name. */
13364 if (! strncmp (name1, system_name, length_until_period)
13365 && name1[length_until_period] == ':')
13366 name1 += length_until_period;
13367 if (! strncmp (name2, system_name, length_until_period)
13368 && name2[length_until_period] == ':')
13369 name2 += length_until_period;
13370
29b38361
KH
13371 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13372 {
13373 if (*name1 == ':')
13374 seen_colon++;
13375 if (seen_colon && *name1 == '.')
13376 return 1;
13377 }
13378 return (seen_colon
13379 && (*name1 == '.' || *name1 == '\0')
13380 && (*name2 == '.' || *name2 == '\0'));
13381}
13382#endif
13383
334208b7 13384struct x_display_info *
1f8255f2 13385x_term_init (display_name, xrm_option, resource_name)
334208b7 13386 Lisp_Object display_name;
1f8255f2
RS
13387 char *xrm_option;
13388 char *resource_name;
dc6f92b8 13389{
334208b7 13390 int connection;
7a13e894 13391 Display *dpy;
334208b7
RS
13392 struct x_display_info *dpyinfo;
13393 XrmDatabase xrdb;
13394
60439948
KH
13395 BLOCK_INPUT;
13396
7a13e894
RS
13397 if (!x_initialized)
13398 {
13399 x_initialize ();
13400 x_initialized = 1;
13401 }
dc6f92b8 13402
3afe33e7 13403#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13404 /* weiner@footloose.sps.mot.com reports that this causes
13405 errors with X11R5:
13406 X protocol error: BadAtom (invalid Atom parameter)
13407 on protocol request 18skiloaf.
13408 So let's not use it until R6. */
13409#ifdef HAVE_X11XTR6
bdcd49ba
RS
13410 XtSetLanguageProc (NULL, NULL, NULL);
13411#endif
13412
7f9c7f94
RS
13413 {
13414 int argc = 0;
13415 char *argv[3];
13416
13417 argv[0] = "";
13418 argc = 1;
13419 if (xrm_option)
13420 {
13421 argv[argc++] = "-xrm";
13422 argv[argc++] = xrm_option;
13423 }
13424 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13425 resource_name, EMACS_CLASS,
13426 emacs_options, XtNumber (emacs_options),
13427 &argc, argv);
39d8bb4d
KH
13428
13429#ifdef HAVE_X11XTR6
10537cb1 13430 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13431 fixup_locale ();
39d8bb4d 13432#endif
7f9c7f94 13433 }
3afe33e7
RS
13434
13435#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13436#ifdef HAVE_X11R5
13437 XSetLocaleModifiers ("");
13438#endif
7a13e894 13439 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13440#endif /* not USE_X_TOOLKIT */
334208b7 13441
7a13e894
RS
13442 /* Detect failure. */
13443 if (dpy == 0)
60439948
KH
13444 {
13445 UNBLOCK_INPUT;
13446 return 0;
13447 }
7a13e894
RS
13448
13449 /* We have definitely succeeded. Record the new connection. */
13450
13451 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
f04e1297 13452 bzero (dpyinfo, sizeof *dpyinfo);
7a13e894 13453
29b38361
KH
13454#ifdef MULTI_KBOARD
13455 {
13456 struct x_display_info *share;
13457 Lisp_Object tail;
13458
13459 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13460 share = share->next, tail = XCDR (tail))
13461 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13462 XSTRING (display_name)->data))
13463 break;
13464 if (share)
13465 dpyinfo->kboard = share->kboard;
13466 else
13467 {
13468 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13469 init_kboard (dpyinfo->kboard);
59e755be
KH
13470 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13471 {
13472 char *vendor = ServerVendor (dpy);
9b6ed9f3 13473 UNBLOCK_INPUT;
59e755be
KH
13474 dpyinfo->kboard->Vsystem_key_alist
13475 = call1 (Qvendor_specific_keysyms,
13476 build_string (vendor ? vendor : ""));
9b6ed9f3 13477 BLOCK_INPUT;
59e755be
KH
13478 }
13479
29b38361
KH
13480 dpyinfo->kboard->next_kboard = all_kboards;
13481 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13482 /* Don't let the initial kboard remain current longer than necessary.
13483 That would cause problems if a file loaded on startup tries to
06a2c219 13484 prompt in the mini-buffer. */
0ad5446c
KH
13485 if (current_kboard == initial_kboard)
13486 current_kboard = dpyinfo->kboard;
29b38361
KH
13487 }
13488 dpyinfo->kboard->reference_count++;
13489 }
b9737ad3
KH
13490#endif
13491
7a13e894
RS
13492 /* Put this display on the chain. */
13493 dpyinfo->next = x_display_list;
13494 x_display_list = dpyinfo;
13495
13496 /* Put it on x_display_name_list as well, to keep them parallel. */
13497 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13498 x_display_name_list);
8e713be6 13499 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13500
13501 dpyinfo->display = dpy;
dc6f92b8 13502
dc6f92b8 13503#if 0
7a13e894 13504 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13505#endif /* ! 0 */
7a13e894
RS
13506
13507 dpyinfo->x_id_name
fc932ac6
RS
13508 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13509 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13510 + 2);
13511 sprintf (dpyinfo->x_id_name, "%s@%s",
13512 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13513
13514 /* Figure out which modifier bits mean what. */
334208b7 13515 x_find_modifier_meanings (dpyinfo);
f451eb13 13516
ab648270 13517 /* Get the scroll bar cursor. */
7a13e894 13518 dpyinfo->vertical_scroll_bar_cursor
334208b7 13519 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13520
334208b7
RS
13521 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13522 resource_name, EMACS_CLASS);
13523#ifdef HAVE_XRMSETDATABASE
13524 XrmSetDatabase (dpyinfo->display, xrdb);
13525#else
13526 dpyinfo->display->db = xrdb;
13527#endif
547d9db8 13528 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13529 all versions. */
13530 dpyinfo->xrdb = xrdb;
334208b7
RS
13531
13532 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13533 DefaultScreen (dpyinfo->display));
5ff67d81 13534 select_visual (dpyinfo);
43bd1b2b 13535 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13536 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13537 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13538 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13539 dpyinfo->grabbed = 0;
13540 dpyinfo->reference_count = 0;
13541 dpyinfo->icon_bitmap_id = -1;
06a2c219 13542 dpyinfo->font_table = NULL;
7a13e894
RS
13543 dpyinfo->n_fonts = 0;
13544 dpyinfo->font_table_size = 0;
13545 dpyinfo->bitmaps = 0;
13546 dpyinfo->bitmaps_size = 0;
13547 dpyinfo->bitmaps_last = 0;
13548 dpyinfo->scratch_cursor_gc = 0;
13549 dpyinfo->mouse_face_mouse_frame = 0;
13550 dpyinfo->mouse_face_deferred_gc = 0;
13551 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13552 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13553 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13554 dpyinfo->mouse_face_window = Qnil;
13555 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13556 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13557 dpyinfo->x_focus_frame = 0;
13558 dpyinfo->x_focus_event_frame = 0;
13559 dpyinfo->x_highlight_frame = 0;
06a2c219 13560 dpyinfo->image_cache = make_image_cache ();
334208b7 13561
43bd1b2b 13562 /* See if a private colormap is requested. */
5ff67d81
GM
13563 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13564 {
13565 if (dpyinfo->visual->class == PseudoColor)
13566 {
13567 Lisp_Object value;
13568 value = display_x_get_resource (dpyinfo,
13569 build_string ("privateColormap"),
13570 build_string ("PrivateColormap"),
13571 Qnil, Qnil);
13572 if (STRINGP (value)
13573 && (!strcmp (XSTRING (value)->data, "true")
13574 || !strcmp (XSTRING (value)->data, "on")))
13575 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13576 }
43bd1b2b 13577 }
5ff67d81
GM
13578 else
13579 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13580 dpyinfo->visual, AllocNone);
43bd1b2b 13581
06a2c219
GM
13582 {
13583 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13584 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13585 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13586 dpyinfo->resy = pixels * 25.4 / mm;
13587 pixels = DisplayWidth (dpyinfo->display, screen_number);
13588 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13589 dpyinfo->resx = pixels * 25.4 / mm;
13590 }
13591
334208b7
RS
13592 dpyinfo->Xatom_wm_protocols
13593 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13594 dpyinfo->Xatom_wm_take_focus
13595 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13596 dpyinfo->Xatom_wm_save_yourself
13597 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13598 dpyinfo->Xatom_wm_delete_window
13599 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13600 dpyinfo->Xatom_wm_change_state
13601 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13602 dpyinfo->Xatom_wm_configure_denied
13603 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13604 dpyinfo->Xatom_wm_window_moved
13605 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13606 dpyinfo->Xatom_editres
13607 = XInternAtom (dpyinfo->display, "Editres", False);
13608 dpyinfo->Xatom_CLIPBOARD
13609 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13610 dpyinfo->Xatom_TIMESTAMP
13611 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13612 dpyinfo->Xatom_TEXT
13613 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13614 dpyinfo->Xatom_COMPOUND_TEXT
13615 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13616 dpyinfo->Xatom_DELETE
13617 = XInternAtom (dpyinfo->display, "DELETE", False);
13618 dpyinfo->Xatom_MULTIPLE
13619 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13620 dpyinfo->Xatom_INCR
13621 = XInternAtom (dpyinfo->display, "INCR", False);
13622 dpyinfo->Xatom_EMACS_TMP
13623 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13624 dpyinfo->Xatom_TARGETS
13625 = XInternAtom (dpyinfo->display, "TARGETS", False);
13626 dpyinfo->Xatom_NULL
13627 = XInternAtom (dpyinfo->display, "NULL", False);
13628 dpyinfo->Xatom_ATOM_PAIR
13629 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13630 /* For properties of font. */
13631 dpyinfo->Xatom_PIXEL_SIZE
13632 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13633 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13634 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13635 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13636 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13637 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13638 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13639
06a2c219
GM
13640 /* Ghostscript support. */
13641 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13642 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13643
13644 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13645 False);
13646
547d9db8
KH
13647 dpyinfo->cut_buffers_initialized = 0;
13648
334208b7
RS
13649 connection = ConnectionNumber (dpyinfo->display);
13650 dpyinfo->connection = connection;
13651
dc43ef94 13652 {
5d7cc324
RS
13653 char null_bits[1];
13654
13655 null_bits[0] = 0x00;
dc43ef94
KH
13656
13657 dpyinfo->null_pixel
13658 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13659 null_bits, 1, 1, (long) 0, (long) 0,
13660 1);
13661 }
13662
06a2c219
GM
13663 {
13664 extern int gray_bitmap_width, gray_bitmap_height;
13665 extern unsigned char *gray_bitmap_bits;
13666 dpyinfo->gray
13667 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13668 gray_bitmap_bits,
13669 gray_bitmap_width, gray_bitmap_height,
13670 (unsigned long) 1, (unsigned long) 0, 1);
13671 }
13672
f5d11644
GM
13673#ifdef HAVE_X_I18N
13674 xim_initialize (dpyinfo, resource_name);
13675#endif
13676
87485d6f
MW
13677#ifdef subprocesses
13678 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13679 if (connection != 0)
7a13e894 13680 add_keyboard_wait_descriptor (connection);
87485d6f 13681#endif
6d4238f3 13682
041b69ac 13683#ifndef F_SETOWN_BUG
dc6f92b8 13684#ifdef F_SETOWN
dc6f92b8 13685#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13686 /* stdin is a socket here */
334208b7 13687 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13688#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13689 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13690#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13691#endif /* ! defined (F_SETOWN) */
041b69ac 13692#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13693
13694#ifdef SIGIO
eee20f6a
KH
13695 if (interrupt_input)
13696 init_sigio (connection);
c118dd06 13697#endif /* ! defined (SIGIO) */
dc6f92b8 13698
51b592fb 13699#ifdef USE_LUCID
f8c39f51 13700#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13701 /* Make sure that we have a valid font for dialog boxes
13702 so that Xt does not crash. */
13703 {
13704 Display *dpy = dpyinfo->display;
13705 XrmValue d, fr, to;
13706 Font font;
e99db5a1 13707 int count;
51b592fb
RS
13708
13709 d.addr = (XPointer)&dpy;
13710 d.size = sizeof (Display *);
13711 fr.addr = XtDefaultFont;
13712 fr.size = sizeof (XtDefaultFont);
13713 to.size = sizeof (Font *);
13714 to.addr = (XPointer)&font;
e99db5a1 13715 count = x_catch_errors (dpy);
51b592fb
RS
13716 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13717 abort ();
13718 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13719 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13720 x_uncatch_errors (dpy, count);
51b592fb
RS
13721 }
13722#endif
f8c39f51 13723#endif
51b592fb 13724
34e23e5a
GM
13725 /* See if we should run in synchronous mode. This is useful
13726 for debugging X code. */
13727 {
13728 Lisp_Object value;
13729 value = display_x_get_resource (dpyinfo,
13730 build_string ("synchronous"),
13731 build_string ("Synchronous"),
13732 Qnil, Qnil);
13733 if (STRINGP (value)
13734 && (!strcmp (XSTRING (value)->data, "true")
13735 || !strcmp (XSTRING (value)->data, "on")))
13736 XSynchronize (dpyinfo->display, True);
13737 }
13738
60439948
KH
13739 UNBLOCK_INPUT;
13740
7a13e894
RS
13741 return dpyinfo;
13742}
13743\f
13744/* Get rid of display DPYINFO, assuming all frames are already gone,
13745 and without sending any more commands to the X server. */
dc6f92b8 13746
7a13e894
RS
13747void
13748x_delete_display (dpyinfo)
13749 struct x_display_info *dpyinfo;
13750{
13751 delete_keyboard_wait_descriptor (dpyinfo->connection);
13752
13753 /* Discard this display from x_display_name_list and x_display_list.
13754 We can't use Fdelq because that can quit. */
13755 if (! NILP (x_display_name_list)
8e713be6
KR
13756 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13757 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13758 else
13759 {
13760 Lisp_Object tail;
13761
13762 tail = x_display_name_list;
8e713be6 13763 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13764 {
bffcfca9 13765 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13766 {
8e713be6 13767 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13768 break;
13769 }
8e713be6 13770 tail = XCDR (tail);
7a13e894
RS
13771 }
13772 }
13773
9bda743f
GM
13774 if (next_noop_dpyinfo == dpyinfo)
13775 next_noop_dpyinfo = dpyinfo->next;
13776
7a13e894
RS
13777 if (x_display_list == dpyinfo)
13778 x_display_list = dpyinfo->next;
7f9c7f94
RS
13779 else
13780 {
13781 struct x_display_info *tail;
7a13e894 13782
7f9c7f94
RS
13783 for (tail = x_display_list; tail; tail = tail->next)
13784 if (tail->next == dpyinfo)
13785 tail->next = tail->next->next;
13786 }
7a13e894 13787
0d777288
RS
13788#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13789#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13790 XrmDestroyDatabase (dpyinfo->xrdb);
13791#endif
0d777288 13792#endif
29b38361
KH
13793#ifdef MULTI_KBOARD
13794 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13795 delete_kboard (dpyinfo->kboard);
b9737ad3 13796#endif
f5d11644
GM
13797#ifdef HAVE_X_I18N
13798 if (dpyinfo->xim)
13799 xim_close_dpy (dpyinfo);
13800#endif
13801
b9737ad3
KH
13802 xfree (dpyinfo->font_table);
13803 xfree (dpyinfo->x_id_name);
f04e1297 13804 xfree (dpyinfo->color_cells);
b9737ad3 13805 xfree (dpyinfo);
7a13e894 13806}
f04e1297 13807
7a13e894
RS
13808\f
13809/* Set up use of X before we make the first connection. */
13810
06a2c219
GM
13811static struct redisplay_interface x_redisplay_interface =
13812{
13813 x_produce_glyphs,
13814 x_write_glyphs,
13815 x_insert_glyphs,
13816 x_clear_end_of_line,
13817 x_scroll_run,
13818 x_after_update_window_line,
13819 x_update_window_begin,
13820 x_update_window_end,
13821 XTcursor_to,
13822 x_flush,
71b8321e 13823 x_clear_mouse_face,
66ac4b0e
GM
13824 x_get_glyph_overhangs,
13825 x_fix_overlapping_area
06a2c219
GM
13826};
13827
dfcf069d 13828void
7a13e894
RS
13829x_initialize ()
13830{
06a2c219
GM
13831 rif = &x_redisplay_interface;
13832
13833 clear_frame_hook = x_clear_frame;
13834 ins_del_lines_hook = x_ins_del_lines;
13835 change_line_highlight_hook = x_change_line_highlight;
13836 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13837 ring_bell_hook = XTring_bell;
13838 reset_terminal_modes_hook = XTreset_terminal_modes;
13839 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13840 update_begin_hook = x_update_begin;
13841 update_end_hook = x_update_end;
dc6f92b8
JB
13842 set_terminal_window_hook = XTset_terminal_window;
13843 read_socket_hook = XTread_socket;
b8009dd1 13844 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13845 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13846 mouse_position_hook = XTmouse_position;
f451eb13 13847 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13848 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13849 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13850 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13851 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13852 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13853 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13854
f676886a 13855 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13856 char_ins_del_ok = 0; /* just as fast to write the line */
13857 line_ins_del_ok = 1; /* we'll just blt 'em */
13858 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13859 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13860 off the bottom */
13861 baud_rate = 19200;
13862
7a13e894 13863 x_noop_count = 0;
9ea173e8 13864 last_tool_bar_item = -1;
06a2c219
GM
13865 any_help_event_p = 0;
13866
b30b24cb
RS
13867 /* Try to use interrupt input; if we can't, then start polling. */
13868 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13869
7f9c7f94
RS
13870#ifdef USE_X_TOOLKIT
13871 XtToolkitInitialize ();
13872 Xt_app_con = XtCreateApplicationContext ();
665881ad 13873 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13874
13875 /* Install an asynchronous timer that processes Xt timeout events
13876 every 0.1s. This is necessary because some widget sets use
13877 timeouts internally, for example the LessTif menu bar, or the
13878 Xaw3d scroll bar. When Xt timouts aren't processed, these
13879 widgets don't behave normally. */
13880 {
13881 EMACS_TIME interval;
13882 EMACS_SET_SECS_USECS (interval, 0, 100000);
13883 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13884 }
db74249b 13885#endif
bffcfca9 13886
db74249b 13887#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13888 xaw3d_arrow_scroll = False;
13889 xaw3d_pick_top = True;
7f9c7f94
RS
13890#endif
13891
58769bee 13892 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13893 original error handler. */
e99db5a1 13894 XSetErrorHandler (x_error_handler);
334208b7 13895 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13896
06a2c219 13897 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13898#ifdef SIGWINCH
13899 signal (SIGWINCH, SIG_DFL);
c118dd06 13900#endif /* ! defined (SIGWINCH) */
dc6f92b8 13901
92e2441b 13902 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13903}
55123275 13904
06a2c219 13905
55123275
JB
13906void
13907syms_of_xterm ()
13908{
e99db5a1
RS
13909 staticpro (&x_error_message_string);
13910 x_error_message_string = Qnil;
13911
7a13e894
RS
13912 staticpro (&x_display_name_list);
13913 x_display_name_list = Qnil;
334208b7 13914
ab648270 13915 staticpro (&last_mouse_scroll_bar);
e53cb100 13916 last_mouse_scroll_bar = Qnil;
59e755be
KH
13917
13918 staticpro (&Qvendor_specific_keysyms);
13919 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13920
13921 staticpro (&last_mouse_press_frame);
13922 last_mouse_press_frame = Qnil;
06a2c219 13923
06a2c219 13924 help_echo = Qnil;
be010514
GM
13925 staticpro (&help_echo);
13926 help_echo_object = Qnil;
13927 staticpro (&help_echo_object);
7cea38bc
GM
13928 help_echo_window = Qnil;
13929 staticpro (&help_echo_window);
06a2c219 13930 previous_help_echo = Qnil;
be010514
GM
13931 staticpro (&previous_help_echo);
13932 help_echo_pos = -1;
06a2c219
GM
13933
13934 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13935 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13936For example, if a block cursor is over a tab, it will be drawn as\n\
13937wide as that tab on the display.");
13938 x_stretch_cursor_p = 0;
13939
13940 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13941 "If not nil, Emacs uses toolkit scroll bars.");
13942#if USE_TOOLKIT_SCROLL_BARS
13943 x_toolkit_scroll_bars_p = 1;
13944#else
13945 x_toolkit_scroll_bars_p = 0;
13946#endif
13947
06a2c219
GM
13948 staticpro (&last_mouse_motion_frame);
13949 last_mouse_motion_frame = Qnil;
55123275 13950}
6cf0ae86
RS
13951
13952#endif /* not HAVE_X_WINDOWS */