Add information about debugging the tty version.
[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"
dc6f92b8 79#include "gnu.h"
dc6f92b8 80#include "disptab.h"
dc6f92b8 81#include "buffer.h"
f451eb13 82#include "window.h"
3b2fa4e6 83#include "keyboard.h"
bde7c500 84#include "intervals.h"
dfcf069d 85#include "process.h"
bffcfca9 86#include "atimer.h"
8feddab4 87#include "keymap.h"
dc6f92b8 88
d2bd6bc4
RS
89#ifdef USE_X_TOOLKIT
90#include <X11/Shell.h>
91#endif
92
06a2c219
GM
93#ifdef HAVE_SYS_TIME_H
94#include <sys/time.h>
95#endif
96#ifdef HAVE_UNISTD_H
97#include <unistd.h>
98#endif
99
d624284c
PJ
100#ifdef USE_LUCID
101extern int xlwmenu_window_p (Widget w, Window window);
102extern void xlwmenu_redisplay P_ ((Widget));
103#endif
104
3afe33e7 105#ifdef USE_X_TOOLKIT
06a2c219 106
952291d9
GM
107extern void free_frame_menubar P_ ((struct frame *));
108extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
109 int));
06a2c219 110
0fdff6bb
RS
111#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
112#define HACK_EDITRES
113extern void _XEditResCheckMessages ();
114#endif /* not NO_EDITRES */
06a2c219
GM
115
116/* Include toolkit specific headers for the scroll bar widget. */
117
118#ifdef USE_TOOLKIT_SCROLL_BARS
119#if defined USE_MOTIF
120#include <Xm/Xm.h> /* for LESSTIF_VERSION */
121#include <Xm/ScrollBar.h>
ec18280f
SM
122#else /* !USE_MOTIF i.e. use Xaw */
123
124#ifdef HAVE_XAW3D
06a2c219 125#include <X11/Xaw3d/Simple.h>
06a2c219
GM
126#include <X11/Xaw3d/Scrollbar.h>
127#define ARROW_SCROLLBAR
128#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
129#else /* !HAVE_XAW3D */
130#include <X11/Xaw/Simple.h>
131#include <X11/Xaw/Scrollbar.h>
132#endif /* !HAVE_XAW3D */
133#ifndef XtNpickTop
134#define XtNpickTop "pickTop"
135#endif /* !XtNpickTop */
136#endif /* !USE_MOTIF */
06a2c219
GM
137#endif /* USE_TOOLKIT_SCROLL_BARS */
138
3afe33e7
RS
139#endif /* USE_X_TOOLKIT */
140
b849c413
RS
141#ifndef USE_X_TOOLKIT
142#define x_any_window_to_frame x_window_to_frame
5627c40e 143#define x_top_window_to_frame x_window_to_frame
b849c413
RS
144#endif
145
546e6d5b 146#ifdef USE_X_TOOLKIT
d067ea8b 147#include "widget.h"
546e6d5b
RS
148#ifndef XtNinitialState
149#define XtNinitialState "initialState"
150#endif
151#endif
152
06a2c219
GM
153#define abs(x) ((x) < 0 ? -(x) : (x))
154
155#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
156
157\f
158/* Bitmaps for truncated lines. */
159
160enum bitmap_type
161{
162 NO_BITMAP,
163 LEFT_TRUNCATION_BITMAP,
164 RIGHT_TRUNCATION_BITMAP,
165 OVERLAY_ARROW_BITMAP,
166 CONTINUED_LINE_BITMAP,
167 CONTINUATION_LINE_BITMAP,
168 ZV_LINE_BITMAP
169};
170
171/* Bitmap drawn to indicate lines not displaying text if
172 `indicate-empty-lines' is non-nil. */
173
174#define zv_width 8
175#define zv_height 8
176static unsigned char zv_bits[] = {
177 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
178
179/* An arrow like this: `<-'. */
180
181#define left_width 8
182#define left_height 8
183static unsigned char left_bits[] = {
184 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
185
110859fc
GM
186/* Right truncation arrow bitmap `->'. */
187
188#define right_width 8
189#define right_height 8
190static unsigned char right_bits[] = {
191 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
192
06a2c219
GM
193/* Marker for continued lines. */
194
195#define continued_width 8
196#define continued_height 8
197static unsigned char continued_bits[] = {
110859fc
GM
198 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
199
200/* Marker for continuation lines. */
06a2c219
GM
201
202#define continuation_width 8
203#define continuation_height 8
204static unsigned char continuation_bits[] = {
110859fc 205 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 206
110859fc 207/* Overlay arrow bitmap. */
06a2c219 208
110859fc
GM
209#if 0
210/* A bomb. */
06a2c219
GM
211#define ov_width 8
212#define ov_height 8
213static unsigned char ov_bits[] = {
214 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 215#else
110859fc 216/* A triangular arrow. */
06a2c219
GM
217#define ov_width 8
218#define ov_height 8
219static unsigned char ov_bits[] = {
110859fc
GM
220 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
221
e4b68333 222#endif
06a2c219
GM
223
224extern Lisp_Object Qhelp_echo;
225
69388238 226\f
5bf04520 227/* Non-nil means Emacs uses toolkit scroll bars. */
06a2c219 228
5bf04520 229Lisp_Object Vx_toolkit_scroll_bars;
06a2c219
GM
230
231/* If a string, XTread_socket generates an event to display that string.
232 (The display is done in read_char.) */
233
234static Lisp_Object help_echo;
7cea38bc 235static Lisp_Object help_echo_window;
be010514
GM
236static Lisp_Object help_echo_object;
237static int help_echo_pos;
06a2c219
GM
238
239/* Temporary variable for XTread_socket. */
240
241static Lisp_Object previous_help_echo;
242
243/* Non-zero means that a HELP_EVENT has been generated since Emacs
244 start. */
245
246static int any_help_event_p;
247
248/* Non-zero means draw block and hollow cursor as wide as the glyph
249 under it. For example, if a block cursor is over a tab, it will be
250 drawn as wide as that tab on the display. */
251
252int x_stretch_cursor_p;
253
a72d5ce5
GM
254/* Non-zero means make use of UNDERLINE_POSITION font properties. */
255
256int x_use_underline_position_properties;
257
06a2c219
GM
258/* This is a chain of structures for all the X displays currently in
259 use. */
260
334208b7 261struct x_display_info *x_display_list;
dc6f92b8 262
06a2c219
GM
263/* This is a list of cons cells, each of the form (NAME
264 . FONT-LIST-CACHE), one for each element of x_display_list and in
265 the same order. NAME is the name of the frame. FONT-LIST-CACHE
266 records previous values returned by x-list-fonts. */
267
7a13e894 268Lisp_Object x_display_name_list;
f451eb13 269
987d2ad1 270/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
271 This is set by update_begin and looked at by all the XT functions.
272 It is zero while not inside an update. In that case, the XT
273 functions assume that `selected_frame' is the frame to apply to. */
274
d0386f2a 275extern struct frame *updating_frame;
dc6f92b8 276
dfcf069d 277extern int waiting_for_input;
0e81d8cd 278
06a2c219
GM
279/* This is a frame waiting to be auto-raised, within XTread_socket. */
280
0134a210
RS
281struct frame *pending_autoraise_frame;
282
7f9c7f94
RS
283#ifdef USE_X_TOOLKIT
284/* The application context for Xt use. */
285XtAppContext Xt_app_con;
06a2c219
GM
286static String Xt_default_resources[] = {0};
287#endif /* USE_X_TOOLKIT */
665881ad 288
06a2c219
GM
289/* Nominal cursor position -- where to draw output.
290 HPOS and VPOS are window relative glyph matrix coordinates.
291 X and Y are window relative pixel coordinates. */
dc6f92b8 292
06a2c219 293struct cursor_pos output_cursor;
dc6f92b8 294
bffcfca9
GM
295/* Non-zero means user is interacting with a toolkit scroll bar. */
296
297static int toolkit_scroll_bar_interaction;
dc6f92b8 298
69388238
RS
299/* Mouse movement.
300
06a2c219 301 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
302 so that we would have to call XQueryPointer after each MotionNotify
303 event to ask for another such event. However, this made mouse tracking
304 slow, and there was a bug that made it eventually stop.
305
306 Simply asking for MotionNotify all the time seems to work better.
307
69388238
RS
308 In order to avoid asking for motion events and then throwing most
309 of them away or busy-polling the server for mouse positions, we ask
310 the server for pointer motion hints. This means that we get only
311 one event per group of mouse movements. "Groups" are delimited by
312 other kinds of events (focus changes and button clicks, for
313 example), or by XQueryPointer calls; when one of these happens, we
314 get another MotionNotify event the next time the mouse moves. This
315 is at least as efficient as getting motion events when mouse
316 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 317 is off. */
69388238
RS
318
319/* Where the mouse was last time we reported a mouse event. */
69388238 320
06a2c219
GM
321FRAME_PTR last_mouse_frame;
322static XRectangle last_mouse_glyph;
2237cac9
RS
323static Lisp_Object last_mouse_press_frame;
324
69388238
RS
325/* The scroll bar in which the last X motion event occurred.
326
06a2c219
GM
327 If the last X motion event occurred in a scroll bar, we set this so
328 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
329 an ordinary motion.
330
06a2c219
GM
331 If the last X motion event didn't occur in a scroll bar, we set
332 this to Qnil, to tell XTmouse_position to return an ordinary motion
333 event. */
334
69388238
RS
335static Lisp_Object last_mouse_scroll_bar;
336
69388238
RS
337/* This is a hack. We would really prefer that XTmouse_position would
338 return the time associated with the position it returns, but there
06a2c219 339 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
340 along with the position query. So, we just keep track of the time
341 of the last movement we received, and return that in hopes that
342 it's somewhat accurate. */
06a2c219 343
69388238
RS
344static Time last_mouse_movement_time;
345
06a2c219
GM
346/* Incremented by XTread_socket whenever it really tries to read
347 events. */
348
c0a04927
RS
349#ifdef __STDC__
350static int volatile input_signal_count;
351#else
352static int input_signal_count;
353#endif
354
7a13e894 355/* Used locally within XTread_socket. */
06a2c219 356
7a13e894 357static int x_noop_count;
dc6f92b8 358
7a13e894 359/* Initial values of argv and argc. */
06a2c219 360
7a13e894
RS
361extern char **initial_argv;
362extern int initial_argc;
dc6f92b8 363
7a13e894 364extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 365
06a2c219 366/* Tells if a window manager is present or not. */
7a13e894
RS
367
368extern Lisp_Object Vx_no_window_manager;
dc6f92b8 369
c2df547c 370extern Lisp_Object Qface, Qmouse_face;
b8009dd1 371
dc6f92b8
JB
372extern int errno;
373
dfeccd2d 374/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 375
64bb1782
RS
376extern int extra_keyboard_modifiers;
377
59e755be
KH
378static Lisp_Object Qvendor_specific_keysyms;
379
952291d9
GM
380extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
381extern Lisp_Object x_icon_type P_ ((struct frame *));
c32cdd9a 382
7a13e894 383
06a2c219
GM
384/* Enumeration for overriding/changing the face to use for drawing
385 glyphs in x_draw_glyphs. */
386
387enum draw_glyphs_face
388{
389 DRAW_NORMAL_TEXT,
390 DRAW_INVERSE_VIDEO,
391 DRAW_CURSOR,
392 DRAW_MOUSE_FACE,
393 DRAW_IMAGE_RAISED,
394 DRAW_IMAGE_SUNKEN
395};
396
b7f83f9e 397static int cursor_in_mouse_face_p P_ ((struct window *));
fa262c07 398static int clear_mouse_face P_ ((struct x_display_info *));
651f03b6 399static int x_alloc_nearest_color_1 P_ ((Display *, Colormap, XColor *));
499b1844 400static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
651f03b6 401static const XColor *x_color_cells P_ ((Display *, int *));
71b8321e 402static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
403static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
404void x_delete_display P_ ((struct x_display_info *));
405static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
406 unsigned));
407static int fast_find_position P_ ((struct window *, int, int *, int *,
7e376260 408 int *, int *, Lisp_Object));
f9db2310
GM
409static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
410 int *, int *, int *, int *, int));
06a2c219
GM
411static void set_output_cursor P_ ((struct cursor_pos *));
412static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
f9db2310 413 int *, int *, int *, int));
06a2c219 414static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 415static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
416static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
417static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
418static void show_mouse_face P_ ((struct x_display_info *,
419 enum draw_glyphs_face));
420static int x_io_error_quitter P_ ((Display *));
421int x_catch_errors P_ ((Display *));
422void x_uncatch_errors P_ ((Display *, int));
423void x_lower_frame P_ ((struct frame *));
424void x_scroll_bar_clear P_ ((struct frame *));
425int x_had_errors_p P_ ((Display *));
426void x_wm_set_size_hint P_ ((struct frame *, long, int));
427void x_raise_frame P_ ((struct frame *));
428void x_set_window_size P_ ((struct frame *, int, int, int));
429void x_wm_set_window_state P_ ((struct frame *, int));
430void x_wm_set_icon_pixmap P_ ((struct frame *, int));
431void x_initialize P_ ((void));
432static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
433static int x_compute_min_glyph_bounds P_ ((struct frame *));
434static void x_draw_phys_cursor_glyph P_ ((struct window *,
435 struct glyph_row *,
436 enum draw_glyphs_face));
437static void x_update_end P_ ((struct frame *));
438static void XTframe_up_to_date P_ ((struct frame *));
06a2c219
GM
439static void XTset_terminal_modes P_ ((void));
440static void XTreset_terminal_modes P_ ((void));
441static void XTcursor_to P_ ((int, int, int, int));
442static void x_write_glyphs P_ ((struct glyph *, int));
443static void x_clear_end_of_line P_ ((int));
444static void x_clear_frame P_ ((void));
445static void x_clear_cursor P_ ((struct window *));
446static void frame_highlight P_ ((struct frame *));
447static void frame_unhighlight P_ ((struct frame *));
448static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
449static void XTframe_rehighlight P_ ((struct frame *));
450static void x_frame_rehighlight P_ ((struct x_display_info *));
451static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
f02d8aa0 452static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
06a2c219
GM
453static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
454 XRectangle *));
455static void expose_frame P_ ((struct frame *, int, int, int, int));
82f053ab 456static int expose_window_tree P_ ((struct window *, XRectangle *));
a39202f6 457static int expose_window P_ ((struct window *, XRectangle *));
06a2c219
GM
458static void expose_area P_ ((struct window *, struct glyph_row *,
459 XRectangle *, enum glyph_row_area));
82f053ab 460static int expose_line P_ ((struct window *, struct glyph_row *,
06a2c219
GM
461 XRectangle *));
462static void x_update_cursor_in_window_tree P_ ((struct window *, int));
463static void x_update_window_cursor P_ ((struct window *, int));
464static void x_erase_phys_cursor P_ ((struct window *));
465void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
466static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
467 enum bitmap_type));
468
469static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
470 GC, int));
471static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
472static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
78a9a4c5 473static void notice_overwritten_cursor P_ ((struct window *, int, int));
06a2c219 474static void x_flush P_ ((struct frame *f));
952291d9
GM
475static void x_update_begin P_ ((struct frame *));
476static void x_update_window_begin P_ ((struct window *));
477static void x_draw_vertical_border P_ ((struct window *));
478static void x_after_update_window_line P_ ((struct glyph_row *));
479static INLINE void take_vertical_position_into_account P_ ((struct it *));
480static void x_produce_stretch_glyph P_ ((struct it *));
b52b65bd
GM
481static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
482static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
483 enum scroll_bar_part *,
484 Lisp_Object *, Lisp_Object *,
485 unsigned long *));
06a2c219
GM
486
487/* Flush display of frame F, or of all frames if F is null. */
488
489static void
490x_flush (f)
491 struct frame *f;
492{
493 BLOCK_INPUT;
494 if (f == NULL)
495 {
496 Lisp_Object rest, frame;
497 FOR_EACH_FRAME (rest, frame)
498 x_flush (XFRAME (frame));
499 }
500 else if (FRAME_X_P (f))
501 XFlush (FRAME_X_DISPLAY (f));
502 UNBLOCK_INPUT;
503}
504
dc6f92b8 505
06a2c219
GM
506/* Remove calls to XFlush by defining XFlush to an empty replacement.
507 Calls to XFlush should be unnecessary because the X output buffer
508 is flushed automatically as needed by calls to XPending,
509 XNextEvent, or XWindowEvent according to the XFlush man page.
510 XTread_socket calls XPending. Removing XFlush improves
511 performance. */
512
513#define XFlush(DISPLAY) (void) 0
b8009dd1 514
334208b7 515\f
06a2c219
GM
516/***********************************************************************
517 Debugging
518 ***********************************************************************/
519
9382638d 520#if 0
06a2c219
GM
521
522/* This is a function useful for recording debugging information about
523 the sequence of occurrences in this file. */
9382638d
KH
524
525struct record
526{
527 char *locus;
528 int type;
529};
530
531struct record event_record[100];
532
533int event_record_index;
534
535record_event (locus, type)
536 char *locus;
537 int type;
538{
539 if (event_record_index == sizeof (event_record) / sizeof (struct record))
540 event_record_index = 0;
541
542 event_record[event_record_index].locus = locus;
543 event_record[event_record_index].type = type;
544 event_record_index++;
545}
546
547#endif /* 0 */
06a2c219
GM
548
549
9382638d 550\f
334208b7
RS
551/* Return the struct x_display_info corresponding to DPY. */
552
553struct x_display_info *
554x_display_info_for_display (dpy)
555 Display *dpy;
556{
557 struct x_display_info *dpyinfo;
558
559 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
560 if (dpyinfo->display == dpy)
561 return dpyinfo;
16bd92ea 562
334208b7
RS
563 return 0;
564}
f451eb13 565
06a2c219
GM
566
567\f
568/***********************************************************************
569 Starting and ending an update
570 ***********************************************************************/
571
572/* Start an update of frame F. This function is installed as a hook
573 for update_begin, i.e. it is called when update_begin is called.
574 This function is called prior to calls to x_update_window_begin for
575 each window being updated. Currently, there is nothing to do here
576 because all interesting stuff is done on a window basis. */
dc6f92b8 577
dfcf069d 578static void
06a2c219 579x_update_begin (f)
f676886a 580 struct frame *f;
58769bee 581{
06a2c219
GM
582 /* Nothing to do. */
583}
dc6f92b8 584
dc6f92b8 585
06a2c219
GM
586/* Start update of window W. Set the global variable updated_window
587 to the window being updated and set output_cursor to the cursor
588 position of W. */
dc6f92b8 589
06a2c219
GM
590static void
591x_update_window_begin (w)
592 struct window *w;
593{
594 struct frame *f = XFRAME (WINDOW_FRAME (w));
595 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
596
597 updated_window = w;
598 set_output_cursor (&w->cursor);
b8009dd1 599
06a2c219 600 BLOCK_INPUT;
d1bc4182 601
06a2c219 602 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 603 {
514e4681 604 /* Don't do highlighting for mouse motion during the update. */
06a2c219 605 display_info->mouse_face_defer = 1;
37c2c98b 606
06a2c219
GM
607 /* If F needs to be redrawn, simply forget about any prior mouse
608 highlighting. */
9f67f20b 609 if (FRAME_GARBAGED_P (f))
06a2c219
GM
610 display_info->mouse_face_window = Qnil;
611
64f26cf5
GM
612#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
613 their mouse_face_p flag set, which means that they are always
614 unequal to rows in a desired matrix which never have that
615 flag set. So, rows containing mouse-face glyphs are never
616 scrolled, and we don't have to switch the mouse highlight off
617 here to prevent it from being scrolled. */
618
06a2c219
GM
619 /* Can we tell that this update does not affect the window
620 where the mouse highlight is? If so, no need to turn off.
621 Likewise, don't do anything if the frame is garbaged;
622 in that case, the frame's current matrix that we would use
623 is all wrong, and we will redisplay that line anyway. */
624 if (!NILP (display_info->mouse_face_window)
625 && w == XWINDOW (display_info->mouse_face_window))
514e4681 626 {
06a2c219 627 int i;
514e4681 628
06a2c219
GM
629 for (i = 0; i < w->desired_matrix->nrows; ++i)
630 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
631 break;
632
06a2c219
GM
633 if (i < w->desired_matrix->nrows)
634 clear_mouse_face (display_info);
514e4681 635 }
64f26cf5 636#endif /* 0 */
b8009dd1 637 }
6ccf47d1 638
dc6f92b8
JB
639 UNBLOCK_INPUT;
640}
641
06a2c219
GM
642
643/* Draw a vertical window border to the right of window W if W doesn't
644 have vertical scroll bars. */
645
dfcf069d 646static void
06a2c219
GM
647x_draw_vertical_border (w)
648 struct window *w;
58769bee 649{
06a2c219
GM
650 struct frame *f = XFRAME (WINDOW_FRAME (w));
651
652 /* Redraw borders between horizontally adjacent windows. Don't
653 do it for frames with vertical scroll bars because either the
654 right scroll bar of a window, or the left scroll bar of its
655 neighbor will suffice as a border. */
656 if (!WINDOW_RIGHTMOST_P (w)
657 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
658 {
659 int x0, x1, y0, y1;
dc6f92b8 660
06a2c219 661 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 662 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
663 y1 -= 1;
664
665 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
666 f->output_data.x->normal_gc, x1, y0, x1, y1);
667 }
668}
669
670
71b8321e
GM
671/* End update of window W (which is equal to updated_window).
672
673 Draw vertical borders between horizontally adjacent windows, and
674 display W's cursor if CURSOR_ON_P is non-zero.
675
676 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
677 glyphs in mouse-face were overwritten. In that case we have to
678 make sure that the mouse-highlight is properly redrawn.
679
680 W may be a menu bar pseudo-window in case we don't have X toolkit
681 support. Such windows don't have a cursor, so don't display it
682 here. */
06a2c219
GM
683
684static void
71b8321e 685x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
06a2c219 686 struct window *w;
71b8321e 687 int cursor_on_p, mouse_face_overwritten_p;
06a2c219 688{
140330de
GM
689 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
690
06a2c219
GM
691 if (!w->pseudo_window_p)
692 {
693 BLOCK_INPUT;
71b8321e 694
06a2c219
GM
695 if (cursor_on_p)
696 x_display_and_set_cursor (w, 1, output_cursor.hpos,
697 output_cursor.vpos,
698 output_cursor.x, output_cursor.y);
71b8321e 699
06a2c219
GM
700 x_draw_vertical_border (w);
701 UNBLOCK_INPUT;
702 }
703
140330de
GM
704 /* If a row with mouse-face was overwritten, arrange for
705 XTframe_up_to_date to redisplay the mouse highlight. */
706 if (mouse_face_overwritten_p)
707 {
708 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
709 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
710 dpyinfo->mouse_face_window = Qnil;
711 }
712
06a2c219
GM
713 updated_window = NULL;
714}
dc6f92b8 715
dc6f92b8 716
06a2c219
GM
717/* End update of frame F. This function is installed as a hook in
718 update_end. */
719
720static void
721x_update_end (f)
722 struct frame *f;
723{
724 /* Mouse highlight may be displayed again. */
aa8bff2e 725 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 726
06a2c219 727 BLOCK_INPUT;
334208b7 728 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
729 UNBLOCK_INPUT;
730}
b8009dd1 731
06a2c219
GM
732
733/* This function is called from various places in xdisp.c whenever a
734 complete update has been performed. The global variable
735 updated_window is not available here. */
b8009dd1 736
dfcf069d 737static void
b8009dd1 738XTframe_up_to_date (f)
06a2c219 739 struct frame *f;
b8009dd1 740{
06a2c219 741 if (FRAME_X_P (f))
514e4681 742 {
06a2c219 743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
71b8321e 744
06a2c219
GM
745 if (dpyinfo->mouse_face_deferred_gc
746 || f == dpyinfo->mouse_face_mouse_frame)
747 {
748 BLOCK_INPUT;
749 if (dpyinfo->mouse_face_mouse_frame)
750 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
751 dpyinfo->mouse_face_mouse_x,
752 dpyinfo->mouse_face_mouse_y);
753 dpyinfo->mouse_face_deferred_gc = 0;
754 UNBLOCK_INPUT;
755 }
514e4681 756 }
b8009dd1 757}
06a2c219
GM
758
759
760/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
761 arrow bitmaps, or clear the areas where they would be displayed
762 before DESIRED_ROW is made current. The window being updated is
763 found in updated_window. This function It is called from
764 update_window_line only if it is known that there are differences
765 between bitmaps to be drawn between current row and DESIRED_ROW. */
766
767static void
768x_after_update_window_line (desired_row)
769 struct glyph_row *desired_row;
770{
771 struct window *w = updated_window;
772
773 xassert (w);
774
775 if (!desired_row->mode_line_p && !w->pseudo_window_p)
776 {
c5e6e06b
GM
777 struct frame *f;
778 int width;
779
06a2c219
GM
780 BLOCK_INPUT;
781 x_draw_row_bitmaps (w, desired_row);
782
783 /* When a window has disappeared, make sure that no rest of
784 full-width rows stays visible in the internal border. */
c5e6e06b
GM
785 if (windows_or_buffers_changed
786 && (f = XFRAME (w->frame),
787 width = FRAME_INTERNAL_BORDER_WIDTH (f),
788 width != 0))
06a2c219 789 {
06a2c219 790 int height = desired_row->visible_height;
110859fc
GM
791 int x = (window_box_right (w, -1)
792 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
793 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
794
c5e6e06b
GM
795 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
796 x, y, width, height, False);
06a2c219
GM
797 }
798
799 UNBLOCK_INPUT;
800 }
801}
802
803
804/* Draw the bitmap WHICH in one of the areas to the left or right of
805 window W. ROW is the glyph row for which to display the bitmap; it
806 determines the vertical position at which the bitmap has to be
807 drawn. */
808
809static void
810x_draw_bitmap (w, row, which)
811 struct window *w;
812 struct glyph_row *row;
813 enum bitmap_type which;
814{
815 struct frame *f = XFRAME (WINDOW_FRAME (w));
816 Display *display = FRAME_X_DISPLAY (f);
817 Window window = FRAME_X_WINDOW (f);
818 int x, y, wd, h, dy;
819 unsigned char *bits;
820 Pixmap pixmap;
821 GC gc = f->output_data.x->normal_gc;
822 struct face *face;
823 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
824
825 /* Must clip because of partially visible lines. */
826 x_clip_to_row (w, row, gc, 1);
827
828 switch (which)
829 {
830 case LEFT_TRUNCATION_BITMAP:
831 wd = left_width;
832 h = left_height;
833 bits = left_bits;
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
835 - wd
110859fc 836 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
837 break;
838
839 case OVERLAY_ARROW_BITMAP:
840 wd = left_width;
841 h = left_height;
842 bits = ov_bits;
843 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
844 - wd
110859fc 845 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
846 break;
847
848 case RIGHT_TRUNCATION_BITMAP:
849 wd = right_width;
850 h = right_height;
851 bits = right_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 CONTINUED_LINE_BITMAP:
857 wd = right_width;
858 h = right_height;
859 bits = continued_bits;
860 x = window_box_right (w, -1);
110859fc 861 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
862 break;
863
864 case CONTINUATION_LINE_BITMAP:
865 wd = continuation_width;
866 h = continuation_height;
867 bits = continuation_bits;
868 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
869 - wd
110859fc 870 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
871 break;
872
873 case ZV_LINE_BITMAP:
874 wd = zv_width;
875 h = zv_height;
876 bits = zv_bits;
877 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
878 - wd
110859fc 879 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
880 break;
881
882 default:
883 abort ();
884 }
885
886 /* Convert to frame coordinates. Set dy to the offset in the row to
887 start drawing the bitmap. */
888 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
889 dy = (row->height - h) / 2;
890
891 /* Draw the bitmap. I believe these small pixmaps can be cached
892 by the server. */
893 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
894 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
895 face->foreground,
896 face->background, depth);
897 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
898 XFreePixmap (display, pixmap);
899 XSetClipMask (display, gc, None);
900}
901
902
903/* Draw flags bitmaps for glyph row ROW on window W. Call this
904 function with input blocked. */
905
906static void
907x_draw_row_bitmaps (w, row)
908 struct window *w;
909 struct glyph_row *row;
910{
911 struct frame *f = XFRAME (w->frame);
912 enum bitmap_type bitmap;
913 struct face *face;
045dee35 914 int header_line_height = -1;
06a2c219
GM
915
916 xassert (interrupt_input_blocked);
917
918 /* If row is completely invisible, because of vscrolling, we
919 don't have to draw anything. */
920 if (row->visible_height <= 0)
921 return;
922
923 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
924 PREPARE_FACE_FOR_DISPLAY (f, face);
925
926 /* Decide which bitmap to draw at the left side. */
927 if (row->overlay_arrow_p)
928 bitmap = OVERLAY_ARROW_BITMAP;
929 else if (row->truncated_on_left_p)
930 bitmap = LEFT_TRUNCATION_BITMAP;
931 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
932 bitmap = CONTINUATION_LINE_BITMAP;
933 else if (row->indicate_empty_line_p)
934 bitmap = ZV_LINE_BITMAP;
935 else
936 bitmap = NO_BITMAP;
937
938 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
939 the flags area. */
940 if (bitmap == NO_BITMAP
110859fc 941 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
942 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
943 {
944 /* If W has a vertical border to its left, don't draw over it. */
945 int border = ((XFASTINT (w->left) > 0
946 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
947 ? 1 : 0);
948 int left = window_box_left (w, -1);
949
045dee35
GM
950 if (header_line_height < 0)
951 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
952
953 /* In case the same realized face is used for bitmap areas and
954 for something displayed in the text (e.g. face `region' on
955 mono-displays, the fill style may have been changed to
956 FillSolid in x_draw_glyph_string_background. */
957 if (face->stipple)
958 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
959 else
960 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
961
06a2c219
GM
962 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
963 face->gc,
964 (left
110859fc 965 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 966 + border),
045dee35 967 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 968 row->y)),
110859fc 969 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 970 row->visible_height);
dcd08bfb
GM
971 if (!face->stipple)
972 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
973 }
974
975 /* Draw the left bitmap. */
976 if (bitmap != NO_BITMAP)
977 x_draw_bitmap (w, row, bitmap);
978
979 /* Decide which bitmap to draw at the right side. */
980 if (row->truncated_on_right_p)
981 bitmap = RIGHT_TRUNCATION_BITMAP;
982 else if (row->continued_p)
983 bitmap = CONTINUED_LINE_BITMAP;
984 else
985 bitmap = NO_BITMAP;
986
987 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
988 the flags area. */
989 if (bitmap == NO_BITMAP
110859fc 990 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
991 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
992 {
993 int right = window_box_right (w, -1);
994
045dee35
GM
995 if (header_line_height < 0)
996 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
997
998 /* In case the same realized face is used for bitmap areas and
999 for something displayed in the text (e.g. face `region' on
1000 mono-displays, the fill style may have been changed to
1001 FillSolid in x_draw_glyph_string_background. */
1002 if (face->stipple)
1003 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1004 else
1005 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
1006 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1007 face->gc,
1008 right,
045dee35 1009 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 1010 row->y)),
110859fc 1011 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 1012 row->visible_height);
dcd08bfb
GM
1013 if (!face->stipple)
1014 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
1015 }
1016
1017 /* Draw the right bitmap. */
1018 if (bitmap != NO_BITMAP)
1019 x_draw_bitmap (w, row, bitmap);
1020}
1021
dc6f92b8 1022\f
06a2c219
GM
1023
1024/* This is called when starting Emacs and when restarting after
1025 suspend. When starting Emacs, no X window is mapped. And nothing
1026 must be done to Emacs's own window if it is suspended (though that
1027 rarely happens). */
dc6f92b8 1028
dfcf069d 1029static void
dc6f92b8
JB
1030XTset_terminal_modes ()
1031{
1032}
1033
06a2c219
GM
1034/* This is called when exiting or suspending Emacs. Exiting will make
1035 the X-windows go away, and suspending requires no action. */
dc6f92b8 1036
dfcf069d 1037static void
dc6f92b8
JB
1038XTreset_terminal_modes ()
1039{
dc6f92b8 1040}
06a2c219
GM
1041
1042
dc6f92b8 1043\f
06a2c219
GM
1044/***********************************************************************
1045 Output Cursor
1046 ***********************************************************************/
1047
1048/* Set the global variable output_cursor to CURSOR. All cursor
1049 positions are relative to updated_window. */
dc6f92b8 1050
dfcf069d 1051static void
06a2c219
GM
1052set_output_cursor (cursor)
1053 struct cursor_pos *cursor;
dc6f92b8 1054{
06a2c219
GM
1055 output_cursor.hpos = cursor->hpos;
1056 output_cursor.vpos = cursor->vpos;
1057 output_cursor.x = cursor->x;
1058 output_cursor.y = cursor->y;
1059}
1060
1061
1062/* Set a nominal cursor position.
dc6f92b8 1063
06a2c219
GM
1064 HPOS and VPOS are column/row positions in a window glyph matrix. X
1065 and Y are window text area relative pixel positions.
1066
1067 If this is done during an update, updated_window will contain the
1068 window that is being updated and the position is the future output
1069 cursor position for that window. If updated_window is null, use
1070 selected_window and display the cursor at the given position. */
1071
1072static void
1073XTcursor_to (vpos, hpos, y, x)
1074 int vpos, hpos, y, x;
1075{
1076 struct window *w;
1077
1078 /* If updated_window is not set, work on selected_window. */
1079 if (updated_window)
1080 w = updated_window;
1081 else
1082 w = XWINDOW (selected_window);
dbcb258a 1083
06a2c219
GM
1084 /* Set the output cursor. */
1085 output_cursor.hpos = hpos;
1086 output_cursor.vpos = vpos;
1087 output_cursor.x = x;
1088 output_cursor.y = y;
dc6f92b8 1089
06a2c219
GM
1090 /* If not called as part of an update, really display the cursor.
1091 This will also set the cursor position of W. */
1092 if (updated_window == NULL)
dc6f92b8
JB
1093 {
1094 BLOCK_INPUT;
06a2c219 1095 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1096 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1097 UNBLOCK_INPUT;
1098 }
1099}
dc43ef94 1100
06a2c219
GM
1101
1102\f
1103/***********************************************************************
1104 Display Iterator
1105 ***********************************************************************/
1106
1107/* Function prototypes of this page. */
1108
1109static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1110 struct glyph *,
ee569018
KH
1111 XChar2b *,
1112 int *));
06a2c219
GM
1113static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1114 int, XChar2b *, int));
1115static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1116static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1117static void x_append_glyph P_ ((struct it *));
b4192550 1118static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1119static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1120 int, int, double));
1121static void x_produce_glyphs P_ ((struct it *));
06a2c219 1122static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1123
1124
e2ef8ee6
GM
1125/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1126 is not contained in the font. */
dc43ef94 1127
06a2c219 1128static INLINE XCharStruct *
ee569018 1129x_per_char_metric (font, char2b)
06a2c219
GM
1130 XFontStruct *font;
1131 XChar2b *char2b;
1132{
1133 /* The result metric information. */
1134 XCharStruct *pcm = NULL;
dc6f92b8 1135
06a2c219 1136 xassert (font && char2b);
dc6f92b8 1137
06a2c219 1138 if (font->per_char != NULL)
dc6f92b8 1139 {
06a2c219 1140 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1141 {
06a2c219
GM
1142 /* min_char_or_byte2 specifies the linear character index
1143 corresponding to the first element of the per_char array,
1144 max_char_or_byte2 is the index of the last character. A
1145 character with non-zero CHAR2B->byte1 is not in the font.
1146 A character with byte2 less than min_char_or_byte2 or
1147 greater max_char_or_byte2 is not in the font. */
1148 if (char2b->byte1 == 0
1149 && char2b->byte2 >= font->min_char_or_byte2
1150 && char2b->byte2 <= font->max_char_or_byte2)
1151 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1152 }
06a2c219 1153 else
dc6f92b8 1154 {
06a2c219
GM
1155 /* If either min_byte1 or max_byte1 are nonzero, both
1156 min_char_or_byte2 and max_char_or_byte2 are less than
1157 256, and the 2-byte character index values corresponding
1158 to the per_char array element N (counting from 0) are:
1159
1160 byte1 = N/D + min_byte1
1161 byte2 = N\D + min_char_or_byte2
1162
1163 where:
1164
1165 D = max_char_or_byte2 - min_char_or_byte2 + 1
1166 / = integer division
1167 \ = integer modulus */
1168 if (char2b->byte1 >= font->min_byte1
1169 && char2b->byte1 <= font->max_byte1
1170 && char2b->byte2 >= font->min_char_or_byte2
1171 && char2b->byte2 <= font->max_char_or_byte2)
1172 {
1173 pcm = (font->per_char
1174 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1175 * (char2b->byte1 - font->min_byte1))
1176 + (char2b->byte2 - font->min_char_or_byte2));
1177 }
dc6f92b8 1178 }
06a2c219
GM
1179 }
1180 else
1181 {
1182 /* If the per_char pointer is null, all glyphs between the first
1183 and last character indexes inclusive have the same
1184 information, as given by both min_bounds and max_bounds. */
1185 if (char2b->byte2 >= font->min_char_or_byte2
1186 && char2b->byte2 <= font->max_char_or_byte2)
1187 pcm = &font->max_bounds;
1188 }
dc6f92b8 1189
ee569018 1190 return ((pcm == NULL
3e71d8f2 1191 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1192 ? NULL : pcm);
06a2c219 1193}
b73b6aaf 1194
57b03282 1195
06a2c219
GM
1196/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1197 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1198
06a2c219
GM
1199static INLINE void
1200x_encode_char (c, char2b, font_info)
1201 int c;
1202 XChar2b *char2b;
1203 struct font_info *font_info;
1204{
1205 int charset = CHAR_CHARSET (c);
1206 XFontStruct *font = font_info->font;
1207
1208 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1209 This may be either a program in a special encoder language or a
1210 fixed encoding. */
1211 if (font_info->font_encoder)
1212 {
1213 /* It's a program. */
1214 struct ccl_program *ccl = font_info->font_encoder;
1215
1216 if (CHARSET_DIMENSION (charset) == 1)
1217 {
1218 ccl->reg[0] = charset;
1219 ccl->reg[1] = char2b->byte2;
1220 }
1221 else
1222 {
1223 ccl->reg[0] = charset;
1224 ccl->reg[1] = char2b->byte1;
1225 ccl->reg[2] = char2b->byte2;
1226 }
1227
1228 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1229
1230 /* We assume that MSBs are appropriately set/reset by CCL
1231 program. */
1232 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1233 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1234 else
1235 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1236 }
1237 else if (font_info->encoding[charset])
1238 {
1239 /* Fixed encoding scheme. See fontset.h for the meaning of the
1240 encoding numbers. */
1241 int enc = font_info->encoding[charset];
1242
1243 if ((enc == 1 || enc == 2)
1244 && CHARSET_DIMENSION (charset) == 2)
1245 char2b->byte1 |= 0x80;
1246
1247 if (enc == 1 || enc == 3)
1248 char2b->byte2 |= 0x80;
1249 }
1250}
1251
1252
1253/* Get face and two-byte form of character C in face FACE_ID on frame
1254 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1255 means we want to display multibyte text. Value is a pointer to a
1256 realized face that is ready for display. */
1257
1258static INLINE struct face *
1259x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1260 struct frame *f;
1261 int c, face_id;
1262 XChar2b *char2b;
1263 int multibyte_p;
1264{
1265 struct face *face = FACE_FROM_ID (f, face_id);
1266
1267 if (!multibyte_p)
1268 {
1269 /* Unibyte case. We don't have to encode, but we have to make
1270 sure to use a face suitable for unibyte. */
1271 char2b->byte1 = 0;
1272 char2b->byte2 = c;
ee569018
KH
1273 face_id = FACE_FOR_CHAR (f, face, c);
1274 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1275 }
1276 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1277 {
1278 /* Case of ASCII in a face known to fit ASCII. */
1279 char2b->byte1 = 0;
1280 char2b->byte2 = c;
1281 }
1282 else
1283 {
1284 int c1, c2, charset;
1285
1286 /* Split characters into bytes. If c2 is -1 afterwards, C is
1287 really a one-byte character so that byte1 is zero. */
1288 SPLIT_CHAR (c, charset, c1, c2);
1289 if (c2 > 0)
1290 char2b->byte1 = c1, char2b->byte2 = c2;
1291 else
1292 char2b->byte1 = 0, char2b->byte2 = c1;
1293
06a2c219 1294 /* Maybe encode the character in *CHAR2B. */
ee569018 1295 if (face->font != NULL)
06a2c219
GM
1296 {
1297 struct font_info *font_info
1298 = FONT_INFO_FROM_ID (f, face->font_info_id);
1299 if (font_info)
ee569018 1300 x_encode_char (c, char2b, font_info);
06a2c219
GM
1301 }
1302 }
1303
1304 /* Make sure X resources of the face are allocated. */
1305 xassert (face != NULL);
1306 PREPARE_FACE_FOR_DISPLAY (f, face);
1307
1308 return face;
1309}
1310
1311
1312/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1313 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1314 a pointer to a realized face that is ready for display. */
1315
1316static INLINE struct face *
ee569018 1317x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1318 struct frame *f;
1319 struct glyph *glyph;
1320 XChar2b *char2b;
ee569018 1321 int *two_byte_p;
06a2c219
GM
1322{
1323 struct face *face;
1324
1325 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1326 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1327
ee569018
KH
1328 if (two_byte_p)
1329 *two_byte_p = 0;
1330
06a2c219
GM
1331 if (!glyph->multibyte_p)
1332 {
1333 /* Unibyte case. We don't have to encode, but we have to make
1334 sure to use a face suitable for unibyte. */
1335 char2b->byte1 = 0;
43d120d8 1336 char2b->byte2 = glyph->u.ch;
06a2c219 1337 }
43d120d8
KH
1338 else if (glyph->u.ch < 128
1339 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1340 {
1341 /* Case of ASCII in a face known to fit ASCII. */
1342 char2b->byte1 = 0;
43d120d8 1343 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1344 }
1345 else
1346 {
1347 int c1, c2, charset;
1348
1349 /* Split characters into bytes. If c2 is -1 afterwards, C is
1350 really a one-byte character so that byte1 is zero. */
43d120d8 1351 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1352 if (c2 > 0)
1353 char2b->byte1 = c1, char2b->byte2 = c2;
1354 else
1355 char2b->byte1 = 0, char2b->byte2 = c1;
1356
1357 /* Maybe encode the character in *CHAR2B. */
1358 if (charset != CHARSET_ASCII)
1359 {
1360 struct font_info *font_info
1361 = FONT_INFO_FROM_ID (f, face->font_info_id);
1362 if (font_info)
1363 {
43d120d8 1364 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1365 if (two_byte_p)
1366 *two_byte_p
1367 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1368 }
1369 }
1370 }
1371
1372 /* Make sure X resources of the face are allocated. */
1373 xassert (face != NULL);
1374 PREPARE_FACE_FOR_DISPLAY (f, face);
1375 return face;
1376}
1377
1378
1379/* Store one glyph for IT->char_to_display in IT->glyph_row.
1380 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1381
1382static INLINE void
1383x_append_glyph (it)
1384 struct it *it;
1385{
1386 struct glyph *glyph;
1387 enum glyph_row_area area = it->area;
1388
1389 xassert (it->glyph_row);
1390 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1391
1392 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1393 if (glyph < it->glyph_row->glyphs[area + 1])
1394 {
06a2c219
GM
1395 glyph->charpos = CHARPOS (it->position);
1396 glyph->object = it->object;
88d75730 1397 glyph->pixel_width = it->pixel_width;
06a2c219 1398 glyph->voffset = it->voffset;
88d75730 1399 glyph->type = CHAR_GLYPH;
06a2c219 1400 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1401 glyph->left_box_line_p = it->start_of_box_run_p;
1402 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1403 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1404 || it->phys_descent > it->descent);
88d75730 1405 glyph->padding_p = 0;
ee569018 1406 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1407 glyph->face_id = it->face_id;
1408 glyph->u.ch = it->char_to_display;
06a2c219
GM
1409 ++it->glyph_row->used[area];
1410 }
1411}
1412
b4192550
KH
1413/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1414 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1415
1416static INLINE void
1417x_append_composite_glyph (it)
1418 struct it *it;
1419{
1420 struct glyph *glyph;
1421 enum glyph_row_area area = it->area;
1422
1423 xassert (it->glyph_row);
1424
1425 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1426 if (glyph < it->glyph_row->glyphs[area + 1])
1427 {
b4192550
KH
1428 glyph->charpos = CHARPOS (it->position);
1429 glyph->object = it->object;
88d75730 1430 glyph->pixel_width = it->pixel_width;
b4192550 1431 glyph->voffset = it->voffset;
88d75730 1432 glyph->type = COMPOSITE_GLYPH;
b4192550 1433 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1434 glyph->left_box_line_p = it->start_of_box_run_p;
1435 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1436 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1437 || it->phys_descent > it->descent);
88d75730
GM
1438 glyph->padding_p = 0;
1439 glyph->glyph_not_available_p = 0;
1440 glyph->face_id = it->face_id;
1441 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1442 ++it->glyph_row->used[area];
1443 }
1444}
1445
06a2c219
GM
1446
1447/* Change IT->ascent and IT->height according to the setting of
1448 IT->voffset. */
1449
1450static INLINE void
1451take_vertical_position_into_account (it)
1452 struct it *it;
1453{
1454 if (it->voffset)
1455 {
1456 if (it->voffset < 0)
1457 /* Increase the ascent so that we can display the text higher
1458 in the line. */
1459 it->ascent += abs (it->voffset);
1460 else
1461 /* Increase the descent so that we can display the text lower
1462 in the line. */
1463 it->descent += it->voffset;
1464 }
1465}
1466
1467
1468/* Produce glyphs/get display metrics for the image IT is loaded with.
1469 See the description of struct display_iterator in dispextern.h for
1470 an overview of struct display_iterator. */
1471
1472static void
1473x_produce_image_glyph (it)
1474 struct it *it;
1475{
1476 struct image *img;
1477 struct face *face;
1478
1479 xassert (it->what == IT_IMAGE);
1480
1481 face = FACE_FROM_ID (it->f, it->face_id);
1482 img = IMAGE_FROM_ID (it->f, it->image_id);
1483 xassert (img);
1484
1485 /* Make sure X resources of the face and image are loaded. */
1486 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1487 prepare_image_for_display (it->f, img);
1488
95af8492 1489 it->ascent = it->phys_ascent = image_ascent (img, face);
22d650b8
GM
1490 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1491 it->pixel_width = img->width + 2 * img->hmargin;
06a2c219
GM
1492
1493 it->nglyphs = 1;
1494
1495 if (face->box != FACE_NO_BOX)
1496 {
ea2ba0d4
KH
1497 if (face->box_line_width > 0)
1498 {
1499 it->ascent += face->box_line_width;
1500 it->descent += face->box_line_width;
1501 }
06a2c219
GM
1502
1503 if (it->start_of_box_run_p)
ea2ba0d4 1504 it->pixel_width += abs (face->box_line_width);
06a2c219 1505 if (it->end_of_box_run_p)
ea2ba0d4 1506 it->pixel_width += abs (face->box_line_width);
06a2c219
GM
1507 }
1508
1509 take_vertical_position_into_account (it);
1510
1511 if (it->glyph_row)
1512 {
1513 struct glyph *glyph;
1514 enum glyph_row_area area = it->area;
1515
1516 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1517 if (glyph < it->glyph_row->glyphs[area + 1])
1518 {
06a2c219
GM
1519 glyph->charpos = CHARPOS (it->position);
1520 glyph->object = it->object;
88d75730 1521 glyph->pixel_width = it->pixel_width;
06a2c219 1522 glyph->voffset = it->voffset;
88d75730 1523 glyph->type = IMAGE_GLYPH;
06a2c219 1524 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1525 glyph->left_box_line_p = it->start_of_box_run_p;
1526 glyph->right_box_line_p = it->end_of_box_run_p;
1527 glyph->overlaps_vertically_p = 0;
1528 glyph->padding_p = 0;
1529 glyph->glyph_not_available_p = 0;
1530 glyph->face_id = it->face_id;
1531 glyph->u.img_id = img->id;
06a2c219
GM
1532 ++it->glyph_row->used[area];
1533 }
1534 }
1535}
1536
1537
1538/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1539 of the glyph, WIDTH and HEIGHT are the width and height of the
1540 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1541 ascent of the glyph (0 <= ASCENT <= 1). */
1542
1543static void
1544x_append_stretch_glyph (it, object, width, height, ascent)
1545 struct it *it;
1546 Lisp_Object object;
1547 int width, height;
1548 double ascent;
1549{
1550 struct glyph *glyph;
1551 enum glyph_row_area area = it->area;
1552
1553 xassert (ascent >= 0 && ascent <= 1);
1554
1555 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1556 if (glyph < it->glyph_row->glyphs[area + 1])
1557 {
06a2c219
GM
1558 glyph->charpos = CHARPOS (it->position);
1559 glyph->object = object;
88d75730 1560 glyph->pixel_width = width;
06a2c219 1561 glyph->voffset = it->voffset;
88d75730 1562 glyph->type = STRETCH_GLYPH;
06a2c219 1563 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1564 glyph->left_box_line_p = it->start_of_box_run_p;
1565 glyph->right_box_line_p = it->end_of_box_run_p;
1566 glyph->overlaps_vertically_p = 0;
1567 glyph->padding_p = 0;
1568 glyph->glyph_not_available_p = 0;
1569 glyph->face_id = it->face_id;
1570 glyph->u.stretch.ascent = height * ascent;
1571 glyph->u.stretch.height = height;
06a2c219
GM
1572 ++it->glyph_row->used[area];
1573 }
1574}
1575
1576
1577/* Produce a stretch glyph for iterator IT. IT->object is the value
1578 of the glyph property displayed. The value must be a list
1579 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1580 being recognized:
1581
1582 1. `:width WIDTH' specifies that the space should be WIDTH *
1583 canonical char width wide. WIDTH may be an integer or floating
1584 point number.
1585
1586 2. `:relative-width FACTOR' specifies that the width of the stretch
1587 should be computed from the width of the first character having the
1588 `glyph' property, and should be FACTOR times that width.
1589
1590 3. `:align-to HPOS' specifies that the space should be wide enough
1591 to reach HPOS, a value in canonical character units.
1592
1593 Exactly one of the above pairs must be present.
1594
1595 4. `:height HEIGHT' specifies that the height of the stretch produced
1596 should be HEIGHT, measured in canonical character units.
1597
1598 5. `:relative-height FACTOR' specifies that the height of the the
1599 stretch should be FACTOR times the height of the characters having
1600 the glyph property.
1601
1602 Either none or exactly one of 4 or 5 must be present.
1603
1604 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1605 of the stretch should be used for the ascent of the stretch.
1606 ASCENT must be in the range 0 <= ASCENT <= 100. */
1607
1608#define NUMVAL(X) \
1609 ((INTEGERP (X) || FLOATP (X)) \
1610 ? XFLOATINT (X) \
1611 : - 1)
1612
1613
1614static void
1615x_produce_stretch_glyph (it)
1616 struct it *it;
1617{
1618 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1619#if GLYPH_DEBUG
1620 extern Lisp_Object Qspace;
1621#endif
1622 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1623 extern Lisp_Object QCrelative_width, QCrelative_height;
1624 extern Lisp_Object QCalign_to;
1625 Lisp_Object prop, plist;
1626 double width = 0, height = 0, ascent = 0;
1627 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1628 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1629
1630 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1631
1632 /* List should start with `space'. */
1633 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1634 plist = XCDR (it->object);
1635
1636 /* Compute the width of the stretch. */
1637 if (prop = Fplist_get (plist, QCwidth),
1638 NUMVAL (prop) > 0)
1639 /* Absolute width `:width WIDTH' specified and valid. */
1640 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1641 else if (prop = Fplist_get (plist, QCrelative_width),
1642 NUMVAL (prop) > 0)
1643 {
1644 /* Relative width `:relative-width FACTOR' specified and valid.
1645 Compute the width of the characters having the `glyph'
1646 property. */
1647 struct it it2;
1648 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1649
1650 it2 = *it;
1651 if (it->multibyte_p)
1652 {
1653 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1654 - IT_BYTEPOS (*it));
1655 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1656 }
1657 else
1658 it2.c = *p, it2.len = 1;
1659
1660 it2.glyph_row = NULL;
1661 it2.what = IT_CHARACTER;
1662 x_produce_glyphs (&it2);
1663 width = NUMVAL (prop) * it2.pixel_width;
1664 }
1665 else if (prop = Fplist_get (plist, QCalign_to),
1666 NUMVAL (prop) > 0)
1667 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1668 else
1669 /* Nothing specified -> width defaults to canonical char width. */
1670 width = CANON_X_UNIT (it->f);
1671
1672 /* Compute height. */
1673 if (prop = Fplist_get (plist, QCheight),
1674 NUMVAL (prop) > 0)
1675 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1676 else if (prop = Fplist_get (plist, QCrelative_height),
1677 NUMVAL (prop) > 0)
1678 height = FONT_HEIGHT (font) * NUMVAL (prop);
1679 else
1680 height = FONT_HEIGHT (font);
1681
1682 /* Compute percentage of height used for ascent. If
1683 `:ascent ASCENT' is present and valid, use that. Otherwise,
1684 derive the ascent from the font in use. */
1685 if (prop = Fplist_get (plist, QCascent),
1686 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1687 ascent = NUMVAL (prop) / 100.0;
1688 else
1689 ascent = (double) font->ascent / FONT_HEIGHT (font);
1690
1691 if (width <= 0)
1692 width = 1;
1693 if (height <= 0)
1694 height = 1;
1695
1696 if (it->glyph_row)
1697 {
1698 Lisp_Object object = it->stack[it->sp - 1].string;
1699 if (!STRINGP (object))
1700 object = it->w->buffer;
1701 x_append_stretch_glyph (it, object, width, height, ascent);
1702 }
1703
1704 it->pixel_width = width;
66ac4b0e
GM
1705 it->ascent = it->phys_ascent = height * ascent;
1706 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1707 it->nglyphs = 1;
1708
1709 if (face->box != FACE_NO_BOX)
1710 {
ea2ba0d4
KH
1711 if (face->box_line_width > 0)
1712 {
1713 it->ascent += face->box_line_width;
1714 it->descent += face->box_line_width;
1715 }
06a2c219
GM
1716
1717 if (it->start_of_box_run_p)
ea2ba0d4 1718 it->pixel_width += abs (face->box_line_width);
06a2c219 1719 if (it->end_of_box_run_p)
ea2ba0d4 1720 it->pixel_width += abs (face->box_line_width);
06a2c219
GM
1721 }
1722
1723 take_vertical_position_into_account (it);
1724}
1725
b4192550
KH
1726/* Return proper value to be used as baseline offset of font that has
1727 ASCENT and DESCENT to draw characters by the font at the vertical
1728 center of the line of frame F.
1729
1730 Here, out task is to find the value of BOFF in the following figure;
1731
1732 -------------------------+-----------+-
1733 -+-+---------+-+ | |
1734 | | | | | |
1735 | | | | F_ASCENT F_HEIGHT
1736 | | | ASCENT | |
1737 HEIGHT | | | | |
1738 | | |-|-+------+-----------|------- baseline
1739 | | | | BOFF | |
1740 | |---------|-+-+ | |
1741 | | | DESCENT | |
1742 -+-+---------+-+ F_DESCENT |
1743 -------------------------+-----------+-
1744
1745 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1746 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1747 DESCENT = FONT->descent
1748 HEIGHT = FONT_HEIGHT (FONT)
1749 F_DESCENT = (F->output_data.x->font->descent
1750 - F->output_data.x->baseline_offset)
1751 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1752*/
1753
458f45fa
KH
1754#define VCENTER_BASELINE_OFFSET(FONT, F) \
1755 ((FONT)->descent \
1756 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1757 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1758 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1759
1760/* Produce glyphs/get display metrics for the display element IT is
1761 loaded with. See the description of struct display_iterator in
1762 dispextern.h for an overview of struct display_iterator. */
1763
1764static void
1765x_produce_glyphs (it)
1766 struct it *it;
1767{
ee569018
KH
1768 it->glyph_not_available_p = 0;
1769
06a2c219
GM
1770 if (it->what == IT_CHARACTER)
1771 {
1772 XChar2b char2b;
1773 XFontStruct *font;
ee569018 1774 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1775 XCharStruct *pcm;
06a2c219 1776 int font_not_found_p;
b4192550
KH
1777 struct font_info *font_info;
1778 int boff; /* baseline offset */
a4249304
KH
1779 /* We may change it->multibyte_p upon unibyte<->multibyte
1780 conversion. So, save the current value now and restore it
1781 later.
1782
1783 Note: It seems that we don't have to record multibyte_p in
1784 struct glyph because the character code itself tells if or
1785 not the character is multibyte. Thus, in the future, we must
1786 consider eliminating the field `multibyte_p' in the struct
c347a1c3 1787 glyph. */
a4249304 1788 int saved_multibyte_p = it->multibyte_p;
06a2c219 1789
ee569018
KH
1790 /* Maybe translate single-byte characters to multibyte, or the
1791 other way. */
06a2c219 1792 it->char_to_display = it->c;
ee569018 1793 if (!ASCII_BYTE_P (it->c))
06a2c219 1794 {
ee569018
KH
1795 if (unibyte_display_via_language_environment
1796 && SINGLE_BYTE_CHAR_P (it->c)
1797 && (it->c >= 0240
1798 || !NILP (Vnonascii_translation_table)))
1799 {
1800 it->char_to_display = unibyte_char_to_multibyte (it->c);
a4249304 1801 it->multibyte_p = 1;
ee569018
KH
1802 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1803 face = FACE_FROM_ID (it->f, it->face_id);
1804 }
1805 else if (!SINGLE_BYTE_CHAR_P (it->c)
1806 && !it->multibyte_p)
1807 {
c347a1c3 1808 it->multibyte_p = 1;
ee569018
KH
1809 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1810 face = FACE_FROM_ID (it->f, it->face_id);
1811 }
06a2c219
GM
1812 }
1813
ee569018
KH
1814 /* Get font to use. Encode IT->char_to_display. */
1815 x_get_char_face_and_encoding (it->f, it->char_to_display,
1816 it->face_id, &char2b,
1817 it->multibyte_p);
06a2c219
GM
1818 font = face->font;
1819
1820 /* When no suitable font found, use the default font. */
1821 font_not_found_p = font == NULL;
1822 if (font_not_found_p)
b4192550
KH
1823 {
1824 font = FRAME_FONT (it->f);
1825 boff = it->f->output_data.x->baseline_offset;
1826 font_info = NULL;
1827 }
1828 else
1829 {
1830 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1831 boff = font_info->baseline_offset;
1832 if (font_info->vertical_centering)
1833 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1834 }
06a2c219
GM
1835
1836 if (it->char_to_display >= ' '
1837 && (!it->multibyte_p || it->char_to_display < 128))
1838 {
1839 /* Either unibyte or ASCII. */
1840 int stretched_p;
1841
1842 it->nglyphs = 1;
06a2c219
GM
1843
1844 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1845 it->ascent = font->ascent + boff;
1846 it->descent = font->descent - boff;
474848ac
GM
1847
1848 if (pcm)
1849 {
1850 it->phys_ascent = pcm->ascent + boff;
1851 it->phys_descent = pcm->descent - boff;
1852 it->pixel_width = pcm->width;
1853 }
1854 else
1855 {
1856 it->glyph_not_available_p = 1;
1857 it->phys_ascent = font->ascent + boff;
1858 it->phys_descent = font->descent - boff;
1859 it->pixel_width = FONT_WIDTH (font);
1860 }
06a2c219
GM
1861
1862 /* If this is a space inside a region of text with
1863 `space-width' property, change its width. */
1864 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1865 if (stretched_p)
1866 it->pixel_width *= XFLOATINT (it->space_width);
1867
1868 /* If face has a box, add the box thickness to the character
1869 height. If character has a box line to the left and/or
1870 right, add the box line width to the character's width. */
1871 if (face->box != FACE_NO_BOX)
1872 {
1873 int thick = face->box_line_width;
1874
ea2ba0d4
KH
1875 if (thick > 0)
1876 {
1877 it->ascent += thick;
1878 it->descent += thick;
1879 }
1880 else
1881 thick = -thick;
1882
06a2c219
GM
1883 if (it->start_of_box_run_p)
1884 it->pixel_width += thick;
1885 if (it->end_of_box_run_p)
1886 it->pixel_width += thick;
1887 }
1888
1889 /* If face has an overline, add the height of the overline
1890 (1 pixel) and a 1 pixel margin to the character height. */
1891 if (face->overline_p)
1892 it->ascent += 2;
1893
1894 take_vertical_position_into_account (it);
1895
1896 /* If we have to actually produce glyphs, do it. */
1897 if (it->glyph_row)
1898 {
1899 if (stretched_p)
1900 {
1901 /* Translate a space with a `space-width' property
1902 into a stretch glyph. */
1903 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1904 x_append_stretch_glyph (it, it->object, it->pixel_width,
1905 it->ascent + it->descent, ascent);
1906 }
1907 else
1908 x_append_glyph (it);
1909
1910 /* If characters with lbearing or rbearing are displayed
1911 in this line, record that fact in a flag of the
1912 glyph row. This is used to optimize X output code. */
1c7e22fd 1913 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1914 it->glyph_row->contains_overlapping_glyphs_p = 1;
1915 }
1916 }
1917 else if (it->char_to_display == '\n')
1918 {
1919 /* A newline has no width but we need the height of the line. */
1920 it->pixel_width = 0;
1921 it->nglyphs = 0;
b4192550
KH
1922 it->ascent = it->phys_ascent = font->ascent + boff;
1923 it->descent = it->phys_descent = font->descent - boff;
06a2c219 1924
ea2ba0d4
KH
1925 if (face->box != FACE_NO_BOX
1926 && face->box_line_width > 0)
06a2c219 1927 {
ea2ba0d4
KH
1928 it->ascent += face->box_line_width;
1929 it->descent += face->box_line_width;
06a2c219
GM
1930 }
1931 }
1932 else if (it->char_to_display == '\t')
1933 {
1934 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1935 int x = it->current_x + it->continuation_lines_width;
06a2c219 1936 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2a32b5ea
GM
1937
1938 /* If the distance from the current position to the next tab
1939 stop is less than a canonical character width, use the
1940 tab stop after that. */
1941 if (next_tab_x - x < CANON_X_UNIT (it->f))
1942 next_tab_x += tab_width;
06a2c219
GM
1943
1944 it->pixel_width = next_tab_x - x;
1945 it->nglyphs = 1;
b4192550
KH
1946 it->ascent = it->phys_ascent = font->ascent + boff;
1947 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1948
1949 if (it->glyph_row)
1950 {
1951 double ascent = (double) it->ascent / (it->ascent + it->descent);
1952 x_append_stretch_glyph (it, it->object, it->pixel_width,
1953 it->ascent + it->descent, ascent);
1954 }
1955 }
1956 else
1957 {
1958 /* A multi-byte character. Assume that the display width of the
1959 character is the width of the character multiplied by the
b4192550 1960 width of the font. */
06a2c219 1961
b4192550
KH
1962 /* If we found a font, this font should give us the right
1963 metrics. If we didn't find a font, use the frame's
1964 default font and calculate the width of the character
1965 from the charset width; this is what old redisplay code
1966 did. */
1967 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1968 if (font_not_found_p || !pcm)
1969 {
1970 int charset = CHAR_CHARSET (it->char_to_display);
1971
1972 it->glyph_not_available_p = 1;
1973 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1974 * CHARSET_WIDTH (charset));
1975 it->phys_ascent = font->ascent + boff;
1976 it->phys_descent = font->descent - boff;
1977 }
1978 else
1979 {
1980 it->pixel_width = pcm->width;
1981 it->phys_ascent = pcm->ascent + boff;
1982 it->phys_descent = pcm->descent - boff;
1983 if (it->glyph_row
1984 && (pcm->lbearing < 0
1985 || pcm->rbearing > pcm->width))
1986 it->glyph_row->contains_overlapping_glyphs_p = 1;
1987 }
b4192550
KH
1988 it->nglyphs = 1;
1989 it->ascent = font->ascent + boff;
1990 it->descent = font->descent - boff;
06a2c219
GM
1991 if (face->box != FACE_NO_BOX)
1992 {
1993 int thick = face->box_line_width;
ea2ba0d4
KH
1994
1995 if (thick > 0)
1996 {
1997 it->ascent += thick;
1998 it->descent += thick;
1999 }
2000 else
2001 thick = - thick;
06a2c219
GM
2002
2003 if (it->start_of_box_run_p)
2004 it->pixel_width += thick;
2005 if (it->end_of_box_run_p)
2006 it->pixel_width += thick;
2007 }
2008
2009 /* If face has an overline, add the height of the overline
2010 (1 pixel) and a 1 pixel margin to the character height. */
2011 if (face->overline_p)
2012 it->ascent += 2;
2013
2014 take_vertical_position_into_account (it);
2015
2016 if (it->glyph_row)
2017 x_append_glyph (it);
2018 }
a4249304 2019 it->multibyte_p = saved_multibyte_p;
06a2c219 2020 }
b4192550
KH
2021 else if (it->what == IT_COMPOSITION)
2022 {
2023 /* Note: A composition is represented as one glyph in the
2024 glyph matrix. There are no padding glyphs. */
2025 XChar2b char2b;
2026 XFontStruct *font;
ee569018 2027 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2028 XCharStruct *pcm;
2029 int font_not_found_p;
2030 struct font_info *font_info;
2031 int boff; /* baseline offset */
2032 struct composition *cmp = composition_table[it->cmp_id];
2033
2034 /* Maybe translate single-byte characters to multibyte. */
2035 it->char_to_display = it->c;
2036 if (unibyte_display_via_language_environment
2037 && SINGLE_BYTE_CHAR_P (it->c)
2038 && (it->c >= 0240
2039 || (it->c >= 0200
2040 && !NILP (Vnonascii_translation_table))))
2041 {
2042 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2043 }
2044
2045 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2046 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2047 face = FACE_FROM_ID (it->f, it->face_id);
2048 x_get_char_face_and_encoding (it->f, it->char_to_display,
2049 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2050 font = face->font;
2051
2052 /* When no suitable font found, use the default font. */
2053 font_not_found_p = font == NULL;
2054 if (font_not_found_p)
2055 {
2056 font = FRAME_FONT (it->f);
2057 boff = it->f->output_data.x->baseline_offset;
2058 font_info = NULL;
2059 }
2060 else
2061 {
2062 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2063 boff = font_info->baseline_offset;
2064 if (font_info->vertical_centering)
2065 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2066 }
2067
2068 /* There are no padding glyphs, so there is only one glyph to
2069 produce for the composition. Important is that pixel_width,
2070 ascent and descent are the values of what is drawn by
2071 draw_glyphs (i.e. the values of the overall glyphs composed). */
2072 it->nglyphs = 1;
2073
2074 /* If we have not yet calculated pixel size data of glyphs of
2075 the composition for the current face font, calculate them
2076 now. Theoretically, we have to check all fonts for the
2077 glyphs, but that requires much time and memory space. So,
2078 here we check only the font of the first glyph. This leads
2079 to incorrect display very rarely, and C-l (recenter) can
2080 correct the display anyway. */
2081 if (cmp->font != (void *) font)
2082 {
2083 /* Ascent and descent of the font of the first character of
2084 this composition (adjusted by baseline offset). Ascent
2085 and descent of overall glyphs should not be less than
2086 them respectively. */
2087 int font_ascent = font->ascent + boff;
2088 int font_descent = font->descent - boff;
2089 /* Bounding box of the overall glyphs. */
2090 int leftmost, rightmost, lowest, highest;
329bed06 2091 int i, width, ascent, descent;
b4192550
KH
2092
2093 cmp->font = (void *) font;
2094
2095 /* Initialize the bounding box. */
1bdeec2e
KH
2096 if (font_info
2097 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2098 {
2099 width = pcm->width;
2100 ascent = pcm->ascent;
2101 descent = pcm->descent;
2102 }
2103 else
2104 {
2105 width = FONT_WIDTH (font);
2106 ascent = font->ascent;
2107 descent = font->descent;
2108 }
2109
2110 rightmost = width;
2111 lowest = - descent + boff;
2112 highest = ascent + boff;
b4192550 2113 leftmost = 0;
329bed06 2114
b4192550
KH
2115 if (font_info
2116 && font_info->default_ascent
2117 && CHAR_TABLE_P (Vuse_default_ascent)
2118 && !NILP (Faref (Vuse_default_ascent,
2119 make_number (it->char_to_display))))
2120 highest = font_info->default_ascent + boff;
2121
2122 /* Draw the first glyph at the normal position. It may be
2123 shifted to right later if some other glyphs are drawn at
2124 the left. */
2125 cmp->offsets[0] = 0;
2126 cmp->offsets[1] = boff;
2127
2128 /* Set cmp->offsets for the remaining glyphs. */
2129 for (i = 1; i < cmp->glyph_len; i++)
2130 {
2131 int left, right, btm, top;
2132 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2133 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2134
2135 face = FACE_FROM_ID (it->f, face_id);
2136 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2137 it->multibyte_p);
b4192550
KH
2138 font = face->font;
2139 if (font == NULL)
2140 {
2141 font = FRAME_FONT (it->f);
2142 boff = it->f->output_data.x->baseline_offset;
2143 font_info = NULL;
2144 }
2145 else
2146 {
2147 font_info
2148 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2149 boff = font_info->baseline_offset;
2150 if (font_info->vertical_centering)
2151 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2152 }
2153
1bdeec2e
KH
2154 if (font_info
2155 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2156 {
2157 width = pcm->width;
2158 ascent = pcm->ascent;
2159 descent = pcm->descent;
2160 }
2161 else
2162 {
2163 width = FONT_WIDTH (font);
1bdeec2e
KH
2164 ascent = 1;
2165 descent = 0;
329bed06 2166 }
b4192550
KH
2167
2168 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2169 {
2170 /* Relative composition with or without
2171 alternate chars. */
329bed06
GM
2172 left = (leftmost + rightmost - width) / 2;
2173 btm = - descent + boff;
b4192550
KH
2174 if (font_info && font_info->relative_compose
2175 && (! CHAR_TABLE_P (Vignore_relative_composition)
2176 || NILP (Faref (Vignore_relative_composition,
2177 make_number (ch)))))
2178 {
2179
329bed06 2180 if (- descent >= font_info->relative_compose)
b4192550
KH
2181 /* One extra pixel between two glyphs. */
2182 btm = highest + 1;
329bed06 2183 else if (ascent <= 0)
b4192550 2184 /* One extra pixel between two glyphs. */
329bed06 2185 btm = lowest - 1 - ascent - descent;
b4192550
KH
2186 }
2187 }
2188 else
2189 {
2190 /* A composition rule is specified by an integer
2191 value that encodes global and new reference
2192 points (GREF and NREF). GREF and NREF are
2193 specified by numbers as below:
2194
2195 0---1---2 -- ascent
2196 | |
2197 | |
2198 | |
2199 9--10--11 -- center
2200 | |
2201 ---3---4---5--- baseline
2202 | |
2203 6---7---8 -- descent
2204 */
2205 int rule = COMPOSITION_RULE (cmp, i);
2206 int gref, nref, grefx, grefy, nrefx, nrefy;
2207
2208 COMPOSITION_DECODE_RULE (rule, gref, nref);
2209 grefx = gref % 3, nrefx = nref % 3;
2210 grefy = gref / 3, nrefy = nref / 3;
2211
2212 left = (leftmost
2213 + grefx * (rightmost - leftmost) / 2
329bed06 2214 - nrefx * width / 2);
b4192550
KH
2215 btm = ((grefy == 0 ? highest
2216 : grefy == 1 ? 0
2217 : grefy == 2 ? lowest
2218 : (highest + lowest) / 2)
329bed06
GM
2219 - (nrefy == 0 ? ascent + descent
2220 : nrefy == 1 ? descent - boff
b4192550 2221 : nrefy == 2 ? 0
329bed06 2222 : (ascent + descent) / 2));
b4192550
KH
2223 }
2224
2225 cmp->offsets[i * 2] = left;
329bed06 2226 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2227
2228 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2229 right = left + width;
2230 top = btm + descent + ascent;
b4192550
KH
2231 if (left < leftmost)
2232 leftmost = left;
2233 if (right > rightmost)
2234 rightmost = right;
2235 if (top > highest)
2236 highest = top;
2237 if (btm < lowest)
2238 lowest = btm;
2239 }
2240
2241 /* If there are glyphs whose x-offsets are negative,
2242 shift all glyphs to the right and make all x-offsets
2243 non-negative. */
2244 if (leftmost < 0)
2245 {
2246 for (i = 0; i < cmp->glyph_len; i++)
2247 cmp->offsets[i * 2] -= leftmost;
2248 rightmost -= leftmost;
2249 }
2250
2251 cmp->pixel_width = rightmost;
2252 cmp->ascent = highest;
2253 cmp->descent = - lowest;
2254 if (cmp->ascent < font_ascent)
2255 cmp->ascent = font_ascent;
2256 if (cmp->descent < font_descent)
2257 cmp->descent = font_descent;
2258 }
2259
2260 it->pixel_width = cmp->pixel_width;
2261 it->ascent = it->phys_ascent = cmp->ascent;
2262 it->descent = it->phys_descent = cmp->descent;
2263
2264 if (face->box != FACE_NO_BOX)
2265 {
2266 int thick = face->box_line_width;
ea2ba0d4
KH
2267
2268 if (thick > 0)
2269 {
2270 it->ascent += thick;
2271 it->descent += thick;
2272 }
2273 else
2274 thick = - thick;
b4192550
KH
2275
2276 if (it->start_of_box_run_p)
2277 it->pixel_width += thick;
2278 if (it->end_of_box_run_p)
2279 it->pixel_width += thick;
2280 }
2281
2282 /* If face has an overline, add the height of the overline
2283 (1 pixel) and a 1 pixel margin to the character height. */
2284 if (face->overline_p)
2285 it->ascent += 2;
2286
2287 take_vertical_position_into_account (it);
2288
2289 if (it->glyph_row)
2290 x_append_composite_glyph (it);
2291 }
06a2c219
GM
2292 else if (it->what == IT_IMAGE)
2293 x_produce_image_glyph (it);
2294 else if (it->what == IT_STRETCH)
2295 x_produce_stretch_glyph (it);
2296
3017fdd1
GM
2297 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2298 because this isn't true for images with `:ascent 100'. */
2299 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2300 if (it->area == TEXT_AREA)
2301 it->current_x += it->pixel_width;
66ac4b0e 2302
d365f5bb
GM
2303 it->descent += it->extra_line_spacing;
2304
06a2c219
GM
2305 it->max_ascent = max (it->max_ascent, it->ascent);
2306 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2307 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2308 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2309}
2310
2311
2312/* Estimate the pixel height of the mode or top line on frame F.
2313 FACE_ID specifies what line's height to estimate. */
2314
2315int
2316x_estimate_mode_line_height (f, face_id)
2317 struct frame *f;
2318 enum face_id face_id;
2319{
43281ee3 2320 int height = FONT_HEIGHT (FRAME_FONT (f));
06a2c219
GM
2321
2322 /* This function is called so early when Emacs starts that the face
2323 cache and mode line face are not yet initialized. */
2324 if (FRAME_FACE_CACHE (f))
2325 {
2326 struct face *face = FACE_FROM_ID (f, face_id);
2327 if (face)
43281ee3
GM
2328 {
2329 if (face->font)
2330 height = FONT_HEIGHT (face->font);
ea2ba0d4
KH
2331 if (face->box_line_width > 0)
2332 height += 2 * face->box_line_width;
43281ee3 2333 }
06a2c219
GM
2334 }
2335
2336 return height;
2337}
2338
2339\f
2340/***********************************************************************
2341 Glyph display
2342 ***********************************************************************/
2343
2344/* A sequence of glyphs to be drawn in the same face.
2345
2346 This data structure is not really completely X specific, so it
2347 could possibly, at least partially, be useful for other systems. It
2348 is currently not part of the external redisplay interface because
2349 it's not clear what other systems will need. */
2350
2351struct glyph_string
2352{
2353 /* X-origin of the string. */
2354 int x;
2355
2356 /* Y-origin and y-position of the base line of this string. */
2357 int y, ybase;
2358
2359 /* The width of the string, not including a face extension. */
2360 int width;
2361
2362 /* The width of the string, including a face extension. */
2363 int background_width;
2364
2365 /* The height of this string. This is the height of the line this
2366 string is drawn in, and can be different from the height of the
2367 font the string is drawn in. */
2368 int height;
2369
2370 /* Number of pixels this string overwrites in front of its x-origin.
2371 This number is zero if the string has an lbearing >= 0; it is
2372 -lbearing, if the string has an lbearing < 0. */
2373 int left_overhang;
2374
2375 /* Number of pixels this string overwrites past its right-most
2376 nominal x-position, i.e. x + width. Zero if the string's
2377 rbearing is <= its nominal width, rbearing - width otherwise. */
2378 int right_overhang;
2379
2380 /* The frame on which the glyph string is drawn. */
2381 struct frame *f;
2382
2383 /* The window on which the glyph string is drawn. */
2384 struct window *w;
2385
2386 /* X display and window for convenience. */
2387 Display *display;
2388 Window window;
2389
2390 /* The glyph row for which this string was built. It determines the
2391 y-origin and height of the string. */
2392 struct glyph_row *row;
2393
2394 /* The area within row. */
2395 enum glyph_row_area area;
2396
2397 /* Characters to be drawn, and number of characters. */
2398 XChar2b *char2b;
2399 int nchars;
2400
06a2c219
GM
2401 /* A face-override for drawing cursors, mouse face and similar. */
2402 enum draw_glyphs_face hl;
2403
2404 /* Face in which this string is to be drawn. */
2405 struct face *face;
2406
2407 /* Font in which this string is to be drawn. */
2408 XFontStruct *font;
2409
2410 /* Font info for this string. */
2411 struct font_info *font_info;
2412
b4192550
KH
2413 /* Non-null means this string describes (part of) a composition.
2414 All characters from char2b are drawn composed. */
2415 struct composition *cmp;
06a2c219
GM
2416
2417 /* Index of this glyph string's first character in the glyph
b4192550
KH
2418 definition of CMP. If this is zero, this glyph string describes
2419 the first character of a composition. */
06a2c219
GM
2420 int gidx;
2421
2422 /* 1 means this glyph strings face has to be drawn to the right end
2423 of the window's drawing area. */
2424 unsigned extends_to_end_of_line_p : 1;
2425
2426 /* 1 means the background of this string has been drawn. */
2427 unsigned background_filled_p : 1;
2428
2429 /* 1 means glyph string must be drawn with 16-bit functions. */
2430 unsigned two_byte_p : 1;
2431
2432 /* 1 means that the original font determined for drawing this glyph
2433 string could not be loaded. The member `font' has been set to
2434 the frame's default font in this case. */
2435 unsigned font_not_found_p : 1;
2436
2437 /* 1 means that the face in which this glyph string is drawn has a
2438 stipple pattern. */
2439 unsigned stippled_p : 1;
2440
66ac4b0e
GM
2441 /* 1 means only the foreground of this glyph string must be drawn,
2442 and we should use the physical height of the line this glyph
2443 string appears in as clip rect. */
2444 unsigned for_overlaps_p : 1;
2445
06a2c219
GM
2446 /* The GC to use for drawing this glyph string. */
2447 GC gc;
2448
2449 /* A pointer to the first glyph in the string. This glyph
2450 corresponds to char2b[0]. Needed to draw rectangles if
2451 font_not_found_p is 1. */
2452 struct glyph *first_glyph;
2453
2454 /* Image, if any. */
2455 struct image *img;
2456
2457 struct glyph_string *next, *prev;
2458};
2459
2460
61869b99 2461#if GLYPH_DEBUG
06a2c219
GM
2462
2463static void
2464x_dump_glyph_string (s)
2465 struct glyph_string *s;
2466{
2467 fprintf (stderr, "glyph string\n");
2468 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2469 s->x, s->y, s->width, s->height);
2470 fprintf (stderr, " ybase = %d\n", s->ybase);
2471 fprintf (stderr, " hl = %d\n", s->hl);
2472 fprintf (stderr, " left overhang = %d, right = %d\n",
2473 s->left_overhang, s->right_overhang);
2474 fprintf (stderr, " nchars = %d\n", s->nchars);
2475 fprintf (stderr, " extends to end of line = %d\n",
2476 s->extends_to_end_of_line_p);
2477 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2478 fprintf (stderr, " bg width = %d\n", s->background_width);
2479}
2480
2481#endif /* GLYPH_DEBUG */
2482
2483
2484
2485static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2486 struct glyph_string **,
2487 struct glyph_string *,
2488 struct glyph_string *));
2489static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2490 struct glyph_string **,
2491 struct glyph_string *,
2492 struct glyph_string *));
2493static void x_append_glyph_string P_ ((struct glyph_string **,
2494 struct glyph_string **,
2495 struct glyph_string *));
2496static int x_left_overwritten P_ ((struct glyph_string *));
2497static int x_left_overwriting P_ ((struct glyph_string *));
2498static int x_right_overwritten P_ ((struct glyph_string *));
2499static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2500static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2501 int));
06a2c219
GM
2502static void x_init_glyph_string P_ ((struct glyph_string *,
2503 XChar2b *, struct window *,
2504 struct glyph_row *,
2505 enum glyph_row_area, int,
2506 enum draw_glyphs_face));
2507static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2508 enum glyph_row_area, int, int,
f0a48a01 2509 enum draw_glyphs_face, int));
06a2c219
GM
2510static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2511static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2512static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2513 int));
2514static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2515static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2516static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2517static void x_draw_glyph_string P_ ((struct glyph_string *));
2518static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2519static void x_set_cursor_gc P_ ((struct glyph_string *));
2520static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2521static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2522static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2523 int *, int *));
2524static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2525static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2526 unsigned long *, double, int));
06a2c219 2527static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2528 double, int, unsigned long));
06a2c219
GM
2529static void x_setup_relief_colors P_ ((struct glyph_string *));
2530static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2531static void x_draw_image_relief P_ ((struct glyph_string *));
2532static void x_draw_image_foreground P_ ((struct glyph_string *));
2533static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2534static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2535static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2536 int, int, int));
2537static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2538 int, int, int, int, XRectangle *));
2539static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2540 int, int, int, XRectangle *));
66ac4b0e
GM
2541static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2542 enum glyph_row_area));
209f68d9
GM
2543static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2544 struct glyph_row *,
2545 enum glyph_row_area, int, int));
06a2c219 2546
163dcff3
GM
2547#if GLYPH_DEBUG
2548static void x_check_font P_ ((struct frame *, XFontStruct *));
2549#endif
2550
06a2c219 2551
06a2c219
GM
2552/* Append the list of glyph strings with head H and tail T to the list
2553 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2554
2555static INLINE void
2556x_append_glyph_string_lists (head, tail, h, t)
2557 struct glyph_string **head, **tail;
2558 struct glyph_string *h, *t;
2559{
2560 if (h)
2561 {
2562 if (*head)
2563 (*tail)->next = h;
2564 else
2565 *head = h;
2566 h->prev = *tail;
2567 *tail = t;
2568 }
2569}
2570
2571
2572/* Prepend the list of glyph strings with head H and tail T to the
2573 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2574 result. */
2575
2576static INLINE void
2577x_prepend_glyph_string_lists (head, tail, h, t)
2578 struct glyph_string **head, **tail;
2579 struct glyph_string *h, *t;
2580{
2581 if (h)
2582 {
2583 if (*head)
2584 (*head)->prev = t;
2585 else
2586 *tail = t;
2587 t->next = *head;
2588 *head = h;
2589 }
2590}
2591
2592
2593/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2594 Set *HEAD and *TAIL to the resulting list. */
2595
2596static INLINE void
2597x_append_glyph_string (head, tail, s)
2598 struct glyph_string **head, **tail;
2599 struct glyph_string *s;
2600{
2601 s->next = s->prev = NULL;
2602 x_append_glyph_string_lists (head, tail, s, s);
2603}
2604
2605
2606/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2607 face. */
2608
2609static void
2610x_set_cursor_gc (s)
2611 struct glyph_string *s;
2612{
2613 if (s->font == FRAME_FONT (s->f)
2614 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2615 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2616 && !s->cmp)
06a2c219
GM
2617 s->gc = s->f->output_data.x->cursor_gc;
2618 else
2619 {
2620 /* Cursor on non-default face: must merge. */
2621 XGCValues xgcv;
2622 unsigned long mask;
2623
2624 xgcv.background = s->f->output_data.x->cursor_pixel;
2625 xgcv.foreground = s->face->background;
2626
2627 /* If the glyph would be invisible, try a different foreground. */
2628 if (xgcv.foreground == xgcv.background)
2629 xgcv.foreground = s->face->foreground;
2630 if (xgcv.foreground == xgcv.background)
2631 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2632 if (xgcv.foreground == xgcv.background)
2633 xgcv.foreground = s->face->foreground;
2634
2635 /* Make sure the cursor is distinct from text in this face. */
2636 if (xgcv.background == s->face->background
2637 && xgcv.foreground == s->face->foreground)
2638 {
2639 xgcv.background = s->face->foreground;
2640 xgcv.foreground = s->face->background;
2641 }
2642
2643 IF_DEBUG (x_check_font (s->f, s->font));
2644 xgcv.font = s->font->fid;
2645 xgcv.graphics_exposures = False;
2646 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2647
2648 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2649 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2650 mask, &xgcv);
2651 else
2652 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2653 = XCreateGC (s->display, s->window, mask, &xgcv);
2654
2655 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2656 }
2657}
2658
2659
2660/* Set up S->gc of glyph string S for drawing text in mouse face. */
2661
2662static void
2663x_set_mouse_face_gc (s)
2664 struct glyph_string *s;
2665{
2666 int face_id;
ee569018 2667 struct face *face;
06a2c219 2668
e4ded23c 2669 /* What face has to be used last for the mouse face? */
06a2c219 2670 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2671 face = FACE_FROM_ID (s->f, face_id);
e4ded23c
GM
2672 if (face == NULL)
2673 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2674
033e3e18
GM
2675 if (s->first_glyph->type == CHAR_GLYPH)
2676 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2677 else
2678 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2679 s->face = FACE_FROM_ID (s->f, face_id);
2680 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2681
2682 /* If font in this face is same as S->font, use it. */
2683 if (s->font == s->face->font)
2684 s->gc = s->face->gc;
2685 else
2686 {
2687 /* Otherwise construct scratch_cursor_gc with values from FACE
2688 but font FONT. */
2689 XGCValues xgcv;
2690 unsigned long mask;
2691
2692 xgcv.background = s->face->background;
2693 xgcv.foreground = s->face->foreground;
2694 IF_DEBUG (x_check_font (s->f, s->font));
2695 xgcv.font = s->font->fid;
2696 xgcv.graphics_exposures = False;
2697 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2698
2699 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2700 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2701 mask, &xgcv);
2702 else
2703 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2704 = XCreateGC (s->display, s->window, mask, &xgcv);
2705
2706 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2707 }
2708
2709 xassert (s->gc != 0);
2710}
2711
2712
2713/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2714 Faces to use in the mode line have already been computed when the
2715 matrix was built, so there isn't much to do, here. */
2716
2717static INLINE void
2718x_set_mode_line_face_gc (s)
2719 struct glyph_string *s;
2720{
2721 s->gc = s->face->gc;
06a2c219
GM
2722}
2723
2724
2725/* Set S->gc of glyph string S for drawing that glyph string. Set
2726 S->stippled_p to a non-zero value if the face of S has a stipple
2727 pattern. */
2728
2729static INLINE void
2730x_set_glyph_string_gc (s)
2731 struct glyph_string *s;
2732{
209f68d9
GM
2733 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2734
06a2c219
GM
2735 if (s->hl == DRAW_NORMAL_TEXT)
2736 {
2737 s->gc = s->face->gc;
2738 s->stippled_p = s->face->stipple != 0;
2739 }
2740 else if (s->hl == DRAW_INVERSE_VIDEO)
2741 {
2742 x_set_mode_line_face_gc (s);
2743 s->stippled_p = s->face->stipple != 0;
2744 }
2745 else if (s->hl == DRAW_CURSOR)
2746 {
2747 x_set_cursor_gc (s);
2748 s->stippled_p = 0;
2749 }
2750 else if (s->hl == DRAW_MOUSE_FACE)
2751 {
2752 x_set_mouse_face_gc (s);
2753 s->stippled_p = s->face->stipple != 0;
2754 }
2755 else if (s->hl == DRAW_IMAGE_RAISED
2756 || s->hl == DRAW_IMAGE_SUNKEN)
2757 {
2758 s->gc = s->face->gc;
2759 s->stippled_p = s->face->stipple != 0;
2760 }
2761 else
2762 {
2763 s->gc = s->face->gc;
2764 s->stippled_p = s->face->stipple != 0;
2765 }
2766
2767 /* GC must have been set. */
2768 xassert (s->gc != 0);
2769}
2770
2771
2772/* Return in *R the clipping rectangle for glyph string S. */
2773
2774static void
2775x_get_glyph_string_clip_rect (s, r)
2776 struct glyph_string *s;
2777 XRectangle *r;
2778{
2779 if (s->row->full_width_p)
2780 {
2781 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2782 int canon_x = CANON_X_UNIT (s->f);
2783
2784 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2785 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2786
2787 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2788 {
1da3fd71 2789 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2790 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2791 r->x -= width;
2792 }
2793
b9432a85 2794 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2795
06a2c219
GM
2796 /* Unless displaying a mode or menu bar line, which are always
2797 fully visible, clip to the visible part of the row. */
2798 if (s->w->pseudo_window_p)
2799 r->height = s->row->visible_height;
2800 else
2801 r->height = s->height;
2802 }
2803 else
2804 {
2805 /* This is a text line that may be partially visible. */
2806 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2807 r->width = window_box_width (s->w, s->area);
2808 r->height = s->row->visible_height;
2809 }
2810
66ac4b0e
GM
2811 /* If S draws overlapping rows, it's sufficient to use the top and
2812 bottom of the window for clipping because this glyph string
2813 intentionally draws over other lines. */
2814 if (s->for_overlaps_p)
2815 {
045dee35 2816 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2817 r->height = window_text_bottom_y (s->w) - r->y;
2818 }
98b8a90f
GM
2819 else
2820 {
2821 /* Don't use S->y for clipping because it doesn't take partially
2822 visible lines into account. For example, it can be negative for
2823 partially visible lines at the top of a window. */
2824 if (!s->row->full_width_p
2825 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2826 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2827 else
2828 r->y = max (0, s->row->y);
2829
2830 /* If drawing a tool-bar window, draw it over the internal border
2831 at the top of the window. */
2832 if (s->w == XWINDOW (s->f->tool_bar_window))
2833 r->y -= s->f->output_data.x->internal_border_width;
2834 }
2835
66ac4b0e 2836 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2837}
2838
2839
2840/* Set clipping for output of glyph string S. S may be part of a mode
2841 line or menu if we don't have X toolkit support. */
2842
2843static INLINE void
2844x_set_glyph_string_clipping (s)
2845 struct glyph_string *s;
2846{
2847 XRectangle r;
2848 x_get_glyph_string_clip_rect (s, &r);
2849 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2850}
2851
2852
2853/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2854 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2855
2856static INLINE void
2857x_compute_glyph_string_overhangs (s)
2858 struct glyph_string *s;
2859{
b4192550 2860 if (s->cmp == NULL
06a2c219
GM
2861 && s->first_glyph->type == CHAR_GLYPH)
2862 {
2863 XCharStruct cs;
2864 int direction, font_ascent, font_descent;
2865 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2866 &font_ascent, &font_descent, &cs);
2867 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2868 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2869 }
2870}
2871
2872
2873/* Compute overhangs and x-positions for glyph string S and its
2874 predecessors, or successors. X is the starting x-position for S.
2875 BACKWARD_P non-zero means process predecessors. */
2876
2877static void
2878x_compute_overhangs_and_x (s, x, backward_p)
2879 struct glyph_string *s;
2880 int x;
2881 int backward_p;
2882{
2883 if (backward_p)
2884 {
2885 while (s)
2886 {
2887 x_compute_glyph_string_overhangs (s);
2888 x -= s->width;
2889 s->x = x;
2890 s = s->prev;
2891 }
2892 }
2893 else
2894 {
2895 while (s)
2896 {
2897 x_compute_glyph_string_overhangs (s);
2898 s->x = x;
2899 x += s->width;
2900 s = s->next;
2901 }
2902 }
2903}
2904
2905
2906/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2907 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2908 assumed to be zero. */
06a2c219
GM
2909
2910static void
2911x_get_glyph_overhangs (glyph, f, left, right)
2912 struct glyph *glyph;
2913 struct frame *f;
2914 int *left, *right;
2915{
06a2c219
GM
2916 *left = *right = 0;
2917
b4192550 2918 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2919 {
2920 XFontStruct *font;
2921 struct face *face;
2922 struct font_info *font_info;
2923 XChar2b char2b;
ee569018
KH
2924 XCharStruct *pcm;
2925
2926 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2927 font = face->font;
2928 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2929 if (font
2930 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2931 {
06a2c219
GM
2932 if (pcm->rbearing > pcm->width)
2933 *right = pcm->rbearing - pcm->width;
2934 if (pcm->lbearing < 0)
2935 *left = -pcm->lbearing;
2936 }
2937 }
2938}
2939
2940
2941/* Return the index of the first glyph preceding glyph string S that
2942 is overwritten by S because of S's left overhang. Value is -1
2943 if no glyphs are overwritten. */
2944
2945static int
2946x_left_overwritten (s)
2947 struct glyph_string *s;
2948{
2949 int k;
2950
2951 if (s->left_overhang)
2952 {
2953 int x = 0, i;
2954 struct glyph *glyphs = s->row->glyphs[s->area];
2955 int first = s->first_glyph - glyphs;
2956
2957 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2958 x -= glyphs[i].pixel_width;
2959
2960 k = i + 1;
2961 }
2962 else
2963 k = -1;
2964
2965 return k;
2966}
2967
2968
2969/* Return the index of the first glyph preceding glyph string S that
2970 is overwriting S because of its right overhang. Value is -1 if no
2971 glyph in front of S overwrites S. */
2972
2973static int
2974x_left_overwriting (s)
2975 struct glyph_string *s;
2976{
2977 int i, k, x;
2978 struct glyph *glyphs = s->row->glyphs[s->area];
2979 int first = s->first_glyph - glyphs;
2980
2981 k = -1;
2982 x = 0;
2983 for (i = first - 1; i >= 0; --i)
2984 {
2985 int left, right;
2986 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2987 if (x + right > 0)
2988 k = i;
2989 x -= glyphs[i].pixel_width;
2990 }
2991
2992 return k;
2993}
2994
2995
2996/* Return the index of the last glyph following glyph string S that is
2997 not overwritten by S because of S's right overhang. Value is -1 if
2998 no such glyph is found. */
2999
3000static int
3001x_right_overwritten (s)
3002 struct glyph_string *s;
3003{
3004 int k = -1;
3005
3006 if (s->right_overhang)
3007 {
3008 int x = 0, i;
3009 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3010 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3011 int end = s->row->used[s->area];
3012
3013 for (i = first; i < end && s->right_overhang > x; ++i)
3014 x += glyphs[i].pixel_width;
3015
3016 k = i;
3017 }
3018
3019 return k;
3020}
3021
3022
3023/* Return the index of the last glyph following glyph string S that
3024 overwrites S because of its left overhang. Value is negative
3025 if no such glyph is found. */
3026
3027static int
3028x_right_overwriting (s)
3029 struct glyph_string *s;
3030{
3031 int i, k, x;
3032 int end = s->row->used[s->area];
3033 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3034 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3035
3036 k = -1;
3037 x = 0;
3038 for (i = first; i < end; ++i)
3039 {
3040 int left, right;
3041 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3042 if (x - left < 0)
3043 k = i;
3044 x += glyphs[i].pixel_width;
3045 }
3046
3047 return k;
3048}
3049
3050
3051/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3052
3053static INLINE void
3054x_clear_glyph_string_rect (s, x, y, w, h)
3055 struct glyph_string *s;
3056 int x, y, w, h;
3057{
3058 XGCValues xgcv;
3059 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3060 XSetForeground (s->display, s->gc, xgcv.background);
3061 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3062 XSetForeground (s->display, s->gc, xgcv.foreground);
3063}
3064
3065
3066/* Draw the background of glyph_string S. If S->background_filled_p
3067 is non-zero don't draw it. FORCE_P non-zero means draw the
3068 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3069 when a string preceding S draws into the background of S, or S
3070 contains the first component of a composition. */
06a2c219
GM
3071
3072static void
3073x_draw_glyph_string_background (s, force_p)
3074 struct glyph_string *s;
3075 int force_p;
3076{
3077 /* Nothing to do if background has already been drawn or if it
3078 shouldn't be drawn in the first place. */
3079 if (!s->background_filled_p)
3080 {
ea2ba0d4
KH
3081 int box_line_width = max (s->face->box_line_width, 0);
3082
b4192550 3083 if (s->stippled_p)
06a2c219
GM
3084 {
3085 /* Fill background with a stipple pattern. */
3086 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3087 XFillRectangle (s->display, s->window, s->gc, s->x,
ea2ba0d4 3088 s->y + box_line_width,
06a2c219 3089 s->background_width,
ea2ba0d4 3090 s->height - 2 * box_line_width);
06a2c219
GM
3091 XSetFillStyle (s->display, s->gc, FillSolid);
3092 s->background_filled_p = 1;
3093 }
ea2ba0d4 3094 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
06a2c219
GM
3095 || s->font_not_found_p
3096 || s->extends_to_end_of_line_p
06a2c219
GM
3097 || force_p)
3098 {
ea2ba0d4 3099 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
06a2c219 3100 s->background_width,
ea2ba0d4 3101 s->height - 2 * box_line_width);
06a2c219
GM
3102 s->background_filled_p = 1;
3103 }
3104 }
3105}
3106
3107
3108/* Draw the foreground of glyph string S. */
3109
3110static void
3111x_draw_glyph_string_foreground (s)
3112 struct glyph_string *s;
3113{
3114 int i, x;
3115
3116 /* If first glyph of S has a left box line, start drawing the text
3117 of S to the right of that box line. */
3118 if (s->face->box != FACE_NO_BOX
3119 && s->first_glyph->left_box_line_p)
ea2ba0d4 3120 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
3121 else
3122 x = s->x;
3123
b4192550
KH
3124 /* Draw characters of S as rectangles if S's font could not be
3125 loaded. */
3126 if (s->font_not_found_p)
06a2c219 3127 {
b4192550 3128 for (i = 0; i < s->nchars; ++i)
06a2c219 3129 {
b4192550
KH
3130 struct glyph *g = s->first_glyph + i;
3131 XDrawRectangle (s->display, s->window,
3132 s->gc, x, s->y, g->pixel_width - 1,
3133 s->height - 1);
3134 x += g->pixel_width;
06a2c219
GM
3135 }
3136 }
3137 else
3138 {
b4192550
KH
3139 char *char1b = (char *) s->char2b;
3140 int boff = s->font_info->baseline_offset;
06a2c219 3141
b4192550
KH
3142 if (s->font_info->vertical_centering)
3143 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3144
3145 /* If we can use 8-bit functions, condense S->char2b. */
3146 if (!s->two_byte_p)
3147 for (i = 0; i < s->nchars; ++i)
3148 char1b[i] = s->char2b[i].byte2;
3149
3150 /* Draw text with XDrawString if background has already been
3151 filled. Otherwise, use XDrawImageString. (Note that
3152 XDrawImageString is usually faster than XDrawString.) Always
3153 use XDrawImageString when drawing the cursor so that there is
3154 no chance that characters under a box cursor are invisible. */
3155 if (s->for_overlaps_p
3156 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3157 {
3158 /* Draw characters with 16-bit or 8-bit functions. */
3159 if (s->two_byte_p)
3160 XDrawString16 (s->display, s->window, s->gc, x,
3161 s->ybase - boff, s->char2b, s->nchars);
3162 else
3163 XDrawString (s->display, s->window, s->gc, x,
3164 s->ybase - boff, char1b, s->nchars);
3165 }
06a2c219
GM
3166 else
3167 {
b4192550
KH
3168 if (s->two_byte_p)
3169 XDrawImageString16 (s->display, s->window, s->gc, x,
3170 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3171 else
b4192550
KH
3172 XDrawImageString (s->display, s->window, s->gc, x,
3173 s->ybase - boff, char1b, s->nchars);
3174 }
3175 }
3176}
06a2c219 3177
b4192550 3178/* Draw the foreground of composite glyph string S. */
06a2c219 3179
b4192550
KH
3180static void
3181x_draw_composite_glyph_string_foreground (s)
3182 struct glyph_string *s;
3183{
3184 int i, x;
06a2c219 3185
b4192550
KH
3186 /* If first glyph of S has a left box line, start drawing the text
3187 of S to the right of that box line. */
3188 if (s->face->box != FACE_NO_BOX
3189 && s->first_glyph->left_box_line_p)
ea2ba0d4 3190 x = s->x + abs (s->face->box_line_width);
b4192550
KH
3191 else
3192 x = s->x;
06a2c219 3193
b4192550
KH
3194 /* S is a glyph string for a composition. S->gidx is the index of
3195 the first character drawn for glyphs of this composition.
3196 S->gidx == 0 means we are drawing the very first character of
3197 this composition. */
06a2c219 3198
b4192550
KH
3199 /* Draw a rectangle for the composition if the font for the very
3200 first character of the composition could not be loaded. */
3201 if (s->font_not_found_p)
3202 {
3203 if (s->gidx == 0)
3204 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3205 s->width - 1, s->height - 1);
3206 }
3207 else
3208 {
3209 for (i = 0; i < s->nchars; i++, ++s->gidx)
3210 XDrawString16 (s->display, s->window, s->gc,
3211 x + s->cmp->offsets[s->gidx * 2],
3212 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3213 s->char2b + i, 1);
06a2c219
GM
3214 }
3215}
3216
3217
80c32bcc
GM
3218#ifdef USE_X_TOOLKIT
3219
3e71d8f2 3220static struct frame *x_frame_of_widget P_ ((Widget));
651f03b6
GM
3221static Boolean cvt_string_to_pixel P_ ((Display *, XrmValue *, Cardinal *,
3222 XrmValue *, XrmValue *, XtPointer *));
3223static void cvt_pixel_dtor P_ ((XtAppContext, XrmValue *, XtPointer,
3224 XrmValue *, Cardinal *));
80c32bcc 3225
3e71d8f2
GM
3226
3227/* Return the frame on which widget WIDGET is used.. Abort if frame
3228 cannot be determined. */
3229
e851c833 3230static struct frame *
3e71d8f2 3231x_frame_of_widget (widget)
80c32bcc 3232 Widget widget;
80c32bcc 3233{
80c32bcc 3234 struct x_display_info *dpyinfo;
5c187dee 3235 Lisp_Object tail;
3e71d8f2
GM
3236 struct frame *f;
3237
80c32bcc
GM
3238 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3239
3240 /* Find the top-level shell of the widget. Note that this function
3241 can be called when the widget is not yet realized, so XtWindow
3242 (widget) == 0. That's the reason we can't simply use
3243 x_any_window_to_frame. */
3244 while (!XtIsTopLevelShell (widget))
3245 widget = XtParent (widget);
3246
3247 /* Look for a frame with that top-level widget. Allocate the color
3248 on that frame to get the right gamma correction value. */
3249 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3250 if (GC_FRAMEP (XCAR (tail))
3251 && (f = XFRAME (XCAR (tail)),
3252 (f->output_data.nothing != 1
3253 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3254 && f->output_data.x->widget == widget)
3e71d8f2 3255 return f;
80c32bcc
GM
3256
3257 abort ();
3258}
3259
3e71d8f2
GM
3260
3261/* Allocate the color COLOR->pixel on the screen and display of
3262 widget WIDGET in colormap CMAP. If an exact match cannot be
3263 allocated, try the nearest color available. Value is non-zero
3264 if successful. This is called from lwlib. */
3265
3266int
3267x_alloc_nearest_color_for_widget (widget, cmap, color)
3268 Widget widget;
3269 Colormap cmap;
3270 XColor *color;
3271{
3272 struct frame *f = x_frame_of_widget (widget);
3273 return x_alloc_nearest_color (f, cmap, color);
3274}
3275
3276
46d516e5
MB
3277/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3278 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3279 If this produces the same color as PIXEL, try a color where all RGB
3280 values have DELTA added. Return the allocated color in *PIXEL.
3281 DISPLAY is the X display, CMAP is the colormap to operate on.
3282 Value is non-zero if successful. */
3283
3284int
3285x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3286 Widget widget;
3287 Display *display;
3288 Colormap cmap;
3289 unsigned long *pixel;
3290 double factor;
3291 int delta;
3292{
3293 struct frame *f = x_frame_of_widget (widget);
3294 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3295}
3296
3297
651f03b6
GM
3298/* Structure specifying which arguments should be passed by Xt to
3299 cvt_string_to_pixel. We want the widget's screen and colormap. */
3300
3301static XtConvertArgRec cvt_string_to_pixel_args[] =
3302 {
3303 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.screen),
3304 sizeof (Screen *)},
3305 {XtWidgetBaseOffset, (XtPointer) XtOffset (Widget, core.colormap),
3306 sizeof (Colormap)}
3307 };
3308
3309
3310/* The address of this variable is returned by
3311 cvt_string_to_pixel. */
3312
3313static Pixel cvt_string_to_pixel_value;
3314
3315
3316/* Convert a color name to a pixel color.
3317
3318 DPY is the display we are working on.
3319
3320 ARGS is an array of *NARGS XrmValue structures holding additional
3321 information about the widget for which the conversion takes place.
3322 The contents of this array are determined by the specification
3323 in cvt_string_to_pixel_args.
3324
3325 FROM is a pointer to an XrmValue which points to the color name to
3326 convert. TO is an XrmValue in which to return the pixel color.
3327
3328 CLOSURE_RET is a pointer to user-data, in which we record if
3329 we allocated the color or not.
3330
3331 Value is True if successful, False otherwise. */
3332
3333static Boolean
3334cvt_string_to_pixel (dpy, args, nargs, from, to, closure_ret)
3335 Display *dpy;
3336 XrmValue *args;
3337 Cardinal *nargs;
3338 XrmValue *from, *to;
3339 XtPointer *closure_ret;
3340{
3341 Screen *screen;
3342 Colormap cmap;
3343 Pixel pixel;
3344 String color_name;
3345 XColor color;
3346
3347 if (*nargs != 2)
3348 {
3349 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3350 "wrongParameters", "cvt_string_to_pixel",
3351 "XtToolkitError",
3352 "Screen and colormap args required", NULL, NULL);
3353 return False;
3354 }
3355
3356 screen = *(Screen **) args[0].addr;
3357 cmap = *(Colormap *) args[1].addr;
3358 color_name = (String) from->addr;
3359
3360 if (strcmp (color_name, XtDefaultBackground) == 0)
3361 {
3362 *closure_ret = (XtPointer) False;
3363 pixel = WhitePixelOfScreen (screen);
3364 }
3365 else if (strcmp (color_name, XtDefaultForeground) == 0)
3366 {
3367 *closure_ret = (XtPointer) False;
3368 pixel = BlackPixelOfScreen (screen);
3369 }
3370 else if (XParseColor (dpy, cmap, color_name, &color)
3371 && x_alloc_nearest_color_1 (dpy, cmap, &color))
3372 {
3373 pixel = color.pixel;
3374 *closure_ret = (XtPointer) True;
3375 }
3376 else
3377 {
3378 String params[1];
3379 Cardinal nparams = 1;
3380
3381 params[0] = color_name;
3382 XtAppWarningMsg (XtDisplayToApplicationContext (dpy),
3383 "badValue", "cvt_string_to_pixel",
3384 "XtToolkitError", "Invalid color `%s'",
3385 params, &nparams);
3386 return False;
3387 }
3388
3389 if (to->addr != NULL)
3390 {
3391 if (to->size < sizeof (Pixel))
3392 {
3393 to->size = sizeof (Pixel);
3394 return False;
3395 }
3396
3397 *(Pixel *) to->addr = pixel;
3398 }
3399 else
3400 {
3401 cvt_string_to_pixel_value = pixel;
3402 to->addr = (XtPointer) &cvt_string_to_pixel_value;
3403 }
3404
3405 to->size = sizeof (Pixel);
3406 return True;
3407}
3408
3409
3410/* Free a pixel color which was previously allocated via
3411 cvt_string_to_pixel. This is registered as the destructor
3412 for this type of resource via XtSetTypeConverter.
3413
3414 APP is the application context in which we work.
3415
3416 TO is a pointer to an XrmValue holding the color to free.
3417 CLOSURE is the value we stored in CLOSURE_RET for this color
3418 in cvt_string_to_pixel.
3419
3420 ARGS and NARGS are like for cvt_string_to_pixel. */
3421
3422static void
3423cvt_pixel_dtor (app, to, closure, args, nargs)
3424 XtAppContext app;
3425 XrmValuePtr to;
3426 XtPointer closure;
3427 XrmValuePtr args;
3428 Cardinal *nargs;
3429{
3430 if (*nargs != 2)
3431 {
3432 XtAppWarningMsg (app, "wrongParameters", "cvt_pixel_dtor",
3433 "XtToolkitError",
3434 "Screen and colormap arguments required",
3435 NULL, NULL);
3436 }
3437 else if (closure != NULL)
3438 {
3439 /* We did allocate the pixel, so free it. */
3440 Screen *screen = *(Screen **) args[0].addr;
3441 Colormap cmap = *(Colormap *) args[1].addr;
3442 x_free_dpy_colors (DisplayOfScreen (screen), screen, cmap,
97762eb7 3443 (Pixel *) to->addr, 1);
651f03b6
GM
3444 }
3445}
3446
3447
80c32bcc
GM
3448#endif /* USE_X_TOOLKIT */
3449
3450
f04e1297 3451/* Value is an array of XColor structures for the contents of the
651f03b6 3452 color map of display DPY. Set *NCELLS to the size of the array.
f04e1297
GM
3453 Note that this probably shouldn't be called for large color maps,
3454 say a 24-bit TrueColor map. */
3455
3456static const XColor *
651f03b6
GM
3457x_color_cells (dpy, ncells)
3458 Display *dpy;
f04e1297
GM
3459 int *ncells;
3460{
651f03b6 3461 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
f04e1297
GM
3462
3463 if (dpyinfo->color_cells == NULL)
3464 {
651f03b6 3465 Screen *screen = dpyinfo->screen;
f04e1297
GM
3466 int i;
3467
3468 dpyinfo->ncolor_cells
651f03b6 3469 = XDisplayCells (dpy, XScreenNumberOfScreen (screen));
f04e1297
GM
3470 dpyinfo->color_cells
3471 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3472 * sizeof *dpyinfo->color_cells);
3473
3474 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3475 dpyinfo->color_cells[i].pixel = i;
3476
651f03b6 3477 XQueryColors (dpy, dpyinfo->cmap,
f04e1297
GM
3478 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3479 }
3480
3481 *ncells = dpyinfo->ncolor_cells;
3482 return dpyinfo->color_cells;
3483}
3484
3485
3486/* On frame F, translate pixel colors to RGB values for the NCOLORS
3487 colors in COLORS. Use cached information, if available. */
3488
3489void
3490x_query_colors (f, colors, ncolors)
3491 struct frame *f;
3492 XColor *colors;
3493 int ncolors;
3494{
3495 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3496
3497 if (dpyinfo->color_cells)
3498 {
3499 int i;
3500 for (i = 0; i < ncolors; ++i)
3501 {
3502 unsigned long pixel = colors[i].pixel;
3503 xassert (pixel < dpyinfo->ncolor_cells);
3504 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3505 colors[i] = dpyinfo->color_cells[pixel];
3506 }
3507 }
3508 else
3509 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3510}
3511
3512
3513/* On frame F, translate pixel color to RGB values for the color in
3514 COLOR. Use cached information, if available. */
3515
3516void
3517x_query_color (f, color)
3518 struct frame *f;
3519 XColor *color;
3520{
3521 x_query_colors (f, color, 1);
3522}
3523
3524
651f03b6
GM
3525/* Allocate the color COLOR->pixel on DISPLAY, colormap CMAP. If an
3526 exact match can't be allocated, try the nearest color available.
3527 Value is non-zero if successful. Set *COLOR to the color
3528 allocated. */
06a2c219 3529
651f03b6
GM
3530static int
3531x_alloc_nearest_color_1 (dpy, cmap, color)
3532 Display *dpy;
06a2c219
GM
3533 Colormap cmap;
3534 XColor *color;
3535{
80c32bcc
GM
3536 int rc;
3537
651f03b6 3538 rc = XAllocColor (dpy, cmap, color);
06a2c219
GM
3539 if (rc == 0)
3540 {
3541 /* If we got to this point, the colormap is full, so we're going
3542 to try to get the next closest color. The algorithm used is
3543 a least-squares matching, which is what X uses for closest
3544 color matching with StaticColor visuals. */
3545 int nearest, i;
3546 unsigned long nearest_delta = ~0;
f04e1297 3547 int ncells;
651f03b6 3548 const XColor *cells = x_color_cells (dpy, &ncells);
06a2c219
GM
3549
3550 for (nearest = i = 0; i < ncells; ++i)
3551 {
3552 long dred = (color->red >> 8) - (cells[i].red >> 8);
3553 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3554 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3555 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3556
3557 if (delta < nearest_delta)
3558 {
3559 nearest = i;
3560 nearest_delta = delta;
3561 }
3562 }
3563
3564 color->red = cells[nearest].red;
3565 color->green = cells[nearest].green;
3566 color->blue = cells[nearest].blue;
651f03b6 3567 rc = XAllocColor (dpy, cmap, color);
06a2c219 3568 }
35efe0a1
GM
3569 else
3570 {
3571 /* If allocation succeeded, and the allocated pixel color is not
3572 equal to a cached pixel color recorded earlier, there was a
3573 change in the colormap, so clear the color cache. */
651f03b6 3574 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
35efe0a1
GM
3575 XColor *cached_color;
3576
3577 if (dpyinfo->color_cells
3578 && (cached_color = &dpyinfo->color_cells[color->pixel],
cae71efe
GM
3579 (cached_color->red != color->red
3580 || cached_color->blue != color->blue
3581 || cached_color->green != color->green)))
35efe0a1
GM
3582 {
3583 xfree (dpyinfo->color_cells);
3584 dpyinfo->color_cells = NULL;
3585 dpyinfo->ncolor_cells = 0;
3586 }
3587 }
06a2c219 3588
d9c545da
GM
3589#ifdef DEBUG_X_COLORS
3590 if (rc)
3591 register_color (color->pixel);
3592#endif /* DEBUG_X_COLORS */
3593
06a2c219
GM
3594 return rc;
3595}
3596
3597
651f03b6
GM
3598/* Allocate the color COLOR->pixel on frame F, colormap CMAP. If an
3599 exact match can't be allocated, try the nearest color available.
3600 Value is non-zero if successful. Set *COLOR to the color
3601 allocated. */
3602
3603int
3604x_alloc_nearest_color (f, cmap, color)
3605 struct frame *f;
3606 Colormap cmap;
3607 XColor *color;
3608{
3609 gamma_correct (f, color);
3610 return x_alloc_nearest_color_1 (FRAME_X_DISPLAY (f), cmap, color);
3611}
3612
3613
d9c545da
GM
3614/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3615 It's necessary to do this instead of just using PIXEL directly to
3616 get color reference counts right. */
3617
3618unsigned long
3619x_copy_color (f, pixel)
3620 struct frame *f;
3621 unsigned long pixel;
3622{
3623 XColor color;
3624
3625 color.pixel = pixel;
3626 BLOCK_INPUT;
f04e1297 3627 x_query_color (f, &color);
d9c545da
GM
3628 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3629 UNBLOCK_INPUT;
3630#ifdef DEBUG_X_COLORS
3631 register_color (pixel);
3632#endif
3633 return color.pixel;
3634}
3635
3636
3e71d8f2
GM
3637/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3638 It's necessary to do this instead of just using PIXEL directly to
3639 get color reference counts right. */
3640
3641unsigned long
3642x_copy_dpy_color (dpy, cmap, pixel)
3643 Display *dpy;
3644 Colormap cmap;
3645 unsigned long pixel;
3646{
3647 XColor color;
3648
3649 color.pixel = pixel;
3650 BLOCK_INPUT;
3651 XQueryColor (dpy, cmap, &color);
3652 XAllocColor (dpy, cmap, &color);
3653 UNBLOCK_INPUT;
3654#ifdef DEBUG_X_COLORS
3655 register_color (pixel);
3656#endif
3657 return color.pixel;
3658}
3659
3660
6d8b0acd 3661/* Brightness beyond which a color won't have its highlight brightness
d7361edf 3662 boosted.
6d8b0acd 3663
d7361edf
MB
3664 Nominally, highlight colors for `3d' faces are calculated by
3665 brightening an object's color by a constant scale factor, but this
3666 doesn't yield good results for dark colors, so for colors who's
3667 brightness is less than this value (on a scale of 0-65535) have an
3668 use an additional additive factor.
6d8b0acd
MB
3669
3670 The value here is set so that the default menu-bar/mode-line color
3671 (grey75) will not have its highlights changed at all. */
3672#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3673
3674
06a2c219
GM
3675/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3676 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3677 If this produces the same color as PIXEL, try a color where all RGB
3678 values have DELTA added. Return the allocated color in *PIXEL.
3679 DISPLAY is the X display, CMAP is the colormap to operate on.
3680 Value is non-zero if successful. */
3681
3682static int
3683x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3684 struct frame *f;
3685 Display *display;
3686 Colormap cmap;
3687 unsigned long *pixel;
68c45bf0 3688 double factor;
06a2c219
GM
3689 int delta;
3690{
3691 XColor color, new;
6d8b0acd 3692 long bright;
06a2c219
GM
3693 int success_p;
3694
3695 /* Get RGB color values. */
3696 color.pixel = *pixel;
f04e1297 3697 x_query_color (f, &color);
06a2c219
GM
3698
3699 /* Change RGB values by specified FACTOR. Avoid overflow! */
3700 xassert (factor >= 0);
3701 new.red = min (0xffff, factor * color.red);
3702 new.green = min (0xffff, factor * color.green);
3703 new.blue = min (0xffff, factor * color.blue);
3704
d7361edf
MB
3705 /* Calculate brightness of COLOR. */
3706 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
6d8b0acd
MB
3707
3708 /* We only boost colors that are darker than
3709 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3710 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3711 /* Make an additive adjustment to NEW, because it's dark enough so
3712 that scaling by FACTOR alone isn't enough. */
3713 {
3714 /* How far below the limit this color is (0 - 1, 1 being darker). */
3715 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3716 /* The additive adjustment. */
d7361edf 3717 int min_delta = delta * dimness * factor / 2;
6d8b0acd
MB
3718
3719 if (factor < 1)
3720 {
6d8b0acd
MB
3721 new.red = max (0, new.red - min_delta);
3722 new.green = max (0, new.green - min_delta);
3723 new.blue = max (0, new.blue - min_delta);
3724 }
3725 else
3726 {
3727 new.red = min (0xffff, min_delta + new.red);
3728 new.green = min (0xffff, min_delta + new.green);
3729 new.blue = min (0xffff, min_delta + new.blue);
3730 }
3731 }
3732
06a2c219 3733 /* Try to allocate the color. */
80c32bcc 3734 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3735 if (success_p)
3736 {
3737 if (new.pixel == *pixel)
3738 {
3739 /* If we end up with the same color as before, try adding
3740 delta to the RGB values. */
0d605c67 3741 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3742
3743 new.red = min (0xffff, delta + color.red);
3744 new.green = min (0xffff, delta + color.green);
3745 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3746 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3747 }
3748 else
3749 success_p = 1;
3750 *pixel = new.pixel;
3751 }
3752
3753 return success_p;
3754}
3755
3756
3757/* Set up the foreground color for drawing relief lines of glyph
3758 string S. RELIEF is a pointer to a struct relief containing the GC
3759 with which lines will be drawn. Use a color that is FACTOR or
3760 DELTA lighter or darker than the relief's background which is found
3761 in S->f->output_data.x->relief_background. If such a color cannot
3762 be allocated, use DEFAULT_PIXEL, instead. */
3763
3764static void
3765x_setup_relief_color (f, relief, factor, delta, default_pixel)
3766 struct frame *f;
3767 struct relief *relief;
68c45bf0 3768 double factor;
06a2c219
GM
3769 int delta;
3770 unsigned long default_pixel;
3771{
3772 XGCValues xgcv;
3773 struct x_output *di = f->output_data.x;
3774 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3775 unsigned long pixel;
3776 unsigned long background = di->relief_background;
43bd1b2b 3777 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3778 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3779 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3780
3781 xgcv.graphics_exposures = False;
3782 xgcv.line_width = 1;
3783
3784 /* Free previously allocated color. The color cell will be reused
3785 when it has been freed as many times as it was allocated, so this
3786 doesn't affect faces using the same colors. */
3787 if (relief->gc
3788 && relief->allocated_p)
3789 {
0d605c67 3790 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3791 relief->allocated_p = 0;
3792 }
3793
3794 /* Allocate new color. */
3795 xgcv.foreground = default_pixel;
3796 pixel = background;
dcd08bfb
GM
3797 if (dpyinfo->n_planes != 1
3798 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3799 {
3800 relief->allocated_p = 1;
3801 xgcv.foreground = relief->pixel = pixel;
3802 }
3803
3804 if (relief->gc == 0)
3805 {
dcd08bfb 3806 xgcv.stipple = dpyinfo->gray;
06a2c219 3807 mask |= GCStipple;
dcd08bfb 3808 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3809 }
3810 else
dcd08bfb 3811 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3812}
3813
3814
3815/* Set up colors for the relief lines around glyph string S. */
3816
3817static void
3818x_setup_relief_colors (s)
3819 struct glyph_string *s;
3820{
3821 struct x_output *di = s->f->output_data.x;
3822 unsigned long color;
3823
3824 if (s->face->use_box_color_for_shadows_p)
3825 color = s->face->box_color;
3826 else
3827 {
3828 XGCValues xgcv;
3829
3830 /* Get the background color of the face. */
3831 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3832 color = xgcv.background;
3833 }
3834
3835 if (di->white_relief.gc == 0
3836 || color != di->relief_background)
3837 {
3838 di->relief_background = color;
3839 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3840 WHITE_PIX_DEFAULT (s->f));
3841 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3842 BLACK_PIX_DEFAULT (s->f));
3843 }
3844}
3845
3846
3847/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3848 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3849 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3850 relief. LEFT_P non-zero means draw a relief on the left side of
3851 the rectangle. RIGHT_P non-zero means draw a relief on the right
3852 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3853 when drawing. */
3854
3855static void
3856x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3857 raised_p, left_p, right_p, clip_rect)
3858 struct frame *f;
3859 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3860 XRectangle *clip_rect;
3861{
de507556
GM
3862 Display *dpy = FRAME_X_DISPLAY (f);
3863 Window window = FRAME_X_WINDOW (f);
06a2c219
GM
3864 int i;
3865 GC gc;
3866
3867 if (raised_p)
3868 gc = f->output_data.x->white_relief.gc;
3869 else
3870 gc = f->output_data.x->black_relief.gc;
de507556 3871 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
06a2c219
GM
3872
3873 /* Top. */
3874 for (i = 0; i < width; ++i)
de507556 3875 XDrawLine (dpy, window, gc,
06a2c219
GM
3876 left_x + i * left_p, top_y + i,
3877 right_x + 1 - i * right_p, top_y + i);
3878
3879 /* Left. */
3880 if (left_p)
3881 for (i = 0; i < width; ++i)
de507556 3882 XDrawLine (dpy, window, gc,
44655e77 3883 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
06a2c219 3884
de507556 3885 XSetClipMask (dpy, gc, None);
06a2c219
GM
3886 if (raised_p)
3887 gc = f->output_data.x->black_relief.gc;
3888 else
3889 gc = f->output_data.x->white_relief.gc;
de507556 3890 XSetClipRectangles (dpy, gc, 0, 0, clip_rect, 1, Unsorted);
06a2c219
GM
3891
3892 /* Bottom. */
3893 for (i = 0; i < width; ++i)
de507556
GM
3894 XDrawLine (dpy, window, gc,
3895 left_x + i * left_p, bottom_y - i,
3896 right_x + 2 - i * right_p, bottom_y - i);
06a2c219
GM
3897
3898 /* Right. */
3899 if (right_p)
3900 for (i = 0; i < width; ++i)
de507556 3901 XDrawLine (dpy, window, gc,
06a2c219
GM
3902 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3903
de507556 3904 XSetClipMask (dpy, gc, None);
06a2c219
GM
3905}
3906
3907
3908/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3909 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3910 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3911 left side of the rectangle. RIGHT_P non-zero means draw a line
3912 on the right side of the rectangle. CLIP_RECT is the clipping
3913 rectangle to use when drawing. */
3914
3915static void
3916x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3917 left_p, right_p, clip_rect)
3918 struct glyph_string *s;
3919 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3920 XRectangle *clip_rect;
3921{
3922 XGCValues xgcv;
3923
3924 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3925 XSetForeground (s->display, s->gc, s->face->box_color);
3926 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3927
3928 /* Top. */
3929 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3930 left_x, top_y, right_x - left_x + 1, width);
06a2c219
GM
3931
3932 /* Left. */
3933 if (left_p)
3934 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3935 left_x, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3936
3937 /* Bottom. */
3938 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3939 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
06a2c219
GM
3940
3941 /* Right. */
3942 if (right_p)
3943 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3944 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3945
3946 XSetForeground (s->display, s->gc, xgcv.foreground);
3947 XSetClipMask (s->display, s->gc, None);
3948}
3949
3950
3951/* Draw a box around glyph string S. */
3952
3953static void
3954x_draw_glyph_string_box (s)
3955 struct glyph_string *s;
3956{
3957 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3958 int left_p, right_p;
3959 struct glyph *last_glyph;
3960 XRectangle clip_rect;
3961
3962 last_x = window_box_right (s->w, s->area);
3963 if (s->row->full_width_p
3964 && !s->w->pseudo_window_p)
3965 {
110859fc 3966 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3967 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3968 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3969 }
3970
3971 /* The glyph that may have a right box line. */
b4192550 3972 last_glyph = (s->cmp || s->img
06a2c219
GM
3973 ? s->first_glyph
3974 : s->first_glyph + s->nchars - 1);
3975
ea2ba0d4 3976 width = abs (s->face->box_line_width);
06a2c219
GM
3977 raised_p = s->face->box == FACE_RAISED_BOX;
3978 left_x = s->x;
57ac7c81
GM
3979 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3980 ? last_x - 1
3981 : min (last_x, s->x + s->background_width) - 1);
06a2c219
GM
3982 top_y = s->y;
3983 bottom_y = top_y + s->height - 1;
3984
3985 left_p = (s->first_glyph->left_box_line_p
3986 || (s->hl == DRAW_MOUSE_FACE
3987 && (s->prev == NULL
3988 || s->prev->hl != s->hl)));
3989 right_p = (last_glyph->right_box_line_p
3990 || (s->hl == DRAW_MOUSE_FACE
3991 && (s->next == NULL
3992 || s->next->hl != s->hl)));
3993
3994 x_get_glyph_string_clip_rect (s, &clip_rect);
3995
3996 if (s->face->box == FACE_SIMPLE_BOX)
3997 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3998 left_p, right_p, &clip_rect);
3999 else
4000 {
4001 x_setup_relief_colors (s);
4002 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
4003 width, raised_p, left_p, right_p, &clip_rect);
4004 }
4005}
4006
4007
4008/* Draw foreground of image glyph string S. */
4009
4010static void
4011x_draw_image_foreground (s)
4012 struct glyph_string *s;
4013{
4014 int x;
95af8492 4015 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
4016
4017 /* If first glyph of S has a left box line, start drawing it to the
4018 right of that line. */
4019 if (s->face->box != FACE_NO_BOX
4020 && s->first_glyph->left_box_line_p)
ea2ba0d4 4021 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
4022 else
4023 x = s->x;
4024
4025 /* If there is a margin around the image, adjust x- and y-position
4026 by that margin. */
22d650b8
GM
4027 x += s->img->hmargin;
4028 y += s->img->vmargin;
06a2c219
GM
4029
4030 if (s->img->pixmap)
4031 {
4032 if (s->img->mask)
4033 {
4034 /* We can't set both a clip mask and use XSetClipRectangles
4035 because the latter also sets a clip mask. We also can't
4036 trust on the shape extension to be available
4037 (XShapeCombineRegion). So, compute the rectangle to draw
4038 manually. */
4039 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4040 | GCFunction);
4041 XGCValues xgcv;
4042 XRectangle clip_rect, image_rect, r;
4043
4044 xgcv.clip_mask = s->img->mask;
4045 xgcv.clip_x_origin = x;
4046 xgcv.clip_y_origin = y;
4047 xgcv.function = GXcopy;
4048 XChangeGC (s->display, s->gc, mask, &xgcv);
4049
4050 x_get_glyph_string_clip_rect (s, &clip_rect);
4051 image_rect.x = x;
4052 image_rect.y = y;
4053 image_rect.width = s->img->width;
4054 image_rect.height = s->img->height;
4055 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4056 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4057 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
4058 }
4059 else
4060 {
49ad1d99
GM
4061 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
4062 XGCValues xgcv;
4063 XRectangle clip_rect, image_rect, r;
4064
4065 x_get_glyph_string_clip_rect (s, &clip_rect);
4066 image_rect.x = x;
4067 image_rect.y = y;
4068 image_rect.width = s->img->width;
4069 image_rect.height = s->img->height;
4070 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
4071 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
4072 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
06a2c219
GM
4073
4074 /* When the image has a mask, we can expect that at
4075 least part of a mouse highlight or a block cursor will
4076 be visible. If the image doesn't have a mask, make
4077 a block cursor visible by drawing a rectangle around
4078 the image. I believe it's looking better if we do
4079 nothing here for mouse-face. */
4080 if (s->hl == DRAW_CURSOR)
4081 XDrawRectangle (s->display, s->window, s->gc, x, y,
4082 s->img->width - 1, s->img->height - 1);
4083 }
4084 }
4085 else
4086 /* Draw a rectangle if image could not be loaded. */
4087 XDrawRectangle (s->display, s->window, s->gc, x, y,
4088 s->img->width - 1, s->img->height - 1);
4089}
4090
4091
4092/* Draw a relief around the image glyph string S. */
4093
4094static void
4095x_draw_image_relief (s)
4096 struct glyph_string *s;
4097{
4098 int x0, y0, x1, y1, thick, raised_p;
4099 XRectangle r;
4100 int x;
95af8492 4101 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
4102
4103 /* If first glyph of S has a left box line, start drawing it to the
4104 right of that line. */
4105 if (s->face->box != FACE_NO_BOX
4106 && s->first_glyph->left_box_line_p)
ea2ba0d4 4107 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
4108 else
4109 x = s->x;
4110
4111 /* If there is a margin around the image, adjust x- and y-position
4112 by that margin. */
22d650b8
GM
4113 x += s->img->hmargin;
4114 y += s->img->vmargin;
06a2c219
GM
4115
4116 if (s->hl == DRAW_IMAGE_SUNKEN
4117 || s->hl == DRAW_IMAGE_RAISED)
4118 {
9ea173e8 4119 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
4120 raised_p = s->hl == DRAW_IMAGE_RAISED;
4121 }
4122 else
4123 {
4124 thick = abs (s->img->relief);
4125 raised_p = s->img->relief > 0;
4126 }
4127
4128 x0 = x - thick;
4129 y0 = y - thick;
4130 x1 = x + s->img->width + thick - 1;
4131 y1 = y + s->img->height + thick - 1;
4132
4133 x_setup_relief_colors (s);
4134 x_get_glyph_string_clip_rect (s, &r);
4135 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
4136}
4137
4138
4139/* Draw the foreground of image glyph string S to PIXMAP. */
4140
4141static void
4142x_draw_image_foreground_1 (s, pixmap)
4143 struct glyph_string *s;
4144 Pixmap pixmap;
4145{
4146 int x;
95af8492 4147 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
4148
4149 /* If first glyph of S has a left box line, start drawing it to the
4150 right of that line. */
4151 if (s->face->box != FACE_NO_BOX
4152 && s->first_glyph->left_box_line_p)
ea2ba0d4 4153 x = abs (s->face->box_line_width);
06a2c219
GM
4154 else
4155 x = 0;
4156
4157 /* If there is a margin around the image, adjust x- and y-position
4158 by that margin. */
22d650b8
GM
4159 x += s->img->hmargin;
4160 y += s->img->vmargin;
dc43ef94 4161
06a2c219
GM
4162 if (s->img->pixmap)
4163 {
4164 if (s->img->mask)
4165 {
4166 /* We can't set both a clip mask and use XSetClipRectangles
4167 because the latter also sets a clip mask. We also can't
4168 trust on the shape extension to be available
4169 (XShapeCombineRegion). So, compute the rectangle to draw
4170 manually. */
4171 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4172 | GCFunction);
4173 XGCValues xgcv;
4174
4175 xgcv.clip_mask = s->img->mask;
4176 xgcv.clip_x_origin = x;
4177 xgcv.clip_y_origin = y;
4178 xgcv.function = GXcopy;
4179 XChangeGC (s->display, s->gc, mask, &xgcv);
4180
4181 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4182 0, 0, s->img->width, s->img->height, x, y);
4183 XSetClipMask (s->display, s->gc, None);
4184 }
4185 else
4186 {
4187 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4188 0, 0, s->img->width, s->img->height, x, y);
4189
4190 /* When the image has a mask, we can expect that at
4191 least part of a mouse highlight or a block cursor will
4192 be visible. If the image doesn't have a mask, make
4193 a block cursor visible by drawing a rectangle around
4194 the image. I believe it's looking better if we do
4195 nothing here for mouse-face. */
4196 if (s->hl == DRAW_CURSOR)
4197 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4198 s->img->width - 1, s->img->height - 1);
4199 }
4200 }
4201 else
4202 /* Draw a rectangle if image could not be loaded. */
4203 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4204 s->img->width - 1, s->img->height - 1);
4205}
dc43ef94 4206
990ba854 4207
06a2c219
GM
4208/* Draw part of the background of glyph string S. X, Y, W, and H
4209 give the rectangle to draw. */
a9a5b0a5 4210
06a2c219
GM
4211static void
4212x_draw_glyph_string_bg_rect (s, x, y, w, h)
4213 struct glyph_string *s;
4214 int x, y, w, h;
4215{
4216 if (s->stippled_p)
4217 {
4218 /* Fill background with a stipple pattern. */
4219 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4220 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4221 XSetFillStyle (s->display, s->gc, FillSolid);
4222 }
4223 else
4224 x_clear_glyph_string_rect (s, x, y, w, h);
4225}
07e34cb0 4226
b5210ea7 4227
06a2c219 4228/* Draw image glyph string S.
dc43ef94 4229
06a2c219
GM
4230 s->y
4231 s->x +-------------------------
4232 | s->face->box
4233 |
4234 | +-------------------------
4235 | | s->img->margin
4236 | |
4237 | | +-------------------
4238 | | | the image
dc43ef94 4239
06a2c219 4240 */
dc43ef94 4241
06a2c219
GM
4242static void
4243x_draw_image_glyph_string (s)
4244 struct glyph_string *s;
4245{
4246 int x, y;
ea2ba0d4
KH
4247 int box_line_hwidth = abs (s->face->box_line_width);
4248 int box_line_vwidth = max (s->face->box_line_width, 0);
06a2c219
GM
4249 int height;
4250 Pixmap pixmap = None;
4251
ea2ba0d4 4252 height = s->height - 2 * box_line_vwidth;
06a2c219
GM
4253
4254 /* Fill background with face under the image. Do it only if row is
4255 taller than image or if image has a clip mask to reduce
4256 flickering. */
4257 s->stippled_p = s->face->stipple != 0;
4258 if (height > s->img->height
22d650b8
GM
4259 || s->img->hmargin
4260 || s->img->vmargin
06a2c219
GM
4261 || s->img->mask
4262 || s->img->pixmap == 0
4263 || s->width != s->background_width)
4264 {
ea2ba0d4
KH
4265 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4266 x = s->x + box_line_hwidth;
06a2c219
GM
4267 else
4268 x = s->x;
4269
ea2ba0d4 4270 y = s->y + box_line_vwidth;
06a2c219
GM
4271
4272 if (s->img->mask)
4273 {
f9b5db02
GM
4274 /* Create a pixmap as large as the glyph string. Fill it
4275 with the background color. Copy the image to it, using
4276 its mask. Copy the temporary pixmap to the display. */
06a2c219
GM
4277 Screen *screen = FRAME_X_SCREEN (s->f);
4278 int depth = DefaultDepthOfScreen (screen);
4279
4280 /* Create a pixmap as large as the glyph string. */
4281 pixmap = XCreatePixmap (s->display, s->window,
4282 s->background_width,
4283 s->height, depth);
4284
4285 /* Don't clip in the following because we're working on the
4286 pixmap. */
4287 XSetClipMask (s->display, s->gc, None);
4288
4289 /* Fill the pixmap with the background color/stipple. */
4290 if (s->stippled_p)
4291 {
4292 /* Fill background with a stipple pattern. */
4293 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4294 XFillRectangle (s->display, pixmap, s->gc,
4295 0, 0, s->background_width, s->height);
4296 XSetFillStyle (s->display, s->gc, FillSolid);
4297 }
4298 else
4299 {
4300 XGCValues xgcv;
4301 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4302 &xgcv);
4303 XSetForeground (s->display, s->gc, xgcv.background);
4304 XFillRectangle (s->display, pixmap, s->gc,
4305 0, 0, s->background_width, s->height);
4306 XSetForeground (s->display, s->gc, xgcv.foreground);
4307 }
4308 }
4309 else
06a2c219
GM
4310 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4311
4312 s->background_filled_p = 1;
4313 }
dc43ef94 4314
06a2c219
GM
4315 /* Draw the foreground. */
4316 if (pixmap != None)
4317 {
4318 x_draw_image_foreground_1 (s, pixmap);
4319 x_set_glyph_string_clipping (s);
4320 XCopyArea (s->display, pixmap, s->window, s->gc,
4321 0, 0, s->background_width, s->height, s->x, s->y);
4322 XFreePixmap (s->display, pixmap);
4323 }
4324 else
4325 x_draw_image_foreground (s);
b5210ea7 4326
06a2c219
GM
4327 /* If we must draw a relief around the image, do it. */
4328 if (s->img->relief
4329 || s->hl == DRAW_IMAGE_RAISED
4330 || s->hl == DRAW_IMAGE_SUNKEN)
4331 x_draw_image_relief (s);
4332}
8c1a6a84 4333
990ba854 4334
06a2c219 4335/* Draw stretch glyph string S. */
dc43ef94 4336
06a2c219
GM
4337static void
4338x_draw_stretch_glyph_string (s)
4339 struct glyph_string *s;
4340{
4341 xassert (s->first_glyph->type == STRETCH_GLYPH);
4342 s->stippled_p = s->face->stipple != 0;
990ba854 4343
06a2c219
GM
4344 if (s->hl == DRAW_CURSOR
4345 && !x_stretch_cursor_p)
4346 {
4347 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4348 as wide as the stretch glyph. */
4349 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4350
06a2c219
GM
4351 /* Draw cursor. */
4352 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4353
06a2c219
GM
4354 /* Clear rest using the GC of the original non-cursor face. */
4355 if (width < s->background_width)
4356 {
06a2c219
GM
4357 int x = s->x + width, y = s->y;
4358 int w = s->background_width - width, h = s->height;
4359 XRectangle r;
b7f83f9e 4360 GC gc;
dc43ef94 4361
b7f83f9e
GM
4362 if (s->row->mouse_face_p
4363 && cursor_in_mouse_face_p (s->w))
4364 {
4365 x_set_mouse_face_gc (s);
4366 gc = s->gc;
4367 }
4368 else
4369 gc = s->face->gc;
4370
06a2c219
GM
4371 x_get_glyph_string_clip_rect (s, &r);
4372 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
b7f83f9e 4373
06a2c219
GM
4374 if (s->face->stipple)
4375 {
4376 /* Fill background with a stipple pattern. */
4377 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4378 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4379 XSetFillStyle (s->display, gc, FillSolid);
4380 }
4381 else
4382 {
4383 XGCValues xgcv;
4384 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4385 XSetForeground (s->display, gc, xgcv.background);
4386 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4387 XSetForeground (s->display, gc, xgcv.foreground);
4388 }
4389 }
4390 }
61e9f9f3 4391 else if (!s->background_filled_p)
06a2c219
GM
4392 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4393 s->height);
4394
4395 s->background_filled_p = 1;
4396}
4397
4398
4399/* Draw glyph string S. */
4400
4401static void
4402x_draw_glyph_string (s)
4403 struct glyph_string *s;
4404{
4458cf11
KH
4405 int relief_drawn_p = 0;
4406
06a2c219
GM
4407 /* If S draws into the background of its successor, draw the
4408 background of the successor first so that S can draw into it.
4409 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4410 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4411 {
4412 xassert (s->next->img == NULL);
4413 x_set_glyph_string_gc (s->next);
4414 x_set_glyph_string_clipping (s->next);
4415 x_draw_glyph_string_background (s->next, 1);
4416 }
97210f4e 4417
06a2c219
GM
4418 /* Set up S->gc, set clipping and draw S. */
4419 x_set_glyph_string_gc (s);
06a2c219 4420
4458cf11
KH
4421 /* Draw relief (if any) in advance for char/composition so that the
4422 glyph string can be drawn over it. */
4423 if (!s->for_overlaps_p
4424 && s->face->box != FACE_NO_BOX
4425 && (s->first_glyph->type == CHAR_GLYPH
4426 || s->first_glyph->type == COMPOSITE_GLYPH))
4427
4428 {
e6269cbb 4429 x_set_glyph_string_clipping (s);
4458cf11
KH
4430 x_draw_glyph_string_background (s, 1);
4431 x_draw_glyph_string_box (s);
e6269cbb 4432 x_set_glyph_string_clipping (s);
4458cf11
KH
4433 relief_drawn_p = 1;
4434 }
e6269cbb
GM
4435 else
4436 x_set_glyph_string_clipping (s);
4458cf11 4437
06a2c219
GM
4438 switch (s->first_glyph->type)
4439 {
4440 case IMAGE_GLYPH:
4441 x_draw_image_glyph_string (s);
4442 break;
4443
4444 case STRETCH_GLYPH:
4445 x_draw_stretch_glyph_string (s);
4446 break;
4447
4448 case CHAR_GLYPH:
66ac4b0e
GM
4449 if (s->for_overlaps_p)
4450 s->background_filled_p = 1;
4451 else
4452 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4453 x_draw_glyph_string_foreground (s);
4454 break;
4455
b4192550
KH
4456 case COMPOSITE_GLYPH:
4457 if (s->for_overlaps_p || s->gidx > 0)
4458 s->background_filled_p = 1;
4459 else
4460 x_draw_glyph_string_background (s, 1);
4461 x_draw_composite_glyph_string_foreground (s);
4462 break;
4463
06a2c219
GM
4464 default:
4465 abort ();
4466 }
4467
66ac4b0e 4468 if (!s->for_overlaps_p)
06a2c219 4469 {
66ac4b0e
GM
4470 /* Draw underline. */
4471 if (s->face->underline_p)
4472 {
e24e84cc
GM
4473 unsigned long tem, h;
4474 int y;
06a2c219 4475
e24e84cc 4476 /* Get the underline thickness. Default is 1 pixel. */
66ac4b0e
GM
4477 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4478 h = 1;
e24e84cc
GM
4479
4480 /* Get the underline position. This is the recommended
4481 vertical offset in pixels from the baseline to the top of
4482 the underline. This is a signed value according to the
4483 specs, and its default is
4484
4485 ROUND ((maximum descent) / 2), with
4486 ROUND(x) = floor (x + 0.5) */
4487
a72d5ce5
GM
4488 if (x_use_underline_position_properties
4489 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
e24e84cc
GM
4490 y = s->ybase + (long) tem;
4491 else if (s->face->font)
4492 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4493 else
a02f1be0 4494 y = s->y + s->height - h;
06a2c219 4495
66ac4b0e 4496 if (s->face->underline_defaulted_p)
e24e84cc
GM
4497 XFillRectangle (s->display, s->window, s->gc,
4498 s->x, y, s->width, h);
66ac4b0e
GM
4499 else
4500 {
4501 XGCValues xgcv;
4502 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4503 XSetForeground (s->display, s->gc, s->face->underline_color);
e24e84cc
GM
4504 XFillRectangle (s->display, s->window, s->gc,
4505 s->x, y, s->width, h);
66ac4b0e
GM
4506 XSetForeground (s->display, s->gc, xgcv.foreground);
4507 }
dc6f92b8 4508 }
07e34cb0 4509
66ac4b0e
GM
4510 /* Draw overline. */
4511 if (s->face->overline_p)
06a2c219 4512 {
66ac4b0e
GM
4513 unsigned long dy = 0, h = 1;
4514
4515 if (s->face->overline_color_defaulted_p)
4516 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4517 s->width, h);
4518 else
4519 {
4520 XGCValues xgcv;
4521 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4522 XSetForeground (s->display, s->gc, s->face->overline_color);
4523 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4524 s->width, h);
4525 XSetForeground (s->display, s->gc, xgcv.foreground);
4526 }
06a2c219 4527 }
06a2c219 4528
66ac4b0e
GM
4529 /* Draw strike-through. */
4530 if (s->face->strike_through_p)
06a2c219 4531 {
66ac4b0e
GM
4532 unsigned long h = 1;
4533 unsigned long dy = (s->height - h) / 2;
4534
4535 if (s->face->strike_through_color_defaulted_p)
4536 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4537 s->width, h);
4538 else
4539 {
4540 XGCValues xgcv;
4541 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4542 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4543 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4544 s->width, h);
4545 XSetForeground (s->display, s->gc, xgcv.foreground);
4546 }
06a2c219 4547 }
06a2c219 4548
4458cf11
KH
4549 /* Draw relief if not yet drawn. */
4550 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
66ac4b0e
GM
4551 x_draw_glyph_string_box (s);
4552 }
06a2c219
GM
4553
4554 /* Reset clipping. */
4555 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4556}
07e34cb0 4557
06a2c219 4558
b4192550
KH
4559static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4560 struct face **, int));
06a2c219 4561
06a2c219 4562
209f68d9
GM
4563/* Fill glyph string S with composition components specified by S->cmp.
4564
b4192550
KH
4565 FACES is an array of faces for all components of this composition.
4566 S->gidx is the index of the first component for S.
4567 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4568 use its physical height for clipping.
06a2c219 4569
b4192550 4570 Value is the index of a component not in S. */
07e34cb0 4571
b4192550
KH
4572static int
4573x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4574 struct glyph_string *s;
b4192550 4575 struct face **faces;
66ac4b0e 4576 int overlaps_p;
07e34cb0 4577{
b4192550 4578 int i;
06a2c219 4579
b4192550 4580 xassert (s);
06a2c219 4581
b4192550 4582 s->for_overlaps_p = overlaps_p;
06a2c219 4583
b4192550
KH
4584 s->face = faces[s->gidx];
4585 s->font = s->face->font;
4586 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4587
b4192550
KH
4588 /* For all glyphs of this composition, starting at the offset
4589 S->gidx, until we reach the end of the definition or encounter a
4590 glyph that requires the different face, add it to S. */
4591 ++s->nchars;
4592 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4593 ++s->nchars;
06a2c219 4594
b4192550
KH
4595 /* All glyph strings for the same composition has the same width,
4596 i.e. the width set for the first component of the composition. */
06a2c219 4597
06a2c219
GM
4598 s->width = s->first_glyph->pixel_width;
4599
4600 /* If the specified font could not be loaded, use the frame's
4601 default font, but record the fact that we couldn't load it in
4602 the glyph string so that we can draw rectangles for the
4603 characters of the glyph string. */
4604 if (s->font == NULL)
4605 {
4606 s->font_not_found_p = 1;
4607 s->font = FRAME_FONT (s->f);
4608 }
4609
4610 /* Adjust base line for subscript/superscript text. */
4611 s->ybase += s->first_glyph->voffset;
4612
4613 xassert (s->face && s->face->gc);
4614
4615 /* This glyph string must always be drawn with 16-bit functions. */
4616 s->two_byte_p = 1;
b4192550
KH
4617
4618 return s->gidx + s->nchars;
06a2c219
GM
4619}
4620
4621
209f68d9
GM
4622/* Fill glyph string S from a sequence of character glyphs.
4623
06a2c219 4624 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4625 first glyph to consider, END is the index of the last + 1.
4626 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4627 use its physical height for clipping.
66ac4b0e
GM
4628
4629 Value is the index of the first glyph not in S. */
06a2c219
GM
4630
4631static int
66ac4b0e 4632x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4633 struct glyph_string *s;
4634 int face_id;
66ac4b0e 4635 int start, end, overlaps_p;
06a2c219
GM
4636{
4637 struct glyph *glyph, *last;
4638 int voffset;
ee569018 4639 int glyph_not_available_p;
06a2c219 4640
06a2c219
GM
4641 xassert (s->f == XFRAME (s->w->frame));
4642 xassert (s->nchars == 0);
4643 xassert (start >= 0 && end > start);
4644
66ac4b0e 4645 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4646 glyph = s->row->glyphs[s->area] + start;
4647 last = s->row->glyphs[s->area] + end;
4648 voffset = glyph->voffset;
4649
ee569018
KH
4650 glyph_not_available_p = glyph->glyph_not_available_p;
4651
06a2c219
GM
4652 while (glyph < last
4653 && glyph->type == CHAR_GLYPH
4654 && glyph->voffset == voffset
ee569018
KH
4655 /* Same face id implies same font, nowadays. */
4656 && glyph->face_id == face_id
4657 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4658 {
ee569018
KH
4659 int two_byte_p;
4660
06a2c219 4661 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4662 s->char2b + s->nchars,
4663 &two_byte_p);
4664 s->two_byte_p = two_byte_p;
06a2c219
GM
4665 ++s->nchars;
4666 xassert (s->nchars <= end - start);
4667 s->width += glyph->pixel_width;
4668 ++glyph;
4669 }
4670
4671 s->font = s->face->font;
4672 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4673
4674 /* If the specified font could not be loaded, use the frame's font,
4675 but record the fact that we couldn't load it in
4676 S->font_not_found_p so that we can draw rectangles for the
4677 characters of the glyph string. */
ee569018 4678 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4679 {
4680 s->font_not_found_p = 1;
4681 s->font = FRAME_FONT (s->f);
4682 }
4683
4684 /* Adjust base line for subscript/superscript text. */
4685 s->ybase += voffset;
66ac4b0e 4686
06a2c219
GM
4687 xassert (s->face && s->face->gc);
4688 return glyph - s->row->glyphs[s->area];
07e34cb0 4689}
dc6f92b8 4690
06a2c219
GM
4691
4692/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4693
dfcf069d 4694static void
06a2c219
GM
4695x_fill_image_glyph_string (s)
4696 struct glyph_string *s;
4697{
4698 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4699 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4700 xassert (s->img);
43d120d8 4701 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4702 s->font = s->face->font;
4703 s->width = s->first_glyph->pixel_width;
4704
4705 /* Adjust base line for subscript/superscript text. */
4706 s->ybase += s->first_glyph->voffset;
4707}
4708
4709
209f68d9 4710/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4711
209f68d9
GM
4712 ROW is the glyph row in which the glyphs are found, AREA is the
4713 area within the row. START is the index of the first glyph to
4714 consider, END is the index of the last + 1.
4715
4716 Value is the index of the first glyph not in S. */
4717
4718static int
4719x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4720 struct glyph_string *s;
209f68d9
GM
4721 struct glyph_row *row;
4722 enum glyph_row_area area;
4723 int start, end;
06a2c219 4724{
209f68d9
GM
4725 struct glyph *glyph, *last;
4726 int voffset, face_id;
4727
06a2c219 4728 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4729
4730 glyph = s->row->glyphs[s->area] + start;
4731 last = s->row->glyphs[s->area] + end;
4732 face_id = glyph->face_id;
4733 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4734 s->font = s->face->font;
209f68d9
GM
4735 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4736 s->width = glyph->pixel_width;
4737 voffset = glyph->voffset;
4738
4739 for (++glyph;
4740 (glyph < last
4741 && glyph->type == STRETCH_GLYPH
4742 && glyph->voffset == voffset
4743 && glyph->face_id == face_id);
4744 ++glyph)
4745 s->width += glyph->pixel_width;
06a2c219
GM
4746
4747 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4748 s->ybase += voffset;
4749
c296fc01
GM
4750 /* The case that face->gc == 0 is handled when drawing the glyph
4751 string by calling PREPARE_FACE_FOR_DISPLAY. */
4752 xassert (s->face);
209f68d9 4753 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4754}
4755
4756
4757/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4758 of XChar2b structures for S; it can't be allocated in
4759 x_init_glyph_string because it must be allocated via `alloca'. W
4760 is the window on which S is drawn. ROW and AREA are the glyph row
4761 and area within the row from which S is constructed. START is the
4762 index of the first glyph structure covered by S. HL is a
4763 face-override for drawing S. */
4764
4765static void
4766x_init_glyph_string (s, char2b, w, row, area, start, hl)
4767 struct glyph_string *s;
4768 XChar2b *char2b;
4769 struct window *w;
4770 struct glyph_row *row;
4771 enum glyph_row_area area;
4772 int start;
4773 enum draw_glyphs_face hl;
4774{
4775 bzero (s, sizeof *s);
4776 s->w = w;
4777 s->f = XFRAME (w->frame);
4778 s->display = FRAME_X_DISPLAY (s->f);
4779 s->window = FRAME_X_WINDOW (s->f);
4780 s->char2b = char2b;
4781 s->hl = hl;
4782 s->row = row;
4783 s->area = area;
4784 s->first_glyph = row->glyphs[area] + start;
4785 s->height = row->height;
4786 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4787
9ea173e8
GM
4788 /* Display the internal border below the tool-bar window. */
4789 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4790 s->y -= s->f->output_data.x->internal_border_width;
4791
4792 s->ybase = s->y + row->ascent;
4793}
4794
4795
4796/* Set background width of glyph string S. START is the index of the
4797 first glyph following S. LAST_X is the right-most x-position + 1
4798 in the drawing area. */
4799
4800static INLINE void
4801x_set_glyph_string_background_width (s, start, last_x)
4802 struct glyph_string *s;
4803 int start;
4804 int last_x;
4805{
4806 /* If the face of this glyph string has to be drawn to the end of
4807 the drawing area, set S->extends_to_end_of_line_p. */
4808 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4809
4810 if (start == s->row->used[s->area]
eb79f5cc 4811 && s->area == TEXT_AREA
7b0870b2
GM
4812 && ((s->hl == DRAW_NORMAL_TEXT
4813 && (s->row->fill_line_p
4814 || s->face->background != default_face->background
4815 || s->face->stipple != default_face->stipple
4816 || s->row->mouse_face_p))
4817 || s->hl == DRAW_MOUSE_FACE))
4818 s->extends_to_end_of_line_p = 1;
06a2c219
GM
4819
4820 /* If S extends its face to the end of the line, set its
4821 background_width to the distance to the right edge of the drawing
4822 area. */
4823 if (s->extends_to_end_of_line_p)
1da3fd71 4824 s->background_width = last_x - s->x + 1;
06a2c219
GM
4825 else
4826 s->background_width = s->width;
4827}
4828
4829
4830/* Add a glyph string for a stretch glyph to the list of strings
4831 between HEAD and TAIL. START is the index of the stretch glyph in
4832 row area AREA of glyph row ROW. END is the index of the last glyph
4833 in that glyph row area. X is the current output position assigned
4834 to the new glyph string constructed. HL overrides that face of the
4835 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4836 is the right-most x-position of the drawing area. */
4837
8abee2e1
DL
4838/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4839 and below -- keep them on one line. */
4840#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4841 do \
4842 { \
4843 s = (struct glyph_string *) alloca (sizeof *s); \
4844 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4845 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4846 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4847 s->x = (X); \
4848 } \
4849 while (0)
4850
4851
4852/* Add a glyph string for an image glyph to the list of strings
4853 between HEAD and TAIL. START is the index of the image glyph in
4854 row area AREA of glyph row ROW. END is the index of the last glyph
4855 in that glyph row area. X is the current output position assigned
4856 to the new glyph string constructed. HL overrides that face of the
4857 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4858 is the right-most x-position of the drawing area. */
4859
8abee2e1 4860#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4861 do \
4862 { \
4863 s = (struct glyph_string *) alloca (sizeof *s); \
4864 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4865 x_fill_image_glyph_string (s); \
4866 x_append_glyph_string (&HEAD, &TAIL, s); \
4867 ++START; \
4868 s->x = (X); \
4869 } \
4870 while (0)
4871
4872
4873/* Add a glyph string for a sequence of character glyphs to the list
4874 of strings between HEAD and TAIL. START is the index of the first
4875 glyph in row area AREA of glyph row ROW that is part of the new
4876 glyph string. END is the index of the last glyph in that glyph row
4877 area. X is the current output position assigned to the new glyph
4878 string constructed. HL overrides that face of the glyph; e.g. it
4879 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4880 right-most x-position of the drawing area. */
4881
8abee2e1 4882#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4883 do \
4884 { \
3e71d8f2 4885 int c, face_id; \
06a2c219
GM
4886 XChar2b *char2b; \
4887 \
43d120d8 4888 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4889 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4890 \
b4192550
KH
4891 s = (struct glyph_string *) alloca (sizeof *s); \
4892 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4893 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4894 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4895 s->x = (X); \
4896 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4897 OVERLAPS_P); \
06a2c219
GM
4898 } \
4899 while (0)
4900
4901
b4192550
KH
4902/* Add a glyph string for a composite sequence to the list of strings
4903 between HEAD and TAIL. START is the index of the first glyph in
4904 row area AREA of glyph row ROW that is part of the new glyph
4905 string. END is the index of the last glyph in that glyph row area.
4906 X is the current output position assigned to the new glyph string
4907 constructed. HL overrides that face of the glyph; e.g. it is
4908 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4909 x-position of the drawing area. */
4910
6c27ec25 4911#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4912 do { \
43d120d8
KH
4913 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4914 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4915 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4916 struct composition *cmp = composition_table[cmp_id]; \
4917 int glyph_len = cmp->glyph_len; \
4918 XChar2b *char2b; \
4919 struct face **faces; \
4920 struct glyph_string *first_s = NULL; \
4921 int n; \
4922 \
ee569018 4923 base_face = base_face->ascii_face; \
b4192550
KH
4924 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4925 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4926 /* At first, fill in `char2b' and `faces'. */ \
4927 for (n = 0; n < glyph_len; n++) \
4928 { \
43d120d8 4929 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4930 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4931 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4932 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4933 this_face_id, char2b + n, 1); \
b4192550
KH
4934 } \
4935 \
4936 /* Make glyph_strings for each glyph sequence that is drawable by \
4937 the same face, and append them to HEAD/TAIL. */ \
4938 for (n = 0; n < cmp->glyph_len;) \
4939 { \
4940 s = (struct glyph_string *) alloca (sizeof *s); \
4941 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4942 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4943 s->cmp = cmp; \
4944 s->gidx = n; \
b4192550
KH
4945 s->x = (X); \
4946 \
4947 if (n == 0) \
4948 first_s = s; \
4949 \
4950 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4951 } \
4952 \
4953 ++START; \
4954 s = first_s; \
4955 } while (0)
4956
4957
06a2c219
GM
4958/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4959 of AREA of glyph row ROW on window W between indices START and END.
4960 HL overrides the face for drawing glyph strings, e.g. it is
4961 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4962 x-positions of the drawing area.
4963
4964 This is an ugly monster macro construct because we must use alloca
4965 to allocate glyph strings (because x_draw_glyphs can be called
4966 asynchronously). */
4967
8abee2e1 4968#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4969 do \
4970 { \
4971 HEAD = TAIL = NULL; \
4972 while (START < END) \
4973 { \
4974 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4975 switch (first_glyph->type) \
4976 { \
4977 case CHAR_GLYPH: \
4978 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4979 TAIL, HL, X, LAST_X, \
4980 OVERLAPS_P); \
06a2c219
GM
4981 break; \
4982 \
b4192550
KH
4983 case COMPOSITE_GLYPH: \
4984 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4985 HEAD, TAIL, HL, X, LAST_X,\
4986 OVERLAPS_P); \
4987 break; \
4988 \
06a2c219
GM
4989 case STRETCH_GLYPH: \
4990 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4991 HEAD, TAIL, HL, X, LAST_X); \
4992 break; \
4993 \
4994 case IMAGE_GLYPH: \
4995 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4996 TAIL, HL, X, LAST_X); \
4997 break; \
4998 \
4999 default: \
5000 abort (); \
5001 } \
5002 \
5003 x_set_glyph_string_background_width (s, START, LAST_X); \
5004 (X) += s->width; \
5005 } \
5006 } \
5007 while (0)
5008
5009
5010/* Draw glyphs between START and END in AREA of ROW on window W,
5011 starting at x-position X. X is relative to AREA in W. HL is a
5012 face-override with the following meaning:
5013
5014 DRAW_NORMAL_TEXT draw normally
5015 DRAW_CURSOR draw in cursor face
5016 DRAW_MOUSE_FACE draw in mouse face.
5017 DRAW_INVERSE_VIDEO draw in mode line face
5018 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
5019 DRAW_IMAGE_RAISED draw an image with a raised relief around it
5020
66ac4b0e
GM
5021 If OVERLAPS_P is non-zero, draw only the foreground of characters
5022 and clip to the physical height of ROW.
5023
06a2c219
GM
5024 Value is the x-position reached, relative to AREA of W. */
5025
5026static int
f0a48a01 5027x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
06a2c219
GM
5028 struct window *w;
5029 int x;
5030 struct glyph_row *row;
5031 enum glyph_row_area area;
5032 int start, end;
5033 enum draw_glyphs_face hl;
66ac4b0e 5034 int overlaps_p;
dc6f92b8 5035{
06a2c219
GM
5036 struct glyph_string *head, *tail;
5037 struct glyph_string *s;
5038 int last_x, area_width;
5039 int x_reached;
5040 int i, j;
5041
5042 /* Let's rather be paranoid than getting a SEGV. */
06a2c219 5043 end = min (end, row->used[area]);
a8710abf
GM
5044 start = max (0, start);
5045 start = min (end, start);
06a2c219
GM
5046
5047 /* Translate X to frame coordinates. Set last_x to the right
5048 end of the drawing area. */
5049 if (row->full_width_p)
5050 {
5051 /* X is relative to the left edge of W, without scroll bars
5052 or flag areas. */
5053 struct frame *f = XFRAME (w->frame);
110859fc 5054 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 5055 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 5056
06a2c219
GM
5057 x += window_left_x;
5058 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
5059 last_x = window_left_x + area_width;
5060
5061 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
5062 {
110859fc 5063 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
5064 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
5065 last_x += width;
5066 else
5067 x -= width;
5068 }
dc6f92b8 5069
b9432a85 5070 x += FRAME_INTERNAL_BORDER_WIDTH (f);
98fedd97 5071 last_x += FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
5072 }
5073 else
dc6f92b8 5074 {
06a2c219
GM
5075 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
5076 area_width = window_box_width (w, area);
5077 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
5078 }
5079
06a2c219
GM
5080 /* Build a doubly-linked list of glyph_string structures between
5081 head and tail from what we have to draw. Note that the macro
5082 BUILD_GLYPH_STRINGS will modify its start parameter. That's
5083 the reason we use a separate variable `i'. */
5084 i = start;
66ac4b0e
GM
5085 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
5086 overlaps_p);
06a2c219
GM
5087 if (tail)
5088 x_reached = tail->x + tail->background_width;
5089 else
5090 x_reached = x;
90e65f07 5091
06a2c219
GM
5092 /* If there are any glyphs with lbearing < 0 or rbearing > width in
5093 the row, redraw some glyphs in front or following the glyph
5094 strings built above. */
a8710abf 5095 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
5096 {
5097 int dummy_x = 0;
5098 struct glyph_string *h, *t;
5099
5100 /* Compute overhangs for all glyph strings. */
5101 for (s = head; s; s = s->next)
5102 x_compute_glyph_string_overhangs (s);
5103
5104 /* Prepend glyph strings for glyphs in front of the first glyph
5105 string that are overwritten because of the first glyph
5106 string's left overhang. The background of all strings
5107 prepended must be drawn because the first glyph string
5108 draws over it. */
5109 i = x_left_overwritten (head);
5110 if (i >= 0)
5111 {
5112 j = i;
5113 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
5114 DRAW_NORMAL_TEXT, dummy_x, last_x,
5115 overlaps_p);
06a2c219 5116 start = i;
06a2c219
GM
5117 x_compute_overhangs_and_x (t, head->x, 1);
5118 x_prepend_glyph_string_lists (&head, &tail, h, t);
5119 }
58769bee 5120
06a2c219
GM
5121 /* Prepend glyph strings for glyphs in front of the first glyph
5122 string that overwrite that glyph string because of their
5123 right overhang. For these strings, only the foreground must
5124 be drawn, because it draws over the glyph string at `head'.
5125 The background must not be drawn because this would overwrite
5126 right overhangs of preceding glyphs for which no glyph
5127 strings exist. */
5128 i = x_left_overwriting (head);
5129 if (i >= 0)
5130 {
5131 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
5132 DRAW_NORMAL_TEXT, dummy_x, last_x,
5133 overlaps_p);
06a2c219
GM
5134 for (s = h; s; s = s->next)
5135 s->background_filled_p = 1;
06a2c219
GM
5136 x_compute_overhangs_and_x (t, head->x, 1);
5137 x_prepend_glyph_string_lists (&head, &tail, h, t);
5138 }
dbcb258a 5139
06a2c219
GM
5140 /* Append glyphs strings for glyphs following the last glyph
5141 string tail that are overwritten by tail. The background of
5142 these strings has to be drawn because tail's foreground draws
5143 over it. */
5144 i = x_right_overwritten (tail);
5145 if (i >= 0)
5146 {
5147 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
5148 DRAW_NORMAL_TEXT, x, last_x,
5149 overlaps_p);
06a2c219
GM
5150 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5151 x_append_glyph_string_lists (&head, &tail, h, t);
06a2c219 5152 }
dc6f92b8 5153
06a2c219
GM
5154 /* Append glyph strings for glyphs following the last glyph
5155 string tail that overwrite tail. The foreground of such
5156 glyphs has to be drawn because it writes into the background
5157 of tail. The background must not be drawn because it could
5158 paint over the foreground of following glyphs. */
5159 i = x_right_overwriting (tail);
5160 if (i >= 0)
5161 {
5162 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
5163 DRAW_NORMAL_TEXT, x, last_x,
5164 overlaps_p);
06a2c219
GM
5165 for (s = h; s; s = s->next)
5166 s->background_filled_p = 1;
5167 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5168 x_append_glyph_string_lists (&head, &tail, h, t);
06a2c219
GM
5169 }
5170 }
58769bee 5171
06a2c219
GM
5172 /* Draw all strings. */
5173 for (s = head; s; s = s->next)
5174 x_draw_glyph_string (s);
dc6f92b8 5175
f0a48a01
GM
5176 if (area == TEXT_AREA)
5177 {
5178 int x0 = head ? head->x : x;
5179 int x1 = tail ? tail->x + tail->background_width : x;
5180
5181 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5182 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5183
5184 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5185 {
5186 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5187 x0 -= left_area_width;
5188 x1 -= left_area_width;
5189 }
5190
5191 notice_overwritten_cursor (w, x0, x1);
5192 }
5193
06a2c219
GM
5194 /* Value is the x-position up to which drawn, relative to AREA of W.
5195 This doesn't include parts drawn because of overhangs. */
5196 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5197 if (!row->full_width_p)
5198 {
f0a48a01 5199 if (area > LEFT_MARGIN_AREA && XFASTINT (w->left_margin_width) != 0)
06a2c219
GM
5200 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5201 if (area > TEXT_AREA)
5202 x_reached -= window_box_width (w, TEXT_AREA);
5203 }
a8710abf 5204
06a2c219
GM
5205 return x_reached;
5206}
dc6f92b8 5207
dc6f92b8 5208
66ac4b0e
GM
5209/* Fix the display of area AREA of overlapping row ROW in window W. */
5210
5211static void
5212x_fix_overlapping_area (w, row, area)
5213 struct window *w;
5214 struct glyph_row *row;
5215 enum glyph_row_area area;
5216{
5217 int i, x;
5218
5219 BLOCK_INPUT;
5220
5221 if (area == LEFT_MARGIN_AREA)
5222 x = 0;
5223 else if (area == TEXT_AREA)
5224 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5225 else
5226 x = (window_box_width (w, LEFT_MARGIN_AREA)
5227 + window_box_width (w, TEXT_AREA));
5228
5229 for (i = 0; i < row->used[area];)
5230 {
5231 if (row->glyphs[area][i].overlaps_vertically_p)
5232 {
5233 int start = i, start_x = x;
5234
5235 do
5236 {
5237 x += row->glyphs[area][i].pixel_width;
5238 ++i;
5239 }
5240 while (i < row->used[area]
5241 && row->glyphs[area][i].overlaps_vertically_p);
5242
5243 x_draw_glyphs (w, start_x, row, area, start, i,
f0a48a01 5244 DRAW_NORMAL_TEXT, 1);
66ac4b0e
GM
5245 }
5246 else
5247 {
5248 x += row->glyphs[area][i].pixel_width;
5249 ++i;
5250 }
5251 }
5252
5253 UNBLOCK_INPUT;
5254}
5255
5256
06a2c219
GM
5257/* Output LEN glyphs starting at START at the nominal cursor position.
5258 Advance the nominal cursor over the text. The global variable
5259 updated_window contains the window being updated, updated_row is
5260 the glyph row being updated, and updated_area is the area of that
5261 row being updated. */
dc6f92b8 5262
06a2c219
GM
5263static void
5264x_write_glyphs (start, len)
5265 struct glyph *start;
5266 int len;
5267{
f0a48a01 5268 int x, hpos;
d9cdbb3d 5269
06a2c219 5270 xassert (updated_window && updated_row);
dc6f92b8 5271 BLOCK_INPUT;
06a2c219
GM
5272
5273 /* Write glyphs. */
dc6f92b8 5274
06a2c219
GM
5275 hpos = start - updated_row->glyphs[updated_area];
5276 x = x_draw_glyphs (updated_window, output_cursor.x,
5277 updated_row, updated_area,
5278 hpos, hpos + len,
f0a48a01 5279 DRAW_NORMAL_TEXT, 0);
dc6f92b8
JB
5280
5281 UNBLOCK_INPUT;
06a2c219
GM
5282
5283 /* Advance the output cursor. */
5284 output_cursor.hpos += len;
5285 output_cursor.x = x;
dc6f92b8
JB
5286}
5287
0cdd0c9f 5288
06a2c219 5289/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 5290
06a2c219
GM
5291static void
5292x_insert_glyphs (start, len)
5293 struct glyph *start;
5294 register int len;
5295{
5296 struct frame *f;
5297 struct window *w;
5298 int line_height, shift_by_width, shifted_region_width;
5299 struct glyph_row *row;
5300 struct glyph *glyph;
5301 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 5302
06a2c219 5303 xassert (updated_window && updated_row);
0cdd0c9f 5304 BLOCK_INPUT;
06a2c219
GM
5305 w = updated_window;
5306 f = XFRAME (WINDOW_FRAME (w));
5307
5308 /* Get the height of the line we are in. */
5309 row = updated_row;
5310 line_height = row->height;
5311
5312 /* Get the width of the glyphs to insert. */
5313 shift_by_width = 0;
5314 for (glyph = start; glyph < start + len; ++glyph)
5315 shift_by_width += glyph->pixel_width;
5316
5317 /* Get the width of the region to shift right. */
5318 shifted_region_width = (window_box_width (w, updated_area)
5319 - output_cursor.x
5320 - shift_by_width);
5321
5322 /* Shift right. */
bf0ab8a2 5323 frame_x = window_box_left (w, updated_area) + output_cursor.x;
06a2c219
GM
5324 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5325 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5326 f->output_data.x->normal_gc,
5327 frame_x, frame_y,
5328 shifted_region_width, line_height,
5329 frame_x + shift_by_width, frame_y);
5330
5331 /* Write the glyphs. */
5332 hpos = start - row->glyphs[updated_area];
5333 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
f0a48a01 5334 DRAW_NORMAL_TEXT, 0);
06a2c219
GM
5335
5336 /* Advance the output cursor. */
5337 output_cursor.hpos += len;
5338 output_cursor.x += shift_by_width;
0cdd0c9f
RS
5339 UNBLOCK_INPUT;
5340}
0cdd0c9f 5341
0cdd0c9f 5342
06a2c219
GM
5343/* Delete N glyphs at the nominal cursor position. Not implemented
5344 for X frames. */
c83febd7
RS
5345
5346static void
06a2c219
GM
5347x_delete_glyphs (n)
5348 register int n;
c83febd7 5349{
06a2c219 5350 abort ();
c83febd7
RS
5351}
5352
0cdd0c9f 5353
c5e6e06b
GM
5354/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5355 If they are <= 0, this is probably an error. */
5356
5357void
5358x_clear_area (dpy, window, x, y, width, height, exposures)
5359 Display *dpy;
5360 Window window;
5361 int x, y;
5362 int width, height;
5363 int exposures;
5364{
5365 xassert (width > 0 && height > 0);
5366 XClearArea (dpy, window, x, y, width, height, exposures);
5367}
5368
5369
06a2c219
GM
5370/* Erase the current text line from the nominal cursor position
5371 (inclusive) to pixel column TO_X (exclusive). The idea is that
5372 everything from TO_X onward is already erased.
5373
5374 TO_X is a pixel position relative to updated_area of
5375 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 5376
06a2c219
GM
5377static void
5378x_clear_end_of_line (to_x)
5379 int to_x;
5380{
5381 struct frame *f;
5382 struct window *w = updated_window;
5383 int max_x, min_y, max_y;
5384 int from_x, from_y, to_y;
5385
5386 xassert (updated_window && updated_row);
5387 f = XFRAME (w->frame);
5388
5389 if (updated_row->full_width_p)
5390 {
5391 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5392 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5393 && !w->pseudo_window_p)
5394 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 5395 }
06a2c219
GM
5396 else
5397 max_x = window_box_width (w, updated_area);
5398 max_y = window_text_bottom_y (w);
dc6f92b8 5399
06a2c219
GM
5400 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5401 of window. For TO_X > 0, truncate to end of drawing area. */
5402 if (to_x == 0)
5403 return;
5404 else if (to_x < 0)
5405 to_x = max_x;
5406 else
5407 to_x = min (to_x, max_x);
dbc4e1c1 5408
06a2c219
GM
5409 to_y = min (max_y, output_cursor.y + updated_row->height);
5410
5411 /* Notice if the cursor will be cleared by this operation. */
5412 if (!updated_row->full_width_p)
f0a48a01 5413 notice_overwritten_cursor (w, output_cursor.x, -1);
dbc4e1c1 5414
06a2c219
GM
5415 from_x = output_cursor.x;
5416
5417 /* Translate to frame coordinates. */
5418 if (updated_row->full_width_p)
5419 {
5420 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5421 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5422 }
0cdd0c9f
RS
5423 else
5424 {
06a2c219
GM
5425 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5426 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5427 }
5428
045dee35 5429 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5430 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5431 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5432
5433 /* Prevent inadvertently clearing to end of the X window. */
5434 if (to_x > from_x && to_y > from_y)
5435 {
5436 BLOCK_INPUT;
c5e6e06b
GM
5437 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5438 from_x, from_y, to_x - from_x, to_y - from_y,
5439 False);
06a2c219 5440 UNBLOCK_INPUT;
0cdd0c9f 5441 }
0cdd0c9f 5442}
dbc4e1c1 5443
0cdd0c9f 5444
06a2c219 5445/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5446 frame. Otherwise clear the selected frame. */
06a2c219
GM
5447
5448static void
5449x_clear_frame ()
0cdd0c9f 5450{
06a2c219 5451 struct frame *f;
0cdd0c9f 5452
06a2c219
GM
5453 if (updating_frame)
5454 f = updating_frame;
0cdd0c9f 5455 else
b86bd3dd 5456 f = SELECTED_FRAME ();
58769bee 5457
06a2c219
GM
5458 /* Clearing the frame will erase any cursor, so mark them all as no
5459 longer visible. */
5460 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5461 output_cursor.hpos = output_cursor.vpos = 0;
5462 output_cursor.x = -1;
5463
5464 /* We don't set the output cursor here because there will always
5465 follow an explicit cursor_to. */
5466 BLOCK_INPUT;
5467 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5468
5469 /* We have to clear the scroll bars, too. If we have changed
5470 colors or something like that, then they should be notified. */
5471 x_scroll_bar_clear (f);
0cdd0c9f 5472
06a2c219
GM
5473 XFlush (FRAME_X_DISPLAY (f));
5474 UNBLOCK_INPUT;
dc6f92b8 5475}
06a2c219
GM
5476
5477
dc6f92b8 5478\f
dbc4e1c1
JB
5479/* Invert the middle quarter of the frame for .15 sec. */
5480
06a2c219
GM
5481/* We use the select system call to do the waiting, so we have to make
5482 sure it's available. If it isn't, we just won't do visual bells. */
5483
dbc4e1c1
JB
5484#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5485
06a2c219
GM
5486
5487/* Subtract the `struct timeval' values X and Y, storing the result in
5488 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5489
5490static int
5491timeval_subtract (result, x, y)
5492 struct timeval *result, x, y;
5493{
06a2c219
GM
5494 /* Perform the carry for the later subtraction by updating y. This
5495 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5496 if (x.tv_usec < y.tv_usec)
5497 {
5498 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5499 y.tv_usec -= 1000000 * nsec;
5500 y.tv_sec += nsec;
5501 }
06a2c219 5502
dbc4e1c1
JB
5503 if (x.tv_usec - y.tv_usec > 1000000)
5504 {
5505 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5506 y.tv_usec += 1000000 * nsec;
5507 y.tv_sec -= nsec;
5508 }
5509
06a2c219
GM
5510 /* Compute the time remaining to wait. tv_usec is certainly
5511 positive. */
dbc4e1c1
JB
5512 result->tv_sec = x.tv_sec - y.tv_sec;
5513 result->tv_usec = x.tv_usec - y.tv_usec;
5514
06a2c219
GM
5515 /* Return indication of whether the result should be considered
5516 negative. */
dbc4e1c1
JB
5517 return x.tv_sec < y.tv_sec;
5518}
dc6f92b8 5519
dfcf069d 5520void
f676886a
JB
5521XTflash (f)
5522 struct frame *f;
dc6f92b8 5523{
dbc4e1c1 5524 BLOCK_INPUT;
dc6f92b8 5525
dbc4e1c1
JB
5526 {
5527 GC gc;
dc6f92b8 5528
06a2c219
GM
5529 /* Create a GC that will use the GXxor function to flip foreground
5530 pixels into background pixels. */
dbc4e1c1
JB
5531 {
5532 XGCValues values;
dc6f92b8 5533
dbc4e1c1 5534 values.function = GXxor;
7556890b
RS
5535 values.foreground = (f->output_data.x->foreground_pixel
5536 ^ f->output_data.x->background_pixel);
58769bee 5537
334208b7 5538 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5539 GCFunction | GCForeground, &values);
5540 }
dc6f92b8 5541
dbc4e1c1 5542 {
e84e14c3
RS
5543 /* Get the height not including a menu bar widget. */
5544 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5545 /* Height of each line to flash. */
5546 int flash_height = FRAME_LINE_HEIGHT (f);
5547 /* These will be the left and right margins of the rectangles. */
5548 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5549 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5550
5551 int width;
5552
5553 /* Don't flash the area between a scroll bar and the frame
5554 edge it is next to. */
5555 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5556 {
5557 case vertical_scroll_bar_left:
5558 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5559 break;
5560
5561 case vertical_scroll_bar_right:
5562 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5563 break;
06a2c219
GM
5564
5565 default:
5566 break;
e84e14c3
RS
5567 }
5568
5569 width = flash_right - flash_left;
5570
5571 /* If window is tall, flash top and bottom line. */
5572 if (height > 3 * FRAME_LINE_HEIGHT (f))
5573 {
5574 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5575 flash_left,
5576 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5577 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5578 width, flash_height);
5579 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5580 flash_left,
5581 (height - flash_height
5582 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5583 width, flash_height);
5584 }
5585 else
5586 /* If it is short, flash it all. */
5587 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5588 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5589 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5590
06a2c219 5591 x_flush (f);
dc6f92b8 5592
dbc4e1c1 5593 {
06a2c219 5594 struct timeval wakeup;
dc6f92b8 5595
66c30ea1 5596 EMACS_GET_TIME (wakeup);
dc6f92b8 5597
dbc4e1c1
JB
5598 /* Compute time to wait until, propagating carry from usecs. */
5599 wakeup.tv_usec += 150000;
5600 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5601 wakeup.tv_usec %= 1000000;
5602
101922c3
GM
5603 /* Keep waiting until past the time wakeup or any input gets
5604 available. */
5605 while (! detect_input_pending ())
dbc4e1c1 5606 {
101922c3 5607 struct timeval current;
dbc4e1c1
JB
5608 struct timeval timeout;
5609
101922c3 5610 EMACS_GET_TIME (current);
dbc4e1c1 5611
101922c3
GM
5612 /* Break if result would be negative. */
5613 if (timeval_subtract (&current, wakeup, current))
dbc4e1c1
JB
5614 break;
5615
101922c3
GM
5616 /* How long `select' should wait. */
5617 timeout.tv_sec = 0;
5618 timeout.tv_usec = 10000;
5619
dbc4e1c1 5620 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5621 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5622 }
5623 }
58769bee 5624
e84e14c3
RS
5625 /* If window is tall, flash top and bottom line. */
5626 if (height > 3 * FRAME_LINE_HEIGHT (f))
5627 {
5628 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5629 flash_left,
5630 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5631 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5632 width, flash_height);
5633 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5634 flash_left,
5635 (height - flash_height
5636 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5637 width, flash_height);
5638 }
5639 else
5640 /* If it is short, flash it all. */
5641 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5642 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5643 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5644
334208b7 5645 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5646 x_flush (f);
dc6f92b8 5647 }
dbc4e1c1
JB
5648 }
5649
5650 UNBLOCK_INPUT;
dc6f92b8
JB
5651}
5652
06a2c219 5653#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5654
5655
dc6f92b8
JB
5656/* Make audible bell. */
5657
dfcf069d 5658void
dc6f92b8
JB
5659XTring_bell ()
5660{
b86bd3dd
GM
5661 struct frame *f = SELECTED_FRAME ();
5662
5663 if (FRAME_X_DISPLAY (f))
5664 {
dbc4e1c1 5665#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5666 if (visible_bell)
5667 XTflash (f);
5668 else
dbc4e1c1 5669#endif
b86bd3dd
GM
5670 {
5671 BLOCK_INPUT;
5672 XBell (FRAME_X_DISPLAY (f), 0);
5673 XFlush (FRAME_X_DISPLAY (f));
5674 UNBLOCK_INPUT;
5675 }
dc6f92b8
JB
5676 }
5677}
06a2c219 5678
dc6f92b8 5679\f
06a2c219
GM
5680/* Specify how many text lines, from the top of the window,
5681 should be affected by insert-lines and delete-lines operations.
5682 This, and those operations, are used only within an update
5683 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5684
dfcf069d 5685static void
06a2c219
GM
5686XTset_terminal_window (n)
5687 register int n;
dc6f92b8 5688{
06a2c219 5689 /* This function intentionally left blank. */
dc6f92b8
JB
5690}
5691
06a2c219
GM
5692
5693\f
5694/***********************************************************************
5695 Line Dance
5696 ***********************************************************************/
5697
5698/* Perform an insert-lines or delete-lines operation, inserting N
5699 lines or deleting -N lines at vertical position VPOS. */
5700
dfcf069d 5701static void
06a2c219
GM
5702x_ins_del_lines (vpos, n)
5703 int vpos, n;
dc6f92b8
JB
5704{
5705 abort ();
5706}
06a2c219
GM
5707
5708
5709/* Scroll part of the display as described by RUN. */
dc6f92b8 5710
dfcf069d 5711static void
06a2c219
GM
5712x_scroll_run (w, run)
5713 struct window *w;
5714 struct run *run;
dc6f92b8 5715{
06a2c219
GM
5716 struct frame *f = XFRAME (w->frame);
5717 int x, y, width, height, from_y, to_y, bottom_y;
5718
5719 /* Get frame-relative bounding box of the text display area of W,
5720 without mode lines. Include in this box the flags areas to the
5721 left and right of W. */
5722 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5723 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5724 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5725
5726 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5727 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5728 bottom_y = y + height;
dc6f92b8 5729
06a2c219
GM
5730 if (to_y < from_y)
5731 {
5732 /* Scrolling up. Make sure we don't copy part of the mode
5733 line at the bottom. */
5734 if (from_y + run->height > bottom_y)
5735 height = bottom_y - from_y;
5736 else
5737 height = run->height;
5738 }
dc6f92b8 5739 else
06a2c219
GM
5740 {
5741 /* Scolling down. Make sure we don't copy over the mode line.
5742 at the bottom. */
5743 if (to_y + run->height > bottom_y)
5744 height = bottom_y - to_y;
5745 else
5746 height = run->height;
5747 }
7a13e894 5748
06a2c219
GM
5749 BLOCK_INPUT;
5750
5751 /* Cursor off. Will be switched on again in x_update_window_end. */
5752 updated_window = w;
5753 x_clear_cursor (w);
5754
5755 XCopyArea (FRAME_X_DISPLAY (f),
5756 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5757 f->output_data.x->normal_gc,
5758 x, from_y,
5759 width, height,
5760 x, to_y);
5761
5762 UNBLOCK_INPUT;
5763}
dc6f92b8 5764
dc6f92b8 5765
06a2c219
GM
5766\f
5767/***********************************************************************
5768 Exposure Events
5769 ***********************************************************************/
5770
5771/* Redisplay an exposed area of frame F. X and Y are the upper-left
5772 corner of the exposed rectangle. W and H are width and height of
5773 the exposed area. All are pixel values. W or H zero means redraw
5774 the entire frame. */
dc6f92b8 5775
06a2c219
GM
5776static void
5777expose_frame (f, x, y, w, h)
5778 struct frame *f;
5779 int x, y, w, h;
dc6f92b8 5780{
06a2c219 5781 XRectangle r;
82f053ab 5782 int mouse_face_overwritten_p = 0;
dc6f92b8 5783
06a2c219 5784 TRACE ((stderr, "expose_frame "));
dc6f92b8 5785
06a2c219
GM
5786 /* No need to redraw if frame will be redrawn soon. */
5787 if (FRAME_GARBAGED_P (f))
dc6f92b8 5788 {
06a2c219
GM
5789 TRACE ((stderr, " garbaged\n"));
5790 return;
5791 }
5792
5793 /* If basic faces haven't been realized yet, there is no point in
5794 trying to redraw anything. This can happen when we get an expose
5795 event while Emacs is starting, e.g. by moving another window. */
5796 if (FRAME_FACE_CACHE (f) == NULL
5797 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5798 {
5799 TRACE ((stderr, " no faces\n"));
5800 return;
58769bee 5801 }
06a2c219
GM
5802
5803 if (w == 0 || h == 0)
58769bee 5804 {
06a2c219
GM
5805 r.x = r.y = 0;
5806 r.width = CANON_X_UNIT (f) * f->width;
5807 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5808 }
5809 else
5810 {
06a2c219
GM
5811 r.x = x;
5812 r.y = y;
5813 r.width = w;
5814 r.height = h;
5815 }
5816
5817 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
82f053ab 5818 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
06a2c219 5819
9ea173e8 5820 if (WINDOWP (f->tool_bar_window))
82f053ab
GM
5821 mouse_face_overwritten_p
5822 |= expose_window (XWINDOW (f->tool_bar_window), &r);
06a2c219
GM
5823
5824#ifndef USE_X_TOOLKIT
5825 if (WINDOWP (f->menu_bar_window))
82f053ab
GM
5826 mouse_face_overwritten_p
5827 |= expose_window (XWINDOW (f->menu_bar_window), &r);
06a2c219 5828#endif /* not USE_X_TOOLKIT */
82f053ab
GM
5829
5830 /* Some window managers support a focus-follows-mouse style with
5831 delayed raising of frames. Imagine a partially obscured frame,
5832 and moving the mouse into partially obscured mouse-face on that
5833 frame. The visible part of the mouse-face will be highlighted,
5834 then the WM raises the obscured frame. With at least one WM, KDE
5835 2.1, Emacs is not getting any event for the raising of the frame
5836 (even tried with SubstructureRedirectMask), only Expose events.
5837 These expose events will draw text normally, i.e. not
5838 highlighted. Which means we must redo the highlight here.
5839 Subsume it under ``we love X''. --gerd 2001-08-15 */
5840 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5841 {
5842 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5843 if (f == dpyinfo->mouse_face_mouse_frame)
5844 {
5845 int x = dpyinfo->mouse_face_mouse_x;
5846 int y = dpyinfo->mouse_face_mouse_y;
5847 clear_mouse_face (dpyinfo);
5848 note_mouse_highlight (f, x, y);
5849 }
5850 }
dc6f92b8
JB
5851}
5852
06a2c219
GM
5853
5854/* Redraw (parts) of all windows in the window tree rooted at W that
82f053ab
GM
5855 intersect R. R contains frame pixel coordinates. Value is
5856 non-zero if the exposure overwrites mouse-face. */
06a2c219 5857
82f053ab 5858static int
06a2c219
GM
5859expose_window_tree (w, r)
5860 struct window *w;
5861 XRectangle *r;
dc6f92b8 5862{
82f053ab
GM
5863 struct frame *f = XFRAME (w->frame);
5864 int mouse_face_overwritten_p = 0;
5865
5866 while (w && !FRAME_GARBAGED_P (f))
06a2c219
GM
5867 {
5868 if (!NILP (w->hchild))
82f053ab
GM
5869 mouse_face_overwritten_p
5870 |= expose_window_tree (XWINDOW (w->hchild), r);
06a2c219 5871 else if (!NILP (w->vchild))
82f053ab
GM
5872 mouse_face_overwritten_p
5873 |= expose_window_tree (XWINDOW (w->vchild), r);
5874 else
5875 mouse_face_overwritten_p |= expose_window (w, r);
5876
a02f1be0 5877 w = NILP (w->next) ? NULL : XWINDOW (w->next);
06a2c219 5878 }
82f053ab
GM
5879
5880 return mouse_face_overwritten_p;
06a2c219 5881}
58769bee 5882
dc6f92b8 5883
06a2c219
GM
5884/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5885 which intersects rectangle R. R is in window-relative coordinates. */
5886
5887static void
5888expose_area (w, row, r, area)
5889 struct window *w;
5890 struct glyph_row *row;
5891 XRectangle *r;
5892 enum glyph_row_area area;
5893{
06a2c219
GM
5894 struct glyph *first = row->glyphs[area];
5895 struct glyph *end = row->glyphs[area] + row->used[area];
5896 struct glyph *last;
4bc6dcc7 5897 int first_x, start_x, x;
06a2c219 5898
6fb13182
GM
5899 if (area == TEXT_AREA && row->fill_line_p)
5900 /* If row extends face to end of line write the whole line. */
153f5ed7 5901 x_draw_glyphs (w, 0, row, area, 0, row->used[area],
f0a48a01 5902 DRAW_NORMAL_TEXT, 0);
6fb13182
GM
5903 else
5904 {
4bc6dcc7
GM
5905 /* Set START_X to the window-relative start position for drawing glyphs of
5906 AREA. The first glyph of the text area can be partially visible.
5907 The first glyphs of other areas cannot. */
5908 if (area == LEFT_MARGIN_AREA)
5909 start_x = 0;
5910 else if (area == TEXT_AREA)
5911 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5912 else
5913 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5914 + window_box_width (w, TEXT_AREA));
5915 x = start_x;
5916
6fb13182
GM
5917 /* Find the first glyph that must be redrawn. */
5918 while (first < end
5919 && x + first->pixel_width < r->x)
5920 {
5921 x += first->pixel_width;
5922 ++first;
5923 }
5924
5925 /* Find the last one. */
5926 last = first;
5927 first_x = x;
5928 while (last < end
5929 && x < r->x + r->width)
5930 {
5931 x += last->pixel_width;
5932 ++last;
5933 }
5934
5935 /* Repaint. */
5936 if (last > first)
4bc6dcc7 5937 x_draw_glyphs (w, first_x - start_x, row, area,
6fb13182
GM
5938 first - row->glyphs[area],
5939 last - row->glyphs[area],
f0a48a01 5940 DRAW_NORMAL_TEXT, 0);
6fb13182 5941 }
06a2c219
GM
5942}
5943
58769bee 5944
06a2c219 5945/* Redraw the parts of the glyph row ROW on window W intersecting
82f053ab
GM
5946 rectangle R. R is in window-relative coordinates. Value is
5947 non-zero if mouse-face was overwritten. */
dc6f92b8 5948
82f053ab 5949static int
06a2c219
GM
5950expose_line (w, row, r)
5951 struct window *w;
5952 struct glyph_row *row;
5953 XRectangle *r;
5954{
5955 xassert (row->enabled_p);
5956
5957 if (row->mode_line_p || w->pseudo_window_p)
5958 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
f0a48a01 5959 DRAW_NORMAL_TEXT, 0);
06a2c219
GM
5960 else
5961 {
5962 if (row->used[LEFT_MARGIN_AREA])
5963 expose_area (w, row, r, LEFT_MARGIN_AREA);
5964 if (row->used[TEXT_AREA])
5965 expose_area (w, row, r, TEXT_AREA);
5966 if (row->used[RIGHT_MARGIN_AREA])
5967 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5968 x_draw_row_bitmaps (w, row);
5969 }
82f053ab
GM
5970
5971 return row->mouse_face_p;
06a2c219 5972}
dc6f92b8 5973
58769bee 5974
06a2c219
GM
5975/* Return non-zero if W's cursor intersects rectangle R. */
5976
5977static int
5978x_phys_cursor_in_rect_p (w, r)
5979 struct window *w;
5980 XRectangle *r;
5981{
5982 XRectangle cr, result;
5983 struct glyph *cursor_glyph;
5984
5985 cursor_glyph = get_phys_cursor_glyph (w);
5986 if (cursor_glyph)
5987 {
5988 cr.x = w->phys_cursor.x;
5989 cr.y = w->phys_cursor.y;
5990 cr.width = cursor_glyph->pixel_width;
5991 cr.height = w->phys_cursor_height;
5992 return x_intersect_rectangles (&cr, r, &result);
5993 }
5994 else
5995 return 0;
dc6f92b8 5996}
dc6f92b8 5997
06a2c219 5998
a02f1be0
GM
5999/* Redraw the part of window W intersection rectangle FR. Pixel
6000 coordinates in FR are frame-relative. Call this function with
82f053ab
GM
6001 input blocked. Value is non-zero if the exposure overwrites
6002 mouse-face. */
dc6f92b8 6003
a39202f6 6004static int
a02f1be0 6005expose_window (w, fr)
06a2c219 6006 struct window *w;
a02f1be0 6007 XRectangle *fr;
dc6f92b8 6008{
a02f1be0 6009 struct frame *f = XFRAME (w->frame);
a02f1be0 6010 XRectangle wr, r;
82f053ab 6011 int mouse_face_overwritten_p = 0;
dc6f92b8 6012
80c32bcc
GM
6013 /* If window is not yet fully initialized, do nothing. This can
6014 happen when toolkit scroll bars are used and a window is split.
6015 Reconfiguring the scroll bar will generate an expose for a newly
6016 created window. */
a39202f6 6017 if (w->current_matrix == NULL)
82f053ab 6018 return 0;
a39202f6
GM
6019
6020 /* When we're currently updating the window, display and current
6021 matrix usually don't agree. Arrange for a thorough display
6022 later. */
6023 if (w == updated_window)
6024 {
6025 SET_FRAME_GARBAGED (f);
6026 return 0;
6027 }
80c32bcc 6028
a39202f6 6029 /* Frame-relative pixel rectangle of W. */
a02f1be0
GM
6030 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
6031 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
6032 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
6033 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
6034
a39202f6
GM
6035 if (x_intersect_rectangles (fr, &wr, &r))
6036 {
6037 int yb = window_text_bottom_y (w);
6038 struct glyph_row *row;
6039 int cursor_cleared_p;
a02f1be0 6040
a39202f6
GM
6041 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
6042 r.x, r.y, r.width, r.height));
dc6f92b8 6043
a39202f6
GM
6044 /* Convert to window coordinates. */
6045 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
6046 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
dc6f92b8 6047
a39202f6
GM
6048 /* Turn off the cursor. */
6049 if (!w->pseudo_window_p
6050 && x_phys_cursor_in_rect_p (w, &r))
6051 {
6052 x_clear_cursor (w);
6053 cursor_cleared_p = 1;
6054 }
6055 else
6056 cursor_cleared_p = 0;
06a2c219 6057
a39202f6
GM
6058 /* Find the first row intersecting the rectangle R. */
6059 for (row = w->current_matrix->rows;
6060 row->enabled_p;
6061 ++row)
6062 {
6063 int y0 = row->y;
6064 int y1 = MATRIX_ROW_BOTTOM_Y (row);
6065
6066 if ((y0 >= r.y && y0 < r.y + r.height)
6067 || (y1 > r.y && y1 < r.y + r.height)
6068 || (r.y >= y0 && r.y < y1)
6069 || (r.y + r.height > y0 && r.y + r.height < y1))
82f053ab
GM
6070 {
6071 if (expose_line (w, row, &r))
6072 mouse_face_overwritten_p = 1;
6073 }
6074
a39202f6
GM
6075 if (y1 >= yb)
6076 break;
6077 }
dc6f92b8 6078
a39202f6
GM
6079 /* Display the mode line if there is one. */
6080 if (WINDOW_WANTS_MODELINE_P (w)
6081 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
6082 row->enabled_p)
6083 && row->y < r.y + r.height)
82f053ab
GM
6084 {
6085 if (expose_line (w, row, &r))
6086 mouse_face_overwritten_p = 1;
6087 }
a39202f6
GM
6088
6089 if (!w->pseudo_window_p)
6090 {
6091 /* Draw border between windows. */
6092 x_draw_vertical_border (w);
06a2c219 6093
a39202f6
GM
6094 /* Turn the cursor on again. */
6095 if (cursor_cleared_p)
6096 x_update_window_cursor (w, 1);
6097 }
06a2c219 6098 }
82f053ab
GM
6099
6100 return mouse_face_overwritten_p;
06a2c219 6101}
dc6f92b8 6102
dc6f92b8 6103
06a2c219
GM
6104/* Determine the intersection of two rectangles R1 and R2. Return
6105 the intersection in *RESULT. Value is non-zero if RESULT is not
6106 empty. */
6107
6108static int
6109x_intersect_rectangles (r1, r2, result)
6110 XRectangle *r1, *r2, *result;
6111{
6112 XRectangle *left, *right;
6113 XRectangle *upper, *lower;
6114 int intersection_p = 0;
6115
6116 /* Rearrange so that R1 is the left-most rectangle. */
6117 if (r1->x < r2->x)
6118 left = r1, right = r2;
6119 else
6120 left = r2, right = r1;
6121
6122 /* X0 of the intersection is right.x0, if this is inside R1,
6123 otherwise there is no intersection. */
6124 if (right->x <= left->x + left->width)
6125 {
6126 result->x = right->x;
6127
6128 /* The right end of the intersection is the minimum of the
6129 the right ends of left and right. */
6130 result->width = (min (left->x + left->width, right->x + right->width)
6131 - result->x);
6132
6133 /* Same game for Y. */
6134 if (r1->y < r2->y)
6135 upper = r1, lower = r2;
6136 else
6137 upper = r2, lower = r1;
6138
6139 /* The upper end of the intersection is lower.y0, if this is inside
6140 of upper. Otherwise, there is no intersection. */
6141 if (lower->y <= upper->y + upper->height)
dc43ef94 6142 {
06a2c219
GM
6143 result->y = lower->y;
6144
6145 /* The lower end of the intersection is the minimum of the lower
6146 ends of upper and lower. */
6147 result->height = (min (lower->y + lower->height,
6148 upper->y + upper->height)
6149 - result->y);
6150 intersection_p = 1;
dc43ef94 6151 }
dc6f92b8
JB
6152 }
6153
06a2c219 6154 return intersection_p;
dc6f92b8 6155}
06a2c219
GM
6156
6157
6158
6159
dc6f92b8 6160\f
dc6f92b8 6161static void
334208b7
RS
6162frame_highlight (f)
6163 struct frame *f;
dc6f92b8 6164{
b3e1e05c
JB
6165 /* We used to only do this if Vx_no_window_manager was non-nil, but
6166 the ICCCM (section 4.1.6) says that the window's border pixmap
6167 and border pixel are window attributes which are "private to the
6168 client", so we can always change it to whatever we want. */
6169 BLOCK_INPUT;
334208b7 6170 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 6171 f->output_data.x->border_pixel);
b3e1e05c 6172 UNBLOCK_INPUT;
5d46f928 6173 x_update_cursor (f, 1);
dc6f92b8
JB
6174}
6175
6176static void
334208b7
RS
6177frame_unhighlight (f)
6178 struct frame *f;
dc6f92b8 6179{
b3e1e05c
JB
6180 /* We used to only do this if Vx_no_window_manager was non-nil, but
6181 the ICCCM (section 4.1.6) says that the window's border pixmap
6182 and border pixel are window attributes which are "private to the
6183 client", so we can always change it to whatever we want. */
6184 BLOCK_INPUT;
334208b7 6185 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 6186 f->output_data.x->border_tile);
b3e1e05c 6187 UNBLOCK_INPUT;
5d46f928 6188 x_update_cursor (f, 1);
dc6f92b8 6189}
dc6f92b8 6190
f676886a
JB
6191/* The focus has changed. Update the frames as necessary to reflect
6192 the new situation. Note that we can't change the selected frame
c5acd733 6193 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 6194 Each event gets marked with the frame in which it occurred, so the
c5acd733 6195 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 6196
6d4238f3 6197static void
0f941935
KH
6198x_new_focus_frame (dpyinfo, frame)
6199 struct x_display_info *dpyinfo;
f676886a 6200 struct frame *frame;
dc6f92b8 6201{
0f941935 6202 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 6203
0f941935 6204 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 6205 {
58769bee 6206 /* Set this before calling other routines, so that they see
f676886a 6207 the correct value of x_focus_frame. */
0f941935 6208 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
6209
6210 if (old_focus && old_focus->auto_lower)
f676886a 6211 x_lower_frame (old_focus);
dc6f92b8
JB
6212
6213#if 0
f676886a 6214 selected_frame = frame;
e0c1aef2
KH
6215 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6216 selected_frame);
f676886a
JB
6217 Fselect_window (selected_frame->selected_window);
6218 choose_minibuf_frame ();
c118dd06 6219#endif /* ! 0 */
dc6f92b8 6220
0f941935
KH
6221 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6222 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
6223 else
6224 pending_autoraise_frame = 0;
6d4238f3 6225 }
dc6f92b8 6226
0f941935 6227 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
6228}
6229
37c2c98b
RS
6230/* Handle an event saying the mouse has moved out of an Emacs frame. */
6231
6232void
0f941935
KH
6233x_mouse_leave (dpyinfo)
6234 struct x_display_info *dpyinfo;
37c2c98b 6235{
0f941935 6236 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 6237}
6d4238f3 6238
f451eb13
JB
6239/* The focus has changed, or we have redirected a frame's focus to
6240 another frame (this happens when a frame uses a surrogate
06a2c219 6241 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
6242
6243 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 6244 frame is being highlighted or un-highlighted; we only use it to find
0f941935 6245 the appropriate X display info. */
06a2c219 6246
6d4238f3 6247static void
0f941935
KH
6248XTframe_rehighlight (frame)
6249 struct frame *frame;
6d4238f3 6250{
0f941935
KH
6251 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6252}
6d4238f3 6253
0f941935
KH
6254static void
6255x_frame_rehighlight (dpyinfo)
6256 struct x_display_info *dpyinfo;
6257{
6258 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6259
6260 if (dpyinfo->x_focus_frame)
6d4238f3 6261 {
0f941935
KH
6262 dpyinfo->x_highlight_frame
6263 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6264 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6265 : dpyinfo->x_focus_frame);
6266 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 6267 {
0f941935
KH
6268 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6269 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 6270 }
dc6f92b8 6271 }
6d4238f3 6272 else
0f941935 6273 dpyinfo->x_highlight_frame = 0;
dc6f92b8 6274
0f941935 6275 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
6276 {
6277 if (old_highlight)
f676886a 6278 frame_unhighlight (old_highlight);
0f941935
KH
6279 if (dpyinfo->x_highlight_frame)
6280 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 6281 }
dc6f92b8 6282}
06a2c219
GM
6283
6284
dc6f92b8 6285\f
06a2c219 6286/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 6287
28430d3c
JB
6288/* Initialize mode_switch_bit and modifier_meaning. */
6289static void
334208b7
RS
6290x_find_modifier_meanings (dpyinfo)
6291 struct x_display_info *dpyinfo;
28430d3c 6292{
f689eb05 6293 int min_code, max_code;
28430d3c
JB
6294 KeySym *syms;
6295 int syms_per_code;
6296 XModifierKeymap *mods;
6297
334208b7
RS
6298 dpyinfo->meta_mod_mask = 0;
6299 dpyinfo->shift_lock_mask = 0;
6300 dpyinfo->alt_mod_mask = 0;
6301 dpyinfo->super_mod_mask = 0;
6302 dpyinfo->hyper_mod_mask = 0;
58769bee 6303
9658a521 6304#ifdef HAVE_X11R4
334208b7 6305 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 6306#else
4a60f8c5
RS
6307 min_code = dpyinfo->display->min_keycode;
6308 max_code = dpyinfo->display->max_keycode;
9658a521
JB
6309#endif
6310
334208b7 6311 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
6312 min_code, max_code - min_code + 1,
6313 &syms_per_code);
334208b7 6314 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 6315
58769bee 6316 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 6317 Alt keysyms are on. */
28430d3c 6318 {
06a2c219 6319 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
6320
6321 for (row = 3; row < 8; row++)
6322 for (col = 0; col < mods->max_keypermod; col++)
6323 {
0299d313
RS
6324 KeyCode code
6325 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 6326
af92970c
KH
6327 /* Zeroes are used for filler. Skip them. */
6328 if (code == 0)
6329 continue;
6330
28430d3c
JB
6331 /* Are any of this keycode's keysyms a meta key? */
6332 {
6333 int code_col;
6334
6335 for (code_col = 0; code_col < syms_per_code; code_col++)
6336 {
f689eb05 6337 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 6338
f689eb05 6339 switch (sym)
28430d3c 6340 {
f689eb05
JB
6341 case XK_Meta_L:
6342 case XK_Meta_R:
334208b7 6343 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 6344 break;
f689eb05
JB
6345
6346 case XK_Alt_L:
6347 case XK_Alt_R:
334208b7 6348 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
6349 break;
6350
6351 case XK_Hyper_L:
6352 case XK_Hyper_R:
334208b7 6353 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
6354 break;
6355
6356 case XK_Super_L:
6357 case XK_Super_R:
334208b7 6358 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 6359 break;
11edeb03
JB
6360
6361 case XK_Shift_Lock:
6362 /* Ignore this if it's not on the lock modifier. */
6363 if ((1 << row) == LockMask)
334208b7 6364 dpyinfo->shift_lock_mask = LockMask;
11edeb03 6365 break;
28430d3c
JB
6366 }
6367 }
6368 }
6369 }
6370 }
6371
f689eb05 6372 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 6373 if (! dpyinfo->meta_mod_mask)
a3c44b14 6374 {
334208b7
RS
6375 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6376 dpyinfo->alt_mod_mask = 0;
a3c44b14 6377 }
f689eb05 6378
148c4b70
RS
6379 /* If some keys are both alt and meta,
6380 make them just meta, not alt. */
334208b7 6381 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 6382 {
334208b7 6383 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 6384 }
58769bee 6385
28430d3c 6386 XFree ((char *) syms);
f689eb05 6387 XFreeModifiermap (mods);
28430d3c
JB
6388}
6389
dfeccd2d
JB
6390/* Convert between the modifier bits X uses and the modifier bits
6391 Emacs uses. */
06a2c219 6392
7c5283e4 6393static unsigned int
334208b7
RS
6394x_x_to_emacs_modifiers (dpyinfo, state)
6395 struct x_display_info *dpyinfo;
dc6f92b8
JB
6396 unsigned int state;
6397{
334208b7
RS
6398 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6399 | ((state & ControlMask) ? ctrl_modifier : 0)
6400 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6401 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6402 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6403 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
6404}
6405
dfeccd2d 6406static unsigned int
334208b7
RS
6407x_emacs_to_x_modifiers (dpyinfo, state)
6408 struct x_display_info *dpyinfo;
dfeccd2d
JB
6409 unsigned int state;
6410{
334208b7
RS
6411 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6412 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6413 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6414 | ((state & shift_modifier) ? ShiftMask : 0)
6415 | ((state & ctrl_modifier) ? ControlMask : 0)
6416 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6417}
d047c4eb
KH
6418
6419/* Convert a keysym to its name. */
6420
6421char *
6422x_get_keysym_name (keysym)
6423 KeySym keysym;
6424{
6425 char *value;
6426
6427 BLOCK_INPUT;
6428 value = XKeysymToString (keysym);
6429 UNBLOCK_INPUT;
6430
6431 return value;
6432}
06a2c219
GM
6433
6434
e4571a43
JB
6435\f
6436/* Mouse clicks and mouse movement. Rah. */
e4571a43 6437
06a2c219
GM
6438/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6439 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6440 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6441 not force the value into range. */
69388238 6442
c8dba240 6443void
69388238 6444pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6445 FRAME_PTR f;
69388238 6446 register int pix_x, pix_y;
e4571a43
JB
6447 register int *x, *y;
6448 XRectangle *bounds;
69388238 6449 int noclip;
e4571a43 6450{
06a2c219 6451 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6452 even for negative values. */
6453 if (pix_x < 0)
7556890b 6454 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6455 if (pix_y < 0)
7556890b 6456 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6457
e4571a43
JB
6458 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6459 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6460
6461 if (bounds)
6462 {
7556890b
RS
6463 bounds->width = FONT_WIDTH (f->output_data.x->font);
6464 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6465 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6466 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6467 }
6468
69388238
RS
6469 if (!noclip)
6470 {
6471 if (pix_x < 0)
6472 pix_x = 0;
3cbd2e0b
RS
6473 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6474 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6475
6476 if (pix_y < 0)
6477 pix_y = 0;
6478 else if (pix_y > f->height)
6479 pix_y = f->height;
6480 }
e4571a43
JB
6481
6482 *x = pix_x;
6483 *y = pix_y;
6484}
6485
06a2c219
GM
6486
6487/* Given HPOS/VPOS in the current matrix of W, return corresponding
6488 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6489 can't tell the positions because W's display is not up to date,
6490 return 0. */
6491
6492int
6493glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6494 struct window *w;
6495 int hpos, vpos;
6496 int *frame_x, *frame_y;
2b5c9e71 6497{
06a2c219
GM
6498 int success_p;
6499
6500 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6501 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6502
6503 if (display_completed)
6504 {
6505 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6506 struct glyph *glyph = row->glyphs[TEXT_AREA];
6507 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6508
6509 *frame_y = row->y;
6510 *frame_x = row->x;
6511 while (glyph < end)
6512 {
6513 *frame_x += glyph->pixel_width;
6514 ++glyph;
6515 }
6516
6517 success_p = 1;
6518 }
6519 else
6520 {
6521 *frame_y = *frame_x = 0;
6522 success_p = 0;
6523 }
6524
6525 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6526 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6527 return success_p;
2b5c9e71
RS
6528}
6529
06a2c219 6530
dc6f92b8
JB
6531/* Prepare a mouse-event in *RESULT for placement in the input queue.
6532
6533 If the event is a button press, then note that we have grabbed
f451eb13 6534 the mouse. */
dc6f92b8
JB
6535
6536static Lisp_Object
f451eb13 6537construct_mouse_click (result, event, f)
dc6f92b8
JB
6538 struct input_event *result;
6539 XButtonEvent *event;
f676886a 6540 struct frame *f;
dc6f92b8 6541{
f451eb13 6542 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6543 otherwise. */
f451eb13 6544 result->kind = mouse_click;
69388238 6545 result->code = event->button - Button1;
1113d9db 6546 result->timestamp = event->time;
334208b7
RS
6547 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6548 event->state)
f689eb05 6549 | (event->type == ButtonRelease
58769bee 6550 ? up_modifier
f689eb05 6551 : down_modifier));
dc6f92b8 6552
06a2c219
GM
6553 XSETINT (result->x, event->x);
6554 XSETINT (result->y, event->y);
6555 XSETFRAME (result->frame_or_window, f);
0f8aabe9 6556 result->arg = Qnil;
06a2c219 6557 return Qnil;
dc6f92b8 6558}
b849c413 6559
69388238 6560\f
90e65f07
JB
6561/* Function to report a mouse movement to the mainstream Emacs code.
6562 The input handler calls this.
6563
6564 We have received a mouse movement event, which is given in *event.
6565 If the mouse is over a different glyph than it was last time, tell
6566 the mainstream emacs code by setting mouse_moved. If not, ask for
6567 another motion event, so we can check again the next time it moves. */
b8009dd1 6568
06a2c219
GM
6569static XMotionEvent last_mouse_motion_event;
6570static Lisp_Object last_mouse_motion_frame;
6571
90e65f07 6572static void
12ba150f 6573note_mouse_movement (frame, event)
f676886a 6574 FRAME_PTR frame;
90e65f07 6575 XMotionEvent *event;
90e65f07 6576{
e5d77022 6577 last_mouse_movement_time = event->time;
06a2c219
GM
6578 last_mouse_motion_event = *event;
6579 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6580
27f338af
RS
6581 if (event->window != FRAME_X_WINDOW (frame))
6582 {
39d8bb4d 6583 frame->mouse_moved = 1;
27f338af 6584 last_mouse_scroll_bar = Qnil;
27f338af 6585 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6586 }
6587
90e65f07 6588 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6589 else if (event->x < last_mouse_glyph.x
6590 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6591 || event->y < last_mouse_glyph.y
6592 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6593 {
39d8bb4d 6594 frame->mouse_moved = 1;
ab648270 6595 last_mouse_scroll_bar = Qnil;
b8009dd1 6596 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6597 }
6598}
6599
bf1c0ba1 6600/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6601
06a2c219
GM
6602 int disable_mouse_highlight;
6603
6604
6605\f
6606/************************************************************************
6607 Mouse Face
6608 ************************************************************************/
6609
6610/* Find the glyph under window-relative coordinates X/Y in window W.
6611 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6612 strings. Return in *HPOS and *VPOS the row and column number of
6613 the glyph found. Return in *AREA the glyph area containing X.
6614 Value is a pointer to the glyph found or null if X/Y is not on
6615 text, or we can't tell because W's current matrix is not up to
6616 date. */
6617
6618static struct glyph *
f9db2310 6619x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
06a2c219
GM
6620 struct window *w;
6621 int x, y;
6622 int *hpos, *vpos, *area;
f9db2310 6623 int buffer_only_p;
06a2c219
GM
6624{
6625 struct glyph *glyph, *end;
3e71d8f2 6626 struct glyph_row *row = NULL;
06a2c219
GM
6627 int x0, i, left_area_width;
6628
6629 /* Find row containing Y. Give up if some row is not enabled. */
6630 for (i = 0; i < w->current_matrix->nrows; ++i)
6631 {
6632 row = MATRIX_ROW (w->current_matrix, i);
6633 if (!row->enabled_p)
6634 return NULL;
6635 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6636 break;
6637 }
6638
6639 *vpos = i;
6640 *hpos = 0;
6641
6642 /* Give up if Y is not in the window. */
6643 if (i == w->current_matrix->nrows)
6644 return NULL;
6645
6646 /* Get the glyph area containing X. */
6647 if (w->pseudo_window_p)
6648 {
6649 *area = TEXT_AREA;
6650 x0 = 0;
6651 }
6652 else
6653 {
6654 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6655 if (x < left_area_width)
6656 {
6657 *area = LEFT_MARGIN_AREA;
6658 x0 = 0;
6659 }
6660 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6661 {
6662 *area = TEXT_AREA;
6663 x0 = row->x + left_area_width;
6664 }
6665 else
6666 {
6667 *area = RIGHT_MARGIN_AREA;
6668 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6669 }
6670 }
6671
6672 /* Find glyph containing X. */
6673 glyph = row->glyphs[*area];
6674 end = glyph + row->used[*area];
6675 while (glyph < end)
6676 {
6677 if (x < x0 + glyph->pixel_width)
6678 {
6679 if (w->pseudo_window_p)
6680 break;
f9db2310 6681 else if (!buffer_only_p || BUFFERP (glyph->object))
06a2c219
GM
6682 break;
6683 }
6684
6685 x0 += glyph->pixel_width;
6686 ++glyph;
6687 }
6688
6689 if (glyph == end)
6690 return NULL;
6691
6692 *hpos = glyph - row->glyphs[*area];
6693 return glyph;
6694}
6695
6696
6697/* Convert frame-relative x/y to coordinates relative to window W.
6698 Takes pseudo-windows into account. */
6699
6700static void
6701frame_to_window_pixel_xy (w, x, y)
6702 struct window *w;
6703 int *x, *y;
6704{
6705 if (w->pseudo_window_p)
6706 {
6707 /* A pseudo-window is always full-width, and starts at the
6708 left edge of the frame, plus a frame border. */
6709 struct frame *f = XFRAME (w->frame);
6710 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6711 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6712 }
6713 else
6714 {
6715 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6716 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6717 }
6718}
6719
6720
e371a781 6721/* Take proper action when mouse has moved to the mode or header line of
06a2c219
GM
6722 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6723 mode line. X is relative to the start of the text display area of
6724 W, so the width of bitmap areas and scroll bars must be subtracted
6725 to get a position relative to the start of the mode line. */
6726
6727static void
6728note_mode_line_highlight (w, x, mode_line_p)
6729 struct window *w;
6730 int x, mode_line_p;
6731{
6732 struct frame *f = XFRAME (w->frame);
6733 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6734 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6735 struct glyph_row *row;
6736
6737 if (mode_line_p)
6738 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6739 else
045dee35 6740 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e371a781 6741
06a2c219
GM
6742 if (row->enabled_p)
6743 {
6744 struct glyph *glyph, *end;
6745 Lisp_Object help, map;
6746 int x0;
6747
6748 /* Find the glyph under X. */
6749 glyph = row->glyphs[TEXT_AREA];
6750 end = glyph + row->used[TEXT_AREA];
6751 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6752 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
e371a781 6753
06a2c219
GM
6754 while (glyph < end
6755 && x >= x0 + glyph->pixel_width)
6756 {
6757 x0 += glyph->pixel_width;
6758 ++glyph;
6759 }
6760
6761 if (glyph < end
6762 && STRINGP (glyph->object)
6763 && XSTRING (glyph->object)->intervals
6764 && glyph->charpos >= 0
6765 && glyph->charpos < XSTRING (glyph->object)->size)
6766 {
6767 /* If we're on a string with `help-echo' text property,
6768 arrange for the help to be displayed. This is done by
6769 setting the global variable help_echo to the help string. */
6770 help = Fget_text_property (make_number (glyph->charpos),
6771 Qhelp_echo, glyph->object);
b7e80413 6772 if (!NILP (help))
be010514
GM
6773 {
6774 help_echo = help;
7cea38bc 6775 XSETWINDOW (help_echo_window, w);
be010514
GM
6776 help_echo_object = glyph->object;
6777 help_echo_pos = glyph->charpos;
6778 }
06a2c219
GM
6779
6780 /* Change the mouse pointer according to what is under X/Y. */
6781 map = Fget_text_property (make_number (glyph->charpos),
6782 Qlocal_map, glyph->object);
02067692 6783 if (KEYMAPP (map))
06a2c219 6784 cursor = f->output_data.x->nontext_cursor;
be010514
GM
6785 else
6786 {
6787 map = Fget_text_property (make_number (glyph->charpos),
6788 Qkeymap, glyph->object);
02067692 6789 if (KEYMAPP (map))
be010514
GM
6790 cursor = f->output_data.x->nontext_cursor;
6791 }
06a2c219
GM
6792 }
6793 }
6794
6795 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6796}
6797
6798
6799/* Take proper action when the mouse has moved to position X, Y on
6800 frame F as regards highlighting characters that have mouse-face
6801 properties. Also de-highlighting chars where the mouse was before.
27f338af 6802 X and Y can be negative or out of range. */
b8009dd1
RS
6803
6804static void
6805note_mouse_highlight (f, x, y)
06a2c219 6806 struct frame *f;
c32cdd9a 6807 int x, y;
b8009dd1 6808{
06a2c219
GM
6809 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6810 int portion;
b8009dd1
RS
6811 Lisp_Object window;
6812 struct window *w;
0d487c52
GM
6813 Cursor cursor = None;
6814 struct buffer *b;
b8009dd1 6815
06a2c219
GM
6816 /* When a menu is active, don't highlight because this looks odd. */
6817#ifdef USE_X_TOOLKIT
6818 if (popup_activated ())
6819 return;
6820#endif
6821
04fff9c0
GM
6822 if (disable_mouse_highlight
6823 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6824 return;
6825
06a2c219
GM
6826 dpyinfo->mouse_face_mouse_x = x;
6827 dpyinfo->mouse_face_mouse_y = y;
6828 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6829
06a2c219 6830 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6831 return;
6832
514e4681
RS
6833 if (gc_in_progress)
6834 {
06a2c219 6835 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6836 return;
6837 }
6838
b8009dd1 6839 /* Which window is that in? */
06a2c219 6840 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6841
6842 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6843 if (! EQ (window, dpyinfo->mouse_face_window))
6844 clear_mouse_face (dpyinfo);
6845
6846 /* Not on a window -> return. */
6847 if (!WINDOWP (window))
6848 return;
6849
6850 /* Convert to window-relative pixel coordinates. */
6851 w = XWINDOW (window);
6852 frame_to_window_pixel_xy (w, &x, &y);
6853
9ea173e8 6854 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6855 buffer. */
9ea173e8 6856 if (EQ (window, f->tool_bar_window))
06a2c219 6857 {
9ea173e8 6858 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6859 return;
6860 }
6861
0d487c52 6862 /* Mouse is on the mode or header line? */
06a2c219
GM
6863 if (portion == 1 || portion == 3)
6864 {
06a2c219
GM
6865 note_mode_line_highlight (w, x, portion == 1);
6866 return;
6867 }
0d487c52
GM
6868
6869 if (portion == 2)
6870 cursor = f->output_data.x->horizontal_drag_cursor;
06a2c219 6871 else
0d487c52 6872 cursor = f->output_data.x->text_cursor;
b8009dd1 6873
0cdd0c9f
RS
6874 /* Are we in a window whose display is up to date?
6875 And verify the buffer's text has not changed. */
0d487c52 6876 b = XBUFFER (w->buffer);
06a2c219
GM
6877 if (/* Within text portion of the window. */
6878 portion == 0
0cdd0c9f 6879 && EQ (w->window_end_valid, w->buffer)
0d487c52
GM
6880 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6881 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
b8009dd1 6882 {
06a2c219
GM
6883 int hpos, vpos, pos, i, area;
6884 struct glyph *glyph;
f9db2310 6885 Lisp_Object object;
0d487c52
GM
6886 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6887 Lisp_Object *overlay_vec = NULL;
6888 int len, noverlays;
6889 struct buffer *obuf;
6890 int obegv, ozv, same_region;
b8009dd1 6891
06a2c219 6892 /* Find the glyph under X/Y. */
f9db2310 6893 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
06a2c219
GM
6894
6895 /* Clear mouse face if X/Y not over text. */
6896 if (glyph == NULL
6897 || area != TEXT_AREA
6898 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6899 {
fa262c07
GM
6900 if (clear_mouse_face (dpyinfo))
6901 cursor = None;
6902 goto set_cursor;
06a2c219
GM
6903 }
6904
6905 pos = glyph->charpos;
f9db2310
GM
6906 object = glyph->object;
6907 if (!STRINGP (object) && !BUFFERP (object))
fa262c07 6908 goto set_cursor;
06a2c219 6909
0d487c52
GM
6910 /* If we get an out-of-range value, return now; avoid an error. */
6911 if (BUFFERP (object) && pos > BUF_Z (b))
fa262c07 6912 goto set_cursor;
06a2c219 6913
0d487c52
GM
6914 /* Make the window's buffer temporarily current for
6915 overlays_at and compute_char_face. */
6916 obuf = current_buffer;
6917 current_buffer = b;
6918 obegv = BEGV;
6919 ozv = ZV;
6920 BEGV = BEG;
6921 ZV = Z;
06a2c219 6922
0d487c52
GM
6923 /* Is this char mouse-active or does it have help-echo? */
6924 position = make_number (pos);
f9db2310 6925
0d487c52
GM
6926 if (BUFFERP (object))
6927 {
6928 /* Put all the overlays we want in a vector in overlay_vec.
6929 Store the length in len. If there are more than 10, make
6930 enough space for all, and try again. */
6931 len = 10;
6932 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6933 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6934 if (noverlays > len)
6935 {
6936 len = noverlays;
6937 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6938 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6939 }
f8349001 6940
0d487c52
GM
6941 /* Sort overlays into increasing priority order. */
6942 noverlays = sort_overlays (overlay_vec, noverlays, w);
6943 }
6944 else
6945 noverlays = 0;
6946
6947 same_region = (EQ (window, dpyinfo->mouse_face_window)
6948 && vpos >= dpyinfo->mouse_face_beg_row
6949 && vpos <= dpyinfo->mouse_face_end_row
6950 && (vpos > dpyinfo->mouse_face_beg_row
6951 || hpos >= dpyinfo->mouse_face_beg_col)
6952 && (vpos < dpyinfo->mouse_face_end_row
6953 || hpos < dpyinfo->mouse_face_end_col
6954 || dpyinfo->mouse_face_past_end));
6955
6956 if (same_region)
6957 cursor = None;
6958
6959 /* Check mouse-face highlighting. */
6960 if (! same_region
6961 /* If there exists an overlay with mouse-face overlapping
6962 the one we are currently highlighting, we have to
6963 check if we enter the overlapping overlay, and then
6964 highlight only that. */
6965 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6966 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6967 {
0d487c52
GM
6968 /* Find the highest priority overlay that has a mouse-face
6969 property. */
6970 overlay = Qnil;
6971 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6972 {
6973 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6974 if (!NILP (mouse_face))
6975 overlay = overlay_vec[i];
6976 }
8bd189fb
GM
6977
6978 /* If we're actually highlighting the same overlay as
6979 before, there's no need to do that again. */
6980 if (!NILP (overlay)
6981 && EQ (overlay, dpyinfo->mouse_face_overlay))
6982 goto check_help_echo;
f9db2310 6983
8bd189fb
GM
6984 dpyinfo->mouse_face_overlay = overlay;
6985
6986 /* Clear the display of the old active region, if any. */
6987 if (clear_mouse_face (dpyinfo))
6988 cursor = None;
6989
0d487c52
GM
6990 /* If no overlay applies, get a text property. */
6991 if (NILP (overlay))
6992 mouse_face = Fget_text_property (position, Qmouse_face, object);
06a2c219 6993
0d487c52
GM
6994 /* Handle the overlay case. */
6995 if (!NILP (overlay))
6996 {
6997 /* Find the range of text around this char that
6998 should be active. */
6999 Lisp_Object before, after;
7000 int ignore;
7001
7002 before = Foverlay_start (overlay);
7003 after = Foverlay_end (overlay);
7004 /* Record this as the current active region. */
7005 fast_find_position (w, XFASTINT (before),
7006 &dpyinfo->mouse_face_beg_col,
7007 &dpyinfo->mouse_face_beg_row,
7008 &dpyinfo->mouse_face_beg_x,
7e376260
GM
7009 &dpyinfo->mouse_face_beg_y, Qnil);
7010
0d487c52
GM
7011 dpyinfo->mouse_face_past_end
7012 = !fast_find_position (w, XFASTINT (after),
7013 &dpyinfo->mouse_face_end_col,
7014 &dpyinfo->mouse_face_end_row,
7015 &dpyinfo->mouse_face_end_x,
7e376260 7016 &dpyinfo->mouse_face_end_y, Qnil);
0d487c52
GM
7017 dpyinfo->mouse_face_window = window;
7018 dpyinfo->mouse_face_face_id
7019 = face_at_buffer_position (w, pos, 0, 0,
7020 &ignore, pos + 1, 1);
7021
7022 /* Display it as active. */
7023 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
58e5af83 7024 cursor = None;
0d487c52
GM
7025 }
7026 /* Handle the text property case. */
7027 else if (!NILP (mouse_face) && BUFFERP (object))
7028 {
7029 /* Find the range of text around this char that
7030 should be active. */
7031 Lisp_Object before, after, beginning, end;
7032 int ignore;
7033
7034 beginning = Fmarker_position (w->start);
7035 end = make_number (BUF_Z (XBUFFER (object))
7036 - XFASTINT (w->window_end_pos));
7037 before
7038 = Fprevious_single_property_change (make_number (pos + 1),
7039 Qmouse_face,
7040 object, beginning);
7041 after
7042 = Fnext_single_property_change (position, Qmouse_face,
7043 object, end);
7044
7045 /* Record this as the current active region. */
7046 fast_find_position (w, XFASTINT (before),
7047 &dpyinfo->mouse_face_beg_col,
7048 &dpyinfo->mouse_face_beg_row,
7049 &dpyinfo->mouse_face_beg_x,
7e376260 7050 &dpyinfo->mouse_face_beg_y, Qnil);
0d487c52
GM
7051 dpyinfo->mouse_face_past_end
7052 = !fast_find_position (w, XFASTINT (after),
7053 &dpyinfo->mouse_face_end_col,
7054 &dpyinfo->mouse_face_end_row,
7055 &dpyinfo->mouse_face_end_x,
7e376260 7056 &dpyinfo->mouse_face_end_y, Qnil);
0d487c52
GM
7057 dpyinfo->mouse_face_window = window;
7058
7059 if (BUFFERP (object))
06a2c219
GM
7060 dpyinfo->mouse_face_face_id
7061 = face_at_buffer_position (w, pos, 0, 0,
7062 &ignore, pos + 1, 1);
7063
0d487c52
GM
7064 /* Display it as active. */
7065 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
58e5af83 7066 cursor = None;
0d487c52
GM
7067 }
7068 else if (!NILP (mouse_face) && STRINGP (object))
7069 {
7070 Lisp_Object b, e;
7071 int ignore;
f9db2310 7072
0d487c52
GM
7073 b = Fprevious_single_property_change (make_number (pos + 1),
7074 Qmouse_face,
7075 object, Qnil);
7076 e = Fnext_single_property_change (position, Qmouse_face,
7077 object, Qnil);
7078 if (NILP (b))
7079 b = make_number (0);
7080 if (NILP (e))
7081 e = make_number (XSTRING (object)->size - 1);
7082 fast_find_string_pos (w, XINT (b), object,
06a2c219
GM
7083 &dpyinfo->mouse_face_beg_col,
7084 &dpyinfo->mouse_face_beg_row,
7085 &dpyinfo->mouse_face_beg_x,
0d487c52
GM
7086 &dpyinfo->mouse_face_beg_y, 0);
7087 fast_find_string_pos (w, XINT (e), object,
7088 &dpyinfo->mouse_face_end_col,
7089 &dpyinfo->mouse_face_end_row,
7090 &dpyinfo->mouse_face_end_x,
7091 &dpyinfo->mouse_face_end_y, 1);
7092 dpyinfo->mouse_face_past_end = 0;
7093 dpyinfo->mouse_face_window = window;
7094 dpyinfo->mouse_face_face_id
7095 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
7096 glyph->face_id, 1);
7097 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
58e5af83 7098 cursor = None;
0d487c52 7099 }
7e376260
GM
7100 else if (STRINGP (object) && NILP (mouse_face))
7101 {
7102 /* A string which doesn't have mouse-face, but
7103 the text ``under'' it might have. */
7104 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
7105 int start = MATRIX_ROW_START_CHARPOS (r);
7106
7107 pos = string_buffer_position (w, object, start);
7108 if (pos > 0)
7109 mouse_face = get_char_property_and_overlay (make_number (pos),
7110 Qmouse_face,
7111 w->buffer,
7112 &overlay);
7113 if (!NILP (mouse_face) && !NILP (overlay))
7114 {
7115 Lisp_Object before = Foverlay_start (overlay);
7116 Lisp_Object after = Foverlay_end (overlay);
7117 Lisp_Object ignore;
7118
7119 /* Note that we might not be able to find position
7120 BEFORE in the glyph matrix if the overlay is
7121 entirely covered by a `display' property. In
7122 this case, we overshoot. So let's stop in
7123 the glyph matrix before glyphs for OBJECT. */
7124 fast_find_position (w, XFASTINT (before),
7125 &dpyinfo->mouse_face_beg_col,
7126 &dpyinfo->mouse_face_beg_row,
7127 &dpyinfo->mouse_face_beg_x,
7128 &dpyinfo->mouse_face_beg_y,
7129 object);
7130
7131 dpyinfo->mouse_face_past_end
7132 = !fast_find_position (w, XFASTINT (after),
7133 &dpyinfo->mouse_face_end_col,
7134 &dpyinfo->mouse_face_end_row,
7135 &dpyinfo->mouse_face_end_x,
7136 &dpyinfo->mouse_face_end_y,
7137 Qnil);
7138 dpyinfo->mouse_face_window = window;
7139 dpyinfo->mouse_face_face_id
7140 = face_at_buffer_position (w, pos, 0, 0,
7141 &ignore, pos + 1, 1);
7142
7143 /* Display it as active. */
7144 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
7145 cursor = None;
7146 }
7147 }
0d487c52 7148 }
06a2c219 7149
8bd189fb
GM
7150 check_help_echo:
7151
0d487c52
GM
7152 /* Look for a `help-echo' property. */
7153 {
7154 Lisp_Object help, overlay;
06a2c219 7155
0d487c52
GM
7156 /* Check overlays first. */
7157 help = overlay = Qnil;
7158 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
7159 {
7160 overlay = overlay_vec[i];
7161 help = Foverlay_get (overlay, Qhelp_echo);
7162 }
be010514 7163
0d487c52
GM
7164 if (!NILP (help))
7165 {
7166 help_echo = help;
7167 help_echo_window = window;
7168 help_echo_object = overlay;
7169 help_echo_pos = pos;
7170 }
7171 else
7172 {
7173 Lisp_Object object = glyph->object;
7174 int charpos = glyph->charpos;
7177d86b 7175
0d487c52
GM
7176 /* Try text properties. */
7177 if (STRINGP (object)
7178 && charpos >= 0
7179 && charpos < XSTRING (object)->size)
7180 {
7181 help = Fget_text_property (make_number (charpos),
7182 Qhelp_echo, object);
7183 if (NILP (help))
7184 {
7185 /* If the string itself doesn't specify a help-echo,
7186 see if the buffer text ``under'' it does. */
7187 struct glyph_row *r
7188 = MATRIX_ROW (w->current_matrix, vpos);
7189 int start = MATRIX_ROW_START_CHARPOS (r);
7190 int pos = string_buffer_position (w, object, start);
7191 if (pos > 0)
7192 {
7e376260 7193 help = Fget_char_property (make_number (pos),
0d487c52
GM
7194 Qhelp_echo, w->buffer);
7195 if (!NILP (help))
7196 {
7197 charpos = pos;
7198 object = w->buffer;
7199 }
7200 }
7201 }
7202 }
7203 else if (BUFFERP (object)
7204 && charpos >= BEGV
7205 && charpos < ZV)
7206 help = Fget_text_property (make_number (charpos), Qhelp_echo,
7207 object);
06a2c219 7208
0d487c52
GM
7209 if (!NILP (help))
7210 {
7211 help_echo = help;
7212 help_echo_window = window;
7213 help_echo_object = object;
7214 help_echo_pos = charpos;
7215 }
7216 }
06a2c219 7217 }
0d487c52
GM
7218
7219 BEGV = obegv;
7220 ZV = ozv;
7221 current_buffer = obuf;
06a2c219 7222 }
0d487c52 7223
fa262c07
GM
7224 set_cursor:
7225
0d487c52
GM
7226 if (cursor != None)
7227 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
06a2c219
GM
7228}
7229
7230static void
7231redo_mouse_highlight ()
7232{
7233 if (!NILP (last_mouse_motion_frame)
7234 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
7235 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
7236 last_mouse_motion_event.x,
7237 last_mouse_motion_event.y);
7238}
7239
7240
7241\f
7242/***********************************************************************
9ea173e8 7243 Tool-bars
06a2c219
GM
7244 ***********************************************************************/
7245
9ea173e8
GM
7246static int x_tool_bar_item P_ ((struct frame *, int, int,
7247 struct glyph **, int *, int *, int *));
06a2c219 7248
9ea173e8 7249/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
7250 or -1. */
7251
9ea173e8 7252static int last_tool_bar_item;
06a2c219
GM
7253
7254
9ea173e8
GM
7255/* Get information about the tool-bar item at position X/Y on frame F.
7256 Return in *GLYPH a pointer to the glyph of the tool-bar item in
7257 the current matrix of the tool-bar window of F, or NULL if not
7258 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8daf1204 7259 item in F->tool_bar_items. Value is
06a2c219 7260
9ea173e8 7261 -1 if X/Y is not on a tool-bar item
06a2c219
GM
7262 0 if X/Y is on the same item that was highlighted before.
7263 1 otherwise. */
7264
7265static int
9ea173e8 7266x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
7267 struct frame *f;
7268 int x, y;
7269 struct glyph **glyph;
7270 int *hpos, *vpos, *prop_idx;
7271{
7272 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 7273 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
7274 int area;
7275
7276 /* Find the glyph under X/Y. */
f9db2310 7277 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
06a2c219
GM
7278 if (*glyph == NULL)
7279 return -1;
7280
9ea173e8 7281 /* Get the start of this tool-bar item's properties in
8daf1204 7282 f->tool_bar_items. */
9ea173e8 7283 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
7284 return -1;
7285
7286 /* Is mouse on the highlighted item? */
9ea173e8 7287 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
7288 && *vpos >= dpyinfo->mouse_face_beg_row
7289 && *vpos <= dpyinfo->mouse_face_end_row
7290 && (*vpos > dpyinfo->mouse_face_beg_row
7291 || *hpos >= dpyinfo->mouse_face_beg_col)
7292 && (*vpos < dpyinfo->mouse_face_end_row
7293 || *hpos < dpyinfo->mouse_face_end_col
7294 || dpyinfo->mouse_face_past_end))
7295 return 0;
7296
7297 return 1;
7298}
7299
7300
9ea173e8 7301/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
7302 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7303 or ButtonRelase. */
7304
7305static void
9ea173e8 7306x_handle_tool_bar_click (f, button_event)
06a2c219
GM
7307 struct frame *f;
7308 XButtonEvent *button_event;
7309{
7310 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 7311 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
7312 int hpos, vpos, prop_idx;
7313 struct glyph *glyph;
7314 Lisp_Object enabled_p;
7315 int x = button_event->x;
7316 int y = button_event->y;
7317
9ea173e8 7318 /* If not on the highlighted tool-bar item, return. */
06a2c219 7319 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 7320 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
7321 return;
7322
7323 /* If item is disabled, do nothing. */
8daf1204 7324 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
7325 if (NILP (enabled_p))
7326 return;
7327
7328 if (button_event->type == ButtonPress)
7329 {
7330 /* Show item in pressed state. */
7331 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7332 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 7333 last_tool_bar_item = prop_idx;
06a2c219
GM
7334 }
7335 else
7336 {
7337 Lisp_Object key, frame;
7338 struct input_event event;
7339
7340 /* Show item in released state. */
7341 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7342 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7343
8daf1204 7344 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
06a2c219
GM
7345
7346 XSETFRAME (frame, f);
9ea173e8 7347 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7348 event.frame_or_window = frame;
7349 event.arg = frame;
06a2c219
GM
7350 kbd_buffer_store_event (&event);
7351
9ea173e8 7352 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7353 event.frame_or_window = frame;
7354 event.arg = key;
06a2c219
GM
7355 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7356 button_event->state);
7357 kbd_buffer_store_event (&event);
9ea173e8 7358 last_tool_bar_item = -1;
06a2c219
GM
7359 }
7360}
7361
7362
9ea173e8
GM
7363/* Possibly highlight a tool-bar item on frame F when mouse moves to
7364 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
7365 note_mouse_highlight. */
7366
7367static void
9ea173e8 7368note_tool_bar_highlight (f, x, y)
06a2c219
GM
7369 struct frame *f;
7370 int x, y;
7371{
9ea173e8 7372 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
7373 struct window *w = XWINDOW (window);
7374 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7375 int hpos, vpos;
7376 struct glyph *glyph;
7377 struct glyph_row *row;
5c187dee 7378 int i;
06a2c219
GM
7379 Lisp_Object enabled_p;
7380 int prop_idx;
140330de 7381 enum draw_glyphs_face draw;
5c187dee 7382 int mouse_down_p, rc;
06a2c219
GM
7383
7384 /* Function note_mouse_highlight is called with negative x(y
7385 values when mouse moves outside of the frame. */
7386 if (x <= 0 || y <= 0)
7387 {
7388 clear_mouse_face (dpyinfo);
7389 return;
7390 }
7391
9ea173e8 7392 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
7393 if (rc < 0)
7394 {
9ea173e8 7395 /* Not on tool-bar item. */
06a2c219
GM
7396 clear_mouse_face (dpyinfo);
7397 return;
7398 }
7399 else if (rc == 0)
06a2c219 7400 goto set_help_echo;
b8009dd1 7401
06a2c219
GM
7402 clear_mouse_face (dpyinfo);
7403
9ea173e8 7404 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
7405 mouse_down_p = (dpyinfo->grabbed
7406 && f == last_mouse_frame
7407 && FRAME_LIVE_P (f));
7408 if (mouse_down_p
9ea173e8 7409 && last_tool_bar_item != prop_idx)
06a2c219
GM
7410 return;
7411
7412 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7413 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7414
9ea173e8 7415 /* If tool-bar item is not enabled, don't highlight it. */
8daf1204 7416 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
7417 if (!NILP (enabled_p))
7418 {
7419 /* Compute the x-position of the glyph. In front and past the
7420 image is a space. We include this is the highlighted area. */
7421 row = MATRIX_ROW (w->current_matrix, vpos);
7422 for (i = x = 0; i < hpos; ++i)
7423 x += row->glyphs[TEXT_AREA][i].pixel_width;
7424
7425 /* Record this as the current active region. */
7426 dpyinfo->mouse_face_beg_col = hpos;
7427 dpyinfo->mouse_face_beg_row = vpos;
7428 dpyinfo->mouse_face_beg_x = x;
7429 dpyinfo->mouse_face_beg_y = row->y;
7430 dpyinfo->mouse_face_past_end = 0;
7431
7432 dpyinfo->mouse_face_end_col = hpos + 1;
7433 dpyinfo->mouse_face_end_row = vpos;
7434 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7435 dpyinfo->mouse_face_end_y = row->y;
7436 dpyinfo->mouse_face_window = window;
9ea173e8 7437 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
7438
7439 /* Display it as active. */
7440 show_mouse_face (dpyinfo, draw);
7441 dpyinfo->mouse_face_image_state = draw;
b8009dd1 7442 }
06a2c219
GM
7443
7444 set_help_echo:
7445
9ea173e8 7446 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 7447 XTread_socket does the rest. */
7cea38bc 7448 help_echo_object = help_echo_window = Qnil;
be010514 7449 help_echo_pos = -1;
8daf1204 7450 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
b7e80413 7451 if (NILP (help_echo))
8daf1204 7452 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
b8009dd1 7453}
4d73d038 7454
06a2c219
GM
7455
7456\f
9f8531e5
GM
7457/* Find the glyph matrix position of buffer position CHARPOS in window
7458 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7459 current glyphs must be up to date. If CHARPOS is above window
7460 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7461 of last line in W. In the row containing CHARPOS, stop before glyphs
7e376260 7462 having STOP as object. */
b8009dd1 7463
9f8531e5
GM
7464#if 0 /* This is a version of fast_find_position that's more correct
7465 in the presence of hscrolling, for example. I didn't install
7466 it right away because the problem fixed is minor, it failed
7467 in 20.x as well, and I think it's too risky to install
7468 so near the release of 21.1. 2001-09-25 gerd. */
7469
7470static int
7471fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7472 struct window *w;
7473 int charpos;
7474 int *hpos, *vpos, *x, *y;
7475 Lisp_Object stop;
7476{
7477 struct glyph_row *row, *first;
7478 struct glyph *glyph, *end;
7479 int i, past_end = 0;
7480
7481 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
62e33982 7482 row = row_containing_pos (w, charpos, first, NULL, 0);
9f8531e5
GM
7483 if (row == NULL)
7484 {
7485 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7486 {
7487 *x = *y = *hpos = *vpos = 0;
7488 return 0;
7489 }
7490 else
7491 {
7492 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7493 past_end = 1;
7494 }
7495 }
7496
7497 *x = row->x;
7498 *y = row->y;
7499 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7500
7501 glyph = row->glyphs[TEXT_AREA];
7502 end = glyph + row->used[TEXT_AREA];
7503
7504 /* Skip over glyphs not having an object at the start of the row.
7505 These are special glyphs like truncation marks on terminal
7506 frames. */
7507 if (row->displays_text_p)
7508 while (glyph < end
7509 && INTEGERP (glyph->object)
7510 && !EQ (stop, glyph->object)
7511 && glyph->charpos < 0)
7512 {
7513 *x += glyph->pixel_width;
7514 ++glyph;
7515 }
7516
7517 while (glyph < end
7518 && !INTEGERP (glyph->object)
7519 && !EQ (stop, glyph->object)
7520 && (!BUFFERP (glyph->object)
7521 || glyph->charpos < charpos))
7522 {
7523 *x += glyph->pixel_width;
7524 ++glyph;
7525 }
7526
7527 *hpos = glyph - row->glyphs[TEXT_AREA];
7528 return past_end;
7529}
7530
7531#else /* not 0 */
7532
b8009dd1 7533static int
7e376260 7534fast_find_position (w, pos, hpos, vpos, x, y, stop)
06a2c219 7535 struct window *w;
b8009dd1 7536 int pos;
06a2c219 7537 int *hpos, *vpos, *x, *y;
7e376260 7538 Lisp_Object stop;
b8009dd1 7539{
b8009dd1 7540 int i;
bf1c0ba1 7541 int lastcol;
06a2c219
GM
7542 int maybe_next_line_p = 0;
7543 int line_start_position;
7544 int yb = window_text_bottom_y (w);
03d1a189
GM
7545 struct glyph_row *row, *best_row;
7546 int row_vpos, best_row_vpos;
06a2c219
GM
7547 int current_x;
7548
03d1a189
GM
7549 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7550 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7551
06a2c219 7552 while (row->y < yb)
b8009dd1 7553 {
06a2c219
GM
7554 if (row->used[TEXT_AREA])
7555 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7556 else
7557 line_start_position = 0;
7558
7559 if (line_start_position > pos)
b8009dd1 7560 break;
77b68646
RS
7561 /* If the position sought is the end of the buffer,
7562 don't include the blank lines at the bottom of the window. */
06a2c219
GM
7563 else if (line_start_position == pos
7564 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 7565 {
06a2c219 7566 maybe_next_line_p = 1;
77b68646
RS
7567 break;
7568 }
06a2c219
GM
7569 else if (line_start_position > 0)
7570 {
7571 best_row = row;
7572 best_row_vpos = row_vpos;
7573 }
4b0bb6f3
GM
7574
7575 if (row->y + row->height >= yb)
7576 break;
06a2c219
GM
7577
7578 ++row;
7579 ++row_vpos;
b8009dd1 7580 }
06a2c219
GM
7581
7582 /* Find the right column within BEST_ROW. */
7583 lastcol = 0;
7584 current_x = best_row->x;
7585 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 7586 {
06a2c219 7587 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7e376260 7588 int charpos = glyph->charpos;
06a2c219 7589
7e376260 7590 if (BUFFERP (glyph->object))
bf1c0ba1 7591 {
7e376260
GM
7592 if (charpos == pos)
7593 {
7594 *hpos = i;
7595 *vpos = best_row_vpos;
7596 *x = current_x;
7597 *y = best_row->y;
7598 return 1;
7599 }
7600 else if (charpos > pos)
7601 break;
bf1c0ba1 7602 }
7e376260 7603 else if (EQ (glyph->object, stop))
4d73d038 7604 break;
06a2c219 7605
7e376260
GM
7606 if (charpos > 0)
7607 lastcol = i;
06a2c219 7608 current_x += glyph->pixel_width;
bf1c0ba1 7609 }
b8009dd1 7610
77b68646
RS
7611 /* If we're looking for the end of the buffer,
7612 and we didn't find it in the line we scanned,
7613 use the start of the following line. */
06a2c219 7614 if (maybe_next_line_p)
77b68646 7615 {
06a2c219
GM
7616 ++best_row;
7617 ++best_row_vpos;
7618 lastcol = 0;
7619 current_x = best_row->x;
77b68646
RS
7620 }
7621
06a2c219
GM
7622 *vpos = best_row_vpos;
7623 *hpos = lastcol + 1;
7624 *x = current_x;
7625 *y = best_row->y;
b8009dd1
RS
7626 return 0;
7627}
7628
9f8531e5
GM
7629#endif /* not 0 */
7630
06a2c219 7631
f9db2310
GM
7632/* Find the position of the the glyph for position POS in OBJECT in
7633 window W's current matrix, and return in *X/*Y the pixel
7634 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7635
7636 RIGHT_P non-zero means return the position of the right edge of the
7637 glyph, RIGHT_P zero means return the left edge position.
7638
7639 If no glyph for POS exists in the matrix, return the position of
7640 the glyph with the next smaller position that is in the matrix, if
7641 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7642 exists in the matrix, return the position of the glyph with the
7643 next larger position in OBJECT.
7644
7645 Value is non-zero if a glyph was found. */
7646
7647static int
7648fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7649 struct window *w;
7650 int pos;
7651 Lisp_Object object;
7652 int *hpos, *vpos, *x, *y;
7653 int right_p;
7654{
7655 int yb = window_text_bottom_y (w);
7656 struct glyph_row *r;
7657 struct glyph *best_glyph = NULL;
7658 struct glyph_row *best_row = NULL;
7659 int best_x = 0;
7660
7661 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7662 r->enabled_p && r->y < yb;
7663 ++r)
7664 {
7665 struct glyph *g = r->glyphs[TEXT_AREA];
7666 struct glyph *e = g + r->used[TEXT_AREA];
7667 int gx;
7668
7669 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7670 if (EQ (g->object, object))
7671 {
7672 if (g->charpos == pos)
7673 {
7674 best_glyph = g;
7675 best_x = gx;
7676 best_row = r;
7677 goto found;
7678 }
7679 else if (best_glyph == NULL
7680 || ((abs (g->charpos - pos)
7681 < abs (best_glyph->charpos - pos))
7682 && (right_p
7683 ? g->charpos < pos
7684 : g->charpos > pos)))
7685 {
7686 best_glyph = g;
7687 best_x = gx;
7688 best_row = r;
7689 }
7690 }
7691 }
7692
7693 found:
7694
7695 if (best_glyph)
7696 {
7697 *x = best_x;
7698 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7699
7700 if (right_p)
7701 {
7702 *x += best_glyph->pixel_width;
7703 ++*hpos;
7704 }
7705
7706 *y = best_row->y;
7707 *vpos = best_row - w->current_matrix->rows;
7708 }
7709
7710 return best_glyph != NULL;
7711}
7712
7713
b8009dd1
RS
7714/* Display the active region described by mouse_face_*
7715 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7716
7717static void
06a2c219 7718show_mouse_face (dpyinfo, draw)
7a13e894 7719 struct x_display_info *dpyinfo;
06a2c219 7720 enum draw_glyphs_face draw;
b8009dd1 7721{
7a13e894 7722 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 7723 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 7724 int i;
06a2c219
GM
7725 int cursor_off_p = 0;
7726 struct cursor_pos saved_cursor;
7727
7728 saved_cursor = output_cursor;
7729
7730 /* If window is in the process of being destroyed, don't bother
7731 to do anything. */
7732 if (w->current_matrix == NULL)
7733 goto set_x_cursor;
7734
7735 /* Recognize when we are called to operate on rows that don't exist
7736 anymore. This can happen when a window is split. */
7737 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7738 goto set_x_cursor;
7739
7740 set_output_cursor (&w->phys_cursor);
7741
7742 /* Note that mouse_face_beg_row etc. are window relative. */
7743 for (i = dpyinfo->mouse_face_beg_row;
7744 i <= dpyinfo->mouse_face_end_row;
7745 i++)
7746 {
7747 int start_hpos, end_hpos, start_x;
7748 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7749
7750 /* Don't do anything if row doesn't have valid contents. */
7751 if (!row->enabled_p)
7752 continue;
7753
7754 /* For all but the first row, the highlight starts at column 0. */
7755 if (i == dpyinfo->mouse_face_beg_row)
7756 {
7757 start_hpos = dpyinfo->mouse_face_beg_col;
7758 start_x = dpyinfo->mouse_face_beg_x;
7759 }
7760 else
7761 {
7762 start_hpos = 0;
7763 start_x = 0;
7764 }
7765
7766 if (i == dpyinfo->mouse_face_end_row)
7767 end_hpos = dpyinfo->mouse_face_end_col;
7768 else
7769 end_hpos = row->used[TEXT_AREA];
7770
7771 /* If the cursor's in the text we are about to rewrite, turn the
7772 cursor off. */
7773 if (!w->pseudo_window_p
7774 && i == output_cursor.vpos
7775 && output_cursor.hpos >= start_hpos - 1
7776 && output_cursor.hpos <= end_hpos)
514e4681 7777 {
06a2c219
GM
7778 x_update_window_cursor (w, 0);
7779 cursor_off_p = 1;
514e4681 7780 }
b8009dd1 7781
06a2c219 7782 if (end_hpos > start_hpos)
64f26cf5 7783 {
64f26cf5 7784 x_draw_glyphs (w, start_x, row, TEXT_AREA,
f0a48a01 7785 start_hpos, end_hpos, draw, 0);
7b0870b2 7786 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
64f26cf5 7787 }
b8009dd1
RS
7788 }
7789
514e4681 7790 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7791 if (cursor_off_p)
7792 x_display_cursor (w, 1,
7793 output_cursor.hpos, output_cursor.vpos,
7794 output_cursor.x, output_cursor.y);
2729a2b5 7795
06a2c219 7796 output_cursor = saved_cursor;
fb3b7de5 7797
06a2c219
GM
7798 set_x_cursor:
7799
7800 /* Change the mouse cursor. */
7801 if (draw == DRAW_NORMAL_TEXT)
7802 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7803 f->output_data.x->text_cursor);
7804 else if (draw == DRAW_MOUSE_FACE)
334208b7 7805 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7806 f->output_data.x->cross_cursor);
27ead1d5 7807 else
334208b7 7808 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7809 f->output_data.x->nontext_cursor);
b8009dd1
RS
7810}
7811
7812/* Clear out the mouse-highlighted active region.
fa262c07
GM
7813 Redraw it un-highlighted first. Value is non-zero if mouse
7814 face was actually drawn unhighlighted. */
b8009dd1 7815
fa262c07 7816static int
7a13e894
RS
7817clear_mouse_face (dpyinfo)
7818 struct x_display_info *dpyinfo;
b8009dd1 7819{
fa262c07 7820 int cleared = 0;
06a2c219 7821
fa262c07
GM
7822 if (!NILP (dpyinfo->mouse_face_window))
7823 {
7824 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7825 cleared = 1;
7826 }
b8009dd1 7827
7a13e894
RS
7828 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7829 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7830 dpyinfo->mouse_face_window = Qnil;
1b85dc1c 7831 dpyinfo->mouse_face_overlay = Qnil;
fa262c07 7832 return cleared;
b8009dd1 7833}
e687d06e 7834
71b8321e
GM
7835
7836/* Clear any mouse-face on window W. This function is part of the
7837 redisplay interface, and is called from try_window_id and similar
7838 functions to ensure the mouse-highlight is off. */
7839
7840static void
7841x_clear_mouse_face (w)
7842 struct window *w;
7843{
7844 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7845 Lisp_Object window;
7846
2e636f9d 7847 BLOCK_INPUT;
71b8321e
GM
7848 XSETWINDOW (window, w);
7849 if (EQ (window, dpyinfo->mouse_face_window))
7850 clear_mouse_face (dpyinfo);
2e636f9d 7851 UNBLOCK_INPUT;
71b8321e
GM
7852}
7853
7854
e687d06e
RS
7855/* Just discard the mouse face information for frame F, if any.
7856 This is used when the size of F is changed. */
7857
dfcf069d 7858void
e687d06e
RS
7859cancel_mouse_face (f)
7860 FRAME_PTR f;
7861{
7862 Lisp_Object window;
7863 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7864
7865 window = dpyinfo->mouse_face_window;
7866 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7867 {
7868 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7869 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7870 dpyinfo->mouse_face_window = Qnil;
7871 }
7872}
b52b65bd 7873
b8009dd1 7874\f
b52b65bd
GM
7875static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7876
7877
7878/* Try to determine frame pixel position and size of the glyph under
7879 frame pixel coordinates X/Y on frame F . Return the position and
7880 size in *RECT. Value is non-zero if we could compute these
7881 values. */
7882
7883static int
7884glyph_rect (f, x, y, rect)
7885 struct frame *f;
7886 int x, y;
7887 XRectangle *rect;
7888{
7889 Lisp_Object window;
7890 int part, found = 0;
7891
7892 window = window_from_coordinates (f, x, y, &part, 0);
7893 if (!NILP (window))
7894 {
7895 struct window *w = XWINDOW (window);
7896 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7897 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7898 int area;
7899
7900 frame_to_window_pixel_xy (w, &x, &y);
7901
7902 for (; !found && r < end && r->enabled_p; ++r)
7903 if (r->y >= y)
7904 {
7905 struct glyph *g = r->glyphs[TEXT_AREA];
7906 struct glyph *end = g + r->used[TEXT_AREA];
7907 int gx;
7908
7909 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7910 if (gx >= x)
7911 {
7912 rect->width = g->pixel_width;
7913 rect->height = r->height;
7914 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7915 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7916 found = 1;
7917 }
7918 }
7919 }
7920
7921 return found;
7922}
7923
12ba150f 7924
90e65f07 7925/* Return the current position of the mouse.
b52b65bd 7926 *FP should be a frame which indicates which display to ask about.
90e65f07 7927
b52b65bd
GM
7928 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7929 and *PART to the frame, window, and scroll bar part that the mouse
7930 is over. Set *X and *Y to the portion and whole of the mouse's
ab648270 7931 position on the scroll bar.
12ba150f 7932
b52b65bd
GM
7933 If the mouse movement started elsewhere, set *FP to the frame the
7934 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
12ba150f
JB
7935 the mouse is over.
7936
b52b65bd 7937 Set *TIME to the server time-stamp for the time at which the mouse
12ba150f
JB
7938 was at this position.
7939
a135645a
RS
7940 Don't store anything if we don't have a valid set of values to report.
7941
90e65f07 7942 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7943 movement. */
90e65f07
JB
7944
7945static void
1cf412ec 7946XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7947 FRAME_PTR *fp;
1cf412ec 7948 int insist;
12ba150f 7949 Lisp_Object *bar_window;
ab648270 7950 enum scroll_bar_part *part;
90e65f07 7951 Lisp_Object *x, *y;
e5d77022 7952 unsigned long *time;
90e65f07 7953{
a135645a
RS
7954 FRAME_PTR f1;
7955
90e65f07
JB
7956 BLOCK_INPUT;
7957
8bcee03e 7958 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7959 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7960 else
7961 {
12ba150f
JB
7962 Window root;
7963 int root_x, root_y;
90e65f07 7964
12ba150f
JB
7965 Window dummy_window;
7966 int dummy;
7967
39d8bb4d
KH
7968 Lisp_Object frame, tail;
7969
7970 /* Clear the mouse-moved flag for every frame on this display. */
7971 FOR_EACH_FRAME (tail, frame)
7972 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7973 XFRAME (frame)->mouse_moved = 0;
7974
ab648270 7975 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7976
7977 /* Figure out which root window we're on. */
334208b7
RS
7978 XQueryPointer (FRAME_X_DISPLAY (*fp),
7979 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7980
7981 /* The root window which contains the pointer. */
7982 &root,
7983
7984 /* Trash which we can't trust if the pointer is on
7985 a different screen. */
7986 &dummy_window,
7987
7988 /* The position on that root window. */
58769bee 7989 &root_x, &root_y,
12ba150f
JB
7990
7991 /* More trash we can't trust. */
7992 &dummy, &dummy,
7993
7994 /* Modifier keys and pointer buttons, about which
7995 we don't care. */
7996 (unsigned int *) &dummy);
7997
7998 /* Now we have a position on the root; find the innermost window
7999 containing the pointer. */
8000 {
8001 Window win, child;
8002 int win_x, win_y;
06a2c219 8003 int parent_x = 0, parent_y = 0;
e99db5a1 8004 int count;
12ba150f
JB
8005
8006 win = root;
69388238 8007
2d7fc7e8
RS
8008 /* XTranslateCoordinates can get errors if the window
8009 structure is changing at the same time this function
8010 is running. So at least we must not crash from them. */
8011
e99db5a1 8012 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 8013
334208b7 8014 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 8015 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 8016 {
69388238
RS
8017 /* If mouse was grabbed on a frame, give coords for that frame
8018 even if the mouse is now outside it. */
334208b7 8019 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 8020
12ba150f 8021 /* From-window, to-window. */
69388238 8022 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
8023
8024 /* From-position, to-position. */
8025 root_x, root_y, &win_x, &win_y,
8026
8027 /* Child of win. */
8028 &child);
69388238
RS
8029 f1 = last_mouse_frame;
8030 }
8031 else
8032 {
8033 while (1)
8034 {
334208b7 8035 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 8036
69388238
RS
8037 /* From-window, to-window. */
8038 root, win,
12ba150f 8039
69388238
RS
8040 /* From-position, to-position. */
8041 root_x, root_y, &win_x, &win_y,
8042
8043 /* Child of win. */
8044 &child);
8045
9af3143a 8046 if (child == None || child == win)
69388238
RS
8047 break;
8048
8049 win = child;
8050 parent_x = win_x;
8051 parent_y = win_y;
8052 }
12ba150f 8053
69388238
RS
8054 /* Now we know that:
8055 win is the innermost window containing the pointer
8056 (XTC says it has no child containing the pointer),
8057 win_x and win_y are the pointer's position in it
8058 (XTC did this the last time through), and
8059 parent_x and parent_y are the pointer's position in win's parent.
8060 (They are what win_x and win_y were when win was child.
8061 If win is the root window, it has no parent, and
8062 parent_{x,y} are invalid, but that's okay, because we'll
8063 never use them in that case.) */
8064
8065 /* Is win one of our frames? */
19126e11 8066 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
aad0f6ab
GM
8067
8068#ifdef USE_X_TOOLKIT
8069 /* If we end up with the menu bar window, say it's not
8070 on the frame. */
8071 if (f1 != NULL
8072 && f1->output_data.x->menubar_widget
8073 && win == XtWindow (f1->output_data.x->menubar_widget))
8074 f1 = NULL;
8075#endif /* USE_X_TOOLKIT */
69388238 8076 }
58769bee 8077
2d7fc7e8
RS
8078 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
8079 f1 = 0;
8080
e99db5a1 8081 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 8082
ab648270 8083 /* If not, is it one of our scroll bars? */
a135645a 8084 if (! f1)
12ba150f 8085 {
ab648270 8086 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
8087
8088 if (bar)
8089 {
a135645a 8090 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
8091 win_x = parent_x;
8092 win_y = parent_y;
8093 }
8094 }
90e65f07 8095
8bcee03e 8096 if (f1 == 0 && insist > 0)
b86bd3dd 8097 f1 = SELECTED_FRAME ();
1cf412ec 8098
a135645a 8099 if (f1)
12ba150f 8100 {
06a2c219
GM
8101 /* Ok, we found a frame. Store all the values.
8102 last_mouse_glyph is a rectangle used to reduce the
8103 generation of mouse events. To not miss any motion
8104 events, we must divide the frame into rectangles of the
8105 size of the smallest character that could be displayed
8106 on it, i.e. into the same rectangles that matrices on
8107 the frame are divided into. */
8108
b52b65bd
GM
8109 int width, height, gx, gy;
8110 XRectangle rect;
8111
8112 if (glyph_rect (f1, win_x, win_y, &rect))
8113 last_mouse_glyph = rect;
8114 else
8115 {
8116 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
8117 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
8118 gx = win_x;
8119 gy = win_y;
06a2c219 8120
b52b65bd
GM
8121 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
8122 round down even for negative values. */
8123 if (gx < 0)
8124 gx -= width - 1;
4f00e84d 8125 if (gy < 0)
b52b65bd
GM
8126 gy -= height - 1;
8127 gx = (gx + width - 1) / width * width;
8128 gy = (gy + height - 1) / height * height;
8129
8130 last_mouse_glyph.width = width;
8131 last_mouse_glyph.height = height;
8132 last_mouse_glyph.x = gx;
8133 last_mouse_glyph.y = gy;
8134 }
12ba150f
JB
8135
8136 *bar_window = Qnil;
8137 *part = 0;
334208b7 8138 *fp = f1;
e0c1aef2
KH
8139 XSETINT (*x, win_x);
8140 XSETINT (*y, win_y);
12ba150f
JB
8141 *time = last_mouse_movement_time;
8142 }
8143 }
8144 }
90e65f07
JB
8145
8146 UNBLOCK_INPUT;
8147}
f451eb13 8148
06a2c219 8149
06a2c219 8150#ifdef USE_X_TOOLKIT
bffcfca9
GM
8151
8152/* Atimer callback function for TIMER. Called every 0.1s to process
8153 Xt timeouts, if needed. We must avoid calling XtAppPending as
8154 much as possible because that function does an implicit XFlush
8155 that slows us down. */
8156
8157static void
8158x_process_timeouts (timer)
8159 struct atimer *timer;
8160{
8161 if (toolkit_scroll_bar_interaction || popup_activated_flag)
8162 {
8163 BLOCK_INPUT;
8164 while (XtAppPending (Xt_app_con) & XtIMTimer)
8165 XtAppProcessEvent (Xt_app_con, XtIMTimer);
8166 UNBLOCK_INPUT;
8167 }
06a2c219
GM
8168}
8169
bffcfca9 8170#endif /* USE_X_TOOLKIT */
06a2c219
GM
8171
8172\f
8173/* Scroll bar support. */
8174
8175/* Given an X window ID, find the struct scroll_bar which manages it.
8176 This can be called in GC, so we have to make sure to strip off mark
8177 bits. */
bffcfca9 8178
06a2c219
GM
8179static struct scroll_bar *
8180x_window_to_scroll_bar (window_id)
8181 Window window_id;
8182{
8183 Lisp_Object tail;
8184
8185 for (tail = Vframe_list;
8186 XGCTYPE (tail) == Lisp_Cons;
8e713be6 8187 tail = XCDR (tail))
06a2c219
GM
8188 {
8189 Lisp_Object frame, bar, condemned;
8190
8e713be6 8191 frame = XCAR (tail);
06a2c219
GM
8192 /* All elements of Vframe_list should be frames. */
8193 if (! GC_FRAMEP (frame))
8194 abort ();
8195
8196 /* Scan this frame's scroll bar list for a scroll bar with the
8197 right window ID. */
8198 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
8199 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
8200 /* This trick allows us to search both the ordinary and
8201 condemned scroll bar lists with one loop. */
8202 ! GC_NILP (bar) || (bar = condemned,
8203 condemned = Qnil,
8204 ! GC_NILP (bar));
8205 bar = XSCROLL_BAR (bar)->next)
8206 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
8207 return XSCROLL_BAR (bar);
8208 }
8209
8210 return 0;
8211}
8212
8213
01f67d2c 8214#if defined USE_LUCID
c95fc5f1
GM
8215
8216/* Return the Lucid menu bar WINDOW is part of. Return null
8217 if WINDOW is not part of a menu bar. */
8218
8219static Widget
8220x_window_to_menu_bar (window)
8221 Window window;
8222{
8223 Lisp_Object tail;
8224
8225 for (tail = Vframe_list;
8226 XGCTYPE (tail) == Lisp_Cons;
8227 tail = XCDR (tail))
8228 {
8229 Lisp_Object frame = XCAR (tail);
8230 Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
8231
8232 if (menu_bar && xlwmenu_window_p (menu_bar, window))
8233 return menu_bar;
8234 }
8235
8236 return NULL;
8237}
8238
01f67d2c 8239#endif /* USE_LUCID */
c95fc5f1 8240
06a2c219
GM
8241\f
8242/************************************************************************
8243 Toolkit scroll bars
8244 ************************************************************************/
8245
eccc05db 8246#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8247
8248static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
8249static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
8250static void x_create_toolkit_scroll_bar P_ ((struct frame *,
8251 struct scroll_bar *));
8252static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
8253 int, int, int));
8254
8255
8256/* Id of action hook installed for scroll bars. */
8257
8258static XtActionHookId action_hook_id;
8259
8260/* Lisp window being scrolled. Set when starting to interact with
8261 a toolkit scroll bar, reset to nil when ending the interaction. */
8262
8263static Lisp_Object window_being_scrolled;
8264
8265/* Last scroll bar part sent in xm_scroll_callback. */
8266
8267static int last_scroll_bar_part;
8268
ec18280f
SM
8269/* Whether this is an Xaw with arrow-scrollbars. This should imply
8270 that movements of 1/20 of the screen size are mapped to up/down. */
8271
8272static Boolean xaw3d_arrow_scroll;
8273
8274/* Whether the drag scrolling maintains the mouse at the top of the
8275 thumb. If not, resizing the thumb needs to be done more carefully
8276 to avoid jerkyness. */
8277
8278static Boolean xaw3d_pick_top;
8279
06a2c219
GM
8280
8281/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 8282 bars are used.. The hook is responsible for detecting when
06a2c219
GM
8283 the user ends an interaction with the scroll bar, and generates
8284 a `end-scroll' scroll_bar_click' event if so. */
8285
8286static void
8287xt_action_hook (widget, client_data, action_name, event, params,
8288 num_params)
8289 Widget widget;
8290 XtPointer client_data;
8291 String action_name;
8292 XEvent *event;
8293 String *params;
8294 Cardinal *num_params;
8295{
8296 int scroll_bar_p;
8297 char *end_action;
8298
8299#ifdef USE_MOTIF
8300 scroll_bar_p = XmIsScrollBar (widget);
8301 end_action = "Release";
ec18280f 8302#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
8303 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
8304 end_action = "EndScroll";
ec18280f 8305#endif /* USE_MOTIF */
06a2c219 8306
06a2c219
GM
8307 if (scroll_bar_p
8308 && strcmp (action_name, end_action) == 0
8309 && WINDOWP (window_being_scrolled))
8310 {
8311 struct window *w;
8312
8313 x_send_scroll_bar_event (window_being_scrolled,
8314 scroll_bar_end_scroll, 0, 0);
8315 w = XWINDOW (window_being_scrolled);
8316 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
8317 window_being_scrolled = Qnil;
8318 last_scroll_bar_part = -1;
bffcfca9
GM
8319
8320 /* Xt timeouts no longer needed. */
8321 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
8322 }
8323}
8324
07b3d16e
GM
8325/* A vector of windows used for communication between
8326 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
8327
8328static struct window **scroll_bar_windows;
8329static int scroll_bar_windows_size;
8330
06a2c219
GM
8331
8332/* Send a client message with message type Xatom_Scrollbar for a
8333 scroll action to the frame of WINDOW. PART is a value identifying
8334 the part of the scroll bar that was clicked on. PORTION is the
8335 amount to scroll of a whole of WHOLE. */
8336
8337static void
8338x_send_scroll_bar_event (window, part, portion, whole)
8339 Lisp_Object window;
8340 int part, portion, whole;
8341{
8342 XEvent event;
8343 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
07b3d16e
GM
8344 struct window *w = XWINDOW (window);
8345 struct frame *f = XFRAME (w->frame);
8346 int i;
06a2c219 8347
07b3d16e
GM
8348 BLOCK_INPUT;
8349
06a2c219
GM
8350 /* Construct a ClientMessage event to send to the frame. */
8351 ev->type = ClientMessage;
8352 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
8353 ev->display = FRAME_X_DISPLAY (f);
8354 ev->window = FRAME_X_WINDOW (f);
8355 ev->format = 32;
07b3d16e
GM
8356
8357 /* We can only transfer 32 bits in the XClientMessageEvent, which is
8358 not enough to store a pointer or Lisp_Object on a 64 bit system.
8359 So, store the window in scroll_bar_windows and pass the index
8360 into that array in the event. */
8361 for (i = 0; i < scroll_bar_windows_size; ++i)
8362 if (scroll_bar_windows[i] == NULL)
8363 break;
8364
8365 if (i == scroll_bar_windows_size)
8366 {
8367 int new_size = max (10, 2 * scroll_bar_windows_size);
8368 size_t nbytes = new_size * sizeof *scroll_bar_windows;
8369 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
8370
8371 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
8372 nbytes);
8373 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8374 scroll_bar_windows_size = new_size;
8375 }
8376
8377 scroll_bar_windows[i] = w;
8378 ev->data.l[0] = (long) i;
06a2c219
GM
8379 ev->data.l[1] = (long) part;
8380 ev->data.l[2] = (long) 0;
8381 ev->data.l[3] = (long) portion;
8382 ev->data.l[4] = (long) whole;
8383
bffcfca9
GM
8384 /* Make Xt timeouts work while the scroll bar is active. */
8385 toolkit_scroll_bar_interaction = 1;
8386
06a2c219
GM
8387 /* Setting the event mask to zero means that the message will
8388 be sent to the client that created the window, and if that
8389 window no longer exists, no event will be sent. */
06a2c219
GM
8390 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8391 UNBLOCK_INPUT;
8392}
8393
8394
8395/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8396 in *IEVENT. */
8397
8398static void
8399x_scroll_bar_to_input_event (event, ievent)
8400 XEvent *event;
8401 struct input_event *ievent;
8402{
8403 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
8404 Lisp_Object window;
8405 struct frame *f;
07b3d16e
GM
8406 struct window *w;
8407
8408 w = scroll_bar_windows[ev->data.l[0]];
8409 scroll_bar_windows[ev->data.l[0]] = NULL;
52e386c2 8410
07b3d16e
GM
8411 XSETWINDOW (window, w);
8412 f = XFRAME (w->frame);
06a2c219
GM
8413
8414 ievent->kind = scroll_bar_click;
8415 ievent->frame_or_window = window;
0f8aabe9 8416 ievent->arg = Qnil;
06a2c219
GM
8417 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8418 ievent->part = ev->data.l[1];
8419 ievent->code = ev->data.l[2];
8420 ievent->x = make_number ((int) ev->data.l[3]);
8421 ievent->y = make_number ((int) ev->data.l[4]);
8422 ievent->modifiers = 0;
8423}
8424
8425
8426#ifdef USE_MOTIF
8427
8428/* Minimum and maximum values used for Motif scroll bars. */
8429
8430#define XM_SB_MIN 1
8431#define XM_SB_MAX 10000000
8432#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8433
8434
8435/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8436 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8437 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8438
8439static void
8440xm_scroll_callback (widget, client_data, call_data)
8441 Widget widget;
8442 XtPointer client_data, call_data;
8443{
8444 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8445 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
06a2c219
GM
8446 int part = -1, whole = 0, portion = 0;
8447
8448 switch (cs->reason)
8449 {
8450 case XmCR_DECREMENT:
8451 bar->dragging = Qnil;
8452 part = scroll_bar_up_arrow;
8453 break;
8454
8455 case XmCR_INCREMENT:
8456 bar->dragging = Qnil;
8457 part = scroll_bar_down_arrow;
8458 break;
8459
8460 case XmCR_PAGE_DECREMENT:
8461 bar->dragging = Qnil;
8462 part = scroll_bar_above_handle;
8463 break;
8464
8465 case XmCR_PAGE_INCREMENT:
8466 bar->dragging = Qnil;
8467 part = scroll_bar_below_handle;
8468 break;
8469
8470 case XmCR_TO_TOP:
8471 bar->dragging = Qnil;
8472 part = scroll_bar_to_top;
8473 break;
8474
8475 case XmCR_TO_BOTTOM:
8476 bar->dragging = Qnil;
8477 part = scroll_bar_to_bottom;
8478 break;
8479
8480 case XmCR_DRAG:
8481 {
8482 int slider_size;
8483 int dragging_down_p = (INTEGERP (bar->dragging)
8484 && XINT (bar->dragging) <= cs->value);
8485
8486 /* Get the slider size. */
8487 BLOCK_INPUT;
8488 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8489 UNBLOCK_INPUT;
8490
8491 /* At the max position of the scroll bar, do a line-wise
23442ae4
GM
8492 movement. Without doing anything, we would be called with
8493 the same cs->value again and again. If we want to make
8494 sure that we can reach the end of the buffer, we have to do
8495 something.
06a2c219
GM
8496
8497 Implementation note: setting bar->dragging always to
8498 cs->value gives a smoother movement at the max position.
8499 Setting it to nil when doing line-wise movement gives
8500 a better slider behavior. */
8501
8502 if (cs->value + slider_size == XM_SB_MAX
8503 || (dragging_down_p
8504 && last_scroll_bar_part == scroll_bar_down_arrow))
8505 {
8506 part = scroll_bar_down_arrow;
8507 bar->dragging = Qnil;
8508 }
8509 else
8510 {
8511 whole = XM_SB_RANGE;
8512 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8513 part = scroll_bar_handle;
8514 bar->dragging = make_number (cs->value);
8515 }
8516 }
8517 break;
8518
8519 case XmCR_VALUE_CHANGED:
8520 break;
8521 };
8522
8523 if (part >= 0)
8524 {
8525 window_being_scrolled = bar->window;
8526 last_scroll_bar_part = part;
8527 x_send_scroll_bar_event (bar->window, part, portion, whole);
8528 }
8529}
8530
8531
ec18280f 8532#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
8533
8534
ec18280f 8535/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
8536 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8537 scroll bar struct. CALL_DATA is a pointer to a float saying where
8538 the thumb is. */
8539
8540static void
ec18280f 8541xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
8542 Widget widget;
8543 XtPointer client_data, call_data;
8544{
8545 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8546 float top = *(float *) call_data;
8547 float shown;
ec18280f
SM
8548 int whole, portion, height;
8549 int part;
06a2c219
GM
8550
8551 /* Get the size of the thumb, a value between 0 and 1. */
8552 BLOCK_INPUT;
ec18280f 8553 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
8554 UNBLOCK_INPUT;
8555
8556 whole = 10000000;
8557 portion = shown < 1 ? top * whole : 0;
06a2c219 8558
ec18280f
SM
8559 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8560 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8561 the bottom, so we force the scrolling whenever we see that we're
8562 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8563 we try to ensure that we always stay two pixels away from the
8564 bottom). */
06a2c219
GM
8565 part = scroll_bar_down_arrow;
8566 else
8567 part = scroll_bar_handle;
8568
8569 window_being_scrolled = bar->window;
8570 bar->dragging = make_number (portion);
8571 last_scroll_bar_part = part;
8572 x_send_scroll_bar_event (bar->window, part, portion, whole);
8573}
8574
8575
ec18280f
SM
8576/* Xaw scroll bar callback. Invoked for incremental scrolling.,
8577 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
8578 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8579 the scroll bar. CALL_DATA is an integer specifying the action that
8580 has taken place. It's magnitude is in the range 0..height of the
8581 scroll bar. Negative values mean scroll towards buffer start.
8582 Values < height of scroll bar mean line-wise movement. */
8583
8584static void
ec18280f 8585xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
8586 Widget widget;
8587 XtPointer client_data, call_data;
8588{
8589 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8590 int position = (int) call_data;
8591 Dimension height;
8592 int part;
8593
8594 /* Get the height of the scroll bar. */
8595 BLOCK_INPUT;
8596 XtVaGetValues (widget, XtNheight, &height, NULL);
8597 UNBLOCK_INPUT;
8598
ec18280f
SM
8599 if (abs (position) >= height)
8600 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8601
8602 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8603 it maps line-movement to call_data = max(5, height/20). */
8604 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8605 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 8606 else
ec18280f 8607 part = scroll_bar_move_ratio;
06a2c219
GM
8608
8609 window_being_scrolled = bar->window;
8610 bar->dragging = Qnil;
8611 last_scroll_bar_part = part;
ec18280f 8612 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
8613}
8614
8615
8616#endif /* not USE_MOTIF */
8617
8618
8619/* Create the widget for scroll bar BAR on frame F. Record the widget
8620 and X window of the scroll bar in BAR. */
8621
8622static void
8623x_create_toolkit_scroll_bar (f, bar)
8624 struct frame *f;
8625 struct scroll_bar *bar;
8626{
8627 Window xwindow;
8628 Widget widget;
8629 Arg av[20];
8630 int ac = 0;
8631 char *scroll_bar_name = "verticalScrollBar";
8632 unsigned long pixel;
8633
8634 BLOCK_INPUT;
8635
8636#ifdef USE_MOTIF
06a2c219
GM
8637 /* Set resources. Create the widget. */
8638 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8639 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8640 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8641 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8642 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8643 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8644 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8645
8646 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8647 if (pixel != -1)
8648 {
8649 XtSetArg (av[ac], XmNforeground, pixel);
8650 ++ac;
8651 }
8652
8653 pixel = f->output_data.x->scroll_bar_background_pixel;
8654 if (pixel != -1)
8655 {
8656 XtSetArg (av[ac], XmNbackground, pixel);
8657 ++ac;
8658 }
8659
8660 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8661 scroll_bar_name, av, ac);
8662
8663 /* Add one callback for everything that can happen. */
8664 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8665 (XtPointer) bar);
8666 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8667 (XtPointer) bar);
8668 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8669 (XtPointer) bar);
8670 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8671 (XtPointer) bar);
8672 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8673 (XtPointer) bar);
8674 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8675 (XtPointer) bar);
8676 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8677 (XtPointer) bar);
8678
8679 /* Realize the widget. Only after that is the X window created. */
8680 XtRealizeWidget (widget);
8681
8682 /* Set the cursor to an arrow. I didn't find a resource to do that.
8683 And I'm wondering why it hasn't an arrow cursor by default. */
8684 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8685 f->output_data.x->nontext_cursor);
8686
ec18280f 8687#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
8688
8689 /* Set resources. Create the widget. The background of the
8690 Xaw3d scroll bar widget is a little bit light for my taste.
8691 We don't alter it here to let users change it according
8692 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8693 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8694 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
8695 /* For smoother scrolling with Xaw3d -sm */
8696 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
06a2c219
GM
8697
8698 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8699 if (pixel != -1)
8700 {
8701 XtSetArg (av[ac], XtNforeground, pixel);
8702 ++ac;
8703 }
8704
8705 pixel = f->output_data.x->scroll_bar_background_pixel;
8706 if (pixel != -1)
8707 {
8708 XtSetArg (av[ac], XtNbackground, pixel);
8709 ++ac;
8710 }
7c1bef7a
MB
8711
8712 /* Top/bottom shadow colors. */
8713
8714 /* Allocate them, if necessary. */
8715 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1)
8716 {
8717 pixel = f->output_data.x->scroll_bar_background_pixel;
8718 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8719 &pixel, 1.2, 0x8000))
8720 pixel = -1;
8721 f->output_data.x->scroll_bar_top_shadow_pixel = pixel;
8722 }
8723 if (f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8724 {
8725 pixel = f->output_data.x->scroll_bar_background_pixel;
8726 if (!x_alloc_lighter_color (f, FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f),
8727 &pixel, 0.6, 0x4000))
8728 pixel = -1;
8729 f->output_data.x->scroll_bar_bottom_shadow_pixel = pixel;
8730 }
8731
8732 /* Tell the toolkit about them. */
8733 if (f->output_data.x->scroll_bar_top_shadow_pixel == -1
8734 || f->output_data.x->scroll_bar_bottom_shadow_pixel == -1)
8735 /* We tried to allocate a color for the top/bottom shadow, and
8736 failed, so tell Xaw3d to use dithering instead. */
8737 {
8738 XtSetArg (av[ac], XtNbeNiceToColormap, True);
8739 ++ac;
8740 }
8741 else
8742 /* Tell what colors Xaw3d should use for the top/bottom shadow, to
8743 be more consistent with other emacs 3d colors, and since Xaw3d is
8744 not good at dealing with allocation failure. */
8745 {
8746 /* This tells Xaw3d to use real colors instead of dithering for
8747 the shadows. */
8748 XtSetArg (av[ac], XtNbeNiceToColormap, False);
8749 ++ac;
8750
8751 /* Specify the colors. */
8752 pixel = f->output_data.x->scroll_bar_top_shadow_pixel;
8753 if (pixel != -1)
8754 {
8755 XtSetArg (av[ac], "topShadowPixel", pixel);
8756 ++ac;
8757 }
8758 pixel = f->output_data.x->scroll_bar_bottom_shadow_pixel;
8759 if (pixel != -1)
8760 {
8761 XtSetArg (av[ac], "bottomShadowPixel", pixel);
8762 ++ac;
8763 }
8764 }
8765
06a2c219
GM
8766 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8767 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
8768
8769 {
8770 char *initial = "";
8771 char *val = initial;
8772 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8773 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8774 if (val == initial)
8775 { /* ARROW_SCROLL */
8776 xaw3d_arrow_scroll = True;
8777 /* Isn't that just a personal preference ? -sm */
8778 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8779 }
8780 }
06a2c219
GM
8781
8782 /* Define callbacks. */
ec18280f
SM
8783 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8784 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
8785 (XtPointer) bar);
8786
8787 /* Realize the widget. Only after that is the X window created. */
8788 XtRealizeWidget (widget);
8789
ec18280f 8790#endif /* !USE_MOTIF */
06a2c219
GM
8791
8792 /* Install an action hook that let's us detect when the user
8793 finishes interacting with a scroll bar. */
8794 if (action_hook_id == 0)
8795 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8796
8797 /* Remember X window and widget in the scroll bar vector. */
8798 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8799 xwindow = XtWindow (widget);
8800 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8801
8802 UNBLOCK_INPUT;
8803}
8804
8805
8806/* Set the thumb size and position of scroll bar BAR. We are currently
8807 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8808
8809static void
8810x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8811 struct scroll_bar *bar;
8812 int portion, position, whole;
f451eb13 8813{
e83dc917
GM
8814 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8815 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
06a2c219 8816 float top, shown;
f451eb13 8817
06a2c219
GM
8818 if (whole == 0)
8819 top = 0, shown = 1;
8820 else
f451eb13 8821 {
06a2c219
GM
8822 top = (float) position / whole;
8823 shown = (float) portion / whole;
8824 }
f451eb13 8825
06a2c219 8826 BLOCK_INPUT;
f451eb13 8827
06a2c219
GM
8828#ifdef USE_MOTIF
8829 {
8830 int size, value;
06a2c219 8831
ec18280f 8832 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
8833 is the scroll bar's maximum and MIN is the scroll bar's minimum
8834 value. */
8835 size = shown * XM_SB_RANGE;
8836 size = min (size, XM_SB_RANGE);
8837 size = max (size, 1);
8838
8839 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8840 value = top * XM_SB_RANGE;
8841 value = min (value, XM_SB_MAX - size);
8842 value = max (value, XM_SB_MIN);
8843
06a2c219
GM
8844 if (NILP (bar->dragging))
8845 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8846 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8847 /* This has the negative side effect that the slider value is
ec18280f 8848 not what it would be if we scrolled here using line-wise or
06a2c219
GM
8849 page-wise movement. */
8850 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8851 else
8852 {
8853 /* If currently dragging, only update the slider size.
8854 This reduces flicker effects. */
8855 int old_value, old_size, increment, page_increment;
8856
8857 XmScrollBarGetValues (widget, &old_value, &old_size,
8858 &increment, &page_increment);
8859 XmScrollBarSetValues (widget, old_value,
8860 min (size, XM_SB_RANGE - old_value),
8861 0, 0, False);
8862 }
06a2c219 8863 }
ec18280f 8864#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 8865 {
ec18280f
SM
8866 float old_top, old_shown;
8867 Dimension height;
8868 XtVaGetValues (widget,
8869 XtNtopOfThumb, &old_top,
8870 XtNshown, &old_shown,
8871 XtNheight, &height,
8872 NULL);
8873
8874 /* Massage the top+shown values. */
8875 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8876 top = max (0, min (1, top));
8877 else
8878 top = old_top;
8879 /* Keep two pixels available for moving the thumb down. */
8880 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8881
8882 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8883 check that your system's configuration file contains a define
8884 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8885 if (top != old_top || shown != old_shown)
eb393530 8886 {
ec18280f 8887 if (NILP (bar->dragging))
eb393530 8888 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8889 else
8890 {
ec18280f
SM
8891#ifdef HAVE_XAW3D
8892 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8893 int scroll_mode = 0;
ec18280f
SM
8894
8895 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8896 if (xaw3d_arrow_scroll)
8897 {
8898 /* Xaw3d stupidly ignores resize requests while dragging
8899 so we have to make it believe it's not in dragging mode. */
8900 scroll_mode = sb->scrollbar.scroll_mode;
8901 if (scroll_mode == 2)
8902 sb->scrollbar.scroll_mode = 0;
8903 }
8904#endif
8905 /* Try to make the scrolling a tad smoother. */
8906 if (!xaw3d_pick_top)
8907 shown = min (shown, old_shown);
8908
8909 XawScrollbarSetThumb (widget, top, shown);
8910
8911#ifdef HAVE_XAW3D
8912 if (xaw3d_arrow_scroll && scroll_mode == 2)
8913 sb->scrollbar.scroll_mode = scroll_mode;
8914#endif
06a2c219 8915 }
06a2c219
GM
8916 }
8917 }
ec18280f 8918#endif /* !USE_MOTIF */
06a2c219
GM
8919
8920 UNBLOCK_INPUT;
f451eb13
JB
8921}
8922
06a2c219
GM
8923#endif /* USE_TOOLKIT_SCROLL_BARS */
8924
8925
8926\f
8927/************************************************************************
8928 Scroll bars, general
8929 ************************************************************************/
8930
8931/* Create a scroll bar and return the scroll bar vector for it. W is
8932 the Emacs window on which to create the scroll bar. TOP, LEFT,
8933 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8934 scroll bar. */
8935
ab648270 8936static struct scroll_bar *
06a2c219
GM
8937x_scroll_bar_create (w, top, left, width, height)
8938 struct window *w;
f451eb13
JB
8939 int top, left, width, height;
8940{
06a2c219 8941 struct frame *f = XFRAME (w->frame);
334208b7
RS
8942 struct scroll_bar *bar
8943 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8944
8945 BLOCK_INPUT;
8946
eccc05db 8947#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8948 x_create_toolkit_scroll_bar (f, bar);
8949#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8950 {
8951 XSetWindowAttributes a;
8952 unsigned long mask;
5c187dee 8953 Window window;
06a2c219
GM
8954
8955 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8956 if (a.background_pixel == -1)
8957 a.background_pixel = f->output_data.x->background_pixel;
8958
12ba150f 8959 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8960 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8961 | ExposureMask);
7a13e894 8962 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8963
dbc4e1c1 8964 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8965
06a2c219
GM
8966 /* Clear the area of W that will serve as a scroll bar. This is
8967 for the case that a window has been split horizontally. In
8968 this case, no clear_frame is generated to reduce flickering. */
c5e6e06b
GM
8969 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8970 left, top, width,
8971 window_box_height (w), False);
06a2c219
GM
8972
8973 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8974 /* Position and size of scroll bar. */
8975 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8976 top,
8977 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8978 height,
8979 /* Border width, depth, class, and visual. */
8980 0,
8981 CopyFromParent,
8982 CopyFromParent,
8983 CopyFromParent,
8984 /* Attributes. */
8985 mask, &a);
8986 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8987 }
06a2c219 8988#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8989
06a2c219 8990 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8991 XSETINT (bar->top, top);
8992 XSETINT (bar->left, left);
8993 XSETINT (bar->width, width);
8994 XSETINT (bar->height, height);
8995 XSETINT (bar->start, 0);
8996 XSETINT (bar->end, 0);
12ba150f 8997 bar->dragging = Qnil;
f451eb13
JB
8998
8999 /* Add bar to its frame's list of scroll bars. */
334208b7 9000 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 9001 bar->prev = Qnil;
334208b7 9002 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 9003 if (!NILP (bar->next))
e0c1aef2 9004 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 9005
06a2c219 9006 /* Map the window/widget. */
eccc05db 9007#ifdef USE_TOOLKIT_SCROLL_BARS
f964b4d7
GM
9008 {
9009 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
9010 XtConfigureWidget (scroll_bar,
9011 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9012 top,
9013 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
9014 max (height, 1), 0);
9015 XtMapWidget (scroll_bar);
9016 }
06a2c219 9017#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 9018 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 9019#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
9020
9021 UNBLOCK_INPUT;
12ba150f 9022 return bar;
f451eb13
JB
9023}
9024
06a2c219 9025
12ba150f 9026/* Draw BAR's handle in the proper position.
06a2c219 9027
12ba150f
JB
9028 If the handle is already drawn from START to END, don't bother
9029 redrawing it, unless REBUILD is non-zero; in that case, always
9030 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 9031 events.)
12ba150f
JB
9032
9033 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
9034 fit inside its rectangle, but if the user is dragging the scroll
9035 bar handle, we want to let them drag it down all the way, so that
9036 the bar's top is as far down as it goes; otherwise, there's no way
9037 to move to the very end of the buffer. */
9038
5c187dee
GM
9039#ifndef USE_TOOLKIT_SCROLL_BARS
9040
f451eb13 9041static void
ab648270
JB
9042x_scroll_bar_set_handle (bar, start, end, rebuild)
9043 struct scroll_bar *bar;
f451eb13 9044 int start, end;
12ba150f 9045 int rebuild;
f451eb13 9046{
12ba150f 9047 int dragging = ! NILP (bar->dragging);
ab648270 9048 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 9049 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 9050 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
9051
9052 /* If the display is already accurate, do nothing. */
9053 if (! rebuild
9054 && start == XINT (bar->start)
9055 && end == XINT (bar->end))
9056 return;
9057
f451eb13
JB
9058 BLOCK_INPUT;
9059
9060 {
d9cdbb3d
RS
9061 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
9062 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
9063 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
9064
9065 /* Make sure the values are reasonable, and try to preserve
9066 the distance between start and end. */
12ba150f
JB
9067 {
9068 int length = end - start;
9069
9070 if (start < 0)
9071 start = 0;
9072 else if (start > top_range)
9073 start = top_range;
9074 end = start + length;
9075
9076 if (end < start)
9077 end = start;
9078 else if (end > top_range && ! dragging)
9079 end = top_range;
9080 }
f451eb13 9081
ab648270 9082 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
9083 XSETINT (bar->start, start);
9084 XSETINT (bar->end, end);
f451eb13 9085
12ba150f
JB
9086 /* Clip the end position, just for display. */
9087 if (end > top_range)
9088 end = top_range;
f451eb13 9089
ab648270 9090 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
9091 below top positions, to make sure the handle is always at least
9092 that many pixels tall. */
ab648270 9093 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 9094
12ba150f
JB
9095 /* Draw the empty space above the handle. Note that we can't clear
9096 zero-height areas; that means "clear to end of window." */
9097 if (0 < start)
c5e6e06b
GM
9098 x_clear_area (FRAME_X_DISPLAY (f), w,
9099 /* x, y, width, height, and exposures. */
9100 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9101 VERTICAL_SCROLL_BAR_TOP_BORDER,
9102 inside_width, start,
9103 False);
f451eb13 9104
06a2c219
GM
9105 /* Change to proper foreground color if one is specified. */
9106 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9107 XSetForeground (FRAME_X_DISPLAY (f), gc,
9108 f->output_data.x->scroll_bar_foreground_pixel);
9109
12ba150f 9110 /* Draw the handle itself. */
334208b7 9111 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
12ba150f 9112 /* x, y, width, height */
ab648270
JB
9113 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9114 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 9115 inside_width, end - start);
f451eb13 9116
06a2c219
GM
9117 /* Restore the foreground color of the GC if we changed it above. */
9118 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
9119 XSetForeground (FRAME_X_DISPLAY (f), gc,
9120 f->output_data.x->foreground_pixel);
f451eb13 9121
12ba150f
JB
9122 /* Draw the empty space below the handle. Note that we can't
9123 clear zero-height areas; that means "clear to end of window." */
9124 if (end < inside_height)
c5e6e06b
GM
9125 x_clear_area (FRAME_X_DISPLAY (f), w,
9126 /* x, y, width, height, and exposures. */
9127 VERTICAL_SCROLL_BAR_LEFT_BORDER,
9128 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
9129 inside_width, inside_height - end,
9130 False);
f451eb13 9131
f451eb13
JB
9132 }
9133
f451eb13
JB
9134 UNBLOCK_INPUT;
9135}
9136
5c187dee 9137#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 9138
06a2c219
GM
9139/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
9140 nil. */
58769bee 9141
12ba150f 9142static void
ab648270
JB
9143x_scroll_bar_remove (bar)
9144 struct scroll_bar *bar;
12ba150f 9145{
e83dc917 9146 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
9147 BLOCK_INPUT;
9148
eccc05db 9149#ifdef USE_TOOLKIT_SCROLL_BARS
e83dc917
GM
9150 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
9151#else
9152 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
9153#endif
06a2c219 9154
ab648270
JB
9155 /* Disassociate this scroll bar from its window. */
9156 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
9157
9158 UNBLOCK_INPUT;
9159}
9160
06a2c219 9161
12ba150f
JB
9162/* Set the handle of the vertical scroll bar for WINDOW to indicate
9163 that we are displaying PORTION characters out of a total of WHOLE
ab648270 9164 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 9165 create one. */
06a2c219 9166
12ba150f 9167static void
06a2c219
GM
9168XTset_vertical_scroll_bar (w, portion, whole, position)
9169 struct window *w;
f451eb13
JB
9170 int portion, whole, position;
9171{
06a2c219 9172 struct frame *f = XFRAME (w->frame);
ab648270 9173 struct scroll_bar *bar;
3c6ede7b 9174 int top, height, left, sb_left, width, sb_width;
06a2c219 9175 int window_x, window_y, window_width, window_height;
06a2c219 9176
3c6ede7b 9177 /* Get window dimensions. */
06a2c219 9178 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
9179 top = window_y;
9180 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9181 height = window_height;
06a2c219 9182
3c6ede7b 9183 /* Compute the left edge of the scroll bar area. */
06a2c219 9184 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
9185 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
9186 else
9187 left = XFASTINT (w->left);
9188 left *= CANON_X_UNIT (f);
9189 left += FRAME_INTERNAL_BORDER_WIDTH (f);
9190
9191 /* Compute the width of the scroll bar which might be less than
9192 the width of the area reserved for the scroll bar. */
9193 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
9194 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 9195 else
3c6ede7b 9196 sb_width = width;
12ba150f 9197
3c6ede7b
GM
9198 /* Compute the left edge of the scroll bar. */
9199#ifdef USE_TOOLKIT_SCROLL_BARS
9200 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9201 sb_left = left + width - sb_width - (width - sb_width) / 2;
9202 else
9203 sb_left = left + (width - sb_width) / 2;
9204#else
9205 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
9206 sb_left = left + width - sb_width;
9207 else
9208 sb_left = left;
9209#endif
9210
ab648270 9211 /* Does the scroll bar exist yet? */
06a2c219 9212 if (NILP (w->vertical_scroll_bar))
3c6ede7b 9213 {
80c32bcc 9214 BLOCK_INPUT;
f964b4d7
GM
9215 if (width && height)
9216 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9217 left, top, width, height, False);
80c32bcc 9218 UNBLOCK_INPUT;
3c6ede7b
GM
9219 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
9220 }
f451eb13 9221 else
12ba150f
JB
9222 {
9223 /* It may just need to be moved and resized. */
06a2c219
GM
9224 unsigned int mask = 0;
9225
9226 bar = XSCROLL_BAR (w->vertical_scroll_bar);
9227
9228 BLOCK_INPUT;
9229
3c6ede7b 9230 if (sb_left != XINT (bar->left))
06a2c219 9231 mask |= CWX;
3c6ede7b 9232 if (top != XINT (bar->top))
06a2c219 9233 mask |= CWY;
3c6ede7b 9234 if (sb_width != XINT (bar->width))
06a2c219 9235 mask |= CWWidth;
3c6ede7b 9236 if (height != XINT (bar->height))
06a2c219
GM
9237 mask |= CWHeight;
9238
9239#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
9240
9241 /* Since toolkit scroll bars are smaller than the space reserved
9242 for them on the frame, we have to clear "under" them. */
f964b4d7
GM
9243 if (width && height)
9244 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9245 left, top, width, height, False);
06a2c219
GM
9246
9247 /* Move/size the scroll bar widget. */
9248 if (mask)
e83dc917 9249 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
3c6ede7b
GM
9250 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9251 top,
9252 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
f964b4d7 9253 max (height, 1), 0);
06a2c219
GM
9254
9255#else /* not USE_TOOLKIT_SCROLL_BARS */
9256
357e7376
GM
9257 /* Clear areas not covered by the scroll bar because of
9258 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
e1f6572f
RS
9259 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
9260 {
c5e6e06b
GM
9261 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9262 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9263 height, False);
9264 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9265 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9266 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
9267 height, False);
e1f6572f 9268 }
357e7376
GM
9269
9270 /* Clear areas not covered by the scroll bar because it's not as
9271 wide as the area reserved for it . This makes sure a
9272 previous mode line display is cleared after C-x 2 C-x 1, for
9273 example. */
9274 {
9275 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
9276 int rest = area_width - sb_width;
9277 if (rest > 0)
9278 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9279 left + area_width - rest, 0,
9280 rest, max (height, 1), False);
9281 }
06a2c219
GM
9282
9283 /* Move/size the scroll bar window. */
9284 if (mask)
9285 {
9286 XWindowChanges wc;
9287
3c6ede7b
GM
9288 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
9289 wc.y = top;
9290 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
9291 wc.height = height;
06a2c219
GM
9292 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
9293 mask, &wc);
9294 }
9295
9296#endif /* not USE_TOOLKIT_SCROLL_BARS */
9297
9298 /* Remember new settings. */
3c6ede7b
GM
9299 XSETINT (bar->left, sb_left);
9300 XSETINT (bar->top, top);
9301 XSETINT (bar->width, sb_width);
9302 XSETINT (bar->height, height);
06a2c219
GM
9303
9304 UNBLOCK_INPUT;
12ba150f 9305 }
f451eb13 9306
eccc05db 9307#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
9308 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
9309#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 9310 /* Set the scroll bar's current state, unless we're currently being
f451eb13 9311 dragged. */
12ba150f 9312 if (NILP (bar->dragging))
f451eb13 9313 {
92857db0 9314 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 9315
12ba150f 9316 if (whole == 0)
ab648270 9317 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
9318 else
9319 {
43f868f5
JB
9320 int start = ((double) position * top_range) / whole;
9321 int end = ((double) (position + portion) * top_range) / whole;
ab648270 9322 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 9323 }
f451eb13 9324 }
06a2c219 9325#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 9326
06a2c219 9327 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
9328}
9329
12ba150f 9330
f451eb13 9331/* The following three hooks are used when we're doing a thorough
ab648270 9332 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 9333 are going to be deleted, because keeping track of when windows go
12ba150f
JB
9334 away is a real pain - "Can you say set-window-configuration, boys
9335 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 9336 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 9337 from the fiery pit when we actually redisplay its window. */
f451eb13 9338
ab648270
JB
9339/* Arrange for all scroll bars on FRAME to be removed at the next call
9340 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
9341 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
9342
58769bee 9343static void
ab648270 9344XTcondemn_scroll_bars (frame)
f451eb13
JB
9345 FRAME_PTR frame;
9346{
f9e24cb9
RS
9347 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
9348 while (! NILP (FRAME_SCROLL_BARS (frame)))
9349 {
9350 Lisp_Object bar;
9351 bar = FRAME_SCROLL_BARS (frame);
9352 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
9353 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
9354 XSCROLL_BAR (bar)->prev = Qnil;
9355 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
9356 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
9357 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
9358 }
f451eb13
JB
9359}
9360
fa2dfc30 9361
06a2c219 9362/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 9363 Note that WINDOW isn't necessarily condemned at all. */
fa2dfc30 9364
f451eb13 9365static void
ab648270 9366XTredeem_scroll_bar (window)
12ba150f 9367 struct window *window;
f451eb13 9368{
ab648270 9369 struct scroll_bar *bar;
fa2dfc30 9370 struct frame *f;
12ba150f 9371
ab648270
JB
9372 /* We can't redeem this window's scroll bar if it doesn't have one. */
9373 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
9374 abort ();
9375
ab648270 9376 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
9377
9378 /* Unlink it from the condemned list. */
fa2dfc30
GM
9379 f = XFRAME (WINDOW_FRAME (window));
9380 if (NILP (bar->prev))
9381 {
9382 /* If the prev pointer is nil, it must be the first in one of
9383 the lists. */
9384 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
9385 /* It's not condemned. Everything's fine. */
9386 return;
9387 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
9388 window->vertical_scroll_bar))
9389 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
9390 else
9391 /* If its prev pointer is nil, it must be at the front of
9392 one or the other! */
9393 abort ();
9394 }
9395 else
9396 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f 9397
fa2dfc30
GM
9398 if (! NILP (bar->next))
9399 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 9400
fa2dfc30
GM
9401 bar->next = FRAME_SCROLL_BARS (f);
9402 bar->prev = Qnil;
9403 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
9404 if (! NILP (bar->next))
9405 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13
JB
9406}
9407
ab648270
JB
9408/* Remove all scroll bars on FRAME that haven't been saved since the
9409 last call to `*condemn_scroll_bars_hook'. */
06a2c219 9410
f451eb13 9411static void
ab648270 9412XTjudge_scroll_bars (f)
12ba150f 9413 FRAME_PTR f;
f451eb13 9414{
12ba150f 9415 Lisp_Object bar, next;
f451eb13 9416
ab648270 9417 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
9418
9419 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
9420 more events on the hapless scroll bars. */
9421 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
9422
9423 for (; ! NILP (bar); bar = next)
f451eb13 9424 {
ab648270 9425 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 9426
ab648270 9427 x_scroll_bar_remove (b);
12ba150f
JB
9428
9429 next = b->next;
9430 b->next = b->prev = Qnil;
f451eb13 9431 }
12ba150f 9432
ab648270 9433 /* Now there should be no references to the condemned scroll bars,
12ba150f 9434 and they should get garbage-collected. */
f451eb13
JB
9435}
9436
9437
06a2c219
GM
9438/* Handle an Expose or GraphicsExpose event on a scroll bar. This
9439 is a no-op when using toolkit scroll bars.
ab648270
JB
9440
9441 This may be called from a signal handler, so we have to ignore GC
9442 mark bits. */
06a2c219 9443
f451eb13 9444static void
ab648270
JB
9445x_scroll_bar_expose (bar, event)
9446 struct scroll_bar *bar;
f451eb13
JB
9447 XEvent *event;
9448{
06a2c219
GM
9449#ifndef USE_TOOLKIT_SCROLL_BARS
9450
ab648270 9451 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 9452 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 9453 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 9454 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 9455
f451eb13
JB
9456 BLOCK_INPUT;
9457
ab648270 9458 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 9459
06a2c219 9460 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 9461 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
9462
9463 /* x, y, width, height */
d9cdbb3d 9464 0, 0,
3cbd2e0b 9465 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
9466 XINT (bar->height) - 1);
9467
f451eb13 9468 UNBLOCK_INPUT;
06a2c219
GM
9469
9470#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
9471}
9472
ab648270
JB
9473/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9474 is set to something other than no_event, it is enqueued.
9475
9476 This may be called from a signal handler, so we have to ignore GC
9477 mark bits. */
06a2c219 9478
5c187dee
GM
9479#ifndef USE_TOOLKIT_SCROLL_BARS
9480
f451eb13 9481static void
ab648270
JB
9482x_scroll_bar_handle_click (bar, event, emacs_event)
9483 struct scroll_bar *bar;
f451eb13
JB
9484 XEvent *event;
9485 struct input_event *emacs_event;
9486{
0299d313 9487 if (! GC_WINDOWP (bar->window))
12ba150f
JB
9488 abort ();
9489
ab648270 9490 emacs_event->kind = scroll_bar_click;
69388238 9491 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
9492 emacs_event->modifiers
9493 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9494 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9495 event->xbutton.state)
9496 | (event->type == ButtonRelease
9497 ? up_modifier
9498 : down_modifier));
12ba150f 9499 emacs_event->frame_or_window = bar->window;
0f8aabe9 9500 emacs_event->arg = Qnil;
f451eb13 9501 emacs_event->timestamp = event->xbutton.time;
12ba150f 9502 {
06a2c219 9503#if 0
d9cdbb3d 9504 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 9505 int internal_height
d9cdbb3d 9506 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 9507#endif
0299d313 9508 int top_range
d9cdbb3d 9509 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 9510 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
9511
9512 if (y < 0) y = 0;
9513 if (y > top_range) y = top_range;
9514
9515 if (y < XINT (bar->start))
ab648270
JB
9516 emacs_event->part = scroll_bar_above_handle;
9517 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9518 emacs_event->part = scroll_bar_handle;
12ba150f 9519 else
ab648270 9520 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
9521
9522 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
9523 they want to drag it. Lisp code needs to be able to decide
9524 whether or not we're dragging. */
929787e1 9525#if 0
12ba150f
JB
9526 /* If the user has just clicked on the handle, record where they're
9527 holding it. */
9528 if (event->type == ButtonPress
ab648270 9529 && emacs_event->part == scroll_bar_handle)
e0c1aef2 9530 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 9531#endif
12ba150f
JB
9532
9533 /* If the user has released the handle, set it to its final position. */
9534 if (event->type == ButtonRelease
9535 && ! NILP (bar->dragging))
9536 {
9537 int new_start = y - XINT (bar->dragging);
9538 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 9539
ab648270 9540 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
9541 bar->dragging = Qnil;
9542 }
f451eb13 9543
5116f055
JB
9544 /* Same deal here as the other #if 0. */
9545#if 0
58769bee 9546 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 9547 the handle. */
ab648270 9548 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
9549 emacs_event->x = bar->start;
9550 else
e0c1aef2 9551 XSETINT (emacs_event->x, y);
5116f055 9552#else
e0c1aef2 9553 XSETINT (emacs_event->x, y);
5116f055 9554#endif
f451eb13 9555
e0c1aef2 9556 XSETINT (emacs_event->y, top_range);
12ba150f
JB
9557 }
9558}
f451eb13 9559
ab648270
JB
9560/* Handle some mouse motion while someone is dragging the scroll bar.
9561
9562 This may be called from a signal handler, so we have to ignore GC
9563 mark bits. */
06a2c219 9564
f451eb13 9565static void
ab648270
JB
9566x_scroll_bar_note_movement (bar, event)
9567 struct scroll_bar *bar;
f451eb13
JB
9568 XEvent *event;
9569{
39d8bb4d
KH
9570 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9571
f451eb13
JB
9572 last_mouse_movement_time = event->xmotion.time;
9573
39d8bb4d 9574 f->mouse_moved = 1;
e0c1aef2 9575 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
9576
9577 /* If we're dragging the bar, display it. */
ab648270 9578 if (! GC_NILP (bar->dragging))
f451eb13
JB
9579 {
9580 /* Where should the handle be now? */
12ba150f 9581 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 9582
12ba150f 9583 if (new_start != XINT (bar->start))
f451eb13 9584 {
12ba150f 9585 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 9586
ab648270 9587 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
9588 }
9589 }
f451eb13
JB
9590}
9591
5c187dee
GM
9592#endif /* !USE_TOOLKIT_SCROLL_BARS */
9593
12ba150f 9594/* Return information to the user about the current position of the mouse
ab648270 9595 on the scroll bar. */
06a2c219 9596
12ba150f 9597static void
334208b7
RS
9598x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9599 FRAME_PTR *fp;
12ba150f 9600 Lisp_Object *bar_window;
ab648270 9601 enum scroll_bar_part *part;
12ba150f
JB
9602 Lisp_Object *x, *y;
9603 unsigned long *time;
9604{
ab648270 9605 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
9606 Window w = SCROLL_BAR_X_WINDOW (bar);
9607 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 9608 int win_x, win_y;
559cb2fb
JB
9609 Window dummy_window;
9610 int dummy_coord;
9611 unsigned int dummy_mask;
12ba150f 9612
cf7cb199
JB
9613 BLOCK_INPUT;
9614
ab648270 9615 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 9616 report that. */
334208b7 9617 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 9618
559cb2fb
JB
9619 /* Root, child, root x and root y. */
9620 &dummy_window, &dummy_window,
9621 &dummy_coord, &dummy_coord,
12ba150f 9622
559cb2fb
JB
9623 /* Position relative to scroll bar. */
9624 &win_x, &win_y,
12ba150f 9625
559cb2fb
JB
9626 /* Mouse buttons and modifier keys. */
9627 &dummy_mask))
7a13e894 9628 ;
559cb2fb
JB
9629 else
9630 {
06a2c219 9631#if 0
559cb2fb 9632 int inside_height
d9cdbb3d 9633 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 9634#endif
559cb2fb 9635 int top_range
d9cdbb3d 9636 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
9637
9638 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9639
9640 if (! NILP (bar->dragging))
9641 win_y -= XINT (bar->dragging);
9642
9643 if (win_y < 0)
9644 win_y = 0;
9645 if (win_y > top_range)
9646 win_y = top_range;
9647
334208b7 9648 *fp = f;
7a13e894 9649 *bar_window = bar->window;
559cb2fb
JB
9650
9651 if (! NILP (bar->dragging))
9652 *part = scroll_bar_handle;
9653 else if (win_y < XINT (bar->start))
9654 *part = scroll_bar_above_handle;
9655 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9656 *part = scroll_bar_handle;
9657 else
9658 *part = scroll_bar_below_handle;
12ba150f 9659
e0c1aef2
KH
9660 XSETINT (*x, win_y);
9661 XSETINT (*y, top_range);
12ba150f 9662
39d8bb4d 9663 f->mouse_moved = 0;
559cb2fb
JB
9664 last_mouse_scroll_bar = Qnil;
9665 }
12ba150f 9666
559cb2fb 9667 *time = last_mouse_movement_time;
cf7cb199 9668
cf7cb199 9669 UNBLOCK_INPUT;
12ba150f
JB
9670}
9671
f451eb13 9672
dbc4e1c1 9673/* The screen has been cleared so we may have changed foreground or
ab648270
JB
9674 background colors, and the scroll bars may need to be redrawn.
9675 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
9676 redraw them. */
9677
dfcf069d 9678void
ab648270 9679x_scroll_bar_clear (f)
dbc4e1c1
JB
9680 FRAME_PTR f;
9681{
06a2c219 9682#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
9683 Lisp_Object bar;
9684
b80c363e
RS
9685 /* We can have scroll bars even if this is 0,
9686 if we just turned off scroll bar mode.
9687 But in that case we should not clear them. */
9688 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9689 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9690 bar = XSCROLL_BAR (bar)->next)
c5e6e06b
GM
9691 XClearArea (FRAME_X_DISPLAY (f),
9692 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
b80c363e 9693 0, 0, 0, 0, True);
06a2c219 9694#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
9695}
9696
06a2c219 9697/* This processes Expose events from the menu-bar specific X event
19126e11 9698 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 9699 when handling menu-bar or pop-up items. */
3afe33e7 9700
06a2c219 9701int
3afe33e7
RS
9702process_expose_from_menu (event)
9703 XEvent event;
9704{
9705 FRAME_PTR f;
19126e11 9706 struct x_display_info *dpyinfo;
06a2c219 9707 int frame_exposed_p = 0;
3afe33e7 9708
f94397b5
KH
9709 BLOCK_INPUT;
9710
19126e11
KH
9711 dpyinfo = x_display_info_for_display (event.xexpose.display);
9712 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
9713 if (f)
9714 {
9715 if (f->async_visible == 0)
9716 {
9717 f->async_visible = 1;
9718 f->async_iconified = 0;
06c488fd 9719 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
9720 SET_FRAME_GARBAGED (f);
9721 }
9722 else
9723 {
06a2c219
GM
9724 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9725 event.xexpose.x, event.xexpose.y,
9726 event.xexpose.width, event.xexpose.height);
9727 frame_exposed_p = 1;
3afe33e7
RS
9728 }
9729 }
9730 else
9731 {
9732 struct scroll_bar *bar
9733 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9734
3afe33e7
RS
9735 if (bar)
9736 x_scroll_bar_expose (bar, &event);
9737 }
f94397b5
KH
9738
9739 UNBLOCK_INPUT;
06a2c219 9740 return frame_exposed_p;
3afe33e7 9741}
09756a85
RS
9742\f
9743/* Define a queue to save up SelectionRequest events for later handling. */
9744
9745struct selection_event_queue
9746 {
9747 XEvent event;
9748 struct selection_event_queue *next;
9749 };
9750
9751static struct selection_event_queue *queue;
9752
9753/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 9754
09756a85
RS
9755static int x_queue_selection_requests;
9756
9757/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 9758
09756a85 9759static void
334208b7
RS
9760x_queue_event (f, event)
9761 FRAME_PTR f;
09756a85
RS
9762 XEvent *event;
9763{
9764 struct selection_event_queue *queue_tmp
06a2c219 9765 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 9766
58769bee 9767 if (queue_tmp != NULL)
09756a85
RS
9768 {
9769 queue_tmp->event = *event;
9770 queue_tmp->next = queue;
9771 queue = queue_tmp;
9772 }
9773}
9774
9775/* Take all the queued events and put them back
9776 so that they get processed afresh. */
9777
9778static void
db3906fd
RS
9779x_unqueue_events (display)
9780 Display *display;
09756a85 9781{
58769bee 9782 while (queue != NULL)
09756a85
RS
9783 {
9784 struct selection_event_queue *queue_tmp = queue;
db3906fd 9785 XPutBackEvent (display, &queue_tmp->event);
09756a85 9786 queue = queue_tmp->next;
06a2c219 9787 xfree ((char *)queue_tmp);
09756a85
RS
9788 }
9789}
9790
9791/* Start queuing SelectionRequest events. */
9792
9793void
db3906fd
RS
9794x_start_queuing_selection_requests (display)
9795 Display *display;
09756a85
RS
9796{
9797 x_queue_selection_requests++;
9798}
9799
9800/* Stop queuing SelectionRequest events. */
9801
9802void
db3906fd
RS
9803x_stop_queuing_selection_requests (display)
9804 Display *display;
09756a85
RS
9805{
9806 x_queue_selection_requests--;
db3906fd 9807 x_unqueue_events (display);
09756a85 9808}
f451eb13
JB
9809\f
9810/* The main X event-reading loop - XTread_socket. */
dc6f92b8 9811
06a2c219 9812/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
9813 but we have to put it out here, since static variables within functions
9814 sometimes don't work. */
06a2c219 9815
dc6f92b8
JB
9816static Time enter_timestamp;
9817
11edeb03 9818/* This holds the state XLookupString needs to implement dead keys
58769bee 9819 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
9820 says that a portable program can't use this, but Stephen Gildea assures
9821 me that letting the compiler initialize it to zeros will work okay.
9822
9823 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
9824 given for enter_time stamp, above. */
9825
11edeb03
JB
9826static XComposeStatus compose_status;
9827
10e6549c
RS
9828/* Record the last 100 characters stored
9829 to help debug the loss-of-chars-during-GC problem. */
06a2c219 9830
2224b905
RS
9831static int temp_index;
9832static short temp_buffer[100];
10e6549c 9833
7a13e894
RS
9834/* Set this to nonzero to fake an "X I/O error"
9835 on a particular display. */
06a2c219 9836
7a13e894
RS
9837struct x_display_info *XTread_socket_fake_io_error;
9838
2224b905
RS
9839/* When we find no input here, we occasionally do a no-op command
9840 to verify that the X server is still running and we can still talk with it.
9841 We try all the open displays, one by one.
9842 This variable is used for cycling thru the displays. */
06a2c219 9843
2224b905
RS
9844static struct x_display_info *next_noop_dpyinfo;
9845
06a2c219
GM
9846#define SET_SAVED_MENU_EVENT(size) \
9847 do \
9848 { \
9849 if (f->output_data.x->saved_menu_event == 0) \
9850 f->output_data.x->saved_menu_event \
9851 = (XEvent *) xmalloc (sizeof (XEvent)); \
9852 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9853 if (numchars >= 1) \
9854 { \
9855 bufp->kind = menu_bar_activate_event; \
9856 XSETFRAME (bufp->frame_or_window, f); \
0f8aabe9 9857 bufp->arg = Qnil; \
06a2c219
GM
9858 bufp++; \
9859 count++; \
9860 numchars--; \
9861 } \
9862 } \
9863 while (0)
9864
8805890a 9865#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 9866#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 9867
dc6f92b8
JB
9868/* Read events coming from the X server.
9869 This routine is called by the SIGIO handler.
9870 We return as soon as there are no more events to be read.
9871
9872 Events representing keys are stored in buffer BUFP,
9873 which can hold up to NUMCHARS characters.
9874 We return the number of characters stored into the buffer,
9875 thus pretending to be `read'.
9876
dc6f92b8
JB
9877 EXPECTED is nonzero if the caller knows input is available. */
9878
7c5283e4 9879int
f66868ba 9880XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 9881 register int sd;
8805890a
KH
9882 /* register */ struct input_event *bufp;
9883 /* register */ int numchars;
dc6f92b8
JB
9884 int expected;
9885{
9886 int count = 0;
9887 int nbytes = 0;
dc6f92b8 9888 XEvent event;
f676886a 9889 struct frame *f;
66f55a9d 9890 int event_found = 0;
334208b7 9891 struct x_display_info *dpyinfo;
379b5ac0 9892 struct coding_system coding;
dc6f92b8 9893
9ac0d9e0 9894 if (interrupt_input_blocked)
dc6f92b8 9895 {
9ac0d9e0 9896 interrupt_input_pending = 1;
dc6f92b8
JB
9897 return -1;
9898 }
9899
9ac0d9e0 9900 interrupt_input_pending = 0;
dc6f92b8 9901 BLOCK_INPUT;
c0a04927
RS
9902
9903 /* So people can tell when we have read the available input. */
9904 input_signal_count++;
9905
dc6f92b8 9906 if (numchars <= 0)
06a2c219 9907 abort (); /* Don't think this happens. */
dc6f92b8 9908
bde5503b
GM
9909 ++handling_signal;
9910
379b5ac0
KH
9911 /* The input should be decoded if it is from XIM. Currently the
9912 locale of XIM is the same as that of the system. So, we can use
9913 Vlocale_coding_system which is initialized properly at Emacs
9914 startup time. */
9915 setup_coding_system (Vlocale_coding_system, &coding);
9916 coding.src_multibyte = 0;
9917 coding.dst_multibyte = 1;
9918 /* The input is converted to events, thus we can't handle
9919 composition. Anyway, there's no XIM that gives us composition
9920 information. */
9921 coding.composing = COMPOSITION_DISABLED;
9922
7a13e894
RS
9923 /* Find the display we are supposed to read input for.
9924 It's the one communicating on descriptor SD. */
9925 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9926 {
9927#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9928#ifdef FIOSNBIO
7a13e894
RS
9929 /* If available, Xlib uses FIOSNBIO to make the socket
9930 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9931 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9932 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9933 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9934#endif /* ! defined (FIOSNBIO) */
7a13e894 9935#endif
dc6f92b8 9936
7a13e894
RS
9937#if 0 /* This code can't be made to work, with multiple displays,
9938 and appears not to be used on any system any more.
9939 Also keyboard.c doesn't turn O_NDELAY on and off
9940 for X connections. */
dc6f92b8
JB
9941#ifndef SIGIO
9942#ifndef HAVE_SELECT
7a13e894
RS
9943 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9944 {
9945 extern int read_alarm_should_throw;
9946 read_alarm_should_throw = 1;
9947 XPeekEvent (dpyinfo->display, &event);
9948 read_alarm_should_throw = 0;
9949 }
c118dd06
JB
9950#endif /* HAVE_SELECT */
9951#endif /* SIGIO */
7a13e894 9952#endif
dc6f92b8 9953
7a13e894
RS
9954 /* For debugging, this gives a way to fake an I/O error. */
9955 if (dpyinfo == XTread_socket_fake_io_error)
9956 {
9957 XTread_socket_fake_io_error = 0;
9958 x_io_error_quitter (dpyinfo->display);
9959 }
dc6f92b8 9960
06a2c219 9961 while (XPending (dpyinfo->display))
dc6f92b8 9962 {
7a13e894 9963 XNextEvent (dpyinfo->display, &event);
06a2c219 9964
531483fb 9965#ifdef HAVE_X_I18N
d1bc4182 9966 {
f2be1146
GM
9967 /* Filter events for the current X input method.
9968 XFilterEvent returns non-zero if the input method has
9969 consumed the event. We pass the frame's X window to
9970 XFilterEvent because that's the one for which the IC
9971 was created. */
f5d11644
GM
9972 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9973 event.xclient.window);
9974 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9975 break;
9976 }
0cd6403b 9977#endif
7a13e894
RS
9978 event_found = 1;
9979
9980 switch (event.type)
9981 {
9982 case ClientMessage:
c047688c 9983 {
7a13e894
RS
9984 if (event.xclient.message_type
9985 == dpyinfo->Xatom_wm_protocols
9986 && event.xclient.format == 32)
c047688c 9987 {
7a13e894
RS
9988 if (event.xclient.data.l[0]
9989 == dpyinfo->Xatom_wm_take_focus)
c047688c 9990 {
8c1a6a84
RS
9991 /* Use x_any_window_to_frame because this
9992 could be the shell widget window
9993 if the frame has no title bar. */
9994 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9995#ifdef HAVE_X_I18N
9996 /* Not quite sure this is needed -pd */
8c1a6a84 9997 if (f && FRAME_XIC (f))
6c183ba5
RS
9998 XSetICFocus (FRAME_XIC (f));
9999#endif
f1da8f06
GM
10000#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
10001 instructs the WM to set the input focus automatically for
10002 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
10003 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
10004 it has set the focus. So, XSetInputFocus below is not
10005 needed.
10006
10007 The call to XSetInputFocus below has also caused trouble. In
10008 cases where the XSetInputFocus done by the WM and the one
10009 below are temporally close (on a fast machine), the call
10010 below can generate additional FocusIn events which confuse
10011 Emacs. */
10012
bf7253f4
RS
10013 /* Since we set WM_TAKE_FOCUS, we must call
10014 XSetInputFocus explicitly. But not if f is null,
10015 since that might be an event for a deleted frame. */
7a13e894 10016 if (f)
bf7253f4
RS
10017 {
10018 Display *d = event.xclient.display;
10019 /* Catch and ignore errors, in case window has been
10020 iconified by a window manager such as GWM. */
10021 int count = x_catch_errors (d);
10022 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
10023 /* The ICCCM says this is
10024 the only valid choice. */
10025 RevertToParent,
bf7253f4
RS
10026 event.xclient.data.l[1]);
10027 /* This is needed to detect the error
10028 if there is an error. */
10029 XSync (d, False);
10030 x_uncatch_errors (d, count);
10031 }
7a13e894 10032 /* Not certain about handling scroll bars here */
f1da8f06 10033#endif /* 0 */
c047688c 10034 }
7a13e894
RS
10035 else if (event.xclient.data.l[0]
10036 == dpyinfo->Xatom_wm_save_yourself)
10037 {
10038 /* Save state modify the WM_COMMAND property to
06a2c219 10039 something which can reinstate us. This notifies
7a13e894
RS
10040 the session manager, who's looking for such a
10041 PropertyNotify. Can restart processing when
06a2c219 10042 a keyboard or mouse event arrives. */
7a13e894
RS
10043 if (numchars > 0)
10044 {
19126e11
KH
10045 f = x_top_window_to_frame (dpyinfo,
10046 event.xclient.window);
7a13e894
RS
10047
10048 /* This is just so we only give real data once
10049 for a single Emacs process. */
b86bd3dd 10050 if (f == SELECTED_FRAME ())
7a13e894
RS
10051 XSetCommand (FRAME_X_DISPLAY (f),
10052 event.xclient.window,
10053 initial_argv, initial_argc);
f000f5c5 10054 else if (f)
7a13e894
RS
10055 XSetCommand (FRAME_X_DISPLAY (f),
10056 event.xclient.window,
10057 0, 0);
10058 }
10059 }
10060 else if (event.xclient.data.l[0]
10061 == dpyinfo->Xatom_wm_delete_window)
1fb20991 10062 {
19126e11
KH
10063 struct frame *f
10064 = x_any_window_to_frame (dpyinfo,
10065 event.xclient.window);
1fb20991 10066
7a13e894
RS
10067 if (f)
10068 {
10069 if (numchars == 0)
10070 abort ();
1fb20991 10071
7a13e894
RS
10072 bufp->kind = delete_window_event;
10073 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10074 bufp->arg = Qnil;
7a13e894
RS
10075 bufp++;
10076
10077 count += 1;
10078 numchars -= 1;
10079 }
1fb20991 10080 }
c047688c 10081 }
7a13e894
RS
10082 else if (event.xclient.message_type
10083 == dpyinfo->Xatom_wm_configure_denied)
10084 {
10085 }
10086 else if (event.xclient.message_type
10087 == dpyinfo->Xatom_wm_window_moved)
10088 {
10089 int new_x, new_y;
19126e11
KH
10090 struct frame *f
10091 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 10092
7a13e894
RS
10093 new_x = event.xclient.data.s[0];
10094 new_y = event.xclient.data.s[1];
1fb20991 10095
7a13e894
RS
10096 if (f)
10097 {
7556890b
RS
10098 f->output_data.x->left_pos = new_x;
10099 f->output_data.x->top_pos = new_y;
7a13e894 10100 }
1fb20991 10101 }
0fdff6bb 10102#ifdef HACK_EDITRES
7a13e894
RS
10103 else if (event.xclient.message_type
10104 == dpyinfo->Xatom_editres)
10105 {
19126e11
KH
10106 struct frame *f
10107 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 10108 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 10109 &event, NULL);
7a13e894 10110 }
0fdff6bb 10111#endif /* HACK_EDITRES */
06a2c219
GM
10112 else if ((event.xclient.message_type
10113 == dpyinfo->Xatom_DONE)
10114 || (event.xclient.message_type
10115 == dpyinfo->Xatom_PAGE))
10116 {
10117 /* Ghostview job completed. Kill it. We could
10118 reply with "Next" if we received "Page", but we
10119 currently never do because we are interested in
10120 images, only, which should have 1 page. */
06a2c219
GM
10121 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
10122 struct frame *f
10123 = x_window_to_frame (dpyinfo, event.xclient.window);
10124 x_kill_gs_process (pixmap, f);
10125 expose_frame (f, 0, 0, 0, 0);
10126 }
10127#ifdef USE_TOOLKIT_SCROLL_BARS
10128 /* Scroll bar callbacks send a ClientMessage from which
10129 we construct an input_event. */
10130 else if (event.xclient.message_type
10131 == dpyinfo->Xatom_Scrollbar)
10132 {
10133 x_scroll_bar_to_input_event (&event, bufp);
10134 ++bufp, ++count, --numchars;
10135 goto out;
10136 }
10137#endif /* USE_TOOLKIT_SCROLL_BARS */
10138 else
10139 goto OTHER;
7a13e894
RS
10140 }
10141 break;
dc6f92b8 10142
7a13e894 10143 case SelectionNotify:
3afe33e7 10144#ifdef USE_X_TOOLKIT
19126e11 10145 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 10146 goto OTHER;
3afe33e7 10147#endif /* not USE_X_TOOLKIT */
dfcf069d 10148 x_handle_selection_notify (&event.xselection);
7a13e894 10149 break;
d56a553a 10150
06a2c219 10151 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 10152#ifdef USE_X_TOOLKIT
19126e11 10153 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 10154 goto OTHER;
3afe33e7 10155#endif /* USE_X_TOOLKIT */
7a13e894
RS
10156 {
10157 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 10158
7a13e894
RS
10159 if (numchars == 0)
10160 abort ();
d56a553a 10161
7a13e894
RS
10162 bufp->kind = selection_clear_event;
10163 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10164 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10165 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 10166 bufp->frame_or_window = Qnil;
0f8aabe9 10167 bufp->arg = Qnil;
7a13e894 10168 bufp++;
d56a553a 10169
7a13e894
RS
10170 count += 1;
10171 numchars -= 1;
10172 }
10173 break;
dc6f92b8 10174
06a2c219 10175 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 10176#ifdef USE_X_TOOLKIT
19126e11 10177 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 10178 goto OTHER;
3afe33e7 10179#endif /* USE_X_TOOLKIT */
7a13e894 10180 if (x_queue_selection_requests)
19126e11 10181 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
10182 &event);
10183 else
10184 {
1d2b2268
GM
10185 XSelectionRequestEvent *eventp
10186 = (XSelectionRequestEvent *) &event;
dc6f92b8 10187
7a13e894
RS
10188 if (numchars == 0)
10189 abort ();
10190
10191 bufp->kind = selection_request_event;
10192 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
10193 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
10194 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
10195 SELECTION_EVENT_TARGET (bufp) = eventp->target;
10196 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
10197 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 10198 bufp->frame_or_window = Qnil;
0f8aabe9 10199 bufp->arg = Qnil;
7a13e894
RS
10200 bufp++;
10201
10202 count += 1;
10203 numchars -= 1;
10204 }
10205 break;
10206
10207 case PropertyNotify:
1d2b2268
GM
10208#if 0 /* This is plain wrong. In the case that we are waiting for a
10209 PropertyNotify used as an ACK in incremental selection
10210 transfer, the property will be on the receiver's window. */
10211#if defined USE_X_TOOLKIT
19126e11 10212 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 10213 goto OTHER;
1d2b2268
GM
10214#endif
10215#endif
dfcf069d 10216 x_handle_property_notify (&event.xproperty);
1d2b2268 10217 goto OTHER;
dc6f92b8 10218
7a13e894 10219 case ReparentNotify:
19126e11 10220 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
10221 if (f)
10222 {
10223 int x, y;
7556890b 10224 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 10225 x_real_positions (f, &x, &y);
7556890b
RS
10226 f->output_data.x->left_pos = x;
10227 f->output_data.x->top_pos = y;
7a13e894
RS
10228 }
10229 break;
3bd330d4 10230
7a13e894 10231 case Expose:
19126e11 10232 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 10233 if (f)
dc6f92b8 10234 {
7a13e894
RS
10235 if (f->async_visible == 0)
10236 {
10237 f->async_visible = 1;
10238 f->async_iconified = 0;
06c488fd 10239 f->output_data.x->has_been_visible = 1;
7a13e894
RS
10240 SET_FRAME_GARBAGED (f);
10241 }
10242 else
06a2c219
GM
10243 expose_frame (x_window_to_frame (dpyinfo,
10244 event.xexpose.window),
10245 event.xexpose.x, event.xexpose.y,
10246 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
10247 }
10248 else
7a13e894 10249 {
12949a7f
EZ
10250#ifndef USE_TOOLKIT_SCROLL_BARS
10251 struct scroll_bar *bar;
10252#endif
01f67d2c 10253#if defined USE_LUCID
c95fc5f1
GM
10254 /* Submenus of the Lucid menu bar aren't widgets
10255 themselves, so there's no way to dispatch events
10256 to them. Recognize this case separately. */
10257 {
10258 Widget widget
10259 = x_window_to_menu_bar (event.xexpose.window);
10260 if (widget)
10261 xlwmenu_redisplay (widget);
10262 }
01f67d2c
PJ
10263#endif /* USE_LUCID */
10264
06a2c219
GM
10265#ifdef USE_TOOLKIT_SCROLL_BARS
10266 /* Dispatch event to the widget. */
10267 goto OTHER;
10268#else /* not USE_TOOLKIT_SCROLL_BARS */
12949a7f 10269 bar = x_window_to_scroll_bar (event.xexpose.window);
58769bee 10270
7a13e894
RS
10271 if (bar)
10272 x_scroll_bar_expose (bar, &event);
3afe33e7 10273#ifdef USE_X_TOOLKIT
7a13e894
RS
10274 else
10275 goto OTHER;
3afe33e7 10276#endif /* USE_X_TOOLKIT */
06a2c219 10277#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10278 }
10279 break;
dc6f92b8 10280
7a13e894 10281 case GraphicsExpose: /* This occurs when an XCopyArea's
d624284c
PJ
10282 source area was obscured or not
10283 available. */
19126e11 10284 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
10285 if (f)
10286 {
06a2c219
GM
10287 expose_frame (f,
10288 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
10289 event.xgraphicsexpose.width,
10290 event.xgraphicsexpose.height);
7a13e894 10291 }
3afe33e7 10292#ifdef USE_X_TOOLKIT
7a13e894
RS
10293 else
10294 goto OTHER;
3afe33e7 10295#endif /* USE_X_TOOLKIT */
7a13e894 10296 break;
dc6f92b8 10297
7a13e894 10298 case NoExpose: /* This occurs when an XCopyArea's
06a2c219 10299 source area was completely
d624284c 10300 available. */
7a13e894 10301 break;
dc6f92b8 10302
7a13e894 10303 case UnmapNotify:
06a2c219
GM
10304 /* Redo the mouse-highlight after the tooltip has gone. */
10305 if (event.xmap.window == tip_window)
10306 {
10307 tip_window = 0;
10308 redo_mouse_highlight ();
10309 }
10310
91ea2a7a 10311 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894 10312 if (f) /* F may no longer exist if
d624284c 10313 the frame was deleted. */
7a13e894
RS
10314 {
10315 /* While a frame is unmapped, display generation is
10316 disabled; you don't want to spend time updating a
10317 display that won't ever be seen. */
10318 f->async_visible = 0;
10319 /* We can't distinguish, from the event, whether the window
10320 has become iconified or invisible. So assume, if it
10321 was previously visible, than now it is iconified.
1aa6072f
RS
10322 But x_make_frame_invisible clears both
10323 the visible flag and the iconified flag;
10324 and that way, we know the window is not iconified now. */
7a13e894 10325 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
10326 {
10327 f->async_iconified = 1;
bddd097c 10328
1aa6072f
RS
10329 bufp->kind = iconify_event;
10330 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10331 bufp->arg = Qnil;
1aa6072f
RS
10332 bufp++;
10333 count++;
10334 numchars--;
10335 }
7a13e894 10336 }
7a13e894 10337 goto OTHER;
dc6f92b8 10338
7a13e894 10339 case MapNotify:
06a2c219
GM
10340 if (event.xmap.window == tip_window)
10341 /* The tooltip has been drawn already. Avoid
10342 the SET_FRAME_GARBAGED below. */
10343 goto OTHER;
10344
10345 /* We use x_top_window_to_frame because map events can
10346 come for sub-windows and they don't mean that the
10347 frame is visible. */
19126e11 10348 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
10349 if (f)
10350 {
10351 f->async_visible = 1;
10352 f->async_iconified = 0;
06c488fd 10353 f->output_data.x->has_been_visible = 1;
dc6f92b8 10354
7a13e894
RS
10355 /* wait_reading_process_input will notice this and update
10356 the frame's display structures. */
10357 SET_FRAME_GARBAGED (f);
bddd097c 10358
d806e720
RS
10359 if (f->iconified)
10360 {
10361 bufp->kind = deiconify_event;
10362 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10363 bufp->arg = Qnil;
d806e720
RS
10364 bufp++;
10365 count++;
10366 numchars--;
10367 }
e73ec6fa 10368 else if (! NILP (Vframe_list)
8e713be6 10369 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
10370 /* Force a redisplay sooner or later
10371 to update the frame titles
10372 in case this is the second frame. */
10373 record_asynch_buffer_change ();
7a13e894 10374 }
7a13e894 10375 goto OTHER;
dc6f92b8 10376
7a13e894 10377 case KeyPress:
19126e11 10378 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 10379
eccc05db 10380#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
10381 if (f == 0)
10382 {
2564ea1b
GM
10383 /* Scroll bars consume key events, but we want
10384 the keys to go to the scroll bar's frame. */
06a2c219
GM
10385 Widget widget = XtWindowToWidget (dpyinfo->display,
10386 event.xkey.window);
10387 if (widget && XmIsScrollBar (widget))
10388 {
10389 widget = XtParent (widget);
10390 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
10391 }
10392 }
eccc05db 10393#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
06a2c219 10394
7a13e894
RS
10395 if (f != 0)
10396 {
10397 KeySym keysym, orig_keysym;
379b5ac0
KH
10398 /* al%imercury@uunet.uu.net says that making this 81
10399 instead of 80 fixed a bug whereby meta chars made
10400 his Emacs hang.
10401
10402 It seems that some version of XmbLookupString has
10403 a bug of not returning XBufferOverflow in
10404 status_return even if the input is too long to
10405 fit in 81 bytes. So, we must prepare sufficient
10406 bytes for copy_buffer. 513 bytes (256 chars for
10407 two-byte character set) seems to be a faily good
10408 approximation. -- 2000.8.10 handa@etl.go.jp */
10409 unsigned char copy_buffer[513];
10410 unsigned char *copy_bufptr = copy_buffer;
10411 int copy_bufsiz = sizeof (copy_buffer);
7a13e894 10412 int modifiers;
64bb1782 10413
7a13e894
RS
10414 event.xkey.state
10415 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
10416 extra_keyboard_modifiers);
10417 modifiers = event.xkey.state;
3a2712f9 10418
7a13e894 10419 /* This will have to go some day... */
752a043f 10420
7a13e894
RS
10421 /* make_lispy_event turns chars into control chars.
10422 Don't do it here because XLookupString is too eager. */
10423 event.xkey.state &= ~ControlMask;
5d46f928
RS
10424 event.xkey.state &= ~(dpyinfo->meta_mod_mask
10425 | dpyinfo->super_mod_mask
10426 | dpyinfo->hyper_mod_mask
10427 | dpyinfo->alt_mod_mask);
10428
1cf4a0d1
RS
10429 /* In case Meta is ComposeCharacter,
10430 clear its status. According to Markus Ehrnsperger
10431 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
10432 this enables ComposeCharacter to work whether or
10433 not it is combined with Meta. */
10434 if (modifiers & dpyinfo->meta_mod_mask)
10435 bzero (&compose_status, sizeof (compose_status));
10436
6c183ba5
RS
10437#ifdef HAVE_X_I18N
10438 if (FRAME_XIC (f))
10439 {
f5d11644
GM
10440 Status status_return;
10441
6c183ba5 10442 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
10443 &event.xkey, copy_bufptr,
10444 copy_bufsiz, &keysym,
6c183ba5 10445 &status_return);
f5d11644
GM
10446 if (status_return == XBufferOverflow)
10447 {
10448 copy_bufsiz = nbytes + 1;
10449 copy_bufptr = (char *) alloca (copy_bufsiz);
10450 nbytes = XmbLookupString (FRAME_XIC (f),
10451 &event.xkey, copy_bufptr,
10452 copy_bufsiz, &keysym,
10453 &status_return);
10454 }
10455
1decb680
PE
10456 if (status_return == XLookupNone)
10457 break;
10458 else if (status_return == XLookupChars)
fdd9d55e
GM
10459 {
10460 keysym = NoSymbol;
10461 modifiers = 0;
10462 }
1decb680
PE
10463 else if (status_return != XLookupKeySym
10464 && status_return != XLookupBoth)
10465 abort ();
6c183ba5
RS
10466 }
10467 else
379b5ac0
KH
10468 nbytes = XLookupString (&event.xkey, copy_bufptr,
10469 copy_bufsiz, &keysym,
10470 &compose_status);
6c183ba5 10471#else
379b5ac0
KH
10472 nbytes = XLookupString (&event.xkey, copy_bufptr,
10473 copy_bufsiz, &keysym,
10474 &compose_status);
6c183ba5 10475#endif
dc6f92b8 10476
7a13e894 10477 orig_keysym = keysym;
55123275 10478
7a13e894
RS
10479 if (numchars > 1)
10480 {
10481 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10482 || keysym == XK_Delete
1097aea0 10483#ifdef XK_ISO_Left_Tab
441affdb 10484 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 10485#endif
852bff8f 10486 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
10487 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10488 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 10489#ifdef HPUX
7a13e894
RS
10490 /* This recognizes the "extended function keys".
10491 It seems there's no cleaner way.
10492 Test IsModifierKey to avoid handling mode_switch
10493 incorrectly. */
10494 || ((unsigned) (keysym) >= XK_Select
10495 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
10496#endif
10497#ifdef XK_dead_circumflex
7a13e894 10498 || orig_keysym == XK_dead_circumflex
69388238
RS
10499#endif
10500#ifdef XK_dead_grave
7a13e894 10501 || orig_keysym == XK_dead_grave
69388238
RS
10502#endif
10503#ifdef XK_dead_tilde
7a13e894 10504 || orig_keysym == XK_dead_tilde
69388238
RS
10505#endif
10506#ifdef XK_dead_diaeresis
7a13e894 10507 || orig_keysym == XK_dead_diaeresis
69388238
RS
10508#endif
10509#ifdef XK_dead_macron
7a13e894 10510 || orig_keysym == XK_dead_macron
69388238
RS
10511#endif
10512#ifdef XK_dead_degree
7a13e894 10513 || orig_keysym == XK_dead_degree
69388238
RS
10514#endif
10515#ifdef XK_dead_acute
7a13e894 10516 || orig_keysym == XK_dead_acute
69388238
RS
10517#endif
10518#ifdef XK_dead_cedilla
7a13e894 10519 || orig_keysym == XK_dead_cedilla
69388238
RS
10520#endif
10521#ifdef XK_dead_breve
7a13e894 10522 || orig_keysym == XK_dead_breve
69388238
RS
10523#endif
10524#ifdef XK_dead_ogonek
7a13e894 10525 || orig_keysym == XK_dead_ogonek
69388238
RS
10526#endif
10527#ifdef XK_dead_caron
7a13e894 10528 || orig_keysym == XK_dead_caron
69388238
RS
10529#endif
10530#ifdef XK_dead_doubleacute
7a13e894 10531 || orig_keysym == XK_dead_doubleacute
69388238
RS
10532#endif
10533#ifdef XK_dead_abovedot
7a13e894 10534 || orig_keysym == XK_dead_abovedot
c34790e0 10535#endif
7a13e894
RS
10536 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10537 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10538 /* Any "vendor-specific" key is ok. */
f0e299de
GM
10539 || (orig_keysym & (1 << 28))
10540 || (keysym != NoSymbol && nbytes == 0))
7a13e894 10541 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
10542#ifndef HAVE_X11R5
10543#ifdef XK_Mode_switch
7a13e894 10544 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
10545#endif
10546#ifdef XK_Num_Lock
7a13e894 10547 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
10548#endif
10549#endif /* not HAVE_X11R5 */
7a13e894 10550 ))
dc6f92b8 10551 {
10e6549c
RS
10552 if (temp_index == sizeof temp_buffer / sizeof (short))
10553 temp_index = 0;
7a13e894
RS
10554 temp_buffer[temp_index++] = keysym;
10555 bufp->kind = non_ascii_keystroke;
10556 bufp->code = keysym;
e0c1aef2 10557 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10558 bufp->arg = Qnil;
334208b7
RS
10559 bufp->modifiers
10560 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10561 modifiers);
1113d9db 10562 bufp->timestamp = event.xkey.time;
dc6f92b8 10563 bufp++;
7a13e894
RS
10564 count++;
10565 numchars--;
dc6f92b8 10566 }
7a13e894
RS
10567 else if (numchars > nbytes)
10568 {
10569 register int i;
379b5ac0 10570 register int c;
379b5ac0 10571 int nchars, len;
7a13e894
RS
10572
10573 for (i = 0; i < nbytes; i++)
10574 {
379b5ac0
KH
10575 if (temp_index == (sizeof temp_buffer
10576 / sizeof (short)))
7a13e894 10577 temp_index = 0;
379b5ac0
KH
10578 temp_buffer[temp_index++] = copy_bufptr[i];
10579 }
10580
10581 if (/* If the event is not from XIM, */
10582 event.xkey.keycode != 0
10583 /* or the current locale doesn't request
10584 decoding of the intup data, ... */
10585 || coding.type == coding_type_raw_text
10586 || coding.type == coding_type_no_conversion)
10587 {
10588 /* ... we can use the input data as is. */
10589 nchars = nbytes;
10590 }
10591 else
10592 {
10593 /* We have to decode the input data. */
10594 int require;
10595 unsigned char *p;
10596
10597 require = decoding_buffer_size (&coding, nbytes);
10598 p = (unsigned char *) alloca (require);
10599 coding.mode |= CODING_MODE_LAST_BLOCK;
10600 decode_coding (&coding, copy_bufptr, p,
10601 nbytes, require);
10602 nbytes = coding.produced;
10603 nchars = coding.produced_char;
10604 copy_bufptr = p;
10605 }
10606
10607 /* Convert the input data to a sequence of
10608 character events. */
10609 for (i = 0; i < nbytes; i += len)
10610 {
10611 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10612 nbytes - i, len);
10613 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10614 ? ascii_keystroke
10615 : multibyte_char_keystroke);
10616 bufp->code = c;
7a13e894 10617 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10618 bufp->arg = Qnil;
7a13e894
RS
10619 bufp->modifiers
10620 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10621 modifiers);
10622 bufp->timestamp = event.xkey.time;
10623 bufp++;
10624 }
10625
379b5ac0
KH
10626 count += nchars;
10627 numchars -= nchars;
1decb680
PE
10628
10629 if (keysym == NoSymbol)
10630 break;
7a13e894
RS
10631 }
10632 else
10633 abort ();
dc6f92b8 10634 }
10e6549c
RS
10635 else
10636 abort ();
dc6f92b8 10637 }
59ddecde
GM
10638#ifdef HAVE_X_I18N
10639 /* Don't dispatch this event since XtDispatchEvent calls
10640 XFilterEvent, and two calls in a row may freeze the
10641 client. */
10642 break;
10643#else
717ca130 10644 goto OTHER;
59ddecde 10645#endif
f451eb13 10646
f5d11644 10647 case KeyRelease:
59ddecde
GM
10648#ifdef HAVE_X_I18N
10649 /* Don't dispatch this event since XtDispatchEvent calls
10650 XFilterEvent, and two calls in a row may freeze the
10651 client. */
10652 break;
10653#else
f5d11644 10654 goto OTHER;
59ddecde 10655#endif
f5d11644 10656
7a13e894 10657 /* Here's a possible interpretation of the whole
06a2c219
GM
10658 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10659 you get a FocusIn event, you have to get a FocusOut
10660 event before you relinquish the focus. If you
10661 haven't received a FocusIn event, then a mere
10662 LeaveNotify is enough to free you. */
f451eb13 10663
7a13e894 10664 case EnterNotify:
06a2c219 10665 {
06a2c219
GM
10666 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10667
582c60f8 10668 if (event.xcrossing.focus)
06a2c219
GM
10669 {
10670 /* Avoid nasty pop/raise loops. */
10671 if (f && (!(f->auto_raise)
10672 || !(f->auto_lower)
10673 || (event.xcrossing.time - enter_timestamp) > 500))
10674 {
10675 x_new_focus_frame (dpyinfo, f);
10676 enter_timestamp = event.xcrossing.time;
10677 }
10678 }
10679 else if (f == dpyinfo->x_focus_frame)
10680 x_new_focus_frame (dpyinfo, 0);
10681
10682 /* EnterNotify counts as mouse movement,
10683 so update things that depend on mouse position. */
2533c408 10684 if (f && !f->output_data.x->hourglass_p)
06a2c219
GM
10685 note_mouse_movement (f, &event.xmotion);
10686 goto OTHER;
10687 }
dc6f92b8 10688
7a13e894 10689 case FocusIn:
19126e11 10690 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10691 if (event.xfocus.detail != NotifyPointer)
0f941935 10692 dpyinfo->x_focus_event_frame = f;
7a13e894 10693 if (f)
eb72635f
GM
10694 {
10695 x_new_focus_frame (dpyinfo, f);
10696
10697 /* Don't stop displaying the initial startup message
10698 for a switch-frame event we don't need. */
10699 if (GC_NILP (Vterminal_frame)
10700 && GC_CONSP (Vframe_list)
10701 && !GC_NILP (XCDR (Vframe_list)))
10702 {
10703 bufp->kind = FOCUS_IN_EVENT;
10704 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10705 bufp->arg = Qnil;
eb72635f
GM
10706 ++bufp, ++count, --numchars;
10707 }
10708 }
f9e24cb9 10709
6c183ba5
RS
10710#ifdef HAVE_X_I18N
10711 if (f && FRAME_XIC (f))
10712 XSetICFocus (FRAME_XIC (f));
10713#endif
10714
7a13e894 10715 goto OTHER;
10c5e63d 10716
7a13e894 10717 case LeaveNotify:
19126e11 10718 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 10719 if (f)
10c5e63d 10720 {
7a13e894 10721 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
10722 {
10723 /* If we move outside the frame, then we're
10724 certainly no longer on any text in the frame. */
10725 clear_mouse_face (dpyinfo);
10726 dpyinfo->mouse_face_mouse_frame = 0;
10727 }
10728
10729 /* Generate a nil HELP_EVENT to cancel a help-echo.
10730 Do it only if there's something to cancel.
10731 Otherwise, the startup message is cleared when
10732 the mouse leaves the frame. */
10733 if (any_help_event_p)
10734 {
be010514
GM
10735 Lisp_Object frame;
10736 int n;
10737
06a2c219 10738 XSETFRAME (frame, f);
82c5d67a 10739 help_echo = Qnil;
5ab2570d
GM
10740 n = gen_help_event (bufp, numchars,
10741 Qnil, frame, Qnil, Qnil, 0);
be010514 10742 bufp += n, count += n, numchars -= n;
06a2c219 10743 }
7a13e894 10744
582c60f8 10745 if (event.xcrossing.focus)
0f941935 10746 x_mouse_leave (dpyinfo);
10c5e63d 10747 else
7a13e894 10748 {
0f941935
KH
10749 if (f == dpyinfo->x_focus_event_frame)
10750 dpyinfo->x_focus_event_frame = 0;
10751 if (f == dpyinfo->x_focus_frame)
10752 x_new_focus_frame (dpyinfo, 0);
7a13e894 10753 }
10c5e63d 10754 }
7a13e894 10755 goto OTHER;
dc6f92b8 10756
7a13e894 10757 case FocusOut:
19126e11 10758 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10759 if (event.xfocus.detail != NotifyPointer
0f941935
KH
10760 && f == dpyinfo->x_focus_event_frame)
10761 dpyinfo->x_focus_event_frame = 0;
10762 if (f && f == dpyinfo->x_focus_frame)
10763 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 10764
6c183ba5
RS
10765#ifdef HAVE_X_I18N
10766 if (f && FRAME_XIC (f))
10767 XUnsetICFocus (FRAME_XIC (f));
10768#endif
10769
7a13e894 10770 goto OTHER;
dc6f92b8 10771
7a13e894 10772 case MotionNotify:
dc6f92b8 10773 {
06a2c219 10774 previous_help_echo = help_echo;
7cea38bc 10775 help_echo = help_echo_object = help_echo_window = Qnil;
be010514 10776 help_echo_pos = -1;
06a2c219 10777
7a13e894
RS
10778 if (dpyinfo->grabbed && last_mouse_frame
10779 && FRAME_LIVE_P (last_mouse_frame))
10780 f = last_mouse_frame;
10781 else
19126e11 10782 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 10783
7a13e894
RS
10784 if (f)
10785 note_mouse_movement (f, &event.xmotion);
10786 else
10787 {
e88b3c50 10788#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10789 struct scroll_bar *bar
10790 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 10791
7a13e894
RS
10792 if (bar)
10793 x_scroll_bar_note_movement (bar, &event);
e88b3c50 10794#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 10795
06a2c219
GM
10796 /* If we move outside the frame, then we're
10797 certainly no longer on any text in the frame. */
7a13e894
RS
10798 clear_mouse_face (dpyinfo);
10799 }
06a2c219
GM
10800
10801 /* If the contents of the global variable help_echo
10802 has changed, generate a HELP_EVENT. */
b7e80413
SM
10803 if (!NILP (help_echo)
10804 || !NILP (previous_help_echo))
06a2c219
GM
10805 {
10806 Lisp_Object frame;
be010514 10807 int n;
06a2c219
GM
10808
10809 if (f)
10810 XSETFRAME (frame, f);
10811 else
10812 frame = Qnil;
10813
10814 any_help_event_p = 1;
5ab2570d 10815 n = gen_help_event (bufp, numchars, help_echo, frame,
7cea38bc
GM
10816 help_echo_window, help_echo_object,
10817 help_echo_pos);
be010514 10818 bufp += n, count += n, numchars -= n;
06a2c219
GM
10819 }
10820
10821 goto OTHER;
dc6f92b8 10822 }
dc6f92b8 10823
7a13e894 10824 case ConfigureNotify:
9829ddba
RS
10825 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10826 if (f)
af395ec1 10827 {
5c187dee 10828#ifndef USE_X_TOOLKIT
bf1b7b30
KH
10829 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10830 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 10831
2d7fc7e8
RS
10832 /* In the toolkit version, change_frame_size
10833 is called by the code that handles resizing
10834 of the EmacsFrame widget. */
7a13e894 10835
7a13e894
RS
10836 /* Even if the number of character rows and columns has
10837 not changed, the font size may have changed, so we need
10838 to check the pixel dimensions as well. */
10839 if (columns != f->width
10840 || rows != f->height
7556890b
RS
10841 || event.xconfigure.width != f->output_data.x->pixel_width
10842 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 10843 {
7d1e984f 10844 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 10845 SET_FRAME_GARBAGED (f);
e687d06e 10846 cancel_mouse_face (f);
7a13e894 10847 }
2d7fc7e8 10848#endif
af395ec1 10849
7556890b
RS
10850 f->output_data.x->pixel_width = event.xconfigure.width;
10851 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
10852
10853 /* What we have now is the position of Emacs's own window.
10854 Convert that to the position of the window manager window. */
dcb07ae9
RS
10855 x_real_positions (f, &f->output_data.x->left_pos,
10856 &f->output_data.x->top_pos);
10857
f5d11644
GM
10858#ifdef HAVE_X_I18N
10859 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10860 xic_set_statusarea (f);
10861#endif
10862
dcb07ae9
RS
10863 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10864 {
10865 /* Since the WM decorations come below top_pos now,
10866 we must put them below top_pos in the future. */
10867 f->output_data.x->win_gravity = NorthWestGravity;
10868 x_wm_set_size_hint (f, (long) 0, 0);
10869 }
8f08dc93
KH
10870#ifdef USE_MOTIF
10871 /* Some window managers pass (0,0) as the location of
10872 the window, and the Motif event handler stores it
10873 in the emacs widget, which messes up Motif menus. */
10874 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10875 {
10876 event.xconfigure.x = f->output_data.x->widget->core.x;
10877 event.xconfigure.y = f->output_data.x->widget->core.y;
10878 }
06a2c219 10879#endif /* USE_MOTIF */
7a13e894 10880 }
2d7fc7e8 10881 goto OTHER;
dc6f92b8 10882
7a13e894
RS
10883 case ButtonPress:
10884 case ButtonRelease:
10885 {
10886 /* If we decide we want to generate an event to be seen
10887 by the rest of Emacs, we put it here. */
10888 struct input_event emacs_event;
9ea173e8 10889 int tool_bar_p = 0;
06a2c219 10890
7a13e894 10891 emacs_event.kind = no_event;
7a13e894 10892 bzero (&compose_status, sizeof (compose_status));
9b07615b 10893
06a2c219
GM
10894 if (dpyinfo->grabbed
10895 && last_mouse_frame
9f67f20b
RS
10896 && FRAME_LIVE_P (last_mouse_frame))
10897 f = last_mouse_frame;
10898 else
2224b905 10899 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 10900
06a2c219
GM
10901 if (f)
10902 {
9ea173e8
GM
10903 /* Is this in the tool-bar? */
10904 if (WINDOWP (f->tool_bar_window)
10905 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
10906 {
10907 Lisp_Object window;
10908 int p, x, y;
10909
10910 x = event.xbutton.x;
10911 y = event.xbutton.y;
10912
10913 /* Set x and y. */
10914 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 10915 if (EQ (window, f->tool_bar_window))
06a2c219 10916 {
9ea173e8
GM
10917 x_handle_tool_bar_click (f, &event.xbutton);
10918 tool_bar_p = 1;
06a2c219
GM
10919 }
10920 }
10921
9ea173e8 10922 if (!tool_bar_p)
06a2c219
GM
10923 if (!dpyinfo->x_focus_frame
10924 || f == dpyinfo->x_focus_frame)
10925 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
10926 }
10927 else
10928 {
06a2c219 10929#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10930 struct scroll_bar *bar
10931 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 10932
7a13e894
RS
10933 if (bar)
10934 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 10935#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10936 }
10937
10938 if (event.type == ButtonPress)
10939 {
10940 dpyinfo->grabbed |= (1 << event.xbutton.button);
10941 last_mouse_frame = f;
edad46f6
KH
10942 /* Ignore any mouse motion that happened
10943 before this event; any subsequent mouse-movement
10944 Emacs events should reflect only motion after
10945 the ButtonPress. */
a00e91cd
KH
10946 if (f != 0)
10947 f->mouse_moved = 0;
06a2c219 10948
9ea173e8
GM
10949 if (!tool_bar_p)
10950 last_tool_bar_item = -1;
7a13e894 10951 }
3afe33e7
RS
10952 else
10953 {
7a13e894 10954 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10955 }
23faf38f 10956
7a13e894
RS
10957 if (numchars >= 1 && emacs_event.kind != no_event)
10958 {
10959 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10960 bufp++;
10961 count++;
10962 numchars--;
10963 }
3afe33e7
RS
10964
10965#ifdef USE_X_TOOLKIT
2224b905
RS
10966 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10967 /* For a down-event in the menu bar,
10968 don't pass it to Xt right now.
10969 Instead, save it away
10970 and we will pass it to Xt from kbd_buffer_get_event.
10971 That way, we can run some Lisp code first. */
91375f8f
RS
10972 if (f && event.type == ButtonPress
10973 /* Verify the event is really within the menu bar
10974 and not just sent to it due to grabbing. */
10975 && event.xbutton.x >= 0
10976 && event.xbutton.x < f->output_data.x->pixel_width
10977 && event.xbutton.y >= 0
10978 && event.xbutton.y < f->output_data.x->menubar_height
10979 && event.xbutton.same_screen)
2224b905 10980 {
8805890a 10981 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10982 XSETFRAME (last_mouse_press_frame, f);
10983 }
10984 else if (event.type == ButtonPress)
10985 {
10986 last_mouse_press_frame = Qnil;
30e671c3 10987 goto OTHER;
ce89ef46 10988 }
06a2c219 10989
2237cac9
RS
10990#ifdef USE_MOTIF /* This should do not harm for Lucid,
10991 but I am trying to be cautious. */
ce89ef46
RS
10992 else if (event.type == ButtonRelease)
10993 {
2237cac9 10994 if (!NILP (last_mouse_press_frame))
f10ded1c 10995 {
2237cac9
RS
10996 f = XFRAME (last_mouse_press_frame);
10997 if (f->output_data.x)
06a2c219 10998 SET_SAVED_BUTTON_EVENT;
f10ded1c 10999 }
06a2c219 11000 else
30e671c3 11001 goto OTHER;
2224b905 11002 }
2237cac9 11003#endif /* USE_MOTIF */
2224b905
RS
11004 else
11005 goto OTHER;
3afe33e7 11006#endif /* USE_X_TOOLKIT */
7a13e894
RS
11007 }
11008 break;
dc6f92b8 11009
7a13e894 11010 case CirculateNotify:
06a2c219
GM
11011 goto OTHER;
11012
7a13e894 11013 case CirculateRequest:
06a2c219
GM
11014 goto OTHER;
11015
11016 case VisibilityNotify:
11017 goto OTHER;
dc6f92b8 11018
7a13e894
RS
11019 case MappingNotify:
11020 /* Someone has changed the keyboard mapping - update the
11021 local cache. */
11022 switch (event.xmapping.request)
11023 {
11024 case MappingModifier:
11025 x_find_modifier_meanings (dpyinfo);
11026 /* This is meant to fall through. */
11027 case MappingKeyboard:
11028 XRefreshKeyboardMapping (&event.xmapping);
11029 }
7a13e894 11030 goto OTHER;
dc6f92b8 11031
7a13e894 11032 default:
7a13e894 11033 OTHER:
717ca130 11034#ifdef USE_X_TOOLKIT
7a13e894
RS
11035 BLOCK_INPUT;
11036 XtDispatchEvent (&event);
11037 UNBLOCK_INPUT;
3afe33e7 11038#endif /* USE_X_TOOLKIT */
7a13e894
RS
11039 break;
11040 }
dc6f92b8
JB
11041 }
11042 }
11043
06a2c219
GM
11044 out:;
11045
9a5196d0
RS
11046 /* On some systems, an X bug causes Emacs to get no more events
11047 when the window is destroyed. Detect that. (1994.) */
58769bee 11048 if (! event_found)
ef2a22d0 11049 {
ef2a22d0
RS
11050 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
11051 One XNOOP in 100 loops will make Emacs terminate.
11052 B. Bretthauer, 1994 */
11053 x_noop_count++;
58769bee 11054 if (x_noop_count >= 100)
ef2a22d0
RS
11055 {
11056 x_noop_count=0;
2224b905
RS
11057
11058 if (next_noop_dpyinfo == 0)
11059 next_noop_dpyinfo = x_display_list;
11060
11061 XNoOp (next_noop_dpyinfo->display);
11062
11063 /* Each time we get here, cycle through the displays now open. */
11064 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
11065 }
11066 }
502add23 11067
06a2c219 11068 /* If the focus was just given to an auto-raising frame,
0134a210 11069 raise it now. */
7a13e894 11070 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
11071 if (pending_autoraise_frame)
11072 {
11073 x_raise_frame (pending_autoraise_frame);
11074 pending_autoraise_frame = 0;
11075 }
0134a210 11076
dc6f92b8 11077 UNBLOCK_INPUT;
bde5503b 11078 --handling_signal;
dc6f92b8
JB
11079 return count;
11080}
06a2c219
GM
11081
11082
11083
dc6f92b8 11084\f
06a2c219
GM
11085/***********************************************************************
11086 Text Cursor
11087 ***********************************************************************/
11088
78a9a4c5 11089/* Notice if the text cursor of window W has been overwritten by a
f0a48a01
GM
11090 drawing operation that outputs N glyphs starting at START_X and
11091 ending at END_X in the line given by output_cursor.vpos.
11092 Coordinates are area-relative. END_X < 0 means means all the rest
11093 of the line after START_X has been written. */
06a2c219
GM
11094
11095static void
f0a48a01 11096notice_overwritten_cursor (w, start_x, end_x)
06a2c219 11097 struct window *w;
f0a48a01 11098 int start_x, end_x;
06a2c219
GM
11099{
11100 if (updated_area == TEXT_AREA
f0a48a01 11101 && w->phys_cursor_on_p
06a2c219 11102 && output_cursor.vpos == w->phys_cursor.vpos
f0a48a01
GM
11103 && start_x <= w->phys_cursor.x
11104 && end_x > w->phys_cursor.x)
11105 w->phys_cursor_on_p = 0;
06a2c219 11106}
f451eb13
JB
11107
11108
06a2c219
GM
11109/* Set clipping for output in glyph row ROW. W is the window in which
11110 we operate. GC is the graphics context to set clipping in.
11111 WHOLE_LINE_P non-zero means include the areas used for truncation
11112 mark display and alike in the clipping rectangle.
11113
11114 ROW may be a text row or, e.g., a mode line. Text rows must be
11115 clipped to the interior of the window dedicated to text display,
11116 mode lines must be clipped to the whole window. */
dc6f92b8
JB
11117
11118static void
06a2c219
GM
11119x_clip_to_row (w, row, gc, whole_line_p)
11120 struct window *w;
11121 struct glyph_row *row;
11122 GC gc;
11123 int whole_line_p;
dc6f92b8 11124{
06a2c219
GM
11125 struct frame *f = XFRAME (WINDOW_FRAME (w));
11126 XRectangle clip_rect;
11127 int window_x, window_y, window_width, window_height;
dc6f92b8 11128
06a2c219 11129 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 11130
06a2c219
GM
11131 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
11132 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
11133 clip_rect.y = max (clip_rect.y, window_y);
11134 clip_rect.width = window_width;
11135 clip_rect.height = row->visible_height;
5c1aae96 11136
06a2c219
GM
11137 /* If clipping to the whole line, including trunc marks, extend
11138 the rectangle to the left and increase its width. */
11139 if (whole_line_p)
11140 {
110859fc
GM
11141 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
11142 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 11143 }
5c1aae96 11144
06a2c219 11145 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
11146}
11147
06a2c219
GM
11148
11149/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
11150
11151static void
06a2c219
GM
11152x_draw_hollow_cursor (w, row)
11153 struct window *w;
11154 struct glyph_row *row;
dc6f92b8 11155{
06a2c219
GM
11156 struct frame *f = XFRAME (WINDOW_FRAME (w));
11157 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11158 Display *dpy = FRAME_X_DISPLAY (f);
11159 int x, y, wd, h;
11160 XGCValues xgcv;
11161 struct glyph *cursor_glyph;
11162 GC gc;
11163
11164 /* Compute frame-relative coordinates from window-relative
11165 coordinates. */
11166 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11167 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
11168 + row->ascent - w->phys_cursor_ascent);
11169 h = row->height - 1;
11170
11171 /* Get the glyph the cursor is on. If we can't tell because
11172 the current matrix is invalid or such, give up. */
11173 cursor_glyph = get_phys_cursor_glyph (w);
11174 if (cursor_glyph == NULL)
dc6f92b8
JB
11175 return;
11176
06a2c219
GM
11177 /* Compute the width of the rectangle to draw. If on a stretch
11178 glyph, and `x-stretch-block-cursor' is nil, don't draw a
11179 rectangle as wide as the glyph, but use a canonical character
11180 width instead. */
11181 wd = cursor_glyph->pixel_width - 1;
11182 if (cursor_glyph->type == STRETCH_GLYPH
11183 && !x_stretch_cursor_p)
11184 wd = min (CANON_X_UNIT (f), wd);
11185
11186 /* The foreground of cursor_gc is typically the same as the normal
11187 background color, which can cause the cursor box to be invisible. */
11188 xgcv.foreground = f->output_data.x->cursor_pixel;
11189 if (dpyinfo->scratch_cursor_gc)
11190 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
11191 else
11192 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
11193 GCForeground, &xgcv);
11194 gc = dpyinfo->scratch_cursor_gc;
11195
11196 /* Set clipping, draw the rectangle, and reset clipping again. */
11197 x_clip_to_row (w, row, gc, 0);
11198 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
11199 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
11200}
11201
06a2c219
GM
11202
11203/* Draw a bar cursor on window W in glyph row ROW.
11204
11205 Implementation note: One would like to draw a bar cursor with an
11206 angle equal to the one given by the font property XA_ITALIC_ANGLE.
11207 Unfortunately, I didn't find a font yet that has this property set.
11208 --gerd. */
dc6f92b8
JB
11209
11210static void
f02d8aa0 11211x_draw_bar_cursor (w, row, width)
06a2c219
GM
11212 struct window *w;
11213 struct glyph_row *row;
f02d8aa0 11214 int width;
dc6f92b8 11215{
92f424df
GM
11216 struct frame *f = XFRAME (w->frame);
11217 struct glyph *cursor_glyph;
11218 GC gc;
11219 int x;
11220 unsigned long mask;
11221 XGCValues xgcv;
11222 Display *dpy;
11223 Window window;
06a2c219 11224
92f424df
GM
11225 /* If cursor is out of bounds, don't draw garbage. This can happen
11226 in mini-buffer windows when switching between echo area glyphs
11227 and mini-buffer. */
11228 cursor_glyph = get_phys_cursor_glyph (w);
11229 if (cursor_glyph == NULL)
11230 return;
06a2c219 11231
92f424df
GM
11232 /* If on an image, draw like a normal cursor. That's usually better
11233 visible than drawing a bar, esp. if the image is large so that
11234 the bar might not be in the window. */
11235 if (cursor_glyph->type == IMAGE_GLYPH)
11236 {
11237 struct glyph_row *row;
11238 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
11239 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
11240 }
11241 else
11242 {
06a2c219
GM
11243 xgcv.background = f->output_data.x->cursor_pixel;
11244 xgcv.foreground = f->output_data.x->cursor_pixel;
11245 xgcv.graphics_exposures = 0;
11246 mask = GCForeground | GCBackground | GCGraphicsExposures;
11247 dpy = FRAME_X_DISPLAY (f);
11248 window = FRAME_X_WINDOW (f);
11249 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
92f424df 11250
06a2c219
GM
11251 if (gc)
11252 XChangeGC (dpy, gc, mask, &xgcv);
11253 else
11254 {
11255 gc = XCreateGC (dpy, window, mask, &xgcv);
11256 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
11257 }
92f424df 11258
f02d8aa0
GM
11259 if (width < 0)
11260 width = f->output_data.x->cursor_width;
92f424df 11261
06a2c219
GM
11262 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
11263 x_clip_to_row (w, row, gc, 0);
11264 XFillRectangle (dpy, window, gc,
11265 x,
11266 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 11267 min (cursor_glyph->pixel_width, width),
06a2c219
GM
11268 row->height);
11269 XSetClipMask (dpy, gc, None);
11270 }
dc6f92b8
JB
11271}
11272
06a2c219
GM
11273
11274/* Clear the cursor of window W to background color, and mark the
11275 cursor as not shown. This is used when the text where the cursor
11276 is is about to be rewritten. */
11277
dc6f92b8 11278static void
06a2c219
GM
11279x_clear_cursor (w)
11280 struct window *w;
dc6f92b8 11281{
06a2c219
GM
11282 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
11283 x_update_window_cursor (w, 0);
11284}
90e65f07 11285
dbc4e1c1 11286
06a2c219
GM
11287/* Draw the cursor glyph of window W in glyph row ROW. See the
11288 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 11289
06a2c219
GM
11290static void
11291x_draw_phys_cursor_glyph (w, row, hl)
11292 struct window *w;
11293 struct glyph_row *row;
11294 enum draw_glyphs_face hl;
11295{
11296 /* If cursor hpos is out of bounds, don't draw garbage. This can
11297 happen in mini-buffer windows when switching between echo area
11298 glyphs and mini-buffer. */
11299 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e 11300 {
f0a48a01
GM
11301 int on_p = w->phys_cursor_on_p;
11302
66ac4b0e
GM
11303 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
11304 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
f0a48a01
GM
11305 hl, 0);
11306 w->phys_cursor_on_p = on_p;
66ac4b0e
GM
11307
11308 /* When we erase the cursor, and ROW is overlapped by other
11309 rows, make sure that these overlapping parts of other rows
11310 are redrawn. */
11311 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
11312 {
11313 if (row > w->current_matrix->rows
11314 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
11315 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
11316
11317 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
11318 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
11319 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
11320 }
11321 }
06a2c219 11322}
dbc4e1c1 11323
eea6af04 11324
06a2c219 11325/* Erase the image of a cursor of window W from the screen. */
eea6af04 11326
06a2c219
GM
11327static void
11328x_erase_phys_cursor (w)
11329 struct window *w;
11330{
11331 struct frame *f = XFRAME (w->frame);
11332 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11333 int hpos = w->phys_cursor.hpos;
11334 int vpos = w->phys_cursor.vpos;
11335 int mouse_face_here_p = 0;
11336 struct glyph_matrix *active_glyphs = w->current_matrix;
11337 struct glyph_row *cursor_row;
11338 struct glyph *cursor_glyph;
11339 enum draw_glyphs_face hl;
11340
11341 /* No cursor displayed or row invalidated => nothing to do on the
11342 screen. */
11343 if (w->phys_cursor_type == NO_CURSOR)
11344 goto mark_cursor_off;
11345
11346 /* VPOS >= active_glyphs->nrows means that window has been resized.
11347 Don't bother to erase the cursor. */
11348 if (vpos >= active_glyphs->nrows)
11349 goto mark_cursor_off;
11350
11351 /* If row containing cursor is marked invalid, there is nothing we
11352 can do. */
11353 cursor_row = MATRIX_ROW (active_glyphs, vpos);
11354 if (!cursor_row->enabled_p)
11355 goto mark_cursor_off;
11356
11357 /* This can happen when the new row is shorter than the old one.
11358 In this case, either x_draw_glyphs or clear_end_of_line
11359 should have cleared the cursor. Note that we wouldn't be
11360 able to erase the cursor in this case because we don't have a
11361 cursor glyph at hand. */
11362 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
11363 goto mark_cursor_off;
11364
11365 /* If the cursor is in the mouse face area, redisplay that when
11366 we clear the cursor. */
8801a864
KR
11367 if (! NILP (dpyinfo->mouse_face_window)
11368 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
11369 && (vpos > dpyinfo->mouse_face_beg_row
11370 || (vpos == dpyinfo->mouse_face_beg_row
11371 && hpos >= dpyinfo->mouse_face_beg_col))
11372 && (vpos < dpyinfo->mouse_face_end_row
11373 || (vpos == dpyinfo->mouse_face_end_row
11374 && hpos < dpyinfo->mouse_face_end_col))
11375 /* Don't redraw the cursor's spot in mouse face if it is at the
11376 end of a line (on a newline). The cursor appears there, but
11377 mouse highlighting does not. */
11378 && cursor_row->used[TEXT_AREA] > hpos)
11379 mouse_face_here_p = 1;
11380
11381 /* Maybe clear the display under the cursor. */
11382 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
11383 {
11384 int x;
045dee35 11385 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 11386
06a2c219
GM
11387 cursor_glyph = get_phys_cursor_glyph (w);
11388 if (cursor_glyph == NULL)
11389 goto mark_cursor_off;
dbc4e1c1 11390
e0300d33 11391 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
06a2c219 11392
c5e6e06b
GM
11393 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11394 x,
11395 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
11396 cursor_row->y)),
11397 cursor_glyph->pixel_width,
11398 cursor_row->visible_height,
11399 False);
dbc4e1c1 11400 }
06a2c219
GM
11401
11402 /* Erase the cursor by redrawing the character underneath it. */
11403 if (mouse_face_here_p)
11404 hl = DRAW_MOUSE_FACE;
06a2c219
GM
11405 else
11406 hl = DRAW_NORMAL_TEXT;
11407 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 11408
06a2c219
GM
11409 mark_cursor_off:
11410 w->phys_cursor_on_p = 0;
11411 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
11412}
11413
11414
b7f83f9e
GM
11415/* Non-zero if physical cursor of window W is within mouse face. */
11416
11417static int
11418cursor_in_mouse_face_p (w)
11419 struct window *w;
11420{
11421 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
11422 int in_mouse_face = 0;
11423
11424 if (WINDOWP (dpyinfo->mouse_face_window)
11425 && XWINDOW (dpyinfo->mouse_face_window) == w)
11426 {
11427 int hpos = w->phys_cursor.hpos;
11428 int vpos = w->phys_cursor.vpos;
11429
11430 if (vpos >= dpyinfo->mouse_face_beg_row
11431 && vpos <= dpyinfo->mouse_face_end_row
11432 && (vpos > dpyinfo->mouse_face_beg_row
11433 || hpos >= dpyinfo->mouse_face_beg_col)
11434 && (vpos < dpyinfo->mouse_face_end_row
11435 || hpos < dpyinfo->mouse_face_end_col
11436 || dpyinfo->mouse_face_past_end))
11437 in_mouse_face = 1;
11438 }
11439
11440 return in_mouse_face;
11441}
11442
11443
06a2c219
GM
11444/* Display or clear cursor of window W. If ON is zero, clear the
11445 cursor. If it is non-zero, display the cursor. If ON is nonzero,
11446 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 11447
06a2c219
GM
11448void
11449x_display_and_set_cursor (w, on, hpos, vpos, x, y)
11450 struct window *w;
11451 int on, hpos, vpos, x, y;
dbc4e1c1 11452{
06a2c219
GM
11453 struct frame *f = XFRAME (w->frame);
11454 int new_cursor_type;
f02d8aa0 11455 int new_cursor_width;
06a2c219
GM
11456 struct glyph_matrix *current_glyphs;
11457 struct glyph_row *glyph_row;
11458 struct glyph *glyph;
dbc4e1c1 11459
49d838ea 11460 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
11461 windows and frames; in the latter case, the frame or window may
11462 be in the midst of changing its size, and x and y may be off the
11463 window. */
11464 if (! FRAME_VISIBLE_P (f)
11465 || FRAME_GARBAGED_P (f)
11466 || vpos >= w->current_matrix->nrows
11467 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
11468 return;
11469
11470 /* If cursor is off and we want it off, return quickly. */
06a2c219 11471 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
11472 return;
11473
06a2c219
GM
11474 current_glyphs = w->current_matrix;
11475 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11476 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11477
11478 /* If cursor row is not enabled, we don't really know where to
11479 display the cursor. */
11480 if (!glyph_row->enabled_p)
11481 {
11482 w->phys_cursor_on_p = 0;
11483 return;
11484 }
11485
11486 xassert (interrupt_input_blocked);
11487
11488 /* Set new_cursor_type to the cursor we want to be displayed. In a
11489 mini-buffer window, we want the cursor only to appear if we are
11490 reading input from this window. For the selected window, we want
11491 the cursor type given by the frame parameter. If explicitly
11492 marked off, draw no cursor. In all other cases, we want a hollow
11493 box cursor. */
f02d8aa0 11494 new_cursor_width = -1;
9b4a7047
GM
11495 if (cursor_in_echo_area
11496 && FRAME_HAS_MINIBUF_P (f)
11497 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 11498 {
9b4a7047
GM
11499 if (w == XWINDOW (echo_area_window))
11500 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
11501 else
11502 new_cursor_type = HOLLOW_BOX_CURSOR;
11503 }
06a2c219 11504 else
9b4a7047 11505 {
7a58ab59
GM
11506 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11507 || w != XWINDOW (f->selected_window))
9b4a7047 11508 {
e55a0b79
GM
11509 extern int cursor_in_non_selected_windows;
11510
5cefa566
GM
11511 if (MINI_WINDOW_P (w)
11512 || !cursor_in_non_selected_windows
11513 || NILP (XBUFFER (w->buffer)->cursor_type))
9b4a7047
GM
11514 new_cursor_type = NO_CURSOR;
11515 else
11516 new_cursor_type = HOLLOW_BOX_CURSOR;
11517 }
11518 else if (w->cursor_off_p)
11519 new_cursor_type = NO_CURSOR;
11520 else
f02d8aa0
GM
11521 {
11522 struct buffer *b = XBUFFER (w->buffer);
11523
11524 if (EQ (b->cursor_type, Qt))
11525 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11526 else
11527 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11528 &new_cursor_width);
11529 }
9b4a7047 11530 }
06a2c219
GM
11531
11532 /* If cursor is currently being shown and we don't want it to be or
11533 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 11534 erase it. */
06a2c219 11535 if (w->phys_cursor_on_p
dc6f92b8 11536 && (!on
06a2c219
GM
11537 || w->phys_cursor.x != x
11538 || w->phys_cursor.y != y
11539 || new_cursor_type != w->phys_cursor_type))
11540 x_erase_phys_cursor (w);
11541
11542 /* If the cursor is now invisible and we want it to be visible,
11543 display it. */
11544 if (on && !w->phys_cursor_on_p)
11545 {
11546 w->phys_cursor_ascent = glyph_row->ascent;
11547 w->phys_cursor_height = glyph_row->height;
11548
11549 /* Set phys_cursor_.* before x_draw_.* is called because some
11550 of them may need the information. */
11551 w->phys_cursor.x = x;
11552 w->phys_cursor.y = glyph_row->y;
11553 w->phys_cursor.hpos = hpos;
11554 w->phys_cursor.vpos = vpos;
11555 w->phys_cursor_type = new_cursor_type;
11556 w->phys_cursor_on_p = 1;
11557
11558 switch (new_cursor_type)
dc6f92b8 11559 {
06a2c219
GM
11560 case HOLLOW_BOX_CURSOR:
11561 x_draw_hollow_cursor (w, glyph_row);
11562 break;
11563
11564 case FILLED_BOX_CURSOR:
11565 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11566 break;
11567
11568 case BAR_CURSOR:
f02d8aa0 11569 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
11570 break;
11571
11572 case NO_CURSOR:
11573 break;
dc6f92b8 11574
06a2c219
GM
11575 default:
11576 abort ();
11577 }
59ddecde
GM
11578
11579#ifdef HAVE_X_I18N
11580 if (w == XWINDOW (f->selected_window))
11581 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11582 xic_set_preeditarea (w, x, y);
11583#endif
dc6f92b8
JB
11584 }
11585
06a2c219 11586#ifndef XFlush
f676886a 11587 if (updating_frame != f)
334208b7 11588 XFlush (FRAME_X_DISPLAY (f));
06a2c219 11589#endif
dc6f92b8
JB
11590}
11591
06a2c219
GM
11592
11593/* Display the cursor on window W, or clear it. X and Y are window
11594 relative pixel coordinates. HPOS and VPOS are glyph matrix
11595 positions. If W is not the selected window, display a hollow
11596 cursor. ON non-zero means display the cursor at X, Y which
11597 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 11598
dfcf069d 11599void
06a2c219
GM
11600x_display_cursor (w, on, hpos, vpos, x, y)
11601 struct window *w;
11602 int on, hpos, vpos, x, y;
dc6f92b8 11603{
f94397b5 11604 BLOCK_INPUT;
06a2c219 11605 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
11606 UNBLOCK_INPUT;
11607}
11608
06a2c219
GM
11609
11610/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
11611 Don't change the cursor's position. */
11612
dfcf069d 11613void
06a2c219 11614x_update_cursor (f, on_p)
5d46f928 11615 struct frame *f;
5d46f928 11616{
06a2c219
GM
11617 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11618}
11619
11620
11621/* Call x_update_window_cursor with parameter ON_P on all leaf windows
11622 in the window tree rooted at W. */
11623
11624static void
11625x_update_cursor_in_window_tree (w, on_p)
11626 struct window *w;
11627 int on_p;
11628{
11629 while (w)
11630 {
11631 if (!NILP (w->hchild))
11632 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11633 else if (!NILP (w->vchild))
11634 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11635 else
11636 x_update_window_cursor (w, on_p);
11637
11638 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11639 }
11640}
5d46f928 11641
f94397b5 11642
06a2c219
GM
11643/* Switch the display of W's cursor on or off, according to the value
11644 of ON. */
11645
11646static void
11647x_update_window_cursor (w, on)
11648 struct window *w;
11649 int on;
11650{
16b5d424
GM
11651 /* Don't update cursor in windows whose frame is in the process
11652 of being deleted. */
11653 if (w->current_matrix)
11654 {
11655 BLOCK_INPUT;
11656 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11657 w->phys_cursor.x, w->phys_cursor.y);
11658 UNBLOCK_INPUT;
11659 }
dc6f92b8 11660}
06a2c219
GM
11661
11662
11663
dc6f92b8
JB
11664\f
11665/* Icons. */
11666
dbc4e1c1 11667/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
11668
11669int
990ba854 11670x_bitmap_icon (f, file)
f676886a 11671 struct frame *f;
990ba854 11672 Lisp_Object file;
dc6f92b8 11673{
06a2c219 11674 int bitmap_id;
dc6f92b8 11675
c118dd06 11676 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11677 return 1;
11678
990ba854 11679 /* Free up our existing icon bitmap if any. */
7556890b
RS
11680 if (f->output_data.x->icon_bitmap > 0)
11681 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11682 f->output_data.x->icon_bitmap = 0;
990ba854
RS
11683
11684 if (STRINGP (file))
7f2ae036
RS
11685 bitmap_id = x_create_bitmap_from_file (f, file);
11686 else
11687 {
990ba854 11688 /* Create the GNU bitmap if necessary. */
5bf01b68 11689 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
11690 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11691 = x_create_bitmap_from_data (f, gnu_bits,
11692 gnu_width, gnu_height);
990ba854
RS
11693
11694 /* The first time we create the GNU bitmap,
06a2c219 11695 this increments the ref-count one extra time.
990ba854
RS
11696 As a result, the GNU bitmap is never freed.
11697 That way, we don't have to worry about allocating it again. */
334208b7 11698 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 11699
334208b7 11700 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
11701 }
11702
11703 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 11704 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
11705
11706 return 0;
11707}
11708
11709
1be2d067
KH
11710/* Make the x-window of frame F use a rectangle with text.
11711 Use ICON_NAME as the text. */
dc6f92b8
JB
11712
11713int
f676886a
JB
11714x_text_icon (f, icon_name)
11715 struct frame *f;
dc6f92b8
JB
11716 char *icon_name;
11717{
c118dd06 11718 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11719 return 1;
11720
1be2d067
KH
11721#ifdef HAVE_X11R4
11722 {
11723 XTextProperty text;
11724 text.value = (unsigned char *) icon_name;
11725 text.encoding = XA_STRING;
11726 text.format = 8;
11727 text.nitems = strlen (icon_name);
11728#ifdef USE_X_TOOLKIT
7556890b 11729 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
11730 &text);
11731#else /* not USE_X_TOOLKIT */
11732 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11733#endif /* not USE_X_TOOLKIT */
11734 }
11735#else /* not HAVE_X11R4 */
11736 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11737#endif /* not HAVE_X11R4 */
58769bee 11738
7556890b
RS
11739 if (f->output_data.x->icon_bitmap > 0)
11740 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11741 f->output_data.x->icon_bitmap = 0;
b1c884c3 11742 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
11743
11744 return 0;
11745}
11746\f
e99db5a1
RS
11747#define X_ERROR_MESSAGE_SIZE 200
11748
11749/* If non-nil, this should be a string.
11750 It means catch X errors and store the error message in this string. */
11751
11752static Lisp_Object x_error_message_string;
11753
11754/* An X error handler which stores the error message in
11755 x_error_message_string. This is called from x_error_handler if
11756 x_catch_errors is in effect. */
11757
06a2c219 11758static void
e99db5a1
RS
11759x_error_catcher (display, error)
11760 Display *display;
11761 XErrorEvent *error;
11762{
11763 XGetErrorText (display, error->error_code,
11764 XSTRING (x_error_message_string)->data,
11765 X_ERROR_MESSAGE_SIZE);
11766}
11767
11768/* Begin trapping X errors for display DPY. Actually we trap X errors
11769 for all displays, but DPY should be the display you are actually
11770 operating on.
11771
11772 After calling this function, X protocol errors no longer cause
11773 Emacs to exit; instead, they are recorded in the string
11774 stored in x_error_message_string.
11775
11776 Calling x_check_errors signals an Emacs error if an X error has
11777 occurred since the last call to x_catch_errors or x_check_errors.
11778
11779 Calling x_uncatch_errors resumes the normal error handling. */
11780
11781void x_check_errors ();
11782static Lisp_Object x_catch_errors_unwind ();
11783
11784int
11785x_catch_errors (dpy)
11786 Display *dpy;
11787{
11788 int count = specpdl_ptr - specpdl;
11789
11790 /* Make sure any errors from previous requests have been dealt with. */
11791 XSync (dpy, False);
11792
11793 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11794
11795 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11796 XSTRING (x_error_message_string)->data[0] = 0;
11797
11798 return count;
11799}
11800
11801/* Unbind the binding that we made to check for X errors. */
11802
11803static Lisp_Object
11804x_catch_errors_unwind (old_val)
11805 Lisp_Object old_val;
11806{
11807 x_error_message_string = old_val;
11808 return Qnil;
11809}
11810
11811/* If any X protocol errors have arrived since the last call to
11812 x_catch_errors or x_check_errors, signal an Emacs error using
11813 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11814
11815void
11816x_check_errors (dpy, format)
11817 Display *dpy;
11818 char *format;
11819{
11820 /* Make sure to catch any errors incurred so far. */
11821 XSync (dpy, False);
11822
11823 if (XSTRING (x_error_message_string)->data[0])
11824 error (format, XSTRING (x_error_message_string)->data);
11825}
11826
9829ddba
RS
11827/* Nonzero if we had any X protocol errors
11828 since we did x_catch_errors on DPY. */
e99db5a1
RS
11829
11830int
11831x_had_errors_p (dpy)
11832 Display *dpy;
11833{
11834 /* Make sure to catch any errors incurred so far. */
11835 XSync (dpy, False);
11836
11837 return XSTRING (x_error_message_string)->data[0] != 0;
11838}
11839
9829ddba
RS
11840/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11841
06a2c219 11842void
9829ddba
RS
11843x_clear_errors (dpy)
11844 Display *dpy;
11845{
11846 XSTRING (x_error_message_string)->data[0] = 0;
11847}
11848
e99db5a1
RS
11849/* Stop catching X protocol errors and let them make Emacs die.
11850 DPY should be the display that was passed to x_catch_errors.
11851 COUNT should be the value that was returned by
11852 the corresponding call to x_catch_errors. */
11853
11854void
11855x_uncatch_errors (dpy, count)
11856 Display *dpy;
11857 int count;
11858{
11859 unbind_to (count, Qnil);
11860}
11861
11862#if 0
11863static unsigned int x_wire_count;
11864x_trace_wire ()
11865{
11866 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11867}
11868#endif /* ! 0 */
11869
11870\f
11871/* Handle SIGPIPE, which can happen when the connection to a server
11872 simply goes away. SIGPIPE is handled by x_connection_signal.
11873 Don't need to do anything, because the write which caused the
11874 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 11875 which will do the appropriate cleanup for us. */
e99db5a1
RS
11876
11877static SIGTYPE
11878x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 11879 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
11880{
11881#ifdef USG
11882 /* USG systems forget handlers when they are used;
11883 must reestablish each time */
11884 signal (signalnum, x_connection_signal);
11885#endif /* USG */
11886}
0da1ab50 11887
e99db5a1 11888\f
0da1ab50
GM
11889/************************************************************************
11890 Handling X errors
11891 ************************************************************************/
4746118a 11892
f0e299de
GM
11893/* Error message passed to x_connection_closed. */
11894
11895static char *error_msg;
11896
11897/* Function installed as fatal_error_signal_hook.in
11898 x_connection_closed. Print the X error message, and exit normally,
11899 instead of dumping core when XtCloseDisplay fails. */
11900
11901static void
11902x_fatal_error_signal ()
11903{
11904 fprintf (stderr, "%s\n", error_msg);
11905 exit (70);
11906}
11907
0da1ab50
GM
11908/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11909 the text of an error message that lead to the connection loss. */
16bd92ea 11910
4746118a 11911static SIGTYPE
5978125e
GM
11912x_connection_closed (dpy, error_message)
11913 Display *dpy;
7a13e894 11914 char *error_message;
4746118a 11915{
5978125e 11916 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7a13e894 11917 Lisp_Object frame, tail;
0da1ab50 11918 int count;
0da1ab50 11919
f0e299de
GM
11920 error_msg = (char *) alloca (strlen (error_message) + 1);
11921 strcpy (error_msg, error_message);
1a532e54
GM
11922 handling_signal = 0;
11923
0da1ab50
GM
11924 /* Prevent being called recursively because of an error condition
11925 below. Otherwise, we might end up with printing ``can't find per
11926 display information'' in the recursive call instead of printing
11927 the original message here. */
11928 count = x_catch_errors (dpy);
11929
8a4f36cc
GM
11930 /* We have to close the display to inform Xt that it doesn't
11931 exist anymore. If we don't, Xt will continue to wait for
11932 events from the display. As a consequence, a sequence of
11933
11934 M-x make-frame-on-display RET :1 RET
11935 ...kill the new frame, so that we get an IO error...
11936 M-x make-frame-on-display RET :1 RET
11937
11938 will indefinitely wait in Xt for events for display `:1', opened
11939 in the first class to make-frame-on-display.
6186a4a0 11940
8a4f36cc
GM
11941 Closing the display is reported to lead to a bus error on
11942 OpenWindows in certain situations. I suspect that is a bug
11943 in OpenWindows. I don't know how to cicumvent it here. */
11944
f613a4c8 11945#ifdef USE_X_TOOLKIT
ae24cb3b
GM
11946 /* If DPYINFO is null, this means we didn't open the display
11947 in the first place, so don't try to close it. */
11948 if (dpyinfo)
f0e299de
GM
11949 {
11950 extern void (*fatal_error_signal_hook) P_ ((void));
11951 fatal_error_signal_hook = x_fatal_error_signal;
11952 XtCloseDisplay (dpy);
11953 fatal_error_signal_hook = NULL;
11954 }
f613a4c8 11955#endif
adabc3a9 11956
8a4f36cc 11957 /* Indicate that this display is dead. */
9e80b57d
KR
11958 if (dpyinfo)
11959 dpyinfo->display = 0;
6186a4a0 11960
06a2c219 11961 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
11962 that are on the dead display. */
11963 FOR_EACH_FRAME (tail, frame)
11964 {
11965 Lisp_Object minibuf_frame;
11966 minibuf_frame
11967 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
11968 if (FRAME_X_P (XFRAME (frame))
11969 && FRAME_X_P (XFRAME (minibuf_frame))
11970 && ! EQ (frame, minibuf_frame)
11971 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
11972 Fdelete_frame (frame, Qt);
11973 }
11974
11975 /* Now delete all remaining frames on the dead display.
06a2c219 11976 We are now sure none of these is used as the mini-buffer
7a13e894
RS
11977 for another frame that we need to delete. */
11978 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
11979 if (FRAME_X_P (XFRAME (frame))
11980 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
11981 {
11982 /* Set this to t so that Fdelete_frame won't get confused
11983 trying to find a replacement. */
11984 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11985 Fdelete_frame (frame, Qt);
11986 }
7a13e894 11987
482a1bd2
KH
11988 if (dpyinfo)
11989 x_delete_display (dpyinfo);
7a13e894 11990
0da1ab50
GM
11991 x_uncatch_errors (dpy, count);
11992
7a13e894
RS
11993 if (x_display_list == 0)
11994 {
f0e299de 11995 fprintf (stderr, "%s\n", error_msg);
7a13e894
RS
11996 shut_down_emacs (0, 0, Qnil);
11997 exit (70);
11998 }
12ba150f 11999
7a13e894
RS
12000 /* Ordinary stack unwind doesn't deal with these. */
12001#ifdef SIGIO
12002 sigunblock (sigmask (SIGIO));
12003#endif
12004 sigunblock (sigmask (SIGALRM));
12005 TOTALLY_UNBLOCK_INPUT;
12006
aa4d9a9e 12007 clear_waiting_for_input ();
f0e299de 12008 error ("%s", error_msg);
4746118a
JB
12009}
12010
0da1ab50 12011
7a13e894
RS
12012/* This is the usual handler for X protocol errors.
12013 It kills all frames on the display that we got the error for.
12014 If that was the only one, it prints an error message and kills Emacs. */
12015
06a2c219 12016static void
c118dd06
JB
12017x_error_quitter (display, error)
12018 Display *display;
12019 XErrorEvent *error;
12020{
7a13e894 12021 char buf[256], buf1[356];
dc6f92b8 12022
58769bee 12023 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 12024 original error handler. */
dc6f92b8 12025
c118dd06 12026 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 12027 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 12028 buf, error->request_code);
7a13e894 12029 x_connection_closed (display, buf1);
dc6f92b8
JB
12030}
12031
0da1ab50 12032
e99db5a1
RS
12033/* This is the first-level handler for X protocol errors.
12034 It calls x_error_quitter or x_error_catcher. */
7a13e894 12035
8922af5f 12036static int
e99db5a1 12037x_error_handler (display, error)
8922af5f 12038 Display *display;
e99db5a1 12039 XErrorEvent *error;
8922af5f 12040{
e99db5a1
RS
12041 if (! NILP (x_error_message_string))
12042 x_error_catcher (display, error);
12043 else
12044 x_error_quitter (display, error);
06a2c219 12045 return 0;
f9e24cb9 12046}
c118dd06 12047
e99db5a1
RS
12048/* This is the handler for X IO errors, always.
12049 It kills all frames on the display that we lost touch with.
12050 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 12051
c118dd06 12052static int
e99db5a1 12053x_io_error_quitter (display)
c118dd06 12054 Display *display;
c118dd06 12055{
e99db5a1 12056 char buf[256];
dc6f92b8 12057
e99db5a1
RS
12058 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
12059 x_connection_closed (display, buf);
06a2c219 12060 return 0;
dc6f92b8 12061}
dc6f92b8 12062\f
f451eb13
JB
12063/* Changing the font of the frame. */
12064
76bcdf39
RS
12065/* Give frame F the font named FONTNAME as its default font, and
12066 return the full name of that font. FONTNAME may be a wildcard
12067 pattern; in that case, we choose some font that fits the pattern.
12068 The return value shows which font we chose. */
12069
b5cf7a0e 12070Lisp_Object
f676886a
JB
12071x_new_font (f, fontname)
12072 struct frame *f;
dc6f92b8
JB
12073 register char *fontname;
12074{
dc43ef94 12075 struct font_info *fontp
ee569018 12076 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 12077
dc43ef94
KH
12078 if (!fontp)
12079 return Qnil;
2224a5fc 12080
dc43ef94 12081 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 12082 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
12083 f->output_data.x->fontset = -1;
12084
b2cad826
KH
12085 /* Compute the scroll bar width in character columns. */
12086 if (f->scroll_bar_pixel_width > 0)
12087 {
7556890b 12088 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
12089 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
12090 }
12091 else
4e61bddf
RS
12092 {
12093 int wid = FONT_WIDTH (f->output_data.x->font);
12094 f->scroll_bar_cols = (14 + wid - 1) / wid;
12095 }
b2cad826 12096
f676886a 12097 /* Now make the frame display the given font. */
c118dd06 12098 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 12099 {
7556890b
RS
12100 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
12101 f->output_data.x->font->fid);
12102 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
12103 f->output_data.x->font->fid);
12104 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
12105 f->output_data.x->font->fid);
f676886a 12106
a27f9f86 12107 frame_update_line_height (f);
3497f73e
GM
12108
12109 /* Don't change the size of a tip frame; there's no point in
12110 doing it because it's done in Fx_show_tip, and it leads to
12111 problems because the tip frame has no widget. */
12112 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
12113 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 12114 }
a27f9f86
RS
12115 else
12116 /* If we are setting a new frame's font for the first time,
12117 there are no faces yet, so this font's height is the line height. */
7556890b 12118 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 12119
dc43ef94
KH
12120 return build_string (fontp->full_name);
12121}
12122
12123/* Give frame F the fontset named FONTSETNAME as its default font, and
12124 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
12125 pattern; in that case, we choose some fontset that fits the pattern.
12126 The return value shows which fontset we chose. */
b5cf7a0e 12127
dc43ef94
KH
12128Lisp_Object
12129x_new_fontset (f, fontsetname)
12130 struct frame *f;
12131 char *fontsetname;
12132{
ee569018 12133 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 12134 Lisp_Object result;
b5cf7a0e 12135
dc43ef94
KH
12136 if (fontset < 0)
12137 return Qnil;
b5cf7a0e 12138
2da424f1
KH
12139 if (f->output_data.x->fontset == fontset)
12140 /* This fontset is already set in frame F. There's nothing more
12141 to do. */
ee569018 12142 return fontset_name (fontset);
dc43ef94 12143
ee569018 12144 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
12145
12146 if (!STRINGP (result))
12147 /* Can't load ASCII font. */
12148 return Qnil;
12149
12150 /* Since x_new_font doesn't update any fontset information, do it now. */
12151 f->output_data.x->fontset = fontset;
dc43ef94 12152
f5d11644
GM
12153#ifdef HAVE_X_I18N
12154 if (FRAME_XIC (f)
12155 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 12156 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
12157#endif
12158
dc43ef94 12159 return build_string (fontsetname);
dc6f92b8 12160}
f5d11644
GM
12161
12162\f
12163/***********************************************************************
12164 X Input Methods
12165 ***********************************************************************/
12166
12167#ifdef HAVE_X_I18N
12168
12169#ifdef HAVE_X11R6
12170
12171/* XIM destroy callback function, which is called whenever the
12172 connection to input method XIM dies. CLIENT_DATA contains a
12173 pointer to the x_display_info structure corresponding to XIM. */
12174
12175static void
12176xim_destroy_callback (xim, client_data, call_data)
12177 XIM xim;
12178 XPointer client_data;
12179 XPointer call_data;
12180{
12181 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
12182 Lisp_Object frame, tail;
12183
12184 BLOCK_INPUT;
12185
12186 /* No need to call XDestroyIC.. */
12187 FOR_EACH_FRAME (tail, frame)
12188 {
12189 struct frame *f = XFRAME (frame);
12190 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
12191 {
12192 FRAME_XIC (f) = NULL;
12193 if (FRAME_XIC_FONTSET (f))
12194 {
12195 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
12196 FRAME_XIC_FONTSET (f) = NULL;
12197 }
12198 }
12199 }
12200
12201 /* No need to call XCloseIM. */
12202 dpyinfo->xim = NULL;
12203 XFree (dpyinfo->xim_styles);
12204 UNBLOCK_INPUT;
12205}
12206
12207#endif /* HAVE_X11R6 */
12208
12209/* Open the connection to the XIM server on display DPYINFO.
12210 RESOURCE_NAME is the resource name Emacs uses. */
12211
12212static void
12213xim_open_dpy (dpyinfo, resource_name)
12214 struct x_display_info *dpyinfo;
12215 char *resource_name;
12216{
287f7dd6 12217#ifdef USE_XIM
f5d11644
GM
12218 XIM xim;
12219
12220 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
12221 dpyinfo->xim = xim;
12222
12223 if (xim)
12224 {
f5d11644
GM
12225#ifdef HAVE_X11R6
12226 XIMCallback destroy;
12227#endif
12228
12229 /* Get supported styles and XIM values. */
12230 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
12231
12232#ifdef HAVE_X11R6
12233 destroy.callback = xim_destroy_callback;
12234 destroy.client_data = (XPointer)dpyinfo;
cea2ad76 12235 /* This isn't prototyped in OSF 5.0. */
f5d11644
GM
12236 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
12237#endif
12238 }
287f7dd6
GM
12239
12240#else /* not USE_XIM */
12241 dpyinfo->xim = NULL;
12242#endif /* not USE_XIM */
f5d11644
GM
12243}
12244
12245
b9de836c 12246#ifdef HAVE_X11R6_XIM
f5d11644
GM
12247
12248struct xim_inst_t
12249{
12250 struct x_display_info *dpyinfo;
12251 char *resource_name;
12252};
12253
12254/* XIM instantiate callback function, which is called whenever an XIM
12255 server is available. DISPLAY is teh display of the XIM.
12256 CLIENT_DATA contains a pointer to an xim_inst_t structure created
12257 when the callback was registered. */
12258
12259static void
12260xim_instantiate_callback (display, client_data, call_data)
12261 Display *display;
12262 XPointer client_data;
12263 XPointer call_data;
12264{
12265 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
12266 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
12267
12268 /* We don't support multiple XIM connections. */
12269 if (dpyinfo->xim)
12270 return;
12271
12272 xim_open_dpy (dpyinfo, xim_inst->resource_name);
12273
12274 /* Create XIC for the existing frames on the same display, as long
12275 as they have no XIC. */
12276 if (dpyinfo->xim && dpyinfo->reference_count > 0)
12277 {
12278 Lisp_Object tail, frame;
12279
12280 BLOCK_INPUT;
12281 FOR_EACH_FRAME (tail, frame)
12282 {
12283 struct frame *f = XFRAME (frame);
12284
12285 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
12286 if (FRAME_XIC (f) == NULL)
12287 {
12288 create_frame_xic (f);
12289 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
12290 xic_set_statusarea (f);
12291 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
12292 {
12293 struct window *w = XWINDOW (f->selected_window);
12294 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
12295 }
12296 }
12297 }
12298
12299 UNBLOCK_INPUT;
12300 }
12301}
12302
b9de836c 12303#endif /* HAVE_X11R6_XIM */
f5d11644
GM
12304
12305
12306/* Open a connection to the XIM server on display DPYINFO.
12307 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
12308 connection only at the first time. On X11R6, open the connection
12309 in the XIM instantiate callback function. */
12310
12311static void
12312xim_initialize (dpyinfo, resource_name)
12313 struct x_display_info *dpyinfo;
12314 char *resource_name;
12315{
287f7dd6 12316#ifdef USE_XIM
b9de836c 12317#ifdef HAVE_X11R6_XIM
f5d11644
GM
12318 struct xim_inst_t *xim_inst;
12319 int len;
12320
12321 dpyinfo->xim = NULL;
12322 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
12323 xim_inst->dpyinfo = dpyinfo;
12324 len = strlen (resource_name);
12325 xim_inst->resource_name = (char *) xmalloc (len + 1);
12326 bcopy (resource_name, xim_inst->resource_name, len + 1);
12327 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12328 resource_name, EMACS_CLASS,
12329 xim_instantiate_callback,
2ebb2f8b
DL
12330 /* Fixme: This is XPointer in
12331 XFree86 but (XPointer *) on
12332 Tru64, at least. */
12333 (XPointer) xim_inst);
b9de836c 12334#else /* not HAVE_X11R6_XIM */
f5d11644
GM
12335 dpyinfo->xim = NULL;
12336 xim_open_dpy (dpyinfo, resource_name);
b9de836c 12337#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
12338
12339#else /* not USE_XIM */
12340 dpyinfo->xim = NULL;
12341#endif /* not USE_XIM */
f5d11644
GM
12342}
12343
12344
12345/* Close the connection to the XIM server on display DPYINFO. */
12346
12347static void
12348xim_close_dpy (dpyinfo)
12349 struct x_display_info *dpyinfo;
12350{
287f7dd6 12351#ifdef USE_XIM
b9de836c 12352#ifdef HAVE_X11R6_XIM
8a4f36cc
GM
12353 if (dpyinfo->display)
12354 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
12355 NULL, EMACS_CLASS,
12356 xim_instantiate_callback, NULL);
b9de836c 12357#endif /* not HAVE_X11R6_XIM */
8a4f36cc
GM
12358 if (dpyinfo->display)
12359 XCloseIM (dpyinfo->xim);
f5d11644
GM
12360 dpyinfo->xim = NULL;
12361 XFree (dpyinfo->xim_styles);
287f7dd6 12362#endif /* USE_XIM */
f5d11644
GM
12363}
12364
b9de836c 12365#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
12366
12367
dc6f92b8 12368\f
2e365682
RS
12369/* Calculate the absolute position in frame F
12370 from its current recorded position values and gravity. */
12371
dfcf069d 12372void
43bca5d5 12373x_calc_absolute_position (f)
f676886a 12374 struct frame *f;
dc6f92b8 12375{
06a2c219 12376 Window child;
6dba1858 12377 int win_x = 0, win_y = 0;
7556890b 12378 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
12379 int this_window;
12380
9829ddba
RS
12381 /* We have nothing to do if the current position
12382 is already for the top-left corner. */
12383 if (! ((flags & XNegative) || (flags & YNegative)))
12384 return;
12385
c81412a0 12386#ifdef USE_X_TOOLKIT
7556890b 12387 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
12388#else
12389 this_window = FRAME_X_WINDOW (f);
12390#endif
6dba1858
RS
12391
12392 /* Find the position of the outside upper-left corner of
9829ddba
RS
12393 the inner window, with respect to the outer window.
12394 But do this only if we will need the results. */
7556890b 12395 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 12396 {
9829ddba
RS
12397 int count;
12398
6dba1858 12399 BLOCK_INPUT;
9829ddba
RS
12400 count = x_catch_errors (FRAME_X_DISPLAY (f));
12401 while (1)
12402 {
12403 x_clear_errors (FRAME_X_DISPLAY (f));
12404 XTranslateCoordinates (FRAME_X_DISPLAY (f),
12405
12406 /* From-window, to-window. */
12407 this_window,
12408 f->output_data.x->parent_desc,
12409
12410 /* From-position, to-position. */
12411 0, 0, &win_x, &win_y,
12412
12413 /* Child of win. */
12414 &child);
12415 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12416 {
12417 Window newroot, newparent = 0xdeadbeef;
12418 Window *newchildren;
2ebb2f8b 12419 unsigned int nchildren;
9829ddba
RS
12420
12421 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
12422 &newparent, &newchildren, &nchildren))
12423 break;
58769bee 12424
7c3c78a3 12425 XFree ((char *) newchildren);
6dba1858 12426
9829ddba
RS
12427 f->output_data.x->parent_desc = newparent;
12428 }
12429 else
12430 break;
12431 }
6dba1858 12432
9829ddba 12433 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
12434 UNBLOCK_INPUT;
12435 }
12436
12437 /* Treat negative positions as relative to the leftmost bottommost
12438 position that fits on the screen. */
20f55f9a 12439 if (flags & XNegative)
7556890b 12440 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
12441 - 2 * f->output_data.x->border_width - win_x
12442 - PIXEL_WIDTH (f)
12443 + f->output_data.x->left_pos);
dc6f92b8 12444
7708ced0
GM
12445 {
12446 int height = PIXEL_HEIGHT (f);
06a2c219 12447
7708ced0
GM
12448#if defined USE_X_TOOLKIT && defined USE_MOTIF
12449 /* Something is fishy here. When using Motif, starting Emacs with
12450 `-g -0-0', the frame appears too low by a few pixels.
12451
12452 This seems to be so because initially, while Emacs is starting,
12453 the column widget's height and the frame's pixel height are
12454 different. The column widget's height is the right one. In
12455 later invocations, when Emacs is up, the frame's pixel height
12456 is right, though.
12457
12458 It's not obvious where the initial small difference comes from.
12459 2000-12-01, gerd. */
12460
12461 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
06a2c219 12462#endif
2e365682 12463
7708ced0
GM
12464 if (flags & YNegative)
12465 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
12466 - 2 * f->output_data.x->border_width
12467 - win_y
12468 - height
12469 + f->output_data.x->top_pos);
12470 }
12471
3a35ab44
RS
12472 /* The left_pos and top_pos
12473 are now relative to the top and left screen edges,
12474 so the flags should correspond. */
7556890b 12475 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
12476}
12477
3a35ab44
RS
12478/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
12479 to really change the position, and 0 when calling from
12480 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
12481 position values). It is -1 when calling from x_set_frame_parameters,
12482 which means, do adjust for borders but don't change the gravity. */
3a35ab44 12483
dfcf069d 12484void
dc05a16b 12485x_set_offset (f, xoff, yoff, change_gravity)
f676886a 12486 struct frame *f;
dc6f92b8 12487 register int xoff, yoff;
dc05a16b 12488 int change_gravity;
dc6f92b8 12489{
4a4cbdd5
KH
12490 int modified_top, modified_left;
12491
aa3ff7c9 12492 if (change_gravity > 0)
3a35ab44 12493 {
7556890b
RS
12494 f->output_data.x->top_pos = yoff;
12495 f->output_data.x->left_pos = xoff;
12496 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 12497 if (xoff < 0)
7556890b 12498 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 12499 if (yoff < 0)
7556890b
RS
12500 f->output_data.x->size_hint_flags |= YNegative;
12501 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 12502 }
43bca5d5 12503 x_calc_absolute_position (f);
dc6f92b8
JB
12504
12505 BLOCK_INPUT;
c32cdd9a 12506 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 12507
7556890b
RS
12508 modified_left = f->output_data.x->left_pos;
12509 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
12510#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12511 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12512 /* It is a mystery why we need to add the border_width here
12513 when the frame is already visible, but experiment says we do. */
aa3ff7c9 12514 if (change_gravity != 0)
4a4cbdd5 12515 {
7556890b
RS
12516 modified_left += f->output_data.x->border_width;
12517 modified_top += f->output_data.x->border_width;
4a4cbdd5 12518 }
e73ec6fa 12519#endif
4a4cbdd5 12520
3afe33e7 12521#ifdef USE_X_TOOLKIT
7556890b 12522 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 12523 modified_left, modified_top);
3afe33e7 12524#else /* not USE_X_TOOLKIT */
334208b7 12525 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 12526 modified_left, modified_top);
3afe33e7 12527#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12528 UNBLOCK_INPUT;
12529}
12530
dc6f92b8 12531
499b1844
GM
12532/* Change the size of frame F's X window to COLS/ROWS in the case F
12533 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12534 top-left-corner window gravity for this size change and subsequent
12535 size changes. Otherwise we leave the window gravity unchanged. */
12536
12537static void
12538x_set_window_size_1 (f, change_gravity, cols, rows)
f676886a 12539 struct frame *f;
bc20ebbf 12540 int change_gravity;
b1c884c3 12541 int cols, rows;
dc6f92b8
JB
12542{
12543 int pixelwidth, pixelheight;
80fd1fe2 12544
b1c884c3 12545 check_frame_size (f, &rows, &cols);
7556890b 12546 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
12547 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12548 ? 0
12549 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 12550 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 12551 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 12552 f->output_data.x->flags_areas_extra
110859fc 12553 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
12554 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12555 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 12556
7556890b 12557 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 12558 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 12559
334208b7
RS
12560 XSync (FRAME_X_DISPLAY (f), False);
12561 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12562 pixelwidth, pixelheight);
b1c884c3
JB
12563
12564 /* Now, strictly speaking, we can't be sure that this is accurate,
12565 but the window manager will get around to dealing with the size
12566 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
12567 ConfigureNotify event gets here.
12568
12569 We could just not bother storing any of this information here,
12570 and let the ConfigureNotify event set everything up, but that
fddd5ceb 12571 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 12572 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
12573 point in the future when the ConfigureNotify event arrives.
12574
12575 We pass 1 for DELAY since we can't run Lisp code inside of
12576 a BLOCK_INPUT. */
7d1e984f 12577 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
12578 PIXEL_WIDTH (f) = pixelwidth;
12579 PIXEL_HEIGHT (f) = pixelheight;
12580
aee9a898
RS
12581 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12582 receive in the ConfigureNotify event; if we get what we asked
12583 for, then the event won't cause the screen to become garbaged, so
12584 we have to make sure to do it here. */
12585 SET_FRAME_GARBAGED (f);
12586
12587 XFlush (FRAME_X_DISPLAY (f));
499b1844
GM
12588}
12589
12590
12591/* Call this to change the size of frame F's x-window.
12592 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12593 for this size change and subsequent size changes.
12594 Otherwise we leave the window gravity unchanged. */
aee9a898 12595
499b1844
GM
12596void
12597x_set_window_size (f, change_gravity, cols, rows)
12598 struct frame *f;
12599 int change_gravity;
12600 int cols, rows;
12601{
12602 BLOCK_INPUT;
12603
12604#ifdef USE_X_TOOLKIT
12605
f1f4d345 12606 if (f->output_data.x->widget != NULL)
499b1844
GM
12607 {
12608 /* The x and y position of the widget is clobbered by the
12609 call to XtSetValues within EmacsFrameSetCharSize.
12610 This is a real kludge, but I don't understand Xt so I can't
12611 figure out a correct fix. Can anyone else tell me? -- rms. */
12612 int xpos = f->output_data.x->widget->core.x;
12613 int ypos = f->output_data.x->widget->core.y;
12614 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12615 f->output_data.x->widget->core.x = xpos;
12616 f->output_data.x->widget->core.y = ypos;
12617 }
12618 else
12619 x_set_window_size_1 (f, change_gravity, cols, rows);
12620
12621#else /* not USE_X_TOOLKIT */
12622
12623 x_set_window_size_1 (f, change_gravity, cols, rows);
12624
aee9a898
RS
12625#endif /* not USE_X_TOOLKIT */
12626
4d73d038 12627 /* If cursor was outside the new size, mark it as off. */
06a2c219 12628 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 12629
aee9a898
RS
12630 /* Clear out any recollection of where the mouse highlighting was,
12631 since it might be in a place that's outside the new frame size.
12632 Actually checking whether it is outside is a pain in the neck,
12633 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 12634 cancel_mouse_face (f);
dbc4e1c1 12635
dc6f92b8
JB
12636 UNBLOCK_INPUT;
12637}
dc6f92b8 12638\f
d047c4eb 12639/* Mouse warping. */
dc6f92b8 12640
9b378208 12641void
f676886a
JB
12642x_set_mouse_position (f, x, y)
12643 struct frame *f;
dc6f92b8
JB
12644 int x, y;
12645{
12646 int pix_x, pix_y;
12647
7556890b
RS
12648 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12649 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
12650
12651 if (pix_x < 0) pix_x = 0;
12652 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12653
12654 if (pix_y < 0) pix_y = 0;
12655 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
12656
12657 BLOCK_INPUT;
dc6f92b8 12658
334208b7
RS
12659 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12660 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
12661 UNBLOCK_INPUT;
12662}
12663
9b378208
RS
12664/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12665
12666void
12667x_set_mouse_pixel_position (f, pix_x, pix_y)
12668 struct frame *f;
12669 int pix_x, pix_y;
12670{
12671 BLOCK_INPUT;
12672
334208b7
RS
12673 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12674 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
12675 UNBLOCK_INPUT;
12676}
d047c4eb
KH
12677\f
12678/* focus shifting, raising and lowering. */
9b378208 12679
dfcf069d 12680void
f676886a
JB
12681x_focus_on_frame (f)
12682 struct frame *f;
dc6f92b8 12683{
1fb20991 12684#if 0 /* This proves to be unpleasant. */
f676886a 12685 x_raise_frame (f);
1fb20991 12686#endif
6d4238f3
JB
12687#if 0
12688 /* I don't think that the ICCCM allows programs to do things like this
12689 without the interaction of the window manager. Whatever you end up
f676886a 12690 doing with this code, do it to x_unfocus_frame too. */
334208b7 12691 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 12692 RevertToPointerRoot, CurrentTime);
c118dd06 12693#endif /* ! 0 */
dc6f92b8
JB
12694}
12695
dfcf069d 12696void
f676886a
JB
12697x_unfocus_frame (f)
12698 struct frame *f;
dc6f92b8 12699{
6d4238f3 12700#if 0
f676886a 12701 /* Look at the remarks in x_focus_on_frame. */
0f941935 12702 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 12703 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 12704 RevertToPointerRoot, CurrentTime);
c118dd06 12705#endif /* ! 0 */
dc6f92b8
JB
12706}
12707
f676886a 12708/* Raise frame F. */
dc6f92b8 12709
dfcf069d 12710void
f676886a
JB
12711x_raise_frame (f)
12712 struct frame *f;
dc6f92b8 12713{
3a88c238 12714 if (f->async_visible)
dc6f92b8
JB
12715 {
12716 BLOCK_INPUT;
3afe33e7 12717#ifdef USE_X_TOOLKIT
7556890b 12718 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12719#else /* not USE_X_TOOLKIT */
334208b7 12720 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12721#endif /* not USE_X_TOOLKIT */
334208b7 12722 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12723 UNBLOCK_INPUT;
12724 }
12725}
12726
f676886a 12727/* Lower frame F. */
dc6f92b8 12728
dfcf069d 12729void
f676886a
JB
12730x_lower_frame (f)
12731 struct frame *f;
dc6f92b8 12732{
3a88c238 12733 if (f->async_visible)
dc6f92b8
JB
12734 {
12735 BLOCK_INPUT;
3afe33e7 12736#ifdef USE_X_TOOLKIT
7556890b 12737 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12738#else /* not USE_X_TOOLKIT */
334208b7 12739 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12740#endif /* not USE_X_TOOLKIT */
334208b7 12741 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12742 UNBLOCK_INPUT;
12743 }
12744}
12745
dbc4e1c1 12746static void
6b0442dc 12747XTframe_raise_lower (f, raise_flag)
dbc4e1c1 12748 FRAME_PTR f;
6b0442dc 12749 int raise_flag;
dbc4e1c1 12750{
6b0442dc 12751 if (raise_flag)
dbc4e1c1
JB
12752 x_raise_frame (f);
12753 else
12754 x_lower_frame (f);
12755}
d047c4eb
KH
12756\f
12757/* Change of visibility. */
dc6f92b8 12758
9382638d
KH
12759/* This tries to wait until the frame is really visible.
12760 However, if the window manager asks the user where to position
12761 the frame, this will return before the user finishes doing that.
12762 The frame will not actually be visible at that time,
12763 but it will become visible later when the window manager
12764 finishes with it. */
12765
dfcf069d 12766void
f676886a
JB
12767x_make_frame_visible (f)
12768 struct frame *f;
dc6f92b8 12769{
990ba854 12770 Lisp_Object type;
1aa6072f 12771 int original_top, original_left;
31be9251
GM
12772 int retry_count = 2;
12773
12774 retry:
dc6f92b8 12775
dc6f92b8 12776 BLOCK_INPUT;
dc6f92b8 12777
990ba854
RS
12778 type = x_icon_type (f);
12779 if (!NILP (type))
12780 x_bitmap_icon (f, type);
bdcd49ba 12781
f676886a 12782 if (! FRAME_VISIBLE_P (f))
90e65f07 12783 {
1aa6072f
RS
12784 /* We test FRAME_GARBAGED_P here to make sure we don't
12785 call x_set_offset a second time
12786 if we get to x_make_frame_visible a second time
12787 before the window gets really visible. */
12788 if (! FRAME_ICONIFIED_P (f)
12789 && ! f->output_data.x->asked_for_visible)
12790 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12791
12792 f->output_data.x->asked_for_visible = 1;
12793
90e65f07 12794 if (! EQ (Vx_no_window_manager, Qt))
f676886a 12795 x_wm_set_window_state (f, NormalState);
3afe33e7 12796#ifdef USE_X_TOOLKIT
d7a38a2e 12797 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12798 XtMapWidget (f->output_data.x->widget);
3afe33e7 12799#else /* not USE_X_TOOLKIT */
7f9c7f94 12800 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12801#endif /* not USE_X_TOOLKIT */
0134a210
RS
12802#if 0 /* This seems to bring back scroll bars in the wrong places
12803 if the window configuration has changed. They seem
12804 to come back ok without this. */
ab648270 12805 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 12806 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 12807#endif
90e65f07 12808 }
dc6f92b8 12809
334208b7 12810 XFlush (FRAME_X_DISPLAY (f));
90e65f07 12811
0dacf791
RS
12812 /* Synchronize to ensure Emacs knows the frame is visible
12813 before we do anything else. We do this loop with input not blocked
12814 so that incoming events are handled. */
12815 {
12816 Lisp_Object frame;
12ce2351 12817 int count;
28c01ffe
RS
12818 /* This must be before UNBLOCK_INPUT
12819 since events that arrive in response to the actions above
12820 will set it when they are handled. */
12821 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
12822
12823 original_left = f->output_data.x->left_pos;
12824 original_top = f->output_data.x->top_pos;
c0a04927
RS
12825
12826 /* This must come after we set COUNT. */
12827 UNBLOCK_INPUT;
12828
2745e6c4 12829 /* We unblock here so that arriving X events are processed. */
1aa6072f 12830
dcb07ae9
RS
12831 /* Now move the window back to where it was "supposed to be".
12832 But don't do it if the gravity is negative.
12833 When the gravity is negative, this uses a position
28c01ffe
RS
12834 that is 3 pixels too low. Perhaps that's really the border width.
12835
12836 Don't do this if the window has never been visible before,
12837 because the window manager may choose the position
12838 and we don't want to override it. */
1aa6072f 12839
4d3f5d9a 12840 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 12841 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 12842 && previously_visible)
1aa6072f 12843 {
2745e6c4
RS
12844 Drawable rootw;
12845 int x, y;
12846 unsigned int width, height, border, depth;
06a2c219 12847
1aa6072f 12848 BLOCK_INPUT;
9829ddba 12849
06a2c219
GM
12850 /* On some window managers (such as FVWM) moving an existing
12851 window, even to the same place, causes the window manager
12852 to introduce an offset. This can cause the window to move
12853 to an unexpected location. Check the geometry (a little
12854 slow here) and then verify that the window is in the right
12855 place. If the window is not in the right place, move it
12856 there, and take the potential window manager hit. */
2745e6c4
RS
12857 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12858 &rootw, &x, &y, &width, &height, &border, &depth);
12859
12860 if (original_left != x || original_top != y)
12861 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12862 original_left, original_top);
12863
1aa6072f
RS
12864 UNBLOCK_INPUT;
12865 }
9829ddba 12866
e0c1aef2 12867 XSETFRAME (frame, f);
c0a04927 12868
12ce2351
GM
12869 /* Wait until the frame is visible. Process X events until a
12870 MapNotify event has been seen, or until we think we won't get a
12871 MapNotify at all.. */
12872 for (count = input_signal_count + 10;
12873 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 12874 {
12ce2351 12875 /* Force processing of queued events. */
334208b7 12876 x_sync (f);
12ce2351
GM
12877
12878 /* Machines that do polling rather than SIGIO have been
12879 observed to go into a busy-wait here. So we'll fake an
12880 alarm signal to let the handler know that there's something
12881 to be read. We used to raise a real alarm, but it seems
12882 that the handler isn't always enabled here. This is
12883 probably a bug. */
8b2f8d4e 12884 if (input_polling_used ())
3b2fa4e6 12885 {
12ce2351
GM
12886 /* It could be confusing if a real alarm arrives while
12887 processing the fake one. Turn it off and let the
12888 handler reset it. */
3e71d8f2 12889 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
12890 int old_poll_suppress_count = poll_suppress_count;
12891 poll_suppress_count = 1;
12892 poll_for_input_1 ();
12893 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 12894 }
12ce2351
GM
12895
12896 /* See if a MapNotify event has been processed. */
12897 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 12898 }
31be9251
GM
12899
12900 /* 2000-09-28: In
12901
12902 (let ((f (selected-frame)))
12903 (iconify-frame f)
12904 (raise-frame f))
12905
12906 the frame is not raised with various window managers on
12907 FreeBSD, Linux and Solaris. It turns out that, for some
12908 unknown reason, the call to XtMapWidget is completely ignored.
12909 Mapping the widget a second time works. */
12910
12911 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12912 goto retry;
0dacf791 12913 }
dc6f92b8
JB
12914}
12915
06a2c219 12916/* Change from mapped state to withdrawn state. */
dc6f92b8 12917
d047c4eb
KH
12918/* Make the frame visible (mapped and not iconified). */
12919
dfcf069d 12920void
f676886a
JB
12921x_make_frame_invisible (f)
12922 struct frame *f;
dc6f92b8 12923{
546e6d5b
RS
12924 Window window;
12925
12926#ifdef USE_X_TOOLKIT
12927 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 12928 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
12929#else /* not USE_X_TOOLKIT */
12930 window = FRAME_X_WINDOW (f);
12931#endif /* not USE_X_TOOLKIT */
dc6f92b8 12932
9319ae23 12933 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12934 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12935 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12936
5627c40e 12937#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 12938 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 12939 return;
5627c40e 12940#endif
dc6f92b8
JB
12941
12942 BLOCK_INPUT;
c118dd06 12943
af31d76f
RS
12944 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12945 that the current position of the window is user-specified, rather than
12946 program-specified, so that when the window is mapped again, it will be
12947 placed at the same location, without forcing the user to position it
12948 by hand again (they have already done that once for this window.) */
c32cdd9a 12949 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 12950
c118dd06
JB
12951#ifdef HAVE_X11R4
12952
334208b7
RS
12953 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12954 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
12955 {
12956 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12957 error ("Can't notify window manager of window withdrawal");
c118dd06 12958 }
c118dd06 12959#else /* ! defined (HAVE_X11R4) */
16bd92ea 12960
c118dd06 12961 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
12962 if (! EQ (Vx_no_window_manager, Qt))
12963 {
16bd92ea 12964 XEvent unmap;
dc6f92b8 12965
16bd92ea 12966 unmap.xunmap.type = UnmapNotify;
546e6d5b 12967 unmap.xunmap.window = window;
334208b7 12968 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 12969 unmap.xunmap.from_configure = False;
334208b7
RS
12970 if (! XSendEvent (FRAME_X_DISPLAY (f),
12971 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 12972 False,
06a2c219 12973 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
12974 &unmap))
12975 {
12976 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12977 error ("Can't notify window manager of withdrawal");
16bd92ea 12978 }
dc6f92b8
JB
12979 }
12980
16bd92ea 12981 /* Unmap the window ourselves. Cheeky! */
334208b7 12982 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 12983#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 12984
5627c40e
RS
12985 /* We can't distinguish this from iconification
12986 just by the event that we get from the server.
12987 So we can't win using the usual strategy of letting
12988 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12989 and synchronize with the server to make sure we agree. */
12990 f->visible = 0;
12991 FRAME_ICONIFIED_P (f) = 0;
12992 f->async_visible = 0;
12993 f->async_iconified = 0;
12994
334208b7 12995 x_sync (f);
5627c40e 12996
dc6f92b8
JB
12997 UNBLOCK_INPUT;
12998}
12999
06a2c219 13000/* Change window state from mapped to iconified. */
dc6f92b8 13001
dfcf069d 13002void
f676886a
JB
13003x_iconify_frame (f)
13004 struct frame *f;
dc6f92b8 13005{
3afe33e7 13006 int result;
990ba854 13007 Lisp_Object type;
dc6f92b8 13008
9319ae23 13009 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
13010 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
13011 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 13012
3a88c238 13013 if (f->async_iconified)
dc6f92b8
JB
13014 return;
13015
3afe33e7 13016 BLOCK_INPUT;
546e6d5b 13017
9af3143a
RS
13018 FRAME_SAMPLE_VISIBILITY (f);
13019
990ba854
RS
13020 type = x_icon_type (f);
13021 if (!NILP (type))
13022 x_bitmap_icon (f, type);
bdcd49ba
RS
13023
13024#ifdef USE_X_TOOLKIT
13025
546e6d5b
RS
13026 if (! FRAME_VISIBLE_P (f))
13027 {
13028 if (! EQ (Vx_no_window_manager, Qt))
13029 x_wm_set_window_state (f, IconicState);
13030 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 13031 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
13032 /* The server won't give us any event to indicate
13033 that an invisible frame was changed to an icon,
13034 so we have to record it here. */
13035 f->iconified = 1;
1e6bc770 13036 f->visible = 1;
9cf30a30 13037 f->async_iconified = 1;
1e6bc770 13038 f->async_visible = 0;
546e6d5b
RS
13039 UNBLOCK_INPUT;
13040 return;
13041 }
13042
334208b7 13043 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 13044 XtWindow (f->output_data.x->widget),
334208b7 13045 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
13046 UNBLOCK_INPUT;
13047
13048 if (!result)
546e6d5b 13049 error ("Can't notify window manager of iconification");
3afe33e7
RS
13050
13051 f->async_iconified = 1;
1e6bc770
RS
13052 f->async_visible = 0;
13053
8c002a25
KH
13054
13055 BLOCK_INPUT;
334208b7 13056 XFlush (FRAME_X_DISPLAY (f));
8c002a25 13057 UNBLOCK_INPUT;
3afe33e7
RS
13058#else /* not USE_X_TOOLKIT */
13059
fd13dbb2
RS
13060 /* Make sure the X server knows where the window should be positioned,
13061 in case the user deiconifies with the window manager. */
13062 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 13063 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 13064
16bd92ea
JB
13065 /* Since we don't know which revision of X we're running, we'll use both
13066 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
13067
13068 /* X11R4: send a ClientMessage to the window manager using the
13069 WM_CHANGE_STATE type. */
13070 {
13071 XEvent message;
58769bee 13072
c118dd06 13073 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 13074 message.xclient.type = ClientMessage;
334208b7 13075 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
13076 message.xclient.format = 32;
13077 message.xclient.data.l[0] = IconicState;
13078
334208b7
RS
13079 if (! XSendEvent (FRAME_X_DISPLAY (f),
13080 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
13081 False,
13082 SubstructureRedirectMask | SubstructureNotifyMask,
13083 &message))
dc6f92b8
JB
13084 {
13085 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 13086 error ("Can't notify window manager of iconification");
dc6f92b8 13087 }
16bd92ea 13088 }
dc6f92b8 13089
58769bee 13090 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
13091 IconicState. */
13092 x_wm_set_window_state (f, IconicState);
dc6f92b8 13093
a9c00105
RS
13094 if (!FRAME_VISIBLE_P (f))
13095 {
13096 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 13097 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
13098 }
13099
3a88c238 13100 f->async_iconified = 1;
1e6bc770 13101 f->async_visible = 0;
dc6f92b8 13102
334208b7 13103 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 13104 UNBLOCK_INPUT;
8c002a25 13105#endif /* not USE_X_TOOLKIT */
dc6f92b8 13106}
19f71add 13107
d047c4eb 13108\f
19f71add 13109/* Free X resources of frame F. */
dc6f92b8 13110
dfcf069d 13111void
19f71add 13112x_free_frame_resources (f)
f676886a 13113 struct frame *f;
dc6f92b8 13114{
7f9c7f94
RS
13115 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13116
dc6f92b8 13117 BLOCK_INPUT;
c0ff3fab 13118
6186a4a0
RS
13119 /* If a display connection is dead, don't try sending more
13120 commands to the X server. */
19f71add 13121 if (dpyinfo->display)
6186a4a0 13122 {
19f71add 13123 if (f->output_data.x->icon_desc)
6186a4a0 13124 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
19f71add 13125
31f41daf 13126#ifdef HAVE_X_I18N
f5d11644
GM
13127 if (FRAME_XIC (f))
13128 free_frame_xic (f);
31f41daf 13129#endif
19f71add 13130
2662734b 13131 if (FRAME_X_WINDOW (f))
19f71add
GM
13132 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
13133
3afe33e7 13134#ifdef USE_X_TOOLKIT
06a2c219 13135 if (f->output_data.x->widget)
30ca89f5
GM
13136 {
13137 XtDestroyWidget (f->output_data.x->widget);
13138 f->output_data.x->widget = NULL;
13139 }
6186a4a0 13140 free_frame_menubar (f);
3afe33e7
RS
13141#endif /* USE_X_TOOLKIT */
13142
3e71d8f2
GM
13143 unload_color (f, f->output_data.x->foreground_pixel);
13144 unload_color (f, f->output_data.x->background_pixel);
13145 unload_color (f, f->output_data.x->cursor_pixel);
13146 unload_color (f, f->output_data.x->cursor_foreground_pixel);
13147 unload_color (f, f->output_data.x->border_pixel);
13148 unload_color (f, f->output_data.x->mouse_pixel);
19f71add 13149
3e71d8f2
GM
13150 if (f->output_data.x->scroll_bar_background_pixel != -1)
13151 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
13152 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
13153 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
7c1bef7a
MB
13154#ifdef USE_TOOLKIT_SCROLL_BARS
13155 /* Scrollbar shadow colors. */
13156 if (f->output_data.x->scroll_bar_top_shadow_pixel != -1)
13157 unload_color (f, f->output_data.x->scroll_bar_top_shadow_pixel);
13158 if (f->output_data.x->scroll_bar_bottom_shadow_pixel != -1)
13159 unload_color (f, f->output_data.x->scroll_bar_bottom_shadow_pixel);
13160#endif /* USE_TOOLKIT_SCROLL_BARS */
3e71d8f2
GM
13161 if (f->output_data.x->white_relief.allocated_p)
13162 unload_color (f, f->output_data.x->white_relief.pixel);
13163 if (f->output_data.x->black_relief.allocated_p)
13164 unload_color (f, f->output_data.x->black_relief.pixel);
4ca78676 13165
19f71add
GM
13166 if (FRAME_FACE_CACHE (f))
13167 free_frame_faces (f);
13168
4ca78676 13169 x_free_gcs (f);
6186a4a0
RS
13170 XFlush (FRAME_X_DISPLAY (f));
13171 }
dc6f92b8 13172
df89d8a4 13173 if (f->output_data.x->saved_menu_event)
06a2c219 13174 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 13175
7556890b 13176 xfree (f->output_data.x);
19f71add
GM
13177 f->output_data.x = NULL;
13178
0f941935
KH
13179 if (f == dpyinfo->x_focus_frame)
13180 dpyinfo->x_focus_frame = 0;
13181 if (f == dpyinfo->x_focus_event_frame)
13182 dpyinfo->x_focus_event_frame = 0;
13183 if (f == dpyinfo->x_highlight_frame)
13184 dpyinfo->x_highlight_frame = 0;
c0ff3fab 13185
7f9c7f94 13186 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 13187 {
7f9c7f94
RS
13188 dpyinfo->mouse_face_beg_row
13189 = dpyinfo->mouse_face_beg_col = -1;
13190 dpyinfo->mouse_face_end_row
13191 = dpyinfo->mouse_face_end_col = -1;
13192 dpyinfo->mouse_face_window = Qnil;
21323706
RS
13193 dpyinfo->mouse_face_deferred_gc = 0;
13194 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 13195 }
0134a210 13196
c0ff3fab 13197 UNBLOCK_INPUT;
dc6f92b8 13198}
19f71add
GM
13199
13200
13201/* Destroy the X window of frame F. */
13202
13203void
13204x_destroy_window (f)
13205 struct frame *f;
13206{
13207 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13208
13209 /* If a display connection is dead, don't try sending more
13210 commands to the X server. */
13211 if (dpyinfo->display != 0)
13212 x_free_frame_resources (f);
13213
13214 dpyinfo->reference_count--;
13215}
13216
dc6f92b8 13217\f
f451eb13
JB
13218/* Setting window manager hints. */
13219
af31d76f
RS
13220/* Set the normal size hints for the window manager, for frame F.
13221 FLAGS is the flags word to use--or 0 meaning preserve the flags
13222 that the window now has.
13223 If USER_POSITION is nonzero, we set the USPosition
13224 flag (this is useful when FLAGS is 0). */
6dba1858 13225
dfcf069d 13226void
af31d76f 13227x_wm_set_size_hint (f, flags, user_position)
f676886a 13228 struct frame *f;
af31d76f
RS
13229 long flags;
13230 int user_position;
dc6f92b8
JB
13231{
13232 XSizeHints size_hints;
3afe33e7
RS
13233
13234#ifdef USE_X_TOOLKIT
7e4f2521
FP
13235 Arg al[2];
13236 int ac = 0;
13237 Dimension widget_width, widget_height;
7556890b 13238 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 13239#else /* not USE_X_TOOLKIT */
c118dd06 13240 Window window = FRAME_X_WINDOW (f);
3afe33e7 13241#endif /* not USE_X_TOOLKIT */
dc6f92b8 13242
b72a58fd
RS
13243 /* Setting PMaxSize caused various problems. */
13244 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 13245
7556890b
RS
13246 size_hints.x = f->output_data.x->left_pos;
13247 size_hints.y = f->output_data.x->top_pos;
7553a6b7 13248
7e4f2521
FP
13249#ifdef USE_X_TOOLKIT
13250 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
13251 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 13252 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
13253 size_hints.height = widget_height;
13254 size_hints.width = widget_width;
13255#else /* not USE_X_TOOLKIT */
f676886a
JB
13256 size_hints.height = PIXEL_HEIGHT (f);
13257 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 13258#endif /* not USE_X_TOOLKIT */
7553a6b7 13259
7556890b
RS
13260 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
13261 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
13262 size_hints.max_width
13263 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
13264 size_hints.max_height
13265 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 13266
d067ea8b
KH
13267 /* Calculate the base and minimum sizes.
13268
13269 (When we use the X toolkit, we don't do it here.
13270 Instead we copy the values that the widgets are using, below.) */
13271#ifndef USE_X_TOOLKIT
b1c884c3 13272 {
b0342f17 13273 int base_width, base_height;
0134a210 13274 int min_rows = 0, min_cols = 0;
b0342f17 13275
f451eb13
JB
13276 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
13277 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 13278
0134a210 13279 check_frame_size (f, &min_rows, &min_cols);
b0342f17 13280
0134a210
RS
13281 /* The window manager uses the base width hints to calculate the
13282 current number of rows and columns in the frame while
13283 resizing; min_width and min_height aren't useful for this
13284 purpose, since they might not give the dimensions for a
13285 zero-row, zero-column frame.
58769bee 13286
0134a210
RS
13287 We use the base_width and base_height members if we have
13288 them; otherwise, we set the min_width and min_height members
13289 to the size for a zero x zero frame. */
b0342f17
JB
13290
13291#ifdef HAVE_X11R4
0134a210
RS
13292 size_hints.flags |= PBaseSize;
13293 size_hints.base_width = base_width;
13294 size_hints.base_height = base_height;
13295 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
13296 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 13297#else
0134a210
RS
13298 size_hints.min_width = base_width;
13299 size_hints.min_height = base_height;
b0342f17 13300#endif
b1c884c3 13301 }
dc6f92b8 13302
d067ea8b 13303 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 13304 if (flags)
dc6f92b8 13305 {
d067ea8b
KH
13306 size_hints.flags |= flags;
13307 goto no_read;
13308 }
13309#endif /* not USE_X_TOOLKIT */
13310
13311 {
13312 XSizeHints hints; /* Sometimes I hate X Windows... */
13313 long supplied_return;
13314 int value;
af31d76f
RS
13315
13316#ifdef HAVE_X11R4
d067ea8b
KH
13317 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
13318 &supplied_return);
af31d76f 13319#else
d067ea8b 13320 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 13321#endif
58769bee 13322
d067ea8b
KH
13323#ifdef USE_X_TOOLKIT
13324 size_hints.base_height = hints.base_height;
13325 size_hints.base_width = hints.base_width;
13326 size_hints.min_height = hints.min_height;
13327 size_hints.min_width = hints.min_width;
13328#endif
13329
13330 if (flags)
13331 size_hints.flags |= flags;
13332 else
13333 {
13334 if (value == 0)
13335 hints.flags = 0;
13336 if (hints.flags & PSize)
13337 size_hints.flags |= PSize;
13338 if (hints.flags & PPosition)
13339 size_hints.flags |= PPosition;
13340 if (hints.flags & USPosition)
13341 size_hints.flags |= USPosition;
13342 if (hints.flags & USSize)
13343 size_hints.flags |= USSize;
13344 }
13345 }
13346
06a2c219 13347#ifndef USE_X_TOOLKIT
d067ea8b 13348 no_read:
06a2c219 13349#endif
0134a210 13350
af31d76f 13351#ifdef PWinGravity
7556890b 13352 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 13353 size_hints.flags |= PWinGravity;
dc05a16b 13354
af31d76f 13355 if (user_position)
6dba1858 13356 {
af31d76f
RS
13357 size_hints.flags &= ~ PPosition;
13358 size_hints.flags |= USPosition;
6dba1858 13359 }
2554751d 13360#endif /* PWinGravity */
6dba1858 13361
b0342f17 13362#ifdef HAVE_X11R4
334208b7 13363 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 13364#else
334208b7 13365 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 13366#endif
dc6f92b8
JB
13367}
13368
13369/* Used for IconicState or NormalState */
06a2c219 13370
dfcf069d 13371void
f676886a
JB
13372x_wm_set_window_state (f, state)
13373 struct frame *f;
dc6f92b8
JB
13374 int state;
13375{
3afe33e7 13376#ifdef USE_X_TOOLKIT
546e6d5b
RS
13377 Arg al[1];
13378
13379 XtSetArg (al[0], XtNinitialState, state);
7556890b 13380 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 13381#else /* not USE_X_TOOLKIT */
c118dd06 13382 Window window = FRAME_X_WINDOW (f);
dc6f92b8 13383
7556890b
RS
13384 f->output_data.x->wm_hints.flags |= StateHint;
13385 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 13386
7556890b 13387 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 13388#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
13389}
13390
dfcf069d 13391void
7f2ae036 13392x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 13393 struct frame *f;
7f2ae036 13394 int pixmap_id;
dc6f92b8 13395{
d2bd6bc4
RS
13396 Pixmap icon_pixmap;
13397
06a2c219 13398#ifndef USE_X_TOOLKIT
c118dd06 13399 Window window = FRAME_X_WINDOW (f);
75231bad 13400#endif
dc6f92b8 13401
7f2ae036 13402 if (pixmap_id > 0)
dbc4e1c1 13403 {
d2bd6bc4 13404 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 13405 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
13406 }
13407 else
68568555
RS
13408 {
13409 /* It seems there is no way to turn off use of an icon pixmap.
13410 The following line does it, only if no icon has yet been created,
13411 for some window managers. But with mwm it crashes.
13412 Some people say it should clear the IconPixmapHint bit in this case,
13413 but that doesn't work, and the X consortium said it isn't the
13414 right thing at all. Since there is no way to win,
13415 best to explicitly give up. */
13416#if 0
13417 f->output_data.x->wm_hints.icon_pixmap = None;
13418#else
13419 return;
13420#endif
13421 }
b1c884c3 13422
d2bd6bc4
RS
13423#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
13424
13425 {
13426 Arg al[1];
13427 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
13428 XtSetValues (f->output_data.x->widget, al, 1);
13429 }
13430
13431#else /* not USE_X_TOOLKIT */
13432
7556890b
RS
13433 f->output_data.x->wm_hints.flags |= IconPixmapHint;
13434 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
13435
13436#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
13437}
13438
dfcf069d 13439void
f676886a
JB
13440x_wm_set_icon_position (f, icon_x, icon_y)
13441 struct frame *f;
dc6f92b8
JB
13442 int icon_x, icon_y;
13443{
75231bad 13444#ifdef USE_X_TOOLKIT
7556890b 13445 Window window = XtWindow (f->output_data.x->widget);
75231bad 13446#else
c118dd06 13447 Window window = FRAME_X_WINDOW (f);
75231bad 13448#endif
dc6f92b8 13449
7556890b
RS
13450 f->output_data.x->wm_hints.flags |= IconPositionHint;
13451 f->output_data.x->wm_hints.icon_x = icon_x;
13452 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 13453
7556890b 13454 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
13455}
13456
13457\f
06a2c219
GM
13458/***********************************************************************
13459 Fonts
13460 ***********************************************************************/
dc43ef94
KH
13461
13462/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 13463
dc43ef94
KH
13464struct font_info *
13465x_get_font_info (f, font_idx)
13466 FRAME_PTR f;
13467 int font_idx;
13468{
13469 return (FRAME_X_FONT_TABLE (f) + font_idx);
13470}
13471
13472
9c11f79e
GM
13473/* Return a list of names of available fonts matching PATTERN on frame F.
13474
13475 If SIZE is > 0, it is the size (maximum bounds width) of fonts
13476 to be listed.
13477
13478 SIZE < 0 means include scalable fonts.
13479
13480 Frame F null means we have not yet created any frame on X, and
13481 consult the first display in x_display_list. MAXNAMES sets a limit
13482 on how many fonts to match. */
dc43ef94
KH
13483
13484Lisp_Object
13485x_list_fonts (f, pattern, size, maxnames)
9c11f79e 13486 struct frame *f;
dc43ef94
KH
13487 Lisp_Object pattern;
13488 int size;
13489 int maxnames;
13490{
06a2c219
GM
13491 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
13492 Lisp_Object tem, second_best;
9c11f79e
GM
13493 struct x_display_info *dpyinfo
13494 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13495 Display *dpy = dpyinfo->display;
09c6077f 13496 int try_XLoadQueryFont = 0;
53ca4657 13497 int count;
9c11f79e
GM
13498 int allow_scalable_fonts_p = 0;
13499
13500 if (size < 0)
13501 {
13502 allow_scalable_fonts_p = 1;
13503 size = 0;
13504 }
dc43ef94 13505
6b0efe73 13506 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
13507 if (NILP (patterns))
13508 patterns = Fcons (pattern, Qnil);
81ba44e5 13509
09c6077f
KH
13510 if (maxnames == 1 && !size)
13511 /* We can return any single font matching PATTERN. */
13512 try_XLoadQueryFont = 1;
9a32686f 13513
8e713be6 13514 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 13515 {
dc43ef94 13516 int num_fonts;
3e71d8f2 13517 char **names = NULL;
dc43ef94 13518
8e713be6 13519 pattern = XCAR (patterns);
536f4067
RS
13520 /* See if we cached the result for this particular query.
13521 The cache is an alist of the form:
9c11f79e
GM
13522 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13523 tem = XCDR (dpyinfo->name_list_element);
13524 key = Fcons (Fcons (pattern, make_number (maxnames)),
13525 allow_scalable_fonts_p ? Qt : Qnil);
13526 list = Fassoc (key, tem);
13527 if (!NILP (list))
b5210ea7
KH
13528 {
13529 list = Fcdr_safe (list);
13530 /* We have a cashed list. Don't have to get the list again. */
13531 goto label_cached;
13532 }
13533
13534 /* At first, put PATTERN in the cache. */
09c6077f 13535
dc43ef94 13536 BLOCK_INPUT;
17d85edc
KH
13537 count = x_catch_errors (dpy);
13538
09c6077f
KH
13539 if (try_XLoadQueryFont)
13540 {
13541 XFontStruct *font;
13542 unsigned long value;
13543
13544 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
13545 if (x_had_errors_p (dpy))
13546 {
13547 /* This error is perhaps due to insufficient memory on X
13548 server. Let's just ignore it. */
13549 font = NULL;
13550 x_clear_errors (dpy);
13551 }
13552
09c6077f
KH
13553 if (font
13554 && XGetFontProperty (font, XA_FONT, &value))
13555 {
13556 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13557 int len = strlen (name);
01c752b5 13558 char *tmp;
09c6077f 13559
6f6512e8
KH
13560 /* If DXPC (a Differential X Protocol Compressor)
13561 Ver.3.7 is running, XGetAtomName will return null
13562 string. We must avoid such a name. */
13563 if (len == 0)
13564 try_XLoadQueryFont = 0;
13565 else
13566 {
13567 num_fonts = 1;
13568 names = (char **) alloca (sizeof (char *));
13569 /* Some systems only allow alloca assigned to a
13570 simple var. */
13571 tmp = (char *) alloca (len + 1); names[0] = tmp;
13572 bcopy (name, names[0], len + 1);
13573 XFree (name);
13574 }
09c6077f
KH
13575 }
13576 else
13577 try_XLoadQueryFont = 0;
a083fd23
RS
13578
13579 if (font)
13580 XFreeFont (dpy, font);
09c6077f
KH
13581 }
13582
13583 if (!try_XLoadQueryFont)
17d85edc
KH
13584 {
13585 /* We try at least 10 fonts because XListFonts will return
13586 auto-scaled fonts at the head. */
13587 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13588 &num_fonts);
13589 if (x_had_errors_p (dpy))
13590 {
13591 /* This error is perhaps due to insufficient memory on X
13592 server. Let's just ignore it. */
13593 names = NULL;
13594 x_clear_errors (dpy);
13595 }
13596 }
13597
13598 x_uncatch_errors (dpy, count);
dc43ef94
KH
13599 UNBLOCK_INPUT;
13600
13601 if (names)
13602 {
13603 int i;
dc43ef94
KH
13604
13605 /* Make a list of all the fonts we got back.
13606 Store that in the font cache for the display. */
13607 for (i = 0; i < num_fonts; i++)
13608 {
06a2c219 13609 int width = 0;
dc43ef94 13610 char *p = names[i];
06a2c219
GM
13611 int average_width = -1, dashes = 0;
13612
dc43ef94 13613 /* Count the number of dashes in NAMES[I]. If there are
9c11f79e
GM
13614 14 dashes, and the field value following 12th dash
13615 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13616 is usually too ugly to be used for editing. Let's
13617 ignore it. */
dc43ef94
KH
13618 while (*p)
13619 if (*p++ == '-')
13620 {
13621 dashes++;
13622 if (dashes == 7) /* PIXEL_SIZE field */
13623 width = atoi (p);
13624 else if (dashes == 12) /* AVERAGE_WIDTH field */
13625 average_width = atoi (p);
13626 }
9c11f79e
GM
13627
13628 if (allow_scalable_fonts_p
13629 || dashes < 14 || average_width != 0)
dc43ef94
KH
13630 {
13631 tem = build_string (names[i]);
13632 if (NILP (Fassoc (tem, list)))
13633 {
13634 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
13635 && ((fast_c_string_match_ignore_case
13636 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
13637 >= 0))
13638 /* We can set the value of PIXEL_SIZE to the
b5210ea7 13639 width of this font. */
dc43ef94
KH
13640 list = Fcons (Fcons (tem, make_number (width)), list);
13641 else
13642 /* For the moment, width is not known. */
13643 list = Fcons (Fcons (tem, Qnil), list);
13644 }
13645 }
13646 }
e38f4136 13647
09c6077f 13648 if (!try_XLoadQueryFont)
e38f4136
GM
13649 {
13650 BLOCK_INPUT;
13651 XFreeFontNames (names);
13652 UNBLOCK_INPUT;
13653 }
dc43ef94
KH
13654 }
13655
b5210ea7 13656 /* Now store the result in the cache. */
f3fbd155
KR
13657 XSETCDR (dpyinfo->name_list_element,
13658 Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element)));
dc43ef94 13659
b5210ea7
KH
13660 label_cached:
13661 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 13662
b5210ea7
KH
13663 newlist = second_best = Qnil;
13664 /* Make a list of the fonts that have the right width. */
8e713be6 13665 for (; CONSP (list); list = XCDR (list))
b5210ea7 13666 {
536f4067
RS
13667 int found_size;
13668
8e713be6 13669 tem = XCAR (list);
dc43ef94 13670
8e713be6 13671 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
13672 continue;
13673 if (!size)
13674 {
8e713be6 13675 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
13676 continue;
13677 }
dc43ef94 13678
8e713be6 13679 if (!INTEGERP (XCDR (tem)))
dc43ef94 13680 {
b5210ea7 13681 /* Since we have not yet known the size of this font, we
9c11f79e 13682 must try slow function call XLoadQueryFont. */
dc43ef94
KH
13683 XFontStruct *thisinfo;
13684
13685 BLOCK_INPUT;
17d85edc 13686 count = x_catch_errors (dpy);
dc43ef94 13687 thisinfo = XLoadQueryFont (dpy,
8e713be6 13688 XSTRING (XCAR (tem))->data);
17d85edc
KH
13689 if (x_had_errors_p (dpy))
13690 {
13691 /* This error is perhaps due to insufficient memory on X
13692 server. Let's just ignore it. */
13693 thisinfo = NULL;
13694 x_clear_errors (dpy);
13695 }
13696 x_uncatch_errors (dpy, count);
dc43ef94
KH
13697 UNBLOCK_INPUT;
13698
13699 if (thisinfo)
13700 {
f3fbd155
KR
13701 XSETCDR (tem,
13702 (thisinfo->min_bounds.width == 0
13703 ? make_number (0)
13704 : make_number (thisinfo->max_bounds.width)));
e38f4136 13705 BLOCK_INPUT;
dc43ef94 13706 XFreeFont (dpy, thisinfo);
e38f4136 13707 UNBLOCK_INPUT;
dc43ef94
KH
13708 }
13709 else
b5210ea7 13710 /* For unknown reason, the previous call of XListFont had
06a2c219 13711 returned a font which can't be opened. Record the size
b5210ea7 13712 as 0 not to try to open it again. */
f3fbd155 13713 XSETCDR (tem, make_number (0));
dc43ef94 13714 }
536f4067 13715
8e713be6 13716 found_size = XINT (XCDR (tem));
536f4067 13717 if (found_size == size)
8e713be6 13718 newlist = Fcons (XCAR (tem), newlist);
536f4067 13719 else if (found_size > 0)
b5210ea7 13720 {
536f4067 13721 if (NILP (second_best))
b5210ea7 13722 second_best = tem;
536f4067
RS
13723 else if (found_size < size)
13724 {
8e713be6
KR
13725 if (XINT (XCDR (second_best)) > size
13726 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
13727 second_best = tem;
13728 }
13729 else
13730 {
8e713be6
KR
13731 if (XINT (XCDR (second_best)) > size
13732 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
13733 second_best = tem;
13734 }
b5210ea7
KH
13735 }
13736 }
13737 if (!NILP (newlist))
13738 break;
13739 else if (!NILP (second_best))
13740 {
8e713be6 13741 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 13742 break;
dc43ef94 13743 }
dc43ef94
KH
13744 }
13745
13746 return newlist;
13747}
13748
06a2c219
GM
13749
13750#if GLYPH_DEBUG
13751
13752/* Check that FONT is valid on frame F. It is if it can be found in F's
13753 font table. */
13754
13755static void
13756x_check_font (f, font)
13757 struct frame *f;
13758 XFontStruct *font;
13759{
13760 int i;
13761 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13762
13763 xassert (font != NULL);
13764
13765 for (i = 0; i < dpyinfo->n_fonts; i++)
13766 if (dpyinfo->font_table[i].name
13767 && font == dpyinfo->font_table[i].font)
13768 break;
13769
13770 xassert (i < dpyinfo->n_fonts);
13771}
13772
13773#endif /* GLYPH_DEBUG != 0 */
13774
13775/* Set *W to the minimum width, *H to the minimum font height of FONT.
13776 Note: There are (broken) X fonts out there with invalid XFontStruct
13777 min_bounds contents. For example, handa@etl.go.jp reports that
13778 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13779 have font->min_bounds.width == 0. */
13780
13781static INLINE void
13782x_font_min_bounds (font, w, h)
13783 XFontStruct *font;
13784 int *w, *h;
13785{
13786 *h = FONT_HEIGHT (font);
13787 *w = font->min_bounds.width;
13788
13789 /* Try to handle the case where FONT->min_bounds has invalid
13790 contents. Since the only font known to have invalid min_bounds
13791 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13792 if (*w <= 0)
13793 *w = font->max_bounds.width;
13794}
13795
13796
13797/* Compute the smallest character width and smallest font height over
13798 all fonts available on frame F. Set the members smallest_char_width
13799 and smallest_font_height in F's x_display_info structure to
13800 the values computed. Value is non-zero if smallest_font_height or
13801 smallest_char_width become smaller than they were before. */
13802
13803static int
13804x_compute_min_glyph_bounds (f)
13805 struct frame *f;
13806{
13807 int i;
13808 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13809 XFontStruct *font;
13810 int old_width = dpyinfo->smallest_char_width;
13811 int old_height = dpyinfo->smallest_font_height;
13812
13813 dpyinfo->smallest_font_height = 100000;
13814 dpyinfo->smallest_char_width = 100000;
13815
13816 for (i = 0; i < dpyinfo->n_fonts; ++i)
13817 if (dpyinfo->font_table[i].name)
13818 {
13819 struct font_info *fontp = dpyinfo->font_table + i;
13820 int w, h;
13821
13822 font = (XFontStruct *) fontp->font;
13823 xassert (font != (XFontStruct *) ~0);
13824 x_font_min_bounds (font, &w, &h);
13825
13826 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13827 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13828 }
13829
13830 xassert (dpyinfo->smallest_char_width > 0
13831 && dpyinfo->smallest_font_height > 0);
13832
13833 return (dpyinfo->n_fonts == 1
13834 || dpyinfo->smallest_char_width < old_width
13835 || dpyinfo->smallest_font_height < old_height);
13836}
13837
13838
dc43ef94
KH
13839/* Load font named FONTNAME of the size SIZE for frame F, and return a
13840 pointer to the structure font_info while allocating it dynamically.
13841 If SIZE is 0, load any size of font.
13842 If loading is failed, return NULL. */
13843
13844struct font_info *
13845x_load_font (f, fontname, size)
13846 struct frame *f;
13847 register char *fontname;
13848 int size;
13849{
13850 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13851 Lisp_Object font_names;
d645aaa4 13852 int count;
dc43ef94
KH
13853
13854 /* Get a list of all the fonts that match this name. Once we
13855 have a list of matching fonts, we compare them against the fonts
13856 we already have by comparing names. */
09c6077f 13857 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
13858
13859 if (!NILP (font_names))
13860 {
13861 Lisp_Object tail;
13862 int i;
13863
13864 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 13865 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
13866 if (dpyinfo->font_table[i].name
13867 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 13868 XSTRING (XCAR (tail))->data)
06a2c219 13869 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 13870 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
13871 return (dpyinfo->font_table + i);
13872 }
13873
13874 /* Load the font and add it to the table. */
13875 {
13876 char *full_name;
13877 XFontStruct *font;
13878 struct font_info *fontp;
13879 unsigned long value;
06a2c219 13880 int i;
dc43ef94 13881
2da424f1
KH
13882 /* If we have found fonts by x_list_font, load one of them. If
13883 not, we still try to load a font by the name given as FONTNAME
13884 because XListFonts (called in x_list_font) of some X server has
13885 a bug of not finding a font even if the font surely exists and
13886 is loadable by XLoadQueryFont. */
e1d6d5b9 13887 if (size > 0 && !NILP (font_names))
8e713be6 13888 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
13889
13890 BLOCK_INPUT;
d645aaa4 13891 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 13892 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
13893 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13894 {
13895 /* This error is perhaps due to insufficient memory on X
13896 server. Let's just ignore it. */
13897 font = NULL;
13898 x_clear_errors (FRAME_X_DISPLAY (f));
13899 }
13900 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 13901 UNBLOCK_INPUT;
b5210ea7 13902 if (!font)
dc43ef94
KH
13903 return NULL;
13904
06a2c219
GM
13905 /* Find a free slot in the font table. */
13906 for (i = 0; i < dpyinfo->n_fonts; ++i)
13907 if (dpyinfo->font_table[i].name == NULL)
13908 break;
13909
13910 /* If no free slot found, maybe enlarge the font table. */
13911 if (i == dpyinfo->n_fonts
13912 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 13913 {
06a2c219
GM
13914 int sz;
13915 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13916 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 13917 dpyinfo->font_table
06a2c219 13918 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
13919 }
13920
06a2c219
GM
13921 fontp = dpyinfo->font_table + i;
13922 if (i == dpyinfo->n_fonts)
13923 ++dpyinfo->n_fonts;
dc43ef94
KH
13924
13925 /* Now fill in the slots of *FONTP. */
13926 BLOCK_INPUT;
13927 fontp->font = font;
06a2c219 13928 fontp->font_idx = i;
dc43ef94
KH
13929 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13930 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13931
13932 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13933 full_name = 0;
13934 if (XGetFontProperty (font, XA_FONT, &value))
13935 {
13936 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13937 char *p = name;
13938 int dashes = 0;
13939
13940 /* Count the number of dashes in the "full name".
13941 If it is too few, this isn't really the font's full name,
13942 so don't use it.
13943 In X11R4, the fonts did not come with their canonical names
13944 stored in them. */
13945 while (*p)
13946 {
13947 if (*p == '-')
13948 dashes++;
13949 p++;
13950 }
13951
13952 if (dashes >= 13)
13953 {
13954 full_name = (char *) xmalloc (p - name + 1);
13955 bcopy (name, full_name, p - name + 1);
13956 }
13957
13958 XFree (name);
13959 }
13960
13961 if (full_name != 0)
13962 fontp->full_name = full_name;
13963 else
13964 fontp->full_name = fontp->name;
13965
13966 fontp->size = font->max_bounds.width;
d5749adb 13967 fontp->height = FONT_HEIGHT (font);
dc43ef94 13968
2da424f1
KH
13969 if (NILP (font_names))
13970 {
13971 /* We come here because of a bug of XListFonts mentioned at
13972 the head of this block. Let's store this information in
13973 the cache for x_list_fonts. */
13974 Lisp_Object lispy_name = build_string (fontname);
13975 Lisp_Object lispy_full_name = build_string (fontp->full_name);
9c11f79e
GM
13976 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13977 Qnil);
2da424f1 13978
f3fbd155
KR
13979 XSETCDR (dpyinfo->name_list_element,
13980 Fcons (Fcons (key,
13981 Fcons (Fcons (lispy_full_name,
13982 make_number (fontp->size)),
13983 Qnil)),
13984 XCDR (dpyinfo->name_list_element)));
2da424f1 13985 if (full_name)
9c11f79e
GM
13986 {
13987 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13988 Qnil);
f3fbd155
KR
13989 XSETCDR (dpyinfo->name_list_element,
13990 Fcons (Fcons (key,
13991 Fcons (Fcons (lispy_full_name,
13992 make_number (fontp->size)),
13993 Qnil)),
13994 XCDR (dpyinfo->name_list_element)));
9c11f79e 13995 }
2da424f1
KH
13996 }
13997
dc43ef94
KH
13998 /* The slot `encoding' specifies how to map a character
13999 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
14000 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
14001 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 14002 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 14003 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
14004 which is never used by any charset. If mapping can't be
14005 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
14006 fontp->encoding[1]
14007 = (font->max_byte1 == 0
14008 /* 1-byte font */
14009 ? (font->min_char_or_byte2 < 0x80
14010 ? (font->max_char_or_byte2 < 0x80
14011 ? 0 /* 0x20..0x7F */
8ff102bd 14012 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
14013 : 1) /* 0xA0..0xFF */
14014 /* 2-byte font */
14015 : (font->min_byte1 < 0x80
14016 ? (font->max_byte1 < 0x80
14017 ? (font->min_char_or_byte2 < 0x80
14018 ? (font->max_char_or_byte2 < 0x80
14019 ? 0 /* 0x2020..0x7F7F */
8ff102bd 14020 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 14021 : 3) /* 0x20A0..0x7FFF */
8ff102bd 14022 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
14023 : (font->min_char_or_byte2 < 0x80
14024 ? (font->max_char_or_byte2 < 0x80
14025 ? 2 /* 0xA020..0xFF7F */
8ff102bd 14026 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
14027 : 1))); /* 0xA0A0..0xFFFF */
14028
14029 fontp->baseline_offset
14030 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
14031 ? (long) value : 0);
14032 fontp->relative_compose
14033 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
14034 ? (long) value : 0);
f78798df
KH
14035 fontp->default_ascent
14036 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
14037 ? (long) value : 0);
dc43ef94 14038
06a2c219
GM
14039 /* Set global flag fonts_changed_p to non-zero if the font loaded
14040 has a character with a smaller width than any other character
14041 before, or if the font loaded has a smalle>r height than any
14042 other font loaded before. If this happens, it will make a
14043 glyph matrix reallocation necessary. */
14044 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 14045 UNBLOCK_INPUT;
dc43ef94
KH
14046 return fontp;
14047 }
14048}
14049
06a2c219
GM
14050
14051/* Return a pointer to struct font_info of a font named FONTNAME for
14052 frame F. If no such font is loaded, return NULL. */
14053
dc43ef94
KH
14054struct font_info *
14055x_query_font (f, fontname)
14056 struct frame *f;
14057 register char *fontname;
14058{
14059 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
14060 int i;
14061
14062 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
14063 if (dpyinfo->font_table[i].name
14064 && (!strcmp (dpyinfo->font_table[i].name, fontname)
14065 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
14066 return (dpyinfo->font_table + i);
14067 return NULL;
14068}
14069
06a2c219
GM
14070
14071/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
14072 `encoder' of the structure. */
14073
14074void
14075x_find_ccl_program (fontp)
14076 struct font_info *fontp;
14077{
a42f54e6 14078 Lisp_Object list, elt;
a6582676 14079
f9b5db02 14080 elt = Qnil;
8e713be6 14081 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 14082 {
8e713be6 14083 elt = XCAR (list);
a6582676 14084 if (CONSP (elt)
8e713be6 14085 && STRINGP (XCAR (elt))
9f2feff6
KH
14086 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
14087 >= 0)
14088 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
14089 >= 0)))
a42f54e6
KH
14090 break;
14091 }
f9b5db02 14092
a42f54e6
KH
14093 if (! NILP (list))
14094 {
d27f8ca7
KH
14095 struct ccl_program *ccl
14096 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 14097
8e713be6 14098 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
14099 xfree (ccl);
14100 else
14101 fontp->font_encoder = ccl;
a6582676
KH
14102 }
14103}
14104
06a2c219 14105
dc43ef94 14106\f
06a2c219
GM
14107/***********************************************************************
14108 Initialization
14109 ***********************************************************************/
f451eb13 14110
3afe33e7
RS
14111#ifdef USE_X_TOOLKIT
14112static XrmOptionDescRec emacs_options[] = {
14113 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
14114 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
14115
14116 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
14117 XrmoptionSepArg, NULL},
14118 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
14119
14120 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14121 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14122 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
14123 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14124 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
14125 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
14126 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
14127};
14128#endif /* USE_X_TOOLKIT */
14129
7a13e894
RS
14130static int x_initialized;
14131
29b38361
KH
14132#ifdef MULTI_KBOARD
14133/* Test whether two display-name strings agree up to the dot that separates
14134 the screen number from the server number. */
14135static int
14136same_x_server (name1, name2)
14137 char *name1, *name2;
14138{
14139 int seen_colon = 0;
cf591cc1
RS
14140 unsigned char *system_name = XSTRING (Vsystem_name)->data;
14141 int system_name_length = strlen (system_name);
14142 int length_until_period = 0;
14143
14144 while (system_name[length_until_period] != 0
14145 && system_name[length_until_period] != '.')
14146 length_until_period++;
14147
14148 /* Treat `unix' like an empty host name. */
14149 if (! strncmp (name1, "unix:", 5))
14150 name1 += 4;
14151 if (! strncmp (name2, "unix:", 5))
14152 name2 += 4;
14153 /* Treat this host's name like an empty host name. */
14154 if (! strncmp (name1, system_name, system_name_length)
14155 && name1[system_name_length] == ':')
14156 name1 += system_name_length;
14157 if (! strncmp (name2, system_name, system_name_length)
14158 && name2[system_name_length] == ':')
14159 name2 += system_name_length;
14160 /* Treat this host's domainless name like an empty host name. */
14161 if (! strncmp (name1, system_name, length_until_period)
14162 && name1[length_until_period] == ':')
14163 name1 += length_until_period;
14164 if (! strncmp (name2, system_name, length_until_period)
14165 && name2[length_until_period] == ':')
14166 name2 += length_until_period;
14167
29b38361
KH
14168 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
14169 {
14170 if (*name1 == ':')
14171 seen_colon++;
14172 if (seen_colon && *name1 == '.')
14173 return 1;
14174 }
14175 return (seen_colon
14176 && (*name1 == '.' || *name1 == '\0')
14177 && (*name2 == '.' || *name2 == '\0'));
14178}
14179#endif
14180
334208b7 14181struct x_display_info *
1f8255f2 14182x_term_init (display_name, xrm_option, resource_name)
334208b7 14183 Lisp_Object display_name;
1f8255f2
RS
14184 char *xrm_option;
14185 char *resource_name;
dc6f92b8 14186{
334208b7 14187 int connection;
7a13e894 14188 Display *dpy;
334208b7
RS
14189 struct x_display_info *dpyinfo;
14190 XrmDatabase xrdb;
14191
60439948
KH
14192 BLOCK_INPUT;
14193
7a13e894
RS
14194 if (!x_initialized)
14195 {
14196 x_initialize ();
14197 x_initialized = 1;
14198 }
dc6f92b8 14199
3afe33e7 14200#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
14201 /* weiner@footloose.sps.mot.com reports that this causes
14202 errors with X11R5:
14203 X protocol error: BadAtom (invalid Atom parameter)
14204 on protocol request 18skiloaf.
14205 So let's not use it until R6. */
14206#ifdef HAVE_X11XTR6
bdcd49ba
RS
14207 XtSetLanguageProc (NULL, NULL, NULL);
14208#endif
14209
7f9c7f94
RS
14210 {
14211 int argc = 0;
14212 char *argv[3];
14213
14214 argv[0] = "";
14215 argc = 1;
14216 if (xrm_option)
14217 {
14218 argv[argc++] = "-xrm";
14219 argv[argc++] = xrm_option;
14220 }
14221 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
14222 resource_name, EMACS_CLASS,
14223 emacs_options, XtNumber (emacs_options),
14224 &argc, argv);
39d8bb4d
KH
14225
14226#ifdef HAVE_X11XTR6
10537cb1 14227 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 14228 fixup_locale ();
39d8bb4d 14229#endif
7f9c7f94 14230 }
3afe33e7
RS
14231
14232#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
14233#ifdef HAVE_X11R5
14234 XSetLocaleModifiers ("");
14235#endif
7a13e894 14236 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 14237#endif /* not USE_X_TOOLKIT */
334208b7 14238
7a13e894
RS
14239 /* Detect failure. */
14240 if (dpy == 0)
60439948
KH
14241 {
14242 UNBLOCK_INPUT;
14243 return 0;
14244 }
7a13e894
RS
14245
14246 /* We have definitely succeeded. Record the new connection. */
14247
14248 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
f04e1297 14249 bzero (dpyinfo, sizeof *dpyinfo);
7a13e894 14250
29b38361
KH
14251#ifdef MULTI_KBOARD
14252 {
14253 struct x_display_info *share;
14254 Lisp_Object tail;
14255
14256 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
14257 share = share->next, tail = XCDR (tail))
14258 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
14259 XSTRING (display_name)->data))
14260 break;
14261 if (share)
14262 dpyinfo->kboard = share->kboard;
14263 else
14264 {
14265 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
14266 init_kboard (dpyinfo->kboard);
59e755be
KH
14267 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
14268 {
14269 char *vendor = ServerVendor (dpy);
9b6ed9f3 14270 UNBLOCK_INPUT;
59e755be
KH
14271 dpyinfo->kboard->Vsystem_key_alist
14272 = call1 (Qvendor_specific_keysyms,
14273 build_string (vendor ? vendor : ""));
9b6ed9f3 14274 BLOCK_INPUT;
59e755be
KH
14275 }
14276
29b38361
KH
14277 dpyinfo->kboard->next_kboard = all_kboards;
14278 all_kboards = dpyinfo->kboard;
0ad5446c
KH
14279 /* Don't let the initial kboard remain current longer than necessary.
14280 That would cause problems if a file loaded on startup tries to
06a2c219 14281 prompt in the mini-buffer. */
0ad5446c
KH
14282 if (current_kboard == initial_kboard)
14283 current_kboard = dpyinfo->kboard;
29b38361
KH
14284 }
14285 dpyinfo->kboard->reference_count++;
14286 }
b9737ad3
KH
14287#endif
14288
7a13e894
RS
14289 /* Put this display on the chain. */
14290 dpyinfo->next = x_display_list;
14291 x_display_list = dpyinfo;
14292
14293 /* Put it on x_display_name_list as well, to keep them parallel. */
14294 x_display_name_list = Fcons (Fcons (display_name, Qnil),
14295 x_display_name_list);
8e713be6 14296 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
14297
14298 dpyinfo->display = dpy;
dc6f92b8 14299
dc6f92b8 14300#if 0
7a13e894 14301 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 14302#endif /* ! 0 */
7a13e894
RS
14303
14304 dpyinfo->x_id_name
fc932ac6
RS
14305 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
14306 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
14307 + 2);
14308 sprintf (dpyinfo->x_id_name, "%s@%s",
14309 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
14310
14311 /* Figure out which modifier bits mean what. */
334208b7 14312 x_find_modifier_meanings (dpyinfo);
f451eb13 14313
ab648270 14314 /* Get the scroll bar cursor. */
7a13e894 14315 dpyinfo->vertical_scroll_bar_cursor
334208b7 14316 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 14317
334208b7
RS
14318 xrdb = x_load_resources (dpyinfo->display, xrm_option,
14319 resource_name, EMACS_CLASS);
14320#ifdef HAVE_XRMSETDATABASE
14321 XrmSetDatabase (dpyinfo->display, xrdb);
14322#else
14323 dpyinfo->display->db = xrdb;
14324#endif
547d9db8 14325 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
14326 all versions. */
14327 dpyinfo->xrdb = xrdb;
334208b7
RS
14328
14329 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
14330 DefaultScreen (dpyinfo->display));
5ff67d81 14331 select_visual (dpyinfo);
43bd1b2b 14332 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
14333 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
14334 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
14335 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
14336 dpyinfo->grabbed = 0;
14337 dpyinfo->reference_count = 0;
14338 dpyinfo->icon_bitmap_id = -1;
06a2c219 14339 dpyinfo->font_table = NULL;
7a13e894
RS
14340 dpyinfo->n_fonts = 0;
14341 dpyinfo->font_table_size = 0;
14342 dpyinfo->bitmaps = 0;
14343 dpyinfo->bitmaps_size = 0;
14344 dpyinfo->bitmaps_last = 0;
14345 dpyinfo->scratch_cursor_gc = 0;
14346 dpyinfo->mouse_face_mouse_frame = 0;
14347 dpyinfo->mouse_face_deferred_gc = 0;
14348 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
14349 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 14350 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894 14351 dpyinfo->mouse_face_window = Qnil;
0a61c667 14352 dpyinfo->mouse_face_overlay = Qnil;
7a13e894
RS
14353 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
14354 dpyinfo->mouse_face_defer = 0;
0f941935
KH
14355 dpyinfo->x_focus_frame = 0;
14356 dpyinfo->x_focus_event_frame = 0;
14357 dpyinfo->x_highlight_frame = 0;
06a2c219 14358 dpyinfo->image_cache = make_image_cache ();
334208b7 14359
43bd1b2b 14360 /* See if a private colormap is requested. */
5ff67d81
GM
14361 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
14362 {
14363 if (dpyinfo->visual->class == PseudoColor)
14364 {
14365 Lisp_Object value;
14366 value = display_x_get_resource (dpyinfo,
14367 build_string ("privateColormap"),
14368 build_string ("PrivateColormap"),
14369 Qnil, Qnil);
14370 if (STRINGP (value)
14371 && (!strcmp (XSTRING (value)->data, "true")
14372 || !strcmp (XSTRING (value)->data, "on")))
14373 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
14374 }
43bd1b2b 14375 }
5ff67d81
GM
14376 else
14377 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
14378 dpyinfo->visual, AllocNone);
43bd1b2b 14379
06a2c219
GM
14380 {
14381 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
14382 double pixels = DisplayHeight (dpyinfo->display, screen_number);
14383 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
14384 dpyinfo->resy = pixels * 25.4 / mm;
14385 pixels = DisplayWidth (dpyinfo->display, screen_number);
14386 mm = DisplayWidthMM (dpyinfo->display, screen_number);
14387 dpyinfo->resx = pixels * 25.4 / mm;
14388 }
14389
334208b7
RS
14390 dpyinfo->Xatom_wm_protocols
14391 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
14392 dpyinfo->Xatom_wm_take_focus
14393 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
14394 dpyinfo->Xatom_wm_save_yourself
14395 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
14396 dpyinfo->Xatom_wm_delete_window
14397 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
14398 dpyinfo->Xatom_wm_change_state
14399 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
14400 dpyinfo->Xatom_wm_configure_denied
14401 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
14402 dpyinfo->Xatom_wm_window_moved
14403 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
14404 dpyinfo->Xatom_editres
14405 = XInternAtom (dpyinfo->display, "Editres", False);
14406 dpyinfo->Xatom_CLIPBOARD
14407 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
14408 dpyinfo->Xatom_TIMESTAMP
14409 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
14410 dpyinfo->Xatom_TEXT
14411 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
14412 dpyinfo->Xatom_COMPOUND_TEXT
14413 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
14414 dpyinfo->Xatom_DELETE
14415 = XInternAtom (dpyinfo->display, "DELETE", False);
14416 dpyinfo->Xatom_MULTIPLE
14417 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
14418 dpyinfo->Xatom_INCR
14419 = XInternAtom (dpyinfo->display, "INCR", False);
14420 dpyinfo->Xatom_EMACS_TMP
14421 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
14422 dpyinfo->Xatom_TARGETS
14423 = XInternAtom (dpyinfo->display, "TARGETS", False);
14424 dpyinfo->Xatom_NULL
14425 = XInternAtom (dpyinfo->display, "NULL", False);
14426 dpyinfo->Xatom_ATOM_PAIR
14427 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
14428 /* For properties of font. */
14429 dpyinfo->Xatom_PIXEL_SIZE
14430 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
14431 dpyinfo->Xatom_MULE_BASELINE_OFFSET
14432 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
14433 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
14434 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
14435 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
14436 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 14437
06a2c219
GM
14438 /* Ghostscript support. */
14439 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
14440 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
14441
14442 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
14443 False);
14444
547d9db8
KH
14445 dpyinfo->cut_buffers_initialized = 0;
14446
334208b7
RS
14447 connection = ConnectionNumber (dpyinfo->display);
14448 dpyinfo->connection = connection;
14449
dc43ef94 14450 {
5d7cc324
RS
14451 char null_bits[1];
14452
14453 null_bits[0] = 0x00;
dc43ef94
KH
14454
14455 dpyinfo->null_pixel
14456 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14457 null_bits, 1, 1, (long) 0, (long) 0,
14458 1);
14459 }
14460
06a2c219
GM
14461 {
14462 extern int gray_bitmap_width, gray_bitmap_height;
10659c77 14463 extern char *gray_bitmap_bits;
06a2c219
GM
14464 dpyinfo->gray
14465 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
14466 gray_bitmap_bits,
14467 gray_bitmap_width, gray_bitmap_height,
14468 (unsigned long) 1, (unsigned long) 0, 1);
14469 }
14470
f5d11644
GM
14471#ifdef HAVE_X_I18N
14472 xim_initialize (dpyinfo, resource_name);
14473#endif
14474
87485d6f
MW
14475#ifdef subprocesses
14476 /* This is only needed for distinguishing keyboard and process input. */
334208b7 14477 if (connection != 0)
7a13e894 14478 add_keyboard_wait_descriptor (connection);
87485d6f 14479#endif
6d4238f3 14480
041b69ac 14481#ifndef F_SETOWN_BUG
dc6f92b8 14482#ifdef F_SETOWN
dc6f92b8 14483#ifdef F_SETOWN_SOCK_NEG
61c3ce62 14484 /* stdin is a socket here */
334208b7 14485 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 14486#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 14487 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
14488#endif /* ! defined (F_SETOWN_SOCK_NEG) */
14489#endif /* ! defined (F_SETOWN) */
041b69ac 14490#endif /* F_SETOWN_BUG */
dc6f92b8
JB
14491
14492#ifdef SIGIO
eee20f6a
KH
14493 if (interrupt_input)
14494 init_sigio (connection);
c118dd06 14495#endif /* ! defined (SIGIO) */
dc6f92b8 14496
51b592fb 14497#ifdef USE_LUCID
f8c39f51 14498#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
14499 /* Make sure that we have a valid font for dialog boxes
14500 so that Xt does not crash. */
14501 {
14502 Display *dpy = dpyinfo->display;
14503 XrmValue d, fr, to;
14504 Font font;
e99db5a1 14505 int count;
51b592fb
RS
14506
14507 d.addr = (XPointer)&dpy;
14508 d.size = sizeof (Display *);
14509 fr.addr = XtDefaultFont;
14510 fr.size = sizeof (XtDefaultFont);
14511 to.size = sizeof (Font *);
14512 to.addr = (XPointer)&font;
e99db5a1 14513 count = x_catch_errors (dpy);
51b592fb
RS
14514 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14515 abort ();
14516 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14517 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 14518 x_uncatch_errors (dpy, count);
51b592fb
RS
14519 }
14520#endif
f8c39f51 14521#endif
51b592fb 14522
34e23e5a
GM
14523 /* See if we should run in synchronous mode. This is useful
14524 for debugging X code. */
14525 {
14526 Lisp_Object value;
14527 value = display_x_get_resource (dpyinfo,
14528 build_string ("synchronous"),
14529 build_string ("Synchronous"),
14530 Qnil, Qnil);
14531 if (STRINGP (value)
14532 && (!strcmp (XSTRING (value)->data, "true")
14533 || !strcmp (XSTRING (value)->data, "on")))
14534 XSynchronize (dpyinfo->display, True);
14535 }
14536
60439948
KH
14537 UNBLOCK_INPUT;
14538
7a13e894
RS
14539 return dpyinfo;
14540}
14541\f
14542/* Get rid of display DPYINFO, assuming all frames are already gone,
14543 and without sending any more commands to the X server. */
dc6f92b8 14544
7a13e894
RS
14545void
14546x_delete_display (dpyinfo)
14547 struct x_display_info *dpyinfo;
14548{
14549 delete_keyboard_wait_descriptor (dpyinfo->connection);
14550
14551 /* Discard this display from x_display_name_list and x_display_list.
14552 We can't use Fdelq because that can quit. */
14553 if (! NILP (x_display_name_list)
8e713be6
KR
14554 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14555 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
14556 else
14557 {
14558 Lisp_Object tail;
14559
14560 tail = x_display_name_list;
8e713be6 14561 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 14562 {
bffcfca9 14563 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 14564 {
f3fbd155 14565 XSETCDR (tail, XCDR (XCDR (tail)));
7a13e894
RS
14566 break;
14567 }
8e713be6 14568 tail = XCDR (tail);
7a13e894
RS
14569 }
14570 }
14571
9bda743f
GM
14572 if (next_noop_dpyinfo == dpyinfo)
14573 next_noop_dpyinfo = dpyinfo->next;
14574
7a13e894
RS
14575 if (x_display_list == dpyinfo)
14576 x_display_list = dpyinfo->next;
7f9c7f94
RS
14577 else
14578 {
14579 struct x_display_info *tail;
7a13e894 14580
7f9c7f94
RS
14581 for (tail = x_display_list; tail; tail = tail->next)
14582 if (tail->next == dpyinfo)
14583 tail->next = tail->next->next;
14584 }
7a13e894 14585
0d777288
RS
14586#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14587#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
14588 XrmDestroyDatabase (dpyinfo->xrdb);
14589#endif
0d777288 14590#endif
29b38361
KH
14591#ifdef MULTI_KBOARD
14592 if (--dpyinfo->kboard->reference_count == 0)
39f79001 14593 delete_kboard (dpyinfo->kboard);
b9737ad3 14594#endif
f5d11644
GM
14595#ifdef HAVE_X_I18N
14596 if (dpyinfo->xim)
14597 xim_close_dpy (dpyinfo);
14598#endif
14599
b9737ad3
KH
14600 xfree (dpyinfo->font_table);
14601 xfree (dpyinfo->x_id_name);
f04e1297 14602 xfree (dpyinfo->color_cells);
b9737ad3 14603 xfree (dpyinfo);
7a13e894 14604}
f04e1297 14605
7a13e894
RS
14606\f
14607/* Set up use of X before we make the first connection. */
14608
06a2c219
GM
14609static struct redisplay_interface x_redisplay_interface =
14610{
14611 x_produce_glyphs,
14612 x_write_glyphs,
14613 x_insert_glyphs,
14614 x_clear_end_of_line,
14615 x_scroll_run,
14616 x_after_update_window_line,
14617 x_update_window_begin,
14618 x_update_window_end,
14619 XTcursor_to,
14620 x_flush,
71b8321e 14621 x_clear_mouse_face,
66ac4b0e
GM
14622 x_get_glyph_overhangs,
14623 x_fix_overlapping_area
06a2c219
GM
14624};
14625
dfcf069d 14626void
7a13e894
RS
14627x_initialize ()
14628{
06a2c219
GM
14629 rif = &x_redisplay_interface;
14630
14631 clear_frame_hook = x_clear_frame;
14632 ins_del_lines_hook = x_ins_del_lines;
06a2c219 14633 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
14634 ring_bell_hook = XTring_bell;
14635 reset_terminal_modes_hook = XTreset_terminal_modes;
14636 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
14637 update_begin_hook = x_update_begin;
14638 update_end_hook = x_update_end;
dc6f92b8
JB
14639 set_terminal_window_hook = XTset_terminal_window;
14640 read_socket_hook = XTread_socket;
b8009dd1 14641 frame_up_to_date_hook = XTframe_up_to_date;
90e65f07 14642 mouse_position_hook = XTmouse_position;
f451eb13 14643 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 14644 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
14645 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14646 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14647 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14648 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 14649 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 14650
f676886a 14651 scroll_region_ok = 1; /* we'll scroll partial frames */
9017309f 14652 char_ins_del_ok = 1;
dc6f92b8
JB
14653 line_ins_del_ok = 1; /* we'll just blt 'em */
14654 fast_clear_end_of_line = 1; /* X does this well */
58769bee 14655 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
14656 off the bottom */
14657 baud_rate = 19200;
14658
7a13e894 14659 x_noop_count = 0;
9ea173e8 14660 last_tool_bar_item = -1;
06a2c219
GM
14661 any_help_event_p = 0;
14662
b30b24cb
RS
14663 /* Try to use interrupt input; if we can't, then start polling. */
14664 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14665
7f9c7f94
RS
14666#ifdef USE_X_TOOLKIT
14667 XtToolkitInitialize ();
651f03b6 14668
7f9c7f94 14669 Xt_app_con = XtCreateApplicationContext ();
651f03b6
GM
14670
14671 /* Register a converter from strings to pixels, which uses
14672 Emacs' color allocation infrastructure. */
14673 XtAppSetTypeConverter (Xt_app_con,
14674 XtRString, XtRPixel, cvt_string_to_pixel,
14675 cvt_string_to_pixel_args,
14676 XtNumber (cvt_string_to_pixel_args),
14677 XtCacheByDisplay, cvt_pixel_dtor);
14678
665881ad 14679 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
14680
14681 /* Install an asynchronous timer that processes Xt timeout events
14682 every 0.1s. This is necessary because some widget sets use
14683 timeouts internally, for example the LessTif menu bar, or the
14684 Xaw3d scroll bar. When Xt timouts aren't processed, these
14685 widgets don't behave normally. */
14686 {
14687 EMACS_TIME interval;
14688 EMACS_SET_SECS_USECS (interval, 0, 100000);
14689 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14690 }
db74249b 14691#endif
bffcfca9 14692
eccc05db 14693#ifdef USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
14694 xaw3d_arrow_scroll = False;
14695 xaw3d_pick_top = True;
7f9c7f94
RS
14696#endif
14697
58769bee 14698 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 14699 original error handler. */
e99db5a1 14700 XSetErrorHandler (x_error_handler);
334208b7 14701 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 14702
06a2c219 14703 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
14704#ifdef SIGWINCH
14705 signal (SIGWINCH, SIG_DFL);
c118dd06 14706#endif /* ! defined (SIGWINCH) */
dc6f92b8 14707
92e2441b 14708 signal (SIGPIPE, x_connection_signal);
dc6f92b8 14709}
55123275 14710
06a2c219 14711
55123275
JB
14712void
14713syms_of_xterm ()
14714{
e99db5a1
RS
14715 staticpro (&x_error_message_string);
14716 x_error_message_string = Qnil;
14717
7a13e894
RS
14718 staticpro (&x_display_name_list);
14719 x_display_name_list = Qnil;
334208b7 14720
ab648270 14721 staticpro (&last_mouse_scroll_bar);
e53cb100 14722 last_mouse_scroll_bar = Qnil;
59e755be
KH
14723
14724 staticpro (&Qvendor_specific_keysyms);
14725 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
14726
14727 staticpro (&last_mouse_press_frame);
14728 last_mouse_press_frame = Qnil;
06a2c219 14729
06a2c219 14730 help_echo = Qnil;
be010514
GM
14731 staticpro (&help_echo);
14732 help_echo_object = Qnil;
14733 staticpro (&help_echo_object);
7cea38bc
GM
14734 help_echo_window = Qnil;
14735 staticpro (&help_echo_window);
06a2c219 14736 previous_help_echo = Qnil;
be010514
GM
14737 staticpro (&previous_help_echo);
14738 help_echo_pos = -1;
06a2c219 14739
7ee72033
MB
14740 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14741 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
228299fa
GM
14742For example, if a block cursor is over a tab, it will be drawn as
14743wide as that tab on the display. */);
06a2c219
GM
14744 x_stretch_cursor_p = 0;
14745
a72d5ce5 14746 DEFVAR_BOOL ("x-use-underline-position-properties",
7ee72033
MB
14747 &x_use_underline_position_properties,
14748 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
228299fa
GM
14749Nil means ignore them. If you encounter fonts with bogus
14750UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
14751to 4.1, set this to nil. */);
a72d5ce5
GM
14752 x_use_underline_position_properties = 1;
14753
7ee72033
MB
14754 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14755 doc: /* What X toolkit scroll bars Emacs uses.
228299fa
GM
14756A value of nil means Emacs doesn't use X toolkit scroll bars.
14757Otherwise, value is a symbol describing the X toolkit. */);
eccc05db 14758#ifdef USE_TOOLKIT_SCROLL_BARS
5bf04520
GM
14759#ifdef USE_MOTIF
14760 Vx_toolkit_scroll_bars = intern ("motif");
14761#elif defined HAVE_XAW3D
14762 Vx_toolkit_scroll_bars = intern ("xaw3d");
14763#else
14764 Vx_toolkit_scroll_bars = intern ("xaw");
14765#endif
06a2c219 14766#else
5bf04520 14767 Vx_toolkit_scroll_bars = Qnil;
06a2c219
GM
14768#endif
14769
06a2c219
GM
14770 staticpro (&last_mouse_motion_frame);
14771 last_mouse_motion_frame = Qnil;
55123275 14772}
6cf0ae86 14773
1d6c120a 14774#endif /* HAVE_X_WINDOWS */