(x_clear_area): Add prototype.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
edf36fe6 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
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
5bf04520 233/* Non-nil means Emacs uses toolkit scroll bars. */
06a2c219 234
5bf04520 235Lisp_Object Vx_toolkit_scroll_bars;
06a2c219
GM
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
499b1844 399static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
f04e1297 400static const XColor *x_color_cells P_ ((struct frame *, int *));
71b8321e 401static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
402static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
403void x_delete_display P_ ((struct x_display_info *));
404static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
405 unsigned));
406static int fast_find_position P_ ((struct window *, int, int *, int *,
407 int *, int *));
408static void set_output_cursor P_ ((struct cursor_pos *));
409static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
410 int *, int *, int *));
411static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 412static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
413static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
414static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
415static void show_mouse_face P_ ((struct x_display_info *,
416 enum draw_glyphs_face));
417static int x_io_error_quitter P_ ((Display *));
418int x_catch_errors P_ ((Display *));
419void x_uncatch_errors P_ ((Display *, int));
420void x_lower_frame P_ ((struct frame *));
421void x_scroll_bar_clear P_ ((struct frame *));
422int x_had_errors_p P_ ((Display *));
423void x_wm_set_size_hint P_ ((struct frame *, long, int));
424void x_raise_frame P_ ((struct frame *));
425void x_set_window_size P_ ((struct frame *, int, int, int));
426void x_wm_set_window_state P_ ((struct frame *, int));
427void x_wm_set_icon_pixmap P_ ((struct frame *, int));
428void x_initialize P_ ((void));
429static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
430static int x_compute_min_glyph_bounds P_ ((struct frame *));
431static void x_draw_phys_cursor_glyph P_ ((struct window *,
432 struct glyph_row *,
433 enum draw_glyphs_face));
434static void x_update_end P_ ((struct frame *));
435static void XTframe_up_to_date P_ ((struct frame *));
436static void XTreassert_line_highlight P_ ((int, int));
437static void x_change_line_highlight P_ ((int, int, int, int));
438static void XTset_terminal_modes P_ ((void));
439static void XTreset_terminal_modes P_ ((void));
440static void XTcursor_to P_ ((int, int, int, int));
441static void x_write_glyphs P_ ((struct glyph *, int));
442static void x_clear_end_of_line P_ ((int));
443static void x_clear_frame P_ ((void));
444static void x_clear_cursor P_ ((struct window *));
445static void frame_highlight P_ ((struct frame *));
446static void frame_unhighlight P_ ((struct frame *));
447static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
448static void XTframe_rehighlight P_ ((struct frame *));
449static void x_frame_rehighlight P_ ((struct x_display_info *));
450static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
f02d8aa0 451static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
06a2c219
GM
452static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
453 XRectangle *));
454static void expose_frame P_ ((struct frame *, int, int, int, int));
455static void expose_window_tree P_ ((struct window *, XRectangle *));
456static void expose_window P_ ((struct window *, XRectangle *));
457static void expose_area P_ ((struct window *, struct glyph_row *,
458 XRectangle *, enum glyph_row_area));
459static void expose_line P_ ((struct window *, struct glyph_row *,
460 XRectangle *));
461static void x_update_cursor_in_window_tree P_ ((struct window *, int));
462static void x_update_window_cursor P_ ((struct window *, int));
463static void x_erase_phys_cursor P_ ((struct window *));
464void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
465static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
466 enum bitmap_type));
467
468static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
469 GC, int));
470static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
471static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
472static void note_overwritten_text_cursor P_ ((struct window *, int, int));
473static void x_flush P_ ((struct frame *f));
952291d9
GM
474static void x_update_begin P_ ((struct frame *));
475static void x_update_window_begin P_ ((struct window *));
476static void x_draw_vertical_border P_ ((struct window *));
477static void x_after_update_window_line P_ ((struct glyph_row *));
478static INLINE void take_vertical_position_into_account P_ ((struct it *));
479static void x_produce_stretch_glyph P_ ((struct it *));
480
06a2c219
GM
481
482/* Flush display of frame F, or of all frames if F is null. */
483
484static void
485x_flush (f)
486 struct frame *f;
487{
488 BLOCK_INPUT;
489 if (f == NULL)
490 {
491 Lisp_Object rest, frame;
492 FOR_EACH_FRAME (rest, frame)
493 x_flush (XFRAME (frame));
494 }
495 else if (FRAME_X_P (f))
496 XFlush (FRAME_X_DISPLAY (f));
497 UNBLOCK_INPUT;
498}
499
dc6f92b8 500
06a2c219
GM
501/* Remove calls to XFlush by defining XFlush to an empty replacement.
502 Calls to XFlush should be unnecessary because the X output buffer
503 is flushed automatically as needed by calls to XPending,
504 XNextEvent, or XWindowEvent according to the XFlush man page.
505 XTread_socket calls XPending. Removing XFlush improves
506 performance. */
507
508#define XFlush(DISPLAY) (void) 0
b8009dd1 509
334208b7 510\f
06a2c219
GM
511/***********************************************************************
512 Debugging
513 ***********************************************************************/
514
9382638d 515#if 0
06a2c219
GM
516
517/* This is a function useful for recording debugging information about
518 the sequence of occurrences in this file. */
9382638d
KH
519
520struct record
521{
522 char *locus;
523 int type;
524};
525
526struct record event_record[100];
527
528int event_record_index;
529
530record_event (locus, type)
531 char *locus;
532 int type;
533{
534 if (event_record_index == sizeof (event_record) / sizeof (struct record))
535 event_record_index = 0;
536
537 event_record[event_record_index].locus = locus;
538 event_record[event_record_index].type = type;
539 event_record_index++;
540}
541
542#endif /* 0 */
06a2c219
GM
543
544
9382638d 545\f
334208b7
RS
546/* Return the struct x_display_info corresponding to DPY. */
547
548struct x_display_info *
549x_display_info_for_display (dpy)
550 Display *dpy;
551{
552 struct x_display_info *dpyinfo;
553
554 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
555 if (dpyinfo->display == dpy)
556 return dpyinfo;
16bd92ea 557
334208b7
RS
558 return 0;
559}
f451eb13 560
06a2c219
GM
561
562\f
563/***********************************************************************
564 Starting and ending an update
565 ***********************************************************************/
566
567/* Start an update of frame F. This function is installed as a hook
568 for update_begin, i.e. it is called when update_begin is called.
569 This function is called prior to calls to x_update_window_begin for
570 each window being updated. Currently, there is nothing to do here
571 because all interesting stuff is done on a window basis. */
dc6f92b8 572
dfcf069d 573static void
06a2c219 574x_update_begin (f)
f676886a 575 struct frame *f;
58769bee 576{
06a2c219
GM
577 /* Nothing to do. */
578}
dc6f92b8 579
dc6f92b8 580
06a2c219
GM
581/* Start update of window W. Set the global variable updated_window
582 to the window being updated and set output_cursor to the cursor
583 position of W. */
dc6f92b8 584
06a2c219
GM
585static void
586x_update_window_begin (w)
587 struct window *w;
588{
589 struct frame *f = XFRAME (WINDOW_FRAME (w));
590 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
591
592 updated_window = w;
593 set_output_cursor (&w->cursor);
b8009dd1 594
06a2c219 595 BLOCK_INPUT;
d1bc4182 596
06a2c219 597 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 598 {
514e4681 599 /* Don't do highlighting for mouse motion during the update. */
06a2c219 600 display_info->mouse_face_defer = 1;
37c2c98b 601
06a2c219
GM
602 /* If F needs to be redrawn, simply forget about any prior mouse
603 highlighting. */
9f67f20b 604 if (FRAME_GARBAGED_P (f))
06a2c219
GM
605 display_info->mouse_face_window = Qnil;
606
64f26cf5
GM
607#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
608 their mouse_face_p flag set, which means that they are always
609 unequal to rows in a desired matrix which never have that
610 flag set. So, rows containing mouse-face glyphs are never
611 scrolled, and we don't have to switch the mouse highlight off
612 here to prevent it from being scrolled. */
613
06a2c219
GM
614 /* Can we tell that this update does not affect the window
615 where the mouse highlight is? If so, no need to turn off.
616 Likewise, don't do anything if the frame is garbaged;
617 in that case, the frame's current matrix that we would use
618 is all wrong, and we will redisplay that line anyway. */
619 if (!NILP (display_info->mouse_face_window)
620 && w == XWINDOW (display_info->mouse_face_window))
514e4681 621 {
06a2c219 622 int i;
514e4681 623
06a2c219
GM
624 for (i = 0; i < w->desired_matrix->nrows; ++i)
625 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
626 break;
627
06a2c219
GM
628 if (i < w->desired_matrix->nrows)
629 clear_mouse_face (display_info);
514e4681 630 }
64f26cf5 631#endif /* 0 */
b8009dd1 632 }
6ccf47d1 633
dc6f92b8
JB
634 UNBLOCK_INPUT;
635}
636
06a2c219
GM
637
638/* Draw a vertical window border to the right of window W if W doesn't
639 have vertical scroll bars. */
640
dfcf069d 641static void
06a2c219
GM
642x_draw_vertical_border (w)
643 struct window *w;
58769bee 644{
06a2c219
GM
645 struct frame *f = XFRAME (WINDOW_FRAME (w));
646
647 /* Redraw borders between horizontally adjacent windows. Don't
648 do it for frames with vertical scroll bars because either the
649 right scroll bar of a window, or the left scroll bar of its
650 neighbor will suffice as a border. */
651 if (!WINDOW_RIGHTMOST_P (w)
652 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
653 {
654 int x0, x1, y0, y1;
dc6f92b8 655
06a2c219 656 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 657 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
658 y1 -= 1;
659
660 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
661 f->output_data.x->normal_gc, x1, y0, x1, y1);
662 }
663}
664
665
71b8321e
GM
666/* End update of window W (which is equal to updated_window).
667
668 Draw vertical borders between horizontally adjacent windows, and
669 display W's cursor if CURSOR_ON_P is non-zero.
670
671 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
672 glyphs in mouse-face were overwritten. In that case we have to
673 make sure that the mouse-highlight is properly redrawn.
674
675 W may be a menu bar pseudo-window in case we don't have X toolkit
676 support. Such windows don't have a cursor, so don't display it
677 here. */
06a2c219
GM
678
679static void
71b8321e 680x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
06a2c219 681 struct window *w;
71b8321e 682 int cursor_on_p, mouse_face_overwritten_p;
06a2c219
GM
683{
684 if (!w->pseudo_window_p)
685 {
71b8321e
GM
686 struct x_display_info *dpyinfo
687 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
688
06a2c219 689 BLOCK_INPUT;
71b8321e
GM
690
691 /* If a row with mouse-face was overwritten, arrange for
692 XTframe_up_to_date to redisplay the mouse highlight. */
693 if (mouse_face_overwritten_p)
694 {
695 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
696 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
697 dpyinfo->mouse_face_window = Qnil;
698 }
699
06a2c219
GM
700 if (cursor_on_p)
701 x_display_and_set_cursor (w, 1, output_cursor.hpos,
702 output_cursor.vpos,
703 output_cursor.x, output_cursor.y);
71b8321e 704
06a2c219
GM
705 x_draw_vertical_border (w);
706 UNBLOCK_INPUT;
707 }
708
709 updated_window = NULL;
710}
dc6f92b8 711
dc6f92b8 712
06a2c219
GM
713/* End update of frame F. This function is installed as a hook in
714 update_end. */
715
716static void
717x_update_end (f)
718 struct frame *f;
719{
720 /* Mouse highlight may be displayed again. */
aa8bff2e 721 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 722
06a2c219 723 BLOCK_INPUT;
334208b7 724 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
725 UNBLOCK_INPUT;
726}
b8009dd1 727
06a2c219
GM
728
729/* This function is called from various places in xdisp.c whenever a
730 complete update has been performed. The global variable
731 updated_window is not available here. */
b8009dd1 732
dfcf069d 733static void
b8009dd1 734XTframe_up_to_date (f)
06a2c219 735 struct frame *f;
b8009dd1 736{
06a2c219 737 if (FRAME_X_P (f))
514e4681 738 {
06a2c219 739 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
71b8321e 740
06a2c219
GM
741 if (dpyinfo->mouse_face_deferred_gc
742 || f == dpyinfo->mouse_face_mouse_frame)
743 {
744 BLOCK_INPUT;
745 if (dpyinfo->mouse_face_mouse_frame)
746 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
747 dpyinfo->mouse_face_mouse_x,
748 dpyinfo->mouse_face_mouse_y);
749 dpyinfo->mouse_face_deferred_gc = 0;
750 UNBLOCK_INPUT;
751 }
514e4681 752 }
b8009dd1 753}
06a2c219
GM
754
755
756/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
757 arrow bitmaps, or clear the areas where they would be displayed
758 before DESIRED_ROW is made current. The window being updated is
759 found in updated_window. This function It is called from
760 update_window_line only if it is known that there are differences
761 between bitmaps to be drawn between current row and DESIRED_ROW. */
762
763static void
764x_after_update_window_line (desired_row)
765 struct glyph_row *desired_row;
766{
767 struct window *w = updated_window;
768
769 xassert (w);
770
771 if (!desired_row->mode_line_p && !w->pseudo_window_p)
772 {
773 BLOCK_INPUT;
774 x_draw_row_bitmaps (w, desired_row);
775
776 /* When a window has disappeared, make sure that no rest of
777 full-width rows stays visible in the internal border. */
778 if (windows_or_buffers_changed)
779 {
780 struct frame *f = XFRAME (w->frame);
781 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
782 int height = desired_row->visible_height;
110859fc
GM
783 int x = (window_box_right (w, -1)
784 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
785 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
786
787 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
788 x, y, width, height, False);
789 }
790
791 UNBLOCK_INPUT;
792 }
793}
794
795
796/* Draw the bitmap WHICH in one of the areas to the left or right of
797 window W. ROW is the glyph row for which to display the bitmap; it
798 determines the vertical position at which the bitmap has to be
799 drawn. */
800
801static void
802x_draw_bitmap (w, row, which)
803 struct window *w;
804 struct glyph_row *row;
805 enum bitmap_type which;
806{
807 struct frame *f = XFRAME (WINDOW_FRAME (w));
808 Display *display = FRAME_X_DISPLAY (f);
809 Window window = FRAME_X_WINDOW (f);
810 int x, y, wd, h, dy;
811 unsigned char *bits;
812 Pixmap pixmap;
813 GC gc = f->output_data.x->normal_gc;
814 struct face *face;
815 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
816
817 /* Must clip because of partially visible lines. */
818 x_clip_to_row (w, row, gc, 1);
819
820 switch (which)
821 {
822 case LEFT_TRUNCATION_BITMAP:
823 wd = left_width;
824 h = left_height;
825 bits = left_bits;
826 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
827 - wd
110859fc 828 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
829 break;
830
831 case OVERLAY_ARROW_BITMAP:
832 wd = left_width;
833 h = left_height;
834 bits = ov_bits;
835 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
836 - wd
110859fc 837 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
838 break;
839
840 case RIGHT_TRUNCATION_BITMAP:
841 wd = right_width;
842 h = right_height;
843 bits = right_bits;
844 x = window_box_right (w, -1);
110859fc 845 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
846 break;
847
848 case CONTINUED_LINE_BITMAP:
849 wd = right_width;
850 h = right_height;
851 bits = continued_bits;
852 x = window_box_right (w, -1);
110859fc 853 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
854 break;
855
856 case CONTINUATION_LINE_BITMAP:
857 wd = continuation_width;
858 h = continuation_height;
859 bits = continuation_bits;
860 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
861 - wd
110859fc 862 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
863 break;
864
865 case ZV_LINE_BITMAP:
866 wd = zv_width;
867 h = zv_height;
868 bits = zv_bits;
869 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
870 - wd
110859fc 871 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
872 break;
873
874 default:
875 abort ();
876 }
877
878 /* Convert to frame coordinates. Set dy to the offset in the row to
879 start drawing the bitmap. */
880 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
881 dy = (row->height - h) / 2;
882
883 /* Draw the bitmap. I believe these small pixmaps can be cached
884 by the server. */
885 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
886 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
887 face->foreground,
888 face->background, depth);
889 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
890 XFreePixmap (display, pixmap);
891 XSetClipMask (display, gc, None);
892}
893
894
895/* Draw flags bitmaps for glyph row ROW on window W. Call this
896 function with input blocked. */
897
898static void
899x_draw_row_bitmaps (w, row)
900 struct window *w;
901 struct glyph_row *row;
902{
903 struct frame *f = XFRAME (w->frame);
904 enum bitmap_type bitmap;
905 struct face *face;
045dee35 906 int header_line_height = -1;
06a2c219
GM
907
908 xassert (interrupt_input_blocked);
909
910 /* If row is completely invisible, because of vscrolling, we
911 don't have to draw anything. */
912 if (row->visible_height <= 0)
913 return;
914
915 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
916 PREPARE_FACE_FOR_DISPLAY (f, face);
917
918 /* Decide which bitmap to draw at the left side. */
919 if (row->overlay_arrow_p)
920 bitmap = OVERLAY_ARROW_BITMAP;
921 else if (row->truncated_on_left_p)
922 bitmap = LEFT_TRUNCATION_BITMAP;
923 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
924 bitmap = CONTINUATION_LINE_BITMAP;
925 else if (row->indicate_empty_line_p)
926 bitmap = ZV_LINE_BITMAP;
927 else
928 bitmap = NO_BITMAP;
929
930 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
931 the flags area. */
932 if (bitmap == NO_BITMAP
110859fc 933 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
934 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
935 {
936 /* If W has a vertical border to its left, don't draw over it. */
937 int border = ((XFASTINT (w->left) > 0
938 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
939 ? 1 : 0);
940 int left = window_box_left (w, -1);
941
045dee35
GM
942 if (header_line_height < 0)
943 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
944
945 /* In case the same realized face is used for bitmap areas and
946 for something displayed in the text (e.g. face `region' on
947 mono-displays, the fill style may have been changed to
948 FillSolid in x_draw_glyph_string_background. */
949 if (face->stipple)
950 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
951 else
952 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
953
06a2c219
GM
954 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
955 face->gc,
956 (left
110859fc 957 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 958 + border),
045dee35 959 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 960 row->y)),
110859fc 961 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 962 row->visible_height);
dcd08bfb
GM
963 if (!face->stipple)
964 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
965 }
966
967 /* Draw the left bitmap. */
968 if (bitmap != NO_BITMAP)
969 x_draw_bitmap (w, row, bitmap);
970
971 /* Decide which bitmap to draw at the right side. */
972 if (row->truncated_on_right_p)
973 bitmap = RIGHT_TRUNCATION_BITMAP;
974 else if (row->continued_p)
975 bitmap = CONTINUED_LINE_BITMAP;
976 else
977 bitmap = NO_BITMAP;
978
979 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
980 the flags area. */
981 if (bitmap == NO_BITMAP
110859fc 982 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
983 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
984 {
985 int right = window_box_right (w, -1);
986
045dee35
GM
987 if (header_line_height < 0)
988 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
989
990 /* In case the same realized face is used for bitmap areas and
991 for something displayed in the text (e.g. face `region' on
992 mono-displays, the fill style may have been changed to
993 FillSolid in x_draw_glyph_string_background. */
994 if (face->stipple)
995 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
996 else
997 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
998 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
999 face->gc,
1000 right,
045dee35 1001 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 1002 row->y)),
110859fc 1003 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 1004 row->visible_height);
dcd08bfb
GM
1005 if (!face->stipple)
1006 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
1007 }
1008
1009 /* Draw the right bitmap. */
1010 if (bitmap != NO_BITMAP)
1011 x_draw_bitmap (w, row, bitmap);
1012}
1013
dc6f92b8 1014\f
06a2c219
GM
1015/***********************************************************************
1016 Line Highlighting
1017 ***********************************************************************/
dc6f92b8 1018
06a2c219
GM
1019/* External interface to control of standout mode. Not used for X
1020 frames. Aborts when called. */
1021
1022static void
dc6f92b8
JB
1023XTreassert_line_highlight (new, vpos)
1024 int new, vpos;
1025{
06a2c219 1026 abort ();
dc6f92b8
JB
1027}
1028
06a2c219
GM
1029
1030/* Call this when about to modify line at position VPOS and change
1031 whether it is highlighted. Not used for X frames. Aborts when
1032 called. */
dc6f92b8 1033
dfcf069d 1034static void
06a2c219
GM
1035x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1036 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1037{
06a2c219 1038 abort ();
dc6f92b8
JB
1039}
1040
06a2c219
GM
1041
1042/* This is called when starting Emacs and when restarting after
1043 suspend. When starting Emacs, no X window is mapped. And nothing
1044 must be done to Emacs's own window if it is suspended (though that
1045 rarely happens). */
dc6f92b8 1046
dfcf069d 1047static void
dc6f92b8
JB
1048XTset_terminal_modes ()
1049{
1050}
1051
06a2c219
GM
1052/* This is called when exiting or suspending Emacs. Exiting will make
1053 the X-windows go away, and suspending requires no action. */
dc6f92b8 1054
dfcf069d 1055static void
dc6f92b8
JB
1056XTreset_terminal_modes ()
1057{
dc6f92b8 1058}
06a2c219
GM
1059
1060
dc6f92b8 1061\f
06a2c219
GM
1062/***********************************************************************
1063 Output Cursor
1064 ***********************************************************************/
1065
1066/* Set the global variable output_cursor to CURSOR. All cursor
1067 positions are relative to updated_window. */
dc6f92b8 1068
dfcf069d 1069static void
06a2c219
GM
1070set_output_cursor (cursor)
1071 struct cursor_pos *cursor;
dc6f92b8 1072{
06a2c219
GM
1073 output_cursor.hpos = cursor->hpos;
1074 output_cursor.vpos = cursor->vpos;
1075 output_cursor.x = cursor->x;
1076 output_cursor.y = cursor->y;
1077}
1078
1079
1080/* Set a nominal cursor position.
dc6f92b8 1081
06a2c219
GM
1082 HPOS and VPOS are column/row positions in a window glyph matrix. X
1083 and Y are window text area relative pixel positions.
1084
1085 If this is done during an update, updated_window will contain the
1086 window that is being updated and the position is the future output
1087 cursor position for that window. If updated_window is null, use
1088 selected_window and display the cursor at the given position. */
1089
1090static void
1091XTcursor_to (vpos, hpos, y, x)
1092 int vpos, hpos, y, x;
1093{
1094 struct window *w;
1095
1096 /* If updated_window is not set, work on selected_window. */
1097 if (updated_window)
1098 w = updated_window;
1099 else
1100 w = XWINDOW (selected_window);
dbcb258a 1101
06a2c219
GM
1102 /* Set the output cursor. */
1103 output_cursor.hpos = hpos;
1104 output_cursor.vpos = vpos;
1105 output_cursor.x = x;
1106 output_cursor.y = y;
dc6f92b8 1107
06a2c219
GM
1108 /* If not called as part of an update, really display the cursor.
1109 This will also set the cursor position of W. */
1110 if (updated_window == NULL)
dc6f92b8
JB
1111 {
1112 BLOCK_INPUT;
06a2c219 1113 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1114 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1115 UNBLOCK_INPUT;
1116 }
1117}
dc43ef94 1118
06a2c219
GM
1119
1120\f
1121/***********************************************************************
1122 Display Iterator
1123 ***********************************************************************/
1124
1125/* Function prototypes of this page. */
1126
1127static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1128 struct glyph *,
ee569018
KH
1129 XChar2b *,
1130 int *));
06a2c219
GM
1131static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1132 int, XChar2b *, int));
1133static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1134static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1135static void x_append_glyph P_ ((struct it *));
b4192550 1136static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1137static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1138 int, int, double));
1139static void x_produce_glyphs P_ ((struct it *));
06a2c219 1140static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1141
1142
e2ef8ee6
GM
1143/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1144 is not contained in the font. */
dc43ef94 1145
06a2c219 1146static INLINE XCharStruct *
ee569018 1147x_per_char_metric (font, char2b)
06a2c219
GM
1148 XFontStruct *font;
1149 XChar2b *char2b;
1150{
1151 /* The result metric information. */
1152 XCharStruct *pcm = NULL;
dc6f92b8 1153
06a2c219 1154 xassert (font && char2b);
dc6f92b8 1155
06a2c219 1156 if (font->per_char != NULL)
dc6f92b8 1157 {
06a2c219 1158 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1159 {
06a2c219
GM
1160 /* min_char_or_byte2 specifies the linear character index
1161 corresponding to the first element of the per_char array,
1162 max_char_or_byte2 is the index of the last character. A
1163 character with non-zero CHAR2B->byte1 is not in the font.
1164 A character with byte2 less than min_char_or_byte2 or
1165 greater max_char_or_byte2 is not in the font. */
1166 if (char2b->byte1 == 0
1167 && char2b->byte2 >= font->min_char_or_byte2
1168 && char2b->byte2 <= font->max_char_or_byte2)
1169 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1170 }
06a2c219 1171 else
dc6f92b8 1172 {
06a2c219
GM
1173 /* If either min_byte1 or max_byte1 are nonzero, both
1174 min_char_or_byte2 and max_char_or_byte2 are less than
1175 256, and the 2-byte character index values corresponding
1176 to the per_char array element N (counting from 0) are:
1177
1178 byte1 = N/D + min_byte1
1179 byte2 = N\D + min_char_or_byte2
1180
1181 where:
1182
1183 D = max_char_or_byte2 - min_char_or_byte2 + 1
1184 / = integer division
1185 \ = integer modulus */
1186 if (char2b->byte1 >= font->min_byte1
1187 && char2b->byte1 <= font->max_byte1
1188 && char2b->byte2 >= font->min_char_or_byte2
1189 && char2b->byte2 <= font->max_char_or_byte2)
1190 {
1191 pcm = (font->per_char
1192 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1193 * (char2b->byte1 - font->min_byte1))
1194 + (char2b->byte2 - font->min_char_or_byte2));
1195 }
dc6f92b8 1196 }
06a2c219
GM
1197 }
1198 else
1199 {
1200 /* If the per_char pointer is null, all glyphs between the first
1201 and last character indexes inclusive have the same
1202 information, as given by both min_bounds and max_bounds. */
1203 if (char2b->byte2 >= font->min_char_or_byte2
1204 && char2b->byte2 <= font->max_char_or_byte2)
1205 pcm = &font->max_bounds;
1206 }
dc6f92b8 1207
ee569018 1208 return ((pcm == NULL
3e71d8f2 1209 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1210 ? NULL : pcm);
06a2c219 1211}
b73b6aaf 1212
57b03282 1213
06a2c219
GM
1214/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1215 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1216
06a2c219
GM
1217static INLINE void
1218x_encode_char (c, char2b, font_info)
1219 int c;
1220 XChar2b *char2b;
1221 struct font_info *font_info;
1222{
1223 int charset = CHAR_CHARSET (c);
1224 XFontStruct *font = font_info->font;
1225
1226 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1227 This may be either a program in a special encoder language or a
1228 fixed encoding. */
1229 if (font_info->font_encoder)
1230 {
1231 /* It's a program. */
1232 struct ccl_program *ccl = font_info->font_encoder;
1233
1234 if (CHARSET_DIMENSION (charset) == 1)
1235 {
1236 ccl->reg[0] = charset;
1237 ccl->reg[1] = char2b->byte2;
1238 }
1239 else
1240 {
1241 ccl->reg[0] = charset;
1242 ccl->reg[1] = char2b->byte1;
1243 ccl->reg[2] = char2b->byte2;
1244 }
1245
1246 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1247
1248 /* We assume that MSBs are appropriately set/reset by CCL
1249 program. */
1250 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1251 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1252 else
1253 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1254 }
1255 else if (font_info->encoding[charset])
1256 {
1257 /* Fixed encoding scheme. See fontset.h for the meaning of the
1258 encoding numbers. */
1259 int enc = font_info->encoding[charset];
1260
1261 if ((enc == 1 || enc == 2)
1262 && CHARSET_DIMENSION (charset) == 2)
1263 char2b->byte1 |= 0x80;
1264
1265 if (enc == 1 || enc == 3)
1266 char2b->byte2 |= 0x80;
1267 }
1268}
1269
1270
1271/* Get face and two-byte form of character C in face FACE_ID on frame
1272 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1273 means we want to display multibyte text. Value is a pointer to a
1274 realized face that is ready for display. */
1275
1276static INLINE struct face *
1277x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1278 struct frame *f;
1279 int c, face_id;
1280 XChar2b *char2b;
1281 int multibyte_p;
1282{
1283 struct face *face = FACE_FROM_ID (f, face_id);
1284
1285 if (!multibyte_p)
1286 {
1287 /* Unibyte case. We don't have to encode, but we have to make
1288 sure to use a face suitable for unibyte. */
1289 char2b->byte1 = 0;
1290 char2b->byte2 = c;
ee569018
KH
1291 face_id = FACE_FOR_CHAR (f, face, c);
1292 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1293 }
1294 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1295 {
1296 /* Case of ASCII in a face known to fit ASCII. */
1297 char2b->byte1 = 0;
1298 char2b->byte2 = c;
1299 }
1300 else
1301 {
1302 int c1, c2, charset;
1303
1304 /* Split characters into bytes. If c2 is -1 afterwards, C is
1305 really a one-byte character so that byte1 is zero. */
1306 SPLIT_CHAR (c, charset, c1, c2);
1307 if (c2 > 0)
1308 char2b->byte1 = c1, char2b->byte2 = c2;
1309 else
1310 char2b->byte1 = 0, char2b->byte2 = c1;
1311
06a2c219 1312 /* Maybe encode the character in *CHAR2B. */
ee569018 1313 if (face->font != NULL)
06a2c219
GM
1314 {
1315 struct font_info *font_info
1316 = FONT_INFO_FROM_ID (f, face->font_info_id);
1317 if (font_info)
ee569018 1318 x_encode_char (c, char2b, font_info);
06a2c219
GM
1319 }
1320 }
1321
1322 /* Make sure X resources of the face are allocated. */
1323 xassert (face != NULL);
1324 PREPARE_FACE_FOR_DISPLAY (f, face);
1325
1326 return face;
1327}
1328
1329
1330/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1331 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1332 a pointer to a realized face that is ready for display. */
1333
1334static INLINE struct face *
ee569018 1335x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1336 struct frame *f;
1337 struct glyph *glyph;
1338 XChar2b *char2b;
ee569018 1339 int *two_byte_p;
06a2c219
GM
1340{
1341 struct face *face;
1342
1343 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1344 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1345
ee569018
KH
1346 if (two_byte_p)
1347 *two_byte_p = 0;
1348
06a2c219
GM
1349 if (!glyph->multibyte_p)
1350 {
1351 /* Unibyte case. We don't have to encode, but we have to make
1352 sure to use a face suitable for unibyte. */
1353 char2b->byte1 = 0;
43d120d8 1354 char2b->byte2 = glyph->u.ch;
06a2c219 1355 }
43d120d8
KH
1356 else if (glyph->u.ch < 128
1357 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1358 {
1359 /* Case of ASCII in a face known to fit ASCII. */
1360 char2b->byte1 = 0;
43d120d8 1361 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1362 }
1363 else
1364 {
1365 int c1, c2, charset;
1366
1367 /* Split characters into bytes. If c2 is -1 afterwards, C is
1368 really a one-byte character so that byte1 is zero. */
43d120d8 1369 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1370 if (c2 > 0)
1371 char2b->byte1 = c1, char2b->byte2 = c2;
1372 else
1373 char2b->byte1 = 0, char2b->byte2 = c1;
1374
1375 /* Maybe encode the character in *CHAR2B. */
1376 if (charset != CHARSET_ASCII)
1377 {
1378 struct font_info *font_info
1379 = FONT_INFO_FROM_ID (f, face->font_info_id);
1380 if (font_info)
1381 {
43d120d8 1382 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1383 if (two_byte_p)
1384 *two_byte_p
1385 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1386 }
1387 }
1388 }
1389
1390 /* Make sure X resources of the face are allocated. */
1391 xassert (face != NULL);
1392 PREPARE_FACE_FOR_DISPLAY (f, face);
1393 return face;
1394}
1395
1396
1397/* Store one glyph for IT->char_to_display in IT->glyph_row.
1398 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1399
1400static INLINE void
1401x_append_glyph (it)
1402 struct it *it;
1403{
1404 struct glyph *glyph;
1405 enum glyph_row_area area = it->area;
1406
1407 xassert (it->glyph_row);
1408 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1409
1410 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1411 if (glyph < it->glyph_row->glyphs[area + 1])
1412 {
06a2c219
GM
1413 glyph->charpos = CHARPOS (it->position);
1414 glyph->object = it->object;
88d75730 1415 glyph->pixel_width = it->pixel_width;
06a2c219 1416 glyph->voffset = it->voffset;
88d75730 1417 glyph->type = CHAR_GLYPH;
06a2c219 1418 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1419 glyph->left_box_line_p = it->start_of_box_run_p;
1420 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1421 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1422 || it->phys_descent > it->descent);
88d75730 1423 glyph->padding_p = 0;
ee569018 1424 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1425 glyph->face_id = it->face_id;
1426 glyph->u.ch = it->char_to_display;
06a2c219
GM
1427 ++it->glyph_row->used[area];
1428 }
1429}
1430
b4192550
KH
1431/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1432 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1433
1434static INLINE void
1435x_append_composite_glyph (it)
1436 struct it *it;
1437{
1438 struct glyph *glyph;
1439 enum glyph_row_area area = it->area;
1440
1441 xassert (it->glyph_row);
1442
1443 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1444 if (glyph < it->glyph_row->glyphs[area + 1])
1445 {
b4192550
KH
1446 glyph->charpos = CHARPOS (it->position);
1447 glyph->object = it->object;
88d75730 1448 glyph->pixel_width = it->pixel_width;
b4192550 1449 glyph->voffset = it->voffset;
88d75730 1450 glyph->type = COMPOSITE_GLYPH;
b4192550 1451 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1452 glyph->left_box_line_p = it->start_of_box_run_p;
1453 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1454 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1455 || it->phys_descent > it->descent);
88d75730
GM
1456 glyph->padding_p = 0;
1457 glyph->glyph_not_available_p = 0;
1458 glyph->face_id = it->face_id;
1459 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1460 ++it->glyph_row->used[area];
1461 }
1462}
1463
06a2c219
GM
1464
1465/* Change IT->ascent and IT->height according to the setting of
1466 IT->voffset. */
1467
1468static INLINE void
1469take_vertical_position_into_account (it)
1470 struct it *it;
1471{
1472 if (it->voffset)
1473 {
1474 if (it->voffset < 0)
1475 /* Increase the ascent so that we can display the text higher
1476 in the line. */
1477 it->ascent += abs (it->voffset);
1478 else
1479 /* Increase the descent so that we can display the text lower
1480 in the line. */
1481 it->descent += it->voffset;
1482 }
1483}
1484
1485
1486/* Produce glyphs/get display metrics for the image IT is loaded with.
1487 See the description of struct display_iterator in dispextern.h for
1488 an overview of struct display_iterator. */
1489
1490static void
1491x_produce_image_glyph (it)
1492 struct it *it;
1493{
1494 struct image *img;
1495 struct face *face;
1496
1497 xassert (it->what == IT_IMAGE);
1498
1499 face = FACE_FROM_ID (it->f, it->face_id);
1500 img = IMAGE_FROM_ID (it->f, it->image_id);
1501 xassert (img);
1502
1503 /* Make sure X resources of the face and image are loaded. */
1504 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1505 prepare_image_for_display (it->f, img);
1506
95af8492 1507 it->ascent = it->phys_ascent = image_ascent (img, face);
22d650b8
GM
1508 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1509 it->pixel_width = img->width + 2 * img->hmargin;
06a2c219
GM
1510
1511 it->nglyphs = 1;
1512
1513 if (face->box != FACE_NO_BOX)
1514 {
1515 it->ascent += face->box_line_width;
1516 it->descent += face->box_line_width;
1517
1518 if (it->start_of_box_run_p)
1519 it->pixel_width += face->box_line_width;
1520 if (it->end_of_box_run_p)
1521 it->pixel_width += face->box_line_width;
1522 }
1523
1524 take_vertical_position_into_account (it);
1525
1526 if (it->glyph_row)
1527 {
1528 struct glyph *glyph;
1529 enum glyph_row_area area = it->area;
1530
1531 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1532 if (glyph < it->glyph_row->glyphs[area + 1])
1533 {
06a2c219
GM
1534 glyph->charpos = CHARPOS (it->position);
1535 glyph->object = it->object;
88d75730 1536 glyph->pixel_width = it->pixel_width;
06a2c219 1537 glyph->voffset = it->voffset;
88d75730 1538 glyph->type = IMAGE_GLYPH;
06a2c219 1539 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1540 glyph->left_box_line_p = it->start_of_box_run_p;
1541 glyph->right_box_line_p = it->end_of_box_run_p;
1542 glyph->overlaps_vertically_p = 0;
1543 glyph->padding_p = 0;
1544 glyph->glyph_not_available_p = 0;
1545 glyph->face_id = it->face_id;
1546 glyph->u.img_id = img->id;
06a2c219
GM
1547 ++it->glyph_row->used[area];
1548 }
1549 }
1550}
1551
1552
1553/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1554 of the glyph, WIDTH and HEIGHT are the width and height of the
1555 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1556 ascent of the glyph (0 <= ASCENT <= 1). */
1557
1558static void
1559x_append_stretch_glyph (it, object, width, height, ascent)
1560 struct it *it;
1561 Lisp_Object object;
1562 int width, height;
1563 double ascent;
1564{
1565 struct glyph *glyph;
1566 enum glyph_row_area area = it->area;
1567
1568 xassert (ascent >= 0 && ascent <= 1);
1569
1570 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1571 if (glyph < it->glyph_row->glyphs[area + 1])
1572 {
06a2c219
GM
1573 glyph->charpos = CHARPOS (it->position);
1574 glyph->object = object;
88d75730 1575 glyph->pixel_width = width;
06a2c219 1576 glyph->voffset = it->voffset;
88d75730 1577 glyph->type = STRETCH_GLYPH;
06a2c219 1578 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1579 glyph->left_box_line_p = it->start_of_box_run_p;
1580 glyph->right_box_line_p = it->end_of_box_run_p;
1581 glyph->overlaps_vertically_p = 0;
1582 glyph->padding_p = 0;
1583 glyph->glyph_not_available_p = 0;
1584 glyph->face_id = it->face_id;
1585 glyph->u.stretch.ascent = height * ascent;
1586 glyph->u.stretch.height = height;
06a2c219
GM
1587 ++it->glyph_row->used[area];
1588 }
1589}
1590
1591
1592/* Produce a stretch glyph for iterator IT. IT->object is the value
1593 of the glyph property displayed. The value must be a list
1594 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1595 being recognized:
1596
1597 1. `:width WIDTH' specifies that the space should be WIDTH *
1598 canonical char width wide. WIDTH may be an integer or floating
1599 point number.
1600
1601 2. `:relative-width FACTOR' specifies that the width of the stretch
1602 should be computed from the width of the first character having the
1603 `glyph' property, and should be FACTOR times that width.
1604
1605 3. `:align-to HPOS' specifies that the space should be wide enough
1606 to reach HPOS, a value in canonical character units.
1607
1608 Exactly one of the above pairs must be present.
1609
1610 4. `:height HEIGHT' specifies that the height of the stretch produced
1611 should be HEIGHT, measured in canonical character units.
1612
1613 5. `:relative-height FACTOR' specifies that the height of the the
1614 stretch should be FACTOR times the height of the characters having
1615 the glyph property.
1616
1617 Either none or exactly one of 4 or 5 must be present.
1618
1619 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1620 of the stretch should be used for the ascent of the stretch.
1621 ASCENT must be in the range 0 <= ASCENT <= 100. */
1622
1623#define NUMVAL(X) \
1624 ((INTEGERP (X) || FLOATP (X)) \
1625 ? XFLOATINT (X) \
1626 : - 1)
1627
1628
1629static void
1630x_produce_stretch_glyph (it)
1631 struct it *it;
1632{
1633 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1634#if GLYPH_DEBUG
1635 extern Lisp_Object Qspace;
1636#endif
1637 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1638 extern Lisp_Object QCrelative_width, QCrelative_height;
1639 extern Lisp_Object QCalign_to;
1640 Lisp_Object prop, plist;
1641 double width = 0, height = 0, ascent = 0;
1642 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1643 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1644
1645 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1646
1647 /* List should start with `space'. */
1648 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1649 plist = XCDR (it->object);
1650
1651 /* Compute the width of the stretch. */
1652 if (prop = Fplist_get (plist, QCwidth),
1653 NUMVAL (prop) > 0)
1654 /* Absolute width `:width WIDTH' specified and valid. */
1655 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1656 else if (prop = Fplist_get (plist, QCrelative_width),
1657 NUMVAL (prop) > 0)
1658 {
1659 /* Relative width `:relative-width FACTOR' specified and valid.
1660 Compute the width of the characters having the `glyph'
1661 property. */
1662 struct it it2;
1663 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1664
1665 it2 = *it;
1666 if (it->multibyte_p)
1667 {
1668 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1669 - IT_BYTEPOS (*it));
1670 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1671 }
1672 else
1673 it2.c = *p, it2.len = 1;
1674
1675 it2.glyph_row = NULL;
1676 it2.what = IT_CHARACTER;
1677 x_produce_glyphs (&it2);
1678 width = NUMVAL (prop) * it2.pixel_width;
1679 }
1680 else if (prop = Fplist_get (plist, QCalign_to),
1681 NUMVAL (prop) > 0)
1682 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1683 else
1684 /* Nothing specified -> width defaults to canonical char width. */
1685 width = CANON_X_UNIT (it->f);
1686
1687 /* Compute height. */
1688 if (prop = Fplist_get (plist, QCheight),
1689 NUMVAL (prop) > 0)
1690 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1691 else if (prop = Fplist_get (plist, QCrelative_height),
1692 NUMVAL (prop) > 0)
1693 height = FONT_HEIGHT (font) * NUMVAL (prop);
1694 else
1695 height = FONT_HEIGHT (font);
1696
1697 /* Compute percentage of height used for ascent. If
1698 `:ascent ASCENT' is present and valid, use that. Otherwise,
1699 derive the ascent from the font in use. */
1700 if (prop = Fplist_get (plist, QCascent),
1701 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1702 ascent = NUMVAL (prop) / 100.0;
1703 else
1704 ascent = (double) font->ascent / FONT_HEIGHT (font);
1705
1706 if (width <= 0)
1707 width = 1;
1708 if (height <= 0)
1709 height = 1;
1710
1711 if (it->glyph_row)
1712 {
1713 Lisp_Object object = it->stack[it->sp - 1].string;
1714 if (!STRINGP (object))
1715 object = it->w->buffer;
1716 x_append_stretch_glyph (it, object, width, height, ascent);
1717 }
1718
1719 it->pixel_width = width;
66ac4b0e
GM
1720 it->ascent = it->phys_ascent = height * ascent;
1721 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1722 it->nglyphs = 1;
1723
1724 if (face->box != FACE_NO_BOX)
1725 {
1726 it->ascent += face->box_line_width;
1727 it->descent += face->box_line_width;
1728
1729 if (it->start_of_box_run_p)
1730 it->pixel_width += face->box_line_width;
1731 if (it->end_of_box_run_p)
1732 it->pixel_width += face->box_line_width;
1733 }
1734
1735 take_vertical_position_into_account (it);
1736}
1737
b4192550
KH
1738/* Return proper value to be used as baseline offset of font that has
1739 ASCENT and DESCENT to draw characters by the font at the vertical
1740 center of the line of frame F.
1741
1742 Here, out task is to find the value of BOFF in the following figure;
1743
1744 -------------------------+-----------+-
1745 -+-+---------+-+ | |
1746 | | | | | |
1747 | | | | F_ASCENT F_HEIGHT
1748 | | | ASCENT | |
1749 HEIGHT | | | | |
1750 | | |-|-+------+-----------|------- baseline
1751 | | | | BOFF | |
1752 | |---------|-+-+ | |
1753 | | | DESCENT | |
1754 -+-+---------+-+ F_DESCENT |
1755 -------------------------+-----------+-
1756
1757 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1758 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1759 DESCENT = FONT->descent
1760 HEIGHT = FONT_HEIGHT (FONT)
1761 F_DESCENT = (F->output_data.x->font->descent
1762 - F->output_data.x->baseline_offset)
1763 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1764*/
1765
458f45fa
KH
1766#define VCENTER_BASELINE_OFFSET(FONT, F) \
1767 ((FONT)->descent \
1768 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1769 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1770 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1771
1772/* Produce glyphs/get display metrics for the display element IT is
1773 loaded with. See the description of struct display_iterator in
1774 dispextern.h for an overview of struct display_iterator. */
1775
1776static void
1777x_produce_glyphs (it)
1778 struct it *it;
1779{
ee569018
KH
1780 it->glyph_not_available_p = 0;
1781
06a2c219
GM
1782 if (it->what == IT_CHARACTER)
1783 {
1784 XChar2b char2b;
1785 XFontStruct *font;
ee569018 1786 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1787 XCharStruct *pcm;
06a2c219 1788 int font_not_found_p;
b4192550
KH
1789 struct font_info *font_info;
1790 int boff; /* baseline offset */
a4249304
KH
1791 /* We may change it->multibyte_p upon unibyte<->multibyte
1792 conversion. So, save the current value now and restore it
1793 later.
1794
1795 Note: It seems that we don't have to record multibyte_p in
1796 struct glyph because the character code itself tells if or
1797 not the character is multibyte. Thus, in the future, we must
1798 consider eliminating the field `multibyte_p' in the struct
1799 glyph.
1800 */
1801 int saved_multibyte_p = it->multibyte_p;
06a2c219 1802
ee569018
KH
1803 /* Maybe translate single-byte characters to multibyte, or the
1804 other way. */
06a2c219 1805 it->char_to_display = it->c;
ee569018 1806 if (!ASCII_BYTE_P (it->c))
06a2c219 1807 {
ee569018
KH
1808 if (unibyte_display_via_language_environment
1809 && SINGLE_BYTE_CHAR_P (it->c)
1810 && (it->c >= 0240
1811 || !NILP (Vnonascii_translation_table)))
1812 {
1813 it->char_to_display = unibyte_char_to_multibyte (it->c);
a4249304 1814 it->multibyte_p = 1;
ee569018
KH
1815 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1816 face = FACE_FROM_ID (it->f, it->face_id);
1817 }
1818 else if (!SINGLE_BYTE_CHAR_P (it->c)
1819 && !it->multibyte_p)
1820 {
1821 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
a4249304 1822 it->multibyte_p = 0;
ee569018
KH
1823 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1824 face = FACE_FROM_ID (it->f, it->face_id);
1825 }
06a2c219
GM
1826 }
1827
ee569018
KH
1828 /* Get font to use. Encode IT->char_to_display. */
1829 x_get_char_face_and_encoding (it->f, it->char_to_display,
1830 it->face_id, &char2b,
1831 it->multibyte_p);
06a2c219
GM
1832 font = face->font;
1833
1834 /* When no suitable font found, use the default font. */
1835 font_not_found_p = font == NULL;
1836 if (font_not_found_p)
b4192550
KH
1837 {
1838 font = FRAME_FONT (it->f);
1839 boff = it->f->output_data.x->baseline_offset;
1840 font_info = NULL;
1841 }
1842 else
1843 {
1844 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1845 boff = font_info->baseline_offset;
1846 if (font_info->vertical_centering)
1847 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1848 }
06a2c219
GM
1849
1850 if (it->char_to_display >= ' '
1851 && (!it->multibyte_p || it->char_to_display < 128))
1852 {
1853 /* Either unibyte or ASCII. */
1854 int stretched_p;
1855
1856 it->nglyphs = 1;
06a2c219
GM
1857
1858 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1859 it->ascent = font->ascent + boff;
1860 it->descent = font->descent - boff;
474848ac
GM
1861
1862 if (pcm)
1863 {
1864 it->phys_ascent = pcm->ascent + boff;
1865 it->phys_descent = pcm->descent - boff;
1866 it->pixel_width = pcm->width;
1867 }
1868 else
1869 {
1870 it->glyph_not_available_p = 1;
1871 it->phys_ascent = font->ascent + boff;
1872 it->phys_descent = font->descent - boff;
1873 it->pixel_width = FONT_WIDTH (font);
1874 }
06a2c219
GM
1875
1876 /* If this is a space inside a region of text with
1877 `space-width' property, change its width. */
1878 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1879 if (stretched_p)
1880 it->pixel_width *= XFLOATINT (it->space_width);
1881
1882 /* If face has a box, add the box thickness to the character
1883 height. If character has a box line to the left and/or
1884 right, add the box line width to the character's width. */
1885 if (face->box != FACE_NO_BOX)
1886 {
1887 int thick = face->box_line_width;
1888
1889 it->ascent += thick;
1890 it->descent += thick;
1891
1892 if (it->start_of_box_run_p)
1893 it->pixel_width += thick;
1894 if (it->end_of_box_run_p)
1895 it->pixel_width += thick;
1896 }
1897
1898 /* If face has an overline, add the height of the overline
1899 (1 pixel) and a 1 pixel margin to the character height. */
1900 if (face->overline_p)
1901 it->ascent += 2;
1902
1903 take_vertical_position_into_account (it);
1904
1905 /* If we have to actually produce glyphs, do it. */
1906 if (it->glyph_row)
1907 {
1908 if (stretched_p)
1909 {
1910 /* Translate a space with a `space-width' property
1911 into a stretch glyph. */
1912 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1913 x_append_stretch_glyph (it, it->object, it->pixel_width,
1914 it->ascent + it->descent, ascent);
1915 }
1916 else
1917 x_append_glyph (it);
1918
1919 /* If characters with lbearing or rbearing are displayed
1920 in this line, record that fact in a flag of the
1921 glyph row. This is used to optimize X output code. */
1c7e22fd 1922 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1923 it->glyph_row->contains_overlapping_glyphs_p = 1;
1924 }
1925 }
1926 else if (it->char_to_display == '\n')
1927 {
1928 /* A newline has no width but we need the height of the line. */
1929 it->pixel_width = 0;
1930 it->nglyphs = 0;
b4192550
KH
1931 it->ascent = it->phys_ascent = font->ascent + boff;
1932 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1933
1934 if (face->box != FACE_NO_BOX)
1935 {
1936 int thick = face->box_line_width;
1937 it->ascent += thick;
1938 it->descent += thick;
1939 }
1940 }
1941 else if (it->char_to_display == '\t')
1942 {
1943 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1944 int x = it->current_x + it->continuation_lines_width;
06a2c219 1945 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2a32b5ea
GM
1946
1947 /* If the distance from the current position to the next tab
1948 stop is less than a canonical character width, use the
1949 tab stop after that. */
1950 if (next_tab_x - x < CANON_X_UNIT (it->f))
1951 next_tab_x += tab_width;
06a2c219
GM
1952
1953 it->pixel_width = next_tab_x - x;
1954 it->nglyphs = 1;
b4192550
KH
1955 it->ascent = it->phys_ascent = font->ascent + boff;
1956 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1957
1958 if (it->glyph_row)
1959 {
1960 double ascent = (double) it->ascent / (it->ascent + it->descent);
1961 x_append_stretch_glyph (it, it->object, it->pixel_width,
1962 it->ascent + it->descent, ascent);
1963 }
1964 }
1965 else
1966 {
1967 /* A multi-byte character. Assume that the display width of the
1968 character is the width of the character multiplied by the
b4192550 1969 width of the font. */
06a2c219 1970
b4192550
KH
1971 /* If we found a font, this font should give us the right
1972 metrics. If we didn't find a font, use the frame's
1973 default font and calculate the width of the character
1974 from the charset width; this is what old redisplay code
1975 did. */
1976 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1977 if (font_not_found_p || !pcm)
1978 {
1979 int charset = CHAR_CHARSET (it->char_to_display);
1980
1981 it->glyph_not_available_p = 1;
1982 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1983 * CHARSET_WIDTH (charset));
1984 it->phys_ascent = font->ascent + boff;
1985 it->phys_descent = font->descent - boff;
1986 }
1987 else
1988 {
1989 it->pixel_width = pcm->width;
1990 it->phys_ascent = pcm->ascent + boff;
1991 it->phys_descent = pcm->descent - boff;
1992 if (it->glyph_row
1993 && (pcm->lbearing < 0
1994 || pcm->rbearing > pcm->width))
1995 it->glyph_row->contains_overlapping_glyphs_p = 1;
1996 }
b4192550
KH
1997 it->nglyphs = 1;
1998 it->ascent = font->ascent + boff;
1999 it->descent = font->descent - boff;
06a2c219
GM
2000 if (face->box != FACE_NO_BOX)
2001 {
2002 int thick = face->box_line_width;
2003 it->ascent += thick;
2004 it->descent += thick;
2005
2006 if (it->start_of_box_run_p)
2007 it->pixel_width += thick;
2008 if (it->end_of_box_run_p)
2009 it->pixel_width += thick;
2010 }
2011
2012 /* If face has an overline, add the height of the overline
2013 (1 pixel) and a 1 pixel margin to the character height. */
2014 if (face->overline_p)
2015 it->ascent += 2;
2016
2017 take_vertical_position_into_account (it);
2018
2019 if (it->glyph_row)
2020 x_append_glyph (it);
2021 }
a4249304 2022 it->multibyte_p = saved_multibyte_p;
06a2c219 2023 }
b4192550
KH
2024 else if (it->what == IT_COMPOSITION)
2025 {
2026 /* Note: A composition is represented as one glyph in the
2027 glyph matrix. There are no padding glyphs. */
2028 XChar2b char2b;
2029 XFontStruct *font;
ee569018 2030 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2031 XCharStruct *pcm;
2032 int font_not_found_p;
2033 struct font_info *font_info;
2034 int boff; /* baseline offset */
2035 struct composition *cmp = composition_table[it->cmp_id];
2036
2037 /* Maybe translate single-byte characters to multibyte. */
2038 it->char_to_display = it->c;
2039 if (unibyte_display_via_language_environment
2040 && SINGLE_BYTE_CHAR_P (it->c)
2041 && (it->c >= 0240
2042 || (it->c >= 0200
2043 && !NILP (Vnonascii_translation_table))))
2044 {
2045 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2046 }
2047
2048 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2049 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2050 face = FACE_FROM_ID (it->f, it->face_id);
2051 x_get_char_face_and_encoding (it->f, it->char_to_display,
2052 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2053 font = face->font;
2054
2055 /* When no suitable font found, use the default font. */
2056 font_not_found_p = font == NULL;
2057 if (font_not_found_p)
2058 {
2059 font = FRAME_FONT (it->f);
2060 boff = it->f->output_data.x->baseline_offset;
2061 font_info = NULL;
2062 }
2063 else
2064 {
2065 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2066 boff = font_info->baseline_offset;
2067 if (font_info->vertical_centering)
2068 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2069 }
2070
2071 /* There are no padding glyphs, so there is only one glyph to
2072 produce for the composition. Important is that pixel_width,
2073 ascent and descent are the values of what is drawn by
2074 draw_glyphs (i.e. the values of the overall glyphs composed). */
2075 it->nglyphs = 1;
2076
2077 /* If we have not yet calculated pixel size data of glyphs of
2078 the composition for the current face font, calculate them
2079 now. Theoretically, we have to check all fonts for the
2080 glyphs, but that requires much time and memory space. So,
2081 here we check only the font of the first glyph. This leads
2082 to incorrect display very rarely, and C-l (recenter) can
2083 correct the display anyway. */
2084 if (cmp->font != (void *) font)
2085 {
2086 /* Ascent and descent of the font of the first character of
2087 this composition (adjusted by baseline offset). Ascent
2088 and descent of overall glyphs should not be less than
2089 them respectively. */
2090 int font_ascent = font->ascent + boff;
2091 int font_descent = font->descent - boff;
2092 /* Bounding box of the overall glyphs. */
2093 int leftmost, rightmost, lowest, highest;
329bed06 2094 int i, width, ascent, descent;
b4192550
KH
2095
2096 cmp->font = (void *) font;
2097
2098 /* Initialize the bounding box. */
1bdeec2e
KH
2099 if (font_info
2100 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2101 {
2102 width = pcm->width;
2103 ascent = pcm->ascent;
2104 descent = pcm->descent;
2105 }
2106 else
2107 {
2108 width = FONT_WIDTH (font);
2109 ascent = font->ascent;
2110 descent = font->descent;
2111 }
2112
2113 rightmost = width;
2114 lowest = - descent + boff;
2115 highest = ascent + boff;
b4192550 2116 leftmost = 0;
329bed06 2117
b4192550
KH
2118 if (font_info
2119 && font_info->default_ascent
2120 && CHAR_TABLE_P (Vuse_default_ascent)
2121 && !NILP (Faref (Vuse_default_ascent,
2122 make_number (it->char_to_display))))
2123 highest = font_info->default_ascent + boff;
2124
2125 /* Draw the first glyph at the normal position. It may be
2126 shifted to right later if some other glyphs are drawn at
2127 the left. */
2128 cmp->offsets[0] = 0;
2129 cmp->offsets[1] = boff;
2130
2131 /* Set cmp->offsets for the remaining glyphs. */
2132 for (i = 1; i < cmp->glyph_len; i++)
2133 {
2134 int left, right, btm, top;
2135 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2136 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2137
2138 face = FACE_FROM_ID (it->f, face_id);
2139 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2140 it->multibyte_p);
b4192550
KH
2141 font = face->font;
2142 if (font == NULL)
2143 {
2144 font = FRAME_FONT (it->f);
2145 boff = it->f->output_data.x->baseline_offset;
2146 font_info = NULL;
2147 }
2148 else
2149 {
2150 font_info
2151 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2152 boff = font_info->baseline_offset;
2153 if (font_info->vertical_centering)
2154 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2155 }
2156
1bdeec2e
KH
2157 if (font_info
2158 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2159 {
2160 width = pcm->width;
2161 ascent = pcm->ascent;
2162 descent = pcm->descent;
2163 }
2164 else
2165 {
2166 width = FONT_WIDTH (font);
1bdeec2e
KH
2167 ascent = 1;
2168 descent = 0;
329bed06 2169 }
b4192550
KH
2170
2171 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2172 {
2173 /* Relative composition with or without
2174 alternate chars. */
329bed06
GM
2175 left = (leftmost + rightmost - width) / 2;
2176 btm = - descent + boff;
b4192550
KH
2177 if (font_info && font_info->relative_compose
2178 && (! CHAR_TABLE_P (Vignore_relative_composition)
2179 || NILP (Faref (Vignore_relative_composition,
2180 make_number (ch)))))
2181 {
2182
329bed06 2183 if (- descent >= font_info->relative_compose)
b4192550
KH
2184 /* One extra pixel between two glyphs. */
2185 btm = highest + 1;
329bed06 2186 else if (ascent <= 0)
b4192550 2187 /* One extra pixel between two glyphs. */
329bed06 2188 btm = lowest - 1 - ascent - descent;
b4192550
KH
2189 }
2190 }
2191 else
2192 {
2193 /* A composition rule is specified by an integer
2194 value that encodes global and new reference
2195 points (GREF and NREF). GREF and NREF are
2196 specified by numbers as below:
2197
2198 0---1---2 -- ascent
2199 | |
2200 | |
2201 | |
2202 9--10--11 -- center
2203 | |
2204 ---3---4---5--- baseline
2205 | |
2206 6---7---8 -- descent
2207 */
2208 int rule = COMPOSITION_RULE (cmp, i);
2209 int gref, nref, grefx, grefy, nrefx, nrefy;
2210
2211 COMPOSITION_DECODE_RULE (rule, gref, nref);
2212 grefx = gref % 3, nrefx = nref % 3;
2213 grefy = gref / 3, nrefy = nref / 3;
2214
2215 left = (leftmost
2216 + grefx * (rightmost - leftmost) / 2
329bed06 2217 - nrefx * width / 2);
b4192550
KH
2218 btm = ((grefy == 0 ? highest
2219 : grefy == 1 ? 0
2220 : grefy == 2 ? lowest
2221 : (highest + lowest) / 2)
329bed06
GM
2222 - (nrefy == 0 ? ascent + descent
2223 : nrefy == 1 ? descent - boff
b4192550 2224 : nrefy == 2 ? 0
329bed06 2225 : (ascent + descent) / 2));
b4192550
KH
2226 }
2227
2228 cmp->offsets[i * 2] = left;
329bed06 2229 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2230
2231 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2232 right = left + width;
2233 top = btm + descent + ascent;
b4192550
KH
2234 if (left < leftmost)
2235 leftmost = left;
2236 if (right > rightmost)
2237 rightmost = right;
2238 if (top > highest)
2239 highest = top;
2240 if (btm < lowest)
2241 lowest = btm;
2242 }
2243
2244 /* If there are glyphs whose x-offsets are negative,
2245 shift all glyphs to the right and make all x-offsets
2246 non-negative. */
2247 if (leftmost < 0)
2248 {
2249 for (i = 0; i < cmp->glyph_len; i++)
2250 cmp->offsets[i * 2] -= leftmost;
2251 rightmost -= leftmost;
2252 }
2253
2254 cmp->pixel_width = rightmost;
2255 cmp->ascent = highest;
2256 cmp->descent = - lowest;
2257 if (cmp->ascent < font_ascent)
2258 cmp->ascent = font_ascent;
2259 if (cmp->descent < font_descent)
2260 cmp->descent = font_descent;
2261 }
2262
2263 it->pixel_width = cmp->pixel_width;
2264 it->ascent = it->phys_ascent = cmp->ascent;
2265 it->descent = it->phys_descent = cmp->descent;
2266
2267 if (face->box != FACE_NO_BOX)
2268 {
2269 int thick = face->box_line_width;
2270 it->ascent += thick;
2271 it->descent += thick;
2272
2273 if (it->start_of_box_run_p)
2274 it->pixel_width += thick;
2275 if (it->end_of_box_run_p)
2276 it->pixel_width += thick;
2277 }
2278
2279 /* If face has an overline, add the height of the overline
2280 (1 pixel) and a 1 pixel margin to the character height. */
2281 if (face->overline_p)
2282 it->ascent += 2;
2283
2284 take_vertical_position_into_account (it);
2285
2286 if (it->glyph_row)
2287 x_append_composite_glyph (it);
2288 }
06a2c219
GM
2289 else if (it->what == IT_IMAGE)
2290 x_produce_image_glyph (it);
2291 else if (it->what == IT_STRETCH)
2292 x_produce_stretch_glyph (it);
2293
3017fdd1
GM
2294 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2295 because this isn't true for images with `:ascent 100'. */
2296 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2297 if (it->area == TEXT_AREA)
2298 it->current_x += it->pixel_width;
66ac4b0e 2299
d365f5bb
GM
2300 it->descent += it->extra_line_spacing;
2301
06a2c219
GM
2302 it->max_ascent = max (it->max_ascent, it->ascent);
2303 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2304 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2305 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2306}
2307
2308
2309/* Estimate the pixel height of the mode or top line on frame F.
2310 FACE_ID specifies what line's height to estimate. */
2311
2312int
2313x_estimate_mode_line_height (f, face_id)
2314 struct frame *f;
2315 enum face_id face_id;
2316{
43281ee3 2317 int height = FONT_HEIGHT (FRAME_FONT (f));
06a2c219
GM
2318
2319 /* This function is called so early when Emacs starts that the face
2320 cache and mode line face are not yet initialized. */
2321 if (FRAME_FACE_CACHE (f))
2322 {
2323 struct face *face = FACE_FROM_ID (f, face_id);
2324 if (face)
43281ee3
GM
2325 {
2326 if (face->font)
2327 height = FONT_HEIGHT (face->font);
2328 height += 2 * face->box_line_width;
2329 }
06a2c219
GM
2330 }
2331
2332 return height;
2333}
2334
2335\f
2336/***********************************************************************
2337 Glyph display
2338 ***********************************************************************/
2339
2340/* A sequence of glyphs to be drawn in the same face.
2341
2342 This data structure is not really completely X specific, so it
2343 could possibly, at least partially, be useful for other systems. It
2344 is currently not part of the external redisplay interface because
2345 it's not clear what other systems will need. */
2346
2347struct glyph_string
2348{
2349 /* X-origin of the string. */
2350 int x;
2351
2352 /* Y-origin and y-position of the base line of this string. */
2353 int y, ybase;
2354
2355 /* The width of the string, not including a face extension. */
2356 int width;
2357
2358 /* The width of the string, including a face extension. */
2359 int background_width;
2360
2361 /* The height of this string. This is the height of the line this
2362 string is drawn in, and can be different from the height of the
2363 font the string is drawn in. */
2364 int height;
2365
2366 /* Number of pixels this string overwrites in front of its x-origin.
2367 This number is zero if the string has an lbearing >= 0; it is
2368 -lbearing, if the string has an lbearing < 0. */
2369 int left_overhang;
2370
2371 /* Number of pixels this string overwrites past its right-most
2372 nominal x-position, i.e. x + width. Zero if the string's
2373 rbearing is <= its nominal width, rbearing - width otherwise. */
2374 int right_overhang;
2375
2376 /* The frame on which the glyph string is drawn. */
2377 struct frame *f;
2378
2379 /* The window on which the glyph string is drawn. */
2380 struct window *w;
2381
2382 /* X display and window for convenience. */
2383 Display *display;
2384 Window window;
2385
2386 /* The glyph row for which this string was built. It determines the
2387 y-origin and height of the string. */
2388 struct glyph_row *row;
2389
2390 /* The area within row. */
2391 enum glyph_row_area area;
2392
2393 /* Characters to be drawn, and number of characters. */
2394 XChar2b *char2b;
2395 int nchars;
2396
06a2c219
GM
2397 /* A face-override for drawing cursors, mouse face and similar. */
2398 enum draw_glyphs_face hl;
2399
2400 /* Face in which this string is to be drawn. */
2401 struct face *face;
2402
2403 /* Font in which this string is to be drawn. */
2404 XFontStruct *font;
2405
2406 /* Font info for this string. */
2407 struct font_info *font_info;
2408
b4192550
KH
2409 /* Non-null means this string describes (part of) a composition.
2410 All characters from char2b are drawn composed. */
2411 struct composition *cmp;
06a2c219
GM
2412
2413 /* Index of this glyph string's first character in the glyph
b4192550
KH
2414 definition of CMP. If this is zero, this glyph string describes
2415 the first character of a composition. */
06a2c219
GM
2416 int gidx;
2417
2418 /* 1 means this glyph strings face has to be drawn to the right end
2419 of the window's drawing area. */
2420 unsigned extends_to_end_of_line_p : 1;
2421
2422 /* 1 means the background of this string has been drawn. */
2423 unsigned background_filled_p : 1;
2424
2425 /* 1 means glyph string must be drawn with 16-bit functions. */
2426 unsigned two_byte_p : 1;
2427
2428 /* 1 means that the original font determined for drawing this glyph
2429 string could not be loaded. The member `font' has been set to
2430 the frame's default font in this case. */
2431 unsigned font_not_found_p : 1;
2432
2433 /* 1 means that the face in which this glyph string is drawn has a
2434 stipple pattern. */
2435 unsigned stippled_p : 1;
2436
66ac4b0e
GM
2437 /* 1 means only the foreground of this glyph string must be drawn,
2438 and we should use the physical height of the line this glyph
2439 string appears in as clip rect. */
2440 unsigned for_overlaps_p : 1;
2441
06a2c219
GM
2442 /* The GC to use for drawing this glyph string. */
2443 GC gc;
2444
2445 /* A pointer to the first glyph in the string. This glyph
2446 corresponds to char2b[0]. Needed to draw rectangles if
2447 font_not_found_p is 1. */
2448 struct glyph *first_glyph;
2449
2450 /* Image, if any. */
2451 struct image *img;
2452
2453 struct glyph_string *next, *prev;
2454};
2455
2456
5c187dee 2457#if 0
06a2c219
GM
2458
2459static void
2460x_dump_glyph_string (s)
2461 struct glyph_string *s;
2462{
2463 fprintf (stderr, "glyph string\n");
2464 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2465 s->x, s->y, s->width, s->height);
2466 fprintf (stderr, " ybase = %d\n", s->ybase);
2467 fprintf (stderr, " hl = %d\n", s->hl);
2468 fprintf (stderr, " left overhang = %d, right = %d\n",
2469 s->left_overhang, s->right_overhang);
2470 fprintf (stderr, " nchars = %d\n", s->nchars);
2471 fprintf (stderr, " extends to end of line = %d\n",
2472 s->extends_to_end_of_line_p);
2473 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2474 fprintf (stderr, " bg width = %d\n", s->background_width);
2475}
2476
2477#endif /* GLYPH_DEBUG */
2478
2479
2480
2481static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2482 struct glyph_string **,
2483 struct glyph_string *,
2484 struct glyph_string *));
2485static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2486 struct glyph_string **,
2487 struct glyph_string *,
2488 struct glyph_string *));
2489static void x_append_glyph_string P_ ((struct glyph_string **,
2490 struct glyph_string **,
2491 struct glyph_string *));
2492static int x_left_overwritten P_ ((struct glyph_string *));
2493static int x_left_overwriting P_ ((struct glyph_string *));
2494static int x_right_overwritten P_ ((struct glyph_string *));
2495static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2496static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2497 int));
06a2c219
GM
2498static void x_init_glyph_string P_ ((struct glyph_string *,
2499 XChar2b *, struct window *,
2500 struct glyph_row *,
2501 enum glyph_row_area, int,
2502 enum draw_glyphs_face));
2503static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2504 enum glyph_row_area, int, int,
66ac4b0e 2505 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2506static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2507static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2508static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2509 int));
2510static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2511static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2512static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2513static void x_draw_glyph_string P_ ((struct glyph_string *));
2514static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2515static void x_set_cursor_gc P_ ((struct glyph_string *));
2516static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2517static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2518static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2519 int *, int *));
2520static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2521static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2522 unsigned long *, double, int));
06a2c219 2523static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2524 double, int, unsigned long));
06a2c219
GM
2525static void x_setup_relief_colors P_ ((struct glyph_string *));
2526static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2527static void x_draw_image_relief P_ ((struct glyph_string *));
2528static void x_draw_image_foreground P_ ((struct glyph_string *));
2529static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2530static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2531static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2532 int, int, int));
2533static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2534 int, int, int, int, XRectangle *));
2535static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2536 int, int, int, XRectangle *));
66ac4b0e
GM
2537static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2538 enum glyph_row_area));
209f68d9
GM
2539static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2540 struct glyph_row *,
2541 enum glyph_row_area, int, int));
06a2c219 2542
163dcff3
GM
2543#if GLYPH_DEBUG
2544static void x_check_font P_ ((struct frame *, XFontStruct *));
2545#endif
2546
06a2c219 2547
06a2c219
GM
2548/* Append the list of glyph strings with head H and tail T to the list
2549 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2550
2551static INLINE void
2552x_append_glyph_string_lists (head, tail, h, t)
2553 struct glyph_string **head, **tail;
2554 struct glyph_string *h, *t;
2555{
2556 if (h)
2557 {
2558 if (*head)
2559 (*tail)->next = h;
2560 else
2561 *head = h;
2562 h->prev = *tail;
2563 *tail = t;
2564 }
2565}
2566
2567
2568/* Prepend the list of glyph strings with head H and tail T to the
2569 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2570 result. */
2571
2572static INLINE void
2573x_prepend_glyph_string_lists (head, tail, h, t)
2574 struct glyph_string **head, **tail;
2575 struct glyph_string *h, *t;
2576{
2577 if (h)
2578 {
2579 if (*head)
2580 (*head)->prev = t;
2581 else
2582 *tail = t;
2583 t->next = *head;
2584 *head = h;
2585 }
2586}
2587
2588
2589/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2590 Set *HEAD and *TAIL to the resulting list. */
2591
2592static INLINE void
2593x_append_glyph_string (head, tail, s)
2594 struct glyph_string **head, **tail;
2595 struct glyph_string *s;
2596{
2597 s->next = s->prev = NULL;
2598 x_append_glyph_string_lists (head, tail, s, s);
2599}
2600
2601
2602/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2603 face. */
2604
2605static void
2606x_set_cursor_gc (s)
2607 struct glyph_string *s;
2608{
2609 if (s->font == FRAME_FONT (s->f)
2610 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2611 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2612 && !s->cmp)
06a2c219
GM
2613 s->gc = s->f->output_data.x->cursor_gc;
2614 else
2615 {
2616 /* Cursor on non-default face: must merge. */
2617 XGCValues xgcv;
2618 unsigned long mask;
2619
2620 xgcv.background = s->f->output_data.x->cursor_pixel;
2621 xgcv.foreground = s->face->background;
2622
2623 /* If the glyph would be invisible, try a different foreground. */
2624 if (xgcv.foreground == xgcv.background)
2625 xgcv.foreground = s->face->foreground;
2626 if (xgcv.foreground == xgcv.background)
2627 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2628 if (xgcv.foreground == xgcv.background)
2629 xgcv.foreground = s->face->foreground;
2630
2631 /* Make sure the cursor is distinct from text in this face. */
2632 if (xgcv.background == s->face->background
2633 && xgcv.foreground == s->face->foreground)
2634 {
2635 xgcv.background = s->face->foreground;
2636 xgcv.foreground = s->face->background;
2637 }
2638
2639 IF_DEBUG (x_check_font (s->f, s->font));
2640 xgcv.font = s->font->fid;
2641 xgcv.graphics_exposures = False;
2642 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2643
2644 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2645 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2646 mask, &xgcv);
2647 else
2648 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2649 = XCreateGC (s->display, s->window, mask, &xgcv);
2650
2651 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2652 }
2653}
2654
2655
2656/* Set up S->gc of glyph string S for drawing text in mouse face. */
2657
2658static void
2659x_set_mouse_face_gc (s)
2660 struct glyph_string *s;
2661{
2662 int face_id;
ee569018 2663 struct face *face;
06a2c219 2664
e4ded23c 2665 /* What face has to be used last for the mouse face? */
06a2c219 2666 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2667 face = FACE_FROM_ID (s->f, face_id);
e4ded23c
GM
2668 if (face == NULL)
2669 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2670
033e3e18
GM
2671 if (s->first_glyph->type == CHAR_GLYPH)
2672 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2673 else
2674 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2675 s->face = FACE_FROM_ID (s->f, face_id);
2676 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2677
2678 /* If font in this face is same as S->font, use it. */
2679 if (s->font == s->face->font)
2680 s->gc = s->face->gc;
2681 else
2682 {
2683 /* Otherwise construct scratch_cursor_gc with values from FACE
2684 but font FONT. */
2685 XGCValues xgcv;
2686 unsigned long mask;
2687
2688 xgcv.background = s->face->background;
2689 xgcv.foreground = s->face->foreground;
2690 IF_DEBUG (x_check_font (s->f, s->font));
2691 xgcv.font = s->font->fid;
2692 xgcv.graphics_exposures = False;
2693 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2694
2695 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2696 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2697 mask, &xgcv);
2698 else
2699 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2700 = XCreateGC (s->display, s->window, mask, &xgcv);
2701
2702 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2703 }
2704
2705 xassert (s->gc != 0);
2706}
2707
2708
2709/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2710 Faces to use in the mode line have already been computed when the
2711 matrix was built, so there isn't much to do, here. */
2712
2713static INLINE void
2714x_set_mode_line_face_gc (s)
2715 struct glyph_string *s;
2716{
2717 s->gc = s->face->gc;
06a2c219
GM
2718}
2719
2720
2721/* Set S->gc of glyph string S for drawing that glyph string. Set
2722 S->stippled_p to a non-zero value if the face of S has a stipple
2723 pattern. */
2724
2725static INLINE void
2726x_set_glyph_string_gc (s)
2727 struct glyph_string *s;
2728{
209f68d9
GM
2729 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2730
06a2c219
GM
2731 if (s->hl == DRAW_NORMAL_TEXT)
2732 {
2733 s->gc = s->face->gc;
2734 s->stippled_p = s->face->stipple != 0;
2735 }
2736 else if (s->hl == DRAW_INVERSE_VIDEO)
2737 {
2738 x_set_mode_line_face_gc (s);
2739 s->stippled_p = s->face->stipple != 0;
2740 }
2741 else if (s->hl == DRAW_CURSOR)
2742 {
2743 x_set_cursor_gc (s);
2744 s->stippled_p = 0;
2745 }
2746 else if (s->hl == DRAW_MOUSE_FACE)
2747 {
2748 x_set_mouse_face_gc (s);
2749 s->stippled_p = s->face->stipple != 0;
2750 }
2751 else if (s->hl == DRAW_IMAGE_RAISED
2752 || s->hl == DRAW_IMAGE_SUNKEN)
2753 {
2754 s->gc = s->face->gc;
2755 s->stippled_p = s->face->stipple != 0;
2756 }
2757 else
2758 {
2759 s->gc = s->face->gc;
2760 s->stippled_p = s->face->stipple != 0;
2761 }
2762
2763 /* GC must have been set. */
2764 xassert (s->gc != 0);
2765}
2766
2767
2768/* Return in *R the clipping rectangle for glyph string S. */
2769
2770static void
2771x_get_glyph_string_clip_rect (s, r)
2772 struct glyph_string *s;
2773 XRectangle *r;
2774{
2775 if (s->row->full_width_p)
2776 {
2777 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2778 int canon_x = CANON_X_UNIT (s->f);
2779
2780 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2781 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2782
2783 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2784 {
1da3fd71 2785 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2786 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2787 r->x -= width;
2788 }
2789
b9432a85 2790 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2791
06a2c219
GM
2792 /* Unless displaying a mode or menu bar line, which are always
2793 fully visible, clip to the visible part of the row. */
2794 if (s->w->pseudo_window_p)
2795 r->height = s->row->visible_height;
2796 else
2797 r->height = s->height;
2798 }
2799 else
2800 {
2801 /* This is a text line that may be partially visible. */
2802 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2803 r->width = window_box_width (s->w, s->area);
2804 r->height = s->row->visible_height;
2805 }
2806
2807 /* Don't use S->y for clipping because it doesn't take partially
2808 visible lines into account. For example, it can be negative for
2809 partially visible lines at the top of a window. */
2810 if (!s->row->full_width_p
2811 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2812 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2813 else
2814 r->y = max (0, s->row->y);
06a2c219 2815
9ea173e8 2816 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2817 at the top of the window. */
9ea173e8 2818 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2819 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2820
2821 /* If S draws overlapping rows, it's sufficient to use the top and
2822 bottom of the window for clipping because this glyph string
2823 intentionally draws over other lines. */
2824 if (s->for_overlaps_p)
2825 {
045dee35 2826 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2827 r->height = window_text_bottom_y (s->w) - r->y;
2828 }
2829
2830 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2831}
2832
2833
2834/* Set clipping for output of glyph string S. S may be part of a mode
2835 line or menu if we don't have X toolkit support. */
2836
2837static INLINE void
2838x_set_glyph_string_clipping (s)
2839 struct glyph_string *s;
2840{
2841 XRectangle r;
2842 x_get_glyph_string_clip_rect (s, &r);
2843 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2844}
2845
2846
2847/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2848 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2849
2850static INLINE void
2851x_compute_glyph_string_overhangs (s)
2852 struct glyph_string *s;
2853{
b4192550 2854 if (s->cmp == NULL
06a2c219
GM
2855 && s->first_glyph->type == CHAR_GLYPH)
2856 {
2857 XCharStruct cs;
2858 int direction, font_ascent, font_descent;
2859 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2860 &font_ascent, &font_descent, &cs);
2861 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2862 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2863 }
2864}
2865
2866
2867/* Compute overhangs and x-positions for glyph string S and its
2868 predecessors, or successors. X is the starting x-position for S.
2869 BACKWARD_P non-zero means process predecessors. */
2870
2871static void
2872x_compute_overhangs_and_x (s, x, backward_p)
2873 struct glyph_string *s;
2874 int x;
2875 int backward_p;
2876{
2877 if (backward_p)
2878 {
2879 while (s)
2880 {
2881 x_compute_glyph_string_overhangs (s);
2882 x -= s->width;
2883 s->x = x;
2884 s = s->prev;
2885 }
2886 }
2887 else
2888 {
2889 while (s)
2890 {
2891 x_compute_glyph_string_overhangs (s);
2892 s->x = x;
2893 x += s->width;
2894 s = s->next;
2895 }
2896 }
2897}
2898
2899
2900/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2901 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2902 assumed to be zero. */
06a2c219
GM
2903
2904static void
2905x_get_glyph_overhangs (glyph, f, left, right)
2906 struct glyph *glyph;
2907 struct frame *f;
2908 int *left, *right;
2909{
06a2c219
GM
2910 *left = *right = 0;
2911
b4192550 2912 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2913 {
2914 XFontStruct *font;
2915 struct face *face;
2916 struct font_info *font_info;
2917 XChar2b char2b;
ee569018
KH
2918 XCharStruct *pcm;
2919
2920 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2921 font = face->font;
2922 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2923 if (font
2924 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2925 {
06a2c219
GM
2926 if (pcm->rbearing > pcm->width)
2927 *right = pcm->rbearing - pcm->width;
2928 if (pcm->lbearing < 0)
2929 *left = -pcm->lbearing;
2930 }
2931 }
2932}
2933
2934
2935/* Return the index of the first glyph preceding glyph string S that
2936 is overwritten by S because of S's left overhang. Value is -1
2937 if no glyphs are overwritten. */
2938
2939static int
2940x_left_overwritten (s)
2941 struct glyph_string *s;
2942{
2943 int k;
2944
2945 if (s->left_overhang)
2946 {
2947 int x = 0, i;
2948 struct glyph *glyphs = s->row->glyphs[s->area];
2949 int first = s->first_glyph - glyphs;
2950
2951 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2952 x -= glyphs[i].pixel_width;
2953
2954 k = i + 1;
2955 }
2956 else
2957 k = -1;
2958
2959 return k;
2960}
2961
2962
2963/* Return the index of the first glyph preceding glyph string S that
2964 is overwriting S because of its right overhang. Value is -1 if no
2965 glyph in front of S overwrites S. */
2966
2967static int
2968x_left_overwriting (s)
2969 struct glyph_string *s;
2970{
2971 int i, k, x;
2972 struct glyph *glyphs = s->row->glyphs[s->area];
2973 int first = s->first_glyph - glyphs;
2974
2975 k = -1;
2976 x = 0;
2977 for (i = first - 1; i >= 0; --i)
2978 {
2979 int left, right;
2980 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2981 if (x + right > 0)
2982 k = i;
2983 x -= glyphs[i].pixel_width;
2984 }
2985
2986 return k;
2987}
2988
2989
2990/* Return the index of the last glyph following glyph string S that is
2991 not overwritten by S because of S's right overhang. Value is -1 if
2992 no such glyph is found. */
2993
2994static int
2995x_right_overwritten (s)
2996 struct glyph_string *s;
2997{
2998 int k = -1;
2999
3000 if (s->right_overhang)
3001 {
3002 int x = 0, i;
3003 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3004 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3005 int end = s->row->used[s->area];
3006
3007 for (i = first; i < end && s->right_overhang > x; ++i)
3008 x += glyphs[i].pixel_width;
3009
3010 k = i;
3011 }
3012
3013 return k;
3014}
3015
3016
3017/* Return the index of the last glyph following glyph string S that
3018 overwrites S because of its left overhang. Value is negative
3019 if no such glyph is found. */
3020
3021static int
3022x_right_overwriting (s)
3023 struct glyph_string *s;
3024{
3025 int i, k, x;
3026 int end = s->row->used[s->area];
3027 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3028 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3029
3030 k = -1;
3031 x = 0;
3032 for (i = first; i < end; ++i)
3033 {
3034 int left, right;
3035 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3036 if (x - left < 0)
3037 k = i;
3038 x += glyphs[i].pixel_width;
3039 }
3040
3041 return k;
3042}
3043
3044
3045/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3046
3047static INLINE void
3048x_clear_glyph_string_rect (s, x, y, w, h)
3049 struct glyph_string *s;
3050 int x, y, w, h;
3051{
3052 XGCValues xgcv;
3053 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3054 XSetForeground (s->display, s->gc, xgcv.background);
3055 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3056 XSetForeground (s->display, s->gc, xgcv.foreground);
3057}
3058
3059
3060/* Draw the background of glyph_string S. If S->background_filled_p
3061 is non-zero don't draw it. FORCE_P non-zero means draw the
3062 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3063 when a string preceding S draws into the background of S, or S
3064 contains the first component of a composition. */
06a2c219
GM
3065
3066static void
3067x_draw_glyph_string_background (s, force_p)
3068 struct glyph_string *s;
3069 int force_p;
3070{
3071 /* Nothing to do if background has already been drawn or if it
3072 shouldn't be drawn in the first place. */
3073 if (!s->background_filled_p)
3074 {
b4192550 3075 if (s->stippled_p)
06a2c219
GM
3076 {
3077 /* Fill background with a stipple pattern. */
3078 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3079 XFillRectangle (s->display, s->window, s->gc, s->x,
3080 s->y + s->face->box_line_width,
3081 s->background_width,
3082 s->height - 2 * s->face->box_line_width);
3083 XSetFillStyle (s->display, s->gc, FillSolid);
3084 s->background_filled_p = 1;
3085 }
3086 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3087 || s->font_not_found_p
3088 || s->extends_to_end_of_line_p
06a2c219
GM
3089 || force_p)
3090 {
3091 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3092 s->background_width,
3093 s->height - 2 * s->face->box_line_width);
3094 s->background_filled_p = 1;
3095 }
3096 }
3097}
3098
3099
3100/* Draw the foreground of glyph string S. */
3101
3102static void
3103x_draw_glyph_string_foreground (s)
3104 struct glyph_string *s;
3105{
3106 int i, x;
3107
3108 /* If first glyph of S has a left box line, start drawing the text
3109 of S to the right of that box line. */
3110 if (s->face->box != FACE_NO_BOX
3111 && s->first_glyph->left_box_line_p)
3112 x = s->x + s->face->box_line_width;
3113 else
3114 x = s->x;
3115
b4192550
KH
3116 /* Draw characters of S as rectangles if S's font could not be
3117 loaded. */
3118 if (s->font_not_found_p)
06a2c219 3119 {
b4192550 3120 for (i = 0; i < s->nchars; ++i)
06a2c219 3121 {
b4192550
KH
3122 struct glyph *g = s->first_glyph + i;
3123 XDrawRectangle (s->display, s->window,
3124 s->gc, x, s->y, g->pixel_width - 1,
3125 s->height - 1);
3126 x += g->pixel_width;
06a2c219
GM
3127 }
3128 }
3129 else
3130 {
b4192550
KH
3131 char *char1b = (char *) s->char2b;
3132 int boff = s->font_info->baseline_offset;
06a2c219 3133
b4192550
KH
3134 if (s->font_info->vertical_centering)
3135 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3136
3137 /* If we can use 8-bit functions, condense S->char2b. */
3138 if (!s->two_byte_p)
3139 for (i = 0; i < s->nchars; ++i)
3140 char1b[i] = s->char2b[i].byte2;
3141
3142 /* Draw text with XDrawString if background has already been
3143 filled. Otherwise, use XDrawImageString. (Note that
3144 XDrawImageString is usually faster than XDrawString.) Always
3145 use XDrawImageString when drawing the cursor so that there is
3146 no chance that characters under a box cursor are invisible. */
3147 if (s->for_overlaps_p
3148 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3149 {
3150 /* Draw characters with 16-bit or 8-bit functions. */
3151 if (s->two_byte_p)
3152 XDrawString16 (s->display, s->window, s->gc, x,
3153 s->ybase - boff, s->char2b, s->nchars);
3154 else
3155 XDrawString (s->display, s->window, s->gc, x,
3156 s->ybase - boff, char1b, s->nchars);
3157 }
06a2c219
GM
3158 else
3159 {
b4192550
KH
3160 if (s->two_byte_p)
3161 XDrawImageString16 (s->display, s->window, s->gc, x,
3162 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3163 else
b4192550
KH
3164 XDrawImageString (s->display, s->window, s->gc, x,
3165 s->ybase - boff, char1b, s->nchars);
3166 }
3167 }
3168}
06a2c219 3169
b4192550 3170/* Draw the foreground of composite glyph string S. */
06a2c219 3171
b4192550
KH
3172static void
3173x_draw_composite_glyph_string_foreground (s)
3174 struct glyph_string *s;
3175{
3176 int i, x;
06a2c219 3177
b4192550
KH
3178 /* If first glyph of S has a left box line, start drawing the text
3179 of S to the right of that box line. */
3180 if (s->face->box != FACE_NO_BOX
3181 && s->first_glyph->left_box_line_p)
3182 x = s->x + s->face->box_line_width;
3183 else
3184 x = s->x;
06a2c219 3185
b4192550
KH
3186 /* S is a glyph string for a composition. S->gidx is the index of
3187 the first character drawn for glyphs of this composition.
3188 S->gidx == 0 means we are drawing the very first character of
3189 this composition. */
06a2c219 3190
b4192550
KH
3191 /* Draw a rectangle for the composition if the font for the very
3192 first character of the composition could not be loaded. */
3193 if (s->font_not_found_p)
3194 {
3195 if (s->gidx == 0)
3196 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3197 s->width - 1, s->height - 1);
3198 }
3199 else
3200 {
3201 for (i = 0; i < s->nchars; i++, ++s->gidx)
3202 XDrawString16 (s->display, s->window, s->gc,
3203 x + s->cmp->offsets[s->gidx * 2],
3204 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3205 s->char2b + i, 1);
06a2c219
GM
3206 }
3207}
3208
3209
80c32bcc
GM
3210#ifdef USE_X_TOOLKIT
3211
3e71d8f2 3212static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3213
3e71d8f2
GM
3214
3215/* Return the frame on which widget WIDGET is used.. Abort if frame
3216 cannot be determined. */
3217
e851c833 3218static struct frame *
3e71d8f2 3219x_frame_of_widget (widget)
80c32bcc 3220 Widget widget;
80c32bcc 3221{
80c32bcc 3222 struct x_display_info *dpyinfo;
5c187dee 3223 Lisp_Object tail;
3e71d8f2
GM
3224 struct frame *f;
3225
80c32bcc
GM
3226 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3227
3228 /* Find the top-level shell of the widget. Note that this function
3229 can be called when the widget is not yet realized, so XtWindow
3230 (widget) == 0. That's the reason we can't simply use
3231 x_any_window_to_frame. */
3232 while (!XtIsTopLevelShell (widget))
3233 widget = XtParent (widget);
3234
3235 /* Look for a frame with that top-level widget. Allocate the color
3236 on that frame to get the right gamma correction value. */
3237 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3238 if (GC_FRAMEP (XCAR (tail))
3239 && (f = XFRAME (XCAR (tail)),
3240 (f->output_data.nothing != 1
3241 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3242 && f->output_data.x->widget == widget)
3e71d8f2 3243 return f;
80c32bcc
GM
3244
3245 abort ();
3246}
3247
3e71d8f2
GM
3248
3249/* Allocate the color COLOR->pixel on the screen and display of
3250 widget WIDGET in colormap CMAP. If an exact match cannot be
3251 allocated, try the nearest color available. Value is non-zero
3252 if successful. This is called from lwlib. */
3253
3254int
3255x_alloc_nearest_color_for_widget (widget, cmap, color)
3256 Widget widget;
3257 Colormap cmap;
3258 XColor *color;
3259{
3260 struct frame *f = x_frame_of_widget (widget);
3261 return x_alloc_nearest_color (f, cmap, color);
3262}
3263
3264
46d516e5
MB
3265/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3266 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3267 If this produces the same color as PIXEL, try a color where all RGB
3268 values have DELTA added. Return the allocated color in *PIXEL.
3269 DISPLAY is the X display, CMAP is the colormap to operate on.
3270 Value is non-zero if successful. */
3271
3272int
3273x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3274 Widget widget;
3275 Display *display;
3276 Colormap cmap;
3277 unsigned long *pixel;
3278 double factor;
3279 int delta;
3280{
3281 struct frame *f = x_frame_of_widget (widget);
3282 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3283}
3284
3285
80c32bcc
GM
3286#endif /* USE_X_TOOLKIT */
3287
3288
f04e1297
GM
3289/* Value is an array of XColor structures for the contents of the
3290 color map of frame F. Set *NCELLS to the size of the array.
3291 Note that this probably shouldn't be called for large color maps,
3292 say a 24-bit TrueColor map. */
3293
3294static const XColor *
3295x_color_cells (f, ncells)
3296 struct frame *f;
3297 int *ncells;
3298{
3299 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3300
3301 if (dpyinfo->color_cells == NULL)
3302 {
3303 Display *display = FRAME_X_DISPLAY (f);
3304 Screen *screen = FRAME_X_SCREEN (f);
3305 int i;
3306
3307 dpyinfo->ncolor_cells
3308 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3309 dpyinfo->color_cells
3310 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3311 * sizeof *dpyinfo->color_cells);
3312
3313 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3314 dpyinfo->color_cells[i].pixel = i;
3315
3316 XQueryColors (display, FRAME_X_COLORMAP (f),
3317 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3318 }
3319
3320 *ncells = dpyinfo->ncolor_cells;
3321 return dpyinfo->color_cells;
3322}
3323
3324
3325/* On frame F, translate pixel colors to RGB values for the NCOLORS
3326 colors in COLORS. Use cached information, if available. */
3327
3328void
3329x_query_colors (f, colors, ncolors)
3330 struct frame *f;
3331 XColor *colors;
3332 int ncolors;
3333{
3334 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3335
3336 if (dpyinfo->color_cells)
3337 {
3338 int i;
3339 for (i = 0; i < ncolors; ++i)
3340 {
3341 unsigned long pixel = colors[i].pixel;
3342 xassert (pixel < dpyinfo->ncolor_cells);
3343 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3344 colors[i] = dpyinfo->color_cells[pixel];
3345 }
3346 }
3347 else
3348 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3349}
3350
3351
3352/* On frame F, translate pixel color to RGB values for the color in
3353 COLOR. Use cached information, if available. */
3354
3355void
3356x_query_color (f, color)
3357 struct frame *f;
3358 XColor *color;
3359{
3360 x_query_colors (f, color, 1);
3361}
3362
3363
06a2c219
GM
3364/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3365 CMAP. If an exact match can't be allocated, try the nearest color
3366 available. Value is non-zero if successful. Set *COLOR to the
3367 color allocated. */
3368
3369int
80c32bcc
GM
3370x_alloc_nearest_color (f, cmap, color)
3371 struct frame *f;
06a2c219
GM
3372 Colormap cmap;
3373 XColor *color;
3374{
80c32bcc
GM
3375 Display *display = FRAME_X_DISPLAY (f);
3376 Screen *screen = FRAME_X_SCREEN (f);
3377 int rc;
3378
3379 gamma_correct (f, color);
3380 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3381 if (rc == 0)
3382 {
3383 /* If we got to this point, the colormap is full, so we're going
3384 to try to get the next closest color. The algorithm used is
3385 a least-squares matching, which is what X uses for closest
3386 color matching with StaticColor visuals. */
3387 int nearest, i;
3388 unsigned long nearest_delta = ~0;
f04e1297
GM
3389 int ncells;
3390 const XColor *cells = x_color_cells (f, &ncells);
06a2c219
GM
3391
3392 for (nearest = i = 0; i < ncells; ++i)
3393 {
3394 long dred = (color->red >> 8) - (cells[i].red >> 8);
3395 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3396 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3397 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3398
3399 if (delta < nearest_delta)
3400 {
3401 nearest = i;
3402 nearest_delta = delta;
3403 }
3404 }
3405
3406 color->red = cells[nearest].red;
3407 color->green = cells[nearest].green;
3408 color->blue = cells[nearest].blue;
3409 rc = XAllocColor (display, cmap, color);
3410 }
35efe0a1
GM
3411 else
3412 {
3413 /* If allocation succeeded, and the allocated pixel color is not
3414 equal to a cached pixel color recorded earlier, there was a
3415 change in the colormap, so clear the color cache. */
3416 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3417 XColor *cached_color;
3418
3419 if (dpyinfo->color_cells
3420 && (cached_color = &dpyinfo->color_cells[color->pixel],
cae71efe
GM
3421 (cached_color->red != color->red
3422 || cached_color->blue != color->blue
3423 || cached_color->green != color->green)))
35efe0a1
GM
3424 {
3425 xfree (dpyinfo->color_cells);
3426 dpyinfo->color_cells = NULL;
3427 dpyinfo->ncolor_cells = 0;
3428 }
3429 }
06a2c219 3430
d9c545da
GM
3431#ifdef DEBUG_X_COLORS
3432 if (rc)
3433 register_color (color->pixel);
3434#endif /* DEBUG_X_COLORS */
3435
06a2c219
GM
3436 return rc;
3437}
3438
3439
d9c545da
GM
3440/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3441 It's necessary to do this instead of just using PIXEL directly to
3442 get color reference counts right. */
3443
3444unsigned long
3445x_copy_color (f, pixel)
3446 struct frame *f;
3447 unsigned long pixel;
3448{
3449 XColor color;
3450
3451 color.pixel = pixel;
3452 BLOCK_INPUT;
f04e1297 3453 x_query_color (f, &color);
d9c545da
GM
3454 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3455 UNBLOCK_INPUT;
3456#ifdef DEBUG_X_COLORS
3457 register_color (pixel);
3458#endif
3459 return color.pixel;
3460}
3461
3462
3e71d8f2
GM
3463/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3464 It's necessary to do this instead of just using PIXEL directly to
3465 get color reference counts right. */
3466
3467unsigned long
3468x_copy_dpy_color (dpy, cmap, pixel)
3469 Display *dpy;
3470 Colormap cmap;
3471 unsigned long pixel;
3472{
3473 XColor color;
3474
3475 color.pixel = pixel;
3476 BLOCK_INPUT;
3477 XQueryColor (dpy, cmap, &color);
3478 XAllocColor (dpy, cmap, &color);
3479 UNBLOCK_INPUT;
3480#ifdef DEBUG_X_COLORS
3481 register_color (pixel);
3482#endif
3483 return color.pixel;
3484}
3485
3486
6d8b0acd 3487/* Brightness beyond which a color won't have its highlight brightness
d7361edf 3488 boosted.
6d8b0acd 3489
d7361edf
MB
3490 Nominally, highlight colors for `3d' faces are calculated by
3491 brightening an object's color by a constant scale factor, but this
3492 doesn't yield good results for dark colors, so for colors who's
3493 brightness is less than this value (on a scale of 0-65535) have an
3494 use an additional additive factor.
6d8b0acd
MB
3495
3496 The value here is set so that the default menu-bar/mode-line color
3497 (grey75) will not have its highlights changed at all. */
3498#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3499
3500
06a2c219
GM
3501/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3502 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3503 If this produces the same color as PIXEL, try a color where all RGB
3504 values have DELTA added. Return the allocated color in *PIXEL.
3505 DISPLAY is the X display, CMAP is the colormap to operate on.
3506 Value is non-zero if successful. */
3507
3508static int
3509x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3510 struct frame *f;
3511 Display *display;
3512 Colormap cmap;
3513 unsigned long *pixel;
68c45bf0 3514 double factor;
06a2c219
GM
3515 int delta;
3516{
3517 XColor color, new;
6d8b0acd 3518 long bright;
06a2c219
GM
3519 int success_p;
3520
3521 /* Get RGB color values. */
3522 color.pixel = *pixel;
f04e1297 3523 x_query_color (f, &color);
06a2c219
GM
3524
3525 /* Change RGB values by specified FACTOR. Avoid overflow! */
3526 xassert (factor >= 0);
3527 new.red = min (0xffff, factor * color.red);
3528 new.green = min (0xffff, factor * color.green);
3529 new.blue = min (0xffff, factor * color.blue);
3530
d7361edf
MB
3531 /* Calculate brightness of COLOR. */
3532 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
6d8b0acd
MB
3533
3534 /* We only boost colors that are darker than
3535 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3536 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3537 /* Make an additive adjustment to NEW, because it's dark enough so
3538 that scaling by FACTOR alone isn't enough. */
3539 {
3540 /* How far below the limit this color is (0 - 1, 1 being darker). */
3541 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3542 /* The additive adjustment. */
d7361edf 3543 int min_delta = delta * dimness * factor / 2;
6d8b0acd
MB
3544
3545 if (factor < 1)
3546 {
6d8b0acd
MB
3547 new.red = max (0, new.red - min_delta);
3548 new.green = max (0, new.green - min_delta);
3549 new.blue = max (0, new.blue - min_delta);
3550 }
3551 else
3552 {
3553 new.red = min (0xffff, min_delta + new.red);
3554 new.green = min (0xffff, min_delta + new.green);
3555 new.blue = min (0xffff, min_delta + new.blue);
3556 }
3557 }
3558
06a2c219 3559 /* Try to allocate the color. */
80c32bcc 3560 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3561 if (success_p)
3562 {
3563 if (new.pixel == *pixel)
3564 {
3565 /* If we end up with the same color as before, try adding
3566 delta to the RGB values. */
0d605c67 3567 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3568
3569 new.red = min (0xffff, delta + color.red);
3570 new.green = min (0xffff, delta + color.green);
3571 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3572 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3573 }
3574 else
3575 success_p = 1;
3576 *pixel = new.pixel;
3577 }
3578
3579 return success_p;
3580}
3581
3582
3583/* Set up the foreground color for drawing relief lines of glyph
3584 string S. RELIEF is a pointer to a struct relief containing the GC
3585 with which lines will be drawn. Use a color that is FACTOR or
3586 DELTA lighter or darker than the relief's background which is found
3587 in S->f->output_data.x->relief_background. If such a color cannot
3588 be allocated, use DEFAULT_PIXEL, instead. */
3589
3590static void
3591x_setup_relief_color (f, relief, factor, delta, default_pixel)
3592 struct frame *f;
3593 struct relief *relief;
68c45bf0 3594 double factor;
06a2c219
GM
3595 int delta;
3596 unsigned long default_pixel;
3597{
3598 XGCValues xgcv;
3599 struct x_output *di = f->output_data.x;
3600 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3601 unsigned long pixel;
3602 unsigned long background = di->relief_background;
43bd1b2b 3603 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3604 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3605 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3606
3607 xgcv.graphics_exposures = False;
3608 xgcv.line_width = 1;
3609
3610 /* Free previously allocated color. The color cell will be reused
3611 when it has been freed as many times as it was allocated, so this
3612 doesn't affect faces using the same colors. */
3613 if (relief->gc
3614 && relief->allocated_p)
3615 {
0d605c67 3616 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3617 relief->allocated_p = 0;
3618 }
3619
3620 /* Allocate new color. */
3621 xgcv.foreground = default_pixel;
3622 pixel = background;
dcd08bfb
GM
3623 if (dpyinfo->n_planes != 1
3624 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3625 {
3626 relief->allocated_p = 1;
3627 xgcv.foreground = relief->pixel = pixel;
3628 }
3629
3630 if (relief->gc == 0)
3631 {
dcd08bfb 3632 xgcv.stipple = dpyinfo->gray;
06a2c219 3633 mask |= GCStipple;
dcd08bfb 3634 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3635 }
3636 else
dcd08bfb 3637 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3638}
3639
3640
3641/* Set up colors for the relief lines around glyph string S. */
3642
3643static void
3644x_setup_relief_colors (s)
3645 struct glyph_string *s;
3646{
3647 struct x_output *di = s->f->output_data.x;
3648 unsigned long color;
3649
3650 if (s->face->use_box_color_for_shadows_p)
3651 color = s->face->box_color;
3652 else
3653 {
3654 XGCValues xgcv;
3655
3656 /* Get the background color of the face. */
3657 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3658 color = xgcv.background;
3659 }
3660
3661 if (di->white_relief.gc == 0
3662 || color != di->relief_background)
3663 {
3664 di->relief_background = color;
3665 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3666 WHITE_PIX_DEFAULT (s->f));
3667 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3668 BLACK_PIX_DEFAULT (s->f));
3669 }
3670}
3671
3672
3673/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3674 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3675 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3676 relief. LEFT_P non-zero means draw a relief on the left side of
3677 the rectangle. RIGHT_P non-zero means draw a relief on the right
3678 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3679 when drawing. */
3680
3681static void
3682x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3683 raised_p, left_p, right_p, clip_rect)
3684 struct frame *f;
3685 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3686 XRectangle *clip_rect;
3687{
3688 int i;
3689 GC gc;
3690
3691 if (raised_p)
3692 gc = f->output_data.x->white_relief.gc;
3693 else
3694 gc = f->output_data.x->black_relief.gc;
3695 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3696
3697 /* Top. */
3698 for (i = 0; i < width; ++i)
3699 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3700 left_x + i * left_p, top_y + i,
3701 right_x + 1 - i * right_p, top_y + i);
3702
3703 /* Left. */
3704 if (left_p)
3705 for (i = 0; i < width; ++i)
3706 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3707 left_x + i, top_y + i, left_x + i, bottom_y - i);
3708
3709 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3710 if (raised_p)
3711 gc = f->output_data.x->black_relief.gc;
3712 else
3713 gc = f->output_data.x->white_relief.gc;
3714 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3715
3716 /* Bottom. */
3717 for (i = 0; i < width; ++i)
3718 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3719 left_x + i * left_p, bottom_y - i,
3720 right_x + 1 - i * right_p, bottom_y - i);
3721
3722 /* Right. */
3723 if (right_p)
3724 for (i = 0; i < width; ++i)
3725 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3726 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3727
3728 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3729}
3730
3731
3732/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3733 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3734 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3735 left side of the rectangle. RIGHT_P non-zero means draw a line
3736 on the right side of the rectangle. CLIP_RECT is the clipping
3737 rectangle to use when drawing. */
3738
3739static void
3740x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3741 left_p, right_p, clip_rect)
3742 struct glyph_string *s;
3743 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3744 XRectangle *clip_rect;
3745{
3746 XGCValues xgcv;
3747
3748 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3749 XSetForeground (s->display, s->gc, s->face->box_color);
3750 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3751
3752 /* Top. */
3753 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3754 left_x, top_y, right_x - left_x + 1, width);
06a2c219
GM
3755
3756 /* Left. */
3757 if (left_p)
3758 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3759 left_x, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3760
3761 /* Bottom. */
3762 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3763 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
06a2c219
GM
3764
3765 /* Right. */
3766 if (right_p)
3767 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3768 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3769
3770 XSetForeground (s->display, s->gc, xgcv.foreground);
3771 XSetClipMask (s->display, s->gc, None);
3772}
3773
3774
3775/* Draw a box around glyph string S. */
3776
3777static void
3778x_draw_glyph_string_box (s)
3779 struct glyph_string *s;
3780{
3781 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3782 int left_p, right_p;
3783 struct glyph *last_glyph;
3784 XRectangle clip_rect;
3785
3786 last_x = window_box_right (s->w, s->area);
3787 if (s->row->full_width_p
3788 && !s->w->pseudo_window_p)
3789 {
110859fc 3790 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3791 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3792 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3793 }
3794
3795 /* The glyph that may have a right box line. */
b4192550 3796 last_glyph = (s->cmp || s->img
06a2c219
GM
3797 ? s->first_glyph
3798 : s->first_glyph + s->nchars - 1);
3799
3800 width = s->face->box_line_width;
3801 raised_p = s->face->box == FACE_RAISED_BOX;
3802 left_x = s->x;
3803 right_x = ((s->row->full_width_p
1da3fd71 3804 ? last_x - 1
a7aeb2de 3805 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3806 top_y = s->y;
3807 bottom_y = top_y + s->height - 1;
3808
3809 left_p = (s->first_glyph->left_box_line_p
3810 || (s->hl == DRAW_MOUSE_FACE
3811 && (s->prev == NULL
3812 || s->prev->hl != s->hl)));
3813 right_p = (last_glyph->right_box_line_p
3814 || (s->hl == DRAW_MOUSE_FACE
3815 && (s->next == NULL
3816 || s->next->hl != s->hl)));
3817
3818 x_get_glyph_string_clip_rect (s, &clip_rect);
3819
3820 if (s->face->box == FACE_SIMPLE_BOX)
3821 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3822 left_p, right_p, &clip_rect);
3823 else
3824 {
3825 x_setup_relief_colors (s);
3826 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3827 width, raised_p, left_p, right_p, &clip_rect);
3828 }
3829}
3830
3831
3832/* Draw foreground of image glyph string S. */
3833
3834static void
3835x_draw_image_foreground (s)
3836 struct glyph_string *s;
3837{
3838 int x;
95af8492 3839 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3840
3841 /* If first glyph of S has a left box line, start drawing it to the
3842 right of that line. */
3843 if (s->face->box != FACE_NO_BOX
3844 && s->first_glyph->left_box_line_p)
3845 x = s->x + s->face->box_line_width;
3846 else
3847 x = s->x;
3848
3849 /* If there is a margin around the image, adjust x- and y-position
3850 by that margin. */
22d650b8
GM
3851 x += s->img->hmargin;
3852 y += s->img->vmargin;
06a2c219
GM
3853
3854 if (s->img->pixmap)
3855 {
3856 if (s->img->mask)
3857 {
3858 /* We can't set both a clip mask and use XSetClipRectangles
3859 because the latter also sets a clip mask. We also can't
3860 trust on the shape extension to be available
3861 (XShapeCombineRegion). So, compute the rectangle to draw
3862 manually. */
3863 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3864 | GCFunction);
3865 XGCValues xgcv;
3866 XRectangle clip_rect, image_rect, r;
3867
3868 xgcv.clip_mask = s->img->mask;
3869 xgcv.clip_x_origin = x;
3870 xgcv.clip_y_origin = y;
3871 xgcv.function = GXcopy;
3872 XChangeGC (s->display, s->gc, mask, &xgcv);
3873
3874 x_get_glyph_string_clip_rect (s, &clip_rect);
3875 image_rect.x = x;
3876 image_rect.y = y;
3877 image_rect.width = s->img->width;
3878 image_rect.height = s->img->height;
3879 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3880 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3881 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3882 }
3883 else
3884 {
49ad1d99
GM
3885 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3886 XGCValues xgcv;
3887 XRectangle clip_rect, image_rect, r;
3888
3889 x_get_glyph_string_clip_rect (s, &clip_rect);
3890 image_rect.x = x;
3891 image_rect.y = y;
3892 image_rect.width = s->img->width;
3893 image_rect.height = s->img->height;
3894 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3895 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3896 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
06a2c219
GM
3897
3898 /* When the image has a mask, we can expect that at
3899 least part of a mouse highlight or a block cursor will
3900 be visible. If the image doesn't have a mask, make
3901 a block cursor visible by drawing a rectangle around
3902 the image. I believe it's looking better if we do
3903 nothing here for mouse-face. */
3904 if (s->hl == DRAW_CURSOR)
3905 XDrawRectangle (s->display, s->window, s->gc, x, y,
3906 s->img->width - 1, s->img->height - 1);
3907 }
3908 }
3909 else
3910 /* Draw a rectangle if image could not be loaded. */
3911 XDrawRectangle (s->display, s->window, s->gc, x, y,
3912 s->img->width - 1, s->img->height - 1);
3913}
3914
3915
3916/* Draw a relief around the image glyph string S. */
3917
3918static void
3919x_draw_image_relief (s)
3920 struct glyph_string *s;
3921{
3922 int x0, y0, x1, y1, thick, raised_p;
3923 XRectangle r;
3924 int x;
95af8492 3925 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3926
3927 /* If first glyph of S has a left box line, start drawing it to the
3928 right of that line. */
3929 if (s->face->box != FACE_NO_BOX
3930 && s->first_glyph->left_box_line_p)
3931 x = s->x + s->face->box_line_width;
3932 else
3933 x = s->x;
3934
3935 /* If there is a margin around the image, adjust x- and y-position
3936 by that margin. */
22d650b8
GM
3937 x += s->img->hmargin;
3938 y += s->img->vmargin;
06a2c219
GM
3939
3940 if (s->hl == DRAW_IMAGE_SUNKEN
3941 || s->hl == DRAW_IMAGE_RAISED)
3942 {
9ea173e8 3943 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3944 raised_p = s->hl == DRAW_IMAGE_RAISED;
3945 }
3946 else
3947 {
3948 thick = abs (s->img->relief);
3949 raised_p = s->img->relief > 0;
3950 }
3951
3952 x0 = x - thick;
3953 y0 = y - thick;
3954 x1 = x + s->img->width + thick - 1;
3955 y1 = y + s->img->height + thick - 1;
3956
3957 x_setup_relief_colors (s);
3958 x_get_glyph_string_clip_rect (s, &r);
3959 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3960}
3961
3962
3963/* Draw the foreground of image glyph string S to PIXMAP. */
3964
3965static void
3966x_draw_image_foreground_1 (s, pixmap)
3967 struct glyph_string *s;
3968 Pixmap pixmap;
3969{
3970 int x;
95af8492 3971 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3972
3973 /* If first glyph of S has a left box line, start drawing it to the
3974 right of that line. */
3975 if (s->face->box != FACE_NO_BOX
3976 && s->first_glyph->left_box_line_p)
3977 x = s->face->box_line_width;
3978 else
3979 x = 0;
3980
3981 /* If there is a margin around the image, adjust x- and y-position
3982 by that margin. */
22d650b8
GM
3983 x += s->img->hmargin;
3984 y += s->img->vmargin;
dc43ef94 3985
06a2c219
GM
3986 if (s->img->pixmap)
3987 {
3988 if (s->img->mask)
3989 {
3990 /* We can't set both a clip mask and use XSetClipRectangles
3991 because the latter also sets a clip mask. We also can't
3992 trust on the shape extension to be available
3993 (XShapeCombineRegion). So, compute the rectangle to draw
3994 manually. */
3995 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3996 | GCFunction);
3997 XGCValues xgcv;
3998
3999 xgcv.clip_mask = s->img->mask;
4000 xgcv.clip_x_origin = x;
4001 xgcv.clip_y_origin = y;
4002 xgcv.function = GXcopy;
4003 XChangeGC (s->display, s->gc, mask, &xgcv);
4004
4005 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4006 0, 0, s->img->width, s->img->height, x, y);
4007 XSetClipMask (s->display, s->gc, None);
4008 }
4009 else
4010 {
4011 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4012 0, 0, s->img->width, s->img->height, x, y);
4013
4014 /* When the image has a mask, we can expect that at
4015 least part of a mouse highlight or a block cursor will
4016 be visible. If the image doesn't have a mask, make
4017 a block cursor visible by drawing a rectangle around
4018 the image. I believe it's looking better if we do
4019 nothing here for mouse-face. */
4020 if (s->hl == DRAW_CURSOR)
4021 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4022 s->img->width - 1, s->img->height - 1);
4023 }
4024 }
4025 else
4026 /* Draw a rectangle if image could not be loaded. */
4027 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4028 s->img->width - 1, s->img->height - 1);
4029}
dc43ef94 4030
990ba854 4031
06a2c219
GM
4032/* Draw part of the background of glyph string S. X, Y, W, and H
4033 give the rectangle to draw. */
a9a5b0a5 4034
06a2c219
GM
4035static void
4036x_draw_glyph_string_bg_rect (s, x, y, w, h)
4037 struct glyph_string *s;
4038 int x, y, w, h;
4039{
4040 if (s->stippled_p)
4041 {
4042 /* Fill background with a stipple pattern. */
4043 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4044 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4045 XSetFillStyle (s->display, s->gc, FillSolid);
4046 }
4047 else
4048 x_clear_glyph_string_rect (s, x, y, w, h);
4049}
07e34cb0 4050
b5210ea7 4051
06a2c219 4052/* Draw image glyph string S.
dc43ef94 4053
06a2c219
GM
4054 s->y
4055 s->x +-------------------------
4056 | s->face->box
4057 |
4058 | +-------------------------
4059 | | s->img->margin
4060 | |
4061 | | +-------------------
4062 | | | the image
dc43ef94 4063
06a2c219 4064 */
dc43ef94 4065
06a2c219
GM
4066static void
4067x_draw_image_glyph_string (s)
4068 struct glyph_string *s;
4069{
4070 int x, y;
4071 int box_line_width = s->face->box_line_width;
06a2c219
GM
4072 int height;
4073 Pixmap pixmap = None;
4074
4075 height = s->height - 2 * box_line_width;
4076
4077 /* Fill background with face under the image. Do it only if row is
4078 taller than image or if image has a clip mask to reduce
4079 flickering. */
4080 s->stippled_p = s->face->stipple != 0;
4081 if (height > s->img->height
22d650b8
GM
4082 || s->img->hmargin
4083 || s->img->vmargin
06a2c219
GM
4084 || s->img->mask
4085 || s->img->pixmap == 0
4086 || s->width != s->background_width)
4087 {
4088 if (box_line_width && s->first_glyph->left_box_line_p)
4089 x = s->x + box_line_width;
4090 else
4091 x = s->x;
4092
4093 y = s->y + box_line_width;
4094
4095 if (s->img->mask)
4096 {
f9b5db02
GM
4097 /* Create a pixmap as large as the glyph string. Fill it
4098 with the background color. Copy the image to it, using
4099 its mask. Copy the temporary pixmap to the display. */
06a2c219
GM
4100 Screen *screen = FRAME_X_SCREEN (s->f);
4101 int depth = DefaultDepthOfScreen (screen);
4102
4103 /* Create a pixmap as large as the glyph string. */
4104 pixmap = XCreatePixmap (s->display, s->window,
4105 s->background_width,
4106 s->height, depth);
4107
4108 /* Don't clip in the following because we're working on the
4109 pixmap. */
4110 XSetClipMask (s->display, s->gc, None);
4111
4112 /* Fill the pixmap with the background color/stipple. */
4113 if (s->stippled_p)
4114 {
4115 /* Fill background with a stipple pattern. */
4116 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4117 XFillRectangle (s->display, pixmap, s->gc,
4118 0, 0, s->background_width, s->height);
4119 XSetFillStyle (s->display, s->gc, FillSolid);
4120 }
4121 else
4122 {
4123 XGCValues xgcv;
4124 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4125 &xgcv);
4126 XSetForeground (s->display, s->gc, xgcv.background);
4127 XFillRectangle (s->display, pixmap, s->gc,
4128 0, 0, s->background_width, s->height);
4129 XSetForeground (s->display, s->gc, xgcv.foreground);
4130 }
4131 }
4132 else
06a2c219
GM
4133 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4134
4135 s->background_filled_p = 1;
4136 }
dc43ef94 4137
06a2c219
GM
4138 /* Draw the foreground. */
4139 if (pixmap != None)
4140 {
4141 x_draw_image_foreground_1 (s, pixmap);
4142 x_set_glyph_string_clipping (s);
4143 XCopyArea (s->display, pixmap, s->window, s->gc,
4144 0, 0, s->background_width, s->height, s->x, s->y);
4145 XFreePixmap (s->display, pixmap);
4146 }
4147 else
4148 x_draw_image_foreground (s);
b5210ea7 4149
06a2c219
GM
4150 /* If we must draw a relief around the image, do it. */
4151 if (s->img->relief
4152 || s->hl == DRAW_IMAGE_RAISED
4153 || s->hl == DRAW_IMAGE_SUNKEN)
4154 x_draw_image_relief (s);
4155}
8c1a6a84 4156
990ba854 4157
06a2c219 4158/* Draw stretch glyph string S. */
dc43ef94 4159
06a2c219
GM
4160static void
4161x_draw_stretch_glyph_string (s)
4162 struct glyph_string *s;
4163{
4164 xassert (s->first_glyph->type == STRETCH_GLYPH);
4165 s->stippled_p = s->face->stipple != 0;
990ba854 4166
06a2c219
GM
4167 if (s->hl == DRAW_CURSOR
4168 && !x_stretch_cursor_p)
4169 {
4170 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4171 as wide as the stretch glyph. */
4172 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4173
06a2c219
GM
4174 /* Draw cursor. */
4175 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4176
06a2c219
GM
4177 /* Clear rest using the GC of the original non-cursor face. */
4178 if (width < s->background_width)
4179 {
4180 GC gc = s->face->gc;
4181 int x = s->x + width, y = s->y;
4182 int w = s->background_width - width, h = s->height;
4183 XRectangle r;
dc43ef94 4184
06a2c219
GM
4185 x_get_glyph_string_clip_rect (s, &r);
4186 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 4187
06a2c219
GM
4188 if (s->face->stipple)
4189 {
4190 /* Fill background with a stipple pattern. */
4191 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4192 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4193 XSetFillStyle (s->display, gc, FillSolid);
4194 }
4195 else
4196 {
4197 XGCValues xgcv;
4198 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4199 XSetForeground (s->display, gc, xgcv.background);
4200 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4201 XSetForeground (s->display, gc, xgcv.foreground);
4202 }
4203 }
4204 }
4205 else
4206 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4207 s->height);
4208
4209 s->background_filled_p = 1;
4210}
4211
4212
4213/* Draw glyph string S. */
4214
4215static void
4216x_draw_glyph_string (s)
4217 struct glyph_string *s;
4218{
4219 /* If S draws into the background of its successor, draw the
4220 background of the successor first so that S can draw into it.
4221 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4222 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4223 {
4224 xassert (s->next->img == NULL);
4225 x_set_glyph_string_gc (s->next);
4226 x_set_glyph_string_clipping (s->next);
4227 x_draw_glyph_string_background (s->next, 1);
4228 }
97210f4e 4229
06a2c219
GM
4230 /* Set up S->gc, set clipping and draw S. */
4231 x_set_glyph_string_gc (s);
4232 x_set_glyph_string_clipping (s);
4233
4234 switch (s->first_glyph->type)
4235 {
4236 case IMAGE_GLYPH:
4237 x_draw_image_glyph_string (s);
4238 break;
4239
4240 case STRETCH_GLYPH:
4241 x_draw_stretch_glyph_string (s);
4242 break;
4243
4244 case CHAR_GLYPH:
66ac4b0e
GM
4245 if (s->for_overlaps_p)
4246 s->background_filled_p = 1;
4247 else
4248 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4249 x_draw_glyph_string_foreground (s);
4250 break;
4251
b4192550
KH
4252 case COMPOSITE_GLYPH:
4253 if (s->for_overlaps_p || s->gidx > 0)
4254 s->background_filled_p = 1;
4255 else
4256 x_draw_glyph_string_background (s, 1);
4257 x_draw_composite_glyph_string_foreground (s);
4258 break;
4259
06a2c219
GM
4260 default:
4261 abort ();
4262 }
4263
66ac4b0e 4264 if (!s->for_overlaps_p)
06a2c219 4265 {
66ac4b0e
GM
4266 /* Draw underline. */
4267 if (s->face->underline_p)
4268 {
e24e84cc
GM
4269 unsigned long tem, h;
4270 int y;
06a2c219 4271
e24e84cc 4272 /* Get the underline thickness. Default is 1 pixel. */
66ac4b0e
GM
4273 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4274 h = 1;
e24e84cc
GM
4275
4276 /* Get the underline position. This is the recommended
4277 vertical offset in pixels from the baseline to the top of
4278 the underline. This is a signed value according to the
4279 specs, and its default is
4280
4281 ROUND ((maximum descent) / 2), with
4282 ROUND(x) = floor (x + 0.5) */
4283
4284 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4285 y = s->ybase + (long) tem;
4286 else if (s->face->font)
4287 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4288 else
4289 y = s->height - h;
06a2c219 4290
66ac4b0e 4291 if (s->face->underline_defaulted_p)
e24e84cc
GM
4292 XFillRectangle (s->display, s->window, s->gc,
4293 s->x, y, s->width, h);
66ac4b0e
GM
4294 else
4295 {
4296 XGCValues xgcv;
4297 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4298 XSetForeground (s->display, s->gc, s->face->underline_color);
e24e84cc
GM
4299 XFillRectangle (s->display, s->window, s->gc,
4300 s->x, y, s->width, h);
66ac4b0e
GM
4301 XSetForeground (s->display, s->gc, xgcv.foreground);
4302 }
dc6f92b8 4303 }
07e34cb0 4304
66ac4b0e
GM
4305 /* Draw overline. */
4306 if (s->face->overline_p)
06a2c219 4307 {
66ac4b0e
GM
4308 unsigned long dy = 0, h = 1;
4309
4310 if (s->face->overline_color_defaulted_p)
4311 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4312 s->width, h);
4313 else
4314 {
4315 XGCValues xgcv;
4316 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4317 XSetForeground (s->display, s->gc, s->face->overline_color);
4318 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4319 s->width, h);
4320 XSetForeground (s->display, s->gc, xgcv.foreground);
4321 }
06a2c219 4322 }
06a2c219 4323
66ac4b0e
GM
4324 /* Draw strike-through. */
4325 if (s->face->strike_through_p)
06a2c219 4326 {
66ac4b0e
GM
4327 unsigned long h = 1;
4328 unsigned long dy = (s->height - h) / 2;
4329
4330 if (s->face->strike_through_color_defaulted_p)
4331 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4332 s->width, h);
4333 else
4334 {
4335 XGCValues xgcv;
4336 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4337 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4338 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4339 s->width, h);
4340 XSetForeground (s->display, s->gc, xgcv.foreground);
4341 }
06a2c219 4342 }
06a2c219 4343
66ac4b0e
GM
4344 /* Draw relief. */
4345 if (s->face->box != FACE_NO_BOX)
4346 x_draw_glyph_string_box (s);
4347 }
06a2c219
GM
4348
4349 /* Reset clipping. */
4350 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4351}
07e34cb0 4352
06a2c219 4353
b4192550
KH
4354static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4355 struct face **, int));
06a2c219 4356
06a2c219 4357
209f68d9
GM
4358/* Fill glyph string S with composition components specified by S->cmp.
4359
b4192550
KH
4360 FACES is an array of faces for all components of this composition.
4361 S->gidx is the index of the first component for S.
4362 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4363 use its physical height for clipping.
06a2c219 4364
b4192550 4365 Value is the index of a component not in S. */
07e34cb0 4366
b4192550
KH
4367static int
4368x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4369 struct glyph_string *s;
b4192550 4370 struct face **faces;
66ac4b0e 4371 int overlaps_p;
07e34cb0 4372{
b4192550 4373 int i;
06a2c219 4374
b4192550 4375 xassert (s);
06a2c219 4376
b4192550 4377 s->for_overlaps_p = overlaps_p;
06a2c219 4378
b4192550
KH
4379 s->face = faces[s->gidx];
4380 s->font = s->face->font;
4381 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4382
b4192550
KH
4383 /* For all glyphs of this composition, starting at the offset
4384 S->gidx, until we reach the end of the definition or encounter a
4385 glyph that requires the different face, add it to S. */
4386 ++s->nchars;
4387 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4388 ++s->nchars;
06a2c219 4389
b4192550
KH
4390 /* All glyph strings for the same composition has the same width,
4391 i.e. the width set for the first component of the composition. */
06a2c219 4392
06a2c219
GM
4393 s->width = s->first_glyph->pixel_width;
4394
4395 /* If the specified font could not be loaded, use the frame's
4396 default font, but record the fact that we couldn't load it in
4397 the glyph string so that we can draw rectangles for the
4398 characters of the glyph string. */
4399 if (s->font == NULL)
4400 {
4401 s->font_not_found_p = 1;
4402 s->font = FRAME_FONT (s->f);
4403 }
4404
4405 /* Adjust base line for subscript/superscript text. */
4406 s->ybase += s->first_glyph->voffset;
4407
4408 xassert (s->face && s->face->gc);
4409
4410 /* This glyph string must always be drawn with 16-bit functions. */
4411 s->two_byte_p = 1;
b4192550
KH
4412
4413 return s->gidx + s->nchars;
06a2c219
GM
4414}
4415
4416
209f68d9
GM
4417/* Fill glyph string S from a sequence of character glyphs.
4418
06a2c219 4419 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4420 first glyph to consider, END is the index of the last + 1.
4421 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4422 use its physical height for clipping.
66ac4b0e
GM
4423
4424 Value is the index of the first glyph not in S. */
06a2c219
GM
4425
4426static int
66ac4b0e 4427x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4428 struct glyph_string *s;
4429 int face_id;
66ac4b0e 4430 int start, end, overlaps_p;
06a2c219
GM
4431{
4432 struct glyph *glyph, *last;
4433 int voffset;
ee569018 4434 int glyph_not_available_p;
06a2c219 4435
06a2c219
GM
4436 xassert (s->f == XFRAME (s->w->frame));
4437 xassert (s->nchars == 0);
4438 xassert (start >= 0 && end > start);
4439
66ac4b0e 4440 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4441 glyph = s->row->glyphs[s->area] + start;
4442 last = s->row->glyphs[s->area] + end;
4443 voffset = glyph->voffset;
4444
ee569018
KH
4445 glyph_not_available_p = glyph->glyph_not_available_p;
4446
06a2c219
GM
4447 while (glyph < last
4448 && glyph->type == CHAR_GLYPH
4449 && glyph->voffset == voffset
ee569018
KH
4450 /* Same face id implies same font, nowadays. */
4451 && glyph->face_id == face_id
4452 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4453 {
ee569018
KH
4454 int two_byte_p;
4455
06a2c219 4456 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4457 s->char2b + s->nchars,
4458 &two_byte_p);
4459 s->two_byte_p = two_byte_p;
06a2c219
GM
4460 ++s->nchars;
4461 xassert (s->nchars <= end - start);
4462 s->width += glyph->pixel_width;
4463 ++glyph;
4464 }
4465
4466 s->font = s->face->font;
4467 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4468
4469 /* If the specified font could not be loaded, use the frame's font,
4470 but record the fact that we couldn't load it in
4471 S->font_not_found_p so that we can draw rectangles for the
4472 characters of the glyph string. */
ee569018 4473 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4474 {
4475 s->font_not_found_p = 1;
4476 s->font = FRAME_FONT (s->f);
4477 }
4478
4479 /* Adjust base line for subscript/superscript text. */
4480 s->ybase += voffset;
66ac4b0e 4481
06a2c219
GM
4482 xassert (s->face && s->face->gc);
4483 return glyph - s->row->glyphs[s->area];
07e34cb0 4484}
dc6f92b8 4485
06a2c219
GM
4486
4487/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4488
dfcf069d 4489static void
06a2c219
GM
4490x_fill_image_glyph_string (s)
4491 struct glyph_string *s;
4492{
4493 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4494 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4495 xassert (s->img);
43d120d8 4496 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4497 s->font = s->face->font;
4498 s->width = s->first_glyph->pixel_width;
4499
4500 /* Adjust base line for subscript/superscript text. */
4501 s->ybase += s->first_glyph->voffset;
4502}
4503
4504
209f68d9 4505/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4506
209f68d9
GM
4507 ROW is the glyph row in which the glyphs are found, AREA is the
4508 area within the row. START is the index of the first glyph to
4509 consider, END is the index of the last + 1.
4510
4511 Value is the index of the first glyph not in S. */
4512
4513static int
4514x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4515 struct glyph_string *s;
209f68d9
GM
4516 struct glyph_row *row;
4517 enum glyph_row_area area;
4518 int start, end;
06a2c219 4519{
209f68d9
GM
4520 struct glyph *glyph, *last;
4521 int voffset, face_id;
4522
06a2c219 4523 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4524
4525 glyph = s->row->glyphs[s->area] + start;
4526 last = s->row->glyphs[s->area] + end;
4527 face_id = glyph->face_id;
4528 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4529 s->font = s->face->font;
209f68d9
GM
4530 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4531 s->width = glyph->pixel_width;
4532 voffset = glyph->voffset;
4533
4534 for (++glyph;
4535 (glyph < last
4536 && glyph->type == STRETCH_GLYPH
4537 && glyph->voffset == voffset
4538 && glyph->face_id == face_id);
4539 ++glyph)
4540 s->width += glyph->pixel_width;
06a2c219
GM
4541
4542 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4543 s->ybase += voffset;
4544
4545 xassert (s->face && s->face->gc);
4546 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4547}
4548
4549
4550/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4551 of XChar2b structures for S; it can't be allocated in
4552 x_init_glyph_string because it must be allocated via `alloca'. W
4553 is the window on which S is drawn. ROW and AREA are the glyph row
4554 and area within the row from which S is constructed. START is the
4555 index of the first glyph structure covered by S. HL is a
4556 face-override for drawing S. */
4557
4558static void
4559x_init_glyph_string (s, char2b, w, row, area, start, hl)
4560 struct glyph_string *s;
4561 XChar2b *char2b;
4562 struct window *w;
4563 struct glyph_row *row;
4564 enum glyph_row_area area;
4565 int start;
4566 enum draw_glyphs_face hl;
4567{
4568 bzero (s, sizeof *s);
4569 s->w = w;
4570 s->f = XFRAME (w->frame);
4571 s->display = FRAME_X_DISPLAY (s->f);
4572 s->window = FRAME_X_WINDOW (s->f);
4573 s->char2b = char2b;
4574 s->hl = hl;
4575 s->row = row;
4576 s->area = area;
4577 s->first_glyph = row->glyphs[area] + start;
4578 s->height = row->height;
4579 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4580
9ea173e8
GM
4581 /* Display the internal border below the tool-bar window. */
4582 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4583 s->y -= s->f->output_data.x->internal_border_width;
4584
4585 s->ybase = s->y + row->ascent;
4586}
4587
4588
4589/* Set background width of glyph string S. START is the index of the
4590 first glyph following S. LAST_X is the right-most x-position + 1
4591 in the drawing area. */
4592
4593static INLINE void
4594x_set_glyph_string_background_width (s, start, last_x)
4595 struct glyph_string *s;
4596 int start;
4597 int last_x;
4598{
4599 /* If the face of this glyph string has to be drawn to the end of
4600 the drawing area, set S->extends_to_end_of_line_p. */
4601 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4602
4603 if (start == s->row->used[s->area]
4604 && s->hl == DRAW_NORMAL_TEXT
4605 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4606 || s->face->background != default_face->background
4607 || s->face->stipple != default_face->stipple))
4608 s->extends_to_end_of_line_p = 1;
4609
4610 /* If S extends its face to the end of the line, set its
4611 background_width to the distance to the right edge of the drawing
4612 area. */
4613 if (s->extends_to_end_of_line_p)
1da3fd71 4614 s->background_width = last_x - s->x + 1;
06a2c219
GM
4615 else
4616 s->background_width = s->width;
4617}
4618
4619
4620/* Add a glyph string for a stretch glyph to the list of strings
4621 between HEAD and TAIL. START is the index of the stretch glyph in
4622 row area AREA of glyph row ROW. END is the index of the last glyph
4623 in that glyph row area. X is the current output position assigned
4624 to the new glyph string constructed. HL overrides that face of the
4625 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4626 is the right-most x-position of the drawing area. */
4627
8abee2e1
DL
4628/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4629 and below -- keep them on one line. */
4630#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4631 do \
4632 { \
4633 s = (struct glyph_string *) alloca (sizeof *s); \
4634 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4635 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4636 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4637 s->x = (X); \
4638 } \
4639 while (0)
4640
4641
4642/* Add a glyph string for an image glyph to the list of strings
4643 between HEAD and TAIL. START is the index of the image glyph in
4644 row area AREA of glyph row ROW. END is the index of the last glyph
4645 in that glyph row area. X is the current output position assigned
4646 to the new glyph string constructed. HL overrides that face of the
4647 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4648 is the right-most x-position of the drawing area. */
4649
8abee2e1 4650#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4651 do \
4652 { \
4653 s = (struct glyph_string *) alloca (sizeof *s); \
4654 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4655 x_fill_image_glyph_string (s); \
4656 x_append_glyph_string (&HEAD, &TAIL, s); \
4657 ++START; \
4658 s->x = (X); \
4659 } \
4660 while (0)
4661
4662
4663/* Add a glyph string for a sequence of character glyphs to the list
4664 of strings between HEAD and TAIL. START is the index of the first
4665 glyph in row area AREA of glyph row ROW that is part of the new
4666 glyph string. END is the index of the last glyph in that glyph row
4667 area. X is the current output position assigned to the new glyph
4668 string constructed. HL overrides that face of the glyph; e.g. it
4669 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4670 right-most x-position of the drawing area. */
4671
8abee2e1 4672#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4673 do \
4674 { \
3e71d8f2 4675 int c, face_id; \
06a2c219
GM
4676 XChar2b *char2b; \
4677 \
43d120d8 4678 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4679 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4680 \
b4192550
KH
4681 s = (struct glyph_string *) alloca (sizeof *s); \
4682 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4683 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4684 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4685 s->x = (X); \
4686 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4687 OVERLAPS_P); \
06a2c219
GM
4688 } \
4689 while (0)
4690
4691
b4192550
KH
4692/* Add a glyph string for a composite sequence to the list of strings
4693 between HEAD and TAIL. START is the index of the first glyph in
4694 row area AREA of glyph row ROW that is part of the new glyph
4695 string. END is the index of the last glyph in that glyph row area.
4696 X is the current output position assigned to the new glyph string
4697 constructed. HL overrides that face of the glyph; e.g. it is
4698 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4699 x-position of the drawing area. */
4700
6c27ec25 4701#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4702 do { \
43d120d8
KH
4703 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4704 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4705 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4706 struct composition *cmp = composition_table[cmp_id]; \
4707 int glyph_len = cmp->glyph_len; \
4708 XChar2b *char2b; \
4709 struct face **faces; \
4710 struct glyph_string *first_s = NULL; \
4711 int n; \
4712 \
ee569018 4713 base_face = base_face->ascii_face; \
b4192550
KH
4714 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4715 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4716 /* At first, fill in `char2b' and `faces'. */ \
4717 for (n = 0; n < glyph_len; n++) \
4718 { \
43d120d8 4719 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4720 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4721 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4722 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4723 this_face_id, char2b + n, 1); \
b4192550
KH
4724 } \
4725 \
4726 /* Make glyph_strings for each glyph sequence that is drawable by \
4727 the same face, and append them to HEAD/TAIL. */ \
4728 for (n = 0; n < cmp->glyph_len;) \
4729 { \
4730 s = (struct glyph_string *) alloca (sizeof *s); \
4731 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4732 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4733 s->cmp = cmp; \
4734 s->gidx = n; \
b4192550
KH
4735 s->x = (X); \
4736 \
4737 if (n == 0) \
4738 first_s = s; \
4739 \
4740 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4741 } \
4742 \
4743 ++START; \
4744 s = first_s; \
4745 } while (0)
4746
4747
06a2c219
GM
4748/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4749 of AREA of glyph row ROW on window W between indices START and END.
4750 HL overrides the face for drawing glyph strings, e.g. it is
4751 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4752 x-positions of the drawing area.
4753
4754 This is an ugly monster macro construct because we must use alloca
4755 to allocate glyph strings (because x_draw_glyphs can be called
4756 asynchronously). */
4757
8abee2e1 4758#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4759 do \
4760 { \
4761 HEAD = TAIL = NULL; \
4762 while (START < END) \
4763 { \
4764 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4765 switch (first_glyph->type) \
4766 { \
4767 case CHAR_GLYPH: \
4768 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4769 TAIL, HL, X, LAST_X, \
4770 OVERLAPS_P); \
06a2c219
GM
4771 break; \
4772 \
b4192550
KH
4773 case COMPOSITE_GLYPH: \
4774 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4775 HEAD, TAIL, HL, X, LAST_X,\
4776 OVERLAPS_P); \
4777 break; \
4778 \
06a2c219
GM
4779 case STRETCH_GLYPH: \
4780 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4781 HEAD, TAIL, HL, X, LAST_X); \
4782 break; \
4783 \
4784 case IMAGE_GLYPH: \
4785 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4786 TAIL, HL, X, LAST_X); \
4787 break; \
4788 \
4789 default: \
4790 abort (); \
4791 } \
4792 \
4793 x_set_glyph_string_background_width (s, START, LAST_X); \
4794 (X) += s->width; \
4795 } \
4796 } \
4797 while (0)
4798
4799
4800/* Draw glyphs between START and END in AREA of ROW on window W,
4801 starting at x-position X. X is relative to AREA in W. HL is a
4802 face-override with the following meaning:
4803
4804 DRAW_NORMAL_TEXT draw normally
4805 DRAW_CURSOR draw in cursor face
4806 DRAW_MOUSE_FACE draw in mouse face.
4807 DRAW_INVERSE_VIDEO draw in mode line face
4808 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4809 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4810
4811 If REAL_START is non-null, return in *REAL_START the real starting
4812 position for display. This can be different from START in case
4813 overlapping glyphs must be displayed. If REAL_END is non-null,
4814 return in *REAL_END the real end position for display. This can be
4815 different from END in case overlapping glyphs must be displayed.
4816
66ac4b0e
GM
4817 If OVERLAPS_P is non-zero, draw only the foreground of characters
4818 and clip to the physical height of ROW.
4819
06a2c219
GM
4820 Value is the x-position reached, relative to AREA of W. */
4821
4822static int
66ac4b0e
GM
4823x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4824 overlaps_p)
06a2c219
GM
4825 struct window *w;
4826 int x;
4827 struct glyph_row *row;
4828 enum glyph_row_area area;
4829 int start, end;
4830 enum draw_glyphs_face hl;
4831 int *real_start, *real_end;
66ac4b0e 4832 int overlaps_p;
dc6f92b8 4833{
06a2c219
GM
4834 struct glyph_string *head, *tail;
4835 struct glyph_string *s;
4836 int last_x, area_width;
4837 int x_reached;
4838 int i, j;
4839
4840 /* Let's rather be paranoid than getting a SEGV. */
06a2c219 4841 end = min (end, row->used[area]);
a8710abf
GM
4842 start = max (0, start);
4843 start = min (end, start);
06a2c219
GM
4844 if (real_start)
4845 *real_start = start;
4846 if (real_end)
4847 *real_end = end;
4848
4849 /* Translate X to frame coordinates. Set last_x to the right
4850 end of the drawing area. */
4851 if (row->full_width_p)
4852 {
4853 /* X is relative to the left edge of W, without scroll bars
4854 or flag areas. */
4855 struct frame *f = XFRAME (w->frame);
110859fc 4856 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4857 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4858
06a2c219
GM
4859 x += window_left_x;
4860 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4861 last_x = window_left_x + area_width;
4862
4863 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4864 {
110859fc 4865 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4866 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4867 last_x += width;
4868 else
4869 x -= width;
4870 }
dc6f92b8 4871
b9432a85
GM
4872 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4873 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4874 }
4875 else
dc6f92b8 4876 {
06a2c219
GM
4877 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4878 area_width = window_box_width (w, area);
4879 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4880 }
4881
06a2c219
GM
4882 /* Build a doubly-linked list of glyph_string structures between
4883 head and tail from what we have to draw. Note that the macro
4884 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4885 the reason we use a separate variable `i'. */
4886 i = start;
66ac4b0e
GM
4887 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4888 overlaps_p);
06a2c219
GM
4889 if (tail)
4890 x_reached = tail->x + tail->background_width;
4891 else
4892 x_reached = x;
90e65f07 4893
06a2c219
GM
4894 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4895 the row, redraw some glyphs in front or following the glyph
4896 strings built above. */
a8710abf 4897 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4898 {
4899 int dummy_x = 0;
4900 struct glyph_string *h, *t;
4901
4902 /* Compute overhangs for all glyph strings. */
4903 for (s = head; s; s = s->next)
4904 x_compute_glyph_string_overhangs (s);
4905
4906 /* Prepend glyph strings for glyphs in front of the first glyph
4907 string that are overwritten because of the first glyph
4908 string's left overhang. The background of all strings
4909 prepended must be drawn because the first glyph string
4910 draws over it. */
4911 i = x_left_overwritten (head);
4912 if (i >= 0)
4913 {
4914 j = i;
4915 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4916 DRAW_NORMAL_TEXT, dummy_x, last_x,
4917 overlaps_p);
06a2c219
GM
4918 start = i;
4919 if (real_start)
4920 *real_start = start;
4921 x_compute_overhangs_and_x (t, head->x, 1);
4922 x_prepend_glyph_string_lists (&head, &tail, h, t);
4923 }
58769bee 4924
06a2c219
GM
4925 /* Prepend glyph strings for glyphs in front of the first glyph
4926 string that overwrite that glyph string because of their
4927 right overhang. For these strings, only the foreground must
4928 be drawn, because it draws over the glyph string at `head'.
4929 The background must not be drawn because this would overwrite
4930 right overhangs of preceding glyphs for which no glyph
4931 strings exist. */
4932 i = x_left_overwriting (head);
4933 if (i >= 0)
4934 {
4935 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4936 DRAW_NORMAL_TEXT, dummy_x, last_x,
4937 overlaps_p);
06a2c219
GM
4938 for (s = h; s; s = s->next)
4939 s->background_filled_p = 1;
4940 if (real_start)
4941 *real_start = i;
4942 x_compute_overhangs_and_x (t, head->x, 1);
4943 x_prepend_glyph_string_lists (&head, &tail, h, t);
4944 }
dbcb258a 4945
06a2c219
GM
4946 /* Append glyphs strings for glyphs following the last glyph
4947 string tail that are overwritten by tail. The background of
4948 these strings has to be drawn because tail's foreground draws
4949 over it. */
4950 i = x_right_overwritten (tail);
4951 if (i >= 0)
4952 {
4953 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4954 DRAW_NORMAL_TEXT, x, last_x,
4955 overlaps_p);
06a2c219
GM
4956 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4957 x_append_glyph_string_lists (&head, &tail, h, t);
4958 if (real_end)
4959 *real_end = i;
4960 }
dc6f92b8 4961
06a2c219
GM
4962 /* Append glyph strings for glyphs following the last glyph
4963 string tail that overwrite tail. The foreground of such
4964 glyphs has to be drawn because it writes into the background
4965 of tail. The background must not be drawn because it could
4966 paint over the foreground of following glyphs. */
4967 i = x_right_overwriting (tail);
4968 if (i >= 0)
4969 {
4970 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4971 DRAW_NORMAL_TEXT, x, last_x,
4972 overlaps_p);
06a2c219
GM
4973 for (s = h; s; s = s->next)
4974 s->background_filled_p = 1;
4975 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4976 x_append_glyph_string_lists (&head, &tail, h, t);
4977 if (real_end)
4978 *real_end = i;
4979 }
4980 }
58769bee 4981
06a2c219
GM
4982 /* Draw all strings. */
4983 for (s = head; s; s = s->next)
4984 x_draw_glyph_string (s);
dc6f92b8 4985
06a2c219
GM
4986 /* Value is the x-position up to which drawn, relative to AREA of W.
4987 This doesn't include parts drawn because of overhangs. */
4988 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4989 if (!row->full_width_p)
4990 {
4991 if (area > LEFT_MARGIN_AREA)
4992 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4993 if (area > TEXT_AREA)
4994 x_reached -= window_box_width (w, TEXT_AREA);
4995 }
a8710abf 4996
06a2c219
GM
4997 return x_reached;
4998}
dc6f92b8 4999
dc6f92b8 5000
66ac4b0e
GM
5001/* Fix the display of area AREA of overlapping row ROW in window W. */
5002
5003static void
5004x_fix_overlapping_area (w, row, area)
5005 struct window *w;
5006 struct glyph_row *row;
5007 enum glyph_row_area area;
5008{
5009 int i, x;
5010
5011 BLOCK_INPUT;
5012
5013 if (area == LEFT_MARGIN_AREA)
5014 x = 0;
5015 else if (area == TEXT_AREA)
5016 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5017 else
5018 x = (window_box_width (w, LEFT_MARGIN_AREA)
5019 + window_box_width (w, TEXT_AREA));
5020
5021 for (i = 0; i < row->used[area];)
5022 {
5023 if (row->glyphs[area][i].overlaps_vertically_p)
5024 {
5025 int start = i, start_x = x;
5026
5027 do
5028 {
5029 x += row->glyphs[area][i].pixel_width;
5030 ++i;
5031 }
5032 while (i < row->used[area]
5033 && row->glyphs[area][i].overlaps_vertically_p);
5034
5035 x_draw_glyphs (w, start_x, row, area, start, i,
5036 (row->inverse_p
5037 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5038 NULL, NULL, 1);
5039 }
5040 else
5041 {
5042 x += row->glyphs[area][i].pixel_width;
5043 ++i;
5044 }
5045 }
5046
5047 UNBLOCK_INPUT;
5048}
5049
5050
06a2c219
GM
5051/* Output LEN glyphs starting at START at the nominal cursor position.
5052 Advance the nominal cursor over the text. The global variable
5053 updated_window contains the window being updated, updated_row is
5054 the glyph row being updated, and updated_area is the area of that
5055 row being updated. */
dc6f92b8 5056
06a2c219
GM
5057static void
5058x_write_glyphs (start, len)
5059 struct glyph *start;
5060 int len;
5061{
5062 int x, hpos, real_start, real_end;
d9cdbb3d 5063
06a2c219 5064 xassert (updated_window && updated_row);
dc6f92b8 5065 BLOCK_INPUT;
06a2c219
GM
5066
5067 /* Write glyphs. */
dc6f92b8 5068
06a2c219
GM
5069 hpos = start - updated_row->glyphs[updated_area];
5070 x = x_draw_glyphs (updated_window, output_cursor.x,
5071 updated_row, updated_area,
5072 hpos, hpos + len,
5073 (updated_row->inverse_p
5074 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 5075 &real_start, &real_end, 0);
b30ec466 5076
06a2c219
GM
5077 /* If we drew over the cursor, note that it is not visible any more. */
5078 note_overwritten_text_cursor (updated_window, real_start,
5079 real_end - real_start);
dc6f92b8
JB
5080
5081 UNBLOCK_INPUT;
06a2c219
GM
5082
5083 /* Advance the output cursor. */
5084 output_cursor.hpos += len;
5085 output_cursor.x = x;
dc6f92b8
JB
5086}
5087
0cdd0c9f 5088
06a2c219 5089/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 5090
06a2c219
GM
5091static void
5092x_insert_glyphs (start, len)
5093 struct glyph *start;
5094 register int len;
5095{
5096 struct frame *f;
5097 struct window *w;
5098 int line_height, shift_by_width, shifted_region_width;
5099 struct glyph_row *row;
5100 struct glyph *glyph;
5101 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 5102
06a2c219 5103 xassert (updated_window && updated_row);
0cdd0c9f 5104 BLOCK_INPUT;
06a2c219
GM
5105 w = updated_window;
5106 f = XFRAME (WINDOW_FRAME (w));
5107
5108 /* Get the height of the line we are in. */
5109 row = updated_row;
5110 line_height = row->height;
5111
5112 /* Get the width of the glyphs to insert. */
5113 shift_by_width = 0;
5114 for (glyph = start; glyph < start + len; ++glyph)
5115 shift_by_width += glyph->pixel_width;
5116
5117 /* Get the width of the region to shift right. */
5118 shifted_region_width = (window_box_width (w, updated_area)
5119 - output_cursor.x
5120 - shift_by_width);
5121
5122 /* Shift right. */
5123 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
5124 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5125 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5126 f->output_data.x->normal_gc,
5127 frame_x, frame_y,
5128 shifted_region_width, line_height,
5129 frame_x + shift_by_width, frame_y);
5130
5131 /* Write the glyphs. */
5132 hpos = start - row->glyphs[updated_area];
5133 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 5134 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
5135 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5136
5137 /* Advance the output cursor. */
5138 output_cursor.hpos += len;
5139 output_cursor.x += shift_by_width;
0cdd0c9f
RS
5140 UNBLOCK_INPUT;
5141}
0cdd0c9f 5142
0cdd0c9f 5143
06a2c219
GM
5144/* Delete N glyphs at the nominal cursor position. Not implemented
5145 for X frames. */
c83febd7
RS
5146
5147static void
06a2c219
GM
5148x_delete_glyphs (n)
5149 register int n;
c83febd7 5150{
06a2c219 5151 abort ();
c83febd7
RS
5152}
5153
0cdd0c9f 5154
06a2c219
GM
5155/* Erase the current text line from the nominal cursor position
5156 (inclusive) to pixel column TO_X (exclusive). The idea is that
5157 everything from TO_X onward is already erased.
5158
5159 TO_X is a pixel position relative to updated_area of
5160 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 5161
06a2c219
GM
5162static void
5163x_clear_end_of_line (to_x)
5164 int to_x;
5165{
5166 struct frame *f;
5167 struct window *w = updated_window;
5168 int max_x, min_y, max_y;
5169 int from_x, from_y, to_y;
5170
5171 xassert (updated_window && updated_row);
5172 f = XFRAME (w->frame);
5173
5174 if (updated_row->full_width_p)
5175 {
5176 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5177 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5178 && !w->pseudo_window_p)
5179 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 5180 }
06a2c219
GM
5181 else
5182 max_x = window_box_width (w, updated_area);
5183 max_y = window_text_bottom_y (w);
dc6f92b8 5184
06a2c219
GM
5185 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5186 of window. For TO_X > 0, truncate to end of drawing area. */
5187 if (to_x == 0)
5188 return;
5189 else if (to_x < 0)
5190 to_x = max_x;
5191 else
5192 to_x = min (to_x, max_x);
dbc4e1c1 5193
06a2c219
GM
5194 to_y = min (max_y, output_cursor.y + updated_row->height);
5195
5196 /* Notice if the cursor will be cleared by this operation. */
5197 if (!updated_row->full_width_p)
5198 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 5199
06a2c219
GM
5200 from_x = output_cursor.x;
5201
5202 /* Translate to frame coordinates. */
5203 if (updated_row->full_width_p)
5204 {
5205 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5206 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5207 }
0cdd0c9f
RS
5208 else
5209 {
06a2c219
GM
5210 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5211 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5212 }
5213
045dee35 5214 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5215 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5216 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5217
5218 /* Prevent inadvertently clearing to end of the X window. */
5219 if (to_x > from_x && to_y > from_y)
5220 {
5221 BLOCK_INPUT;
5222 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5223 from_x, from_y, to_x - from_x, to_y - from_y,
5224 False);
5225 UNBLOCK_INPUT;
0cdd0c9f 5226 }
0cdd0c9f 5227}
dbc4e1c1 5228
0cdd0c9f 5229
06a2c219 5230/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5231 frame. Otherwise clear the selected frame. */
06a2c219
GM
5232
5233static void
5234x_clear_frame ()
0cdd0c9f 5235{
06a2c219 5236 struct frame *f;
0cdd0c9f 5237
06a2c219
GM
5238 if (updating_frame)
5239 f = updating_frame;
0cdd0c9f 5240 else
b86bd3dd 5241 f = SELECTED_FRAME ();
58769bee 5242
06a2c219
GM
5243 /* Clearing the frame will erase any cursor, so mark them all as no
5244 longer visible. */
5245 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5246 output_cursor.hpos = output_cursor.vpos = 0;
5247 output_cursor.x = -1;
5248
5249 /* We don't set the output cursor here because there will always
5250 follow an explicit cursor_to. */
5251 BLOCK_INPUT;
5252 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5253
5254 /* We have to clear the scroll bars, too. If we have changed
5255 colors or something like that, then they should be notified. */
5256 x_scroll_bar_clear (f);
0cdd0c9f 5257
06a2c219
GM
5258 XFlush (FRAME_X_DISPLAY (f));
5259 UNBLOCK_INPUT;
dc6f92b8 5260}
06a2c219
GM
5261
5262
dc6f92b8 5263\f
dbc4e1c1
JB
5264/* Invert the middle quarter of the frame for .15 sec. */
5265
06a2c219
GM
5266/* We use the select system call to do the waiting, so we have to make
5267 sure it's available. If it isn't, we just won't do visual bells. */
5268
dbc4e1c1
JB
5269#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5270
06a2c219
GM
5271
5272/* Subtract the `struct timeval' values X and Y, storing the result in
5273 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5274
5275static int
5276timeval_subtract (result, x, y)
5277 struct timeval *result, x, y;
5278{
06a2c219
GM
5279 /* Perform the carry for the later subtraction by updating y. This
5280 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5281 if (x.tv_usec < y.tv_usec)
5282 {
5283 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5284 y.tv_usec -= 1000000 * nsec;
5285 y.tv_sec += nsec;
5286 }
06a2c219 5287
dbc4e1c1
JB
5288 if (x.tv_usec - y.tv_usec > 1000000)
5289 {
5290 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5291 y.tv_usec += 1000000 * nsec;
5292 y.tv_sec -= nsec;
5293 }
5294
06a2c219
GM
5295 /* Compute the time remaining to wait. tv_usec is certainly
5296 positive. */
dbc4e1c1
JB
5297 result->tv_sec = x.tv_sec - y.tv_sec;
5298 result->tv_usec = x.tv_usec - y.tv_usec;
5299
06a2c219
GM
5300 /* Return indication of whether the result should be considered
5301 negative. */
dbc4e1c1
JB
5302 return x.tv_sec < y.tv_sec;
5303}
dc6f92b8 5304
dfcf069d 5305void
f676886a
JB
5306XTflash (f)
5307 struct frame *f;
dc6f92b8 5308{
dbc4e1c1 5309 BLOCK_INPUT;
dc6f92b8 5310
dbc4e1c1
JB
5311 {
5312 GC gc;
dc6f92b8 5313
06a2c219
GM
5314 /* Create a GC that will use the GXxor function to flip foreground
5315 pixels into background pixels. */
dbc4e1c1
JB
5316 {
5317 XGCValues values;
dc6f92b8 5318
dbc4e1c1 5319 values.function = GXxor;
7556890b
RS
5320 values.foreground = (f->output_data.x->foreground_pixel
5321 ^ f->output_data.x->background_pixel);
58769bee 5322
334208b7 5323 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5324 GCFunction | GCForeground, &values);
5325 }
dc6f92b8 5326
dbc4e1c1 5327 {
e84e14c3
RS
5328 /* Get the height not including a menu bar widget. */
5329 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5330 /* Height of each line to flash. */
5331 int flash_height = FRAME_LINE_HEIGHT (f);
5332 /* These will be the left and right margins of the rectangles. */
5333 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5334 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5335
5336 int width;
5337
5338 /* Don't flash the area between a scroll bar and the frame
5339 edge it is next to. */
5340 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5341 {
5342 case vertical_scroll_bar_left:
5343 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5344 break;
5345
5346 case vertical_scroll_bar_right:
5347 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5348 break;
06a2c219
GM
5349
5350 default:
5351 break;
e84e14c3
RS
5352 }
5353
5354 width = flash_right - flash_left;
5355
5356 /* If window is tall, flash top and bottom line. */
5357 if (height > 3 * FRAME_LINE_HEIGHT (f))
5358 {
5359 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5360 flash_left,
5361 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5362 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5363 width, flash_height);
5364 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5365 flash_left,
5366 (height - flash_height
5367 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5368 width, flash_height);
5369 }
5370 else
5371 /* If it is short, flash it all. */
5372 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5373 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5374 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5375
06a2c219 5376 x_flush (f);
dc6f92b8 5377
dbc4e1c1 5378 {
06a2c219 5379 struct timeval wakeup;
dc6f92b8 5380
66c30ea1 5381 EMACS_GET_TIME (wakeup);
dc6f92b8 5382
dbc4e1c1
JB
5383 /* Compute time to wait until, propagating carry from usecs. */
5384 wakeup.tv_usec += 150000;
5385 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5386 wakeup.tv_usec %= 1000000;
5387
5388 /* Keep waiting until past the time wakeup. */
5389 while (1)
5390 {
5391 struct timeval timeout;
5392
66c30ea1 5393 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5394
5395 /* In effect, timeout = wakeup - timeout.
5396 Break if result would be negative. */
5397 if (timeval_subtract (&timeout, wakeup, timeout))
5398 break;
5399
5400 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5401 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5402 }
5403 }
58769bee 5404
e84e14c3
RS
5405 /* If window is tall, flash top and bottom line. */
5406 if (height > 3 * FRAME_LINE_HEIGHT (f))
5407 {
5408 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5409 flash_left,
5410 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5411 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5412 width, flash_height);
5413 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5414 flash_left,
5415 (height - flash_height
5416 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5417 width, flash_height);
5418 }
5419 else
5420 /* If it is short, flash it all. */
5421 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5422 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5423 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5424
334208b7 5425 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5426 x_flush (f);
dc6f92b8 5427 }
dbc4e1c1
JB
5428 }
5429
5430 UNBLOCK_INPUT;
dc6f92b8
JB
5431}
5432
06a2c219 5433#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5434
5435
dc6f92b8
JB
5436/* Make audible bell. */
5437
dfcf069d 5438void
dc6f92b8
JB
5439XTring_bell ()
5440{
b86bd3dd
GM
5441 struct frame *f = SELECTED_FRAME ();
5442
5443 if (FRAME_X_DISPLAY (f))
5444 {
dbc4e1c1 5445#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5446 if (visible_bell)
5447 XTflash (f);
5448 else
dbc4e1c1 5449#endif
b86bd3dd
GM
5450 {
5451 BLOCK_INPUT;
5452 XBell (FRAME_X_DISPLAY (f), 0);
5453 XFlush (FRAME_X_DISPLAY (f));
5454 UNBLOCK_INPUT;
5455 }
dc6f92b8
JB
5456 }
5457}
06a2c219 5458
dc6f92b8 5459\f
06a2c219
GM
5460/* Specify how many text lines, from the top of the window,
5461 should be affected by insert-lines and delete-lines operations.
5462 This, and those operations, are used only within an update
5463 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5464
dfcf069d 5465static void
06a2c219
GM
5466XTset_terminal_window (n)
5467 register int n;
dc6f92b8 5468{
06a2c219 5469 /* This function intentionally left blank. */
dc6f92b8
JB
5470}
5471
06a2c219
GM
5472
5473\f
5474/***********************************************************************
5475 Line Dance
5476 ***********************************************************************/
5477
5478/* Perform an insert-lines or delete-lines operation, inserting N
5479 lines or deleting -N lines at vertical position VPOS. */
5480
dfcf069d 5481static void
06a2c219
GM
5482x_ins_del_lines (vpos, n)
5483 int vpos, n;
dc6f92b8
JB
5484{
5485 abort ();
5486}
06a2c219
GM
5487
5488
5489/* Scroll part of the display as described by RUN. */
dc6f92b8 5490
dfcf069d 5491static void
06a2c219
GM
5492x_scroll_run (w, run)
5493 struct window *w;
5494 struct run *run;
dc6f92b8 5495{
06a2c219
GM
5496 struct frame *f = XFRAME (w->frame);
5497 int x, y, width, height, from_y, to_y, bottom_y;
5498
5499 /* Get frame-relative bounding box of the text display area of W,
5500 without mode lines. Include in this box the flags areas to the
5501 left and right of W. */
5502 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5503 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5504 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5505
5506 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5507 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5508 bottom_y = y + height;
dc6f92b8 5509
06a2c219
GM
5510 if (to_y < from_y)
5511 {
5512 /* Scrolling up. Make sure we don't copy part of the mode
5513 line at the bottom. */
5514 if (from_y + run->height > bottom_y)
5515 height = bottom_y - from_y;
5516 else
5517 height = run->height;
5518 }
dc6f92b8 5519 else
06a2c219
GM
5520 {
5521 /* Scolling down. Make sure we don't copy over the mode line.
5522 at the bottom. */
5523 if (to_y + run->height > bottom_y)
5524 height = bottom_y - to_y;
5525 else
5526 height = run->height;
5527 }
7a13e894 5528
06a2c219
GM
5529 BLOCK_INPUT;
5530
5531 /* Cursor off. Will be switched on again in x_update_window_end. */
5532 updated_window = w;
5533 x_clear_cursor (w);
5534
5535 XCopyArea (FRAME_X_DISPLAY (f),
5536 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5537 f->output_data.x->normal_gc,
5538 x, from_y,
5539 width, height,
5540 x, to_y);
5541
5542 UNBLOCK_INPUT;
5543}
dc6f92b8 5544
dc6f92b8 5545
06a2c219
GM
5546\f
5547/***********************************************************************
5548 Exposure Events
5549 ***********************************************************************/
5550
5551/* Redisplay an exposed area of frame F. X and Y are the upper-left
5552 corner of the exposed rectangle. W and H are width and height of
5553 the exposed area. All are pixel values. W or H zero means redraw
5554 the entire frame. */
dc6f92b8 5555
06a2c219
GM
5556static void
5557expose_frame (f, x, y, w, h)
5558 struct frame *f;
5559 int x, y, w, h;
dc6f92b8 5560{
06a2c219 5561 XRectangle r;
dc6f92b8 5562
06a2c219 5563 TRACE ((stderr, "expose_frame "));
dc6f92b8 5564
06a2c219
GM
5565 /* No need to redraw if frame will be redrawn soon. */
5566 if (FRAME_GARBAGED_P (f))
dc6f92b8 5567 {
06a2c219
GM
5568 TRACE ((stderr, " garbaged\n"));
5569 return;
5570 }
5571
5572 /* If basic faces haven't been realized yet, there is no point in
5573 trying to redraw anything. This can happen when we get an expose
5574 event while Emacs is starting, e.g. by moving another window. */
5575 if (FRAME_FACE_CACHE (f) == NULL
5576 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5577 {
5578 TRACE ((stderr, " no faces\n"));
5579 return;
58769bee 5580 }
06a2c219
GM
5581
5582 if (w == 0 || h == 0)
58769bee 5583 {
06a2c219
GM
5584 r.x = r.y = 0;
5585 r.width = CANON_X_UNIT (f) * f->width;
5586 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5587 }
5588 else
5589 {
06a2c219
GM
5590 r.x = x;
5591 r.y = y;
5592 r.width = w;
5593 r.height = h;
5594 }
5595
5596 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5597 expose_window_tree (XWINDOW (f->root_window), &r);
5598
9ea173e8 5599 if (WINDOWP (f->tool_bar_window))
06a2c219 5600 {
9ea173e8 5601 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5602 XRectangle window_rect;
5603 XRectangle intersection_rect;
5604 int window_x, window_y, window_width, window_height;
5605
5606
5607 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5608 window_rect.x = window_x;
5609 window_rect.y = window_y;
5610 window_rect.width = window_width;
5611 window_rect.height = window_height;
5612
5613 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5614 expose_window (w, &intersection_rect);
5615 }
5616
5617#ifndef USE_X_TOOLKIT
5618 if (WINDOWP (f->menu_bar_window))
5619 {
5620 struct window *w = XWINDOW (f->menu_bar_window);
5621 XRectangle window_rect;
5622 XRectangle intersection_rect;
5623 int window_x, window_y, window_width, window_height;
5624
5625
5626 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5627 window_rect.x = window_x;
5628 window_rect.y = window_y;
5629 window_rect.width = window_width;
5630 window_rect.height = window_height;
5631
5632 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5633 expose_window (w, &intersection_rect);
dc6f92b8 5634 }
06a2c219 5635#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5636}
5637
06a2c219
GM
5638
5639/* Redraw (parts) of all windows in the window tree rooted at W that
5640 intersect R. R contains frame pixel coordinates. */
5641
58769bee 5642static void
06a2c219
GM
5643expose_window_tree (w, r)
5644 struct window *w;
5645 XRectangle *r;
dc6f92b8 5646{
06a2c219
GM
5647 while (w)
5648 {
5649 if (!NILP (w->hchild))
5650 expose_window_tree (XWINDOW (w->hchild), r);
5651 else if (!NILP (w->vchild))
5652 expose_window_tree (XWINDOW (w->vchild), r);
5653 else
5654 {
5655 XRectangle window_rect;
5656 XRectangle intersection_rect;
5657 struct frame *f = XFRAME (w->frame);
5658 int window_x, window_y, window_width, window_height;
5659
5660 /* Frame-relative pixel rectangle of W. */
5661 window_box (w, -1, &window_x, &window_y, &window_width,
5662 &window_height);
5663 window_rect.x
5664 = (window_x
110859fc 5665 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5666 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5667 window_rect.y = window_y;
5668 window_rect.width
5669 = (window_width
110859fc 5670 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5671 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5672 window_rect.height
5673 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5674
5675 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5676 expose_window (w, &intersection_rect);
5677 }
58769bee 5678
06a2c219
GM
5679 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5680 }
5681}
58769bee 5682
dc6f92b8 5683
06a2c219
GM
5684/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5685 which intersects rectangle R. R is in window-relative coordinates. */
5686
5687static void
5688expose_area (w, row, r, area)
5689 struct window *w;
5690 struct glyph_row *row;
5691 XRectangle *r;
5692 enum glyph_row_area area;
5693{
06a2c219
GM
5694 struct glyph *first = row->glyphs[area];
5695 struct glyph *end = row->glyphs[area] + row->used[area];
5696 struct glyph *last;
4bc6dcc7 5697 int first_x, start_x, x;
06a2c219 5698
6fb13182
GM
5699 if (area == TEXT_AREA && row->fill_line_p)
5700 /* If row extends face to end of line write the whole line. */
4bc6dcc7 5701 x_draw_glyphs (w, 0, row, area,
6fb13182 5702 0, row->used[area],
06a2c219 5703 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5704 NULL, NULL, 0);
6fb13182
GM
5705 else
5706 {
4bc6dcc7
GM
5707 /* Set START_X to the window-relative start position for drawing glyphs of
5708 AREA. The first glyph of the text area can be partially visible.
5709 The first glyphs of other areas cannot. */
5710 if (area == LEFT_MARGIN_AREA)
5711 start_x = 0;
5712 else if (area == TEXT_AREA)
5713 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5714 else
5715 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5716 + window_box_width (w, TEXT_AREA));
5717 x = start_x;
5718
6fb13182
GM
5719 /* Find the first glyph that must be redrawn. */
5720 while (first < end
5721 && x + first->pixel_width < r->x)
5722 {
5723 x += first->pixel_width;
5724 ++first;
5725 }
5726
5727 /* Find the last one. */
5728 last = first;
5729 first_x = x;
5730 while (last < end
5731 && x < r->x + r->width)
5732 {
5733 x += last->pixel_width;
5734 ++last;
5735 }
5736
5737 /* Repaint. */
5738 if (last > first)
4bc6dcc7 5739 x_draw_glyphs (w, first_x - start_x, row, area,
6fb13182
GM
5740 first - row->glyphs[area],
5741 last - row->glyphs[area],
5742 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5743 NULL, NULL, 0);
5744 }
06a2c219
GM
5745}
5746
58769bee 5747
06a2c219
GM
5748/* Redraw the parts of the glyph row ROW on window W intersecting
5749 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5750
06a2c219
GM
5751static void
5752expose_line (w, row, r)
5753 struct window *w;
5754 struct glyph_row *row;
5755 XRectangle *r;
5756{
5757 xassert (row->enabled_p);
5758
5759 if (row->mode_line_p || w->pseudo_window_p)
5760 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5761 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5762 NULL, NULL, 0);
06a2c219
GM
5763 else
5764 {
5765 if (row->used[LEFT_MARGIN_AREA])
5766 expose_area (w, row, r, LEFT_MARGIN_AREA);
5767 if (row->used[TEXT_AREA])
5768 expose_area (w, row, r, TEXT_AREA);
5769 if (row->used[RIGHT_MARGIN_AREA])
5770 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5771 x_draw_row_bitmaps (w, row);
5772 }
5773}
dc6f92b8 5774
58769bee 5775
06a2c219
GM
5776/* Return non-zero if W's cursor intersects rectangle R. */
5777
5778static int
5779x_phys_cursor_in_rect_p (w, r)
5780 struct window *w;
5781 XRectangle *r;
5782{
5783 XRectangle cr, result;
5784 struct glyph *cursor_glyph;
5785
5786 cursor_glyph = get_phys_cursor_glyph (w);
5787 if (cursor_glyph)
5788 {
5789 cr.x = w->phys_cursor.x;
5790 cr.y = w->phys_cursor.y;
5791 cr.width = cursor_glyph->pixel_width;
5792 cr.height = w->phys_cursor_height;
5793 return x_intersect_rectangles (&cr, r, &result);
5794 }
5795 else
5796 return 0;
dc6f92b8 5797}
dc6f92b8 5798
06a2c219
GM
5799
5800/* Redraw a rectangle of window W. R is a rectangle in window
5801 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5802
5803static void
06a2c219
GM
5804expose_window (w, r)
5805 struct window *w;
5806 XRectangle *r;
dc6f92b8 5807{
06a2c219
GM
5808 struct glyph_row *row;
5809 int y;
5810 int yb = window_text_bottom_y (w);
5811 int cursor_cleared_p;
dc6f92b8 5812
80c32bcc
GM
5813 /* If window is not yet fully initialized, do nothing. This can
5814 happen when toolkit scroll bars are used and a window is split.
5815 Reconfiguring the scroll bar will generate an expose for a newly
5816 created window. */
c7911417 5817 if (w->current_matrix == NULL || w == updated_window)
80c32bcc
GM
5818 return;
5819
06a2c219
GM
5820 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5821 r->x, r->y, r->width, r->height));
dc6f92b8 5822
06a2c219
GM
5823 /* Convert to window coordinates. */
5824 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5825 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5826
06a2c219
GM
5827 /* Turn off the cursor. */
5828 if (!w->pseudo_window_p
5829 && x_phys_cursor_in_rect_p (w, r))
5830 {
5831 x_clear_cursor (w);
5832 cursor_cleared_p = 1;
5833 }
5834 else
5835 cursor_cleared_p = 0;
5836
5837 /* Find the first row intersecting the rectangle R. */
5838 row = w->current_matrix->rows;
5839 y = 0;
5840 while (row->enabled_p
5841 && y < yb
5842 && y + row->height < r->y)
5843 {
5844 y += row->height;
5845 ++row;
5846 }
5847
dc6f92b8 5848 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5849 while (row->enabled_p
5850 && y < yb
5851 && y < r->y + r->height)
5852 {
5853 expose_line (w, row, r);
5854 y += row->height;
5855 ++row;
5856 }
5857
5858 /* Display the mode line if there is one. */
5859 if (WINDOW_WANTS_MODELINE_P (w)
5860 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5861 row->enabled_p)
5862 && row->y < r->y + r->height)
5863 expose_line (w, row, r);
dc6f92b8 5864
06a2c219 5865 if (!w->pseudo_window_p)
dc6f92b8 5866 {
06a2c219
GM
5867 /* Draw border between windows. */
5868 x_draw_vertical_border (w);
5869
5870 /* Turn the cursor on again. */
5871 if (cursor_cleared_p)
5872 x_update_window_cursor (w, 1);
5873 }
5874}
dc6f92b8 5875
dc6f92b8 5876
06a2c219
GM
5877/* Determine the intersection of two rectangles R1 and R2. Return
5878 the intersection in *RESULT. Value is non-zero if RESULT is not
5879 empty. */
5880
5881static int
5882x_intersect_rectangles (r1, r2, result)
5883 XRectangle *r1, *r2, *result;
5884{
5885 XRectangle *left, *right;
5886 XRectangle *upper, *lower;
5887 int intersection_p = 0;
5888
5889 /* Rearrange so that R1 is the left-most rectangle. */
5890 if (r1->x < r2->x)
5891 left = r1, right = r2;
5892 else
5893 left = r2, right = r1;
5894
5895 /* X0 of the intersection is right.x0, if this is inside R1,
5896 otherwise there is no intersection. */
5897 if (right->x <= left->x + left->width)
5898 {
5899 result->x = right->x;
5900
5901 /* The right end of the intersection is the minimum of the
5902 the right ends of left and right. */
5903 result->width = (min (left->x + left->width, right->x + right->width)
5904 - result->x);
5905
5906 /* Same game for Y. */
5907 if (r1->y < r2->y)
5908 upper = r1, lower = r2;
5909 else
5910 upper = r2, lower = r1;
5911
5912 /* The upper end of the intersection is lower.y0, if this is inside
5913 of upper. Otherwise, there is no intersection. */
5914 if (lower->y <= upper->y + upper->height)
dc43ef94 5915 {
06a2c219
GM
5916 result->y = lower->y;
5917
5918 /* The lower end of the intersection is the minimum of the lower
5919 ends of upper and lower. */
5920 result->height = (min (lower->y + lower->height,
5921 upper->y + upper->height)
5922 - result->y);
5923 intersection_p = 1;
dc43ef94 5924 }
dc6f92b8
JB
5925 }
5926
06a2c219 5927 return intersection_p;
dc6f92b8 5928}
06a2c219
GM
5929
5930
5931
5932
dc6f92b8 5933\f
dc6f92b8 5934static void
334208b7
RS
5935frame_highlight (f)
5936 struct frame *f;
dc6f92b8 5937{
b3e1e05c
JB
5938 /* We used to only do this if Vx_no_window_manager was non-nil, but
5939 the ICCCM (section 4.1.6) says that the window's border pixmap
5940 and border pixel are window attributes which are "private to the
5941 client", so we can always change it to whatever we want. */
5942 BLOCK_INPUT;
334208b7 5943 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5944 f->output_data.x->border_pixel);
b3e1e05c 5945 UNBLOCK_INPUT;
5d46f928 5946 x_update_cursor (f, 1);
dc6f92b8
JB
5947}
5948
5949static void
334208b7
RS
5950frame_unhighlight (f)
5951 struct frame *f;
dc6f92b8 5952{
b3e1e05c
JB
5953 /* We used to only do this if Vx_no_window_manager was non-nil, but
5954 the ICCCM (section 4.1.6) says that the window's border pixmap
5955 and border pixel are window attributes which are "private to the
5956 client", so we can always change it to whatever we want. */
5957 BLOCK_INPUT;
334208b7 5958 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5959 f->output_data.x->border_tile);
b3e1e05c 5960 UNBLOCK_INPUT;
5d46f928 5961 x_update_cursor (f, 1);
dc6f92b8 5962}
dc6f92b8 5963
f676886a
JB
5964/* The focus has changed. Update the frames as necessary to reflect
5965 the new situation. Note that we can't change the selected frame
c5acd733 5966 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5967 Each event gets marked with the frame in which it occurred, so the
c5acd733 5968 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5969
6d4238f3 5970static void
0f941935
KH
5971x_new_focus_frame (dpyinfo, frame)
5972 struct x_display_info *dpyinfo;
f676886a 5973 struct frame *frame;
dc6f92b8 5974{
0f941935 5975 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5976
0f941935 5977 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5978 {
58769bee 5979 /* Set this before calling other routines, so that they see
f676886a 5980 the correct value of x_focus_frame. */
0f941935 5981 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5982
5983 if (old_focus && old_focus->auto_lower)
f676886a 5984 x_lower_frame (old_focus);
dc6f92b8
JB
5985
5986#if 0
f676886a 5987 selected_frame = frame;
e0c1aef2
KH
5988 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5989 selected_frame);
f676886a
JB
5990 Fselect_window (selected_frame->selected_window);
5991 choose_minibuf_frame ();
c118dd06 5992#endif /* ! 0 */
dc6f92b8 5993
0f941935
KH
5994 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5995 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5996 else
5997 pending_autoraise_frame = 0;
6d4238f3 5998 }
dc6f92b8 5999
0f941935 6000 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
6001}
6002
37c2c98b
RS
6003/* Handle an event saying the mouse has moved out of an Emacs frame. */
6004
6005void
0f941935
KH
6006x_mouse_leave (dpyinfo)
6007 struct x_display_info *dpyinfo;
37c2c98b 6008{
0f941935 6009 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 6010}
6d4238f3 6011
f451eb13
JB
6012/* The focus has changed, or we have redirected a frame's focus to
6013 another frame (this happens when a frame uses a surrogate
06a2c219 6014 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
6015
6016 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 6017 frame is being highlighted or un-highlighted; we only use it to find
0f941935 6018 the appropriate X display info. */
06a2c219 6019
6d4238f3 6020static void
0f941935
KH
6021XTframe_rehighlight (frame)
6022 struct frame *frame;
6d4238f3 6023{
0f941935
KH
6024 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6025}
6d4238f3 6026
0f941935
KH
6027static void
6028x_frame_rehighlight (dpyinfo)
6029 struct x_display_info *dpyinfo;
6030{
6031 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6032
6033 if (dpyinfo->x_focus_frame)
6d4238f3 6034 {
0f941935
KH
6035 dpyinfo->x_highlight_frame
6036 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6037 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6038 : dpyinfo->x_focus_frame);
6039 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 6040 {
0f941935
KH
6041 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6042 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 6043 }
dc6f92b8 6044 }
6d4238f3 6045 else
0f941935 6046 dpyinfo->x_highlight_frame = 0;
dc6f92b8 6047
0f941935 6048 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
6049 {
6050 if (old_highlight)
f676886a 6051 frame_unhighlight (old_highlight);
0f941935
KH
6052 if (dpyinfo->x_highlight_frame)
6053 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 6054 }
dc6f92b8 6055}
06a2c219
GM
6056
6057
dc6f92b8 6058\f
06a2c219 6059/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 6060
28430d3c
JB
6061/* Initialize mode_switch_bit and modifier_meaning. */
6062static void
334208b7
RS
6063x_find_modifier_meanings (dpyinfo)
6064 struct x_display_info *dpyinfo;
28430d3c 6065{
f689eb05 6066 int min_code, max_code;
28430d3c
JB
6067 KeySym *syms;
6068 int syms_per_code;
6069 XModifierKeymap *mods;
6070
334208b7
RS
6071 dpyinfo->meta_mod_mask = 0;
6072 dpyinfo->shift_lock_mask = 0;
6073 dpyinfo->alt_mod_mask = 0;
6074 dpyinfo->super_mod_mask = 0;
6075 dpyinfo->hyper_mod_mask = 0;
58769bee 6076
9658a521 6077#ifdef HAVE_X11R4
334208b7 6078 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 6079#else
4a60f8c5
RS
6080 min_code = dpyinfo->display->min_keycode;
6081 max_code = dpyinfo->display->max_keycode;
9658a521
JB
6082#endif
6083
334208b7 6084 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
6085 min_code, max_code - min_code + 1,
6086 &syms_per_code);
334208b7 6087 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 6088
58769bee 6089 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 6090 Alt keysyms are on. */
28430d3c 6091 {
06a2c219 6092 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
6093
6094 for (row = 3; row < 8; row++)
6095 for (col = 0; col < mods->max_keypermod; col++)
6096 {
0299d313
RS
6097 KeyCode code
6098 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 6099
af92970c
KH
6100 /* Zeroes are used for filler. Skip them. */
6101 if (code == 0)
6102 continue;
6103
28430d3c
JB
6104 /* Are any of this keycode's keysyms a meta key? */
6105 {
6106 int code_col;
6107
6108 for (code_col = 0; code_col < syms_per_code; code_col++)
6109 {
f689eb05 6110 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 6111
f689eb05 6112 switch (sym)
28430d3c 6113 {
f689eb05
JB
6114 case XK_Meta_L:
6115 case XK_Meta_R:
334208b7 6116 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 6117 break;
f689eb05
JB
6118
6119 case XK_Alt_L:
6120 case XK_Alt_R:
334208b7 6121 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
6122 break;
6123
6124 case XK_Hyper_L:
6125 case XK_Hyper_R:
334208b7 6126 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
6127 break;
6128
6129 case XK_Super_L:
6130 case XK_Super_R:
334208b7 6131 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 6132 break;
11edeb03
JB
6133
6134 case XK_Shift_Lock:
6135 /* Ignore this if it's not on the lock modifier. */
6136 if ((1 << row) == LockMask)
334208b7 6137 dpyinfo->shift_lock_mask = LockMask;
11edeb03 6138 break;
28430d3c
JB
6139 }
6140 }
6141 }
6142 }
6143 }
6144
f689eb05 6145 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 6146 if (! dpyinfo->meta_mod_mask)
a3c44b14 6147 {
334208b7
RS
6148 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6149 dpyinfo->alt_mod_mask = 0;
a3c44b14 6150 }
f689eb05 6151
148c4b70
RS
6152 /* If some keys are both alt and meta,
6153 make them just meta, not alt. */
334208b7 6154 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 6155 {
334208b7 6156 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 6157 }
58769bee 6158
28430d3c 6159 XFree ((char *) syms);
f689eb05 6160 XFreeModifiermap (mods);
28430d3c
JB
6161}
6162
dfeccd2d
JB
6163/* Convert between the modifier bits X uses and the modifier bits
6164 Emacs uses. */
06a2c219 6165
7c5283e4 6166static unsigned int
334208b7
RS
6167x_x_to_emacs_modifiers (dpyinfo, state)
6168 struct x_display_info *dpyinfo;
dc6f92b8
JB
6169 unsigned int state;
6170{
334208b7
RS
6171 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6172 | ((state & ControlMask) ? ctrl_modifier : 0)
6173 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6174 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6175 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6176 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
6177}
6178
dfeccd2d 6179static unsigned int
334208b7
RS
6180x_emacs_to_x_modifiers (dpyinfo, state)
6181 struct x_display_info *dpyinfo;
dfeccd2d
JB
6182 unsigned int state;
6183{
334208b7
RS
6184 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6185 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6186 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6187 | ((state & shift_modifier) ? ShiftMask : 0)
6188 | ((state & ctrl_modifier) ? ControlMask : 0)
6189 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6190}
d047c4eb
KH
6191
6192/* Convert a keysym to its name. */
6193
6194char *
6195x_get_keysym_name (keysym)
6196 KeySym keysym;
6197{
6198 char *value;
6199
6200 BLOCK_INPUT;
6201 value = XKeysymToString (keysym);
6202 UNBLOCK_INPUT;
6203
6204 return value;
6205}
06a2c219
GM
6206
6207
e4571a43
JB
6208\f
6209/* Mouse clicks and mouse movement. Rah. */
e4571a43 6210
06a2c219
GM
6211/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6212 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6213 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6214 not force the value into range. */
69388238 6215
c8dba240 6216void
69388238 6217pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6218 FRAME_PTR f;
69388238 6219 register int pix_x, pix_y;
e4571a43
JB
6220 register int *x, *y;
6221 XRectangle *bounds;
69388238 6222 int noclip;
e4571a43 6223{
06a2c219 6224 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6225 even for negative values. */
6226 if (pix_x < 0)
7556890b 6227 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6228 if (pix_y < 0)
7556890b 6229 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6230
e4571a43
JB
6231 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6232 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6233
6234 if (bounds)
6235 {
7556890b
RS
6236 bounds->width = FONT_WIDTH (f->output_data.x->font);
6237 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6238 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6239 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6240 }
6241
69388238
RS
6242 if (!noclip)
6243 {
6244 if (pix_x < 0)
6245 pix_x = 0;
3cbd2e0b
RS
6246 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6247 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6248
6249 if (pix_y < 0)
6250 pix_y = 0;
6251 else if (pix_y > f->height)
6252 pix_y = f->height;
6253 }
e4571a43
JB
6254
6255 *x = pix_x;
6256 *y = pix_y;
6257}
6258
06a2c219
GM
6259
6260/* Given HPOS/VPOS in the current matrix of W, return corresponding
6261 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6262 can't tell the positions because W's display is not up to date,
6263 return 0. */
6264
6265int
6266glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6267 struct window *w;
6268 int hpos, vpos;
6269 int *frame_x, *frame_y;
2b5c9e71 6270{
06a2c219
GM
6271 int success_p;
6272
6273 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6274 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6275
6276 if (display_completed)
6277 {
6278 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6279 struct glyph *glyph = row->glyphs[TEXT_AREA];
6280 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6281
6282 *frame_y = row->y;
6283 *frame_x = row->x;
6284 while (glyph < end)
6285 {
6286 *frame_x += glyph->pixel_width;
6287 ++glyph;
6288 }
6289
6290 success_p = 1;
6291 }
6292 else
6293 {
6294 *frame_y = *frame_x = 0;
6295 success_p = 0;
6296 }
6297
6298 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6299 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6300 return success_p;
2b5c9e71
RS
6301}
6302
06a2c219 6303
dc6f92b8
JB
6304/* Prepare a mouse-event in *RESULT for placement in the input queue.
6305
6306 If the event is a button press, then note that we have grabbed
f451eb13 6307 the mouse. */
dc6f92b8
JB
6308
6309static Lisp_Object
f451eb13 6310construct_mouse_click (result, event, f)
dc6f92b8
JB
6311 struct input_event *result;
6312 XButtonEvent *event;
f676886a 6313 struct frame *f;
dc6f92b8 6314{
f451eb13 6315 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6316 otherwise. */
f451eb13 6317 result->kind = mouse_click;
69388238 6318 result->code = event->button - Button1;
1113d9db 6319 result->timestamp = event->time;
334208b7
RS
6320 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6321 event->state)
f689eb05 6322 | (event->type == ButtonRelease
58769bee 6323 ? up_modifier
f689eb05 6324 : down_modifier));
dc6f92b8 6325
06a2c219
GM
6326 XSETINT (result->x, event->x);
6327 XSETINT (result->y, event->y);
6328 XSETFRAME (result->frame_or_window, f);
0f8aabe9 6329 result->arg = Qnil;
06a2c219 6330 return Qnil;
dc6f92b8 6331}
b849c413 6332
69388238 6333\f
90e65f07
JB
6334/* Function to report a mouse movement to the mainstream Emacs code.
6335 The input handler calls this.
6336
6337 We have received a mouse movement event, which is given in *event.
6338 If the mouse is over a different glyph than it was last time, tell
6339 the mainstream emacs code by setting mouse_moved. If not, ask for
6340 another motion event, so we can check again the next time it moves. */
b8009dd1 6341
06a2c219
GM
6342static XMotionEvent last_mouse_motion_event;
6343static Lisp_Object last_mouse_motion_frame;
6344
90e65f07 6345static void
12ba150f 6346note_mouse_movement (frame, event)
f676886a 6347 FRAME_PTR frame;
90e65f07 6348 XMotionEvent *event;
90e65f07 6349{
e5d77022 6350 last_mouse_movement_time = event->time;
06a2c219
GM
6351 last_mouse_motion_event = *event;
6352 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6353
27f338af
RS
6354 if (event->window != FRAME_X_WINDOW (frame))
6355 {
39d8bb4d 6356 frame->mouse_moved = 1;
27f338af 6357 last_mouse_scroll_bar = Qnil;
27f338af 6358 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6359 }
6360
90e65f07 6361 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6362 else if (event->x < last_mouse_glyph.x
6363 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6364 || event->y < last_mouse_glyph.y
6365 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6366 {
39d8bb4d 6367 frame->mouse_moved = 1;
ab648270 6368 last_mouse_scroll_bar = Qnil;
b8009dd1 6369 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6370 }
6371}
6372
bf1c0ba1 6373/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6374
06a2c219
GM
6375 int disable_mouse_highlight;
6376
6377
6378\f
6379/************************************************************************
6380 Mouse Face
6381 ************************************************************************/
6382
6383/* Find the glyph under window-relative coordinates X/Y in window W.
6384 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6385 strings. Return in *HPOS and *VPOS the row and column number of
6386 the glyph found. Return in *AREA the glyph area containing X.
6387 Value is a pointer to the glyph found or null if X/Y is not on
6388 text, or we can't tell because W's current matrix is not up to
6389 date. */
6390
6391static struct glyph *
6392x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6393 struct window *w;
6394 int x, y;
6395 int *hpos, *vpos, *area;
6396{
6397 struct glyph *glyph, *end;
3e71d8f2 6398 struct glyph_row *row = NULL;
06a2c219
GM
6399 int x0, i, left_area_width;
6400
6401 /* Find row containing Y. Give up if some row is not enabled. */
6402 for (i = 0; i < w->current_matrix->nrows; ++i)
6403 {
6404 row = MATRIX_ROW (w->current_matrix, i);
6405 if (!row->enabled_p)
6406 return NULL;
6407 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6408 break;
6409 }
6410
6411 *vpos = i;
6412 *hpos = 0;
6413
6414 /* Give up if Y is not in the window. */
6415 if (i == w->current_matrix->nrows)
6416 return NULL;
6417
6418 /* Get the glyph area containing X. */
6419 if (w->pseudo_window_p)
6420 {
6421 *area = TEXT_AREA;
6422 x0 = 0;
6423 }
6424 else
6425 {
6426 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6427 if (x < left_area_width)
6428 {
6429 *area = LEFT_MARGIN_AREA;
6430 x0 = 0;
6431 }
6432 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6433 {
6434 *area = TEXT_AREA;
6435 x0 = row->x + left_area_width;
6436 }
6437 else
6438 {
6439 *area = RIGHT_MARGIN_AREA;
6440 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6441 }
6442 }
6443
6444 /* Find glyph containing X. */
6445 glyph = row->glyphs[*area];
6446 end = glyph + row->used[*area];
6447 while (glyph < end)
6448 {
6449 if (x < x0 + glyph->pixel_width)
6450 {
6451 if (w->pseudo_window_p)
6452 break;
6453 else if (BUFFERP (glyph->object))
6454 break;
6455 }
6456
6457 x0 += glyph->pixel_width;
6458 ++glyph;
6459 }
6460
6461 if (glyph == end)
6462 return NULL;
6463
6464 *hpos = glyph - row->glyphs[*area];
6465 return glyph;
6466}
6467
6468
6469/* Convert frame-relative x/y to coordinates relative to window W.
6470 Takes pseudo-windows into account. */
6471
6472static void
6473frame_to_window_pixel_xy (w, x, y)
6474 struct window *w;
6475 int *x, *y;
6476{
6477 if (w->pseudo_window_p)
6478 {
6479 /* A pseudo-window is always full-width, and starts at the
6480 left edge of the frame, plus a frame border. */
6481 struct frame *f = XFRAME (w->frame);
6482 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6483 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6484 }
6485 else
6486 {
6487 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6488 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6489 }
6490}
6491
6492
e371a781 6493/* Take proper action when mouse has moved to the mode or header line of
06a2c219
GM
6494 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6495 mode line. X is relative to the start of the text display area of
6496 W, so the width of bitmap areas and scroll bars must be subtracted
6497 to get a position relative to the start of the mode line. */
6498
6499static void
6500note_mode_line_highlight (w, x, mode_line_p)
6501 struct window *w;
6502 int x, mode_line_p;
6503{
6504 struct frame *f = XFRAME (w->frame);
6505 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6506 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6507 struct glyph_row *row;
6508
6509 if (mode_line_p)
6510 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6511 else
045dee35 6512 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e371a781 6513
06a2c219
GM
6514 if (row->enabled_p)
6515 {
6516 struct glyph *glyph, *end;
6517 Lisp_Object help, map;
6518 int x0;
6519
6520 /* Find the glyph under X. */
6521 glyph = row->glyphs[TEXT_AREA];
6522 end = glyph + row->used[TEXT_AREA];
6523 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6524 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
e371a781 6525
06a2c219
GM
6526 while (glyph < end
6527 && x >= x0 + glyph->pixel_width)
6528 {
6529 x0 += glyph->pixel_width;
6530 ++glyph;
6531 }
6532
6533 if (glyph < end
6534 && STRINGP (glyph->object)
6535 && XSTRING (glyph->object)->intervals
6536 && glyph->charpos >= 0
6537 && glyph->charpos < XSTRING (glyph->object)->size)
6538 {
6539 /* If we're on a string with `help-echo' text property,
6540 arrange for the help to be displayed. This is done by
6541 setting the global variable help_echo to the help string. */
6542 help = Fget_text_property (make_number (glyph->charpos),
6543 Qhelp_echo, glyph->object);
b7e80413 6544 if (!NILP (help))
be010514
GM
6545 {
6546 help_echo = help;
7cea38bc 6547 XSETWINDOW (help_echo_window, w);
be010514
GM
6548 help_echo_object = glyph->object;
6549 help_echo_pos = glyph->charpos;
6550 }
06a2c219
GM
6551
6552 /* Change the mouse pointer according to what is under X/Y. */
6553 map = Fget_text_property (make_number (glyph->charpos),
6554 Qlocal_map, glyph->object);
02067692 6555 if (KEYMAPP (map))
06a2c219 6556 cursor = f->output_data.x->nontext_cursor;
be010514
GM
6557 else
6558 {
6559 map = Fget_text_property (make_number (glyph->charpos),
6560 Qkeymap, glyph->object);
02067692 6561 if (KEYMAPP (map))
be010514
GM
6562 cursor = f->output_data.x->nontext_cursor;
6563 }
06a2c219
GM
6564 }
6565 }
6566
6567 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6568}
6569
6570
6571/* Take proper action when the mouse has moved to position X, Y on
6572 frame F as regards highlighting characters that have mouse-face
6573 properties. Also de-highlighting chars where the mouse was before.
27f338af 6574 X and Y can be negative or out of range. */
b8009dd1
RS
6575
6576static void
6577note_mouse_highlight (f, x, y)
06a2c219 6578 struct frame *f;
c32cdd9a 6579 int x, y;
b8009dd1 6580{
06a2c219
GM
6581 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6582 int portion;
b8009dd1
RS
6583 Lisp_Object window;
6584 struct window *w;
6585
06a2c219
GM
6586 /* When a menu is active, don't highlight because this looks odd. */
6587#ifdef USE_X_TOOLKIT
6588 if (popup_activated ())
6589 return;
6590#endif
6591
04fff9c0
GM
6592 if (disable_mouse_highlight
6593 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6594 return;
6595
06a2c219
GM
6596 dpyinfo->mouse_face_mouse_x = x;
6597 dpyinfo->mouse_face_mouse_y = y;
6598 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6599
06a2c219 6600 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6601 return;
6602
514e4681
RS
6603 if (gc_in_progress)
6604 {
06a2c219 6605 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6606 return;
6607 }
6608
b8009dd1 6609 /* Which window is that in? */
06a2c219 6610 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6611
6612 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6613 if (! EQ (window, dpyinfo->mouse_face_window))
6614 clear_mouse_face (dpyinfo);
6615
6616 /* Not on a window -> return. */
6617 if (!WINDOWP (window))
6618 return;
6619
6620 /* Convert to window-relative pixel coordinates. */
6621 w = XWINDOW (window);
6622 frame_to_window_pixel_xy (w, &x, &y);
6623
9ea173e8 6624 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6625 buffer. */
9ea173e8 6626 if (EQ (window, f->tool_bar_window))
06a2c219 6627 {
9ea173e8 6628 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6629 return;
6630 }
6631
6632 if (portion == 1 || portion == 3)
6633 {
6634 /* Mouse is on the mode or top line. */
6635 note_mode_line_highlight (w, x, portion == 1);
6636 return;
6637 }
e371a781
GM
6638 else if (portion == 2)
6639 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6640 f->output_data.x->horizontal_drag_cursor);
06a2c219
GM
6641 else
6642 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6643 f->output_data.x->text_cursor);
b8009dd1 6644
0cdd0c9f
RS
6645 /* Are we in a window whose display is up to date?
6646 And verify the buffer's text has not changed. */
06a2c219
GM
6647 if (/* Within text portion of the window. */
6648 portion == 0
0cdd0c9f 6649 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6650 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6651 && (XFASTINT (w->last_overlay_modified)
6652 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6653 {
06a2c219
GM
6654 int hpos, vpos, pos, i, area;
6655 struct glyph *glyph;
b8009dd1 6656
06a2c219
GM
6657 /* Find the glyph under X/Y. */
6658 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6659
6660 /* Clear mouse face if X/Y not over text. */
6661 if (glyph == NULL
6662 || area != TEXT_AREA
6663 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6664 {
06a2c219
GM
6665 clear_mouse_face (dpyinfo);
6666 return;
6667 }
6668
6669 pos = glyph->charpos;
6670 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6671
6672 /* Check for mouse-face and help-echo. */
6673 {
6674 Lisp_Object mouse_face, overlay, position;
6675 Lisp_Object *overlay_vec;
6676 int len, noverlays;
6677 struct buffer *obuf;
6678 int obegv, ozv;
6679
6680 /* If we get an out-of-range value, return now; avoid an error. */
6681 if (pos > BUF_Z (XBUFFER (w->buffer)))
6682 return;
6683
6684 /* Make the window's buffer temporarily current for
6685 overlays_at and compute_char_face. */
6686 obuf = current_buffer;
6687 current_buffer = XBUFFER (w->buffer);
6688 obegv = BEGV;
6689 ozv = ZV;
6690 BEGV = BEG;
6691 ZV = Z;
6692
6693 /* Is this char mouse-active or does it have help-echo? */
6694 XSETINT (position, pos);
6695
6696 /* Put all the overlays we want in a vector in overlay_vec.
6697 Store the length in len. If there are more than 10, make
6698 enough space for all, and try again. */
6699 len = 10;
6700 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6701 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
06a2c219
GM
6702 if (noverlays > len)
6703 {
6704 len = noverlays;
6705 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6706 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
06a2c219 6707 }
f8349001
GM
6708
6709 /* Sort overlays into increasing priority order. */
06a2c219
GM
6710 noverlays = sort_overlays (overlay_vec, noverlays, w);
6711
6712 /* Check mouse-face highlighting. */
6713 if (! (EQ (window, dpyinfo->mouse_face_window)
6714 && vpos >= dpyinfo->mouse_face_beg_row
6715 && vpos <= dpyinfo->mouse_face_end_row
6716 && (vpos > dpyinfo->mouse_face_beg_row
6717 || hpos >= dpyinfo->mouse_face_beg_col)
6718 && (vpos < dpyinfo->mouse_face_end_row
6719 || hpos < dpyinfo->mouse_face_end_col
6720 || dpyinfo->mouse_face_past_end)))
6721 {
6722 /* Clear the display of the old active region, if any. */
6723 clear_mouse_face (dpyinfo);
6724
6725 /* Find the highest priority overlay that has a mouse-face prop. */
6726 overlay = Qnil;
f8349001 6727 for (i = noverlays - 1; i >= 0; --i)
06a2c219
GM
6728 {
6729 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6730 if (!NILP (mouse_face))
6731 {
6732 overlay = overlay_vec[i];
6733 break;
6734 }
6735 }
6736
6737 /* If no overlay applies, get a text property. */
6738 if (NILP (overlay))
6739 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6740
6741 /* Handle the overlay case. */
6742 if (! NILP (overlay))
6743 {
6744 /* Find the range of text around this char that
6745 should be active. */
6746 Lisp_Object before, after;
6747 int ignore;
6748
6749 before = Foverlay_start (overlay);
6750 after = Foverlay_end (overlay);
6751 /* Record this as the current active region. */
6752 fast_find_position (w, XFASTINT (before),
6753 &dpyinfo->mouse_face_beg_col,
6754 &dpyinfo->mouse_face_beg_row,
6755 &dpyinfo->mouse_face_beg_x,
6756 &dpyinfo->mouse_face_beg_y);
6757 dpyinfo->mouse_face_past_end
6758 = !fast_find_position (w, XFASTINT (after),
6759 &dpyinfo->mouse_face_end_col,
6760 &dpyinfo->mouse_face_end_row,
6761 &dpyinfo->mouse_face_end_x,
6762 &dpyinfo->mouse_face_end_y);
6763 dpyinfo->mouse_face_window = window;
6764 dpyinfo->mouse_face_face_id
6765 = face_at_buffer_position (w, pos, 0, 0,
6766 &ignore, pos + 1, 1);
6767
6768 /* Display it as active. */
6769 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6770 }
6771 /* Handle the text property case. */
6772 else if (! NILP (mouse_face))
6773 {
6774 /* Find the range of text around this char that
6775 should be active. */
6776 Lisp_Object before, after, beginning, end;
6777 int ignore;
6778
6779 beginning = Fmarker_position (w->start);
6780 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6781 - XFASTINT (w->window_end_pos)));
6782 before
6783 = Fprevious_single_property_change (make_number (pos + 1),
6784 Qmouse_face,
6785 w->buffer, beginning);
6786 after
6787 = Fnext_single_property_change (position, Qmouse_face,
6788 w->buffer, end);
6789 /* Record this as the current active region. */
6790 fast_find_position (w, XFASTINT (before),
6791 &dpyinfo->mouse_face_beg_col,
6792 &dpyinfo->mouse_face_beg_row,
6793 &dpyinfo->mouse_face_beg_x,
6794 &dpyinfo->mouse_face_beg_y);
6795 dpyinfo->mouse_face_past_end
6796 = !fast_find_position (w, XFASTINT (after),
6797 &dpyinfo->mouse_face_end_col,
6798 &dpyinfo->mouse_face_end_row,
6799 &dpyinfo->mouse_face_end_x,
6800 &dpyinfo->mouse_face_end_y);
6801 dpyinfo->mouse_face_window = window;
6802 dpyinfo->mouse_face_face_id
6803 = face_at_buffer_position (w, pos, 0, 0,
6804 &ignore, pos + 1, 1);
6805
6806 /* Display it as active. */
6807 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6808 }
6809 }
6810
6811 /* Look for a `help-echo' property. */
6812 {
743934db 6813 Lisp_Object help, overlay;
06a2c219
GM
6814
6815 /* Check overlays first. */
f9b5db02 6816 help = overlay = Qnil;
f8349001 6817 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
743934db
GM
6818 {
6819 overlay = overlay_vec[i];
6820 help = Foverlay_get (overlay, Qhelp_echo);
6821 }
be010514
GM
6822
6823 if (!NILP (help))
6824 {
6825 help_echo = help;
7cea38bc 6826 help_echo_window = window;
743934db 6827 help_echo_object = overlay;
be010514
GM
6828 help_echo_pos = pos;
6829 }
6830 else
6831 {
6832 /* Try text properties. */
6833 if ((STRINGP (glyph->object)
06a2c219
GM
6834 && glyph->charpos >= 0
6835 && glyph->charpos < XSTRING (glyph->object)->size)
6836 || (BUFFERP (glyph->object)
6837 && glyph->charpos >= BEGV
be010514
GM
6838 && glyph->charpos < ZV))
6839 help = Fget_text_property (make_number (glyph->charpos),
6840 Qhelp_echo, glyph->object);
06a2c219 6841
be010514
GM
6842 if (!NILP (help))
6843 {
6844 help_echo = help;
7cea38bc 6845 help_echo_window = window;
be010514
GM
6846 help_echo_object = glyph->object;
6847 help_echo_pos = glyph->charpos;
6848 }
6849 }
06a2c219
GM
6850 }
6851
6852 BEGV = obegv;
6853 ZV = ozv;
6854 current_buffer = obuf;
6855 }
6856 }
6857}
6858
6859static void
6860redo_mouse_highlight ()
6861{
6862 if (!NILP (last_mouse_motion_frame)
6863 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6864 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6865 last_mouse_motion_event.x,
6866 last_mouse_motion_event.y);
6867}
6868
6869
6870\f
6871/***********************************************************************
9ea173e8 6872 Tool-bars
06a2c219
GM
6873 ***********************************************************************/
6874
9ea173e8
GM
6875static int x_tool_bar_item P_ ((struct frame *, int, int,
6876 struct glyph **, int *, int *, int *));
06a2c219 6877
9ea173e8 6878/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6879 or -1. */
6880
9ea173e8 6881static int last_tool_bar_item;
06a2c219
GM
6882
6883
9ea173e8
GM
6884/* Get information about the tool-bar item at position X/Y on frame F.
6885 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6886 the current matrix of the tool-bar window of F, or NULL if not
6887 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8daf1204 6888 item in F->tool_bar_items. Value is
06a2c219 6889
9ea173e8 6890 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6891 0 if X/Y is on the same item that was highlighted before.
6892 1 otherwise. */
6893
6894static int
9ea173e8 6895x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6896 struct frame *f;
6897 int x, y;
6898 struct glyph **glyph;
6899 int *hpos, *vpos, *prop_idx;
6900{
6901 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6902 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6903 int area;
6904
6905 /* Find the glyph under X/Y. */
6906 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6907 if (*glyph == NULL)
6908 return -1;
6909
9ea173e8 6910 /* Get the start of this tool-bar item's properties in
8daf1204 6911 f->tool_bar_items. */
9ea173e8 6912 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6913 return -1;
6914
6915 /* Is mouse on the highlighted item? */
9ea173e8 6916 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6917 && *vpos >= dpyinfo->mouse_face_beg_row
6918 && *vpos <= dpyinfo->mouse_face_end_row
6919 && (*vpos > dpyinfo->mouse_face_beg_row
6920 || *hpos >= dpyinfo->mouse_face_beg_col)
6921 && (*vpos < dpyinfo->mouse_face_end_row
6922 || *hpos < dpyinfo->mouse_face_end_col
6923 || dpyinfo->mouse_face_past_end))
6924 return 0;
6925
6926 return 1;
6927}
6928
6929
9ea173e8 6930/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6931 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6932 or ButtonRelase. */
6933
6934static void
9ea173e8 6935x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6936 struct frame *f;
6937 XButtonEvent *button_event;
6938{
6939 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6940 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6941 int hpos, vpos, prop_idx;
6942 struct glyph *glyph;
6943 Lisp_Object enabled_p;
6944 int x = button_event->x;
6945 int y = button_event->y;
6946
9ea173e8 6947 /* If not on the highlighted tool-bar item, return. */
06a2c219 6948 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6949 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6950 return;
6951
6952 /* If item is disabled, do nothing. */
8daf1204 6953 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
6954 if (NILP (enabled_p))
6955 return;
6956
6957 if (button_event->type == ButtonPress)
6958 {
6959 /* Show item in pressed state. */
6960 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6961 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6962 last_tool_bar_item = prop_idx;
06a2c219
GM
6963 }
6964 else
6965 {
6966 Lisp_Object key, frame;
6967 struct input_event event;
6968
6969 /* Show item in released state. */
6970 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6971 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6972
8daf1204 6973 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
06a2c219
GM
6974
6975 XSETFRAME (frame, f);
9ea173e8 6976 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
6977 event.frame_or_window = frame;
6978 event.arg = frame;
06a2c219
GM
6979 kbd_buffer_store_event (&event);
6980
9ea173e8 6981 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
6982 event.frame_or_window = frame;
6983 event.arg = key;
06a2c219
GM
6984 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6985 button_event->state);
6986 kbd_buffer_store_event (&event);
9ea173e8 6987 last_tool_bar_item = -1;
06a2c219
GM
6988 }
6989}
6990
6991
9ea173e8
GM
6992/* Possibly highlight a tool-bar item on frame F when mouse moves to
6993 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6994 note_mouse_highlight. */
6995
6996static void
9ea173e8 6997note_tool_bar_highlight (f, x, y)
06a2c219
GM
6998 struct frame *f;
6999 int x, y;
7000{
9ea173e8 7001 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
7002 struct window *w = XWINDOW (window);
7003 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7004 int hpos, vpos;
7005 struct glyph *glyph;
7006 struct glyph_row *row;
5c187dee 7007 int i;
06a2c219
GM
7008 Lisp_Object enabled_p;
7009 int prop_idx;
7010 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 7011 int mouse_down_p, rc;
06a2c219
GM
7012
7013 /* Function note_mouse_highlight is called with negative x(y
7014 values when mouse moves outside of the frame. */
7015 if (x <= 0 || y <= 0)
7016 {
7017 clear_mouse_face (dpyinfo);
7018 return;
7019 }
7020
9ea173e8 7021 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
7022 if (rc < 0)
7023 {
9ea173e8 7024 /* Not on tool-bar item. */
06a2c219
GM
7025 clear_mouse_face (dpyinfo);
7026 return;
7027 }
7028 else if (rc == 0)
9ea173e8 7029 /* On same tool-bar item as before. */
06a2c219 7030 goto set_help_echo;
b8009dd1 7031
06a2c219
GM
7032 clear_mouse_face (dpyinfo);
7033
9ea173e8 7034 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
7035 mouse_down_p = (dpyinfo->grabbed
7036 && f == last_mouse_frame
7037 && FRAME_LIVE_P (f));
7038 if (mouse_down_p
9ea173e8 7039 && last_tool_bar_item != prop_idx)
06a2c219
GM
7040 return;
7041
7042 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7043 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7044
9ea173e8 7045 /* If tool-bar item is not enabled, don't highlight it. */
8daf1204 7046 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
7047 if (!NILP (enabled_p))
7048 {
7049 /* Compute the x-position of the glyph. In front and past the
7050 image is a space. We include this is the highlighted area. */
7051 row = MATRIX_ROW (w->current_matrix, vpos);
7052 for (i = x = 0; i < hpos; ++i)
7053 x += row->glyphs[TEXT_AREA][i].pixel_width;
7054
7055 /* Record this as the current active region. */
7056 dpyinfo->mouse_face_beg_col = hpos;
7057 dpyinfo->mouse_face_beg_row = vpos;
7058 dpyinfo->mouse_face_beg_x = x;
7059 dpyinfo->mouse_face_beg_y = row->y;
7060 dpyinfo->mouse_face_past_end = 0;
7061
7062 dpyinfo->mouse_face_end_col = hpos + 1;
7063 dpyinfo->mouse_face_end_row = vpos;
7064 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7065 dpyinfo->mouse_face_end_y = row->y;
7066 dpyinfo->mouse_face_window = window;
9ea173e8 7067 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
7068
7069 /* Display it as active. */
7070 show_mouse_face (dpyinfo, draw);
7071 dpyinfo->mouse_face_image_state = draw;
b8009dd1 7072 }
06a2c219
GM
7073
7074 set_help_echo:
7075
9ea173e8 7076 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 7077 XTread_socket does the rest. */
7cea38bc 7078 help_echo_object = help_echo_window = Qnil;
be010514 7079 help_echo_pos = -1;
8daf1204 7080 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
b7e80413 7081 if (NILP (help_echo))
8daf1204 7082 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
b8009dd1 7083}
4d73d038 7084
06a2c219
GM
7085
7086\f
7087/* Find the glyph matrix position of buffer position POS in window W.
7088 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7089 current glyphs must be up to date. If POS is above window start
7090 return (0, 0, 0, 0). If POS is after end of W, return end of
7091 last line in W. */
b8009dd1
RS
7092
7093static int
06a2c219
GM
7094fast_find_position (w, pos, hpos, vpos, x, y)
7095 struct window *w;
b8009dd1 7096 int pos;
06a2c219 7097 int *hpos, *vpos, *x, *y;
b8009dd1 7098{
b8009dd1 7099 int i;
bf1c0ba1 7100 int lastcol;
06a2c219
GM
7101 int maybe_next_line_p = 0;
7102 int line_start_position;
7103 int yb = window_text_bottom_y (w);
7104 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
7105 struct glyph_row *best_row = row;
7106 int row_vpos = 0, best_row_vpos = 0;
7107 int current_x;
7108
7109 while (row->y < yb)
b8009dd1 7110 {
06a2c219
GM
7111 if (row->used[TEXT_AREA])
7112 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7113 else
7114 line_start_position = 0;
7115
7116 if (line_start_position > pos)
b8009dd1 7117 break;
77b68646
RS
7118 /* If the position sought is the end of the buffer,
7119 don't include the blank lines at the bottom of the window. */
06a2c219
GM
7120 else if (line_start_position == pos
7121 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 7122 {
06a2c219 7123 maybe_next_line_p = 1;
77b68646
RS
7124 break;
7125 }
06a2c219
GM
7126 else if (line_start_position > 0)
7127 {
7128 best_row = row;
7129 best_row_vpos = row_vpos;
7130 }
4b0bb6f3
GM
7131
7132 if (row->y + row->height >= yb)
7133 break;
06a2c219
GM
7134
7135 ++row;
7136 ++row_vpos;
b8009dd1 7137 }
06a2c219
GM
7138
7139 /* Find the right column within BEST_ROW. */
7140 lastcol = 0;
7141 current_x = best_row->x;
7142 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 7143 {
06a2c219
GM
7144 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7145 int charpos;
7146
7147 charpos = glyph->charpos;
7148 if (charpos == pos)
bf1c0ba1 7149 {
06a2c219
GM
7150 *hpos = i;
7151 *vpos = best_row_vpos;
7152 *x = current_x;
7153 *y = best_row->y;
bf1c0ba1
RS
7154 return 1;
7155 }
06a2c219 7156 else if (charpos > pos)
4d73d038 7157 break;
06a2c219
GM
7158 else if (charpos > 0)
7159 lastcol = i;
7160
7161 current_x += glyph->pixel_width;
bf1c0ba1 7162 }
b8009dd1 7163
77b68646
RS
7164 /* If we're looking for the end of the buffer,
7165 and we didn't find it in the line we scanned,
7166 use the start of the following line. */
06a2c219 7167 if (maybe_next_line_p)
77b68646 7168 {
06a2c219
GM
7169 ++best_row;
7170 ++best_row_vpos;
7171 lastcol = 0;
7172 current_x = best_row->x;
77b68646
RS
7173 }
7174
06a2c219
GM
7175 *vpos = best_row_vpos;
7176 *hpos = lastcol + 1;
7177 *x = current_x;
7178 *y = best_row->y;
b8009dd1
RS
7179 return 0;
7180}
7181
06a2c219 7182
b8009dd1
RS
7183/* Display the active region described by mouse_face_*
7184 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7185
7186static void
06a2c219 7187show_mouse_face (dpyinfo, draw)
7a13e894 7188 struct x_display_info *dpyinfo;
06a2c219 7189 enum draw_glyphs_face draw;
b8009dd1 7190{
7a13e894 7191 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 7192 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 7193 int i;
06a2c219
GM
7194 int cursor_off_p = 0;
7195 struct cursor_pos saved_cursor;
7196
7197 saved_cursor = output_cursor;
7198
7199 /* If window is in the process of being destroyed, don't bother
7200 to do anything. */
7201 if (w->current_matrix == NULL)
7202 goto set_x_cursor;
7203
7204 /* Recognize when we are called to operate on rows that don't exist
7205 anymore. This can happen when a window is split. */
7206 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7207 goto set_x_cursor;
7208
7209 set_output_cursor (&w->phys_cursor);
7210
7211 /* Note that mouse_face_beg_row etc. are window relative. */
7212 for (i = dpyinfo->mouse_face_beg_row;
7213 i <= dpyinfo->mouse_face_end_row;
7214 i++)
7215 {
7216 int start_hpos, end_hpos, start_x;
7217 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7218
7219 /* Don't do anything if row doesn't have valid contents. */
7220 if (!row->enabled_p)
7221 continue;
7222
7223 /* For all but the first row, the highlight starts at column 0. */
7224 if (i == dpyinfo->mouse_face_beg_row)
7225 {
7226 start_hpos = dpyinfo->mouse_face_beg_col;
7227 start_x = dpyinfo->mouse_face_beg_x;
7228 }
7229 else
7230 {
7231 start_hpos = 0;
7232 start_x = 0;
7233 }
7234
7235 if (i == dpyinfo->mouse_face_end_row)
7236 end_hpos = dpyinfo->mouse_face_end_col;
7237 else
7238 end_hpos = row->used[TEXT_AREA];
7239
7240 /* If the cursor's in the text we are about to rewrite, turn the
7241 cursor off. */
7242 if (!w->pseudo_window_p
7243 && i == output_cursor.vpos
7244 && output_cursor.hpos >= start_hpos - 1
7245 && output_cursor.hpos <= end_hpos)
514e4681 7246 {
06a2c219
GM
7247 x_update_window_cursor (w, 0);
7248 cursor_off_p = 1;
514e4681 7249 }
b8009dd1 7250
06a2c219 7251 if (end_hpos > start_hpos)
64f26cf5
GM
7252 {
7253 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7254 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7255 start_hpos, end_hpos, draw, NULL, NULL, 0);
7256 }
b8009dd1
RS
7257 }
7258
514e4681 7259 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7260 if (cursor_off_p)
7261 x_display_cursor (w, 1,
7262 output_cursor.hpos, output_cursor.vpos,
7263 output_cursor.x, output_cursor.y);
2729a2b5 7264
06a2c219 7265 output_cursor = saved_cursor;
fb3b7de5 7266
06a2c219
GM
7267 set_x_cursor:
7268
7269 /* Change the mouse cursor. */
7270 if (draw == DRAW_NORMAL_TEXT)
7271 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7272 f->output_data.x->text_cursor);
7273 else if (draw == DRAW_MOUSE_FACE)
334208b7 7274 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7275 f->output_data.x->cross_cursor);
27ead1d5 7276 else
334208b7 7277 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7278 f->output_data.x->nontext_cursor);
b8009dd1
RS
7279}
7280
7281/* Clear out the mouse-highlighted active region.
06a2c219 7282 Redraw it un-highlighted first. */
b8009dd1 7283
06a2c219 7284void
7a13e894
RS
7285clear_mouse_face (dpyinfo)
7286 struct x_display_info *dpyinfo;
b8009dd1 7287{
607d9f9f
GM
7288#if 0 /* This prevents redrawing tool bar items when changing from one
7289 to another while a tooltip is open, so don't do it. */
685f4368 7290 if (!NILP (tip_frame))
06a2c219 7291 return;
7948d50a 7292#endif
06a2c219 7293
7a13e894 7294 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7295 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7296
7a13e894
RS
7297 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7298 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7299 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7300}
e687d06e 7301
71b8321e
GM
7302
7303/* Clear any mouse-face on window W. This function is part of the
7304 redisplay interface, and is called from try_window_id and similar
7305 functions to ensure the mouse-highlight is off. */
7306
7307static void
7308x_clear_mouse_face (w)
7309 struct window *w;
7310{
7311 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7312 Lisp_Object window;
7313
2e636f9d 7314 BLOCK_INPUT;
71b8321e
GM
7315 XSETWINDOW (window, w);
7316 if (EQ (window, dpyinfo->mouse_face_window))
7317 clear_mouse_face (dpyinfo);
2e636f9d 7318 UNBLOCK_INPUT;
71b8321e
GM
7319}
7320
7321
e687d06e
RS
7322/* Just discard the mouse face information for frame F, if any.
7323 This is used when the size of F is changed. */
7324
dfcf069d 7325void
e687d06e
RS
7326cancel_mouse_face (f)
7327 FRAME_PTR f;
7328{
7329 Lisp_Object window;
7330 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7331
7332 window = dpyinfo->mouse_face_window;
7333 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7334 {
7335 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7336 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7337 dpyinfo->mouse_face_window = Qnil;
7338 }
7339}
b8009dd1 7340\f
ab648270
JB
7341static struct scroll_bar *x_window_to_scroll_bar ();
7342static void x_scroll_bar_report_motion ();
12ba150f 7343
90e65f07 7344/* Return the current position of the mouse.
2d7fc7e8 7345 *fp should be a frame which indicates which display to ask about.
90e65f07 7346
2d7fc7e8 7347 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7348 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7349 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7350 position on the scroll bar.
12ba150f 7351
2d7fc7e8 7352 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7353 mouse is on, *bar_window to nil, and *x and *y to the character cell
7354 the mouse is over.
7355
06a2c219 7356 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7357 was at this position.
7358
a135645a
RS
7359 Don't store anything if we don't have a valid set of values to report.
7360
90e65f07 7361 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7362 movement. */
90e65f07
JB
7363
7364static void
1cf412ec 7365XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7366 FRAME_PTR *fp;
1cf412ec 7367 int insist;
12ba150f 7368 Lisp_Object *bar_window;
ab648270 7369 enum scroll_bar_part *part;
90e65f07 7370 Lisp_Object *x, *y;
e5d77022 7371 unsigned long *time;
90e65f07 7372{
a135645a
RS
7373 FRAME_PTR f1;
7374
90e65f07
JB
7375 BLOCK_INPUT;
7376
8bcee03e 7377 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7378 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7379 else
7380 {
12ba150f
JB
7381 Window root;
7382 int root_x, root_y;
90e65f07 7383
12ba150f
JB
7384 Window dummy_window;
7385 int dummy;
7386
39d8bb4d
KH
7387 Lisp_Object frame, tail;
7388
7389 /* Clear the mouse-moved flag for every frame on this display. */
7390 FOR_EACH_FRAME (tail, frame)
7391 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7392 XFRAME (frame)->mouse_moved = 0;
7393
ab648270 7394 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7395
7396 /* Figure out which root window we're on. */
334208b7
RS
7397 XQueryPointer (FRAME_X_DISPLAY (*fp),
7398 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7399
7400 /* The root window which contains the pointer. */
7401 &root,
7402
7403 /* Trash which we can't trust if the pointer is on
7404 a different screen. */
7405 &dummy_window,
7406
7407 /* The position on that root window. */
58769bee 7408 &root_x, &root_y,
12ba150f
JB
7409
7410 /* More trash we can't trust. */
7411 &dummy, &dummy,
7412
7413 /* Modifier keys and pointer buttons, about which
7414 we don't care. */
7415 (unsigned int *) &dummy);
7416
7417 /* Now we have a position on the root; find the innermost window
7418 containing the pointer. */
7419 {
7420 Window win, child;
7421 int win_x, win_y;
06a2c219 7422 int parent_x = 0, parent_y = 0;
e99db5a1 7423 int count;
12ba150f
JB
7424
7425 win = root;
69388238 7426
2d7fc7e8
RS
7427 /* XTranslateCoordinates can get errors if the window
7428 structure is changing at the same time this function
7429 is running. So at least we must not crash from them. */
7430
e99db5a1 7431 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7432
334208b7 7433 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7434 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7435 {
69388238
RS
7436 /* If mouse was grabbed on a frame, give coords for that frame
7437 even if the mouse is now outside it. */
334208b7 7438 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7439
12ba150f 7440 /* From-window, to-window. */
69388238 7441 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7442
7443 /* From-position, to-position. */
7444 root_x, root_y, &win_x, &win_y,
7445
7446 /* Child of win. */
7447 &child);
69388238
RS
7448 f1 = last_mouse_frame;
7449 }
7450 else
7451 {
7452 while (1)
7453 {
334208b7 7454 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7455
69388238
RS
7456 /* From-window, to-window. */
7457 root, win,
12ba150f 7458
69388238
RS
7459 /* From-position, to-position. */
7460 root_x, root_y, &win_x, &win_y,
7461
7462 /* Child of win. */
7463 &child);
7464
9af3143a 7465 if (child == None || child == win)
69388238
RS
7466 break;
7467
7468 win = child;
7469 parent_x = win_x;
7470 parent_y = win_y;
7471 }
12ba150f 7472
69388238
RS
7473 /* Now we know that:
7474 win is the innermost window containing the pointer
7475 (XTC says it has no child containing the pointer),
7476 win_x and win_y are the pointer's position in it
7477 (XTC did this the last time through), and
7478 parent_x and parent_y are the pointer's position in win's parent.
7479 (They are what win_x and win_y were when win was child.
7480 If win is the root window, it has no parent, and
7481 parent_{x,y} are invalid, but that's okay, because we'll
7482 never use them in that case.) */
7483
7484 /* Is win one of our frames? */
19126e11 7485 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
aad0f6ab
GM
7486
7487#ifdef USE_X_TOOLKIT
7488 /* If we end up with the menu bar window, say it's not
7489 on the frame. */
7490 if (f1 != NULL
7491 && f1->output_data.x->menubar_widget
7492 && win == XtWindow (f1->output_data.x->menubar_widget))
7493 f1 = NULL;
7494#endif /* USE_X_TOOLKIT */
69388238 7495 }
58769bee 7496
2d7fc7e8
RS
7497 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7498 f1 = 0;
7499
e99db5a1 7500 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7501
ab648270 7502 /* If not, is it one of our scroll bars? */
a135645a 7503 if (! f1)
12ba150f 7504 {
ab648270 7505 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7506
7507 if (bar)
7508 {
a135645a 7509 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7510 win_x = parent_x;
7511 win_y = parent_y;
7512 }
7513 }
90e65f07 7514
8bcee03e 7515 if (f1 == 0 && insist > 0)
b86bd3dd 7516 f1 = SELECTED_FRAME ();
1cf412ec 7517
a135645a 7518 if (f1)
12ba150f 7519 {
06a2c219
GM
7520 /* Ok, we found a frame. Store all the values.
7521 last_mouse_glyph is a rectangle used to reduce the
7522 generation of mouse events. To not miss any motion
7523 events, we must divide the frame into rectangles of the
7524 size of the smallest character that could be displayed
7525 on it, i.e. into the same rectangles that matrices on
7526 the frame are divided into. */
7527
7528#if OLD_REDISPLAY_CODE
2b5c9e71 7529 int ignore1, ignore2;
2b5c9e71 7530 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7531 &last_mouse_glyph,
1cf412ec
RS
7532 FRAME_X_DISPLAY_INFO (f1)->grabbed
7533 || insist);
06a2c219
GM
7534#else
7535 {
7536 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7537 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7538 int x = win_x;
7539 int y = win_y;
7540
7541 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7542 round down even for negative values. */
7543 if (x < 0)
7544 x -= width - 1;
7545 if (y < 0)
7546 y -= height - 1;
7547
7548 last_mouse_glyph.width = width;
7549 last_mouse_glyph.height = height;
7550 last_mouse_glyph.x = (x + width - 1) / width * width;
7551 last_mouse_glyph.y = (y + height - 1) / height * height;
7552 }
7553#endif
12ba150f
JB
7554
7555 *bar_window = Qnil;
7556 *part = 0;
334208b7 7557 *fp = f1;
e0c1aef2
KH
7558 XSETINT (*x, win_x);
7559 XSETINT (*y, win_y);
12ba150f
JB
7560 *time = last_mouse_movement_time;
7561 }
7562 }
7563 }
90e65f07
JB
7564
7565 UNBLOCK_INPUT;
7566}
f451eb13 7567
06a2c219 7568
06a2c219 7569#ifdef USE_X_TOOLKIT
bffcfca9
GM
7570
7571/* Atimer callback function for TIMER. Called every 0.1s to process
7572 Xt timeouts, if needed. We must avoid calling XtAppPending as
7573 much as possible because that function does an implicit XFlush
7574 that slows us down. */
7575
7576static void
7577x_process_timeouts (timer)
7578 struct atimer *timer;
7579{
7580 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7581 {
7582 BLOCK_INPUT;
7583 while (XtAppPending (Xt_app_con) & XtIMTimer)
7584 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7585 UNBLOCK_INPUT;
7586 }
06a2c219
GM
7587}
7588
bffcfca9 7589#endif /* USE_X_TOOLKIT */
06a2c219
GM
7590
7591\f
7592/* Scroll bar support. */
7593
7594/* Given an X window ID, find the struct scroll_bar which manages it.
7595 This can be called in GC, so we have to make sure to strip off mark
7596 bits. */
bffcfca9 7597
06a2c219
GM
7598static struct scroll_bar *
7599x_window_to_scroll_bar (window_id)
7600 Window window_id;
7601{
7602 Lisp_Object tail;
7603
7604 for (tail = Vframe_list;
7605 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7606 tail = XCDR (tail))
06a2c219
GM
7607 {
7608 Lisp_Object frame, bar, condemned;
7609
8e713be6 7610 frame = XCAR (tail);
06a2c219
GM
7611 /* All elements of Vframe_list should be frames. */
7612 if (! GC_FRAMEP (frame))
7613 abort ();
7614
7615 /* Scan this frame's scroll bar list for a scroll bar with the
7616 right window ID. */
7617 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7618 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7619 /* This trick allows us to search both the ordinary and
7620 condemned scroll bar lists with one loop. */
7621 ! GC_NILP (bar) || (bar = condemned,
7622 condemned = Qnil,
7623 ! GC_NILP (bar));
7624 bar = XSCROLL_BAR (bar)->next)
7625 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7626 return XSCROLL_BAR (bar);
7627 }
7628
7629 return 0;
7630}
7631
7632
7633\f
7634/************************************************************************
7635 Toolkit scroll bars
7636 ************************************************************************/
7637
eccc05db 7638#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
7639
7640static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7641static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7642static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7643 struct scroll_bar *));
7644static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7645 int, int, int));
7646
7647
7648/* Id of action hook installed for scroll bars. */
7649
7650static XtActionHookId action_hook_id;
7651
7652/* Lisp window being scrolled. Set when starting to interact with
7653 a toolkit scroll bar, reset to nil when ending the interaction. */
7654
7655static Lisp_Object window_being_scrolled;
7656
7657/* Last scroll bar part sent in xm_scroll_callback. */
7658
7659static int last_scroll_bar_part;
7660
ec18280f
SM
7661/* Whether this is an Xaw with arrow-scrollbars. This should imply
7662 that movements of 1/20 of the screen size are mapped to up/down. */
7663
7664static Boolean xaw3d_arrow_scroll;
7665
7666/* Whether the drag scrolling maintains the mouse at the top of the
7667 thumb. If not, resizing the thumb needs to be done more carefully
7668 to avoid jerkyness. */
7669
7670static Boolean xaw3d_pick_top;
7671
06a2c219
GM
7672
7673/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7674 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7675 the user ends an interaction with the scroll bar, and generates
7676 a `end-scroll' scroll_bar_click' event if so. */
7677
7678static void
7679xt_action_hook (widget, client_data, action_name, event, params,
7680 num_params)
7681 Widget widget;
7682 XtPointer client_data;
7683 String action_name;
7684 XEvent *event;
7685 String *params;
7686 Cardinal *num_params;
7687{
7688 int scroll_bar_p;
7689 char *end_action;
7690
7691#ifdef USE_MOTIF
7692 scroll_bar_p = XmIsScrollBar (widget);
7693 end_action = "Release";
ec18280f 7694#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7695 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7696 end_action = "EndScroll";
ec18280f 7697#endif /* USE_MOTIF */
06a2c219 7698
06a2c219
GM
7699 if (scroll_bar_p
7700 && strcmp (action_name, end_action) == 0
7701 && WINDOWP (window_being_scrolled))
7702 {
7703 struct window *w;
7704
7705 x_send_scroll_bar_event (window_being_scrolled,
7706 scroll_bar_end_scroll, 0, 0);
7707 w = XWINDOW (window_being_scrolled);
7708 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7709 window_being_scrolled = Qnil;
7710 last_scroll_bar_part = -1;
bffcfca9
GM
7711
7712 /* Xt timeouts no longer needed. */
7713 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7714 }
7715}
7716
07b3d16e
GM
7717/* A vector of windows used for communication between
7718 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
7719
7720static struct window **scroll_bar_windows;
7721static int scroll_bar_windows_size;
7722
06a2c219
GM
7723
7724/* Send a client message with message type Xatom_Scrollbar for a
7725 scroll action to the frame of WINDOW. PART is a value identifying
7726 the part of the scroll bar that was clicked on. PORTION is the
7727 amount to scroll of a whole of WHOLE. */
7728
7729static void
7730x_send_scroll_bar_event (window, part, portion, whole)
7731 Lisp_Object window;
7732 int part, portion, whole;
7733{
7734 XEvent event;
7735 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
07b3d16e
GM
7736 struct window *w = XWINDOW (window);
7737 struct frame *f = XFRAME (w->frame);
7738 int i;
06a2c219 7739
07b3d16e
GM
7740 BLOCK_INPUT;
7741
06a2c219
GM
7742 /* Construct a ClientMessage event to send to the frame. */
7743 ev->type = ClientMessage;
7744 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7745 ev->display = FRAME_X_DISPLAY (f);
7746 ev->window = FRAME_X_WINDOW (f);
7747 ev->format = 32;
07b3d16e
GM
7748
7749 /* We can only transfer 32 bits in the XClientMessageEvent, which is
7750 not enough to store a pointer or Lisp_Object on a 64 bit system.
7751 So, store the window in scroll_bar_windows and pass the index
7752 into that array in the event. */
7753 for (i = 0; i < scroll_bar_windows_size; ++i)
7754 if (scroll_bar_windows[i] == NULL)
7755 break;
7756
7757 if (i == scroll_bar_windows_size)
7758 {
7759 int new_size = max (10, 2 * scroll_bar_windows_size);
7760 size_t nbytes = new_size * sizeof *scroll_bar_windows;
7761 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
7762
7763 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
7764 nbytes);
7765 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
7766 scroll_bar_windows_size = new_size;
7767 }
7768
7769 scroll_bar_windows[i] = w;
7770 ev->data.l[0] = (long) i;
06a2c219
GM
7771 ev->data.l[1] = (long) part;
7772 ev->data.l[2] = (long) 0;
7773 ev->data.l[3] = (long) portion;
7774 ev->data.l[4] = (long) whole;
7775
bffcfca9
GM
7776 /* Make Xt timeouts work while the scroll bar is active. */
7777 toolkit_scroll_bar_interaction = 1;
7778
06a2c219
GM
7779 /* Setting the event mask to zero means that the message will
7780 be sent to the client that created the window, and if that
7781 window no longer exists, no event will be sent. */
06a2c219
GM
7782 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7783 UNBLOCK_INPUT;
7784}
7785
7786
7787/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7788 in *IEVENT. */
7789
7790static void
7791x_scroll_bar_to_input_event (event, ievent)
7792 XEvent *event;
7793 struct input_event *ievent;
7794{
7795 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7796 Lisp_Object window;
7797 struct frame *f;
07b3d16e
GM
7798 struct window *w;
7799
7800 w = scroll_bar_windows[ev->data.l[0]];
7801 scroll_bar_windows[ev->data.l[0]] = NULL;
52e386c2 7802
07b3d16e
GM
7803 XSETWINDOW (window, w);
7804 f = XFRAME (w->frame);
06a2c219
GM
7805
7806 ievent->kind = scroll_bar_click;
7807 ievent->frame_or_window = window;
0f8aabe9 7808 ievent->arg = Qnil;
06a2c219
GM
7809 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7810 ievent->part = ev->data.l[1];
7811 ievent->code = ev->data.l[2];
7812 ievent->x = make_number ((int) ev->data.l[3]);
7813 ievent->y = make_number ((int) ev->data.l[4]);
7814 ievent->modifiers = 0;
7815}
7816
7817
7818#ifdef USE_MOTIF
7819
7820/* Minimum and maximum values used for Motif scroll bars. */
7821
7822#define XM_SB_MIN 1
7823#define XM_SB_MAX 10000000
7824#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7825
7826
7827/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7828 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7829 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7830
7831static void
7832xm_scroll_callback (widget, client_data, call_data)
7833 Widget widget;
7834 XtPointer client_data, call_data;
7835{
7836 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7837 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7838 double percent;
7839 int part = -1, whole = 0, portion = 0;
7840
7841 switch (cs->reason)
7842 {
7843 case XmCR_DECREMENT:
7844 bar->dragging = Qnil;
7845 part = scroll_bar_up_arrow;
7846 break;
7847
7848 case XmCR_INCREMENT:
7849 bar->dragging = Qnil;
7850 part = scroll_bar_down_arrow;
7851 break;
7852
7853 case XmCR_PAGE_DECREMENT:
7854 bar->dragging = Qnil;
7855 part = scroll_bar_above_handle;
7856 break;
7857
7858 case XmCR_PAGE_INCREMENT:
7859 bar->dragging = Qnil;
7860 part = scroll_bar_below_handle;
7861 break;
7862
7863 case XmCR_TO_TOP:
7864 bar->dragging = Qnil;
7865 part = scroll_bar_to_top;
7866 break;
7867
7868 case XmCR_TO_BOTTOM:
7869 bar->dragging = Qnil;
7870 part = scroll_bar_to_bottom;
7871 break;
7872
7873 case XmCR_DRAG:
7874 {
7875 int slider_size;
7876 int dragging_down_p = (INTEGERP (bar->dragging)
7877 && XINT (bar->dragging) <= cs->value);
7878
7879 /* Get the slider size. */
7880 BLOCK_INPUT;
7881 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7882 UNBLOCK_INPUT;
7883
7884 /* At the max position of the scroll bar, do a line-wise
7885 movement. Without doing anything, the LessTif scroll bar
7886 calls us with the same cs->value again and again. If we
7887 want to make sure that we can reach the end of the buffer,
7888 we have to do something.
7889
7890 Implementation note: setting bar->dragging always to
7891 cs->value gives a smoother movement at the max position.
7892 Setting it to nil when doing line-wise movement gives
7893 a better slider behavior. */
7894
7895 if (cs->value + slider_size == XM_SB_MAX
7896 || (dragging_down_p
7897 && last_scroll_bar_part == scroll_bar_down_arrow))
7898 {
7899 part = scroll_bar_down_arrow;
7900 bar->dragging = Qnil;
7901 }
7902 else
7903 {
7904 whole = XM_SB_RANGE;
7905 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7906 part = scroll_bar_handle;
7907 bar->dragging = make_number (cs->value);
7908 }
7909 }
7910 break;
7911
7912 case XmCR_VALUE_CHANGED:
7913 break;
7914 };
7915
7916 if (part >= 0)
7917 {
7918 window_being_scrolled = bar->window;
7919 last_scroll_bar_part = part;
7920 x_send_scroll_bar_event (bar->window, part, portion, whole);
7921 }
7922}
7923
7924
ec18280f 7925#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7926
7927
ec18280f 7928/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7929 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7930 scroll bar struct. CALL_DATA is a pointer to a float saying where
7931 the thumb is. */
7932
7933static void
ec18280f 7934xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7935 Widget widget;
7936 XtPointer client_data, call_data;
7937{
7938 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7939 float top = *(float *) call_data;
7940 float shown;
ec18280f
SM
7941 int whole, portion, height;
7942 int part;
06a2c219
GM
7943
7944 /* Get the size of the thumb, a value between 0 and 1. */
7945 BLOCK_INPUT;
ec18280f 7946 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7947 UNBLOCK_INPUT;
7948
7949 whole = 10000000;
7950 portion = shown < 1 ? top * whole : 0;
06a2c219 7951
ec18280f
SM
7952 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7953 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7954 the bottom, so we force the scrolling whenever we see that we're
7955 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7956 we try to ensure that we always stay two pixels away from the
7957 bottom). */
06a2c219
GM
7958 part = scroll_bar_down_arrow;
7959 else
7960 part = scroll_bar_handle;
7961
7962 window_being_scrolled = bar->window;
7963 bar->dragging = make_number (portion);
7964 last_scroll_bar_part = part;
7965 x_send_scroll_bar_event (bar->window, part, portion, whole);
7966}
7967
7968
ec18280f
SM
7969/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7970 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7971 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7972 the scroll bar. CALL_DATA is an integer specifying the action that
7973 has taken place. It's magnitude is in the range 0..height of the
7974 scroll bar. Negative values mean scroll towards buffer start.
7975 Values < height of scroll bar mean line-wise movement. */
7976
7977static void
ec18280f 7978xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7979 Widget widget;
7980 XtPointer client_data, call_data;
7981{
7982 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7983 int position = (int) call_data;
7984 Dimension height;
7985 int part;
7986
7987 /* Get the height of the scroll bar. */
7988 BLOCK_INPUT;
7989 XtVaGetValues (widget, XtNheight, &height, NULL);
7990 UNBLOCK_INPUT;
7991
ec18280f
SM
7992 if (abs (position) >= height)
7993 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7994
7995 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7996 it maps line-movement to call_data = max(5, height/20). */
7997 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7998 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7999 else
ec18280f 8000 part = scroll_bar_move_ratio;
06a2c219
GM
8001
8002 window_being_scrolled = bar->window;
8003 bar->dragging = Qnil;
8004 last_scroll_bar_part = part;
ec18280f 8005 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
8006}
8007
8008
8009#endif /* not USE_MOTIF */
8010
8011
8012/* Create the widget for scroll bar BAR on frame F. Record the widget
8013 and X window of the scroll bar in BAR. */
8014
8015static void
8016x_create_toolkit_scroll_bar (f, bar)
8017 struct frame *f;
8018 struct scroll_bar *bar;
8019{
8020 Window xwindow;
8021 Widget widget;
8022 Arg av[20];
8023 int ac = 0;
8024 char *scroll_bar_name = "verticalScrollBar";
8025 unsigned long pixel;
8026
8027 BLOCK_INPUT;
8028
8029#ifdef USE_MOTIF
8030 /* LessTif 0.85, problems:
8031
8032 1. When the mouse if over the scroll bar, the scroll bar will
8033 get keyboard events. I didn't find a way to turn this off.
8034
8035 2. Do we have to explicitly set the cursor to get an arrow
8036 cursor (see below)? */
8037
8038 /* Set resources. Create the widget. */
8039 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8040 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8041 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8042 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8043 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8044 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8045 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8046
8047 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8048 if (pixel != -1)
8049 {
8050 XtSetArg (av[ac], XmNforeground, pixel);
8051 ++ac;
8052 }
8053
8054 pixel = f->output_data.x->scroll_bar_background_pixel;
8055 if (pixel != -1)
8056 {
8057 XtSetArg (av[ac], XmNbackground, pixel);
8058 ++ac;
8059 }
8060
8061 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8062 scroll_bar_name, av, ac);
8063
8064 /* Add one callback for everything that can happen. */
8065 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8066 (XtPointer) bar);
8067 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8068 (XtPointer) bar);
8069 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8070 (XtPointer) bar);
8071 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8072 (XtPointer) bar);
8073 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8074 (XtPointer) bar);
8075 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8076 (XtPointer) bar);
8077 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8078 (XtPointer) bar);
8079
8080 /* Realize the widget. Only after that is the X window created. */
8081 XtRealizeWidget (widget);
8082
8083 /* Set the cursor to an arrow. I didn't find a resource to do that.
8084 And I'm wondering why it hasn't an arrow cursor by default. */
8085 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8086 f->output_data.x->nontext_cursor);
8087
ec18280f 8088#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
8089
8090 /* Set resources. Create the widget. The background of the
8091 Xaw3d scroll bar widget is a little bit light for my taste.
8092 We don't alter it here to let users change it according
8093 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8094 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8095 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
8096 /* For smoother scrolling with Xaw3d -sm */
8097 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8098 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
8099
8100 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8101 if (pixel != -1)
8102 {
8103 XtSetArg (av[ac], XtNforeground, pixel);
8104 ++ac;
8105 }
8106
8107 pixel = f->output_data.x->scroll_bar_background_pixel;
8108 if (pixel != -1)
8109 {
8110 XtSetArg (av[ac], XtNbackground, pixel);
8111 ++ac;
8112 }
8113
8114 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8115 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
8116
8117 {
8118 char *initial = "";
8119 char *val = initial;
8120 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8121 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8122 if (val == initial)
8123 { /* ARROW_SCROLL */
8124 xaw3d_arrow_scroll = True;
8125 /* Isn't that just a personal preference ? -sm */
8126 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8127 }
8128 }
06a2c219
GM
8129
8130 /* Define callbacks. */
ec18280f
SM
8131 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8132 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
8133 (XtPointer) bar);
8134
8135 /* Realize the widget. Only after that is the X window created. */
8136 XtRealizeWidget (widget);
8137
ec18280f 8138#endif /* !USE_MOTIF */
06a2c219
GM
8139
8140 /* Install an action hook that let's us detect when the user
8141 finishes interacting with a scroll bar. */
8142 if (action_hook_id == 0)
8143 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8144
8145 /* Remember X window and widget in the scroll bar vector. */
8146 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8147 xwindow = XtWindow (widget);
8148 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8149
8150 UNBLOCK_INPUT;
8151}
8152
8153
8154/* Set the thumb size and position of scroll bar BAR. We are currently
8155 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8156
8157static void
8158x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8159 struct scroll_bar *bar;
8160 int portion, position, whole;
f451eb13 8161{
e83dc917
GM
8162 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8163 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
06a2c219 8164 float top, shown;
f451eb13 8165
06a2c219
GM
8166 if (whole == 0)
8167 top = 0, shown = 1;
8168 else
f451eb13 8169 {
06a2c219
GM
8170 top = (float) position / whole;
8171 shown = (float) portion / whole;
8172 }
f451eb13 8173
06a2c219 8174 BLOCK_INPUT;
f451eb13 8175
06a2c219
GM
8176#ifdef USE_MOTIF
8177 {
8178 int size, value;
8179 Boolean arrow1_selected, arrow2_selected;
8180 unsigned char flags;
8181 XmScrollBarWidget sb;
8182
ec18280f 8183 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
8184 is the scroll bar's maximum and MIN is the scroll bar's minimum
8185 value. */
8186 size = shown * XM_SB_RANGE;
8187 size = min (size, XM_SB_RANGE);
8188 size = max (size, 1);
8189
8190 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8191 value = top * XM_SB_RANGE;
8192 value = min (value, XM_SB_MAX - size);
8193 value = max (value, XM_SB_MIN);
8194
8195 /* LessTif: Calling XmScrollBarSetValues after an increment or
8196 decrement turns off auto-repeat LessTif-internally. This can
8197 be seen in ScrollBar.c which resets Arrow1Selected and
8198 Arrow2Selected. It also sets internal flags so that LessTif
8199 believes the mouse is in the slider. We either have to change
8200 our code, or work around that by accessing private data. */
8201
8202 sb = (XmScrollBarWidget) widget;
8203 arrow1_selected = sb->scrollBar.arrow1_selected;
8204 arrow2_selected = sb->scrollBar.arrow2_selected;
8205 flags = sb->scrollBar.flags;
8206
8207 if (NILP (bar->dragging))
8208 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8209 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8210 /* This has the negative side effect that the slider value is
ec18280f 8211 not what it would be if we scrolled here using line-wise or
06a2c219
GM
8212 page-wise movement. */
8213 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8214 else
8215 {
8216 /* If currently dragging, only update the slider size.
8217 This reduces flicker effects. */
8218 int old_value, old_size, increment, page_increment;
8219
8220 XmScrollBarGetValues (widget, &old_value, &old_size,
8221 &increment, &page_increment);
8222 XmScrollBarSetValues (widget, old_value,
8223 min (size, XM_SB_RANGE - old_value),
8224 0, 0, False);
8225 }
8226
8227 sb->scrollBar.arrow1_selected = arrow1_selected;
8228 sb->scrollBar.arrow2_selected = arrow2_selected;
8229 sb->scrollBar.flags = flags;
8230 }
ec18280f 8231#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 8232 {
ec18280f
SM
8233 float old_top, old_shown;
8234 Dimension height;
8235 XtVaGetValues (widget,
8236 XtNtopOfThumb, &old_top,
8237 XtNshown, &old_shown,
8238 XtNheight, &height,
8239 NULL);
8240
8241 /* Massage the top+shown values. */
8242 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8243 top = max (0, min (1, top));
8244 else
8245 top = old_top;
8246 /* Keep two pixels available for moving the thumb down. */
8247 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8248
8249 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8250 check that your system's configuration file contains a define
8251 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8252 if (top != old_top || shown != old_shown)
eb393530 8253 {
ec18280f 8254 if (NILP (bar->dragging))
eb393530 8255 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8256 else
8257 {
ec18280f
SM
8258#ifdef HAVE_XAW3D
8259 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8260 int scroll_mode = 0;
ec18280f
SM
8261
8262 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8263 if (xaw3d_arrow_scroll)
8264 {
8265 /* Xaw3d stupidly ignores resize requests while dragging
8266 so we have to make it believe it's not in dragging mode. */
8267 scroll_mode = sb->scrollbar.scroll_mode;
8268 if (scroll_mode == 2)
8269 sb->scrollbar.scroll_mode = 0;
8270 }
8271#endif
8272 /* Try to make the scrolling a tad smoother. */
8273 if (!xaw3d_pick_top)
8274 shown = min (shown, old_shown);
8275
8276 XawScrollbarSetThumb (widget, top, shown);
8277
8278#ifdef HAVE_XAW3D
8279 if (xaw3d_arrow_scroll && scroll_mode == 2)
8280 sb->scrollbar.scroll_mode = scroll_mode;
8281#endif
06a2c219 8282 }
06a2c219
GM
8283 }
8284 }
ec18280f 8285#endif /* !USE_MOTIF */
06a2c219
GM
8286
8287 UNBLOCK_INPUT;
f451eb13
JB
8288}
8289
06a2c219
GM
8290#endif /* USE_TOOLKIT_SCROLL_BARS */
8291
8292
8293\f
8294/************************************************************************
8295 Scroll bars, general
8296 ************************************************************************/
8297
8298/* Create a scroll bar and return the scroll bar vector for it. W is
8299 the Emacs window on which to create the scroll bar. TOP, LEFT,
8300 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8301 scroll bar. */
8302
ab648270 8303static struct scroll_bar *
06a2c219
GM
8304x_scroll_bar_create (w, top, left, width, height)
8305 struct window *w;
f451eb13
JB
8306 int top, left, width, height;
8307{
06a2c219 8308 struct frame *f = XFRAME (w->frame);
334208b7
RS
8309 struct scroll_bar *bar
8310 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8311
8312 BLOCK_INPUT;
8313
eccc05db 8314#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8315 x_create_toolkit_scroll_bar (f, bar);
8316#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8317 {
8318 XSetWindowAttributes a;
8319 unsigned long mask;
5c187dee 8320 Window window;
06a2c219
GM
8321
8322 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8323 if (a.background_pixel == -1)
8324 a.background_pixel = f->output_data.x->background_pixel;
8325
12ba150f 8326 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8327 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8328 | ExposureMask);
7a13e894 8329 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8330
dbc4e1c1 8331 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8332
06a2c219
GM
8333 /* Clear the area of W that will serve as a scroll bar. This is
8334 for the case that a window has been split horizontally. In
8335 this case, no clear_frame is generated to reduce flickering. */
8336 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8337 left, top, width,
8338 window_box_height (w), False);
8339
8340 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8341 /* Position and size of scroll bar. */
8342 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8343 top,
8344 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8345 height,
8346 /* Border width, depth, class, and visual. */
8347 0,
8348 CopyFromParent,
8349 CopyFromParent,
8350 CopyFromParent,
8351 /* Attributes. */
8352 mask, &a);
8353 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8354 }
06a2c219 8355#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8356
06a2c219 8357 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8358 XSETINT (bar->top, top);
8359 XSETINT (bar->left, left);
8360 XSETINT (bar->width, width);
8361 XSETINT (bar->height, height);
8362 XSETINT (bar->start, 0);
8363 XSETINT (bar->end, 0);
12ba150f 8364 bar->dragging = Qnil;
f451eb13
JB
8365
8366 /* Add bar to its frame's list of scroll bars. */
334208b7 8367 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8368 bar->prev = Qnil;
334208b7 8369 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8370 if (!NILP (bar->next))
e0c1aef2 8371 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8372
06a2c219 8373 /* Map the window/widget. */
eccc05db 8374#ifdef USE_TOOLKIT_SCROLL_BARS
e83dc917
GM
8375 {
8376 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8377 XtConfigureWidget (scroll_bar,
06a2c219
GM
8378 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8379 top,
8380 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8381 height, 0);
e83dc917
GM
8382 XtMapWidget (scroll_bar);
8383 }
06a2c219 8384#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8385 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8386#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8387
8388 UNBLOCK_INPUT;
12ba150f 8389 return bar;
f451eb13
JB
8390}
8391
06a2c219 8392
12ba150f 8393/* Draw BAR's handle in the proper position.
06a2c219 8394
12ba150f
JB
8395 If the handle is already drawn from START to END, don't bother
8396 redrawing it, unless REBUILD is non-zero; in that case, always
8397 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8398 events.)
12ba150f
JB
8399
8400 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8401 fit inside its rectangle, but if the user is dragging the scroll
8402 bar handle, we want to let them drag it down all the way, so that
8403 the bar's top is as far down as it goes; otherwise, there's no way
8404 to move to the very end of the buffer. */
8405
5c187dee
GM
8406#ifndef USE_TOOLKIT_SCROLL_BARS
8407
f451eb13 8408static void
ab648270
JB
8409x_scroll_bar_set_handle (bar, start, end, rebuild)
8410 struct scroll_bar *bar;
f451eb13 8411 int start, end;
12ba150f 8412 int rebuild;
f451eb13 8413{
12ba150f 8414 int dragging = ! NILP (bar->dragging);
ab648270 8415 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8416 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8417 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8418
8419 /* If the display is already accurate, do nothing. */
8420 if (! rebuild
8421 && start == XINT (bar->start)
8422 && end == XINT (bar->end))
8423 return;
8424
f451eb13
JB
8425 BLOCK_INPUT;
8426
8427 {
d9cdbb3d
RS
8428 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8429 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8430 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8431
8432 /* Make sure the values are reasonable, and try to preserve
8433 the distance between start and end. */
12ba150f
JB
8434 {
8435 int length = end - start;
8436
8437 if (start < 0)
8438 start = 0;
8439 else if (start > top_range)
8440 start = top_range;
8441 end = start + length;
8442
8443 if (end < start)
8444 end = start;
8445 else if (end > top_range && ! dragging)
8446 end = top_range;
8447 }
f451eb13 8448
ab648270 8449 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8450 XSETINT (bar->start, start);
8451 XSETINT (bar->end, end);
f451eb13 8452
12ba150f
JB
8453 /* Clip the end position, just for display. */
8454 if (end > top_range)
8455 end = top_range;
f451eb13 8456
ab648270 8457 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8458 below top positions, to make sure the handle is always at least
8459 that many pixels tall. */
ab648270 8460 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8461
12ba150f
JB
8462 /* Draw the empty space above the handle. Note that we can't clear
8463 zero-height areas; that means "clear to end of window." */
8464 if (0 < start)
334208b7 8465 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8466
12ba150f 8467 /* x, y, width, height, and exposures. */
ab648270
JB
8468 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8469 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8470 inside_width, start,
8471 False);
f451eb13 8472
06a2c219
GM
8473 /* Change to proper foreground color if one is specified. */
8474 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8475 XSetForeground (FRAME_X_DISPLAY (f), gc,
8476 f->output_data.x->scroll_bar_foreground_pixel);
8477
12ba150f 8478 /* Draw the handle itself. */
334208b7 8479 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8480
12ba150f 8481 /* x, y, width, height */
ab648270
JB
8482 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8483 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8484 inside_width, end - start);
f451eb13 8485
06a2c219
GM
8486 /* Restore the foreground color of the GC if we changed it above. */
8487 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8488 XSetForeground (FRAME_X_DISPLAY (f), gc,
8489 f->output_data.x->foreground_pixel);
f451eb13 8490
12ba150f
JB
8491 /* Draw the empty space below the handle. Note that we can't
8492 clear zero-height areas; that means "clear to end of window." */
8493 if (end < inside_height)
334208b7 8494 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8495
12ba150f 8496 /* x, y, width, height, and exposures. */
ab648270
JB
8497 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8498 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8499 inside_width, inside_height - end,
8500 False);
f451eb13 8501
f451eb13
JB
8502 }
8503
f451eb13
JB
8504 UNBLOCK_INPUT;
8505}
8506
5c187dee 8507#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8508
06a2c219
GM
8509/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8510 nil. */
58769bee 8511
12ba150f 8512static void
ab648270
JB
8513x_scroll_bar_remove (bar)
8514 struct scroll_bar *bar;
12ba150f 8515{
e83dc917 8516 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
8517 BLOCK_INPUT;
8518
eccc05db 8519#ifdef USE_TOOLKIT_SCROLL_BARS
e83dc917
GM
8520 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8521#else
8522 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8523#endif
06a2c219 8524
ab648270
JB
8525 /* Disassociate this scroll bar from its window. */
8526 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8527
8528 UNBLOCK_INPUT;
8529}
8530
06a2c219 8531
12ba150f
JB
8532/* Set the handle of the vertical scroll bar for WINDOW to indicate
8533 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8534 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8535 create one. */
06a2c219 8536
12ba150f 8537static void
06a2c219
GM
8538XTset_vertical_scroll_bar (w, portion, whole, position)
8539 struct window *w;
f451eb13
JB
8540 int portion, whole, position;
8541{
06a2c219 8542 struct frame *f = XFRAME (w->frame);
ab648270 8543 struct scroll_bar *bar;
3c6ede7b 8544 int top, height, left, sb_left, width, sb_width;
06a2c219 8545 int window_x, window_y, window_width, window_height;
06a2c219 8546
3c6ede7b 8547 /* Get window dimensions. */
06a2c219 8548 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8549 top = window_y;
8550 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8551 height = window_height;
06a2c219 8552
3c6ede7b 8553 /* Compute the left edge of the scroll bar area. */
06a2c219 8554 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8555 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8556 else
8557 left = XFASTINT (w->left);
8558 left *= CANON_X_UNIT (f);
8559 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8560
8561 /* Compute the width of the scroll bar which might be less than
8562 the width of the area reserved for the scroll bar. */
8563 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8564 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8565 else
3c6ede7b 8566 sb_width = width;
12ba150f 8567
3c6ede7b
GM
8568 /* Compute the left edge of the scroll bar. */
8569#ifdef USE_TOOLKIT_SCROLL_BARS
8570 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8571 sb_left = left + width - sb_width - (width - sb_width) / 2;
8572 else
8573 sb_left = left + (width - sb_width) / 2;
8574#else
8575 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8576 sb_left = left + width - sb_width;
8577 else
8578 sb_left = left;
8579#endif
8580
ab648270 8581 /* Does the scroll bar exist yet? */
06a2c219 8582 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8583 {
80c32bcc 8584 BLOCK_INPUT;
3c6ede7b
GM
8585 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8586 left, top, width, height, False);
80c32bcc 8587 UNBLOCK_INPUT;
3c6ede7b
GM
8588 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8589 }
f451eb13 8590 else
12ba150f
JB
8591 {
8592 /* It may just need to be moved and resized. */
06a2c219
GM
8593 unsigned int mask = 0;
8594
8595 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8596
8597 BLOCK_INPUT;
8598
3c6ede7b 8599 if (sb_left != XINT (bar->left))
06a2c219 8600 mask |= CWX;
3c6ede7b 8601 if (top != XINT (bar->top))
06a2c219 8602 mask |= CWY;
3c6ede7b 8603 if (sb_width != XINT (bar->width))
06a2c219 8604 mask |= CWWidth;
3c6ede7b 8605 if (height != XINT (bar->height))
06a2c219
GM
8606 mask |= CWHeight;
8607
8608#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8609
8610 /* Since toolkit scroll bars are smaller than the space reserved
8611 for them on the frame, we have to clear "under" them. */
8612 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8613 left, top, width, height, False);
06a2c219
GM
8614
8615 /* Move/size the scroll bar widget. */
8616 if (mask)
e83dc917 8617 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
3c6ede7b
GM
8618 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8619 top,
8620 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8621 height, 0);
06a2c219
GM
8622
8623#else /* not USE_TOOLKIT_SCROLL_BARS */
8624
e1f6572f
RS
8625 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8626 {
8627 /* Clear areas not covered by the scroll bar. This makes sure a
8628 previous mode line display is cleared after C-x 2 C-x 1, for
8629 example. Non-toolkit scroll bars are as wide as the area
8630 reserved for scroll bars - trim at both sides. */
8631 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8632 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8633 height, False);
8634 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8635 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8636 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8637 height, False);
8638 }
06a2c219
GM
8639
8640 /* Move/size the scroll bar window. */
8641 if (mask)
8642 {
8643 XWindowChanges wc;
8644
3c6ede7b
GM
8645 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8646 wc.y = top;
8647 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8648 wc.height = height;
06a2c219
GM
8649 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8650 mask, &wc);
8651 }
8652
8653#endif /* not USE_TOOLKIT_SCROLL_BARS */
8654
8655 /* Remember new settings. */
3c6ede7b
GM
8656 XSETINT (bar->left, sb_left);
8657 XSETINT (bar->top, top);
8658 XSETINT (bar->width, sb_width);
8659 XSETINT (bar->height, height);
06a2c219
GM
8660
8661 UNBLOCK_INPUT;
12ba150f 8662 }
f451eb13 8663
eccc05db 8664#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8665 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8666#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8667 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8668 dragged. */
12ba150f 8669 if (NILP (bar->dragging))
f451eb13 8670 {
92857db0 8671 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8672
12ba150f 8673 if (whole == 0)
ab648270 8674 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8675 else
8676 {
43f868f5
JB
8677 int start = ((double) position * top_range) / whole;
8678 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8679 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8680 }
f451eb13 8681 }
06a2c219 8682#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8683
06a2c219 8684 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8685}
8686
12ba150f 8687
f451eb13 8688/* The following three hooks are used when we're doing a thorough
ab648270 8689 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8690 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8691 away is a real pain - "Can you say set-window-configuration, boys
8692 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8693 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8694 from the fiery pit when we actually redisplay its window. */
f451eb13 8695
ab648270
JB
8696/* Arrange for all scroll bars on FRAME to be removed at the next call
8697 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8698 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8699
58769bee 8700static void
ab648270 8701XTcondemn_scroll_bars (frame)
f451eb13
JB
8702 FRAME_PTR frame;
8703{
f9e24cb9
RS
8704 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8705 while (! NILP (FRAME_SCROLL_BARS (frame)))
8706 {
8707 Lisp_Object bar;
8708 bar = FRAME_SCROLL_BARS (frame);
8709 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8710 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8711 XSCROLL_BAR (bar)->prev = Qnil;
8712 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8713 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8714 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8715 }
f451eb13
JB
8716}
8717
fa2dfc30 8718
06a2c219 8719/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8720 Note that WINDOW isn't necessarily condemned at all. */
fa2dfc30 8721
f451eb13 8722static void
ab648270 8723XTredeem_scroll_bar (window)
12ba150f 8724 struct window *window;
f451eb13 8725{
ab648270 8726 struct scroll_bar *bar;
fa2dfc30 8727 struct frame *f;
12ba150f 8728
ab648270
JB
8729 /* We can't redeem this window's scroll bar if it doesn't have one. */
8730 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8731 abort ();
8732
ab648270 8733 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8734
8735 /* Unlink it from the condemned list. */
fa2dfc30
GM
8736 f = XFRAME (WINDOW_FRAME (window));
8737 if (NILP (bar->prev))
8738 {
8739 /* If the prev pointer is nil, it must be the first in one of
8740 the lists. */
8741 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8742 /* It's not condemned. Everything's fine. */
8743 return;
8744 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8745 window->vertical_scroll_bar))
8746 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8747 else
8748 /* If its prev pointer is nil, it must be at the front of
8749 one or the other! */
8750 abort ();
8751 }
8752 else
8753 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f 8754
fa2dfc30
GM
8755 if (! NILP (bar->next))
8756 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8757
fa2dfc30
GM
8758 bar->next = FRAME_SCROLL_BARS (f);
8759 bar->prev = Qnil;
8760 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8761 if (! NILP (bar->next))
8762 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13
JB
8763}
8764
ab648270
JB
8765/* Remove all scroll bars on FRAME that haven't been saved since the
8766 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8767
f451eb13 8768static void
ab648270 8769XTjudge_scroll_bars (f)
12ba150f 8770 FRAME_PTR f;
f451eb13 8771{
12ba150f 8772 Lisp_Object bar, next;
f451eb13 8773
ab648270 8774 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8775
8776 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8777 more events on the hapless scroll bars. */
8778 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8779
8780 for (; ! NILP (bar); bar = next)
f451eb13 8781 {
ab648270 8782 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8783
ab648270 8784 x_scroll_bar_remove (b);
12ba150f
JB
8785
8786 next = b->next;
8787 b->next = b->prev = Qnil;
f451eb13 8788 }
12ba150f 8789
ab648270 8790 /* Now there should be no references to the condemned scroll bars,
12ba150f 8791 and they should get garbage-collected. */
f451eb13
JB
8792}
8793
8794
06a2c219
GM
8795/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8796 is a no-op when using toolkit scroll bars.
ab648270
JB
8797
8798 This may be called from a signal handler, so we have to ignore GC
8799 mark bits. */
06a2c219 8800
f451eb13 8801static void
ab648270
JB
8802x_scroll_bar_expose (bar, event)
8803 struct scroll_bar *bar;
f451eb13
JB
8804 XEvent *event;
8805{
06a2c219
GM
8806#ifndef USE_TOOLKIT_SCROLL_BARS
8807
ab648270 8808 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8809 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8810 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8811 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8812
f451eb13
JB
8813 BLOCK_INPUT;
8814
ab648270 8815 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8816
06a2c219 8817 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8818 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8819
8820 /* x, y, width, height */
d9cdbb3d 8821 0, 0,
3cbd2e0b 8822 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8823 XINT (bar->height) - 1);
8824
f451eb13 8825 UNBLOCK_INPUT;
06a2c219
GM
8826
8827#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8828}
8829
ab648270
JB
8830/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8831 is set to something other than no_event, it is enqueued.
8832
8833 This may be called from a signal handler, so we have to ignore GC
8834 mark bits. */
06a2c219 8835
5c187dee
GM
8836#ifndef USE_TOOLKIT_SCROLL_BARS
8837
f451eb13 8838static void
ab648270
JB
8839x_scroll_bar_handle_click (bar, event, emacs_event)
8840 struct scroll_bar *bar;
f451eb13
JB
8841 XEvent *event;
8842 struct input_event *emacs_event;
8843{
0299d313 8844 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8845 abort ();
8846
ab648270 8847 emacs_event->kind = scroll_bar_click;
69388238 8848 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8849 emacs_event->modifiers
8850 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8851 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8852 event->xbutton.state)
8853 | (event->type == ButtonRelease
8854 ? up_modifier
8855 : down_modifier));
12ba150f 8856 emacs_event->frame_or_window = bar->window;
0f8aabe9 8857 emacs_event->arg = Qnil;
f451eb13 8858 emacs_event->timestamp = event->xbutton.time;
12ba150f 8859 {
06a2c219 8860#if 0
d9cdbb3d 8861 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8862 int internal_height
d9cdbb3d 8863 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8864#endif
0299d313 8865 int top_range
d9cdbb3d 8866 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8867 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8868
8869 if (y < 0) y = 0;
8870 if (y > top_range) y = top_range;
8871
8872 if (y < XINT (bar->start))
ab648270
JB
8873 emacs_event->part = scroll_bar_above_handle;
8874 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8875 emacs_event->part = scroll_bar_handle;
12ba150f 8876 else
ab648270 8877 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8878
8879 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8880 they want to drag it. Lisp code needs to be able to decide
8881 whether or not we're dragging. */
929787e1 8882#if 0
12ba150f
JB
8883 /* If the user has just clicked on the handle, record where they're
8884 holding it. */
8885 if (event->type == ButtonPress
ab648270 8886 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8887 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8888#endif
12ba150f
JB
8889
8890 /* If the user has released the handle, set it to its final position. */
8891 if (event->type == ButtonRelease
8892 && ! NILP (bar->dragging))
8893 {
8894 int new_start = y - XINT (bar->dragging);
8895 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8896
ab648270 8897 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8898 bar->dragging = Qnil;
8899 }
f451eb13 8900
5116f055
JB
8901 /* Same deal here as the other #if 0. */
8902#if 0
58769bee 8903 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8904 the handle. */
ab648270 8905 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8906 emacs_event->x = bar->start;
8907 else
e0c1aef2 8908 XSETINT (emacs_event->x, y);
5116f055 8909#else
e0c1aef2 8910 XSETINT (emacs_event->x, y);
5116f055 8911#endif
f451eb13 8912
e0c1aef2 8913 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8914 }
8915}
f451eb13 8916
ab648270
JB
8917/* Handle some mouse motion while someone is dragging the scroll bar.
8918
8919 This may be called from a signal handler, so we have to ignore GC
8920 mark bits. */
06a2c219 8921
f451eb13 8922static void
ab648270
JB
8923x_scroll_bar_note_movement (bar, event)
8924 struct scroll_bar *bar;
f451eb13
JB
8925 XEvent *event;
8926{
39d8bb4d
KH
8927 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8928
f451eb13
JB
8929 last_mouse_movement_time = event->xmotion.time;
8930
39d8bb4d 8931 f->mouse_moved = 1;
e0c1aef2 8932 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8933
8934 /* If we're dragging the bar, display it. */
ab648270 8935 if (! GC_NILP (bar->dragging))
f451eb13
JB
8936 {
8937 /* Where should the handle be now? */
12ba150f 8938 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8939
12ba150f 8940 if (new_start != XINT (bar->start))
f451eb13 8941 {
12ba150f 8942 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8943
ab648270 8944 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8945 }
8946 }
f451eb13
JB
8947}
8948
5c187dee
GM
8949#endif /* !USE_TOOLKIT_SCROLL_BARS */
8950
12ba150f 8951/* Return information to the user about the current position of the mouse
ab648270 8952 on the scroll bar. */
06a2c219 8953
12ba150f 8954static void
334208b7
RS
8955x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8956 FRAME_PTR *fp;
12ba150f 8957 Lisp_Object *bar_window;
ab648270 8958 enum scroll_bar_part *part;
12ba150f
JB
8959 Lisp_Object *x, *y;
8960 unsigned long *time;
8961{
ab648270 8962 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8963 Window w = SCROLL_BAR_X_WINDOW (bar);
8964 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8965 int win_x, win_y;
559cb2fb
JB
8966 Window dummy_window;
8967 int dummy_coord;
8968 unsigned int dummy_mask;
12ba150f 8969
cf7cb199
JB
8970 BLOCK_INPUT;
8971
ab648270 8972 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8973 report that. */
334208b7 8974 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8975
559cb2fb
JB
8976 /* Root, child, root x and root y. */
8977 &dummy_window, &dummy_window,
8978 &dummy_coord, &dummy_coord,
12ba150f 8979
559cb2fb
JB
8980 /* Position relative to scroll bar. */
8981 &win_x, &win_y,
12ba150f 8982
559cb2fb
JB
8983 /* Mouse buttons and modifier keys. */
8984 &dummy_mask))
7a13e894 8985 ;
559cb2fb
JB
8986 else
8987 {
06a2c219 8988#if 0
559cb2fb 8989 int inside_height
d9cdbb3d 8990 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8991#endif
559cb2fb 8992 int top_range
d9cdbb3d 8993 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8994
8995 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8996
8997 if (! NILP (bar->dragging))
8998 win_y -= XINT (bar->dragging);
8999
9000 if (win_y < 0)
9001 win_y = 0;
9002 if (win_y > top_range)
9003 win_y = top_range;
9004
334208b7 9005 *fp = f;
7a13e894 9006 *bar_window = bar->window;
559cb2fb
JB
9007
9008 if (! NILP (bar->dragging))
9009 *part = scroll_bar_handle;
9010 else if (win_y < XINT (bar->start))
9011 *part = scroll_bar_above_handle;
9012 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9013 *part = scroll_bar_handle;
9014 else
9015 *part = scroll_bar_below_handle;
12ba150f 9016
e0c1aef2
KH
9017 XSETINT (*x, win_y);
9018 XSETINT (*y, top_range);
12ba150f 9019
39d8bb4d 9020 f->mouse_moved = 0;
559cb2fb
JB
9021 last_mouse_scroll_bar = Qnil;
9022 }
12ba150f 9023
559cb2fb 9024 *time = last_mouse_movement_time;
cf7cb199 9025
cf7cb199 9026 UNBLOCK_INPUT;
12ba150f
JB
9027}
9028
f451eb13 9029
dbc4e1c1 9030/* The screen has been cleared so we may have changed foreground or
ab648270
JB
9031 background colors, and the scroll bars may need to be redrawn.
9032 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
9033 redraw them. */
9034
dfcf069d 9035void
ab648270 9036x_scroll_bar_clear (f)
dbc4e1c1
JB
9037 FRAME_PTR f;
9038{
06a2c219 9039#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
9040 Lisp_Object bar;
9041
b80c363e
RS
9042 /* We can have scroll bars even if this is 0,
9043 if we just turned off scroll bar mode.
9044 But in that case we should not clear them. */
9045 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9046 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9047 bar = XSCROLL_BAR (bar)->next)
9048 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
9049 0, 0, 0, 0, True);
06a2c219 9050#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
9051}
9052
06a2c219 9053/* This processes Expose events from the menu-bar specific X event
19126e11 9054 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 9055 when handling menu-bar or pop-up items. */
3afe33e7 9056
06a2c219 9057int
3afe33e7
RS
9058process_expose_from_menu (event)
9059 XEvent event;
9060{
9061 FRAME_PTR f;
19126e11 9062 struct x_display_info *dpyinfo;
06a2c219 9063 int frame_exposed_p = 0;
3afe33e7 9064
f94397b5
KH
9065 BLOCK_INPUT;
9066
19126e11
KH
9067 dpyinfo = x_display_info_for_display (event.xexpose.display);
9068 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
9069 if (f)
9070 {
9071 if (f->async_visible == 0)
9072 {
9073 f->async_visible = 1;
9074 f->async_iconified = 0;
06c488fd 9075 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
9076 SET_FRAME_GARBAGED (f);
9077 }
9078 else
9079 {
06a2c219
GM
9080 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9081 event.xexpose.x, event.xexpose.y,
9082 event.xexpose.width, event.xexpose.height);
9083 frame_exposed_p = 1;
3afe33e7
RS
9084 }
9085 }
9086 else
9087 {
9088 struct scroll_bar *bar
9089 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9090
3afe33e7
RS
9091 if (bar)
9092 x_scroll_bar_expose (bar, &event);
9093 }
f94397b5
KH
9094
9095 UNBLOCK_INPUT;
06a2c219 9096 return frame_exposed_p;
3afe33e7 9097}
09756a85
RS
9098\f
9099/* Define a queue to save up SelectionRequest events for later handling. */
9100
9101struct selection_event_queue
9102 {
9103 XEvent event;
9104 struct selection_event_queue *next;
9105 };
9106
9107static struct selection_event_queue *queue;
9108
9109/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 9110
09756a85
RS
9111static int x_queue_selection_requests;
9112
9113/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 9114
09756a85 9115static void
334208b7
RS
9116x_queue_event (f, event)
9117 FRAME_PTR f;
09756a85
RS
9118 XEvent *event;
9119{
9120 struct selection_event_queue *queue_tmp
06a2c219 9121 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 9122
58769bee 9123 if (queue_tmp != NULL)
09756a85
RS
9124 {
9125 queue_tmp->event = *event;
9126 queue_tmp->next = queue;
9127 queue = queue_tmp;
9128 }
9129}
9130
9131/* Take all the queued events and put them back
9132 so that they get processed afresh. */
9133
9134static void
db3906fd
RS
9135x_unqueue_events (display)
9136 Display *display;
09756a85 9137{
58769bee 9138 while (queue != NULL)
09756a85
RS
9139 {
9140 struct selection_event_queue *queue_tmp = queue;
db3906fd 9141 XPutBackEvent (display, &queue_tmp->event);
09756a85 9142 queue = queue_tmp->next;
06a2c219 9143 xfree ((char *)queue_tmp);
09756a85
RS
9144 }
9145}
9146
9147/* Start queuing SelectionRequest events. */
9148
9149void
db3906fd
RS
9150x_start_queuing_selection_requests (display)
9151 Display *display;
09756a85
RS
9152{
9153 x_queue_selection_requests++;
9154}
9155
9156/* Stop queuing SelectionRequest events. */
9157
9158void
db3906fd
RS
9159x_stop_queuing_selection_requests (display)
9160 Display *display;
09756a85
RS
9161{
9162 x_queue_selection_requests--;
db3906fd 9163 x_unqueue_events (display);
09756a85 9164}
f451eb13
JB
9165\f
9166/* The main X event-reading loop - XTread_socket. */
dc6f92b8 9167
06a2c219 9168/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
9169 but we have to put it out here, since static variables within functions
9170 sometimes don't work. */
06a2c219 9171
dc6f92b8
JB
9172static Time enter_timestamp;
9173
11edeb03 9174/* This holds the state XLookupString needs to implement dead keys
58769bee 9175 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
9176 says that a portable program can't use this, but Stephen Gildea assures
9177 me that letting the compiler initialize it to zeros will work okay.
9178
9179 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
9180 given for enter_time stamp, above. */
9181
11edeb03
JB
9182static XComposeStatus compose_status;
9183
10e6549c
RS
9184/* Record the last 100 characters stored
9185 to help debug the loss-of-chars-during-GC problem. */
06a2c219 9186
2224b905
RS
9187static int temp_index;
9188static short temp_buffer[100];
10e6549c 9189
7a13e894
RS
9190/* Set this to nonzero to fake an "X I/O error"
9191 on a particular display. */
06a2c219 9192
7a13e894
RS
9193struct x_display_info *XTread_socket_fake_io_error;
9194
2224b905
RS
9195/* When we find no input here, we occasionally do a no-op command
9196 to verify that the X server is still running and we can still talk with it.
9197 We try all the open displays, one by one.
9198 This variable is used for cycling thru the displays. */
06a2c219 9199
2224b905
RS
9200static struct x_display_info *next_noop_dpyinfo;
9201
06a2c219
GM
9202#define SET_SAVED_MENU_EVENT(size) \
9203 do \
9204 { \
9205 if (f->output_data.x->saved_menu_event == 0) \
9206 f->output_data.x->saved_menu_event \
9207 = (XEvent *) xmalloc (sizeof (XEvent)); \
9208 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9209 if (numchars >= 1) \
9210 { \
9211 bufp->kind = menu_bar_activate_event; \
9212 XSETFRAME (bufp->frame_or_window, f); \
0f8aabe9 9213 bufp->arg = Qnil; \
06a2c219
GM
9214 bufp++; \
9215 count++; \
9216 numchars--; \
9217 } \
9218 } \
9219 while (0)
9220
8805890a 9221#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 9222#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 9223
dc6f92b8
JB
9224/* Read events coming from the X server.
9225 This routine is called by the SIGIO handler.
9226 We return as soon as there are no more events to be read.
9227
9228 Events representing keys are stored in buffer BUFP,
9229 which can hold up to NUMCHARS characters.
9230 We return the number of characters stored into the buffer,
9231 thus pretending to be `read'.
9232
dc6f92b8
JB
9233 EXPECTED is nonzero if the caller knows input is available. */
9234
7c5283e4 9235int
f66868ba 9236XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 9237 register int sd;
8805890a
KH
9238 /* register */ struct input_event *bufp;
9239 /* register */ int numchars;
dc6f92b8
JB
9240 int expected;
9241{
9242 int count = 0;
9243 int nbytes = 0;
dc6f92b8 9244 XEvent event;
f676886a 9245 struct frame *f;
66f55a9d 9246 int event_found = 0;
334208b7 9247 struct x_display_info *dpyinfo;
379b5ac0 9248 struct coding_system coding;
dc6f92b8 9249
9ac0d9e0 9250 if (interrupt_input_blocked)
dc6f92b8 9251 {
9ac0d9e0 9252 interrupt_input_pending = 1;
dc6f92b8
JB
9253 return -1;
9254 }
9255
9ac0d9e0 9256 interrupt_input_pending = 0;
dc6f92b8 9257 BLOCK_INPUT;
c0a04927
RS
9258
9259 /* So people can tell when we have read the available input. */
9260 input_signal_count++;
9261
dc6f92b8 9262 if (numchars <= 0)
06a2c219 9263 abort (); /* Don't think this happens. */
dc6f92b8 9264
bde5503b
GM
9265 ++handling_signal;
9266
379b5ac0
KH
9267 /* The input should be decoded if it is from XIM. Currently the
9268 locale of XIM is the same as that of the system. So, we can use
9269 Vlocale_coding_system which is initialized properly at Emacs
9270 startup time. */
9271 setup_coding_system (Vlocale_coding_system, &coding);
9272 coding.src_multibyte = 0;
9273 coding.dst_multibyte = 1;
9274 /* The input is converted to events, thus we can't handle
9275 composition. Anyway, there's no XIM that gives us composition
9276 information. */
9277 coding.composing = COMPOSITION_DISABLED;
9278
7a13e894
RS
9279 /* Find the display we are supposed to read input for.
9280 It's the one communicating on descriptor SD. */
9281 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9282 {
9283#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9284#ifdef FIOSNBIO
7a13e894
RS
9285 /* If available, Xlib uses FIOSNBIO to make the socket
9286 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9287 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9288 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9289 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9290#endif /* ! defined (FIOSNBIO) */
7a13e894 9291#endif
dc6f92b8 9292
7a13e894
RS
9293#if 0 /* This code can't be made to work, with multiple displays,
9294 and appears not to be used on any system any more.
9295 Also keyboard.c doesn't turn O_NDELAY on and off
9296 for X connections. */
dc6f92b8
JB
9297#ifndef SIGIO
9298#ifndef HAVE_SELECT
7a13e894
RS
9299 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9300 {
9301 extern int read_alarm_should_throw;
9302 read_alarm_should_throw = 1;
9303 XPeekEvent (dpyinfo->display, &event);
9304 read_alarm_should_throw = 0;
9305 }
c118dd06
JB
9306#endif /* HAVE_SELECT */
9307#endif /* SIGIO */
7a13e894 9308#endif
dc6f92b8 9309
7a13e894
RS
9310 /* For debugging, this gives a way to fake an I/O error. */
9311 if (dpyinfo == XTread_socket_fake_io_error)
9312 {
9313 XTread_socket_fake_io_error = 0;
9314 x_io_error_quitter (dpyinfo->display);
9315 }
dc6f92b8 9316
06a2c219 9317 while (XPending (dpyinfo->display))
dc6f92b8 9318 {
7a13e894 9319 XNextEvent (dpyinfo->display, &event);
06a2c219 9320
531483fb 9321#ifdef HAVE_X_I18N
d1bc4182 9322 {
f2be1146
GM
9323 /* Filter events for the current X input method.
9324 XFilterEvent returns non-zero if the input method has
9325 consumed the event. We pass the frame's X window to
9326 XFilterEvent because that's the one for which the IC
9327 was created. */
f5d11644
GM
9328 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9329 event.xclient.window);
9330 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9331 break;
9332 }
0cd6403b 9333#endif
7a13e894
RS
9334 event_found = 1;
9335
9336 switch (event.type)
9337 {
9338 case ClientMessage:
c047688c 9339 {
7a13e894
RS
9340 if (event.xclient.message_type
9341 == dpyinfo->Xatom_wm_protocols
9342 && event.xclient.format == 32)
c047688c 9343 {
7a13e894
RS
9344 if (event.xclient.data.l[0]
9345 == dpyinfo->Xatom_wm_take_focus)
c047688c 9346 {
8c1a6a84
RS
9347 /* Use x_any_window_to_frame because this
9348 could be the shell widget window
9349 if the frame has no title bar. */
9350 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9351#ifdef HAVE_X_I18N
9352 /* Not quite sure this is needed -pd */
8c1a6a84 9353 if (f && FRAME_XIC (f))
6c183ba5
RS
9354 XSetICFocus (FRAME_XIC (f));
9355#endif
f1da8f06
GM
9356#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9357 instructs the WM to set the input focus automatically for
9358 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9359 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9360 it has set the focus. So, XSetInputFocus below is not
9361 needed.
9362
9363 The call to XSetInputFocus below has also caused trouble. In
9364 cases where the XSetInputFocus done by the WM and the one
9365 below are temporally close (on a fast machine), the call
9366 below can generate additional FocusIn events which confuse
9367 Emacs. */
9368
bf7253f4
RS
9369 /* Since we set WM_TAKE_FOCUS, we must call
9370 XSetInputFocus explicitly. But not if f is null,
9371 since that might be an event for a deleted frame. */
7a13e894 9372 if (f)
bf7253f4
RS
9373 {
9374 Display *d = event.xclient.display;
9375 /* Catch and ignore errors, in case window has been
9376 iconified by a window manager such as GWM. */
9377 int count = x_catch_errors (d);
9378 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9379 /* The ICCCM says this is
9380 the only valid choice. */
9381 RevertToParent,
bf7253f4
RS
9382 event.xclient.data.l[1]);
9383 /* This is needed to detect the error
9384 if there is an error. */
9385 XSync (d, False);
9386 x_uncatch_errors (d, count);
9387 }
7a13e894 9388 /* Not certain about handling scroll bars here */
f1da8f06 9389#endif /* 0 */
c047688c 9390 }
7a13e894
RS
9391 else if (event.xclient.data.l[0]
9392 == dpyinfo->Xatom_wm_save_yourself)
9393 {
9394 /* Save state modify the WM_COMMAND property to
06a2c219 9395 something which can reinstate us. This notifies
7a13e894
RS
9396 the session manager, who's looking for such a
9397 PropertyNotify. Can restart processing when
06a2c219 9398 a keyboard or mouse event arrives. */
7a13e894
RS
9399 if (numchars > 0)
9400 {
19126e11
KH
9401 f = x_top_window_to_frame (dpyinfo,
9402 event.xclient.window);
7a13e894
RS
9403
9404 /* This is just so we only give real data once
9405 for a single Emacs process. */
b86bd3dd 9406 if (f == SELECTED_FRAME ())
7a13e894
RS
9407 XSetCommand (FRAME_X_DISPLAY (f),
9408 event.xclient.window,
9409 initial_argv, initial_argc);
f000f5c5 9410 else if (f)
7a13e894
RS
9411 XSetCommand (FRAME_X_DISPLAY (f),
9412 event.xclient.window,
9413 0, 0);
9414 }
9415 }
9416 else if (event.xclient.data.l[0]
9417 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9418 {
19126e11
KH
9419 struct frame *f
9420 = x_any_window_to_frame (dpyinfo,
9421 event.xclient.window);
1fb20991 9422
7a13e894
RS
9423 if (f)
9424 {
9425 if (numchars == 0)
9426 abort ();
1fb20991 9427
7a13e894
RS
9428 bufp->kind = delete_window_event;
9429 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9430 bufp->arg = Qnil;
7a13e894
RS
9431 bufp++;
9432
9433 count += 1;
9434 numchars -= 1;
9435 }
1fb20991 9436 }
c047688c 9437 }
7a13e894
RS
9438 else if (event.xclient.message_type
9439 == dpyinfo->Xatom_wm_configure_denied)
9440 {
9441 }
9442 else if (event.xclient.message_type
9443 == dpyinfo->Xatom_wm_window_moved)
9444 {
9445 int new_x, new_y;
19126e11
KH
9446 struct frame *f
9447 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9448
7a13e894
RS
9449 new_x = event.xclient.data.s[0];
9450 new_y = event.xclient.data.s[1];
1fb20991 9451
7a13e894
RS
9452 if (f)
9453 {
7556890b
RS
9454 f->output_data.x->left_pos = new_x;
9455 f->output_data.x->top_pos = new_y;
7a13e894 9456 }
1fb20991 9457 }
0fdff6bb 9458#ifdef HACK_EDITRES
7a13e894
RS
9459 else if (event.xclient.message_type
9460 == dpyinfo->Xatom_editres)
9461 {
19126e11
KH
9462 struct frame *f
9463 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9464 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9465 &event, NULL);
7a13e894 9466 }
0fdff6bb 9467#endif /* HACK_EDITRES */
06a2c219
GM
9468 else if ((event.xclient.message_type
9469 == dpyinfo->Xatom_DONE)
9470 || (event.xclient.message_type
9471 == dpyinfo->Xatom_PAGE))
9472 {
9473 /* Ghostview job completed. Kill it. We could
9474 reply with "Next" if we received "Page", but we
9475 currently never do because we are interested in
9476 images, only, which should have 1 page. */
06a2c219
GM
9477 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9478 struct frame *f
9479 = x_window_to_frame (dpyinfo, event.xclient.window);
9480 x_kill_gs_process (pixmap, f);
9481 expose_frame (f, 0, 0, 0, 0);
9482 }
9483#ifdef USE_TOOLKIT_SCROLL_BARS
9484 /* Scroll bar callbacks send a ClientMessage from which
9485 we construct an input_event. */
9486 else if (event.xclient.message_type
9487 == dpyinfo->Xatom_Scrollbar)
9488 {
9489 x_scroll_bar_to_input_event (&event, bufp);
9490 ++bufp, ++count, --numchars;
9491 goto out;
9492 }
9493#endif /* USE_TOOLKIT_SCROLL_BARS */
9494 else
9495 goto OTHER;
7a13e894
RS
9496 }
9497 break;
dc6f92b8 9498
7a13e894 9499 case SelectionNotify:
3afe33e7 9500#ifdef USE_X_TOOLKIT
19126e11 9501 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9502 goto OTHER;
3afe33e7 9503#endif /* not USE_X_TOOLKIT */
dfcf069d 9504 x_handle_selection_notify (&event.xselection);
7a13e894 9505 break;
d56a553a 9506
06a2c219 9507 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9508#ifdef USE_X_TOOLKIT
19126e11 9509 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9510 goto OTHER;
3afe33e7 9511#endif /* USE_X_TOOLKIT */
7a13e894
RS
9512 {
9513 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9514
7a13e894
RS
9515 if (numchars == 0)
9516 abort ();
d56a553a 9517
7a13e894
RS
9518 bufp->kind = selection_clear_event;
9519 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9520 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9521 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9522 bufp->frame_or_window = Qnil;
0f8aabe9 9523 bufp->arg = Qnil;
7a13e894 9524 bufp++;
d56a553a 9525
7a13e894
RS
9526 count += 1;
9527 numchars -= 1;
9528 }
9529 break;
dc6f92b8 9530
06a2c219 9531 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9532#ifdef USE_X_TOOLKIT
19126e11 9533 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9534 goto OTHER;
3afe33e7 9535#endif /* USE_X_TOOLKIT */
7a13e894 9536 if (x_queue_selection_requests)
19126e11 9537 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9538 &event);
9539 else
9540 {
9541 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9542
7a13e894
RS
9543 if (numchars == 0)
9544 abort ();
9545
9546 bufp->kind = selection_request_event;
9547 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9548 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9549 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9550 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9551 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9552 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9553 bufp->frame_or_window = Qnil;
0f8aabe9 9554 bufp->arg = Qnil;
7a13e894
RS
9555 bufp++;
9556
9557 count += 1;
9558 numchars -= 1;
9559 }
9560 break;
9561
9562 case PropertyNotify:
3afe33e7 9563#ifdef USE_X_TOOLKIT
19126e11 9564 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9565 goto OTHER;
3afe33e7 9566#endif /* not USE_X_TOOLKIT */
dfcf069d 9567 x_handle_property_notify (&event.xproperty);
7a13e894 9568 break;
dc6f92b8 9569
7a13e894 9570 case ReparentNotify:
19126e11 9571 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9572 if (f)
9573 {
9574 int x, y;
7556890b 9575 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9576 x_real_positions (f, &x, &y);
7556890b
RS
9577 f->output_data.x->left_pos = x;
9578 f->output_data.x->top_pos = y;
7a13e894
RS
9579 }
9580 break;
3bd330d4 9581
7a13e894 9582 case Expose:
19126e11 9583 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9584 if (f)
dc6f92b8 9585 {
7a13e894
RS
9586 if (f->async_visible == 0)
9587 {
9588 f->async_visible = 1;
9589 f->async_iconified = 0;
06c488fd 9590 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9591 SET_FRAME_GARBAGED (f);
9592 }
9593 else
06a2c219
GM
9594 expose_frame (x_window_to_frame (dpyinfo,
9595 event.xexpose.window),
9596 event.xexpose.x, event.xexpose.y,
9597 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9598 }
9599 else
7a13e894 9600 {
06a2c219
GM
9601#ifdef USE_TOOLKIT_SCROLL_BARS
9602 /* Dispatch event to the widget. */
9603 goto OTHER;
9604#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9605 struct scroll_bar *bar
9606 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9607
7a13e894
RS
9608 if (bar)
9609 x_scroll_bar_expose (bar, &event);
3afe33e7 9610#ifdef USE_X_TOOLKIT
7a13e894
RS
9611 else
9612 goto OTHER;
3afe33e7 9613#endif /* USE_X_TOOLKIT */
06a2c219 9614#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9615 }
9616 break;
dc6f92b8 9617
7a13e894
RS
9618 case GraphicsExpose: /* This occurs when an XCopyArea's
9619 source area was obscured or not
9620 available.*/
19126e11 9621 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9622 if (f)
9623 {
06a2c219
GM
9624 expose_frame (f,
9625 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9626 event.xgraphicsexpose.width,
9627 event.xgraphicsexpose.height);
7a13e894 9628 }
3afe33e7 9629#ifdef USE_X_TOOLKIT
7a13e894
RS
9630 else
9631 goto OTHER;
3afe33e7 9632#endif /* USE_X_TOOLKIT */
7a13e894 9633 break;
dc6f92b8 9634
7a13e894 9635 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9636 source area was completely
9637 available */
7a13e894 9638 break;
dc6f92b8 9639
7a13e894 9640 case UnmapNotify:
06a2c219
GM
9641 /* Redo the mouse-highlight after the tooltip has gone. */
9642 if (event.xmap.window == tip_window)
9643 {
9644 tip_window = 0;
9645 redo_mouse_highlight ();
9646 }
9647
91ea2a7a 9648 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9649 if (f) /* F may no longer exist if
9650 the frame was deleted. */
9651 {
9652 /* While a frame is unmapped, display generation is
9653 disabled; you don't want to spend time updating a
9654 display that won't ever be seen. */
9655 f->async_visible = 0;
9656 /* We can't distinguish, from the event, whether the window
9657 has become iconified or invisible. So assume, if it
9658 was previously visible, than now it is iconified.
1aa6072f
RS
9659 But x_make_frame_invisible clears both
9660 the visible flag and the iconified flag;
9661 and that way, we know the window is not iconified now. */
7a13e894 9662 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9663 {
9664 f->async_iconified = 1;
bddd097c 9665
1aa6072f
RS
9666 bufp->kind = iconify_event;
9667 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9668 bufp->arg = Qnil;
1aa6072f
RS
9669 bufp++;
9670 count++;
9671 numchars--;
9672 }
7a13e894 9673 }
7a13e894 9674 goto OTHER;
dc6f92b8 9675
7a13e894 9676 case MapNotify:
06a2c219
GM
9677 if (event.xmap.window == tip_window)
9678 /* The tooltip has been drawn already. Avoid
9679 the SET_FRAME_GARBAGED below. */
9680 goto OTHER;
9681
9682 /* We use x_top_window_to_frame because map events can
9683 come for sub-windows and they don't mean that the
9684 frame is visible. */
19126e11 9685 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9686 if (f)
9687 {
9688 f->async_visible = 1;
9689 f->async_iconified = 0;
06c488fd 9690 f->output_data.x->has_been_visible = 1;
dc6f92b8 9691
7a13e894
RS
9692 /* wait_reading_process_input will notice this and update
9693 the frame's display structures. */
9694 SET_FRAME_GARBAGED (f);
bddd097c 9695
d806e720
RS
9696 if (f->iconified)
9697 {
9698 bufp->kind = deiconify_event;
9699 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9700 bufp->arg = Qnil;
d806e720
RS
9701 bufp++;
9702 count++;
9703 numchars--;
9704 }
e73ec6fa 9705 else if (! NILP (Vframe_list)
8e713be6 9706 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9707 /* Force a redisplay sooner or later
9708 to update the frame titles
9709 in case this is the second frame. */
9710 record_asynch_buffer_change ();
7a13e894 9711 }
7a13e894 9712 goto OTHER;
dc6f92b8 9713
7a13e894 9714 case KeyPress:
19126e11 9715 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9716
eccc05db 9717#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
9718 /* I couldn't find a way to prevent LessTif scroll bars
9719 from consuming key events. */
9720 if (f == 0)
9721 {
9722 Widget widget = XtWindowToWidget (dpyinfo->display,
9723 event.xkey.window);
9724 if (widget && XmIsScrollBar (widget))
9725 {
9726 widget = XtParent (widget);
9727 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9728 }
9729 }
eccc05db 9730#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
06a2c219 9731
7a13e894
RS
9732 if (f != 0)
9733 {
9734 KeySym keysym, orig_keysym;
379b5ac0
KH
9735 /* al%imercury@uunet.uu.net says that making this 81
9736 instead of 80 fixed a bug whereby meta chars made
9737 his Emacs hang.
9738
9739 It seems that some version of XmbLookupString has
9740 a bug of not returning XBufferOverflow in
9741 status_return even if the input is too long to
9742 fit in 81 bytes. So, we must prepare sufficient
9743 bytes for copy_buffer. 513 bytes (256 chars for
9744 two-byte character set) seems to be a faily good
9745 approximation. -- 2000.8.10 handa@etl.go.jp */
9746 unsigned char copy_buffer[513];
9747 unsigned char *copy_bufptr = copy_buffer;
9748 int copy_bufsiz = sizeof (copy_buffer);
7a13e894 9749 int modifiers;
64bb1782 9750
7a13e894
RS
9751 event.xkey.state
9752 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9753 extra_keyboard_modifiers);
9754 modifiers = event.xkey.state;
3a2712f9 9755
7a13e894 9756 /* This will have to go some day... */
752a043f 9757
7a13e894
RS
9758 /* make_lispy_event turns chars into control chars.
9759 Don't do it here because XLookupString is too eager. */
9760 event.xkey.state &= ~ControlMask;
5d46f928
RS
9761 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9762 | dpyinfo->super_mod_mask
9763 | dpyinfo->hyper_mod_mask
9764 | dpyinfo->alt_mod_mask);
9765
1cf4a0d1
RS
9766 /* In case Meta is ComposeCharacter,
9767 clear its status. According to Markus Ehrnsperger
9768 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9769 this enables ComposeCharacter to work whether or
9770 not it is combined with Meta. */
9771 if (modifiers & dpyinfo->meta_mod_mask)
9772 bzero (&compose_status, sizeof (compose_status));
9773
6c183ba5
RS
9774#ifdef HAVE_X_I18N
9775 if (FRAME_XIC (f))
9776 {
f5d11644
GM
9777 Status status_return;
9778
6c183ba5 9779 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9780 &event.xkey, copy_bufptr,
9781 copy_bufsiz, &keysym,
6c183ba5 9782 &status_return);
f5d11644
GM
9783 if (status_return == XBufferOverflow)
9784 {
9785 copy_bufsiz = nbytes + 1;
9786 copy_bufptr = (char *) alloca (copy_bufsiz);
9787 nbytes = XmbLookupString (FRAME_XIC (f),
9788 &event.xkey, copy_bufptr,
9789 copy_bufsiz, &keysym,
9790 &status_return);
9791 }
9792
1decb680
PE
9793 if (status_return == XLookupNone)
9794 break;
9795 else if (status_return == XLookupChars)
fdd9d55e
GM
9796 {
9797 keysym = NoSymbol;
9798 modifiers = 0;
9799 }
1decb680
PE
9800 else if (status_return != XLookupKeySym
9801 && status_return != XLookupBoth)
9802 abort ();
6c183ba5
RS
9803 }
9804 else
379b5ac0
KH
9805 nbytes = XLookupString (&event.xkey, copy_bufptr,
9806 copy_bufsiz, &keysym,
9807 &compose_status);
6c183ba5 9808#else
379b5ac0
KH
9809 nbytes = XLookupString (&event.xkey, copy_bufptr,
9810 copy_bufsiz, &keysym,
9811 &compose_status);
6c183ba5 9812#endif
dc6f92b8 9813
7a13e894 9814 orig_keysym = keysym;
55123275 9815
7a13e894
RS
9816 if (numchars > 1)
9817 {
9818 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9819 || keysym == XK_Delete
1097aea0 9820#ifdef XK_ISO_Left_Tab
441affdb 9821 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9822#endif
852bff8f 9823 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9824 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9825 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9826#ifdef HPUX
7a13e894
RS
9827 /* This recognizes the "extended function keys".
9828 It seems there's no cleaner way.
9829 Test IsModifierKey to avoid handling mode_switch
9830 incorrectly. */
9831 || ((unsigned) (keysym) >= XK_Select
9832 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9833#endif
9834#ifdef XK_dead_circumflex
7a13e894 9835 || orig_keysym == XK_dead_circumflex
69388238
RS
9836#endif
9837#ifdef XK_dead_grave
7a13e894 9838 || orig_keysym == XK_dead_grave
69388238
RS
9839#endif
9840#ifdef XK_dead_tilde
7a13e894 9841 || orig_keysym == XK_dead_tilde
69388238
RS
9842#endif
9843#ifdef XK_dead_diaeresis
7a13e894 9844 || orig_keysym == XK_dead_diaeresis
69388238
RS
9845#endif
9846#ifdef XK_dead_macron
7a13e894 9847 || orig_keysym == XK_dead_macron
69388238
RS
9848#endif
9849#ifdef XK_dead_degree
7a13e894 9850 || orig_keysym == XK_dead_degree
69388238
RS
9851#endif
9852#ifdef XK_dead_acute
7a13e894 9853 || orig_keysym == XK_dead_acute
69388238
RS
9854#endif
9855#ifdef XK_dead_cedilla
7a13e894 9856 || orig_keysym == XK_dead_cedilla
69388238
RS
9857#endif
9858#ifdef XK_dead_breve
7a13e894 9859 || orig_keysym == XK_dead_breve
69388238
RS
9860#endif
9861#ifdef XK_dead_ogonek
7a13e894 9862 || orig_keysym == XK_dead_ogonek
69388238
RS
9863#endif
9864#ifdef XK_dead_caron
7a13e894 9865 || orig_keysym == XK_dead_caron
69388238
RS
9866#endif
9867#ifdef XK_dead_doubleacute
7a13e894 9868 || orig_keysym == XK_dead_doubleacute
69388238
RS
9869#endif
9870#ifdef XK_dead_abovedot
7a13e894 9871 || orig_keysym == XK_dead_abovedot
c34790e0 9872#endif
7a13e894
RS
9873 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9874 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9875 /* Any "vendor-specific" key is ok. */
9876 || (orig_keysym & (1 << 28)))
9877 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9878#ifndef HAVE_X11R5
9879#ifdef XK_Mode_switch
7a13e894 9880 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9881#endif
9882#ifdef XK_Num_Lock
7a13e894 9883 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9884#endif
9885#endif /* not HAVE_X11R5 */
7a13e894 9886 ))
dc6f92b8 9887 {
10e6549c
RS
9888 if (temp_index == sizeof temp_buffer / sizeof (short))
9889 temp_index = 0;
7a13e894
RS
9890 temp_buffer[temp_index++] = keysym;
9891 bufp->kind = non_ascii_keystroke;
9892 bufp->code = keysym;
e0c1aef2 9893 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9894 bufp->arg = Qnil;
334208b7
RS
9895 bufp->modifiers
9896 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9897 modifiers);
1113d9db 9898 bufp->timestamp = event.xkey.time;
dc6f92b8 9899 bufp++;
7a13e894
RS
9900 count++;
9901 numchars--;
dc6f92b8 9902 }
7a13e894
RS
9903 else if (numchars > nbytes)
9904 {
9905 register int i;
379b5ac0 9906 register int c;
379b5ac0 9907 int nchars, len;
7a13e894
RS
9908
9909 for (i = 0; i < nbytes; i++)
9910 {
379b5ac0
KH
9911 if (temp_index == (sizeof temp_buffer
9912 / sizeof (short)))
7a13e894 9913 temp_index = 0;
379b5ac0
KH
9914 temp_buffer[temp_index++] = copy_bufptr[i];
9915 }
9916
9917 if (/* If the event is not from XIM, */
9918 event.xkey.keycode != 0
9919 /* or the current locale doesn't request
9920 decoding of the intup data, ... */
9921 || coding.type == coding_type_raw_text
9922 || coding.type == coding_type_no_conversion)
9923 {
9924 /* ... we can use the input data as is. */
9925 nchars = nbytes;
9926 }
9927 else
9928 {
9929 /* We have to decode the input data. */
9930 int require;
9931 unsigned char *p;
9932
9933 require = decoding_buffer_size (&coding, nbytes);
9934 p = (unsigned char *) alloca (require);
9935 coding.mode |= CODING_MODE_LAST_BLOCK;
9936 decode_coding (&coding, copy_bufptr, p,
9937 nbytes, require);
9938 nbytes = coding.produced;
9939 nchars = coding.produced_char;
9940 copy_bufptr = p;
9941 }
9942
9943 /* Convert the input data to a sequence of
9944 character events. */
9945 for (i = 0; i < nbytes; i += len)
9946 {
9947 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9948 nbytes - i, len);
9949 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9950 ? ascii_keystroke
9951 : multibyte_char_keystroke);
9952 bufp->code = c;
7a13e894 9953 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9954 bufp->arg = Qnil;
7a13e894
RS
9955 bufp->modifiers
9956 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9957 modifiers);
9958 bufp->timestamp = event.xkey.time;
9959 bufp++;
9960 }
9961
379b5ac0
KH
9962 count += nchars;
9963 numchars -= nchars;
1decb680
PE
9964
9965 if (keysym == NoSymbol)
9966 break;
7a13e894
RS
9967 }
9968 else
9969 abort ();
dc6f92b8 9970 }
10e6549c
RS
9971 else
9972 abort ();
dc6f92b8 9973 }
59ddecde
GM
9974#ifdef HAVE_X_I18N
9975 /* Don't dispatch this event since XtDispatchEvent calls
9976 XFilterEvent, and two calls in a row may freeze the
9977 client. */
9978 break;
9979#else
717ca130 9980 goto OTHER;
59ddecde 9981#endif
f451eb13 9982
f5d11644 9983 case KeyRelease:
59ddecde
GM
9984#ifdef HAVE_X_I18N
9985 /* Don't dispatch this event since XtDispatchEvent calls
9986 XFilterEvent, and two calls in a row may freeze the
9987 client. */
9988 break;
9989#else
f5d11644 9990 goto OTHER;
59ddecde 9991#endif
f5d11644 9992
7a13e894 9993 /* Here's a possible interpretation of the whole
06a2c219
GM
9994 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9995 you get a FocusIn event, you have to get a FocusOut
9996 event before you relinquish the focus. If you
9997 haven't received a FocusIn event, then a mere
9998 LeaveNotify is enough to free you. */
f451eb13 9999
7a13e894 10000 case EnterNotify:
06a2c219
GM
10001 {
10002 int from_menu_bar_p = 0;
10003
10004 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10005
10006#ifdef LESSTIF_VERSION
10007 /* When clicking outside of a menu bar popup to close
10008 it, we get a FocusIn/ EnterNotify sequence of
10009 events. The flag event.xcrossing.focus is not set
10010 in the EnterNotify event of that sequence because
10011 the focus is in the menu bar,
10012 event.xcrossing.window is the frame's X window.
10013 Unconditionally setting the focus frame to null in
10014 this case is not the right thing, because no event
10015 follows that could set the focus frame to the right
10016 value.
10017
10018 This could be a LessTif bug, but I wasn't able to
10019 reproduce the behavior in a simple test program.
3be7e417
GM
10020 On the other hand, Motif seems to not have this
10021 problem.
06a2c219 10022
3be7e417 10023 (gerd, LessTif 0.92). */
06a2c219
GM
10024
10025 if (!event.xcrossing.focus
10026 && f
10027 && f->output_data.x->menubar_widget)
10028 {
10029 Window focus;
10030 int revert;
10031
10032 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10033 if (focus == XtWindow (f->output_data.x->menubar_widget))
10034 from_menu_bar_p = 1;
10035 }
10036#endif /* LESSTIF_VERSION */
6d4238f3 10037
06a2c219
GM
10038 if (event.xcrossing.focus || from_menu_bar_p)
10039 {
10040 /* Avoid nasty pop/raise loops. */
10041 if (f && (!(f->auto_raise)
10042 || !(f->auto_lower)
10043 || (event.xcrossing.time - enter_timestamp) > 500))
10044 {
10045 x_new_focus_frame (dpyinfo, f);
10046 enter_timestamp = event.xcrossing.time;
10047 }
10048 }
10049 else if (f == dpyinfo->x_focus_frame)
10050 x_new_focus_frame (dpyinfo, 0);
10051
10052 /* EnterNotify counts as mouse movement,
10053 so update things that depend on mouse position. */
10054 if (f && !f->output_data.x->busy_p)
10055 note_mouse_movement (f, &event.xmotion);
10056 goto OTHER;
10057 }
dc6f92b8 10058
7a13e894 10059 case FocusIn:
19126e11 10060 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10061 if (event.xfocus.detail != NotifyPointer)
0f941935 10062 dpyinfo->x_focus_event_frame = f;
7a13e894 10063 if (f)
eb72635f
GM
10064 {
10065 x_new_focus_frame (dpyinfo, f);
10066
10067 /* Don't stop displaying the initial startup message
10068 for a switch-frame event we don't need. */
10069 if (GC_NILP (Vterminal_frame)
10070 && GC_CONSP (Vframe_list)
10071 && !GC_NILP (XCDR (Vframe_list)))
10072 {
10073 bufp->kind = FOCUS_IN_EVENT;
10074 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10075 bufp->arg = Qnil;
eb72635f
GM
10076 ++bufp, ++count, --numchars;
10077 }
10078 }
f9e24cb9 10079
6c183ba5
RS
10080#ifdef HAVE_X_I18N
10081 if (f && FRAME_XIC (f))
10082 XSetICFocus (FRAME_XIC (f));
10083#endif
10084
7a13e894 10085 goto OTHER;
10c5e63d 10086
7a13e894 10087 case LeaveNotify:
19126e11 10088 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 10089 if (f)
10c5e63d 10090 {
06a2c219
GM
10091 int from_menu_bar_p = 0;
10092
7a13e894 10093 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
10094 {
10095 /* If we move outside the frame, then we're
10096 certainly no longer on any text in the frame. */
10097 clear_mouse_face (dpyinfo);
10098 dpyinfo->mouse_face_mouse_frame = 0;
10099 }
10100
10101 /* Generate a nil HELP_EVENT to cancel a help-echo.
10102 Do it only if there's something to cancel.
10103 Otherwise, the startup message is cleared when
10104 the mouse leaves the frame. */
10105 if (any_help_event_p)
10106 {
be010514
GM
10107 Lisp_Object frame;
10108 int n;
10109
06a2c219 10110 XSETFRAME (frame, f);
82c5d67a 10111 help_echo = Qnil;
5ab2570d
GM
10112 n = gen_help_event (bufp, numchars,
10113 Qnil, frame, Qnil, Qnil, 0);
be010514 10114 bufp += n, count += n, numchars -= n;
06a2c219 10115 }
7a13e894 10116
06a2c219
GM
10117#ifdef LESSTIF_VERSION
10118 /* Please see the comment at the start of the
10119 EnterNotify case. */
10120 if (!event.xcrossing.focus
10121 && f->output_data.x->menubar_widget)
10122 {
10123 Window focus;
10124 int revert;
10125 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
10126 if (focus == XtWindow (f->output_data.x->menubar_widget))
10127 from_menu_bar_p = 1;
10128 }
10129#endif /* LESSTIF_VERSION */
10130
10131 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 10132 x_mouse_leave (dpyinfo);
10c5e63d 10133 else
7a13e894 10134 {
0f941935
KH
10135 if (f == dpyinfo->x_focus_event_frame)
10136 dpyinfo->x_focus_event_frame = 0;
10137 if (f == dpyinfo->x_focus_frame)
10138 x_new_focus_frame (dpyinfo, 0);
7a13e894 10139 }
10c5e63d 10140 }
7a13e894 10141 goto OTHER;
dc6f92b8 10142
7a13e894 10143 case FocusOut:
19126e11 10144 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10145 if (event.xfocus.detail != NotifyPointer
0f941935
KH
10146 && f == dpyinfo->x_focus_event_frame)
10147 dpyinfo->x_focus_event_frame = 0;
10148 if (f && f == dpyinfo->x_focus_frame)
10149 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 10150
6c183ba5
RS
10151#ifdef HAVE_X_I18N
10152 if (f && FRAME_XIC (f))
10153 XUnsetICFocus (FRAME_XIC (f));
10154#endif
10155
7a13e894 10156 goto OTHER;
dc6f92b8 10157
7a13e894 10158 case MotionNotify:
dc6f92b8 10159 {
06a2c219 10160 previous_help_echo = help_echo;
7cea38bc 10161 help_echo = help_echo_object = help_echo_window = Qnil;
be010514 10162 help_echo_pos = -1;
06a2c219 10163
7a13e894
RS
10164 if (dpyinfo->grabbed && last_mouse_frame
10165 && FRAME_LIVE_P (last_mouse_frame))
10166 f = last_mouse_frame;
10167 else
19126e11 10168 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 10169
7a13e894
RS
10170 if (f)
10171 note_mouse_movement (f, &event.xmotion);
10172 else
10173 {
e88b3c50 10174#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10175 struct scroll_bar *bar
10176 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 10177
7a13e894
RS
10178 if (bar)
10179 x_scroll_bar_note_movement (bar, &event);
e88b3c50 10180#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 10181
06a2c219
GM
10182 /* If we move outside the frame, then we're
10183 certainly no longer on any text in the frame. */
7a13e894
RS
10184 clear_mouse_face (dpyinfo);
10185 }
06a2c219
GM
10186
10187 /* If the contents of the global variable help_echo
10188 has changed, generate a HELP_EVENT. */
b7e80413
SM
10189 if (!NILP (help_echo)
10190 || !NILP (previous_help_echo))
06a2c219
GM
10191 {
10192 Lisp_Object frame;
be010514 10193 int n;
06a2c219
GM
10194
10195 if (f)
10196 XSETFRAME (frame, f);
10197 else
10198 frame = Qnil;
10199
10200 any_help_event_p = 1;
5ab2570d 10201 n = gen_help_event (bufp, numchars, help_echo, frame,
7cea38bc
GM
10202 help_echo_window, help_echo_object,
10203 help_echo_pos);
be010514 10204 bufp += n, count += n, numchars -= n;
06a2c219
GM
10205 }
10206
10207 goto OTHER;
dc6f92b8 10208 }
dc6f92b8 10209
7a13e894 10210 case ConfigureNotify:
9829ddba
RS
10211 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10212 if (f)
af395ec1 10213 {
5c187dee 10214#ifndef USE_X_TOOLKIT
bf1b7b30
KH
10215 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10216 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 10217
2d7fc7e8
RS
10218 /* In the toolkit version, change_frame_size
10219 is called by the code that handles resizing
10220 of the EmacsFrame widget. */
7a13e894 10221
7a13e894
RS
10222 /* Even if the number of character rows and columns has
10223 not changed, the font size may have changed, so we need
10224 to check the pixel dimensions as well. */
10225 if (columns != f->width
10226 || rows != f->height
7556890b
RS
10227 || event.xconfigure.width != f->output_data.x->pixel_width
10228 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 10229 {
7d1e984f 10230 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 10231 SET_FRAME_GARBAGED (f);
e687d06e 10232 cancel_mouse_face (f);
7a13e894 10233 }
2d7fc7e8 10234#endif
af395ec1 10235
7556890b
RS
10236 f->output_data.x->pixel_width = event.xconfigure.width;
10237 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
10238
10239 /* What we have now is the position of Emacs's own window.
10240 Convert that to the position of the window manager window. */
dcb07ae9
RS
10241 x_real_positions (f, &f->output_data.x->left_pos,
10242 &f->output_data.x->top_pos);
10243
f5d11644
GM
10244#ifdef HAVE_X_I18N
10245 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10246 xic_set_statusarea (f);
10247#endif
10248
dcb07ae9
RS
10249 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10250 {
10251 /* Since the WM decorations come below top_pos now,
10252 we must put them below top_pos in the future. */
10253 f->output_data.x->win_gravity = NorthWestGravity;
10254 x_wm_set_size_hint (f, (long) 0, 0);
10255 }
8f08dc93
KH
10256#ifdef USE_MOTIF
10257 /* Some window managers pass (0,0) as the location of
10258 the window, and the Motif event handler stores it
10259 in the emacs widget, which messes up Motif menus. */
10260 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10261 {
10262 event.xconfigure.x = f->output_data.x->widget->core.x;
10263 event.xconfigure.y = f->output_data.x->widget->core.y;
10264 }
06a2c219 10265#endif /* USE_MOTIF */
7a13e894 10266 }
2d7fc7e8 10267 goto OTHER;
dc6f92b8 10268
7a13e894
RS
10269 case ButtonPress:
10270 case ButtonRelease:
10271 {
10272 /* If we decide we want to generate an event to be seen
10273 by the rest of Emacs, we put it here. */
10274 struct input_event emacs_event;
9ea173e8 10275 int tool_bar_p = 0;
06a2c219 10276
7a13e894 10277 emacs_event.kind = no_event;
7a13e894 10278 bzero (&compose_status, sizeof (compose_status));
9b07615b 10279
06a2c219
GM
10280 if (dpyinfo->grabbed
10281 && last_mouse_frame
9f67f20b
RS
10282 && FRAME_LIVE_P (last_mouse_frame))
10283 f = last_mouse_frame;
10284 else
2224b905 10285 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 10286
06a2c219
GM
10287 if (f)
10288 {
9ea173e8
GM
10289 /* Is this in the tool-bar? */
10290 if (WINDOWP (f->tool_bar_window)
10291 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
10292 {
10293 Lisp_Object window;
10294 int p, x, y;
10295
10296 x = event.xbutton.x;
10297 y = event.xbutton.y;
10298
10299 /* Set x and y. */
10300 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 10301 if (EQ (window, f->tool_bar_window))
06a2c219 10302 {
9ea173e8
GM
10303 x_handle_tool_bar_click (f, &event.xbutton);
10304 tool_bar_p = 1;
06a2c219
GM
10305 }
10306 }
10307
9ea173e8 10308 if (!tool_bar_p)
06a2c219
GM
10309 if (!dpyinfo->x_focus_frame
10310 || f == dpyinfo->x_focus_frame)
10311 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
10312 }
10313 else
10314 {
06a2c219 10315#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10316 struct scroll_bar *bar
10317 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 10318
7a13e894
RS
10319 if (bar)
10320 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 10321#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10322 }
10323
10324 if (event.type == ButtonPress)
10325 {
10326 dpyinfo->grabbed |= (1 << event.xbutton.button);
10327 last_mouse_frame = f;
edad46f6
KH
10328 /* Ignore any mouse motion that happened
10329 before this event; any subsequent mouse-movement
10330 Emacs events should reflect only motion after
10331 the ButtonPress. */
a00e91cd
KH
10332 if (f != 0)
10333 f->mouse_moved = 0;
06a2c219 10334
9ea173e8
GM
10335 if (!tool_bar_p)
10336 last_tool_bar_item = -1;
7a13e894 10337 }
3afe33e7
RS
10338 else
10339 {
7a13e894 10340 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10341 }
23faf38f 10342
7a13e894
RS
10343 if (numchars >= 1 && emacs_event.kind != no_event)
10344 {
10345 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10346 bufp++;
10347 count++;
10348 numchars--;
10349 }
3afe33e7
RS
10350
10351#ifdef USE_X_TOOLKIT
2224b905
RS
10352 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10353 /* For a down-event in the menu bar,
10354 don't pass it to Xt right now.
10355 Instead, save it away
10356 and we will pass it to Xt from kbd_buffer_get_event.
10357 That way, we can run some Lisp code first. */
91375f8f
RS
10358 if (f && event.type == ButtonPress
10359 /* Verify the event is really within the menu bar
10360 and not just sent to it due to grabbing. */
10361 && event.xbutton.x >= 0
10362 && event.xbutton.x < f->output_data.x->pixel_width
10363 && event.xbutton.y >= 0
10364 && event.xbutton.y < f->output_data.x->menubar_height
10365 && event.xbutton.same_screen)
2224b905 10366 {
8805890a 10367 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10368 XSETFRAME (last_mouse_press_frame, f);
10369 }
10370 else if (event.type == ButtonPress)
10371 {
10372 last_mouse_press_frame = Qnil;
30e671c3 10373 goto OTHER;
ce89ef46 10374 }
06a2c219 10375
2237cac9
RS
10376#ifdef USE_MOTIF /* This should do not harm for Lucid,
10377 but I am trying to be cautious. */
ce89ef46
RS
10378 else if (event.type == ButtonRelease)
10379 {
2237cac9 10380 if (!NILP (last_mouse_press_frame))
f10ded1c 10381 {
2237cac9
RS
10382 f = XFRAME (last_mouse_press_frame);
10383 if (f->output_data.x)
06a2c219 10384 SET_SAVED_BUTTON_EVENT;
f10ded1c 10385 }
06a2c219 10386 else
30e671c3 10387 goto OTHER;
2224b905 10388 }
2237cac9 10389#endif /* USE_MOTIF */
2224b905
RS
10390 else
10391 goto OTHER;
3afe33e7 10392#endif /* USE_X_TOOLKIT */
7a13e894
RS
10393 }
10394 break;
dc6f92b8 10395
7a13e894 10396 case CirculateNotify:
06a2c219
GM
10397 goto OTHER;
10398
7a13e894 10399 case CirculateRequest:
06a2c219
GM
10400 goto OTHER;
10401
10402 case VisibilityNotify:
10403 goto OTHER;
dc6f92b8 10404
7a13e894
RS
10405 case MappingNotify:
10406 /* Someone has changed the keyboard mapping - update the
10407 local cache. */
10408 switch (event.xmapping.request)
10409 {
10410 case MappingModifier:
10411 x_find_modifier_meanings (dpyinfo);
10412 /* This is meant to fall through. */
10413 case MappingKeyboard:
10414 XRefreshKeyboardMapping (&event.xmapping);
10415 }
7a13e894 10416 goto OTHER;
dc6f92b8 10417
7a13e894 10418 default:
7a13e894 10419 OTHER:
717ca130 10420#ifdef USE_X_TOOLKIT
7a13e894
RS
10421 BLOCK_INPUT;
10422 XtDispatchEvent (&event);
10423 UNBLOCK_INPUT;
3afe33e7 10424#endif /* USE_X_TOOLKIT */
7a13e894
RS
10425 break;
10426 }
dc6f92b8
JB
10427 }
10428 }
10429
06a2c219
GM
10430 out:;
10431
9a5196d0
RS
10432 /* On some systems, an X bug causes Emacs to get no more events
10433 when the window is destroyed. Detect that. (1994.) */
58769bee 10434 if (! event_found)
ef2a22d0 10435 {
ef2a22d0
RS
10436 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10437 One XNOOP in 100 loops will make Emacs terminate.
10438 B. Bretthauer, 1994 */
10439 x_noop_count++;
58769bee 10440 if (x_noop_count >= 100)
ef2a22d0
RS
10441 {
10442 x_noop_count=0;
2224b905
RS
10443
10444 if (next_noop_dpyinfo == 0)
10445 next_noop_dpyinfo = x_display_list;
10446
10447 XNoOp (next_noop_dpyinfo->display);
10448
10449 /* Each time we get here, cycle through the displays now open. */
10450 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10451 }
10452 }
502add23 10453
06a2c219 10454 /* If the focus was just given to an auto-raising frame,
0134a210 10455 raise it now. */
7a13e894 10456 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10457 if (pending_autoraise_frame)
10458 {
10459 x_raise_frame (pending_autoraise_frame);
10460 pending_autoraise_frame = 0;
10461 }
0134a210 10462
dc6f92b8 10463 UNBLOCK_INPUT;
bde5503b 10464 --handling_signal;
dc6f92b8
JB
10465 return count;
10466}
06a2c219
GM
10467
10468
10469
dc6f92b8 10470\f
06a2c219
GM
10471/***********************************************************************
10472 Text Cursor
10473 ***********************************************************************/
10474
10475/* Note if the text cursor of window W has been overwritten by a
10476 drawing operation that outputs N glyphs starting at HPOS in the
10477 line given by output_cursor.vpos. N < 0 means all the rest of the
10478 line after HPOS has been written. */
10479
10480static void
10481note_overwritten_text_cursor (w, hpos, n)
10482 struct window *w;
10483 int hpos, n;
10484{
10485 if (updated_area == TEXT_AREA
10486 && output_cursor.vpos == w->phys_cursor.vpos
10487 && hpos <= w->phys_cursor.hpos
10488 && (n < 0
10489 || hpos + n > w->phys_cursor.hpos))
10490 w->phys_cursor_on_p = 0;
10491}
f451eb13
JB
10492
10493
06a2c219
GM
10494/* Set clipping for output in glyph row ROW. W is the window in which
10495 we operate. GC is the graphics context to set clipping in.
10496 WHOLE_LINE_P non-zero means include the areas used for truncation
10497 mark display and alike in the clipping rectangle.
10498
10499 ROW may be a text row or, e.g., a mode line. Text rows must be
10500 clipped to the interior of the window dedicated to text display,
10501 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10502
10503static void
06a2c219
GM
10504x_clip_to_row (w, row, gc, whole_line_p)
10505 struct window *w;
10506 struct glyph_row *row;
10507 GC gc;
10508 int whole_line_p;
dc6f92b8 10509{
06a2c219
GM
10510 struct frame *f = XFRAME (WINDOW_FRAME (w));
10511 XRectangle clip_rect;
10512 int window_x, window_y, window_width, window_height;
dc6f92b8 10513
06a2c219 10514 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10515
06a2c219
GM
10516 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10517 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10518 clip_rect.y = max (clip_rect.y, window_y);
10519 clip_rect.width = window_width;
10520 clip_rect.height = row->visible_height;
5c1aae96 10521
06a2c219
GM
10522 /* If clipping to the whole line, including trunc marks, extend
10523 the rectangle to the left and increase its width. */
10524 if (whole_line_p)
10525 {
110859fc
GM
10526 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10527 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10528 }
5c1aae96 10529
06a2c219 10530 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10531}
10532
06a2c219
GM
10533
10534/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10535
10536static void
06a2c219
GM
10537x_draw_hollow_cursor (w, row)
10538 struct window *w;
10539 struct glyph_row *row;
dc6f92b8 10540{
06a2c219
GM
10541 struct frame *f = XFRAME (WINDOW_FRAME (w));
10542 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10543 Display *dpy = FRAME_X_DISPLAY (f);
10544 int x, y, wd, h;
10545 XGCValues xgcv;
10546 struct glyph *cursor_glyph;
10547 GC gc;
10548
10549 /* Compute frame-relative coordinates from window-relative
10550 coordinates. */
10551 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10552 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10553 + row->ascent - w->phys_cursor_ascent);
10554 h = row->height - 1;
10555
10556 /* Get the glyph the cursor is on. If we can't tell because
10557 the current matrix is invalid or such, give up. */
10558 cursor_glyph = get_phys_cursor_glyph (w);
10559 if (cursor_glyph == NULL)
dc6f92b8
JB
10560 return;
10561
06a2c219
GM
10562 /* Compute the width of the rectangle to draw. If on a stretch
10563 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10564 rectangle as wide as the glyph, but use a canonical character
10565 width instead. */
10566 wd = cursor_glyph->pixel_width - 1;
10567 if (cursor_glyph->type == STRETCH_GLYPH
10568 && !x_stretch_cursor_p)
10569 wd = min (CANON_X_UNIT (f), wd);
10570
10571 /* The foreground of cursor_gc is typically the same as the normal
10572 background color, which can cause the cursor box to be invisible. */
10573 xgcv.foreground = f->output_data.x->cursor_pixel;
10574 if (dpyinfo->scratch_cursor_gc)
10575 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10576 else
10577 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10578 GCForeground, &xgcv);
10579 gc = dpyinfo->scratch_cursor_gc;
10580
10581 /* Set clipping, draw the rectangle, and reset clipping again. */
10582 x_clip_to_row (w, row, gc, 0);
10583 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10584 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10585}
10586
06a2c219
GM
10587
10588/* Draw a bar cursor on window W in glyph row ROW.
10589
10590 Implementation note: One would like to draw a bar cursor with an
10591 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10592 Unfortunately, I didn't find a font yet that has this property set.
10593 --gerd. */
dc6f92b8
JB
10594
10595static void
f02d8aa0 10596x_draw_bar_cursor (w, row, width)
06a2c219
GM
10597 struct window *w;
10598 struct glyph_row *row;
f02d8aa0 10599 int width;
dc6f92b8 10600{
92f424df
GM
10601 struct frame *f = XFRAME (w->frame);
10602 struct glyph *cursor_glyph;
10603 GC gc;
10604 int x;
10605 unsigned long mask;
10606 XGCValues xgcv;
10607 Display *dpy;
10608 Window window;
06a2c219 10609
92f424df
GM
10610 /* If cursor is out of bounds, don't draw garbage. This can happen
10611 in mini-buffer windows when switching between echo area glyphs
10612 and mini-buffer. */
10613 cursor_glyph = get_phys_cursor_glyph (w);
10614 if (cursor_glyph == NULL)
10615 return;
06a2c219 10616
92f424df
GM
10617 /* If on an image, draw like a normal cursor. That's usually better
10618 visible than drawing a bar, esp. if the image is large so that
10619 the bar might not be in the window. */
10620 if (cursor_glyph->type == IMAGE_GLYPH)
10621 {
10622 struct glyph_row *row;
10623 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10624 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10625 }
10626 else
10627 {
06a2c219
GM
10628 xgcv.background = f->output_data.x->cursor_pixel;
10629 xgcv.foreground = f->output_data.x->cursor_pixel;
10630 xgcv.graphics_exposures = 0;
10631 mask = GCForeground | GCBackground | GCGraphicsExposures;
10632 dpy = FRAME_X_DISPLAY (f);
10633 window = FRAME_X_WINDOW (f);
10634 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
92f424df 10635
06a2c219
GM
10636 if (gc)
10637 XChangeGC (dpy, gc, mask, &xgcv);
10638 else
10639 {
10640 gc = XCreateGC (dpy, window, mask, &xgcv);
10641 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10642 }
92f424df 10643
f02d8aa0
GM
10644 if (width < 0)
10645 width = f->output_data.x->cursor_width;
92f424df 10646
06a2c219
GM
10647 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10648 x_clip_to_row (w, row, gc, 0);
10649 XFillRectangle (dpy, window, gc,
10650 x,
10651 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10652 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10653 row->height);
10654 XSetClipMask (dpy, gc, None);
10655 }
dc6f92b8
JB
10656}
10657
06a2c219
GM
10658
10659/* Clear the cursor of window W to background color, and mark the
10660 cursor as not shown. This is used when the text where the cursor
10661 is is about to be rewritten. */
10662
dc6f92b8 10663static void
06a2c219
GM
10664x_clear_cursor (w)
10665 struct window *w;
dc6f92b8 10666{
06a2c219
GM
10667 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10668 x_update_window_cursor (w, 0);
10669}
90e65f07 10670
dbc4e1c1 10671
06a2c219
GM
10672/* Draw the cursor glyph of window W in glyph row ROW. See the
10673 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10674
06a2c219
GM
10675static void
10676x_draw_phys_cursor_glyph (w, row, hl)
10677 struct window *w;
10678 struct glyph_row *row;
10679 enum draw_glyphs_face hl;
10680{
10681 /* If cursor hpos is out of bounds, don't draw garbage. This can
10682 happen in mini-buffer windows when switching between echo area
10683 glyphs and mini-buffer. */
10684 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10685 {
10686 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10687 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10688 hl, 0, 0, 0);
10689
10690 /* When we erase the cursor, and ROW is overlapped by other
10691 rows, make sure that these overlapping parts of other rows
10692 are redrawn. */
10693 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10694 {
10695 if (row > w->current_matrix->rows
10696 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10697 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10698
10699 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10700 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10701 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10702 }
10703 }
06a2c219 10704}
dbc4e1c1 10705
eea6af04 10706
06a2c219 10707/* Erase the image of a cursor of window W from the screen. */
eea6af04 10708
06a2c219
GM
10709static void
10710x_erase_phys_cursor (w)
10711 struct window *w;
10712{
10713 struct frame *f = XFRAME (w->frame);
10714 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10715 int hpos = w->phys_cursor.hpos;
10716 int vpos = w->phys_cursor.vpos;
10717 int mouse_face_here_p = 0;
10718 struct glyph_matrix *active_glyphs = w->current_matrix;
10719 struct glyph_row *cursor_row;
10720 struct glyph *cursor_glyph;
10721 enum draw_glyphs_face hl;
10722
10723 /* No cursor displayed or row invalidated => nothing to do on the
10724 screen. */
10725 if (w->phys_cursor_type == NO_CURSOR)
10726 goto mark_cursor_off;
10727
10728 /* VPOS >= active_glyphs->nrows means that window has been resized.
10729 Don't bother to erase the cursor. */
10730 if (vpos >= active_glyphs->nrows)
10731 goto mark_cursor_off;
10732
10733 /* If row containing cursor is marked invalid, there is nothing we
10734 can do. */
10735 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10736 if (!cursor_row->enabled_p)
10737 goto mark_cursor_off;
10738
10739 /* This can happen when the new row is shorter than the old one.
10740 In this case, either x_draw_glyphs or clear_end_of_line
10741 should have cleared the cursor. Note that we wouldn't be
10742 able to erase the cursor in this case because we don't have a
10743 cursor glyph at hand. */
10744 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10745 goto mark_cursor_off;
10746
10747 /* If the cursor is in the mouse face area, redisplay that when
10748 we clear the cursor. */
8801a864
KR
10749 if (! NILP (dpyinfo->mouse_face_window)
10750 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10751 && (vpos > dpyinfo->mouse_face_beg_row
10752 || (vpos == dpyinfo->mouse_face_beg_row
10753 && hpos >= dpyinfo->mouse_face_beg_col))
10754 && (vpos < dpyinfo->mouse_face_end_row
10755 || (vpos == dpyinfo->mouse_face_end_row
10756 && hpos < dpyinfo->mouse_face_end_col))
10757 /* Don't redraw the cursor's spot in mouse face if it is at the
10758 end of a line (on a newline). The cursor appears there, but
10759 mouse highlighting does not. */
10760 && cursor_row->used[TEXT_AREA] > hpos)
10761 mouse_face_here_p = 1;
10762
10763 /* Maybe clear the display under the cursor. */
10764 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10765 {
10766 int x;
045dee35 10767 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10768
06a2c219
GM
10769 cursor_glyph = get_phys_cursor_glyph (w);
10770 if (cursor_glyph == NULL)
10771 goto mark_cursor_off;
dbc4e1c1 10772
06a2c219
GM
10773 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10774
10775 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10776 x,
045dee35 10777 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10778 cursor_row->y)),
10779 cursor_glyph->pixel_width,
10780 cursor_row->visible_height,
10781 False);
dbc4e1c1 10782 }
06a2c219
GM
10783
10784 /* Erase the cursor by redrawing the character underneath it. */
10785 if (mouse_face_here_p)
10786 hl = DRAW_MOUSE_FACE;
10787 else if (cursor_row->inverse_p)
10788 hl = DRAW_INVERSE_VIDEO;
10789 else
10790 hl = DRAW_NORMAL_TEXT;
10791 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10792
06a2c219
GM
10793 mark_cursor_off:
10794 w->phys_cursor_on_p = 0;
10795 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10796}
10797
10798
06a2c219
GM
10799/* Display or clear cursor of window W. If ON is zero, clear the
10800 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10801 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10802
06a2c219
GM
10803void
10804x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10805 struct window *w;
10806 int on, hpos, vpos, x, y;
dbc4e1c1 10807{
06a2c219
GM
10808 struct frame *f = XFRAME (w->frame);
10809 int new_cursor_type;
f02d8aa0 10810 int new_cursor_width;
06a2c219
GM
10811 struct glyph_matrix *current_glyphs;
10812 struct glyph_row *glyph_row;
10813 struct glyph *glyph;
dbc4e1c1 10814
49d838ea 10815 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10816 windows and frames; in the latter case, the frame or window may
10817 be in the midst of changing its size, and x and y may be off the
10818 window. */
10819 if (! FRAME_VISIBLE_P (f)
10820 || FRAME_GARBAGED_P (f)
10821 || vpos >= w->current_matrix->nrows
10822 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10823 return;
10824
10825 /* If cursor is off and we want it off, return quickly. */
06a2c219 10826 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10827 return;
10828
06a2c219
GM
10829 current_glyphs = w->current_matrix;
10830 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10831 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10832
10833 /* If cursor row is not enabled, we don't really know where to
10834 display the cursor. */
10835 if (!glyph_row->enabled_p)
10836 {
10837 w->phys_cursor_on_p = 0;
10838 return;
10839 }
10840
10841 xassert (interrupt_input_blocked);
10842
10843 /* Set new_cursor_type to the cursor we want to be displayed. In a
10844 mini-buffer window, we want the cursor only to appear if we are
10845 reading input from this window. For the selected window, we want
10846 the cursor type given by the frame parameter. If explicitly
10847 marked off, draw no cursor. In all other cases, we want a hollow
10848 box cursor. */
f02d8aa0 10849 new_cursor_width = -1;
9b4a7047
GM
10850 if (cursor_in_echo_area
10851 && FRAME_HAS_MINIBUF_P (f)
10852 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10853 {
9b4a7047
GM
10854 if (w == XWINDOW (echo_area_window))
10855 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10856 else
10857 new_cursor_type = HOLLOW_BOX_CURSOR;
10858 }
06a2c219 10859 else
9b4a7047
GM
10860 {
10861 if (w != XWINDOW (selected_window)
10862 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10863 {
e55a0b79
GM
10864 extern int cursor_in_non_selected_windows;
10865
5cefa566
GM
10866 if (MINI_WINDOW_P (w)
10867 || !cursor_in_non_selected_windows
10868 || NILP (XBUFFER (w->buffer)->cursor_type))
9b4a7047
GM
10869 new_cursor_type = NO_CURSOR;
10870 else
10871 new_cursor_type = HOLLOW_BOX_CURSOR;
10872 }
10873 else if (w->cursor_off_p)
10874 new_cursor_type = NO_CURSOR;
10875 else
f02d8aa0
GM
10876 {
10877 struct buffer *b = XBUFFER (w->buffer);
10878
10879 if (EQ (b->cursor_type, Qt))
10880 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10881 else
10882 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10883 &new_cursor_width);
10884 }
9b4a7047 10885 }
06a2c219
GM
10886
10887 /* If cursor is currently being shown and we don't want it to be or
10888 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10889 erase it. */
06a2c219 10890 if (w->phys_cursor_on_p
dc6f92b8 10891 && (!on
06a2c219
GM
10892 || w->phys_cursor.x != x
10893 || w->phys_cursor.y != y
10894 || new_cursor_type != w->phys_cursor_type))
10895 x_erase_phys_cursor (w);
10896
10897 /* If the cursor is now invisible and we want it to be visible,
10898 display it. */
10899 if (on && !w->phys_cursor_on_p)
10900 {
10901 w->phys_cursor_ascent = glyph_row->ascent;
10902 w->phys_cursor_height = glyph_row->height;
10903
10904 /* Set phys_cursor_.* before x_draw_.* is called because some
10905 of them may need the information. */
10906 w->phys_cursor.x = x;
10907 w->phys_cursor.y = glyph_row->y;
10908 w->phys_cursor.hpos = hpos;
10909 w->phys_cursor.vpos = vpos;
10910 w->phys_cursor_type = new_cursor_type;
10911 w->phys_cursor_on_p = 1;
10912
10913 switch (new_cursor_type)
dc6f92b8 10914 {
06a2c219
GM
10915 case HOLLOW_BOX_CURSOR:
10916 x_draw_hollow_cursor (w, glyph_row);
10917 break;
10918
10919 case FILLED_BOX_CURSOR:
10920 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10921 break;
10922
10923 case BAR_CURSOR:
f02d8aa0 10924 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10925 break;
10926
10927 case NO_CURSOR:
10928 break;
dc6f92b8 10929
06a2c219
GM
10930 default:
10931 abort ();
10932 }
59ddecde
GM
10933
10934#ifdef HAVE_X_I18N
10935 if (w == XWINDOW (f->selected_window))
10936 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10937 xic_set_preeditarea (w, x, y);
10938#endif
dc6f92b8
JB
10939 }
10940
06a2c219 10941#ifndef XFlush
f676886a 10942 if (updating_frame != f)
334208b7 10943 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10944#endif
dc6f92b8
JB
10945}
10946
06a2c219
GM
10947
10948/* Display the cursor on window W, or clear it. X and Y are window
10949 relative pixel coordinates. HPOS and VPOS are glyph matrix
10950 positions. If W is not the selected window, display a hollow
10951 cursor. ON non-zero means display the cursor at X, Y which
10952 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10953
dfcf069d 10954void
06a2c219
GM
10955x_display_cursor (w, on, hpos, vpos, x, y)
10956 struct window *w;
10957 int on, hpos, vpos, x, y;
dc6f92b8 10958{
f94397b5 10959 BLOCK_INPUT;
06a2c219 10960 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10961 UNBLOCK_INPUT;
10962}
10963
06a2c219
GM
10964
10965/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10966 Don't change the cursor's position. */
10967
dfcf069d 10968void
06a2c219 10969x_update_cursor (f, on_p)
5d46f928 10970 struct frame *f;
5d46f928 10971{
06a2c219
GM
10972 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10973}
10974
10975
10976/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10977 in the window tree rooted at W. */
10978
10979static void
10980x_update_cursor_in_window_tree (w, on_p)
10981 struct window *w;
10982 int on_p;
10983{
10984 while (w)
10985 {
10986 if (!NILP (w->hchild))
10987 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10988 else if (!NILP (w->vchild))
10989 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10990 else
10991 x_update_window_cursor (w, on_p);
10992
10993 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10994 }
10995}
5d46f928 10996
f94397b5 10997
06a2c219
GM
10998/* Switch the display of W's cursor on or off, according to the value
10999 of ON. */
11000
11001static void
11002x_update_window_cursor (w, on)
11003 struct window *w;
11004 int on;
11005{
16b5d424
GM
11006 /* Don't update cursor in windows whose frame is in the process
11007 of being deleted. */
11008 if (w->current_matrix)
11009 {
11010 BLOCK_INPUT;
11011 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11012 w->phys_cursor.x, w->phys_cursor.y);
11013 UNBLOCK_INPUT;
11014 }
dc6f92b8 11015}
06a2c219
GM
11016
11017
11018
dc6f92b8
JB
11019\f
11020/* Icons. */
11021
f676886a 11022/* Refresh bitmap kitchen sink icon for frame F
06a2c219 11023 when we get an expose event for it. */
dc6f92b8 11024
dfcf069d 11025void
f676886a
JB
11026refreshicon (f)
11027 struct frame *f;
dc6f92b8 11028{
06a2c219 11029 /* Normally, the window manager handles this function. */
dc6f92b8
JB
11030}
11031
dbc4e1c1 11032/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
11033
11034int
990ba854 11035x_bitmap_icon (f, file)
f676886a 11036 struct frame *f;
990ba854 11037 Lisp_Object file;
dc6f92b8 11038{
06a2c219 11039 int bitmap_id;
dc6f92b8 11040
c118dd06 11041 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11042 return 1;
11043
990ba854 11044 /* Free up our existing icon bitmap if any. */
7556890b
RS
11045 if (f->output_data.x->icon_bitmap > 0)
11046 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11047 f->output_data.x->icon_bitmap = 0;
990ba854
RS
11048
11049 if (STRINGP (file))
7f2ae036
RS
11050 bitmap_id = x_create_bitmap_from_file (f, file);
11051 else
11052 {
990ba854 11053 /* Create the GNU bitmap if necessary. */
5bf01b68 11054 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
11055 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11056 = x_create_bitmap_from_data (f, gnu_bits,
11057 gnu_width, gnu_height);
990ba854
RS
11058
11059 /* The first time we create the GNU bitmap,
06a2c219 11060 this increments the ref-count one extra time.
990ba854
RS
11061 As a result, the GNU bitmap is never freed.
11062 That way, we don't have to worry about allocating it again. */
334208b7 11063 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 11064
334208b7 11065 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
11066 }
11067
11068 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 11069 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
11070
11071 return 0;
11072}
11073
11074
1be2d067
KH
11075/* Make the x-window of frame F use a rectangle with text.
11076 Use ICON_NAME as the text. */
dc6f92b8
JB
11077
11078int
f676886a
JB
11079x_text_icon (f, icon_name)
11080 struct frame *f;
dc6f92b8
JB
11081 char *icon_name;
11082{
c118dd06 11083 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11084 return 1;
11085
1be2d067
KH
11086#ifdef HAVE_X11R4
11087 {
11088 XTextProperty text;
11089 text.value = (unsigned char *) icon_name;
11090 text.encoding = XA_STRING;
11091 text.format = 8;
11092 text.nitems = strlen (icon_name);
11093#ifdef USE_X_TOOLKIT
7556890b 11094 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
11095 &text);
11096#else /* not USE_X_TOOLKIT */
11097 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11098#endif /* not USE_X_TOOLKIT */
11099 }
11100#else /* not HAVE_X11R4 */
11101 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11102#endif /* not HAVE_X11R4 */
58769bee 11103
7556890b
RS
11104 if (f->output_data.x->icon_bitmap > 0)
11105 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11106 f->output_data.x->icon_bitmap = 0;
b1c884c3 11107 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
11108
11109 return 0;
11110}
11111\f
e99db5a1
RS
11112#define X_ERROR_MESSAGE_SIZE 200
11113
11114/* If non-nil, this should be a string.
11115 It means catch X errors and store the error message in this string. */
11116
11117static Lisp_Object x_error_message_string;
11118
11119/* An X error handler which stores the error message in
11120 x_error_message_string. This is called from x_error_handler if
11121 x_catch_errors is in effect. */
11122
06a2c219 11123static void
e99db5a1
RS
11124x_error_catcher (display, error)
11125 Display *display;
11126 XErrorEvent *error;
11127{
11128 XGetErrorText (display, error->error_code,
11129 XSTRING (x_error_message_string)->data,
11130 X_ERROR_MESSAGE_SIZE);
11131}
11132
11133/* Begin trapping X errors for display DPY. Actually we trap X errors
11134 for all displays, but DPY should be the display you are actually
11135 operating on.
11136
11137 After calling this function, X protocol errors no longer cause
11138 Emacs to exit; instead, they are recorded in the string
11139 stored in x_error_message_string.
11140
11141 Calling x_check_errors signals an Emacs error if an X error has
11142 occurred since the last call to x_catch_errors or x_check_errors.
11143
11144 Calling x_uncatch_errors resumes the normal error handling. */
11145
11146void x_check_errors ();
11147static Lisp_Object x_catch_errors_unwind ();
11148
11149int
11150x_catch_errors (dpy)
11151 Display *dpy;
11152{
11153 int count = specpdl_ptr - specpdl;
11154
11155 /* Make sure any errors from previous requests have been dealt with. */
11156 XSync (dpy, False);
11157
11158 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11159
11160 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11161 XSTRING (x_error_message_string)->data[0] = 0;
11162
11163 return count;
11164}
11165
11166/* Unbind the binding that we made to check for X errors. */
11167
11168static Lisp_Object
11169x_catch_errors_unwind (old_val)
11170 Lisp_Object old_val;
11171{
11172 x_error_message_string = old_val;
11173 return Qnil;
11174}
11175
11176/* If any X protocol errors have arrived since the last call to
11177 x_catch_errors or x_check_errors, signal an Emacs error using
11178 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11179
11180void
11181x_check_errors (dpy, format)
11182 Display *dpy;
11183 char *format;
11184{
11185 /* Make sure to catch any errors incurred so far. */
11186 XSync (dpy, False);
11187
11188 if (XSTRING (x_error_message_string)->data[0])
11189 error (format, XSTRING (x_error_message_string)->data);
11190}
11191
9829ddba
RS
11192/* Nonzero if we had any X protocol errors
11193 since we did x_catch_errors on DPY. */
e99db5a1
RS
11194
11195int
11196x_had_errors_p (dpy)
11197 Display *dpy;
11198{
11199 /* Make sure to catch any errors incurred so far. */
11200 XSync (dpy, False);
11201
11202 return XSTRING (x_error_message_string)->data[0] != 0;
11203}
11204
9829ddba
RS
11205/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11206
06a2c219 11207void
9829ddba
RS
11208x_clear_errors (dpy)
11209 Display *dpy;
11210{
11211 XSTRING (x_error_message_string)->data[0] = 0;
11212}
11213
e99db5a1
RS
11214/* Stop catching X protocol errors and let them make Emacs die.
11215 DPY should be the display that was passed to x_catch_errors.
11216 COUNT should be the value that was returned by
11217 the corresponding call to x_catch_errors. */
11218
11219void
11220x_uncatch_errors (dpy, count)
11221 Display *dpy;
11222 int count;
11223{
11224 unbind_to (count, Qnil);
11225}
11226
11227#if 0
11228static unsigned int x_wire_count;
11229x_trace_wire ()
11230{
11231 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11232}
11233#endif /* ! 0 */
11234
11235\f
11236/* Handle SIGPIPE, which can happen when the connection to a server
11237 simply goes away. SIGPIPE is handled by x_connection_signal.
11238 Don't need to do anything, because the write which caused the
11239 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 11240 which will do the appropriate cleanup for us. */
e99db5a1
RS
11241
11242static SIGTYPE
11243x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 11244 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
11245{
11246#ifdef USG
11247 /* USG systems forget handlers when they are used;
11248 must reestablish each time */
11249 signal (signalnum, x_connection_signal);
11250#endif /* USG */
11251}
0da1ab50 11252
e99db5a1 11253\f
0da1ab50
GM
11254/************************************************************************
11255 Handling X errors
11256 ************************************************************************/
4746118a 11257
0da1ab50
GM
11258/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11259 the text of an error message that lead to the connection loss. */
16bd92ea 11260
4746118a 11261static SIGTYPE
5978125e
GM
11262x_connection_closed (dpy, error_message)
11263 Display *dpy;
7a13e894 11264 char *error_message;
4746118a 11265{
5978125e 11266 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7a13e894 11267 Lisp_Object frame, tail;
0da1ab50
GM
11268 int count;
11269 char *msg;
11270
11271 msg = (char *) alloca (strlen (error_message) + 1);
11272 strcpy (msg, error_message);
1a532e54
GM
11273 handling_signal = 0;
11274
0da1ab50
GM
11275 /* Prevent being called recursively because of an error condition
11276 below. Otherwise, we might end up with printing ``can't find per
11277 display information'' in the recursive call instead of printing
11278 the original message here. */
11279 count = x_catch_errors (dpy);
11280
8a4f36cc
GM
11281 /* We have to close the display to inform Xt that it doesn't
11282 exist anymore. If we don't, Xt will continue to wait for
11283 events from the display. As a consequence, a sequence of
11284
11285 M-x make-frame-on-display RET :1 RET
11286 ...kill the new frame, so that we get an IO error...
11287 M-x make-frame-on-display RET :1 RET
11288
11289 will indefinitely wait in Xt for events for display `:1', opened
11290 in the first class to make-frame-on-display.
6186a4a0 11291
8a4f36cc
GM
11292 Closing the display is reported to lead to a bus error on
11293 OpenWindows in certain situations. I suspect that is a bug
11294 in OpenWindows. I don't know how to cicumvent it here. */
11295
f613a4c8 11296#ifdef USE_X_TOOLKIT
ae24cb3b
GM
11297 /* If DPYINFO is null, this means we didn't open the display
11298 in the first place, so don't try to close it. */
11299 if (dpyinfo)
11300 XtCloseDisplay (dpy);
f613a4c8 11301#endif
adabc3a9 11302
8a4f36cc 11303 /* Indicate that this display is dead. */
9e80b57d
KR
11304 if (dpyinfo)
11305 dpyinfo->display = 0;
6186a4a0 11306
06a2c219 11307 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
11308 that are on the dead display. */
11309 FOR_EACH_FRAME (tail, frame)
11310 {
11311 Lisp_Object minibuf_frame;
11312 minibuf_frame
11313 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
11314 if (FRAME_X_P (XFRAME (frame))
11315 && FRAME_X_P (XFRAME (minibuf_frame))
11316 && ! EQ (frame, minibuf_frame)
11317 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
11318 Fdelete_frame (frame, Qt);
11319 }
11320
11321 /* Now delete all remaining frames on the dead display.
06a2c219 11322 We are now sure none of these is used as the mini-buffer
7a13e894
RS
11323 for another frame that we need to delete. */
11324 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
11325 if (FRAME_X_P (XFRAME (frame))
11326 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
11327 {
11328 /* Set this to t so that Fdelete_frame won't get confused
11329 trying to find a replacement. */
11330 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11331 Fdelete_frame (frame, Qt);
11332 }
7a13e894 11333
482a1bd2
KH
11334 if (dpyinfo)
11335 x_delete_display (dpyinfo);
7a13e894 11336
0da1ab50
GM
11337 x_uncatch_errors (dpy, count);
11338
7a13e894
RS
11339 if (x_display_list == 0)
11340 {
0da1ab50 11341 fprintf (stderr, "%s\n", msg);
7a13e894
RS
11342 shut_down_emacs (0, 0, Qnil);
11343 exit (70);
11344 }
12ba150f 11345
7a13e894
RS
11346 /* Ordinary stack unwind doesn't deal with these. */
11347#ifdef SIGIO
11348 sigunblock (sigmask (SIGIO));
11349#endif
11350 sigunblock (sigmask (SIGALRM));
11351 TOTALLY_UNBLOCK_INPUT;
11352
aa4d9a9e 11353 clear_waiting_for_input ();
0da1ab50 11354 error ("%s", msg);
4746118a
JB
11355}
11356
0da1ab50 11357
7a13e894
RS
11358/* This is the usual handler for X protocol errors.
11359 It kills all frames on the display that we got the error for.
11360 If that was the only one, it prints an error message and kills Emacs. */
11361
06a2c219 11362static void
c118dd06
JB
11363x_error_quitter (display, error)
11364 Display *display;
11365 XErrorEvent *error;
11366{
7a13e894 11367 char buf[256], buf1[356];
dc6f92b8 11368
58769bee 11369 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 11370 original error handler. */
dc6f92b8 11371
c118dd06 11372 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 11373 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 11374 buf, error->request_code);
7a13e894 11375 x_connection_closed (display, buf1);
dc6f92b8
JB
11376}
11377
0da1ab50 11378
e99db5a1
RS
11379/* This is the first-level handler for X protocol errors.
11380 It calls x_error_quitter or x_error_catcher. */
7a13e894 11381
8922af5f 11382static int
e99db5a1 11383x_error_handler (display, error)
8922af5f 11384 Display *display;
e99db5a1 11385 XErrorEvent *error;
8922af5f 11386{
e99db5a1
RS
11387 if (! NILP (x_error_message_string))
11388 x_error_catcher (display, error);
11389 else
11390 x_error_quitter (display, error);
06a2c219 11391 return 0;
f9e24cb9 11392}
c118dd06 11393
e99db5a1
RS
11394/* This is the handler for X IO errors, always.
11395 It kills all frames on the display that we lost touch with.
11396 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 11397
c118dd06 11398static int
e99db5a1 11399x_io_error_quitter (display)
c118dd06 11400 Display *display;
c118dd06 11401{
e99db5a1 11402 char buf[256];
dc6f92b8 11403
e99db5a1
RS
11404 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11405 x_connection_closed (display, buf);
06a2c219 11406 return 0;
dc6f92b8 11407}
dc6f92b8 11408\f
f451eb13
JB
11409/* Changing the font of the frame. */
11410
76bcdf39
RS
11411/* Give frame F the font named FONTNAME as its default font, and
11412 return the full name of that font. FONTNAME may be a wildcard
11413 pattern; in that case, we choose some font that fits the pattern.
11414 The return value shows which font we chose. */
11415
b5cf7a0e 11416Lisp_Object
f676886a
JB
11417x_new_font (f, fontname)
11418 struct frame *f;
dc6f92b8
JB
11419 register char *fontname;
11420{
dc43ef94 11421 struct font_info *fontp
ee569018 11422 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 11423
dc43ef94
KH
11424 if (!fontp)
11425 return Qnil;
2224a5fc 11426
dc43ef94 11427 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11428 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11429 f->output_data.x->fontset = -1;
11430
b2cad826
KH
11431 /* Compute the scroll bar width in character columns. */
11432 if (f->scroll_bar_pixel_width > 0)
11433 {
7556890b 11434 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11435 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11436 }
11437 else
4e61bddf
RS
11438 {
11439 int wid = FONT_WIDTH (f->output_data.x->font);
11440 f->scroll_bar_cols = (14 + wid - 1) / wid;
11441 }
b2cad826 11442
f676886a 11443 /* Now make the frame display the given font. */
c118dd06 11444 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11445 {
7556890b
RS
11446 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11447 f->output_data.x->font->fid);
11448 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11449 f->output_data.x->font->fid);
11450 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11451 f->output_data.x->font->fid);
f676886a 11452
a27f9f86 11453 frame_update_line_height (f);
3497f73e
GM
11454
11455 /* Don't change the size of a tip frame; there's no point in
11456 doing it because it's done in Fx_show_tip, and it leads to
11457 problems because the tip frame has no widget. */
11458 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11459 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11460 }
a27f9f86
RS
11461 else
11462 /* If we are setting a new frame's font for the first time,
11463 there are no faces yet, so this font's height is the line height. */
7556890b 11464 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11465
dc43ef94
KH
11466 return build_string (fontp->full_name);
11467}
11468
11469/* Give frame F the fontset named FONTSETNAME as its default font, and
11470 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11471 pattern; in that case, we choose some fontset that fits the pattern.
11472 The return value shows which fontset we chose. */
b5cf7a0e 11473
dc43ef94
KH
11474Lisp_Object
11475x_new_fontset (f, fontsetname)
11476 struct frame *f;
11477 char *fontsetname;
11478{
ee569018 11479 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11480 Lisp_Object result;
b5cf7a0e 11481
dc43ef94
KH
11482 if (fontset < 0)
11483 return Qnil;
b5cf7a0e 11484
2da424f1
KH
11485 if (f->output_data.x->fontset == fontset)
11486 /* This fontset is already set in frame F. There's nothing more
11487 to do. */
ee569018 11488 return fontset_name (fontset);
dc43ef94 11489
ee569018 11490 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11491
11492 if (!STRINGP (result))
11493 /* Can't load ASCII font. */
11494 return Qnil;
11495
11496 /* Since x_new_font doesn't update any fontset information, do it now. */
11497 f->output_data.x->fontset = fontset;
dc43ef94 11498
f5d11644
GM
11499#ifdef HAVE_X_I18N
11500 if (FRAME_XIC (f)
11501 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11502 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11503#endif
11504
dc43ef94 11505 return build_string (fontsetname);
dc6f92b8 11506}
f5d11644
GM
11507
11508\f
11509/***********************************************************************
11510 X Input Methods
11511 ***********************************************************************/
11512
11513#ifdef HAVE_X_I18N
11514
11515#ifdef HAVE_X11R6
11516
11517/* XIM destroy callback function, which is called whenever the
11518 connection to input method XIM dies. CLIENT_DATA contains a
11519 pointer to the x_display_info structure corresponding to XIM. */
11520
11521static void
11522xim_destroy_callback (xim, client_data, call_data)
11523 XIM xim;
11524 XPointer client_data;
11525 XPointer call_data;
11526{
11527 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11528 Lisp_Object frame, tail;
11529
11530 BLOCK_INPUT;
11531
11532 /* No need to call XDestroyIC.. */
11533 FOR_EACH_FRAME (tail, frame)
11534 {
11535 struct frame *f = XFRAME (frame);
11536 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11537 {
11538 FRAME_XIC (f) = NULL;
11539 if (FRAME_XIC_FONTSET (f))
11540 {
11541 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11542 FRAME_XIC_FONTSET (f) = NULL;
11543 }
11544 }
11545 }
11546
11547 /* No need to call XCloseIM. */
11548 dpyinfo->xim = NULL;
11549 XFree (dpyinfo->xim_styles);
11550 UNBLOCK_INPUT;
11551}
11552
11553#endif /* HAVE_X11R6 */
11554
11555/* Open the connection to the XIM server on display DPYINFO.
11556 RESOURCE_NAME is the resource name Emacs uses. */
11557
11558static void
11559xim_open_dpy (dpyinfo, resource_name)
11560 struct x_display_info *dpyinfo;
11561 char *resource_name;
11562{
287f7dd6 11563#ifdef USE_XIM
f5d11644
GM
11564 XIM xim;
11565
11566 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11567 dpyinfo->xim = xim;
11568
11569 if (xim)
11570 {
f5d11644
GM
11571#ifdef HAVE_X11R6
11572 XIMCallback destroy;
11573#endif
11574
11575 /* Get supported styles and XIM values. */
11576 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11577
11578#ifdef HAVE_X11R6
11579 destroy.callback = xim_destroy_callback;
11580 destroy.client_data = (XPointer)dpyinfo;
68642df6 11581 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11582 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11583#endif
11584 }
287f7dd6
GM
11585
11586#else /* not USE_XIM */
11587 dpyinfo->xim = NULL;
11588#endif /* not USE_XIM */
f5d11644
GM
11589}
11590
11591
b9de836c 11592#ifdef HAVE_X11R6_XIM
f5d11644
GM
11593
11594struct xim_inst_t
11595{
11596 struct x_display_info *dpyinfo;
11597 char *resource_name;
11598};
11599
11600/* XIM instantiate callback function, which is called whenever an XIM
11601 server is available. DISPLAY is teh display of the XIM.
11602 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11603 when the callback was registered. */
11604
11605static void
11606xim_instantiate_callback (display, client_data, call_data)
11607 Display *display;
11608 XPointer client_data;
11609 XPointer call_data;
11610{
11611 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11612 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11613
11614 /* We don't support multiple XIM connections. */
11615 if (dpyinfo->xim)
11616 return;
11617
11618 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11619
11620 /* Create XIC for the existing frames on the same display, as long
11621 as they have no XIC. */
11622 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11623 {
11624 Lisp_Object tail, frame;
11625
11626 BLOCK_INPUT;
11627 FOR_EACH_FRAME (tail, frame)
11628 {
11629 struct frame *f = XFRAME (frame);
11630
11631 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11632 if (FRAME_XIC (f) == NULL)
11633 {
11634 create_frame_xic (f);
11635 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11636 xic_set_statusarea (f);
11637 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11638 {
11639 struct window *w = XWINDOW (f->selected_window);
11640 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11641 }
11642 }
11643 }
11644
11645 UNBLOCK_INPUT;
11646 }
11647}
11648
b9de836c 11649#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11650
11651
11652/* Open a connection to the XIM server on display DPYINFO.
11653 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11654 connection only at the first time. On X11R6, open the connection
11655 in the XIM instantiate callback function. */
11656
11657static void
11658xim_initialize (dpyinfo, resource_name)
11659 struct x_display_info *dpyinfo;
11660 char *resource_name;
11661{
287f7dd6 11662#ifdef USE_XIM
b9de836c 11663#ifdef HAVE_X11R6_XIM
f5d11644
GM
11664 struct xim_inst_t *xim_inst;
11665 int len;
11666
11667 dpyinfo->xim = NULL;
11668 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11669 xim_inst->dpyinfo = dpyinfo;
11670 len = strlen (resource_name);
11671 xim_inst->resource_name = (char *) xmalloc (len + 1);
11672 bcopy (resource_name, xim_inst->resource_name, len + 1);
11673 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11674 resource_name, EMACS_CLASS,
11675 xim_instantiate_callback,
2ebb2f8b
DL
11676 /* Fixme: This is XPointer in
11677 XFree86 but (XPointer *) on
11678 Tru64, at least. */
11679 (XPointer) xim_inst);
b9de836c 11680#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11681 dpyinfo->xim = NULL;
11682 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11683#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11684
11685#else /* not USE_XIM */
11686 dpyinfo->xim = NULL;
11687#endif /* not USE_XIM */
f5d11644
GM
11688}
11689
11690
11691/* Close the connection to the XIM server on display DPYINFO. */
11692
11693static void
11694xim_close_dpy (dpyinfo)
11695 struct x_display_info *dpyinfo;
11696{
287f7dd6 11697#ifdef USE_XIM
b9de836c 11698#ifdef HAVE_X11R6_XIM
8a4f36cc
GM
11699 if (dpyinfo->display)
11700 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11701 NULL, EMACS_CLASS,
11702 xim_instantiate_callback, NULL);
b9de836c 11703#endif /* not HAVE_X11R6_XIM */
8a4f36cc
GM
11704 if (dpyinfo->display)
11705 XCloseIM (dpyinfo->xim);
f5d11644
GM
11706 dpyinfo->xim = NULL;
11707 XFree (dpyinfo->xim_styles);
287f7dd6 11708#endif /* USE_XIM */
f5d11644
GM
11709}
11710
b9de836c 11711#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11712
11713
dc6f92b8 11714\f
2e365682
RS
11715/* Calculate the absolute position in frame F
11716 from its current recorded position values and gravity. */
11717
dfcf069d 11718void
43bca5d5 11719x_calc_absolute_position (f)
f676886a 11720 struct frame *f;
dc6f92b8 11721{
06a2c219 11722 Window child;
6dba1858 11723 int win_x = 0, win_y = 0;
7556890b 11724 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11725 int this_window;
11726
9829ddba
RS
11727 /* We have nothing to do if the current position
11728 is already for the top-left corner. */
11729 if (! ((flags & XNegative) || (flags & YNegative)))
11730 return;
11731
c81412a0 11732#ifdef USE_X_TOOLKIT
7556890b 11733 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11734#else
11735 this_window = FRAME_X_WINDOW (f);
11736#endif
6dba1858
RS
11737
11738 /* Find the position of the outside upper-left corner of
9829ddba
RS
11739 the inner window, with respect to the outer window.
11740 But do this only if we will need the results. */
7556890b 11741 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11742 {
9829ddba
RS
11743 int count;
11744
6dba1858 11745 BLOCK_INPUT;
9829ddba
RS
11746 count = x_catch_errors (FRAME_X_DISPLAY (f));
11747 while (1)
11748 {
11749 x_clear_errors (FRAME_X_DISPLAY (f));
11750 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11751
11752 /* From-window, to-window. */
11753 this_window,
11754 f->output_data.x->parent_desc,
11755
11756 /* From-position, to-position. */
11757 0, 0, &win_x, &win_y,
11758
11759 /* Child of win. */
11760 &child);
11761 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11762 {
11763 Window newroot, newparent = 0xdeadbeef;
11764 Window *newchildren;
2ebb2f8b 11765 unsigned int nchildren;
9829ddba
RS
11766
11767 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11768 &newparent, &newchildren, &nchildren))
11769 break;
58769bee 11770
7c3c78a3 11771 XFree ((char *) newchildren);
6dba1858 11772
9829ddba
RS
11773 f->output_data.x->parent_desc = newparent;
11774 }
11775 else
11776 break;
11777 }
6dba1858 11778
9829ddba 11779 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11780 UNBLOCK_INPUT;
11781 }
11782
11783 /* Treat negative positions as relative to the leftmost bottommost
11784 position that fits on the screen. */
20f55f9a 11785 if (flags & XNegative)
7556890b 11786 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11787 - 2 * f->output_data.x->border_width - win_x
11788 - PIXEL_WIDTH (f)
11789 + f->output_data.x->left_pos);
dc6f92b8 11790
7708ced0
GM
11791 {
11792 int height = PIXEL_HEIGHT (f);
06a2c219 11793
7708ced0
GM
11794#if defined USE_X_TOOLKIT && defined USE_MOTIF
11795 /* Something is fishy here. When using Motif, starting Emacs with
11796 `-g -0-0', the frame appears too low by a few pixels.
11797
11798 This seems to be so because initially, while Emacs is starting,
11799 the column widget's height and the frame's pixel height are
11800 different. The column widget's height is the right one. In
11801 later invocations, when Emacs is up, the frame's pixel height
11802 is right, though.
11803
11804 It's not obvious where the initial small difference comes from.
11805 2000-12-01, gerd. */
11806
11807 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
06a2c219 11808#endif
2e365682 11809
7708ced0
GM
11810 if (flags & YNegative)
11811 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11812 - 2 * f->output_data.x->border_width
11813 - win_y
11814 - height
11815 + f->output_data.x->top_pos);
11816 }
11817
3a35ab44
RS
11818 /* The left_pos and top_pos
11819 are now relative to the top and left screen edges,
11820 so the flags should correspond. */
7556890b 11821 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11822}
11823
3a35ab44
RS
11824/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11825 to really change the position, and 0 when calling from
11826 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11827 position values). It is -1 when calling from x_set_frame_parameters,
11828 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11829
dfcf069d 11830void
dc05a16b 11831x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11832 struct frame *f;
dc6f92b8 11833 register int xoff, yoff;
dc05a16b 11834 int change_gravity;
dc6f92b8 11835{
4a4cbdd5
KH
11836 int modified_top, modified_left;
11837
aa3ff7c9 11838 if (change_gravity > 0)
3a35ab44 11839 {
7556890b
RS
11840 f->output_data.x->top_pos = yoff;
11841 f->output_data.x->left_pos = xoff;
11842 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11843 if (xoff < 0)
7556890b 11844 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11845 if (yoff < 0)
7556890b
RS
11846 f->output_data.x->size_hint_flags |= YNegative;
11847 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11848 }
43bca5d5 11849 x_calc_absolute_position (f);
dc6f92b8
JB
11850
11851 BLOCK_INPUT;
c32cdd9a 11852 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11853
7556890b
RS
11854 modified_left = f->output_data.x->left_pos;
11855 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11856#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11857 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11858 /* It is a mystery why we need to add the border_width here
11859 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11860 if (change_gravity != 0)
4a4cbdd5 11861 {
7556890b
RS
11862 modified_left += f->output_data.x->border_width;
11863 modified_top += f->output_data.x->border_width;
4a4cbdd5 11864 }
e73ec6fa 11865#endif
4a4cbdd5 11866
3afe33e7 11867#ifdef USE_X_TOOLKIT
7556890b 11868 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11869 modified_left, modified_top);
3afe33e7 11870#else /* not USE_X_TOOLKIT */
334208b7 11871 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11872 modified_left, modified_top);
3afe33e7 11873#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11874 UNBLOCK_INPUT;
11875}
11876
dc6f92b8 11877
499b1844
GM
11878/* Change the size of frame F's X window to COLS/ROWS in the case F
11879 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
11880 top-left-corner window gravity for this size change and subsequent
11881 size changes. Otherwise we leave the window gravity unchanged. */
11882
11883static void
11884x_set_window_size_1 (f, change_gravity, cols, rows)
f676886a 11885 struct frame *f;
bc20ebbf 11886 int change_gravity;
b1c884c3 11887 int cols, rows;
dc6f92b8
JB
11888{
11889 int pixelwidth, pixelheight;
80fd1fe2 11890
b1c884c3 11891 check_frame_size (f, &rows, &cols);
7556890b 11892 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11893 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11894 ? 0
11895 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11896 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11897 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11898 f->output_data.x->flags_areas_extra
110859fc 11899 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11900 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11901 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11902
7556890b 11903 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11904 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11905
334208b7
RS
11906 XSync (FRAME_X_DISPLAY (f), False);
11907 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11908 pixelwidth, pixelheight);
b1c884c3
JB
11909
11910 /* Now, strictly speaking, we can't be sure that this is accurate,
11911 but the window manager will get around to dealing with the size
11912 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11913 ConfigureNotify event gets here.
11914
11915 We could just not bother storing any of this information here,
11916 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11917 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11918 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11919 point in the future when the ConfigureNotify event arrives.
11920
11921 We pass 1 for DELAY since we can't run Lisp code inside of
11922 a BLOCK_INPUT. */
7d1e984f 11923 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11924 PIXEL_WIDTH (f) = pixelwidth;
11925 PIXEL_HEIGHT (f) = pixelheight;
11926
aee9a898
RS
11927 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11928 receive in the ConfigureNotify event; if we get what we asked
11929 for, then the event won't cause the screen to become garbaged, so
11930 we have to make sure to do it here. */
11931 SET_FRAME_GARBAGED (f);
11932
11933 XFlush (FRAME_X_DISPLAY (f));
499b1844
GM
11934}
11935
11936
11937/* Call this to change the size of frame F's x-window.
11938 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11939 for this size change and subsequent size changes.
11940 Otherwise we leave the window gravity unchanged. */
aee9a898 11941
499b1844
GM
11942void
11943x_set_window_size (f, change_gravity, cols, rows)
11944 struct frame *f;
11945 int change_gravity;
11946 int cols, rows;
11947{
11948 BLOCK_INPUT;
11949
11950#ifdef USE_X_TOOLKIT
11951
11952 if (f->output_data.x->widget != None)
11953 {
11954 /* The x and y position of the widget is clobbered by the
11955 call to XtSetValues within EmacsFrameSetCharSize.
11956 This is a real kludge, but I don't understand Xt so I can't
11957 figure out a correct fix. Can anyone else tell me? -- rms. */
11958 int xpos = f->output_data.x->widget->core.x;
11959 int ypos = f->output_data.x->widget->core.y;
11960 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11961 f->output_data.x->widget->core.x = xpos;
11962 f->output_data.x->widget->core.y = ypos;
11963 }
11964 else
11965 x_set_window_size_1 (f, change_gravity, cols, rows);
11966
11967#else /* not USE_X_TOOLKIT */
11968
11969 x_set_window_size_1 (f, change_gravity, cols, rows);
11970
aee9a898
RS
11971#endif /* not USE_X_TOOLKIT */
11972
4d73d038 11973 /* If cursor was outside the new size, mark it as off. */
06a2c219 11974 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11975
aee9a898
RS
11976 /* Clear out any recollection of where the mouse highlighting was,
11977 since it might be in a place that's outside the new frame size.
11978 Actually checking whether it is outside is a pain in the neck,
11979 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11980 cancel_mouse_face (f);
dbc4e1c1 11981
dc6f92b8
JB
11982 UNBLOCK_INPUT;
11983}
dc6f92b8 11984\f
d047c4eb 11985/* Mouse warping. */
dc6f92b8 11986
9b378208 11987void
f676886a
JB
11988x_set_mouse_position (f, x, y)
11989 struct frame *f;
dc6f92b8
JB
11990 int x, y;
11991{
11992 int pix_x, pix_y;
11993
7556890b
RS
11994 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11995 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11996
11997 if (pix_x < 0) pix_x = 0;
11998 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11999
12000 if (pix_y < 0) pix_y = 0;
12001 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
12002
12003 BLOCK_INPUT;
dc6f92b8 12004
334208b7
RS
12005 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12006 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
12007 UNBLOCK_INPUT;
12008}
12009
9b378208
RS
12010/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12011
12012void
12013x_set_mouse_pixel_position (f, pix_x, pix_y)
12014 struct frame *f;
12015 int pix_x, pix_y;
12016{
12017 BLOCK_INPUT;
12018
334208b7
RS
12019 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12020 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
12021 UNBLOCK_INPUT;
12022}
d047c4eb
KH
12023\f
12024/* focus shifting, raising and lowering. */
9b378208 12025
dfcf069d 12026void
f676886a
JB
12027x_focus_on_frame (f)
12028 struct frame *f;
dc6f92b8 12029{
1fb20991 12030#if 0 /* This proves to be unpleasant. */
f676886a 12031 x_raise_frame (f);
1fb20991 12032#endif
6d4238f3
JB
12033#if 0
12034 /* I don't think that the ICCCM allows programs to do things like this
12035 without the interaction of the window manager. Whatever you end up
f676886a 12036 doing with this code, do it to x_unfocus_frame too. */
334208b7 12037 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 12038 RevertToPointerRoot, CurrentTime);
c118dd06 12039#endif /* ! 0 */
dc6f92b8
JB
12040}
12041
dfcf069d 12042void
f676886a
JB
12043x_unfocus_frame (f)
12044 struct frame *f;
dc6f92b8 12045{
6d4238f3 12046#if 0
f676886a 12047 /* Look at the remarks in x_focus_on_frame. */
0f941935 12048 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 12049 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 12050 RevertToPointerRoot, CurrentTime);
c118dd06 12051#endif /* ! 0 */
dc6f92b8
JB
12052}
12053
f676886a 12054/* Raise frame F. */
dc6f92b8 12055
dfcf069d 12056void
f676886a
JB
12057x_raise_frame (f)
12058 struct frame *f;
dc6f92b8 12059{
3a88c238 12060 if (f->async_visible)
dc6f92b8
JB
12061 {
12062 BLOCK_INPUT;
3afe33e7 12063#ifdef USE_X_TOOLKIT
7556890b 12064 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12065#else /* not USE_X_TOOLKIT */
334208b7 12066 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12067#endif /* not USE_X_TOOLKIT */
334208b7 12068 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12069 UNBLOCK_INPUT;
12070 }
12071}
12072
f676886a 12073/* Lower frame F. */
dc6f92b8 12074
dfcf069d 12075void
f676886a
JB
12076x_lower_frame (f)
12077 struct frame *f;
dc6f92b8 12078{
3a88c238 12079 if (f->async_visible)
dc6f92b8
JB
12080 {
12081 BLOCK_INPUT;
3afe33e7 12082#ifdef USE_X_TOOLKIT
7556890b 12083 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12084#else /* not USE_X_TOOLKIT */
334208b7 12085 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12086#endif /* not USE_X_TOOLKIT */
334208b7 12087 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12088 UNBLOCK_INPUT;
12089 }
12090}
12091
dbc4e1c1 12092static void
6b0442dc 12093XTframe_raise_lower (f, raise_flag)
dbc4e1c1 12094 FRAME_PTR f;
6b0442dc 12095 int raise_flag;
dbc4e1c1 12096{
6b0442dc 12097 if (raise_flag)
dbc4e1c1
JB
12098 x_raise_frame (f);
12099 else
12100 x_lower_frame (f);
12101}
d047c4eb
KH
12102\f
12103/* Change of visibility. */
dc6f92b8 12104
9382638d
KH
12105/* This tries to wait until the frame is really visible.
12106 However, if the window manager asks the user where to position
12107 the frame, this will return before the user finishes doing that.
12108 The frame will not actually be visible at that time,
12109 but it will become visible later when the window manager
12110 finishes with it. */
12111
dfcf069d 12112void
f676886a
JB
12113x_make_frame_visible (f)
12114 struct frame *f;
dc6f92b8 12115{
990ba854 12116 Lisp_Object type;
1aa6072f 12117 int original_top, original_left;
31be9251
GM
12118 int retry_count = 2;
12119
12120 retry:
dc6f92b8 12121
dc6f92b8 12122 BLOCK_INPUT;
dc6f92b8 12123
990ba854
RS
12124 type = x_icon_type (f);
12125 if (!NILP (type))
12126 x_bitmap_icon (f, type);
bdcd49ba 12127
f676886a 12128 if (! FRAME_VISIBLE_P (f))
90e65f07 12129 {
1aa6072f
RS
12130 /* We test FRAME_GARBAGED_P here to make sure we don't
12131 call x_set_offset a second time
12132 if we get to x_make_frame_visible a second time
12133 before the window gets really visible. */
12134 if (! FRAME_ICONIFIED_P (f)
12135 && ! f->output_data.x->asked_for_visible)
12136 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12137
12138 f->output_data.x->asked_for_visible = 1;
12139
90e65f07 12140 if (! EQ (Vx_no_window_manager, Qt))
f676886a 12141 x_wm_set_window_state (f, NormalState);
3afe33e7 12142#ifdef USE_X_TOOLKIT
d7a38a2e 12143 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12144 XtMapWidget (f->output_data.x->widget);
3afe33e7 12145#else /* not USE_X_TOOLKIT */
7f9c7f94 12146 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12147#endif /* not USE_X_TOOLKIT */
0134a210
RS
12148#if 0 /* This seems to bring back scroll bars in the wrong places
12149 if the window configuration has changed. They seem
12150 to come back ok without this. */
ab648270 12151 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 12152 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 12153#endif
90e65f07 12154 }
dc6f92b8 12155
334208b7 12156 XFlush (FRAME_X_DISPLAY (f));
90e65f07 12157
0dacf791
RS
12158 /* Synchronize to ensure Emacs knows the frame is visible
12159 before we do anything else. We do this loop with input not blocked
12160 so that incoming events are handled. */
12161 {
12162 Lisp_Object frame;
12ce2351 12163 int count;
28c01ffe
RS
12164 /* This must be before UNBLOCK_INPUT
12165 since events that arrive in response to the actions above
12166 will set it when they are handled. */
12167 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
12168
12169 original_left = f->output_data.x->left_pos;
12170 original_top = f->output_data.x->top_pos;
c0a04927
RS
12171
12172 /* This must come after we set COUNT. */
12173 UNBLOCK_INPUT;
12174
2745e6c4 12175 /* We unblock here so that arriving X events are processed. */
1aa6072f 12176
dcb07ae9
RS
12177 /* Now move the window back to where it was "supposed to be".
12178 But don't do it if the gravity is negative.
12179 When the gravity is negative, this uses a position
28c01ffe
RS
12180 that is 3 pixels too low. Perhaps that's really the border width.
12181
12182 Don't do this if the window has never been visible before,
12183 because the window manager may choose the position
12184 and we don't want to override it. */
1aa6072f 12185
4d3f5d9a 12186 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 12187 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 12188 && previously_visible)
1aa6072f 12189 {
2745e6c4
RS
12190 Drawable rootw;
12191 int x, y;
12192 unsigned int width, height, border, depth;
06a2c219 12193
1aa6072f 12194 BLOCK_INPUT;
9829ddba 12195
06a2c219
GM
12196 /* On some window managers (such as FVWM) moving an existing
12197 window, even to the same place, causes the window manager
12198 to introduce an offset. This can cause the window to move
12199 to an unexpected location. Check the geometry (a little
12200 slow here) and then verify that the window is in the right
12201 place. If the window is not in the right place, move it
12202 there, and take the potential window manager hit. */
2745e6c4
RS
12203 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12204 &rootw, &x, &y, &width, &height, &border, &depth);
12205
12206 if (original_left != x || original_top != y)
12207 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12208 original_left, original_top);
12209
1aa6072f
RS
12210 UNBLOCK_INPUT;
12211 }
9829ddba 12212
e0c1aef2 12213 XSETFRAME (frame, f);
c0a04927 12214
12ce2351
GM
12215 /* Wait until the frame is visible. Process X events until a
12216 MapNotify event has been seen, or until we think we won't get a
12217 MapNotify at all.. */
12218 for (count = input_signal_count + 10;
12219 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 12220 {
12ce2351 12221 /* Force processing of queued events. */
334208b7 12222 x_sync (f);
12ce2351
GM
12223
12224 /* Machines that do polling rather than SIGIO have been
12225 observed to go into a busy-wait here. So we'll fake an
12226 alarm signal to let the handler know that there's something
12227 to be read. We used to raise a real alarm, but it seems
12228 that the handler isn't always enabled here. This is
12229 probably a bug. */
8b2f8d4e 12230 if (input_polling_used ())
3b2fa4e6 12231 {
12ce2351
GM
12232 /* It could be confusing if a real alarm arrives while
12233 processing the fake one. Turn it off and let the
12234 handler reset it. */
3e71d8f2 12235 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
12236 int old_poll_suppress_count = poll_suppress_count;
12237 poll_suppress_count = 1;
12238 poll_for_input_1 ();
12239 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 12240 }
12ce2351
GM
12241
12242 /* See if a MapNotify event has been processed. */
12243 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 12244 }
31be9251
GM
12245
12246 /* 2000-09-28: In
12247
12248 (let ((f (selected-frame)))
12249 (iconify-frame f)
12250 (raise-frame f))
12251
12252 the frame is not raised with various window managers on
12253 FreeBSD, Linux and Solaris. It turns out that, for some
12254 unknown reason, the call to XtMapWidget is completely ignored.
12255 Mapping the widget a second time works. */
12256
12257 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12258 goto retry;
0dacf791 12259 }
dc6f92b8
JB
12260}
12261
06a2c219 12262/* Change from mapped state to withdrawn state. */
dc6f92b8 12263
d047c4eb
KH
12264/* Make the frame visible (mapped and not iconified). */
12265
dfcf069d 12266void
f676886a
JB
12267x_make_frame_invisible (f)
12268 struct frame *f;
dc6f92b8 12269{
546e6d5b
RS
12270 Window window;
12271
12272#ifdef USE_X_TOOLKIT
12273 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 12274 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
12275#else /* not USE_X_TOOLKIT */
12276 window = FRAME_X_WINDOW (f);
12277#endif /* not USE_X_TOOLKIT */
dc6f92b8 12278
9319ae23 12279 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12280 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12281 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12282
5627c40e 12283#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 12284 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 12285 return;
5627c40e 12286#endif
dc6f92b8
JB
12287
12288 BLOCK_INPUT;
c118dd06 12289
af31d76f
RS
12290 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12291 that the current position of the window is user-specified, rather than
12292 program-specified, so that when the window is mapped again, it will be
12293 placed at the same location, without forcing the user to position it
12294 by hand again (they have already done that once for this window.) */
c32cdd9a 12295 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 12296
c118dd06
JB
12297#ifdef HAVE_X11R4
12298
334208b7
RS
12299 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12300 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
12301 {
12302 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12303 error ("Can't notify window manager of window withdrawal");
c118dd06 12304 }
c118dd06 12305#else /* ! defined (HAVE_X11R4) */
16bd92ea 12306
c118dd06 12307 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
12308 if (! EQ (Vx_no_window_manager, Qt))
12309 {
16bd92ea 12310 XEvent unmap;
dc6f92b8 12311
16bd92ea 12312 unmap.xunmap.type = UnmapNotify;
546e6d5b 12313 unmap.xunmap.window = window;
334208b7 12314 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 12315 unmap.xunmap.from_configure = False;
334208b7
RS
12316 if (! XSendEvent (FRAME_X_DISPLAY (f),
12317 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 12318 False,
06a2c219 12319 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
12320 &unmap))
12321 {
12322 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12323 error ("Can't notify window manager of withdrawal");
16bd92ea 12324 }
dc6f92b8
JB
12325 }
12326
16bd92ea 12327 /* Unmap the window ourselves. Cheeky! */
334208b7 12328 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 12329#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 12330
5627c40e
RS
12331 /* We can't distinguish this from iconification
12332 just by the event that we get from the server.
12333 So we can't win using the usual strategy of letting
12334 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12335 and synchronize with the server to make sure we agree. */
12336 f->visible = 0;
12337 FRAME_ICONIFIED_P (f) = 0;
12338 f->async_visible = 0;
12339 f->async_iconified = 0;
12340
334208b7 12341 x_sync (f);
5627c40e 12342
dc6f92b8
JB
12343 UNBLOCK_INPUT;
12344}
12345
06a2c219 12346/* Change window state from mapped to iconified. */
dc6f92b8 12347
dfcf069d 12348void
f676886a
JB
12349x_iconify_frame (f)
12350 struct frame *f;
dc6f92b8 12351{
3afe33e7 12352 int result;
990ba854 12353 Lisp_Object type;
dc6f92b8 12354
9319ae23 12355 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12356 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12357 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12358
3a88c238 12359 if (f->async_iconified)
dc6f92b8
JB
12360 return;
12361
3afe33e7 12362 BLOCK_INPUT;
546e6d5b 12363
9af3143a
RS
12364 FRAME_SAMPLE_VISIBILITY (f);
12365
990ba854
RS
12366 type = x_icon_type (f);
12367 if (!NILP (type))
12368 x_bitmap_icon (f, type);
bdcd49ba
RS
12369
12370#ifdef USE_X_TOOLKIT
12371
546e6d5b
RS
12372 if (! FRAME_VISIBLE_P (f))
12373 {
12374 if (! EQ (Vx_no_window_manager, Qt))
12375 x_wm_set_window_state (f, IconicState);
12376 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12377 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
12378 /* The server won't give us any event to indicate
12379 that an invisible frame was changed to an icon,
12380 so we have to record it here. */
12381 f->iconified = 1;
1e6bc770 12382 f->visible = 1;
9cf30a30 12383 f->async_iconified = 1;
1e6bc770 12384 f->async_visible = 0;
546e6d5b
RS
12385 UNBLOCK_INPUT;
12386 return;
12387 }
12388
334208b7 12389 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 12390 XtWindow (f->output_data.x->widget),
334208b7 12391 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
12392 UNBLOCK_INPUT;
12393
12394 if (!result)
546e6d5b 12395 error ("Can't notify window manager of iconification");
3afe33e7
RS
12396
12397 f->async_iconified = 1;
1e6bc770
RS
12398 f->async_visible = 0;
12399
8c002a25
KH
12400
12401 BLOCK_INPUT;
334208b7 12402 XFlush (FRAME_X_DISPLAY (f));
8c002a25 12403 UNBLOCK_INPUT;
3afe33e7
RS
12404#else /* not USE_X_TOOLKIT */
12405
fd13dbb2
RS
12406 /* Make sure the X server knows where the window should be positioned,
12407 in case the user deiconifies with the window manager. */
12408 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 12409 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 12410
16bd92ea
JB
12411 /* Since we don't know which revision of X we're running, we'll use both
12412 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12413
12414 /* X11R4: send a ClientMessage to the window manager using the
12415 WM_CHANGE_STATE type. */
12416 {
12417 XEvent message;
58769bee 12418
c118dd06 12419 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 12420 message.xclient.type = ClientMessage;
334208b7 12421 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
12422 message.xclient.format = 32;
12423 message.xclient.data.l[0] = IconicState;
12424
334208b7
RS
12425 if (! XSendEvent (FRAME_X_DISPLAY (f),
12426 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
12427 False,
12428 SubstructureRedirectMask | SubstructureNotifyMask,
12429 &message))
dc6f92b8
JB
12430 {
12431 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12432 error ("Can't notify window manager of iconification");
dc6f92b8 12433 }
16bd92ea 12434 }
dc6f92b8 12435
58769bee 12436 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
12437 IconicState. */
12438 x_wm_set_window_state (f, IconicState);
dc6f92b8 12439
a9c00105
RS
12440 if (!FRAME_VISIBLE_P (f))
12441 {
12442 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 12443 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
12444 }
12445
3a88c238 12446 f->async_iconified = 1;
1e6bc770 12447 f->async_visible = 0;
dc6f92b8 12448
334208b7 12449 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 12450 UNBLOCK_INPUT;
8c002a25 12451#endif /* not USE_X_TOOLKIT */
dc6f92b8 12452}
19f71add 12453
d047c4eb 12454\f
19f71add 12455/* Free X resources of frame F. */
dc6f92b8 12456
dfcf069d 12457void
19f71add 12458x_free_frame_resources (f)
f676886a 12459 struct frame *f;
dc6f92b8 12460{
7f9c7f94
RS
12461 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12462
dc6f92b8 12463 BLOCK_INPUT;
c0ff3fab 12464
6186a4a0
RS
12465 /* If a display connection is dead, don't try sending more
12466 commands to the X server. */
19f71add 12467 if (dpyinfo->display)
6186a4a0 12468 {
19f71add 12469 if (f->output_data.x->icon_desc)
6186a4a0 12470 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
19f71add 12471
31f41daf 12472#ifdef HAVE_X_I18N
f5d11644
GM
12473 if (FRAME_XIC (f))
12474 free_frame_xic (f);
31f41daf 12475#endif
19f71add 12476
2662734b 12477 if (FRAME_X_WINDOW (f))
19f71add
GM
12478 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12479
3afe33e7 12480#ifdef USE_X_TOOLKIT
06a2c219
GM
12481 if (f->output_data.x->widget)
12482 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12483 free_frame_menubar (f);
3afe33e7
RS
12484#endif /* USE_X_TOOLKIT */
12485
3e71d8f2
GM
12486 unload_color (f, f->output_data.x->foreground_pixel);
12487 unload_color (f, f->output_data.x->background_pixel);
12488 unload_color (f, f->output_data.x->cursor_pixel);
12489 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12490 unload_color (f, f->output_data.x->border_pixel);
12491 unload_color (f, f->output_data.x->mouse_pixel);
19f71add 12492
3e71d8f2
GM
12493 if (f->output_data.x->scroll_bar_background_pixel != -1)
12494 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12495 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12496 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12497 if (f->output_data.x->white_relief.allocated_p)
12498 unload_color (f, f->output_data.x->white_relief.pixel);
12499 if (f->output_data.x->black_relief.allocated_p)
12500 unload_color (f, f->output_data.x->black_relief.pixel);
4ca78676 12501
19f71add
GM
12502 if (FRAME_FACE_CACHE (f))
12503 free_frame_faces (f);
12504
4ca78676 12505 x_free_gcs (f);
6186a4a0
RS
12506 XFlush (FRAME_X_DISPLAY (f));
12507 }
dc6f92b8 12508
df89d8a4 12509 if (f->output_data.x->saved_menu_event)
06a2c219 12510 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12511
7556890b 12512 xfree (f->output_data.x);
19f71add
GM
12513 f->output_data.x = NULL;
12514
0f941935
KH
12515 if (f == dpyinfo->x_focus_frame)
12516 dpyinfo->x_focus_frame = 0;
12517 if (f == dpyinfo->x_focus_event_frame)
12518 dpyinfo->x_focus_event_frame = 0;
12519 if (f == dpyinfo->x_highlight_frame)
12520 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12521
7f9c7f94 12522 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12523 {
7f9c7f94
RS
12524 dpyinfo->mouse_face_beg_row
12525 = dpyinfo->mouse_face_beg_col = -1;
12526 dpyinfo->mouse_face_end_row
12527 = dpyinfo->mouse_face_end_col = -1;
12528 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12529 dpyinfo->mouse_face_deferred_gc = 0;
12530 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12531 }
0134a210 12532
c0ff3fab 12533 UNBLOCK_INPUT;
dc6f92b8 12534}
19f71add
GM
12535
12536
12537/* Destroy the X window of frame F. */
12538
12539void
12540x_destroy_window (f)
12541 struct frame *f;
12542{
12543 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12544
12545 /* If a display connection is dead, don't try sending more
12546 commands to the X server. */
12547 if (dpyinfo->display != 0)
12548 x_free_frame_resources (f);
12549
12550 dpyinfo->reference_count--;
12551}
12552
dc6f92b8 12553\f
f451eb13
JB
12554/* Setting window manager hints. */
12555
af31d76f
RS
12556/* Set the normal size hints for the window manager, for frame F.
12557 FLAGS is the flags word to use--or 0 meaning preserve the flags
12558 that the window now has.
12559 If USER_POSITION is nonzero, we set the USPosition
12560 flag (this is useful when FLAGS is 0). */
6dba1858 12561
dfcf069d 12562void
af31d76f 12563x_wm_set_size_hint (f, flags, user_position)
f676886a 12564 struct frame *f;
af31d76f
RS
12565 long flags;
12566 int user_position;
dc6f92b8
JB
12567{
12568 XSizeHints size_hints;
3afe33e7
RS
12569
12570#ifdef USE_X_TOOLKIT
7e4f2521
FP
12571 Arg al[2];
12572 int ac = 0;
12573 Dimension widget_width, widget_height;
7556890b 12574 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12575#else /* not USE_X_TOOLKIT */
c118dd06 12576 Window window = FRAME_X_WINDOW (f);
3afe33e7 12577#endif /* not USE_X_TOOLKIT */
dc6f92b8 12578
b72a58fd
RS
12579 /* Setting PMaxSize caused various problems. */
12580 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12581
7556890b
RS
12582 size_hints.x = f->output_data.x->left_pos;
12583 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12584
7e4f2521
FP
12585#ifdef USE_X_TOOLKIT
12586 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12587 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12588 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12589 size_hints.height = widget_height;
12590 size_hints.width = widget_width;
12591#else /* not USE_X_TOOLKIT */
f676886a
JB
12592 size_hints.height = PIXEL_HEIGHT (f);
12593 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12594#endif /* not USE_X_TOOLKIT */
7553a6b7 12595
7556890b
RS
12596 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12597 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12598 size_hints.max_width
12599 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12600 size_hints.max_height
12601 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12602
d067ea8b
KH
12603 /* Calculate the base and minimum sizes.
12604
12605 (When we use the X toolkit, we don't do it here.
12606 Instead we copy the values that the widgets are using, below.) */
12607#ifndef USE_X_TOOLKIT
b1c884c3 12608 {
b0342f17 12609 int base_width, base_height;
0134a210 12610 int min_rows = 0, min_cols = 0;
b0342f17 12611
f451eb13
JB
12612 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12613 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12614
0134a210 12615 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12616
0134a210
RS
12617 /* The window manager uses the base width hints to calculate the
12618 current number of rows and columns in the frame while
12619 resizing; min_width and min_height aren't useful for this
12620 purpose, since they might not give the dimensions for a
12621 zero-row, zero-column frame.
58769bee 12622
0134a210
RS
12623 We use the base_width and base_height members if we have
12624 them; otherwise, we set the min_width and min_height members
12625 to the size for a zero x zero frame. */
b0342f17
JB
12626
12627#ifdef HAVE_X11R4
0134a210
RS
12628 size_hints.flags |= PBaseSize;
12629 size_hints.base_width = base_width;
12630 size_hints.base_height = base_height;
12631 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12632 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12633#else
0134a210
RS
12634 size_hints.min_width = base_width;
12635 size_hints.min_height = base_height;
b0342f17 12636#endif
b1c884c3 12637 }
dc6f92b8 12638
d067ea8b 12639 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12640 if (flags)
dc6f92b8 12641 {
d067ea8b
KH
12642 size_hints.flags |= flags;
12643 goto no_read;
12644 }
12645#endif /* not USE_X_TOOLKIT */
12646
12647 {
12648 XSizeHints hints; /* Sometimes I hate X Windows... */
12649 long supplied_return;
12650 int value;
af31d76f
RS
12651
12652#ifdef HAVE_X11R4
d067ea8b
KH
12653 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12654 &supplied_return);
af31d76f 12655#else
d067ea8b 12656 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12657#endif
58769bee 12658
d067ea8b
KH
12659#ifdef USE_X_TOOLKIT
12660 size_hints.base_height = hints.base_height;
12661 size_hints.base_width = hints.base_width;
12662 size_hints.min_height = hints.min_height;
12663 size_hints.min_width = hints.min_width;
12664#endif
12665
12666 if (flags)
12667 size_hints.flags |= flags;
12668 else
12669 {
12670 if (value == 0)
12671 hints.flags = 0;
12672 if (hints.flags & PSize)
12673 size_hints.flags |= PSize;
12674 if (hints.flags & PPosition)
12675 size_hints.flags |= PPosition;
12676 if (hints.flags & USPosition)
12677 size_hints.flags |= USPosition;
12678 if (hints.flags & USSize)
12679 size_hints.flags |= USSize;
12680 }
12681 }
12682
06a2c219 12683#ifndef USE_X_TOOLKIT
d067ea8b 12684 no_read:
06a2c219 12685#endif
0134a210 12686
af31d76f 12687#ifdef PWinGravity
7556890b 12688 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12689 size_hints.flags |= PWinGravity;
dc05a16b 12690
af31d76f 12691 if (user_position)
6dba1858 12692 {
af31d76f
RS
12693 size_hints.flags &= ~ PPosition;
12694 size_hints.flags |= USPosition;
6dba1858 12695 }
2554751d 12696#endif /* PWinGravity */
6dba1858 12697
b0342f17 12698#ifdef HAVE_X11R4
334208b7 12699 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12700#else
334208b7 12701 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12702#endif
dc6f92b8
JB
12703}
12704
12705/* Used for IconicState or NormalState */
06a2c219 12706
dfcf069d 12707void
f676886a
JB
12708x_wm_set_window_state (f, state)
12709 struct frame *f;
dc6f92b8
JB
12710 int state;
12711{
3afe33e7 12712#ifdef USE_X_TOOLKIT
546e6d5b
RS
12713 Arg al[1];
12714
12715 XtSetArg (al[0], XtNinitialState, state);
7556890b 12716 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12717#else /* not USE_X_TOOLKIT */
c118dd06 12718 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12719
7556890b
RS
12720 f->output_data.x->wm_hints.flags |= StateHint;
12721 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12722
7556890b 12723 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12724#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12725}
12726
dfcf069d 12727void
7f2ae036 12728x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12729 struct frame *f;
7f2ae036 12730 int pixmap_id;
dc6f92b8 12731{
d2bd6bc4
RS
12732 Pixmap icon_pixmap;
12733
06a2c219 12734#ifndef USE_X_TOOLKIT
c118dd06 12735 Window window = FRAME_X_WINDOW (f);
75231bad 12736#endif
dc6f92b8 12737
7f2ae036 12738 if (pixmap_id > 0)
dbc4e1c1 12739 {
d2bd6bc4 12740 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12741 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12742 }
12743 else
68568555
RS
12744 {
12745 /* It seems there is no way to turn off use of an icon pixmap.
12746 The following line does it, only if no icon has yet been created,
12747 for some window managers. But with mwm it crashes.
12748 Some people say it should clear the IconPixmapHint bit in this case,
12749 but that doesn't work, and the X consortium said it isn't the
12750 right thing at all. Since there is no way to win,
12751 best to explicitly give up. */
12752#if 0
12753 f->output_data.x->wm_hints.icon_pixmap = None;
12754#else
12755 return;
12756#endif
12757 }
b1c884c3 12758
d2bd6bc4
RS
12759#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12760
12761 {
12762 Arg al[1];
12763 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12764 XtSetValues (f->output_data.x->widget, al, 1);
12765 }
12766
12767#else /* not USE_X_TOOLKIT */
12768
7556890b
RS
12769 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12770 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12771
12772#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12773}
12774
dfcf069d 12775void
f676886a
JB
12776x_wm_set_icon_position (f, icon_x, icon_y)
12777 struct frame *f;
dc6f92b8
JB
12778 int icon_x, icon_y;
12779{
75231bad 12780#ifdef USE_X_TOOLKIT
7556890b 12781 Window window = XtWindow (f->output_data.x->widget);
75231bad 12782#else
c118dd06 12783 Window window = FRAME_X_WINDOW (f);
75231bad 12784#endif
dc6f92b8 12785
7556890b
RS
12786 f->output_data.x->wm_hints.flags |= IconPositionHint;
12787 f->output_data.x->wm_hints.icon_x = icon_x;
12788 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12789
7556890b 12790 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12791}
12792
12793\f
06a2c219
GM
12794/***********************************************************************
12795 Fonts
12796 ***********************************************************************/
dc43ef94
KH
12797
12798/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12799
dc43ef94
KH
12800struct font_info *
12801x_get_font_info (f, font_idx)
12802 FRAME_PTR f;
12803 int font_idx;
12804{
12805 return (FRAME_X_FONT_TABLE (f) + font_idx);
12806}
12807
12808
9c11f79e
GM
12809/* Return a list of names of available fonts matching PATTERN on frame F.
12810
12811 If SIZE is > 0, it is the size (maximum bounds width) of fonts
12812 to be listed.
12813
12814 SIZE < 0 means include scalable fonts.
12815
12816 Frame F null means we have not yet created any frame on X, and
12817 consult the first display in x_display_list. MAXNAMES sets a limit
12818 on how many fonts to match. */
dc43ef94
KH
12819
12820Lisp_Object
12821x_list_fonts (f, pattern, size, maxnames)
9c11f79e 12822 struct frame *f;
dc43ef94
KH
12823 Lisp_Object pattern;
12824 int size;
12825 int maxnames;
12826{
06a2c219
GM
12827 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12828 Lisp_Object tem, second_best;
9c11f79e
GM
12829 struct x_display_info *dpyinfo
12830 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
12831 Display *dpy = dpyinfo->display;
09c6077f 12832 int try_XLoadQueryFont = 0;
53ca4657 12833 int count;
9c11f79e
GM
12834 int allow_scalable_fonts_p = 0;
12835
12836 if (size < 0)
12837 {
12838 allow_scalable_fonts_p = 1;
12839 size = 0;
12840 }
dc43ef94 12841
6b0efe73 12842 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12843 if (NILP (patterns))
12844 patterns = Fcons (pattern, Qnil);
81ba44e5 12845
09c6077f
KH
12846 if (maxnames == 1 && !size)
12847 /* We can return any single font matching PATTERN. */
12848 try_XLoadQueryFont = 1;
9a32686f 12849
8e713be6 12850 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12851 {
dc43ef94 12852 int num_fonts;
3e71d8f2 12853 char **names = NULL;
dc43ef94 12854
8e713be6 12855 pattern = XCAR (patterns);
536f4067
RS
12856 /* See if we cached the result for this particular query.
12857 The cache is an alist of the form:
9c11f79e
GM
12858 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
12859 tem = XCDR (dpyinfo->name_list_element);
12860 key = Fcons (Fcons (pattern, make_number (maxnames)),
12861 allow_scalable_fonts_p ? Qt : Qnil);
12862 list = Fassoc (key, tem);
12863 if (!NILP (list))
b5210ea7
KH
12864 {
12865 list = Fcdr_safe (list);
12866 /* We have a cashed list. Don't have to get the list again. */
12867 goto label_cached;
12868 }
12869
12870 /* At first, put PATTERN in the cache. */
09c6077f 12871
dc43ef94 12872 BLOCK_INPUT;
17d85edc
KH
12873 count = x_catch_errors (dpy);
12874
09c6077f
KH
12875 if (try_XLoadQueryFont)
12876 {
12877 XFontStruct *font;
12878 unsigned long value;
12879
12880 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12881 if (x_had_errors_p (dpy))
12882 {
12883 /* This error is perhaps due to insufficient memory on X
12884 server. Let's just ignore it. */
12885 font = NULL;
12886 x_clear_errors (dpy);
12887 }
12888
09c6077f
KH
12889 if (font
12890 && XGetFontProperty (font, XA_FONT, &value))
12891 {
12892 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12893 int len = strlen (name);
01c752b5 12894 char *tmp;
09c6077f 12895
6f6512e8
KH
12896 /* If DXPC (a Differential X Protocol Compressor)
12897 Ver.3.7 is running, XGetAtomName will return null
12898 string. We must avoid such a name. */
12899 if (len == 0)
12900 try_XLoadQueryFont = 0;
12901 else
12902 {
12903 num_fonts = 1;
12904 names = (char **) alloca (sizeof (char *));
12905 /* Some systems only allow alloca assigned to a
12906 simple var. */
12907 tmp = (char *) alloca (len + 1); names[0] = tmp;
12908 bcopy (name, names[0], len + 1);
12909 XFree (name);
12910 }
09c6077f
KH
12911 }
12912 else
12913 try_XLoadQueryFont = 0;
a083fd23
RS
12914
12915 if (font)
12916 XFreeFont (dpy, font);
09c6077f
KH
12917 }
12918
12919 if (!try_XLoadQueryFont)
17d85edc
KH
12920 {
12921 /* We try at least 10 fonts because XListFonts will return
12922 auto-scaled fonts at the head. */
12923 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12924 &num_fonts);
12925 if (x_had_errors_p (dpy))
12926 {
12927 /* This error is perhaps due to insufficient memory on X
12928 server. Let's just ignore it. */
12929 names = NULL;
12930 x_clear_errors (dpy);
12931 }
12932 }
12933
12934 x_uncatch_errors (dpy, count);
dc43ef94
KH
12935 UNBLOCK_INPUT;
12936
12937 if (names)
12938 {
12939 int i;
dc43ef94
KH
12940
12941 /* Make a list of all the fonts we got back.
12942 Store that in the font cache for the display. */
12943 for (i = 0; i < num_fonts; i++)
12944 {
06a2c219 12945 int width = 0;
dc43ef94 12946 char *p = names[i];
06a2c219
GM
12947 int average_width = -1, dashes = 0;
12948
dc43ef94 12949 /* Count the number of dashes in NAMES[I]. If there are
9c11f79e
GM
12950 14 dashes, and the field value following 12th dash
12951 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12952 is usually too ugly to be used for editing. Let's
12953 ignore it. */
dc43ef94
KH
12954 while (*p)
12955 if (*p++ == '-')
12956 {
12957 dashes++;
12958 if (dashes == 7) /* PIXEL_SIZE field */
12959 width = atoi (p);
12960 else if (dashes == 12) /* AVERAGE_WIDTH field */
12961 average_width = atoi (p);
12962 }
9c11f79e
GM
12963
12964 if (allow_scalable_fonts_p
12965 || dashes < 14 || average_width != 0)
dc43ef94
KH
12966 {
12967 tem = build_string (names[i]);
12968 if (NILP (Fassoc (tem, list)))
12969 {
12970 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12971 && ((fast_c_string_match_ignore_case
12972 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12973 >= 0))
12974 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12975 width of this font. */
dc43ef94
KH
12976 list = Fcons (Fcons (tem, make_number (width)), list);
12977 else
12978 /* For the moment, width is not known. */
12979 list = Fcons (Fcons (tem, Qnil), list);
12980 }
12981 }
12982 }
09c6077f
KH
12983 if (!try_XLoadQueryFont)
12984 XFreeFontNames (names);
dc43ef94
KH
12985 }
12986
b5210ea7 12987 /* Now store the result in the cache. */
9c11f79e
GM
12988 XCDR (dpyinfo->name_list_element)
12989 = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
dc43ef94 12990
b5210ea7
KH
12991 label_cached:
12992 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12993
b5210ea7
KH
12994 newlist = second_best = Qnil;
12995 /* Make a list of the fonts that have the right width. */
8e713be6 12996 for (; CONSP (list); list = XCDR (list))
b5210ea7 12997 {
536f4067
RS
12998 int found_size;
12999
8e713be6 13000 tem = XCAR (list);
dc43ef94 13001
8e713be6 13002 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
13003 continue;
13004 if (!size)
13005 {
8e713be6 13006 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
13007 continue;
13008 }
dc43ef94 13009
8e713be6 13010 if (!INTEGERP (XCDR (tem)))
dc43ef94 13011 {
b5210ea7 13012 /* Since we have not yet known the size of this font, we
9c11f79e 13013 must try slow function call XLoadQueryFont. */
dc43ef94
KH
13014 XFontStruct *thisinfo;
13015
13016 BLOCK_INPUT;
17d85edc 13017 count = x_catch_errors (dpy);
dc43ef94 13018 thisinfo = XLoadQueryFont (dpy,
8e713be6 13019 XSTRING (XCAR (tem))->data);
17d85edc
KH
13020 if (x_had_errors_p (dpy))
13021 {
13022 /* This error is perhaps due to insufficient memory on X
13023 server. Let's just ignore it. */
13024 thisinfo = NULL;
13025 x_clear_errors (dpy);
13026 }
13027 x_uncatch_errors (dpy, count);
dc43ef94
KH
13028 UNBLOCK_INPUT;
13029
13030 if (thisinfo)
13031 {
8e713be6 13032 XCDR (tem)
536f4067
RS
13033 = (thisinfo->min_bounds.width == 0
13034 ? make_number (0)
13035 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
13036 XFreeFont (dpy, thisinfo);
13037 }
13038 else
b5210ea7 13039 /* For unknown reason, the previous call of XListFont had
06a2c219 13040 returned a font which can't be opened. Record the size
b5210ea7 13041 as 0 not to try to open it again. */
8e713be6 13042 XCDR (tem) = make_number (0);
dc43ef94 13043 }
536f4067 13044
8e713be6 13045 found_size = XINT (XCDR (tem));
536f4067 13046 if (found_size == size)
8e713be6 13047 newlist = Fcons (XCAR (tem), newlist);
536f4067 13048 else if (found_size > 0)
b5210ea7 13049 {
536f4067 13050 if (NILP (second_best))
b5210ea7 13051 second_best = tem;
536f4067
RS
13052 else if (found_size < size)
13053 {
8e713be6
KR
13054 if (XINT (XCDR (second_best)) > size
13055 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
13056 second_best = tem;
13057 }
13058 else
13059 {
8e713be6
KR
13060 if (XINT (XCDR (second_best)) > size
13061 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
13062 second_best = tem;
13063 }
b5210ea7
KH
13064 }
13065 }
13066 if (!NILP (newlist))
13067 break;
13068 else if (!NILP (second_best))
13069 {
8e713be6 13070 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 13071 break;
dc43ef94 13072 }
dc43ef94
KH
13073 }
13074
13075 return newlist;
13076}
13077
06a2c219
GM
13078
13079#if GLYPH_DEBUG
13080
13081/* Check that FONT is valid on frame F. It is if it can be found in F's
13082 font table. */
13083
13084static void
13085x_check_font (f, font)
13086 struct frame *f;
13087 XFontStruct *font;
13088{
13089 int i;
13090 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13091
13092 xassert (font != NULL);
13093
13094 for (i = 0; i < dpyinfo->n_fonts; i++)
13095 if (dpyinfo->font_table[i].name
13096 && font == dpyinfo->font_table[i].font)
13097 break;
13098
13099 xassert (i < dpyinfo->n_fonts);
13100}
13101
13102#endif /* GLYPH_DEBUG != 0 */
13103
13104/* Set *W to the minimum width, *H to the minimum font height of FONT.
13105 Note: There are (broken) X fonts out there with invalid XFontStruct
13106 min_bounds contents. For example, handa@etl.go.jp reports that
13107 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13108 have font->min_bounds.width == 0. */
13109
13110static INLINE void
13111x_font_min_bounds (font, w, h)
13112 XFontStruct *font;
13113 int *w, *h;
13114{
13115 *h = FONT_HEIGHT (font);
13116 *w = font->min_bounds.width;
13117
13118 /* Try to handle the case where FONT->min_bounds has invalid
13119 contents. Since the only font known to have invalid min_bounds
13120 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13121 if (*w <= 0)
13122 *w = font->max_bounds.width;
13123}
13124
13125
13126/* Compute the smallest character width and smallest font height over
13127 all fonts available on frame F. Set the members smallest_char_width
13128 and smallest_font_height in F's x_display_info structure to
13129 the values computed. Value is non-zero if smallest_font_height or
13130 smallest_char_width become smaller than they were before. */
13131
13132static int
13133x_compute_min_glyph_bounds (f)
13134 struct frame *f;
13135{
13136 int i;
13137 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13138 XFontStruct *font;
13139 int old_width = dpyinfo->smallest_char_width;
13140 int old_height = dpyinfo->smallest_font_height;
13141
13142 dpyinfo->smallest_font_height = 100000;
13143 dpyinfo->smallest_char_width = 100000;
13144
13145 for (i = 0; i < dpyinfo->n_fonts; ++i)
13146 if (dpyinfo->font_table[i].name)
13147 {
13148 struct font_info *fontp = dpyinfo->font_table + i;
13149 int w, h;
13150
13151 font = (XFontStruct *) fontp->font;
13152 xassert (font != (XFontStruct *) ~0);
13153 x_font_min_bounds (font, &w, &h);
13154
13155 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13156 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13157 }
13158
13159 xassert (dpyinfo->smallest_char_width > 0
13160 && dpyinfo->smallest_font_height > 0);
13161
13162 return (dpyinfo->n_fonts == 1
13163 || dpyinfo->smallest_char_width < old_width
13164 || dpyinfo->smallest_font_height < old_height);
13165}
13166
13167
dc43ef94
KH
13168/* Load font named FONTNAME of the size SIZE for frame F, and return a
13169 pointer to the structure font_info while allocating it dynamically.
13170 If SIZE is 0, load any size of font.
13171 If loading is failed, return NULL. */
13172
13173struct font_info *
13174x_load_font (f, fontname, size)
13175 struct frame *f;
13176 register char *fontname;
13177 int size;
13178{
13179 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13180 Lisp_Object font_names;
d645aaa4 13181 int count;
dc43ef94
KH
13182
13183 /* Get a list of all the fonts that match this name. Once we
13184 have a list of matching fonts, we compare them against the fonts
13185 we already have by comparing names. */
09c6077f 13186 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
13187
13188 if (!NILP (font_names))
13189 {
13190 Lisp_Object tail;
13191 int i;
13192
13193 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 13194 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
13195 if (dpyinfo->font_table[i].name
13196 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 13197 XSTRING (XCAR (tail))->data)
06a2c219 13198 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 13199 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
13200 return (dpyinfo->font_table + i);
13201 }
13202
13203 /* Load the font and add it to the table. */
13204 {
13205 char *full_name;
13206 XFontStruct *font;
13207 struct font_info *fontp;
13208 unsigned long value;
06a2c219 13209 int i;
dc43ef94 13210
2da424f1
KH
13211 /* If we have found fonts by x_list_font, load one of them. If
13212 not, we still try to load a font by the name given as FONTNAME
13213 because XListFonts (called in x_list_font) of some X server has
13214 a bug of not finding a font even if the font surely exists and
13215 is loadable by XLoadQueryFont. */
e1d6d5b9 13216 if (size > 0 && !NILP (font_names))
8e713be6 13217 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
13218
13219 BLOCK_INPUT;
d645aaa4 13220 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 13221 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
13222 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13223 {
13224 /* This error is perhaps due to insufficient memory on X
13225 server. Let's just ignore it. */
13226 font = NULL;
13227 x_clear_errors (FRAME_X_DISPLAY (f));
13228 }
13229 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 13230 UNBLOCK_INPUT;
b5210ea7 13231 if (!font)
dc43ef94
KH
13232 return NULL;
13233
06a2c219
GM
13234 /* Find a free slot in the font table. */
13235 for (i = 0; i < dpyinfo->n_fonts; ++i)
13236 if (dpyinfo->font_table[i].name == NULL)
13237 break;
13238
13239 /* If no free slot found, maybe enlarge the font table. */
13240 if (i == dpyinfo->n_fonts
13241 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 13242 {
06a2c219
GM
13243 int sz;
13244 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13245 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 13246 dpyinfo->font_table
06a2c219 13247 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
13248 }
13249
06a2c219
GM
13250 fontp = dpyinfo->font_table + i;
13251 if (i == dpyinfo->n_fonts)
13252 ++dpyinfo->n_fonts;
dc43ef94
KH
13253
13254 /* Now fill in the slots of *FONTP. */
13255 BLOCK_INPUT;
13256 fontp->font = font;
06a2c219 13257 fontp->font_idx = i;
dc43ef94
KH
13258 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13259 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13260
13261 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13262 full_name = 0;
13263 if (XGetFontProperty (font, XA_FONT, &value))
13264 {
13265 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13266 char *p = name;
13267 int dashes = 0;
13268
13269 /* Count the number of dashes in the "full name".
13270 If it is too few, this isn't really the font's full name,
13271 so don't use it.
13272 In X11R4, the fonts did not come with their canonical names
13273 stored in them. */
13274 while (*p)
13275 {
13276 if (*p == '-')
13277 dashes++;
13278 p++;
13279 }
13280
13281 if (dashes >= 13)
13282 {
13283 full_name = (char *) xmalloc (p - name + 1);
13284 bcopy (name, full_name, p - name + 1);
13285 }
13286
13287 XFree (name);
13288 }
13289
13290 if (full_name != 0)
13291 fontp->full_name = full_name;
13292 else
13293 fontp->full_name = fontp->name;
13294
13295 fontp->size = font->max_bounds.width;
d5749adb 13296 fontp->height = FONT_HEIGHT (font);
dc43ef94 13297
2da424f1
KH
13298 if (NILP (font_names))
13299 {
13300 /* We come here because of a bug of XListFonts mentioned at
13301 the head of this block. Let's store this information in
13302 the cache for x_list_fonts. */
13303 Lisp_Object lispy_name = build_string (fontname);
13304 Lisp_Object lispy_full_name = build_string (fontp->full_name);
9c11f79e
GM
13305 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13306 Qnil);
2da424f1 13307
8e713be6 13308 XCDR (dpyinfo->name_list_element)
9c11f79e 13309 = Fcons (Fcons (key,
2da424f1
KH
13310 Fcons (Fcons (lispy_full_name,
13311 make_number (fontp->size)),
13312 Qnil)),
8e713be6 13313 XCDR (dpyinfo->name_list_element));
2da424f1 13314 if (full_name)
9c11f79e
GM
13315 {
13316 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13317 Qnil);
13318 XCDR (dpyinfo->name_list_element)
13319 = Fcons (Fcons (key,
13320 Fcons (Fcons (lispy_full_name,
13321 make_number (fontp->size)),
13322 Qnil)),
13323 XCDR (dpyinfo->name_list_element));
13324 }
2da424f1
KH
13325 }
13326
dc43ef94
KH
13327 /* The slot `encoding' specifies how to map a character
13328 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
13329 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13330 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 13331 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 13332 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
13333 which is never used by any charset. If mapping can't be
13334 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
13335 fontp->encoding[1]
13336 = (font->max_byte1 == 0
13337 /* 1-byte font */
13338 ? (font->min_char_or_byte2 < 0x80
13339 ? (font->max_char_or_byte2 < 0x80
13340 ? 0 /* 0x20..0x7F */
8ff102bd 13341 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
13342 : 1) /* 0xA0..0xFF */
13343 /* 2-byte font */
13344 : (font->min_byte1 < 0x80
13345 ? (font->max_byte1 < 0x80
13346 ? (font->min_char_or_byte2 < 0x80
13347 ? (font->max_char_or_byte2 < 0x80
13348 ? 0 /* 0x2020..0x7F7F */
8ff102bd 13349 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 13350 : 3) /* 0x20A0..0x7FFF */
8ff102bd 13351 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
13352 : (font->min_char_or_byte2 < 0x80
13353 ? (font->max_char_or_byte2 < 0x80
13354 ? 2 /* 0xA020..0xFF7F */
8ff102bd 13355 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
13356 : 1))); /* 0xA0A0..0xFFFF */
13357
13358 fontp->baseline_offset
13359 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13360 ? (long) value : 0);
13361 fontp->relative_compose
13362 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13363 ? (long) value : 0);
f78798df
KH
13364 fontp->default_ascent
13365 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13366 ? (long) value : 0);
dc43ef94 13367
06a2c219
GM
13368 /* Set global flag fonts_changed_p to non-zero if the font loaded
13369 has a character with a smaller width than any other character
13370 before, or if the font loaded has a smalle>r height than any
13371 other font loaded before. If this happens, it will make a
13372 glyph matrix reallocation necessary. */
13373 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 13374 UNBLOCK_INPUT;
dc43ef94
KH
13375 return fontp;
13376 }
13377}
13378
06a2c219
GM
13379
13380/* Return a pointer to struct font_info of a font named FONTNAME for
13381 frame F. If no such font is loaded, return NULL. */
13382
dc43ef94
KH
13383struct font_info *
13384x_query_font (f, fontname)
13385 struct frame *f;
13386 register char *fontname;
13387{
13388 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13389 int i;
13390
13391 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
13392 if (dpyinfo->font_table[i].name
13393 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13394 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
13395 return (dpyinfo->font_table + i);
13396 return NULL;
13397}
13398
06a2c219
GM
13399
13400/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
13401 `encoder' of the structure. */
13402
13403void
13404x_find_ccl_program (fontp)
13405 struct font_info *fontp;
13406{
a42f54e6 13407 Lisp_Object list, elt;
a6582676 13408
f9b5db02 13409 elt = Qnil;
8e713be6 13410 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 13411 {
8e713be6 13412 elt = XCAR (list);
a6582676 13413 if (CONSP (elt)
8e713be6 13414 && STRINGP (XCAR (elt))
9f2feff6
KH
13415 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13416 >= 0)
13417 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13418 >= 0)))
a42f54e6
KH
13419 break;
13420 }
f9b5db02 13421
a42f54e6
KH
13422 if (! NILP (list))
13423 {
d27f8ca7
KH
13424 struct ccl_program *ccl
13425 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 13426
8e713be6 13427 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
13428 xfree (ccl);
13429 else
13430 fontp->font_encoder = ccl;
a6582676
KH
13431 }
13432}
13433
06a2c219 13434
dc43ef94 13435\f
06a2c219
GM
13436/***********************************************************************
13437 Initialization
13438 ***********************************************************************/
f451eb13 13439
3afe33e7
RS
13440#ifdef USE_X_TOOLKIT
13441static XrmOptionDescRec emacs_options[] = {
13442 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13443 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13444
13445 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13446 XrmoptionSepArg, NULL},
13447 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13448
13449 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13450 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13451 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13452 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13453 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13454 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13455 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13456};
13457#endif /* USE_X_TOOLKIT */
13458
7a13e894
RS
13459static int x_initialized;
13460
29b38361
KH
13461#ifdef MULTI_KBOARD
13462/* Test whether two display-name strings agree up to the dot that separates
13463 the screen number from the server number. */
13464static int
13465same_x_server (name1, name2)
13466 char *name1, *name2;
13467{
13468 int seen_colon = 0;
cf591cc1
RS
13469 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13470 int system_name_length = strlen (system_name);
13471 int length_until_period = 0;
13472
13473 while (system_name[length_until_period] != 0
13474 && system_name[length_until_period] != '.')
13475 length_until_period++;
13476
13477 /* Treat `unix' like an empty host name. */
13478 if (! strncmp (name1, "unix:", 5))
13479 name1 += 4;
13480 if (! strncmp (name2, "unix:", 5))
13481 name2 += 4;
13482 /* Treat this host's name like an empty host name. */
13483 if (! strncmp (name1, system_name, system_name_length)
13484 && name1[system_name_length] == ':')
13485 name1 += system_name_length;
13486 if (! strncmp (name2, system_name, system_name_length)
13487 && name2[system_name_length] == ':')
13488 name2 += system_name_length;
13489 /* Treat this host's domainless name like an empty host name. */
13490 if (! strncmp (name1, system_name, length_until_period)
13491 && name1[length_until_period] == ':')
13492 name1 += length_until_period;
13493 if (! strncmp (name2, system_name, length_until_period)
13494 && name2[length_until_period] == ':')
13495 name2 += length_until_period;
13496
29b38361
KH
13497 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13498 {
13499 if (*name1 == ':')
13500 seen_colon++;
13501 if (seen_colon && *name1 == '.')
13502 return 1;
13503 }
13504 return (seen_colon
13505 && (*name1 == '.' || *name1 == '\0')
13506 && (*name2 == '.' || *name2 == '\0'));
13507}
13508#endif
13509
334208b7 13510struct x_display_info *
1f8255f2 13511x_term_init (display_name, xrm_option, resource_name)
334208b7 13512 Lisp_Object display_name;
1f8255f2
RS
13513 char *xrm_option;
13514 char *resource_name;
dc6f92b8 13515{
334208b7 13516 int connection;
7a13e894 13517 Display *dpy;
334208b7
RS
13518 struct x_display_info *dpyinfo;
13519 XrmDatabase xrdb;
13520
60439948
KH
13521 BLOCK_INPUT;
13522
7a13e894
RS
13523 if (!x_initialized)
13524 {
13525 x_initialize ();
13526 x_initialized = 1;
13527 }
dc6f92b8 13528
3afe33e7 13529#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13530 /* weiner@footloose.sps.mot.com reports that this causes
13531 errors with X11R5:
13532 X protocol error: BadAtom (invalid Atom parameter)
13533 on protocol request 18skiloaf.
13534 So let's not use it until R6. */
13535#ifdef HAVE_X11XTR6
bdcd49ba
RS
13536 XtSetLanguageProc (NULL, NULL, NULL);
13537#endif
13538
7f9c7f94
RS
13539 {
13540 int argc = 0;
13541 char *argv[3];
13542
13543 argv[0] = "";
13544 argc = 1;
13545 if (xrm_option)
13546 {
13547 argv[argc++] = "-xrm";
13548 argv[argc++] = xrm_option;
13549 }
13550 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13551 resource_name, EMACS_CLASS,
13552 emacs_options, XtNumber (emacs_options),
13553 &argc, argv);
39d8bb4d
KH
13554
13555#ifdef HAVE_X11XTR6
10537cb1 13556 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13557 fixup_locale ();
39d8bb4d 13558#endif
7f9c7f94 13559 }
3afe33e7
RS
13560
13561#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13562#ifdef HAVE_X11R5
13563 XSetLocaleModifiers ("");
13564#endif
7a13e894 13565 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13566#endif /* not USE_X_TOOLKIT */
334208b7 13567
7a13e894
RS
13568 /* Detect failure. */
13569 if (dpy == 0)
60439948
KH
13570 {
13571 UNBLOCK_INPUT;
13572 return 0;
13573 }
7a13e894
RS
13574
13575 /* We have definitely succeeded. Record the new connection. */
13576
13577 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
f04e1297 13578 bzero (dpyinfo, sizeof *dpyinfo);
7a13e894 13579
29b38361
KH
13580#ifdef MULTI_KBOARD
13581 {
13582 struct x_display_info *share;
13583 Lisp_Object tail;
13584
13585 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13586 share = share->next, tail = XCDR (tail))
13587 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13588 XSTRING (display_name)->data))
13589 break;
13590 if (share)
13591 dpyinfo->kboard = share->kboard;
13592 else
13593 {
13594 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13595 init_kboard (dpyinfo->kboard);
59e755be
KH
13596 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13597 {
13598 char *vendor = ServerVendor (dpy);
9b6ed9f3 13599 UNBLOCK_INPUT;
59e755be
KH
13600 dpyinfo->kboard->Vsystem_key_alist
13601 = call1 (Qvendor_specific_keysyms,
13602 build_string (vendor ? vendor : ""));
9b6ed9f3 13603 BLOCK_INPUT;
59e755be
KH
13604 }
13605
29b38361
KH
13606 dpyinfo->kboard->next_kboard = all_kboards;
13607 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13608 /* Don't let the initial kboard remain current longer than necessary.
13609 That would cause problems if a file loaded on startup tries to
06a2c219 13610 prompt in the mini-buffer. */
0ad5446c
KH
13611 if (current_kboard == initial_kboard)
13612 current_kboard = dpyinfo->kboard;
29b38361
KH
13613 }
13614 dpyinfo->kboard->reference_count++;
13615 }
b9737ad3
KH
13616#endif
13617
7a13e894
RS
13618 /* Put this display on the chain. */
13619 dpyinfo->next = x_display_list;
13620 x_display_list = dpyinfo;
13621
13622 /* Put it on x_display_name_list as well, to keep them parallel. */
13623 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13624 x_display_name_list);
8e713be6 13625 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13626
13627 dpyinfo->display = dpy;
dc6f92b8 13628
dc6f92b8 13629#if 0
7a13e894 13630 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13631#endif /* ! 0 */
7a13e894
RS
13632
13633 dpyinfo->x_id_name
fc932ac6
RS
13634 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13635 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13636 + 2);
13637 sprintf (dpyinfo->x_id_name, "%s@%s",
13638 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13639
13640 /* Figure out which modifier bits mean what. */
334208b7 13641 x_find_modifier_meanings (dpyinfo);
f451eb13 13642
ab648270 13643 /* Get the scroll bar cursor. */
7a13e894 13644 dpyinfo->vertical_scroll_bar_cursor
334208b7 13645 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13646
334208b7
RS
13647 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13648 resource_name, EMACS_CLASS);
13649#ifdef HAVE_XRMSETDATABASE
13650 XrmSetDatabase (dpyinfo->display, xrdb);
13651#else
13652 dpyinfo->display->db = xrdb;
13653#endif
547d9db8 13654 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13655 all versions. */
13656 dpyinfo->xrdb = xrdb;
334208b7
RS
13657
13658 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13659 DefaultScreen (dpyinfo->display));
5ff67d81 13660 select_visual (dpyinfo);
43bd1b2b 13661 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13662 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13663 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13664 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13665 dpyinfo->grabbed = 0;
13666 dpyinfo->reference_count = 0;
13667 dpyinfo->icon_bitmap_id = -1;
06a2c219 13668 dpyinfo->font_table = NULL;
7a13e894
RS
13669 dpyinfo->n_fonts = 0;
13670 dpyinfo->font_table_size = 0;
13671 dpyinfo->bitmaps = 0;
13672 dpyinfo->bitmaps_size = 0;
13673 dpyinfo->bitmaps_last = 0;
13674 dpyinfo->scratch_cursor_gc = 0;
13675 dpyinfo->mouse_face_mouse_frame = 0;
13676 dpyinfo->mouse_face_deferred_gc = 0;
13677 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13678 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13679 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13680 dpyinfo->mouse_face_window = Qnil;
13681 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13682 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13683 dpyinfo->x_focus_frame = 0;
13684 dpyinfo->x_focus_event_frame = 0;
13685 dpyinfo->x_highlight_frame = 0;
06a2c219 13686 dpyinfo->image_cache = make_image_cache ();
334208b7 13687
43bd1b2b 13688 /* See if a private colormap is requested. */
5ff67d81
GM
13689 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13690 {
13691 if (dpyinfo->visual->class == PseudoColor)
13692 {
13693 Lisp_Object value;
13694 value = display_x_get_resource (dpyinfo,
13695 build_string ("privateColormap"),
13696 build_string ("PrivateColormap"),
13697 Qnil, Qnil);
13698 if (STRINGP (value)
13699 && (!strcmp (XSTRING (value)->data, "true")
13700 || !strcmp (XSTRING (value)->data, "on")))
13701 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13702 }
43bd1b2b 13703 }
5ff67d81
GM
13704 else
13705 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13706 dpyinfo->visual, AllocNone);
43bd1b2b 13707
06a2c219
GM
13708 {
13709 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13710 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13711 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13712 dpyinfo->resy = pixels * 25.4 / mm;
13713 pixels = DisplayWidth (dpyinfo->display, screen_number);
13714 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13715 dpyinfo->resx = pixels * 25.4 / mm;
13716 }
13717
334208b7
RS
13718 dpyinfo->Xatom_wm_protocols
13719 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13720 dpyinfo->Xatom_wm_take_focus
13721 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13722 dpyinfo->Xatom_wm_save_yourself
13723 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13724 dpyinfo->Xatom_wm_delete_window
13725 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13726 dpyinfo->Xatom_wm_change_state
13727 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13728 dpyinfo->Xatom_wm_configure_denied
13729 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13730 dpyinfo->Xatom_wm_window_moved
13731 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13732 dpyinfo->Xatom_editres
13733 = XInternAtom (dpyinfo->display, "Editres", False);
13734 dpyinfo->Xatom_CLIPBOARD
13735 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13736 dpyinfo->Xatom_TIMESTAMP
13737 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13738 dpyinfo->Xatom_TEXT
13739 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13740 dpyinfo->Xatom_COMPOUND_TEXT
13741 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13742 dpyinfo->Xatom_DELETE
13743 = XInternAtom (dpyinfo->display, "DELETE", False);
13744 dpyinfo->Xatom_MULTIPLE
13745 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13746 dpyinfo->Xatom_INCR
13747 = XInternAtom (dpyinfo->display, "INCR", False);
13748 dpyinfo->Xatom_EMACS_TMP
13749 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13750 dpyinfo->Xatom_TARGETS
13751 = XInternAtom (dpyinfo->display, "TARGETS", False);
13752 dpyinfo->Xatom_NULL
13753 = XInternAtom (dpyinfo->display, "NULL", False);
13754 dpyinfo->Xatom_ATOM_PAIR
13755 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13756 /* For properties of font. */
13757 dpyinfo->Xatom_PIXEL_SIZE
13758 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13759 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13760 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13761 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13762 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13763 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13764 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13765
06a2c219
GM
13766 /* Ghostscript support. */
13767 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13768 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13769
13770 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13771 False);
13772
547d9db8
KH
13773 dpyinfo->cut_buffers_initialized = 0;
13774
334208b7
RS
13775 connection = ConnectionNumber (dpyinfo->display);
13776 dpyinfo->connection = connection;
13777
dc43ef94 13778 {
5d7cc324
RS
13779 char null_bits[1];
13780
13781 null_bits[0] = 0x00;
dc43ef94
KH
13782
13783 dpyinfo->null_pixel
13784 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13785 null_bits, 1, 1, (long) 0, (long) 0,
13786 1);
13787 }
13788
06a2c219
GM
13789 {
13790 extern int gray_bitmap_width, gray_bitmap_height;
10659c77 13791 extern char *gray_bitmap_bits;
06a2c219
GM
13792 dpyinfo->gray
13793 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13794 gray_bitmap_bits,
13795 gray_bitmap_width, gray_bitmap_height,
13796 (unsigned long) 1, (unsigned long) 0, 1);
13797 }
13798
f5d11644
GM
13799#ifdef HAVE_X_I18N
13800 xim_initialize (dpyinfo, resource_name);
13801#endif
13802
87485d6f
MW
13803#ifdef subprocesses
13804 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13805 if (connection != 0)
7a13e894 13806 add_keyboard_wait_descriptor (connection);
87485d6f 13807#endif
6d4238f3 13808
041b69ac 13809#ifndef F_SETOWN_BUG
dc6f92b8 13810#ifdef F_SETOWN
dc6f92b8 13811#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13812 /* stdin is a socket here */
334208b7 13813 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13814#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13815 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13816#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13817#endif /* ! defined (F_SETOWN) */
041b69ac 13818#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13819
13820#ifdef SIGIO
eee20f6a
KH
13821 if (interrupt_input)
13822 init_sigio (connection);
c118dd06 13823#endif /* ! defined (SIGIO) */
dc6f92b8 13824
51b592fb 13825#ifdef USE_LUCID
f8c39f51 13826#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13827 /* Make sure that we have a valid font for dialog boxes
13828 so that Xt does not crash. */
13829 {
13830 Display *dpy = dpyinfo->display;
13831 XrmValue d, fr, to;
13832 Font font;
e99db5a1 13833 int count;
51b592fb
RS
13834
13835 d.addr = (XPointer)&dpy;
13836 d.size = sizeof (Display *);
13837 fr.addr = XtDefaultFont;
13838 fr.size = sizeof (XtDefaultFont);
13839 to.size = sizeof (Font *);
13840 to.addr = (XPointer)&font;
e99db5a1 13841 count = x_catch_errors (dpy);
51b592fb
RS
13842 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13843 abort ();
13844 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13845 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13846 x_uncatch_errors (dpy, count);
51b592fb
RS
13847 }
13848#endif
f8c39f51 13849#endif
51b592fb 13850
34e23e5a
GM
13851 /* See if we should run in synchronous mode. This is useful
13852 for debugging X code. */
13853 {
13854 Lisp_Object value;
13855 value = display_x_get_resource (dpyinfo,
13856 build_string ("synchronous"),
13857 build_string ("Synchronous"),
13858 Qnil, Qnil);
13859 if (STRINGP (value)
13860 && (!strcmp (XSTRING (value)->data, "true")
13861 || !strcmp (XSTRING (value)->data, "on")))
13862 XSynchronize (dpyinfo->display, True);
13863 }
13864
60439948
KH
13865 UNBLOCK_INPUT;
13866
7a13e894
RS
13867 return dpyinfo;
13868}
13869\f
13870/* Get rid of display DPYINFO, assuming all frames are already gone,
13871 and without sending any more commands to the X server. */
dc6f92b8 13872
7a13e894
RS
13873void
13874x_delete_display (dpyinfo)
13875 struct x_display_info *dpyinfo;
13876{
13877 delete_keyboard_wait_descriptor (dpyinfo->connection);
13878
13879 /* Discard this display from x_display_name_list and x_display_list.
13880 We can't use Fdelq because that can quit. */
13881 if (! NILP (x_display_name_list)
8e713be6
KR
13882 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13883 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13884 else
13885 {
13886 Lisp_Object tail;
13887
13888 tail = x_display_name_list;
8e713be6 13889 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13890 {
bffcfca9 13891 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13892 {
8e713be6 13893 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13894 break;
13895 }
8e713be6 13896 tail = XCDR (tail);
7a13e894
RS
13897 }
13898 }
13899
9bda743f
GM
13900 if (next_noop_dpyinfo == dpyinfo)
13901 next_noop_dpyinfo = dpyinfo->next;
13902
7a13e894
RS
13903 if (x_display_list == dpyinfo)
13904 x_display_list = dpyinfo->next;
7f9c7f94
RS
13905 else
13906 {
13907 struct x_display_info *tail;
7a13e894 13908
7f9c7f94
RS
13909 for (tail = x_display_list; tail; tail = tail->next)
13910 if (tail->next == dpyinfo)
13911 tail->next = tail->next->next;
13912 }
7a13e894 13913
0d777288
RS
13914#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13915#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13916 XrmDestroyDatabase (dpyinfo->xrdb);
13917#endif
0d777288 13918#endif
29b38361
KH
13919#ifdef MULTI_KBOARD
13920 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13921 delete_kboard (dpyinfo->kboard);
b9737ad3 13922#endif
f5d11644
GM
13923#ifdef HAVE_X_I18N
13924 if (dpyinfo->xim)
13925 xim_close_dpy (dpyinfo);
13926#endif
13927
b9737ad3
KH
13928 xfree (dpyinfo->font_table);
13929 xfree (dpyinfo->x_id_name);
f04e1297 13930 xfree (dpyinfo->color_cells);
b9737ad3 13931 xfree (dpyinfo);
7a13e894 13932}
f04e1297 13933
7a13e894
RS
13934\f
13935/* Set up use of X before we make the first connection. */
13936
06a2c219
GM
13937static struct redisplay_interface x_redisplay_interface =
13938{
13939 x_produce_glyphs,
13940 x_write_glyphs,
13941 x_insert_glyphs,
13942 x_clear_end_of_line,
13943 x_scroll_run,
13944 x_after_update_window_line,
13945 x_update_window_begin,
13946 x_update_window_end,
13947 XTcursor_to,
13948 x_flush,
71b8321e 13949 x_clear_mouse_face,
66ac4b0e
GM
13950 x_get_glyph_overhangs,
13951 x_fix_overlapping_area
06a2c219
GM
13952};
13953
dfcf069d 13954void
7a13e894
RS
13955x_initialize ()
13956{
06a2c219
GM
13957 rif = &x_redisplay_interface;
13958
13959 clear_frame_hook = x_clear_frame;
13960 ins_del_lines_hook = x_ins_del_lines;
13961 change_line_highlight_hook = x_change_line_highlight;
13962 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13963 ring_bell_hook = XTring_bell;
13964 reset_terminal_modes_hook = XTreset_terminal_modes;
13965 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13966 update_begin_hook = x_update_begin;
13967 update_end_hook = x_update_end;
dc6f92b8
JB
13968 set_terminal_window_hook = XTset_terminal_window;
13969 read_socket_hook = XTread_socket;
b8009dd1 13970 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13971 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13972 mouse_position_hook = XTmouse_position;
f451eb13 13973 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13974 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13975 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13976 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13977 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13978 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13979 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13980
f676886a 13981 scroll_region_ok = 1; /* we'll scroll partial frames */
9017309f 13982 char_ins_del_ok = 1;
dc6f92b8
JB
13983 line_ins_del_ok = 1; /* we'll just blt 'em */
13984 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13985 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13986 off the bottom */
13987 baud_rate = 19200;
13988
7a13e894 13989 x_noop_count = 0;
9ea173e8 13990 last_tool_bar_item = -1;
06a2c219
GM
13991 any_help_event_p = 0;
13992
b30b24cb
RS
13993 /* Try to use interrupt input; if we can't, then start polling. */
13994 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13995
7f9c7f94
RS
13996#ifdef USE_X_TOOLKIT
13997 XtToolkitInitialize ();
13998 Xt_app_con = XtCreateApplicationContext ();
665881ad 13999 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
14000
14001 /* Install an asynchronous timer that processes Xt timeout events
14002 every 0.1s. This is necessary because some widget sets use
14003 timeouts internally, for example the LessTif menu bar, or the
14004 Xaw3d scroll bar. When Xt timouts aren't processed, these
14005 widgets don't behave normally. */
14006 {
14007 EMACS_TIME interval;
14008 EMACS_SET_SECS_USECS (interval, 0, 100000);
14009 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14010 }
db74249b 14011#endif
bffcfca9 14012
eccc05db 14013#ifdef USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
14014 xaw3d_arrow_scroll = False;
14015 xaw3d_pick_top = True;
7f9c7f94
RS
14016#endif
14017
58769bee 14018 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 14019 original error handler. */
e99db5a1 14020 XSetErrorHandler (x_error_handler);
334208b7 14021 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 14022
06a2c219 14023 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
14024#ifdef SIGWINCH
14025 signal (SIGWINCH, SIG_DFL);
c118dd06 14026#endif /* ! defined (SIGWINCH) */
dc6f92b8 14027
92e2441b 14028 signal (SIGPIPE, x_connection_signal);
dc6f92b8 14029}
55123275 14030
06a2c219 14031
55123275
JB
14032void
14033syms_of_xterm ()
14034{
e99db5a1
RS
14035 staticpro (&x_error_message_string);
14036 x_error_message_string = Qnil;
14037
7a13e894
RS
14038 staticpro (&x_display_name_list);
14039 x_display_name_list = Qnil;
334208b7 14040
ab648270 14041 staticpro (&last_mouse_scroll_bar);
e53cb100 14042 last_mouse_scroll_bar = Qnil;
59e755be
KH
14043
14044 staticpro (&Qvendor_specific_keysyms);
14045 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
14046
14047 staticpro (&last_mouse_press_frame);
14048 last_mouse_press_frame = Qnil;
06a2c219 14049
06a2c219 14050 help_echo = Qnil;
be010514
GM
14051 staticpro (&help_echo);
14052 help_echo_object = Qnil;
14053 staticpro (&help_echo_object);
7cea38bc
GM
14054 help_echo_window = Qnil;
14055 staticpro (&help_echo_window);
06a2c219 14056 previous_help_echo = Qnil;
be010514
GM
14057 staticpro (&previous_help_echo);
14058 help_echo_pos = -1;
06a2c219
GM
14059
14060 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14061 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
14062For example, if a block cursor is over a tab, it will be drawn as\n\
14063wide as that tab on the display.");
14064 x_stretch_cursor_p = 0;
14065
5bf04520
GM
14066 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14067 "What X toolkit scroll bars Emacs uses.\n\
14068A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
14069Otherwise, value is a symbol describing the X toolkit.");
eccc05db 14070#ifdef USE_TOOLKIT_SCROLL_BARS
5bf04520
GM
14071#ifdef USE_MOTIF
14072 Vx_toolkit_scroll_bars = intern ("motif");
14073#elif defined HAVE_XAW3D
14074 Vx_toolkit_scroll_bars = intern ("xaw3d");
14075#else
14076 Vx_toolkit_scroll_bars = intern ("xaw");
14077#endif
06a2c219 14078#else
5bf04520 14079 Vx_toolkit_scroll_bars = Qnil;
06a2c219
GM
14080#endif
14081
06a2c219
GM
14082 staticpro (&last_mouse_motion_frame);
14083 last_mouse_motion_frame = Qnil;
55123275 14084}
6cf0ae86
RS
14085
14086#endif /* not HAVE_X_WINDOWS */