Undo last commit by John Wiegley.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
edf36fe6 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
06a2c219 3 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
06a2c219 22/* New display code by Gerd Moellmann <gerd@gnu.org>. */
3afe33e7
RS
23/* Xt features made by Fred Pierresteguy. */
24
68c45bf0
PE
25#include <config.h>
26
039440c4 27/* On 4.3 these lose if they come after xterm.h. */
039440c4 28/* Putting these at the beginning seems to be standard for other .c files. */
039440c4
RS
29#include <signal.h>
30
4846819e
RS
31#include <stdio.h>
32
dc6f92b8
JB
33#ifdef HAVE_X_WINDOWS
34
35#include "lisp.h"
9ac0d9e0 36#include "blockinput.h"
dc6f92b8 37
ae79c227
AS
38/* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40#include "syssignal.h"
41
dc6f92b8
JB
42/* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44#include "xterm.h"
f451eb13 45#include <X11/cursorfont.h>
dc6f92b8
JB
46
47/* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49#ifndef makedev
50#include <sys/types.h>
c118dd06 51#endif /* makedev */
dc6f92b8 52
6df54671 53#ifdef BSD_SYSTEM
dc6f92b8 54#include <sys/ioctl.h>
6df54671 55#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 56
2d368234 57#include "systty.h"
3a2712f9 58#include "systime.h"
dc6f92b8 59
b8009dd1 60#ifndef INCLUDED_FCNTL
dc6f92b8 61#include <fcntl.h>
b8009dd1 62#endif
dc6f92b8
JB
63#include <ctype.h>
64#include <errno.h>
65#include <setjmp.h>
66#include <sys/stat.h>
a0a7635f
RS
67/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68/* #include <sys/param.h> */
dc6f92b8 69
dc43ef94 70#include "charset.h"
379b5ac0 71#include "coding.h"
dc43ef94 72#include "ccl.h"
7a13e894 73#include "frame.h"
dc6f92b8 74#include "dispextern.h"
ee569018 75#include "fontset.h"
dc6f92b8
JB
76#include "termhooks.h"
77#include "termopts.h"
78#include "termchar.h"
79#if 0
80#include "sink.h"
81#include "sinkmask.h"
c118dd06 82#endif /* ! 0 */
dc6f92b8 83#include "gnu.h"
dc6f92b8 84#include "disptab.h"
dc6f92b8 85#include "buffer.h"
f451eb13 86#include "window.h"
3b2fa4e6 87#include "keyboard.h"
bde7c500 88#include "intervals.h"
dfcf069d 89#include "process.h"
bffcfca9 90#include "atimer.h"
dc6f92b8 91
d2bd6bc4
RS
92#ifdef USE_X_TOOLKIT
93#include <X11/Shell.h>
94#endif
95
06a2c219
GM
96#ifdef HAVE_SYS_TIME_H
97#include <sys/time.h>
98#endif
99#ifdef HAVE_UNISTD_H
100#include <unistd.h>
101#endif
102
3afe33e7 103#ifdef USE_X_TOOLKIT
06a2c219 104
952291d9
GM
105extern void free_frame_menubar P_ ((struct frame *));
106extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
06a2c219 108
0fdff6bb
RS
109#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110#define HACK_EDITRES
111extern void _XEditResCheckMessages ();
112#endif /* not NO_EDITRES */
06a2c219
GM
113
114/* Include toolkit specific headers for the scroll bar widget. */
115
116#ifdef USE_TOOLKIT_SCROLL_BARS
117#if defined USE_MOTIF
118#include <Xm/Xm.h> /* for LESSTIF_VERSION */
119#include <Xm/ScrollBar.h>
ec18280f
SM
120#else /* !USE_MOTIF i.e. use Xaw */
121
122#ifdef HAVE_XAW3D
06a2c219 123#include <X11/Xaw3d/Simple.h>
06a2c219
GM
124#include <X11/Xaw3d/Scrollbar.h>
125#define ARROW_SCROLLBAR
126#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
127#else /* !HAVE_XAW3D */
128#include <X11/Xaw/Simple.h>
129#include <X11/Xaw/Scrollbar.h>
130#endif /* !HAVE_XAW3D */
131#ifndef XtNpickTop
132#define XtNpickTop "pickTop"
133#endif /* !XtNpickTop */
134#endif /* !USE_MOTIF */
06a2c219
GM
135#endif /* USE_TOOLKIT_SCROLL_BARS */
136
3afe33e7
RS
137#endif /* USE_X_TOOLKIT */
138
b849c413
RS
139#ifndef USE_X_TOOLKIT
140#define x_any_window_to_frame x_window_to_frame
5627c40e 141#define x_top_window_to_frame x_window_to_frame
b849c413
RS
142#endif
143
546e6d5b 144#ifdef USE_X_TOOLKIT
d067ea8b 145#include "widget.h"
546e6d5b
RS
146#ifndef XtNinitialState
147#define XtNinitialState "initialState"
148#endif
149#endif
150
e4b68333 151#ifndef min
06a2c219 152#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
153#endif
154#ifndef max
06a2c219
GM
155#define max(a,b) ((a) > (b) ? (a) : (b))
156#endif
157
158#define abs(x) ((x) < 0 ? -(x) : (x))
159
160#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
161
162\f
163/* Bitmaps for truncated lines. */
164
165enum bitmap_type
166{
167 NO_BITMAP,
168 LEFT_TRUNCATION_BITMAP,
169 RIGHT_TRUNCATION_BITMAP,
170 OVERLAY_ARROW_BITMAP,
171 CONTINUED_LINE_BITMAP,
172 CONTINUATION_LINE_BITMAP,
173 ZV_LINE_BITMAP
174};
175
176/* Bitmap drawn to indicate lines not displaying text if
177 `indicate-empty-lines' is non-nil. */
178
179#define zv_width 8
180#define zv_height 8
181static unsigned char zv_bits[] = {
182 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
183
184/* An arrow like this: `<-'. */
185
186#define left_width 8
187#define left_height 8
188static unsigned char left_bits[] = {
189 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
190
110859fc
GM
191/* Right truncation arrow bitmap `->'. */
192
193#define right_width 8
194#define right_height 8
195static unsigned char right_bits[] = {
196 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
197
06a2c219
GM
198/* Marker for continued lines. */
199
200#define continued_width 8
201#define continued_height 8
202static unsigned char continued_bits[] = {
110859fc
GM
203 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
204
205/* Marker for continuation lines. */
06a2c219
GM
206
207#define continuation_width 8
208#define continuation_height 8
209static unsigned char continuation_bits[] = {
110859fc 210 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 211
110859fc 212/* Overlay arrow bitmap. */
06a2c219 213
110859fc
GM
214#if 0
215/* A bomb. */
06a2c219
GM
216#define ov_width 8
217#define ov_height 8
218static unsigned char ov_bits[] = {
219 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 220#else
110859fc 221/* A triangular arrow. */
06a2c219
GM
222#define ov_width 8
223#define ov_height 8
224static unsigned char ov_bits[] = {
110859fc
GM
225 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
226
e4b68333 227#endif
06a2c219
GM
228
229extern Lisp_Object Qhelp_echo;
230
69388238 231\f
5bf04520 232/* Non-nil means Emacs uses toolkit scroll bars. */
06a2c219 233
5bf04520 234Lisp_Object Vx_toolkit_scroll_bars;
06a2c219
GM
235
236/* If a string, XTread_socket generates an event to display that string.
237 (The display is done in read_char.) */
238
239static Lisp_Object help_echo;
7cea38bc 240static Lisp_Object help_echo_window;
be010514
GM
241static Lisp_Object help_echo_object;
242static int help_echo_pos;
06a2c219
GM
243
244/* Temporary variable for XTread_socket. */
245
246static Lisp_Object previous_help_echo;
247
248/* Non-zero means that a HELP_EVENT has been generated since Emacs
249 start. */
250
251static int any_help_event_p;
252
253/* Non-zero means draw block and hollow cursor as wide as the glyph
254 under it. For example, if a block cursor is over a tab, it will be
255 drawn as wide as that tab on the display. */
256
257int x_stretch_cursor_p;
258
259/* This is a chain of structures for all the X displays currently in
260 use. */
261
334208b7 262struct x_display_info *x_display_list;
dc6f92b8 263
06a2c219
GM
264/* This is a list of cons cells, each of the form (NAME
265 . FONT-LIST-CACHE), one for each element of x_display_list and in
266 the same order. NAME is the name of the frame. FONT-LIST-CACHE
267 records previous values returned by x-list-fonts. */
268
7a13e894 269Lisp_Object x_display_name_list;
f451eb13 270
987d2ad1 271/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
272 This is set by update_begin and looked at by all the XT functions.
273 It is zero while not inside an update. In that case, the XT
274 functions assume that `selected_frame' is the frame to apply to. */
275
d0386f2a 276extern struct frame *updating_frame;
dc6f92b8 277
dfcf069d 278extern int waiting_for_input;
0e81d8cd 279
06a2c219
GM
280/* This is a frame waiting to be auto-raised, within XTread_socket. */
281
0134a210
RS
282struct frame *pending_autoraise_frame;
283
7f9c7f94
RS
284#ifdef USE_X_TOOLKIT
285/* The application context for Xt use. */
286XtAppContext Xt_app_con;
06a2c219
GM
287static String Xt_default_resources[] = {0};
288#endif /* USE_X_TOOLKIT */
665881ad 289
06a2c219
GM
290/* Nominal cursor position -- where to draw output.
291 HPOS and VPOS are window relative glyph matrix coordinates.
292 X and Y are window relative pixel coordinates. */
dc6f92b8 293
06a2c219 294struct cursor_pos output_cursor;
dc6f92b8 295
bffcfca9
GM
296/* Non-zero means user is interacting with a toolkit scroll bar. */
297
298static int toolkit_scroll_bar_interaction;
dc6f92b8 299
69388238
RS
300/* Mouse movement.
301
06a2c219 302 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
303 so that we would have to call XQueryPointer after each MotionNotify
304 event to ask for another such event. However, this made mouse tracking
305 slow, and there was a bug that made it eventually stop.
306
307 Simply asking for MotionNotify all the time seems to work better.
308
69388238
RS
309 In order to avoid asking for motion events and then throwing most
310 of them away or busy-polling the server for mouse positions, we ask
311 the server for pointer motion hints. This means that we get only
312 one event per group of mouse movements. "Groups" are delimited by
313 other kinds of events (focus changes and button clicks, for
314 example), or by XQueryPointer calls; when one of these happens, we
315 get another MotionNotify event the next time the mouse moves. This
316 is at least as efficient as getting motion events when mouse
317 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 318 is off. */
69388238
RS
319
320/* Where the mouse was last time we reported a mouse event. */
69388238 321
06a2c219
GM
322FRAME_PTR last_mouse_frame;
323static XRectangle last_mouse_glyph;
2237cac9
RS
324static Lisp_Object last_mouse_press_frame;
325
69388238
RS
326/* The scroll bar in which the last X motion event occurred.
327
06a2c219
GM
328 If the last X motion event occurred in a scroll bar, we set this so
329 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
330 an ordinary motion.
331
06a2c219
GM
332 If the last X motion event didn't occur in a scroll bar, we set
333 this to Qnil, to tell XTmouse_position to return an ordinary motion
334 event. */
335
69388238
RS
336static Lisp_Object last_mouse_scroll_bar;
337
69388238
RS
338/* This is a hack. We would really prefer that XTmouse_position would
339 return the time associated with the position it returns, but there
06a2c219 340 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
341 along with the position query. So, we just keep track of the time
342 of the last movement we received, and return that in hopes that
343 it's somewhat accurate. */
06a2c219 344
69388238
RS
345static Time last_mouse_movement_time;
346
06a2c219
GM
347/* Incremented by XTread_socket whenever it really tries to read
348 events. */
349
c0a04927
RS
350#ifdef __STDC__
351static int volatile input_signal_count;
352#else
353static int input_signal_count;
354#endif
355
7a13e894 356/* Used locally within XTread_socket. */
06a2c219 357
7a13e894 358static int x_noop_count;
dc6f92b8 359
7a13e894 360/* Initial values of argv and argc. */
06a2c219 361
7a13e894
RS
362extern char **initial_argv;
363extern int initial_argc;
dc6f92b8 364
7a13e894 365extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 366
06a2c219 367/* Tells if a window manager is present or not. */
7a13e894
RS
368
369extern Lisp_Object Vx_no_window_manager;
dc6f92b8 370
c2df547c 371extern Lisp_Object Qface, Qmouse_face;
b8009dd1 372
dc6f92b8
JB
373extern int errno;
374
dfeccd2d 375/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 376
64bb1782
RS
377extern int extra_keyboard_modifiers;
378
59e755be
KH
379static Lisp_Object Qvendor_specific_keysyms;
380
952291d9
GM
381extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
382extern Lisp_Object x_icon_type P_ ((struct frame *));
c32cdd9a 383
7a13e894 384
06a2c219
GM
385/* Enumeration for overriding/changing the face to use for drawing
386 glyphs in x_draw_glyphs. */
387
388enum draw_glyphs_face
389{
390 DRAW_NORMAL_TEXT,
391 DRAW_INVERSE_VIDEO,
392 DRAW_CURSOR,
393 DRAW_MOUSE_FACE,
394 DRAW_IMAGE_RAISED,
395 DRAW_IMAGE_SUNKEN
396};
397
499b1844 398static void x_set_window_size_1 P_ ((struct frame *, int, int, int));
f04e1297 399static const XColor *x_color_cells P_ ((struct frame *, int *));
71b8321e 400static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
401static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
402void x_delete_display P_ ((struct x_display_info *));
403static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
404 unsigned));
405static int fast_find_position P_ ((struct window *, int, int *, int *,
406 int *, int *));
f9db2310
GM
407static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
408 int *, int *, int *, int *, int));
06a2c219
GM
409static void set_output_cursor P_ ((struct cursor_pos *));
410static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
f9db2310 411 int *, int *, int *, int));
06a2c219 412static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 413static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
414static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
415static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
416static void show_mouse_face P_ ((struct x_display_info *,
417 enum draw_glyphs_face));
418static int x_io_error_quitter P_ ((Display *));
419int x_catch_errors P_ ((Display *));
420void x_uncatch_errors P_ ((Display *, int));
421void x_lower_frame P_ ((struct frame *));
422void x_scroll_bar_clear P_ ((struct frame *));
423int x_had_errors_p P_ ((Display *));
424void x_wm_set_size_hint P_ ((struct frame *, long, int));
425void x_raise_frame P_ ((struct frame *));
426void x_set_window_size P_ ((struct frame *, int, int, int));
427void x_wm_set_window_state P_ ((struct frame *, int));
428void x_wm_set_icon_pixmap P_ ((struct frame *, int));
429void x_initialize P_ ((void));
430static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
431static int x_compute_min_glyph_bounds P_ ((struct frame *));
432static void x_draw_phys_cursor_glyph P_ ((struct window *,
433 struct glyph_row *,
434 enum draw_glyphs_face));
435static void x_update_end P_ ((struct frame *));
436static void XTframe_up_to_date P_ ((struct frame *));
437static void XTreassert_line_highlight P_ ((int, int));
438static void x_change_line_highlight P_ ((int, int, int, int));
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));
456static void expose_window_tree P_ ((struct window *, XRectangle *));
457static void expose_window P_ ((struct window *, XRectangle *));
458static void expose_area P_ ((struct window *, struct glyph_row *,
459 XRectangle *, enum glyph_row_area));
460static void expose_line P_ ((struct window *, struct glyph_row *,
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 *));
473static void note_overwritten_text_cursor P_ ((struct window *, int, int));
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 Line Highlighting
1025 ***********************************************************************/
dc6f92b8 1026
06a2c219
GM
1027/* External interface to control of standout mode. Not used for X
1028 frames. Aborts when called. */
1029
1030static void
dc6f92b8
JB
1031XTreassert_line_highlight (new, vpos)
1032 int new, vpos;
1033{
06a2c219 1034 abort ();
dc6f92b8
JB
1035}
1036
06a2c219
GM
1037
1038/* Call this when about to modify line at position VPOS and change
1039 whether it is highlighted. Not used for X frames. Aborts when
1040 called. */
dc6f92b8 1041
dfcf069d 1042static void
06a2c219
GM
1043x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1044 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1045{
06a2c219 1046 abort ();
dc6f92b8
JB
1047}
1048
06a2c219
GM
1049
1050/* This is called when starting Emacs and when restarting after
1051 suspend. When starting Emacs, no X window is mapped. And nothing
1052 must be done to Emacs's own window if it is suspended (though that
1053 rarely happens). */
dc6f92b8 1054
dfcf069d 1055static void
dc6f92b8
JB
1056XTset_terminal_modes ()
1057{
1058}
1059
06a2c219
GM
1060/* This is called when exiting or suspending Emacs. Exiting will make
1061 the X-windows go away, and suspending requires no action. */
dc6f92b8 1062
dfcf069d 1063static void
dc6f92b8
JB
1064XTreset_terminal_modes ()
1065{
dc6f92b8 1066}
06a2c219
GM
1067
1068
dc6f92b8 1069\f
06a2c219
GM
1070/***********************************************************************
1071 Output Cursor
1072 ***********************************************************************/
1073
1074/* Set the global variable output_cursor to CURSOR. All cursor
1075 positions are relative to updated_window. */
dc6f92b8 1076
dfcf069d 1077static void
06a2c219
GM
1078set_output_cursor (cursor)
1079 struct cursor_pos *cursor;
dc6f92b8 1080{
06a2c219
GM
1081 output_cursor.hpos = cursor->hpos;
1082 output_cursor.vpos = cursor->vpos;
1083 output_cursor.x = cursor->x;
1084 output_cursor.y = cursor->y;
1085}
1086
1087
1088/* Set a nominal cursor position.
dc6f92b8 1089
06a2c219
GM
1090 HPOS and VPOS are column/row positions in a window glyph matrix. X
1091 and Y are window text area relative pixel positions.
1092
1093 If this is done during an update, updated_window will contain the
1094 window that is being updated and the position is the future output
1095 cursor position for that window. If updated_window is null, use
1096 selected_window and display the cursor at the given position. */
1097
1098static void
1099XTcursor_to (vpos, hpos, y, x)
1100 int vpos, hpos, y, x;
1101{
1102 struct window *w;
1103
1104 /* If updated_window is not set, work on selected_window. */
1105 if (updated_window)
1106 w = updated_window;
1107 else
1108 w = XWINDOW (selected_window);
dbcb258a 1109
06a2c219
GM
1110 /* Set the output cursor. */
1111 output_cursor.hpos = hpos;
1112 output_cursor.vpos = vpos;
1113 output_cursor.x = x;
1114 output_cursor.y = y;
dc6f92b8 1115
06a2c219
GM
1116 /* If not called as part of an update, really display the cursor.
1117 This will also set the cursor position of W. */
1118 if (updated_window == NULL)
dc6f92b8
JB
1119 {
1120 BLOCK_INPUT;
06a2c219 1121 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1122 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1123 UNBLOCK_INPUT;
1124 }
1125}
dc43ef94 1126
06a2c219
GM
1127
1128\f
1129/***********************************************************************
1130 Display Iterator
1131 ***********************************************************************/
1132
1133/* Function prototypes of this page. */
1134
1135static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1136 struct glyph *,
ee569018
KH
1137 XChar2b *,
1138 int *));
06a2c219
GM
1139static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1140 int, XChar2b *, int));
1141static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1142static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1143static void x_append_glyph P_ ((struct it *));
b4192550 1144static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1145static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1146 int, int, double));
1147static void x_produce_glyphs P_ ((struct it *));
06a2c219 1148static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1149
1150
e2ef8ee6
GM
1151/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1152 is not contained in the font. */
dc43ef94 1153
06a2c219 1154static INLINE XCharStruct *
ee569018 1155x_per_char_metric (font, char2b)
06a2c219
GM
1156 XFontStruct *font;
1157 XChar2b *char2b;
1158{
1159 /* The result metric information. */
1160 XCharStruct *pcm = NULL;
dc6f92b8 1161
06a2c219 1162 xassert (font && char2b);
dc6f92b8 1163
06a2c219 1164 if (font->per_char != NULL)
dc6f92b8 1165 {
06a2c219 1166 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1167 {
06a2c219
GM
1168 /* min_char_or_byte2 specifies the linear character index
1169 corresponding to the first element of the per_char array,
1170 max_char_or_byte2 is the index of the last character. A
1171 character with non-zero CHAR2B->byte1 is not in the font.
1172 A character with byte2 less than min_char_or_byte2 or
1173 greater max_char_or_byte2 is not in the font. */
1174 if (char2b->byte1 == 0
1175 && char2b->byte2 >= font->min_char_or_byte2
1176 && char2b->byte2 <= font->max_char_or_byte2)
1177 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1178 }
06a2c219 1179 else
dc6f92b8 1180 {
06a2c219
GM
1181 /* If either min_byte1 or max_byte1 are nonzero, both
1182 min_char_or_byte2 and max_char_or_byte2 are less than
1183 256, and the 2-byte character index values corresponding
1184 to the per_char array element N (counting from 0) are:
1185
1186 byte1 = N/D + min_byte1
1187 byte2 = N\D + min_char_or_byte2
1188
1189 where:
1190
1191 D = max_char_or_byte2 - min_char_or_byte2 + 1
1192 / = integer division
1193 \ = integer modulus */
1194 if (char2b->byte1 >= font->min_byte1
1195 && char2b->byte1 <= font->max_byte1
1196 && char2b->byte2 >= font->min_char_or_byte2
1197 && char2b->byte2 <= font->max_char_or_byte2)
1198 {
1199 pcm = (font->per_char
1200 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1201 * (char2b->byte1 - font->min_byte1))
1202 + (char2b->byte2 - font->min_char_or_byte2));
1203 }
dc6f92b8 1204 }
06a2c219
GM
1205 }
1206 else
1207 {
1208 /* If the per_char pointer is null, all glyphs between the first
1209 and last character indexes inclusive have the same
1210 information, as given by both min_bounds and max_bounds. */
1211 if (char2b->byte2 >= font->min_char_or_byte2
1212 && char2b->byte2 <= font->max_char_or_byte2)
1213 pcm = &font->max_bounds;
1214 }
dc6f92b8 1215
ee569018 1216 return ((pcm == NULL
3e71d8f2 1217 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1218 ? NULL : pcm);
06a2c219 1219}
b73b6aaf 1220
57b03282 1221
06a2c219
GM
1222/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1223 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1224
06a2c219
GM
1225static INLINE void
1226x_encode_char (c, char2b, font_info)
1227 int c;
1228 XChar2b *char2b;
1229 struct font_info *font_info;
1230{
1231 int charset = CHAR_CHARSET (c);
1232 XFontStruct *font = font_info->font;
1233
1234 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1235 This may be either a program in a special encoder language or a
1236 fixed encoding. */
1237 if (font_info->font_encoder)
1238 {
1239 /* It's a program. */
1240 struct ccl_program *ccl = font_info->font_encoder;
1241
1242 if (CHARSET_DIMENSION (charset) == 1)
1243 {
1244 ccl->reg[0] = charset;
1245 ccl->reg[1] = char2b->byte2;
1246 }
1247 else
1248 {
1249 ccl->reg[0] = charset;
1250 ccl->reg[1] = char2b->byte1;
1251 ccl->reg[2] = char2b->byte2;
1252 }
1253
1254 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1255
1256 /* We assume that MSBs are appropriately set/reset by CCL
1257 program. */
1258 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1259 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1260 else
1261 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1262 }
1263 else if (font_info->encoding[charset])
1264 {
1265 /* Fixed encoding scheme. See fontset.h for the meaning of the
1266 encoding numbers. */
1267 int enc = font_info->encoding[charset];
1268
1269 if ((enc == 1 || enc == 2)
1270 && CHARSET_DIMENSION (charset) == 2)
1271 char2b->byte1 |= 0x80;
1272
1273 if (enc == 1 || enc == 3)
1274 char2b->byte2 |= 0x80;
1275 }
1276}
1277
1278
1279/* Get face and two-byte form of character C in face FACE_ID on frame
1280 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1281 means we want to display multibyte text. Value is a pointer to a
1282 realized face that is ready for display. */
1283
1284static INLINE struct face *
1285x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1286 struct frame *f;
1287 int c, face_id;
1288 XChar2b *char2b;
1289 int multibyte_p;
1290{
1291 struct face *face = FACE_FROM_ID (f, face_id);
1292
1293 if (!multibyte_p)
1294 {
1295 /* Unibyte case. We don't have to encode, but we have to make
1296 sure to use a face suitable for unibyte. */
1297 char2b->byte1 = 0;
1298 char2b->byte2 = c;
ee569018
KH
1299 face_id = FACE_FOR_CHAR (f, face, c);
1300 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1301 }
1302 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1303 {
1304 /* Case of ASCII in a face known to fit ASCII. */
1305 char2b->byte1 = 0;
1306 char2b->byte2 = c;
1307 }
1308 else
1309 {
1310 int c1, c2, charset;
1311
1312 /* Split characters into bytes. If c2 is -1 afterwards, C is
1313 really a one-byte character so that byte1 is zero. */
1314 SPLIT_CHAR (c, charset, c1, c2);
1315 if (c2 > 0)
1316 char2b->byte1 = c1, char2b->byte2 = c2;
1317 else
1318 char2b->byte1 = 0, char2b->byte2 = c1;
1319
06a2c219 1320 /* Maybe encode the character in *CHAR2B. */
ee569018 1321 if (face->font != NULL)
06a2c219
GM
1322 {
1323 struct font_info *font_info
1324 = FONT_INFO_FROM_ID (f, face->font_info_id);
1325 if (font_info)
ee569018 1326 x_encode_char (c, char2b, font_info);
06a2c219
GM
1327 }
1328 }
1329
1330 /* Make sure X resources of the face are allocated. */
1331 xassert (face != NULL);
1332 PREPARE_FACE_FOR_DISPLAY (f, face);
1333
1334 return face;
1335}
1336
1337
1338/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1339 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1340 a pointer to a realized face that is ready for display. */
1341
1342static INLINE struct face *
ee569018 1343x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1344 struct frame *f;
1345 struct glyph *glyph;
1346 XChar2b *char2b;
ee569018 1347 int *two_byte_p;
06a2c219
GM
1348{
1349 struct face *face;
1350
1351 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1352 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1353
ee569018
KH
1354 if (two_byte_p)
1355 *two_byte_p = 0;
1356
06a2c219
GM
1357 if (!glyph->multibyte_p)
1358 {
1359 /* Unibyte case. We don't have to encode, but we have to make
1360 sure to use a face suitable for unibyte. */
1361 char2b->byte1 = 0;
43d120d8 1362 char2b->byte2 = glyph->u.ch;
06a2c219 1363 }
43d120d8
KH
1364 else if (glyph->u.ch < 128
1365 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1366 {
1367 /* Case of ASCII in a face known to fit ASCII. */
1368 char2b->byte1 = 0;
43d120d8 1369 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1370 }
1371 else
1372 {
1373 int c1, c2, charset;
1374
1375 /* Split characters into bytes. If c2 is -1 afterwards, C is
1376 really a one-byte character so that byte1 is zero. */
43d120d8 1377 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1378 if (c2 > 0)
1379 char2b->byte1 = c1, char2b->byte2 = c2;
1380 else
1381 char2b->byte1 = 0, char2b->byte2 = c1;
1382
1383 /* Maybe encode the character in *CHAR2B. */
1384 if (charset != CHARSET_ASCII)
1385 {
1386 struct font_info *font_info
1387 = FONT_INFO_FROM_ID (f, face->font_info_id);
1388 if (font_info)
1389 {
43d120d8 1390 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1391 if (two_byte_p)
1392 *two_byte_p
1393 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1394 }
1395 }
1396 }
1397
1398 /* Make sure X resources of the face are allocated. */
1399 xassert (face != NULL);
1400 PREPARE_FACE_FOR_DISPLAY (f, face);
1401 return face;
1402}
1403
1404
1405/* Store one glyph for IT->char_to_display in IT->glyph_row.
1406 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1407
1408static INLINE void
1409x_append_glyph (it)
1410 struct it *it;
1411{
1412 struct glyph *glyph;
1413 enum glyph_row_area area = it->area;
1414
1415 xassert (it->glyph_row);
1416 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1417
1418 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1419 if (glyph < it->glyph_row->glyphs[area + 1])
1420 {
06a2c219
GM
1421 glyph->charpos = CHARPOS (it->position);
1422 glyph->object = it->object;
88d75730 1423 glyph->pixel_width = it->pixel_width;
06a2c219 1424 glyph->voffset = it->voffset;
88d75730 1425 glyph->type = CHAR_GLYPH;
06a2c219 1426 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1427 glyph->left_box_line_p = it->start_of_box_run_p;
1428 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1429 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1430 || it->phys_descent > it->descent);
88d75730 1431 glyph->padding_p = 0;
ee569018 1432 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1433 glyph->face_id = it->face_id;
1434 glyph->u.ch = it->char_to_display;
06a2c219
GM
1435 ++it->glyph_row->used[area];
1436 }
1437}
1438
b4192550
KH
1439/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1440 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1441
1442static INLINE void
1443x_append_composite_glyph (it)
1444 struct it *it;
1445{
1446 struct glyph *glyph;
1447 enum glyph_row_area area = it->area;
1448
1449 xassert (it->glyph_row);
1450
1451 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1452 if (glyph < it->glyph_row->glyphs[area + 1])
1453 {
b4192550
KH
1454 glyph->charpos = CHARPOS (it->position);
1455 glyph->object = it->object;
88d75730 1456 glyph->pixel_width = it->pixel_width;
b4192550 1457 glyph->voffset = it->voffset;
88d75730 1458 glyph->type = COMPOSITE_GLYPH;
b4192550 1459 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1460 glyph->left_box_line_p = it->start_of_box_run_p;
1461 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1462 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1463 || it->phys_descent > it->descent);
88d75730
GM
1464 glyph->padding_p = 0;
1465 glyph->glyph_not_available_p = 0;
1466 glyph->face_id = it->face_id;
1467 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1468 ++it->glyph_row->used[area];
1469 }
1470}
1471
06a2c219
GM
1472
1473/* Change IT->ascent and IT->height according to the setting of
1474 IT->voffset. */
1475
1476static INLINE void
1477take_vertical_position_into_account (it)
1478 struct it *it;
1479{
1480 if (it->voffset)
1481 {
1482 if (it->voffset < 0)
1483 /* Increase the ascent so that we can display the text higher
1484 in the line. */
1485 it->ascent += abs (it->voffset);
1486 else
1487 /* Increase the descent so that we can display the text lower
1488 in the line. */
1489 it->descent += it->voffset;
1490 }
1491}
1492
1493
1494/* Produce glyphs/get display metrics for the image IT is loaded with.
1495 See the description of struct display_iterator in dispextern.h for
1496 an overview of struct display_iterator. */
1497
1498static void
1499x_produce_image_glyph (it)
1500 struct it *it;
1501{
1502 struct image *img;
1503 struct face *face;
1504
1505 xassert (it->what == IT_IMAGE);
1506
1507 face = FACE_FROM_ID (it->f, it->face_id);
1508 img = IMAGE_FROM_ID (it->f, it->image_id);
1509 xassert (img);
1510
1511 /* Make sure X resources of the face and image are loaded. */
1512 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1513 prepare_image_for_display (it->f, img);
1514
95af8492 1515 it->ascent = it->phys_ascent = image_ascent (img, face);
22d650b8
GM
1516 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1517 it->pixel_width = img->width + 2 * img->hmargin;
06a2c219
GM
1518
1519 it->nglyphs = 1;
1520
1521 if (face->box != FACE_NO_BOX)
1522 {
ea2ba0d4
KH
1523 if (face->box_line_width > 0)
1524 {
1525 it->ascent += face->box_line_width;
1526 it->descent += face->box_line_width;
1527 }
06a2c219
GM
1528
1529 if (it->start_of_box_run_p)
ea2ba0d4 1530 it->pixel_width += abs (face->box_line_width);
06a2c219 1531 if (it->end_of_box_run_p)
ea2ba0d4 1532 it->pixel_width += abs (face->box_line_width);
06a2c219
GM
1533 }
1534
1535 take_vertical_position_into_account (it);
1536
1537 if (it->glyph_row)
1538 {
1539 struct glyph *glyph;
1540 enum glyph_row_area area = it->area;
1541
1542 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1543 if (glyph < it->glyph_row->glyphs[area + 1])
1544 {
06a2c219
GM
1545 glyph->charpos = CHARPOS (it->position);
1546 glyph->object = it->object;
88d75730 1547 glyph->pixel_width = it->pixel_width;
06a2c219 1548 glyph->voffset = it->voffset;
88d75730 1549 glyph->type = IMAGE_GLYPH;
06a2c219 1550 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1551 glyph->left_box_line_p = it->start_of_box_run_p;
1552 glyph->right_box_line_p = it->end_of_box_run_p;
1553 glyph->overlaps_vertically_p = 0;
1554 glyph->padding_p = 0;
1555 glyph->glyph_not_available_p = 0;
1556 glyph->face_id = it->face_id;
1557 glyph->u.img_id = img->id;
06a2c219
GM
1558 ++it->glyph_row->used[area];
1559 }
1560 }
1561}
1562
1563
1564/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1565 of the glyph, WIDTH and HEIGHT are the width and height of the
1566 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1567 ascent of the glyph (0 <= ASCENT <= 1). */
1568
1569static void
1570x_append_stretch_glyph (it, object, width, height, ascent)
1571 struct it *it;
1572 Lisp_Object object;
1573 int width, height;
1574 double ascent;
1575{
1576 struct glyph *glyph;
1577 enum glyph_row_area area = it->area;
1578
1579 xassert (ascent >= 0 && ascent <= 1);
1580
1581 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1582 if (glyph < it->glyph_row->glyphs[area + 1])
1583 {
06a2c219
GM
1584 glyph->charpos = CHARPOS (it->position);
1585 glyph->object = object;
88d75730 1586 glyph->pixel_width = width;
06a2c219 1587 glyph->voffset = it->voffset;
88d75730 1588 glyph->type = STRETCH_GLYPH;
06a2c219 1589 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1590 glyph->left_box_line_p = it->start_of_box_run_p;
1591 glyph->right_box_line_p = it->end_of_box_run_p;
1592 glyph->overlaps_vertically_p = 0;
1593 glyph->padding_p = 0;
1594 glyph->glyph_not_available_p = 0;
1595 glyph->face_id = it->face_id;
1596 glyph->u.stretch.ascent = height * ascent;
1597 glyph->u.stretch.height = height;
06a2c219
GM
1598 ++it->glyph_row->used[area];
1599 }
1600}
1601
1602
1603/* Produce a stretch glyph for iterator IT. IT->object is the value
1604 of the glyph property displayed. The value must be a list
1605 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1606 being recognized:
1607
1608 1. `:width WIDTH' specifies that the space should be WIDTH *
1609 canonical char width wide. WIDTH may be an integer or floating
1610 point number.
1611
1612 2. `:relative-width FACTOR' specifies that the width of the stretch
1613 should be computed from the width of the first character having the
1614 `glyph' property, and should be FACTOR times that width.
1615
1616 3. `:align-to HPOS' specifies that the space should be wide enough
1617 to reach HPOS, a value in canonical character units.
1618
1619 Exactly one of the above pairs must be present.
1620
1621 4. `:height HEIGHT' specifies that the height of the stretch produced
1622 should be HEIGHT, measured in canonical character units.
1623
1624 5. `:relative-height FACTOR' specifies that the height of the the
1625 stretch should be FACTOR times the height of the characters having
1626 the glyph property.
1627
1628 Either none or exactly one of 4 or 5 must be present.
1629
1630 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1631 of the stretch should be used for the ascent of the stretch.
1632 ASCENT must be in the range 0 <= ASCENT <= 100. */
1633
1634#define NUMVAL(X) \
1635 ((INTEGERP (X) || FLOATP (X)) \
1636 ? XFLOATINT (X) \
1637 : - 1)
1638
1639
1640static void
1641x_produce_stretch_glyph (it)
1642 struct it *it;
1643{
1644 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1645#if GLYPH_DEBUG
1646 extern Lisp_Object Qspace;
1647#endif
1648 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1649 extern Lisp_Object QCrelative_width, QCrelative_height;
1650 extern Lisp_Object QCalign_to;
1651 Lisp_Object prop, plist;
1652 double width = 0, height = 0, ascent = 0;
1653 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1654 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1655
1656 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1657
1658 /* List should start with `space'. */
1659 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1660 plist = XCDR (it->object);
1661
1662 /* Compute the width of the stretch. */
1663 if (prop = Fplist_get (plist, QCwidth),
1664 NUMVAL (prop) > 0)
1665 /* Absolute width `:width WIDTH' specified and valid. */
1666 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1667 else if (prop = Fplist_get (plist, QCrelative_width),
1668 NUMVAL (prop) > 0)
1669 {
1670 /* Relative width `:relative-width FACTOR' specified and valid.
1671 Compute the width of the characters having the `glyph'
1672 property. */
1673 struct it it2;
1674 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1675
1676 it2 = *it;
1677 if (it->multibyte_p)
1678 {
1679 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1680 - IT_BYTEPOS (*it));
1681 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1682 }
1683 else
1684 it2.c = *p, it2.len = 1;
1685
1686 it2.glyph_row = NULL;
1687 it2.what = IT_CHARACTER;
1688 x_produce_glyphs (&it2);
1689 width = NUMVAL (prop) * it2.pixel_width;
1690 }
1691 else if (prop = Fplist_get (plist, QCalign_to),
1692 NUMVAL (prop) > 0)
1693 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1694 else
1695 /* Nothing specified -> width defaults to canonical char width. */
1696 width = CANON_X_UNIT (it->f);
1697
1698 /* Compute height. */
1699 if (prop = Fplist_get (plist, QCheight),
1700 NUMVAL (prop) > 0)
1701 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1702 else if (prop = Fplist_get (plist, QCrelative_height),
1703 NUMVAL (prop) > 0)
1704 height = FONT_HEIGHT (font) * NUMVAL (prop);
1705 else
1706 height = FONT_HEIGHT (font);
1707
1708 /* Compute percentage of height used for ascent. If
1709 `:ascent ASCENT' is present and valid, use that. Otherwise,
1710 derive the ascent from the font in use. */
1711 if (prop = Fplist_get (plist, QCascent),
1712 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1713 ascent = NUMVAL (prop) / 100.0;
1714 else
1715 ascent = (double) font->ascent / FONT_HEIGHT (font);
1716
1717 if (width <= 0)
1718 width = 1;
1719 if (height <= 0)
1720 height = 1;
1721
1722 if (it->glyph_row)
1723 {
1724 Lisp_Object object = it->stack[it->sp - 1].string;
1725 if (!STRINGP (object))
1726 object = it->w->buffer;
1727 x_append_stretch_glyph (it, object, width, height, ascent);
1728 }
1729
1730 it->pixel_width = width;
66ac4b0e
GM
1731 it->ascent = it->phys_ascent = height * ascent;
1732 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1733 it->nglyphs = 1;
1734
1735 if (face->box != FACE_NO_BOX)
1736 {
ea2ba0d4
KH
1737 if (face->box_line_width > 0)
1738 {
1739 it->ascent += face->box_line_width;
1740 it->descent += face->box_line_width;
1741 }
06a2c219
GM
1742
1743 if (it->start_of_box_run_p)
ea2ba0d4 1744 it->pixel_width += abs (face->box_line_width);
06a2c219 1745 if (it->end_of_box_run_p)
ea2ba0d4 1746 it->pixel_width += abs (face->box_line_width);
06a2c219
GM
1747 }
1748
1749 take_vertical_position_into_account (it);
1750}
1751
b4192550
KH
1752/* Return proper value to be used as baseline offset of font that has
1753 ASCENT and DESCENT to draw characters by the font at the vertical
1754 center of the line of frame F.
1755
1756 Here, out task is to find the value of BOFF in the following figure;
1757
1758 -------------------------+-----------+-
1759 -+-+---------+-+ | |
1760 | | | | | |
1761 | | | | F_ASCENT F_HEIGHT
1762 | | | ASCENT | |
1763 HEIGHT | | | | |
1764 | | |-|-+------+-----------|------- baseline
1765 | | | | BOFF | |
1766 | |---------|-+-+ | |
1767 | | | DESCENT | |
1768 -+-+---------+-+ F_DESCENT |
1769 -------------------------+-----------+-
1770
1771 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1772 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1773 DESCENT = FONT->descent
1774 HEIGHT = FONT_HEIGHT (FONT)
1775 F_DESCENT = (F->output_data.x->font->descent
1776 - F->output_data.x->baseline_offset)
1777 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1778*/
1779
458f45fa
KH
1780#define VCENTER_BASELINE_OFFSET(FONT, F) \
1781 ((FONT)->descent \
1782 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1783 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1784 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1785
1786/* Produce glyphs/get display metrics for the display element IT is
1787 loaded with. See the description of struct display_iterator in
1788 dispextern.h for an overview of struct display_iterator. */
1789
1790static void
1791x_produce_glyphs (it)
1792 struct it *it;
1793{
ee569018
KH
1794 it->glyph_not_available_p = 0;
1795
06a2c219
GM
1796 if (it->what == IT_CHARACTER)
1797 {
1798 XChar2b char2b;
1799 XFontStruct *font;
ee569018 1800 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1801 XCharStruct *pcm;
06a2c219 1802 int font_not_found_p;
b4192550
KH
1803 struct font_info *font_info;
1804 int boff; /* baseline offset */
a4249304
KH
1805 /* We may change it->multibyte_p upon unibyte<->multibyte
1806 conversion. So, save the current value now and restore it
1807 later.
1808
1809 Note: It seems that we don't have to record multibyte_p in
1810 struct glyph because the character code itself tells if or
1811 not the character is multibyte. Thus, in the future, we must
1812 consider eliminating the field `multibyte_p' in the struct
1813 glyph.
1814 */
1815 int saved_multibyte_p = it->multibyte_p;
06a2c219 1816
ee569018
KH
1817 /* Maybe translate single-byte characters to multibyte, or the
1818 other way. */
06a2c219 1819 it->char_to_display = it->c;
ee569018 1820 if (!ASCII_BYTE_P (it->c))
06a2c219 1821 {
ee569018
KH
1822 if (unibyte_display_via_language_environment
1823 && SINGLE_BYTE_CHAR_P (it->c)
1824 && (it->c >= 0240
1825 || !NILP (Vnonascii_translation_table)))
1826 {
1827 it->char_to_display = unibyte_char_to_multibyte (it->c);
a4249304 1828 it->multibyte_p = 1;
ee569018
KH
1829 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1830 face = FACE_FROM_ID (it->f, it->face_id);
1831 }
1832 else if (!SINGLE_BYTE_CHAR_P (it->c)
1833 && !it->multibyte_p)
1834 {
1835 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
a4249304 1836 it->multibyte_p = 0;
ee569018
KH
1837 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1838 face = FACE_FROM_ID (it->f, it->face_id);
1839 }
06a2c219
GM
1840 }
1841
ee569018
KH
1842 /* Get font to use. Encode IT->char_to_display. */
1843 x_get_char_face_and_encoding (it->f, it->char_to_display,
1844 it->face_id, &char2b,
1845 it->multibyte_p);
06a2c219
GM
1846 font = face->font;
1847
1848 /* When no suitable font found, use the default font. */
1849 font_not_found_p = font == NULL;
1850 if (font_not_found_p)
b4192550
KH
1851 {
1852 font = FRAME_FONT (it->f);
1853 boff = it->f->output_data.x->baseline_offset;
1854 font_info = NULL;
1855 }
1856 else
1857 {
1858 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1859 boff = font_info->baseline_offset;
1860 if (font_info->vertical_centering)
1861 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1862 }
06a2c219
GM
1863
1864 if (it->char_to_display >= ' '
1865 && (!it->multibyte_p || it->char_to_display < 128))
1866 {
1867 /* Either unibyte or ASCII. */
1868 int stretched_p;
1869
1870 it->nglyphs = 1;
06a2c219
GM
1871
1872 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1873 it->ascent = font->ascent + boff;
1874 it->descent = font->descent - boff;
474848ac
GM
1875
1876 if (pcm)
1877 {
1878 it->phys_ascent = pcm->ascent + boff;
1879 it->phys_descent = pcm->descent - boff;
1880 it->pixel_width = pcm->width;
1881 }
1882 else
1883 {
1884 it->glyph_not_available_p = 1;
1885 it->phys_ascent = font->ascent + boff;
1886 it->phys_descent = font->descent - boff;
1887 it->pixel_width = FONT_WIDTH (font);
1888 }
06a2c219
GM
1889
1890 /* If this is a space inside a region of text with
1891 `space-width' property, change its width. */
1892 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1893 if (stretched_p)
1894 it->pixel_width *= XFLOATINT (it->space_width);
1895
1896 /* If face has a box, add the box thickness to the character
1897 height. If character has a box line to the left and/or
1898 right, add the box line width to the character's width. */
1899 if (face->box != FACE_NO_BOX)
1900 {
1901 int thick = face->box_line_width;
1902
ea2ba0d4
KH
1903 if (thick > 0)
1904 {
1905 it->ascent += thick;
1906 it->descent += thick;
1907 }
1908 else
1909 thick = -thick;
1910
06a2c219
GM
1911 if (it->start_of_box_run_p)
1912 it->pixel_width += thick;
1913 if (it->end_of_box_run_p)
1914 it->pixel_width += thick;
1915 }
1916
1917 /* If face has an overline, add the height of the overline
1918 (1 pixel) and a 1 pixel margin to the character height. */
1919 if (face->overline_p)
1920 it->ascent += 2;
1921
1922 take_vertical_position_into_account (it);
1923
1924 /* If we have to actually produce glyphs, do it. */
1925 if (it->glyph_row)
1926 {
1927 if (stretched_p)
1928 {
1929 /* Translate a space with a `space-width' property
1930 into a stretch glyph. */
1931 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1932 x_append_stretch_glyph (it, it->object, it->pixel_width,
1933 it->ascent + it->descent, ascent);
1934 }
1935 else
1936 x_append_glyph (it);
1937
1938 /* If characters with lbearing or rbearing are displayed
1939 in this line, record that fact in a flag of the
1940 glyph row. This is used to optimize X output code. */
1c7e22fd 1941 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1942 it->glyph_row->contains_overlapping_glyphs_p = 1;
1943 }
1944 }
1945 else if (it->char_to_display == '\n')
1946 {
1947 /* A newline has no width but we need the height of the line. */
1948 it->pixel_width = 0;
1949 it->nglyphs = 0;
b4192550
KH
1950 it->ascent = it->phys_ascent = font->ascent + boff;
1951 it->descent = it->phys_descent = font->descent - boff;
06a2c219 1952
ea2ba0d4
KH
1953 if (face->box != FACE_NO_BOX
1954 && face->box_line_width > 0)
06a2c219 1955 {
ea2ba0d4
KH
1956 it->ascent += face->box_line_width;
1957 it->descent += face->box_line_width;
06a2c219
GM
1958 }
1959 }
1960 else if (it->char_to_display == '\t')
1961 {
1962 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1963 int x = it->current_x + it->continuation_lines_width;
06a2c219 1964 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2a32b5ea
GM
1965
1966 /* If the distance from the current position to the next tab
1967 stop is less than a canonical character width, use the
1968 tab stop after that. */
1969 if (next_tab_x - x < CANON_X_UNIT (it->f))
1970 next_tab_x += tab_width;
06a2c219
GM
1971
1972 it->pixel_width = next_tab_x - x;
1973 it->nglyphs = 1;
b4192550
KH
1974 it->ascent = it->phys_ascent = font->ascent + boff;
1975 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1976
1977 if (it->glyph_row)
1978 {
1979 double ascent = (double) it->ascent / (it->ascent + it->descent);
1980 x_append_stretch_glyph (it, it->object, it->pixel_width,
1981 it->ascent + it->descent, ascent);
1982 }
1983 }
1984 else
1985 {
1986 /* A multi-byte character. Assume that the display width of the
1987 character is the width of the character multiplied by the
b4192550 1988 width of the font. */
06a2c219 1989
b4192550
KH
1990 /* If we found a font, this font should give us the right
1991 metrics. If we didn't find a font, use the frame's
1992 default font and calculate the width of the character
1993 from the charset width; this is what old redisplay code
1994 did. */
1995 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1996 if (font_not_found_p || !pcm)
1997 {
1998 int charset = CHAR_CHARSET (it->char_to_display);
1999
2000 it->glyph_not_available_p = 1;
2001 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2002 * CHARSET_WIDTH (charset));
2003 it->phys_ascent = font->ascent + boff;
2004 it->phys_descent = font->descent - boff;
2005 }
2006 else
2007 {
2008 it->pixel_width = pcm->width;
2009 it->phys_ascent = pcm->ascent + boff;
2010 it->phys_descent = pcm->descent - boff;
2011 if (it->glyph_row
2012 && (pcm->lbearing < 0
2013 || pcm->rbearing > pcm->width))
2014 it->glyph_row->contains_overlapping_glyphs_p = 1;
2015 }
b4192550
KH
2016 it->nglyphs = 1;
2017 it->ascent = font->ascent + boff;
2018 it->descent = font->descent - boff;
06a2c219
GM
2019 if (face->box != FACE_NO_BOX)
2020 {
2021 int thick = face->box_line_width;
ea2ba0d4
KH
2022
2023 if (thick > 0)
2024 {
2025 it->ascent += thick;
2026 it->descent += thick;
2027 }
2028 else
2029 thick = - thick;
06a2c219
GM
2030
2031 if (it->start_of_box_run_p)
2032 it->pixel_width += thick;
2033 if (it->end_of_box_run_p)
2034 it->pixel_width += thick;
2035 }
2036
2037 /* If face has an overline, add the height of the overline
2038 (1 pixel) and a 1 pixel margin to the character height. */
2039 if (face->overline_p)
2040 it->ascent += 2;
2041
2042 take_vertical_position_into_account (it);
2043
2044 if (it->glyph_row)
2045 x_append_glyph (it);
2046 }
a4249304 2047 it->multibyte_p = saved_multibyte_p;
06a2c219 2048 }
b4192550
KH
2049 else if (it->what == IT_COMPOSITION)
2050 {
2051 /* Note: A composition is represented as one glyph in the
2052 glyph matrix. There are no padding glyphs. */
2053 XChar2b char2b;
2054 XFontStruct *font;
ee569018 2055 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2056 XCharStruct *pcm;
2057 int font_not_found_p;
2058 struct font_info *font_info;
2059 int boff; /* baseline offset */
2060 struct composition *cmp = composition_table[it->cmp_id];
2061
2062 /* Maybe translate single-byte characters to multibyte. */
2063 it->char_to_display = it->c;
2064 if (unibyte_display_via_language_environment
2065 && SINGLE_BYTE_CHAR_P (it->c)
2066 && (it->c >= 0240
2067 || (it->c >= 0200
2068 && !NILP (Vnonascii_translation_table))))
2069 {
2070 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2071 }
2072
2073 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2074 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2075 face = FACE_FROM_ID (it->f, it->face_id);
2076 x_get_char_face_and_encoding (it->f, it->char_to_display,
2077 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2078 font = face->font;
2079
2080 /* When no suitable font found, use the default font. */
2081 font_not_found_p = font == NULL;
2082 if (font_not_found_p)
2083 {
2084 font = FRAME_FONT (it->f);
2085 boff = it->f->output_data.x->baseline_offset;
2086 font_info = NULL;
2087 }
2088 else
2089 {
2090 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2091 boff = font_info->baseline_offset;
2092 if (font_info->vertical_centering)
2093 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2094 }
2095
2096 /* There are no padding glyphs, so there is only one glyph to
2097 produce for the composition. Important is that pixel_width,
2098 ascent and descent are the values of what is drawn by
2099 draw_glyphs (i.e. the values of the overall glyphs composed). */
2100 it->nglyphs = 1;
2101
2102 /* If we have not yet calculated pixel size data of glyphs of
2103 the composition for the current face font, calculate them
2104 now. Theoretically, we have to check all fonts for the
2105 glyphs, but that requires much time and memory space. So,
2106 here we check only the font of the first glyph. This leads
2107 to incorrect display very rarely, and C-l (recenter) can
2108 correct the display anyway. */
2109 if (cmp->font != (void *) font)
2110 {
2111 /* Ascent and descent of the font of the first character of
2112 this composition (adjusted by baseline offset). Ascent
2113 and descent of overall glyphs should not be less than
2114 them respectively. */
2115 int font_ascent = font->ascent + boff;
2116 int font_descent = font->descent - boff;
2117 /* Bounding box of the overall glyphs. */
2118 int leftmost, rightmost, lowest, highest;
329bed06 2119 int i, width, ascent, descent;
b4192550
KH
2120
2121 cmp->font = (void *) font;
2122
2123 /* Initialize the bounding box. */
1bdeec2e
KH
2124 if (font_info
2125 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2126 {
2127 width = pcm->width;
2128 ascent = pcm->ascent;
2129 descent = pcm->descent;
2130 }
2131 else
2132 {
2133 width = FONT_WIDTH (font);
2134 ascent = font->ascent;
2135 descent = font->descent;
2136 }
2137
2138 rightmost = width;
2139 lowest = - descent + boff;
2140 highest = ascent + boff;
b4192550 2141 leftmost = 0;
329bed06 2142
b4192550
KH
2143 if (font_info
2144 && font_info->default_ascent
2145 && CHAR_TABLE_P (Vuse_default_ascent)
2146 && !NILP (Faref (Vuse_default_ascent,
2147 make_number (it->char_to_display))))
2148 highest = font_info->default_ascent + boff;
2149
2150 /* Draw the first glyph at the normal position. It may be
2151 shifted to right later if some other glyphs are drawn at
2152 the left. */
2153 cmp->offsets[0] = 0;
2154 cmp->offsets[1] = boff;
2155
2156 /* Set cmp->offsets for the remaining glyphs. */
2157 for (i = 1; i < cmp->glyph_len; i++)
2158 {
2159 int left, right, btm, top;
2160 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2161 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2162
2163 face = FACE_FROM_ID (it->f, face_id);
2164 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2165 it->multibyte_p);
b4192550
KH
2166 font = face->font;
2167 if (font == NULL)
2168 {
2169 font = FRAME_FONT (it->f);
2170 boff = it->f->output_data.x->baseline_offset;
2171 font_info = NULL;
2172 }
2173 else
2174 {
2175 font_info
2176 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2177 boff = font_info->baseline_offset;
2178 if (font_info->vertical_centering)
2179 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2180 }
2181
1bdeec2e
KH
2182 if (font_info
2183 && (pcm = x_per_char_metric (font, &char2b)))
329bed06
GM
2184 {
2185 width = pcm->width;
2186 ascent = pcm->ascent;
2187 descent = pcm->descent;
2188 }
2189 else
2190 {
2191 width = FONT_WIDTH (font);
1bdeec2e
KH
2192 ascent = 1;
2193 descent = 0;
329bed06 2194 }
b4192550
KH
2195
2196 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2197 {
2198 /* Relative composition with or without
2199 alternate chars. */
329bed06
GM
2200 left = (leftmost + rightmost - width) / 2;
2201 btm = - descent + boff;
b4192550
KH
2202 if (font_info && font_info->relative_compose
2203 && (! CHAR_TABLE_P (Vignore_relative_composition)
2204 || NILP (Faref (Vignore_relative_composition,
2205 make_number (ch)))))
2206 {
2207
329bed06 2208 if (- descent >= font_info->relative_compose)
b4192550
KH
2209 /* One extra pixel between two glyphs. */
2210 btm = highest + 1;
329bed06 2211 else if (ascent <= 0)
b4192550 2212 /* One extra pixel between two glyphs. */
329bed06 2213 btm = lowest - 1 - ascent - descent;
b4192550
KH
2214 }
2215 }
2216 else
2217 {
2218 /* A composition rule is specified by an integer
2219 value that encodes global and new reference
2220 points (GREF and NREF). GREF and NREF are
2221 specified by numbers as below:
2222
2223 0---1---2 -- ascent
2224 | |
2225 | |
2226 | |
2227 9--10--11 -- center
2228 | |
2229 ---3---4---5--- baseline
2230 | |
2231 6---7---8 -- descent
2232 */
2233 int rule = COMPOSITION_RULE (cmp, i);
2234 int gref, nref, grefx, grefy, nrefx, nrefy;
2235
2236 COMPOSITION_DECODE_RULE (rule, gref, nref);
2237 grefx = gref % 3, nrefx = nref % 3;
2238 grefy = gref / 3, nrefy = nref / 3;
2239
2240 left = (leftmost
2241 + grefx * (rightmost - leftmost) / 2
329bed06 2242 - nrefx * width / 2);
b4192550
KH
2243 btm = ((grefy == 0 ? highest
2244 : grefy == 1 ? 0
2245 : grefy == 2 ? lowest
2246 : (highest + lowest) / 2)
329bed06
GM
2247 - (nrefy == 0 ? ascent + descent
2248 : nrefy == 1 ? descent - boff
b4192550 2249 : nrefy == 2 ? 0
329bed06 2250 : (ascent + descent) / 2));
b4192550
KH
2251 }
2252
2253 cmp->offsets[i * 2] = left;
329bed06 2254 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2255
2256 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2257 right = left + width;
2258 top = btm + descent + ascent;
b4192550
KH
2259 if (left < leftmost)
2260 leftmost = left;
2261 if (right > rightmost)
2262 rightmost = right;
2263 if (top > highest)
2264 highest = top;
2265 if (btm < lowest)
2266 lowest = btm;
2267 }
2268
2269 /* If there are glyphs whose x-offsets are negative,
2270 shift all glyphs to the right and make all x-offsets
2271 non-negative. */
2272 if (leftmost < 0)
2273 {
2274 for (i = 0; i < cmp->glyph_len; i++)
2275 cmp->offsets[i * 2] -= leftmost;
2276 rightmost -= leftmost;
2277 }
2278
2279 cmp->pixel_width = rightmost;
2280 cmp->ascent = highest;
2281 cmp->descent = - lowest;
2282 if (cmp->ascent < font_ascent)
2283 cmp->ascent = font_ascent;
2284 if (cmp->descent < font_descent)
2285 cmp->descent = font_descent;
2286 }
2287
2288 it->pixel_width = cmp->pixel_width;
2289 it->ascent = it->phys_ascent = cmp->ascent;
2290 it->descent = it->phys_descent = cmp->descent;
2291
2292 if (face->box != FACE_NO_BOX)
2293 {
2294 int thick = face->box_line_width;
ea2ba0d4
KH
2295
2296 if (thick > 0)
2297 {
2298 it->ascent += thick;
2299 it->descent += thick;
2300 }
2301 else
2302 thick = - thick;
b4192550
KH
2303
2304 if (it->start_of_box_run_p)
2305 it->pixel_width += thick;
2306 if (it->end_of_box_run_p)
2307 it->pixel_width += thick;
2308 }
2309
2310 /* If face has an overline, add the height of the overline
2311 (1 pixel) and a 1 pixel margin to the character height. */
2312 if (face->overline_p)
2313 it->ascent += 2;
2314
2315 take_vertical_position_into_account (it);
2316
2317 if (it->glyph_row)
2318 x_append_composite_glyph (it);
2319 }
06a2c219
GM
2320 else if (it->what == IT_IMAGE)
2321 x_produce_image_glyph (it);
2322 else if (it->what == IT_STRETCH)
2323 x_produce_stretch_glyph (it);
2324
3017fdd1
GM
2325 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2326 because this isn't true for images with `:ascent 100'. */
2327 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2328 if (it->area == TEXT_AREA)
2329 it->current_x += it->pixel_width;
66ac4b0e 2330
d365f5bb
GM
2331 it->descent += it->extra_line_spacing;
2332
06a2c219
GM
2333 it->max_ascent = max (it->max_ascent, it->ascent);
2334 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2335 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2336 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2337}
2338
2339
2340/* Estimate the pixel height of the mode or top line on frame F.
2341 FACE_ID specifies what line's height to estimate. */
2342
2343int
2344x_estimate_mode_line_height (f, face_id)
2345 struct frame *f;
2346 enum face_id face_id;
2347{
43281ee3 2348 int height = FONT_HEIGHT (FRAME_FONT (f));
06a2c219
GM
2349
2350 /* This function is called so early when Emacs starts that the face
2351 cache and mode line face are not yet initialized. */
2352 if (FRAME_FACE_CACHE (f))
2353 {
2354 struct face *face = FACE_FROM_ID (f, face_id);
2355 if (face)
43281ee3
GM
2356 {
2357 if (face->font)
2358 height = FONT_HEIGHT (face->font);
ea2ba0d4
KH
2359 if (face->box_line_width > 0)
2360 height += 2 * face->box_line_width;
43281ee3 2361 }
06a2c219
GM
2362 }
2363
2364 return height;
2365}
2366
2367\f
2368/***********************************************************************
2369 Glyph display
2370 ***********************************************************************/
2371
2372/* A sequence of glyphs to be drawn in the same face.
2373
2374 This data structure is not really completely X specific, so it
2375 could possibly, at least partially, be useful for other systems. It
2376 is currently not part of the external redisplay interface because
2377 it's not clear what other systems will need. */
2378
2379struct glyph_string
2380{
2381 /* X-origin of the string. */
2382 int x;
2383
2384 /* Y-origin and y-position of the base line of this string. */
2385 int y, ybase;
2386
2387 /* The width of the string, not including a face extension. */
2388 int width;
2389
2390 /* The width of the string, including a face extension. */
2391 int background_width;
2392
2393 /* The height of this string. This is the height of the line this
2394 string is drawn in, and can be different from the height of the
2395 font the string is drawn in. */
2396 int height;
2397
2398 /* Number of pixels this string overwrites in front of its x-origin.
2399 This number is zero if the string has an lbearing >= 0; it is
2400 -lbearing, if the string has an lbearing < 0. */
2401 int left_overhang;
2402
2403 /* Number of pixels this string overwrites past its right-most
2404 nominal x-position, i.e. x + width. Zero if the string's
2405 rbearing is <= its nominal width, rbearing - width otherwise. */
2406 int right_overhang;
2407
2408 /* The frame on which the glyph string is drawn. */
2409 struct frame *f;
2410
2411 /* The window on which the glyph string is drawn. */
2412 struct window *w;
2413
2414 /* X display and window for convenience. */
2415 Display *display;
2416 Window window;
2417
2418 /* The glyph row for which this string was built. It determines the
2419 y-origin and height of the string. */
2420 struct glyph_row *row;
2421
2422 /* The area within row. */
2423 enum glyph_row_area area;
2424
2425 /* Characters to be drawn, and number of characters. */
2426 XChar2b *char2b;
2427 int nchars;
2428
06a2c219
GM
2429 /* A face-override for drawing cursors, mouse face and similar. */
2430 enum draw_glyphs_face hl;
2431
2432 /* Face in which this string is to be drawn. */
2433 struct face *face;
2434
2435 /* Font in which this string is to be drawn. */
2436 XFontStruct *font;
2437
2438 /* Font info for this string. */
2439 struct font_info *font_info;
2440
b4192550
KH
2441 /* Non-null means this string describes (part of) a composition.
2442 All characters from char2b are drawn composed. */
2443 struct composition *cmp;
06a2c219
GM
2444
2445 /* Index of this glyph string's first character in the glyph
b4192550
KH
2446 definition of CMP. If this is zero, this glyph string describes
2447 the first character of a composition. */
06a2c219
GM
2448 int gidx;
2449
2450 /* 1 means this glyph strings face has to be drawn to the right end
2451 of the window's drawing area. */
2452 unsigned extends_to_end_of_line_p : 1;
2453
2454 /* 1 means the background of this string has been drawn. */
2455 unsigned background_filled_p : 1;
2456
2457 /* 1 means glyph string must be drawn with 16-bit functions. */
2458 unsigned two_byte_p : 1;
2459
2460 /* 1 means that the original font determined for drawing this glyph
2461 string could not be loaded. The member `font' has been set to
2462 the frame's default font in this case. */
2463 unsigned font_not_found_p : 1;
2464
2465 /* 1 means that the face in which this glyph string is drawn has a
2466 stipple pattern. */
2467 unsigned stippled_p : 1;
2468
66ac4b0e
GM
2469 /* 1 means only the foreground of this glyph string must be drawn,
2470 and we should use the physical height of the line this glyph
2471 string appears in as clip rect. */
2472 unsigned for_overlaps_p : 1;
2473
06a2c219
GM
2474 /* The GC to use for drawing this glyph string. */
2475 GC gc;
2476
2477 /* A pointer to the first glyph in the string. This glyph
2478 corresponds to char2b[0]. Needed to draw rectangles if
2479 font_not_found_p is 1. */
2480 struct glyph *first_glyph;
2481
2482 /* Image, if any. */
2483 struct image *img;
2484
2485 struct glyph_string *next, *prev;
2486};
2487
2488
57ac7c81 2489#if 1
06a2c219
GM
2490
2491static void
2492x_dump_glyph_string (s)
2493 struct glyph_string *s;
2494{
2495 fprintf (stderr, "glyph string\n");
2496 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2497 s->x, s->y, s->width, s->height);
2498 fprintf (stderr, " ybase = %d\n", s->ybase);
2499 fprintf (stderr, " hl = %d\n", s->hl);
2500 fprintf (stderr, " left overhang = %d, right = %d\n",
2501 s->left_overhang, s->right_overhang);
2502 fprintf (stderr, " nchars = %d\n", s->nchars);
2503 fprintf (stderr, " extends to end of line = %d\n",
2504 s->extends_to_end_of_line_p);
2505 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2506 fprintf (stderr, " bg width = %d\n", s->background_width);
2507}
2508
2509#endif /* GLYPH_DEBUG */
2510
2511
2512
2513static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2514 struct glyph_string **,
2515 struct glyph_string *,
2516 struct glyph_string *));
2517static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2518 struct glyph_string **,
2519 struct glyph_string *,
2520 struct glyph_string *));
2521static void x_append_glyph_string P_ ((struct glyph_string **,
2522 struct glyph_string **,
2523 struct glyph_string *));
2524static int x_left_overwritten P_ ((struct glyph_string *));
2525static int x_left_overwriting P_ ((struct glyph_string *));
2526static int x_right_overwritten P_ ((struct glyph_string *));
2527static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2528static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2529 int));
06a2c219
GM
2530static void x_init_glyph_string P_ ((struct glyph_string *,
2531 XChar2b *, struct window *,
2532 struct glyph_row *,
2533 enum glyph_row_area, int,
2534 enum draw_glyphs_face));
2535static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2536 enum glyph_row_area, int, int,
66ac4b0e 2537 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2538static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2539static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2540static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2541 int));
2542static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2543static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2544static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2545static void x_draw_glyph_string P_ ((struct glyph_string *));
2546static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2547static void x_set_cursor_gc P_ ((struct glyph_string *));
2548static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2549static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2550static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2551 int *, int *));
2552static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2553static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2554 unsigned long *, double, int));
06a2c219 2555static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2556 double, int, unsigned long));
06a2c219
GM
2557static void x_setup_relief_colors P_ ((struct glyph_string *));
2558static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2559static void x_draw_image_relief P_ ((struct glyph_string *));
2560static void x_draw_image_foreground P_ ((struct glyph_string *));
2561static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2562static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2563static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2564 int, int, int));
2565static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2566 int, int, int, int, XRectangle *));
2567static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2568 int, int, int, XRectangle *));
66ac4b0e
GM
2569static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2570 enum glyph_row_area));
209f68d9
GM
2571static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2572 struct glyph_row *,
2573 enum glyph_row_area, int, int));
06a2c219 2574
163dcff3
GM
2575#if GLYPH_DEBUG
2576static void x_check_font P_ ((struct frame *, XFontStruct *));
2577#endif
2578
06a2c219 2579
06a2c219
GM
2580/* Append the list of glyph strings with head H and tail T to the list
2581 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2582
2583static INLINE void
2584x_append_glyph_string_lists (head, tail, h, t)
2585 struct glyph_string **head, **tail;
2586 struct glyph_string *h, *t;
2587{
2588 if (h)
2589 {
2590 if (*head)
2591 (*tail)->next = h;
2592 else
2593 *head = h;
2594 h->prev = *tail;
2595 *tail = t;
2596 }
2597}
2598
2599
2600/* Prepend the list of glyph strings with head H and tail T to the
2601 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2602 result. */
2603
2604static INLINE void
2605x_prepend_glyph_string_lists (head, tail, h, t)
2606 struct glyph_string **head, **tail;
2607 struct glyph_string *h, *t;
2608{
2609 if (h)
2610 {
2611 if (*head)
2612 (*head)->prev = t;
2613 else
2614 *tail = t;
2615 t->next = *head;
2616 *head = h;
2617 }
2618}
2619
2620
2621/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2622 Set *HEAD and *TAIL to the resulting list. */
2623
2624static INLINE void
2625x_append_glyph_string (head, tail, s)
2626 struct glyph_string **head, **tail;
2627 struct glyph_string *s;
2628{
2629 s->next = s->prev = NULL;
2630 x_append_glyph_string_lists (head, tail, s, s);
2631}
2632
2633
2634/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2635 face. */
2636
2637static void
2638x_set_cursor_gc (s)
2639 struct glyph_string *s;
2640{
2641 if (s->font == FRAME_FONT (s->f)
2642 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2643 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2644 && !s->cmp)
06a2c219
GM
2645 s->gc = s->f->output_data.x->cursor_gc;
2646 else
2647 {
2648 /* Cursor on non-default face: must merge. */
2649 XGCValues xgcv;
2650 unsigned long mask;
2651
2652 xgcv.background = s->f->output_data.x->cursor_pixel;
2653 xgcv.foreground = s->face->background;
2654
2655 /* If the glyph would be invisible, try a different foreground. */
2656 if (xgcv.foreground == xgcv.background)
2657 xgcv.foreground = s->face->foreground;
2658 if (xgcv.foreground == xgcv.background)
2659 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2660 if (xgcv.foreground == xgcv.background)
2661 xgcv.foreground = s->face->foreground;
2662
2663 /* Make sure the cursor is distinct from text in this face. */
2664 if (xgcv.background == s->face->background
2665 && xgcv.foreground == s->face->foreground)
2666 {
2667 xgcv.background = s->face->foreground;
2668 xgcv.foreground = s->face->background;
2669 }
2670
2671 IF_DEBUG (x_check_font (s->f, s->font));
2672 xgcv.font = s->font->fid;
2673 xgcv.graphics_exposures = False;
2674 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2675
2676 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2677 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2678 mask, &xgcv);
2679 else
2680 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2681 = XCreateGC (s->display, s->window, mask, &xgcv);
2682
2683 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2684 }
2685}
2686
2687
2688/* Set up S->gc of glyph string S for drawing text in mouse face. */
2689
2690static void
2691x_set_mouse_face_gc (s)
2692 struct glyph_string *s;
2693{
2694 int face_id;
ee569018 2695 struct face *face;
06a2c219 2696
e4ded23c 2697 /* What face has to be used last for the mouse face? */
06a2c219 2698 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2699 face = FACE_FROM_ID (s->f, face_id);
e4ded23c
GM
2700 if (face == NULL)
2701 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2702
033e3e18
GM
2703 if (s->first_glyph->type == CHAR_GLYPH)
2704 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2705 else
2706 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2707 s->face = FACE_FROM_ID (s->f, face_id);
2708 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2709
2710 /* If font in this face is same as S->font, use it. */
2711 if (s->font == s->face->font)
2712 s->gc = s->face->gc;
2713 else
2714 {
2715 /* Otherwise construct scratch_cursor_gc with values from FACE
2716 but font FONT. */
2717 XGCValues xgcv;
2718 unsigned long mask;
2719
2720 xgcv.background = s->face->background;
2721 xgcv.foreground = s->face->foreground;
2722 IF_DEBUG (x_check_font (s->f, s->font));
2723 xgcv.font = s->font->fid;
2724 xgcv.graphics_exposures = False;
2725 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2726
2727 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2728 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2729 mask, &xgcv);
2730 else
2731 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2732 = XCreateGC (s->display, s->window, mask, &xgcv);
2733
2734 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2735 }
2736
2737 xassert (s->gc != 0);
2738}
2739
2740
2741/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2742 Faces to use in the mode line have already been computed when the
2743 matrix was built, so there isn't much to do, here. */
2744
2745static INLINE void
2746x_set_mode_line_face_gc (s)
2747 struct glyph_string *s;
2748{
2749 s->gc = s->face->gc;
06a2c219
GM
2750}
2751
2752
2753/* Set S->gc of glyph string S for drawing that glyph string. Set
2754 S->stippled_p to a non-zero value if the face of S has a stipple
2755 pattern. */
2756
2757static INLINE void
2758x_set_glyph_string_gc (s)
2759 struct glyph_string *s;
2760{
209f68d9
GM
2761 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2762
06a2c219
GM
2763 if (s->hl == DRAW_NORMAL_TEXT)
2764 {
2765 s->gc = s->face->gc;
2766 s->stippled_p = s->face->stipple != 0;
2767 }
2768 else if (s->hl == DRAW_INVERSE_VIDEO)
2769 {
2770 x_set_mode_line_face_gc (s);
2771 s->stippled_p = s->face->stipple != 0;
2772 }
2773 else if (s->hl == DRAW_CURSOR)
2774 {
2775 x_set_cursor_gc (s);
2776 s->stippled_p = 0;
2777 }
2778 else if (s->hl == DRAW_MOUSE_FACE)
2779 {
2780 x_set_mouse_face_gc (s);
2781 s->stippled_p = s->face->stipple != 0;
2782 }
2783 else if (s->hl == DRAW_IMAGE_RAISED
2784 || s->hl == DRAW_IMAGE_SUNKEN)
2785 {
2786 s->gc = s->face->gc;
2787 s->stippled_p = s->face->stipple != 0;
2788 }
2789 else
2790 {
2791 s->gc = s->face->gc;
2792 s->stippled_p = s->face->stipple != 0;
2793 }
2794
2795 /* GC must have been set. */
2796 xassert (s->gc != 0);
2797}
2798
2799
2800/* Return in *R the clipping rectangle for glyph string S. */
2801
2802static void
2803x_get_glyph_string_clip_rect (s, r)
2804 struct glyph_string *s;
2805 XRectangle *r;
2806{
2807 if (s->row->full_width_p)
2808 {
2809 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2810 int canon_x = CANON_X_UNIT (s->f);
2811
2812 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2813 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2814
2815 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2816 {
1da3fd71 2817 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2818 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2819 r->x -= width;
2820 }
2821
b9432a85 2822 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2823
06a2c219
GM
2824 /* Unless displaying a mode or menu bar line, which are always
2825 fully visible, clip to the visible part of the row. */
2826 if (s->w->pseudo_window_p)
2827 r->height = s->row->visible_height;
2828 else
2829 r->height = s->height;
2830 }
2831 else
2832 {
2833 /* This is a text line that may be partially visible. */
2834 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2835 r->width = window_box_width (s->w, s->area);
2836 r->height = s->row->visible_height;
2837 }
2838
2839 /* Don't use S->y for clipping because it doesn't take partially
2840 visible lines into account. For example, it can be negative for
2841 partially visible lines at the top of a window. */
2842 if (!s->row->full_width_p
2843 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2844 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2845 else
2846 r->y = max (0, s->row->y);
06a2c219 2847
9ea173e8 2848 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2849 at the top of the window. */
9ea173e8 2850 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2851 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2852
2853 /* If S draws overlapping rows, it's sufficient to use the top and
2854 bottom of the window for clipping because this glyph string
2855 intentionally draws over other lines. */
2856 if (s->for_overlaps_p)
2857 {
045dee35 2858 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2859 r->height = window_text_bottom_y (s->w) - r->y;
2860 }
2861
2862 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2863}
2864
2865
2866/* Set clipping for output of glyph string S. S may be part of a mode
2867 line or menu if we don't have X toolkit support. */
2868
2869static INLINE void
2870x_set_glyph_string_clipping (s)
2871 struct glyph_string *s;
2872{
2873 XRectangle r;
2874 x_get_glyph_string_clip_rect (s, &r);
2875 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2876}
2877
2878
2879/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2880 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2881
2882static INLINE void
2883x_compute_glyph_string_overhangs (s)
2884 struct glyph_string *s;
2885{
b4192550 2886 if (s->cmp == NULL
06a2c219
GM
2887 && s->first_glyph->type == CHAR_GLYPH)
2888 {
2889 XCharStruct cs;
2890 int direction, font_ascent, font_descent;
2891 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2892 &font_ascent, &font_descent, &cs);
2893 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2894 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2895 }
2896}
2897
2898
2899/* Compute overhangs and x-positions for glyph string S and its
2900 predecessors, or successors. X is the starting x-position for S.
2901 BACKWARD_P non-zero means process predecessors. */
2902
2903static void
2904x_compute_overhangs_and_x (s, x, backward_p)
2905 struct glyph_string *s;
2906 int x;
2907 int backward_p;
2908{
2909 if (backward_p)
2910 {
2911 while (s)
2912 {
2913 x_compute_glyph_string_overhangs (s);
2914 x -= s->width;
2915 s->x = x;
2916 s = s->prev;
2917 }
2918 }
2919 else
2920 {
2921 while (s)
2922 {
2923 x_compute_glyph_string_overhangs (s);
2924 s->x = x;
2925 x += s->width;
2926 s = s->next;
2927 }
2928 }
2929}
2930
2931
2932/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2933 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2934 assumed to be zero. */
06a2c219
GM
2935
2936static void
2937x_get_glyph_overhangs (glyph, f, left, right)
2938 struct glyph *glyph;
2939 struct frame *f;
2940 int *left, *right;
2941{
06a2c219
GM
2942 *left = *right = 0;
2943
b4192550 2944 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2945 {
2946 XFontStruct *font;
2947 struct face *face;
2948 struct font_info *font_info;
2949 XChar2b char2b;
ee569018
KH
2950 XCharStruct *pcm;
2951
2952 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2953 font = face->font;
2954 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2955 if (font
2956 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2957 {
06a2c219
GM
2958 if (pcm->rbearing > pcm->width)
2959 *right = pcm->rbearing - pcm->width;
2960 if (pcm->lbearing < 0)
2961 *left = -pcm->lbearing;
2962 }
2963 }
2964}
2965
2966
2967/* Return the index of the first glyph preceding glyph string S that
2968 is overwritten by S because of S's left overhang. Value is -1
2969 if no glyphs are overwritten. */
2970
2971static int
2972x_left_overwritten (s)
2973 struct glyph_string *s;
2974{
2975 int k;
2976
2977 if (s->left_overhang)
2978 {
2979 int x = 0, i;
2980 struct glyph *glyphs = s->row->glyphs[s->area];
2981 int first = s->first_glyph - glyphs;
2982
2983 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2984 x -= glyphs[i].pixel_width;
2985
2986 k = i + 1;
2987 }
2988 else
2989 k = -1;
2990
2991 return k;
2992}
2993
2994
2995/* Return the index of the first glyph preceding glyph string S that
2996 is overwriting S because of its right overhang. Value is -1 if no
2997 glyph in front of S overwrites S. */
2998
2999static int
3000x_left_overwriting (s)
3001 struct glyph_string *s;
3002{
3003 int i, k, x;
3004 struct glyph *glyphs = s->row->glyphs[s->area];
3005 int first = s->first_glyph - glyphs;
3006
3007 k = -1;
3008 x = 0;
3009 for (i = first - 1; i >= 0; --i)
3010 {
3011 int left, right;
3012 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3013 if (x + right > 0)
3014 k = i;
3015 x -= glyphs[i].pixel_width;
3016 }
3017
3018 return k;
3019}
3020
3021
3022/* Return the index of the last glyph following glyph string S that is
3023 not overwritten by S because of S's right overhang. Value is -1 if
3024 no such glyph is found. */
3025
3026static int
3027x_right_overwritten (s)
3028 struct glyph_string *s;
3029{
3030 int k = -1;
3031
3032 if (s->right_overhang)
3033 {
3034 int x = 0, i;
3035 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3036 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3037 int end = s->row->used[s->area];
3038
3039 for (i = first; i < end && s->right_overhang > x; ++i)
3040 x += glyphs[i].pixel_width;
3041
3042 k = i;
3043 }
3044
3045 return k;
3046}
3047
3048
3049/* Return the index of the last glyph following glyph string S that
3050 overwrites S because of its left overhang. Value is negative
3051 if no such glyph is found. */
3052
3053static int
3054x_right_overwriting (s)
3055 struct glyph_string *s;
3056{
3057 int i, k, x;
3058 int end = s->row->used[s->area];
3059 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3060 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3061
3062 k = -1;
3063 x = 0;
3064 for (i = first; i < end; ++i)
3065 {
3066 int left, right;
3067 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3068 if (x - left < 0)
3069 k = i;
3070 x += glyphs[i].pixel_width;
3071 }
3072
3073 return k;
3074}
3075
3076
3077/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3078
3079static INLINE void
3080x_clear_glyph_string_rect (s, x, y, w, h)
3081 struct glyph_string *s;
3082 int x, y, w, h;
3083{
3084 XGCValues xgcv;
3085 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3086 XSetForeground (s->display, s->gc, xgcv.background);
3087 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3088 XSetForeground (s->display, s->gc, xgcv.foreground);
3089}
3090
3091
3092/* Draw the background of glyph_string S. If S->background_filled_p
3093 is non-zero don't draw it. FORCE_P non-zero means draw the
3094 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3095 when a string preceding S draws into the background of S, or S
3096 contains the first component of a composition. */
06a2c219
GM
3097
3098static void
3099x_draw_glyph_string_background (s, force_p)
3100 struct glyph_string *s;
3101 int force_p;
3102{
3103 /* Nothing to do if background has already been drawn or if it
3104 shouldn't be drawn in the first place. */
3105 if (!s->background_filled_p)
3106 {
ea2ba0d4
KH
3107 int box_line_width = max (s->face->box_line_width, 0);
3108
b4192550 3109 if (s->stippled_p)
06a2c219
GM
3110 {
3111 /* Fill background with a stipple pattern. */
3112 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3113 XFillRectangle (s->display, s->window, s->gc, s->x,
ea2ba0d4 3114 s->y + box_line_width,
06a2c219 3115 s->background_width,
ea2ba0d4 3116 s->height - 2 * box_line_width);
06a2c219
GM
3117 XSetFillStyle (s->display, s->gc, FillSolid);
3118 s->background_filled_p = 1;
3119 }
ea2ba0d4 3120 else if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
06a2c219
GM
3121 || s->font_not_found_p
3122 || s->extends_to_end_of_line_p
06a2c219
GM
3123 || force_p)
3124 {
ea2ba0d4 3125 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
06a2c219 3126 s->background_width,
ea2ba0d4 3127 s->height - 2 * box_line_width);
06a2c219
GM
3128 s->background_filled_p = 1;
3129 }
3130 }
3131}
3132
3133
3134/* Draw the foreground of glyph string S. */
3135
3136static void
3137x_draw_glyph_string_foreground (s)
3138 struct glyph_string *s;
3139{
3140 int i, x;
3141
3142 /* If first glyph of S has a left box line, start drawing the text
3143 of S to the right of that box line. */
3144 if (s->face->box != FACE_NO_BOX
3145 && s->first_glyph->left_box_line_p)
ea2ba0d4 3146 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
3147 else
3148 x = s->x;
3149
b4192550
KH
3150 /* Draw characters of S as rectangles if S's font could not be
3151 loaded. */
3152 if (s->font_not_found_p)
06a2c219 3153 {
b4192550 3154 for (i = 0; i < s->nchars; ++i)
06a2c219 3155 {
b4192550
KH
3156 struct glyph *g = s->first_glyph + i;
3157 XDrawRectangle (s->display, s->window,
3158 s->gc, x, s->y, g->pixel_width - 1,
3159 s->height - 1);
3160 x += g->pixel_width;
06a2c219
GM
3161 }
3162 }
3163 else
3164 {
b4192550
KH
3165 char *char1b = (char *) s->char2b;
3166 int boff = s->font_info->baseline_offset;
06a2c219 3167
b4192550
KH
3168 if (s->font_info->vertical_centering)
3169 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3170
3171 /* If we can use 8-bit functions, condense S->char2b. */
3172 if (!s->two_byte_p)
3173 for (i = 0; i < s->nchars; ++i)
3174 char1b[i] = s->char2b[i].byte2;
3175
3176 /* Draw text with XDrawString if background has already been
3177 filled. Otherwise, use XDrawImageString. (Note that
3178 XDrawImageString is usually faster than XDrawString.) Always
3179 use XDrawImageString when drawing the cursor so that there is
3180 no chance that characters under a box cursor are invisible. */
3181 if (s->for_overlaps_p
3182 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3183 {
3184 /* Draw characters with 16-bit or 8-bit functions. */
3185 if (s->two_byte_p)
3186 XDrawString16 (s->display, s->window, s->gc, x,
3187 s->ybase - boff, s->char2b, s->nchars);
3188 else
3189 XDrawString (s->display, s->window, s->gc, x,
3190 s->ybase - boff, char1b, s->nchars);
3191 }
06a2c219
GM
3192 else
3193 {
b4192550
KH
3194 if (s->two_byte_p)
3195 XDrawImageString16 (s->display, s->window, s->gc, x,
3196 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3197 else
b4192550
KH
3198 XDrawImageString (s->display, s->window, s->gc, x,
3199 s->ybase - boff, char1b, s->nchars);
3200 }
3201 }
3202}
06a2c219 3203
b4192550 3204/* Draw the foreground of composite glyph string S. */
06a2c219 3205
b4192550
KH
3206static void
3207x_draw_composite_glyph_string_foreground (s)
3208 struct glyph_string *s;
3209{
3210 int i, x;
06a2c219 3211
b4192550
KH
3212 /* If first glyph of S has a left box line, start drawing the text
3213 of S to the right of that box line. */
3214 if (s->face->box != FACE_NO_BOX
3215 && s->first_glyph->left_box_line_p)
ea2ba0d4 3216 x = s->x + abs (s->face->box_line_width);
b4192550
KH
3217 else
3218 x = s->x;
06a2c219 3219
b4192550
KH
3220 /* S is a glyph string for a composition. S->gidx is the index of
3221 the first character drawn for glyphs of this composition.
3222 S->gidx == 0 means we are drawing the very first character of
3223 this composition. */
06a2c219 3224
b4192550
KH
3225 /* Draw a rectangle for the composition if the font for the very
3226 first character of the composition could not be loaded. */
3227 if (s->font_not_found_p)
3228 {
3229 if (s->gidx == 0)
3230 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3231 s->width - 1, s->height - 1);
3232 }
3233 else
3234 {
3235 for (i = 0; i < s->nchars; i++, ++s->gidx)
3236 XDrawString16 (s->display, s->window, s->gc,
3237 x + s->cmp->offsets[s->gidx * 2],
3238 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3239 s->char2b + i, 1);
06a2c219
GM
3240 }
3241}
3242
3243
80c32bcc
GM
3244#ifdef USE_X_TOOLKIT
3245
3e71d8f2 3246static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3247
3e71d8f2
GM
3248
3249/* Return the frame on which widget WIDGET is used.. Abort if frame
3250 cannot be determined. */
3251
e851c833 3252static struct frame *
3e71d8f2 3253x_frame_of_widget (widget)
80c32bcc 3254 Widget widget;
80c32bcc 3255{
80c32bcc 3256 struct x_display_info *dpyinfo;
5c187dee 3257 Lisp_Object tail;
3e71d8f2
GM
3258 struct frame *f;
3259
80c32bcc
GM
3260 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3261
3262 /* Find the top-level shell of the widget. Note that this function
3263 can be called when the widget is not yet realized, so XtWindow
3264 (widget) == 0. That's the reason we can't simply use
3265 x_any_window_to_frame. */
3266 while (!XtIsTopLevelShell (widget))
3267 widget = XtParent (widget);
3268
3269 /* Look for a frame with that top-level widget. Allocate the color
3270 on that frame to get the right gamma correction value. */
3271 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3272 if (GC_FRAMEP (XCAR (tail))
3273 && (f = XFRAME (XCAR (tail)),
3274 (f->output_data.nothing != 1
3275 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3276 && f->output_data.x->widget == widget)
3e71d8f2 3277 return f;
80c32bcc
GM
3278
3279 abort ();
3280}
3281
3e71d8f2
GM
3282
3283/* Allocate the color COLOR->pixel on the screen and display of
3284 widget WIDGET in colormap CMAP. If an exact match cannot be
3285 allocated, try the nearest color available. Value is non-zero
3286 if successful. This is called from lwlib. */
3287
3288int
3289x_alloc_nearest_color_for_widget (widget, cmap, color)
3290 Widget widget;
3291 Colormap cmap;
3292 XColor *color;
3293{
3294 struct frame *f = x_frame_of_widget (widget);
3295 return x_alloc_nearest_color (f, cmap, color);
3296}
3297
3298
46d516e5
MB
3299/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3300 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3301 If this produces the same color as PIXEL, try a color where all RGB
3302 values have DELTA added. Return the allocated color in *PIXEL.
3303 DISPLAY is the X display, CMAP is the colormap to operate on.
3304 Value is non-zero if successful. */
3305
3306int
3307x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3308 Widget widget;
3309 Display *display;
3310 Colormap cmap;
3311 unsigned long *pixel;
3312 double factor;
3313 int delta;
3314{
3315 struct frame *f = x_frame_of_widget (widget);
3316 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3317}
3318
3319
80c32bcc
GM
3320#endif /* USE_X_TOOLKIT */
3321
3322
f04e1297
GM
3323/* Value is an array of XColor structures for the contents of the
3324 color map of frame F. Set *NCELLS to the size of the array.
3325 Note that this probably shouldn't be called for large color maps,
3326 say a 24-bit TrueColor map. */
3327
3328static const XColor *
3329x_color_cells (f, ncells)
3330 struct frame *f;
3331 int *ncells;
3332{
3333 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3334
3335 if (dpyinfo->color_cells == NULL)
3336 {
3337 Display *display = FRAME_X_DISPLAY (f);
3338 Screen *screen = FRAME_X_SCREEN (f);
3339 int i;
3340
3341 dpyinfo->ncolor_cells
3342 = XDisplayCells (display, XScreenNumberOfScreen (screen));
3343 dpyinfo->color_cells
3344 = (XColor *) xmalloc (dpyinfo->ncolor_cells
3345 * sizeof *dpyinfo->color_cells);
3346
3347 for (i = 0; i < dpyinfo->ncolor_cells; ++i)
3348 dpyinfo->color_cells[i].pixel = i;
3349
3350 XQueryColors (display, FRAME_X_COLORMAP (f),
3351 dpyinfo->color_cells, dpyinfo->ncolor_cells);
3352 }
3353
3354 *ncells = dpyinfo->ncolor_cells;
3355 return dpyinfo->color_cells;
3356}
3357
3358
3359/* On frame F, translate pixel colors to RGB values for the NCOLORS
3360 colors in COLORS. Use cached information, if available. */
3361
3362void
3363x_query_colors (f, colors, ncolors)
3364 struct frame *f;
3365 XColor *colors;
3366 int ncolors;
3367{
3368 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3369
3370 if (dpyinfo->color_cells)
3371 {
3372 int i;
3373 for (i = 0; i < ncolors; ++i)
3374 {
3375 unsigned long pixel = colors[i].pixel;
3376 xassert (pixel < dpyinfo->ncolor_cells);
3377 xassert (dpyinfo->color_cells[pixel].pixel == pixel);
3378 colors[i] = dpyinfo->color_cells[pixel];
3379 }
3380 }
3381 else
3382 XQueryColors (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), colors, ncolors);
3383}
3384
3385
3386/* On frame F, translate pixel color to RGB values for the color in
3387 COLOR. Use cached information, if available. */
3388
3389void
3390x_query_color (f, color)
3391 struct frame *f;
3392 XColor *color;
3393{
3394 x_query_colors (f, color, 1);
3395}
3396
3397
06a2c219
GM
3398/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3399 CMAP. If an exact match can't be allocated, try the nearest color
3400 available. Value is non-zero if successful. Set *COLOR to the
3401 color allocated. */
3402
3403int
80c32bcc
GM
3404x_alloc_nearest_color (f, cmap, color)
3405 struct frame *f;
06a2c219
GM
3406 Colormap cmap;
3407 XColor *color;
3408{
80c32bcc
GM
3409 Display *display = FRAME_X_DISPLAY (f);
3410 Screen *screen = FRAME_X_SCREEN (f);
3411 int rc;
3412
3413 gamma_correct (f, color);
3414 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3415 if (rc == 0)
3416 {
3417 /* If we got to this point, the colormap is full, so we're going
3418 to try to get the next closest color. The algorithm used is
3419 a least-squares matching, which is what X uses for closest
3420 color matching with StaticColor visuals. */
3421 int nearest, i;
3422 unsigned long nearest_delta = ~0;
f04e1297
GM
3423 int ncells;
3424 const XColor *cells = x_color_cells (f, &ncells);
06a2c219
GM
3425
3426 for (nearest = i = 0; i < ncells; ++i)
3427 {
3428 long dred = (color->red >> 8) - (cells[i].red >> 8);
3429 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3430 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3431 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3432
3433 if (delta < nearest_delta)
3434 {
3435 nearest = i;
3436 nearest_delta = delta;
3437 }
3438 }
3439
3440 color->red = cells[nearest].red;
3441 color->green = cells[nearest].green;
3442 color->blue = cells[nearest].blue;
3443 rc = XAllocColor (display, cmap, color);
3444 }
35efe0a1
GM
3445 else
3446 {
3447 /* If allocation succeeded, and the allocated pixel color is not
3448 equal to a cached pixel color recorded earlier, there was a
3449 change in the colormap, so clear the color cache. */
3450 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3451 XColor *cached_color;
3452
3453 if (dpyinfo->color_cells
3454 && (cached_color = &dpyinfo->color_cells[color->pixel],
cae71efe
GM
3455 (cached_color->red != color->red
3456 || cached_color->blue != color->blue
3457 || cached_color->green != color->green)))
35efe0a1
GM
3458 {
3459 xfree (dpyinfo->color_cells);
3460 dpyinfo->color_cells = NULL;
3461 dpyinfo->ncolor_cells = 0;
3462 }
3463 }
06a2c219 3464
d9c545da
GM
3465#ifdef DEBUG_X_COLORS
3466 if (rc)
3467 register_color (color->pixel);
3468#endif /* DEBUG_X_COLORS */
3469
06a2c219
GM
3470 return rc;
3471}
3472
3473
d9c545da
GM
3474/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3475 It's necessary to do this instead of just using PIXEL directly to
3476 get color reference counts right. */
3477
3478unsigned long
3479x_copy_color (f, pixel)
3480 struct frame *f;
3481 unsigned long pixel;
3482{
3483 XColor color;
3484
3485 color.pixel = pixel;
3486 BLOCK_INPUT;
f04e1297 3487 x_query_color (f, &color);
d9c545da
GM
3488 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3489 UNBLOCK_INPUT;
3490#ifdef DEBUG_X_COLORS
3491 register_color (pixel);
3492#endif
3493 return color.pixel;
3494}
3495
3496
3e71d8f2
GM
3497/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3498 It's necessary to do this instead of just using PIXEL directly to
3499 get color reference counts right. */
3500
3501unsigned long
3502x_copy_dpy_color (dpy, cmap, pixel)
3503 Display *dpy;
3504 Colormap cmap;
3505 unsigned long pixel;
3506{
3507 XColor color;
3508
3509 color.pixel = pixel;
3510 BLOCK_INPUT;
3511 XQueryColor (dpy, cmap, &color);
3512 XAllocColor (dpy, cmap, &color);
3513 UNBLOCK_INPUT;
3514#ifdef DEBUG_X_COLORS
3515 register_color (pixel);
3516#endif
3517 return color.pixel;
3518}
3519
3520
6d8b0acd 3521/* Brightness beyond which a color won't have its highlight brightness
d7361edf 3522 boosted.
6d8b0acd 3523
d7361edf
MB
3524 Nominally, highlight colors for `3d' faces are calculated by
3525 brightening an object's color by a constant scale factor, but this
3526 doesn't yield good results for dark colors, so for colors who's
3527 brightness is less than this value (on a scale of 0-65535) have an
3528 use an additional additive factor.
6d8b0acd
MB
3529
3530 The value here is set so that the default menu-bar/mode-line color
3531 (grey75) will not have its highlights changed at all. */
3532#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 48000
3533
3534
06a2c219
GM
3535/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3536 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3537 If this produces the same color as PIXEL, try a color where all RGB
3538 values have DELTA added. Return the allocated color in *PIXEL.
3539 DISPLAY is the X display, CMAP is the colormap to operate on.
3540 Value is non-zero if successful. */
3541
3542static int
3543x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3544 struct frame *f;
3545 Display *display;
3546 Colormap cmap;
3547 unsigned long *pixel;
68c45bf0 3548 double factor;
06a2c219
GM
3549 int delta;
3550{
3551 XColor color, new;
6d8b0acd 3552 long bright;
06a2c219
GM
3553 int success_p;
3554
3555 /* Get RGB color values. */
3556 color.pixel = *pixel;
f04e1297 3557 x_query_color (f, &color);
06a2c219
GM
3558
3559 /* Change RGB values by specified FACTOR. Avoid overflow! */
3560 xassert (factor >= 0);
3561 new.red = min (0xffff, factor * color.red);
3562 new.green = min (0xffff, factor * color.green);
3563 new.blue = min (0xffff, factor * color.blue);
3564
d7361edf
MB
3565 /* Calculate brightness of COLOR. */
3566 bright = (2 * color.red + 3 * color.green + color.blue) / 6;
6d8b0acd
MB
3567
3568 /* We only boost colors that are darker than
3569 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3570 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3571 /* Make an additive adjustment to NEW, because it's dark enough so
3572 that scaling by FACTOR alone isn't enough. */
3573 {
3574 /* How far below the limit this color is (0 - 1, 1 being darker). */
3575 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3576 /* The additive adjustment. */
d7361edf 3577 int min_delta = delta * dimness * factor / 2;
6d8b0acd
MB
3578
3579 if (factor < 1)
3580 {
6d8b0acd
MB
3581 new.red = max (0, new.red - min_delta);
3582 new.green = max (0, new.green - min_delta);
3583 new.blue = max (0, new.blue - min_delta);
3584 }
3585 else
3586 {
3587 new.red = min (0xffff, min_delta + new.red);
3588 new.green = min (0xffff, min_delta + new.green);
3589 new.blue = min (0xffff, min_delta + new.blue);
3590 }
3591 }
3592
06a2c219 3593 /* Try to allocate the color. */
80c32bcc 3594 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3595 if (success_p)
3596 {
3597 if (new.pixel == *pixel)
3598 {
3599 /* If we end up with the same color as before, try adding
3600 delta to the RGB values. */
0d605c67 3601 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3602
3603 new.red = min (0xffff, delta + color.red);
3604 new.green = min (0xffff, delta + color.green);
3605 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3606 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3607 }
3608 else
3609 success_p = 1;
3610 *pixel = new.pixel;
3611 }
3612
3613 return success_p;
3614}
3615
3616
3617/* Set up the foreground color for drawing relief lines of glyph
3618 string S. RELIEF is a pointer to a struct relief containing the GC
3619 with which lines will be drawn. Use a color that is FACTOR or
3620 DELTA lighter or darker than the relief's background which is found
3621 in S->f->output_data.x->relief_background. If such a color cannot
3622 be allocated, use DEFAULT_PIXEL, instead. */
3623
3624static void
3625x_setup_relief_color (f, relief, factor, delta, default_pixel)
3626 struct frame *f;
3627 struct relief *relief;
68c45bf0 3628 double factor;
06a2c219
GM
3629 int delta;
3630 unsigned long default_pixel;
3631{
3632 XGCValues xgcv;
3633 struct x_output *di = f->output_data.x;
3634 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3635 unsigned long pixel;
3636 unsigned long background = di->relief_background;
43bd1b2b 3637 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3638 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3639 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3640
3641 xgcv.graphics_exposures = False;
3642 xgcv.line_width = 1;
3643
3644 /* Free previously allocated color. The color cell will be reused
3645 when it has been freed as many times as it was allocated, so this
3646 doesn't affect faces using the same colors. */
3647 if (relief->gc
3648 && relief->allocated_p)
3649 {
0d605c67 3650 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3651 relief->allocated_p = 0;
3652 }
3653
3654 /* Allocate new color. */
3655 xgcv.foreground = default_pixel;
3656 pixel = background;
dcd08bfb
GM
3657 if (dpyinfo->n_planes != 1
3658 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3659 {
3660 relief->allocated_p = 1;
3661 xgcv.foreground = relief->pixel = pixel;
3662 }
3663
3664 if (relief->gc == 0)
3665 {
dcd08bfb 3666 xgcv.stipple = dpyinfo->gray;
06a2c219 3667 mask |= GCStipple;
dcd08bfb 3668 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3669 }
3670 else
dcd08bfb 3671 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3672}
3673
3674
3675/* Set up colors for the relief lines around glyph string S. */
3676
3677static void
3678x_setup_relief_colors (s)
3679 struct glyph_string *s;
3680{
3681 struct x_output *di = s->f->output_data.x;
3682 unsigned long color;
3683
3684 if (s->face->use_box_color_for_shadows_p)
3685 color = s->face->box_color;
3686 else
3687 {
3688 XGCValues xgcv;
3689
3690 /* Get the background color of the face. */
3691 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3692 color = xgcv.background;
3693 }
3694
3695 if (di->white_relief.gc == 0
3696 || color != di->relief_background)
3697 {
3698 di->relief_background = color;
3699 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3700 WHITE_PIX_DEFAULT (s->f));
3701 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3702 BLACK_PIX_DEFAULT (s->f));
3703 }
3704}
3705
3706
3707/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3708 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3709 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3710 relief. LEFT_P non-zero means draw a relief on the left side of
3711 the rectangle. RIGHT_P non-zero means draw a relief on the right
3712 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3713 when drawing. */
3714
3715static void
3716x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3717 raised_p, left_p, right_p, clip_rect)
3718 struct frame *f;
3719 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3720 XRectangle *clip_rect;
3721{
3722 int i;
3723 GC gc;
3724
3725 if (raised_p)
3726 gc = f->output_data.x->white_relief.gc;
3727 else
3728 gc = f->output_data.x->black_relief.gc;
3729 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3730
3731 /* Top. */
3732 for (i = 0; i < width; ++i)
3733 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3734 left_x + i * left_p, top_y + i,
3735 right_x + 1 - i * right_p, top_y + i);
3736
3737 /* Left. */
3738 if (left_p)
3739 for (i = 0; i < width; ++i)
3740 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
44655e77 3741 left_x + i, top_y + i, left_x + i, bottom_y - i + 1);
06a2c219
GM
3742
3743 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3744 if (raised_p)
3745 gc = f->output_data.x->black_relief.gc;
3746 else
3747 gc = f->output_data.x->white_relief.gc;
3748 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3749
3750 /* Bottom. */
3751 for (i = 0; i < width; ++i)
3752 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
44655e77 3753 left_x + i * left_p + 1, bottom_y - i,
06a2c219
GM
3754 right_x + 1 - i * right_p, bottom_y - i);
3755
3756 /* Right. */
3757 if (right_p)
3758 for (i = 0; i < width; ++i)
3759 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3760 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3761
3762 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3763}
3764
3765
3766/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3767 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3768 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3769 left side of the rectangle. RIGHT_P non-zero means draw a line
3770 on the right side of the rectangle. CLIP_RECT is the clipping
3771 rectangle to use when drawing. */
3772
3773static void
3774x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3775 left_p, right_p, clip_rect)
3776 struct glyph_string *s;
3777 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3778 XRectangle *clip_rect;
3779{
3780 XGCValues xgcv;
3781
3782 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3783 XSetForeground (s->display, s->gc, s->face->box_color);
3784 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3785
3786 /* Top. */
3787 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3788 left_x, top_y, right_x - left_x + 1, width);
06a2c219
GM
3789
3790 /* Left. */
3791 if (left_p)
3792 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3793 left_x, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3794
3795 /* Bottom. */
3796 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3797 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
06a2c219
GM
3798
3799 /* Right. */
3800 if (right_p)
3801 XFillRectangle (s->display, s->window, s->gc,
58e4fce8 3802 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
06a2c219
GM
3803
3804 XSetForeground (s->display, s->gc, xgcv.foreground);
3805 XSetClipMask (s->display, s->gc, None);
3806}
3807
3808
3809/* Draw a box around glyph string S. */
3810
3811static void
3812x_draw_glyph_string_box (s)
3813 struct glyph_string *s;
3814{
3815 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3816 int left_p, right_p;
3817 struct glyph *last_glyph;
3818 XRectangle clip_rect;
3819
3820 last_x = window_box_right (s->w, s->area);
3821 if (s->row->full_width_p
3822 && !s->w->pseudo_window_p)
3823 {
110859fc 3824 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3825 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3826 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3827 }
3828
3829 /* The glyph that may have a right box line. */
b4192550 3830 last_glyph = (s->cmp || s->img
06a2c219
GM
3831 ? s->first_glyph
3832 : s->first_glyph + s->nchars - 1);
3833
ea2ba0d4 3834 width = abs (s->face->box_line_width);
06a2c219
GM
3835 raised_p = s->face->box == FACE_RAISED_BOX;
3836 left_x = s->x;
57ac7c81
GM
3837 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
3838 ? last_x - 1
3839 : min (last_x, s->x + s->background_width) - 1);
06a2c219
GM
3840 top_y = s->y;
3841 bottom_y = top_y + s->height - 1;
3842
3843 left_p = (s->first_glyph->left_box_line_p
3844 || (s->hl == DRAW_MOUSE_FACE
3845 && (s->prev == NULL
3846 || s->prev->hl != s->hl)));
3847 right_p = (last_glyph->right_box_line_p
3848 || (s->hl == DRAW_MOUSE_FACE
3849 && (s->next == NULL
3850 || s->next->hl != s->hl)));
3851
3852 x_get_glyph_string_clip_rect (s, &clip_rect);
3853
3854 if (s->face->box == FACE_SIMPLE_BOX)
3855 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3856 left_p, right_p, &clip_rect);
3857 else
3858 {
3859 x_setup_relief_colors (s);
3860 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3861 width, raised_p, left_p, right_p, &clip_rect);
3862 }
3863}
3864
3865
3866/* Draw foreground of image glyph string S. */
3867
3868static void
3869x_draw_image_foreground (s)
3870 struct glyph_string *s;
3871{
3872 int x;
95af8492 3873 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3874
3875 /* If first glyph of S has a left box line, start drawing it to the
3876 right of that line. */
3877 if (s->face->box != FACE_NO_BOX
3878 && s->first_glyph->left_box_line_p)
ea2ba0d4 3879 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
3880 else
3881 x = s->x;
3882
3883 /* If there is a margin around the image, adjust x- and y-position
3884 by that margin. */
22d650b8
GM
3885 x += s->img->hmargin;
3886 y += s->img->vmargin;
06a2c219
GM
3887
3888 if (s->img->pixmap)
3889 {
3890 if (s->img->mask)
3891 {
3892 /* We can't set both a clip mask and use XSetClipRectangles
3893 because the latter also sets a clip mask. We also can't
3894 trust on the shape extension to be available
3895 (XShapeCombineRegion). So, compute the rectangle to draw
3896 manually. */
3897 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3898 | GCFunction);
3899 XGCValues xgcv;
3900 XRectangle clip_rect, image_rect, r;
3901
3902 xgcv.clip_mask = s->img->mask;
3903 xgcv.clip_x_origin = x;
3904 xgcv.clip_y_origin = y;
3905 xgcv.function = GXcopy;
3906 XChangeGC (s->display, s->gc, mask, &xgcv);
3907
3908 x_get_glyph_string_clip_rect (s, &clip_rect);
3909 image_rect.x = x;
3910 image_rect.y = y;
3911 image_rect.width = s->img->width;
3912 image_rect.height = s->img->height;
3913 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3914 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3915 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3916 }
3917 else
3918 {
49ad1d99
GM
3919 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3920 XGCValues xgcv;
3921 XRectangle clip_rect, image_rect, r;
3922
3923 x_get_glyph_string_clip_rect (s, &clip_rect);
3924 image_rect.x = x;
3925 image_rect.y = y;
3926 image_rect.width = s->img->width;
3927 image_rect.height = s->img->height;
3928 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3929 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3930 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
06a2c219
GM
3931
3932 /* When the image has a mask, we can expect that at
3933 least part of a mouse highlight or a block cursor will
3934 be visible. If the image doesn't have a mask, make
3935 a block cursor visible by drawing a rectangle around
3936 the image. I believe it's looking better if we do
3937 nothing here for mouse-face. */
3938 if (s->hl == DRAW_CURSOR)
3939 XDrawRectangle (s->display, s->window, s->gc, x, y,
3940 s->img->width - 1, s->img->height - 1);
3941 }
3942 }
3943 else
3944 /* Draw a rectangle if image could not be loaded. */
3945 XDrawRectangle (s->display, s->window, s->gc, x, y,
3946 s->img->width - 1, s->img->height - 1);
3947}
3948
3949
3950/* Draw a relief around the image glyph string S. */
3951
3952static void
3953x_draw_image_relief (s)
3954 struct glyph_string *s;
3955{
3956 int x0, y0, x1, y1, thick, raised_p;
3957 XRectangle r;
3958 int x;
95af8492 3959 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3960
3961 /* If first glyph of S has a left box line, start drawing it to the
3962 right of that line. */
3963 if (s->face->box != FACE_NO_BOX
3964 && s->first_glyph->left_box_line_p)
ea2ba0d4 3965 x = s->x + abs (s->face->box_line_width);
06a2c219
GM
3966 else
3967 x = s->x;
3968
3969 /* If there is a margin around the image, adjust x- and y-position
3970 by that margin. */
22d650b8
GM
3971 x += s->img->hmargin;
3972 y += s->img->vmargin;
06a2c219
GM
3973
3974 if (s->hl == DRAW_IMAGE_SUNKEN
3975 || s->hl == DRAW_IMAGE_RAISED)
3976 {
9ea173e8 3977 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3978 raised_p = s->hl == DRAW_IMAGE_RAISED;
3979 }
3980 else
3981 {
3982 thick = abs (s->img->relief);
3983 raised_p = s->img->relief > 0;
3984 }
3985
3986 x0 = x - thick;
3987 y0 = y - thick;
3988 x1 = x + s->img->width + thick - 1;
3989 y1 = y + s->img->height + thick - 1;
3990
3991 x_setup_relief_colors (s);
3992 x_get_glyph_string_clip_rect (s, &r);
3993 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3994}
3995
3996
3997/* Draw the foreground of image glyph string S to PIXMAP. */
3998
3999static void
4000x_draw_image_foreground_1 (s, pixmap)
4001 struct glyph_string *s;
4002 Pixmap pixmap;
4003{
4004 int x;
95af8492 4005 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
4006
4007 /* If first glyph of S has a left box line, start drawing it to the
4008 right of that line. */
4009 if (s->face->box != FACE_NO_BOX
4010 && s->first_glyph->left_box_line_p)
ea2ba0d4 4011 x = abs (s->face->box_line_width);
06a2c219
GM
4012 else
4013 x = 0;
4014
4015 /* If there is a margin around the image, adjust x- and y-position
4016 by that margin. */
22d650b8
GM
4017 x += s->img->hmargin;
4018 y += s->img->vmargin;
dc43ef94 4019
06a2c219
GM
4020 if (s->img->pixmap)
4021 {
4022 if (s->img->mask)
4023 {
4024 /* We can't set both a clip mask and use XSetClipRectangles
4025 because the latter also sets a clip mask. We also can't
4026 trust on the shape extension to be available
4027 (XShapeCombineRegion). So, compute the rectangle to draw
4028 manually. */
4029 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4030 | GCFunction);
4031 XGCValues xgcv;
4032
4033 xgcv.clip_mask = s->img->mask;
4034 xgcv.clip_x_origin = x;
4035 xgcv.clip_y_origin = y;
4036 xgcv.function = GXcopy;
4037 XChangeGC (s->display, s->gc, mask, &xgcv);
4038
4039 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4040 0, 0, s->img->width, s->img->height, x, y);
4041 XSetClipMask (s->display, s->gc, None);
4042 }
4043 else
4044 {
4045 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4046 0, 0, s->img->width, s->img->height, x, y);
4047
4048 /* When the image has a mask, we can expect that at
4049 least part of a mouse highlight or a block cursor will
4050 be visible. If the image doesn't have a mask, make
4051 a block cursor visible by drawing a rectangle around
4052 the image. I believe it's looking better if we do
4053 nothing here for mouse-face. */
4054 if (s->hl == DRAW_CURSOR)
4055 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4056 s->img->width - 1, s->img->height - 1);
4057 }
4058 }
4059 else
4060 /* Draw a rectangle if image could not be loaded. */
4061 XDrawRectangle (s->display, pixmap, s->gc, x, y,
4062 s->img->width - 1, s->img->height - 1);
4063}
dc43ef94 4064
990ba854 4065
06a2c219
GM
4066/* Draw part of the background of glyph string S. X, Y, W, and H
4067 give the rectangle to draw. */
a9a5b0a5 4068
06a2c219
GM
4069static void
4070x_draw_glyph_string_bg_rect (s, x, y, w, h)
4071 struct glyph_string *s;
4072 int x, y, w, h;
4073{
4074 if (s->stippled_p)
4075 {
4076 /* Fill background with a stipple pattern. */
4077 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4078 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4079 XSetFillStyle (s->display, s->gc, FillSolid);
4080 }
4081 else
4082 x_clear_glyph_string_rect (s, x, y, w, h);
4083}
07e34cb0 4084
b5210ea7 4085
06a2c219 4086/* Draw image glyph string S.
dc43ef94 4087
06a2c219
GM
4088 s->y
4089 s->x +-------------------------
4090 | s->face->box
4091 |
4092 | +-------------------------
4093 | | s->img->margin
4094 | |
4095 | | +-------------------
4096 | | | the image
dc43ef94 4097
06a2c219 4098 */
dc43ef94 4099
06a2c219
GM
4100static void
4101x_draw_image_glyph_string (s)
4102 struct glyph_string *s;
4103{
4104 int x, y;
ea2ba0d4
KH
4105 int box_line_hwidth = abs (s->face->box_line_width);
4106 int box_line_vwidth = max (s->face->box_line_width, 0);
06a2c219
GM
4107 int height;
4108 Pixmap pixmap = None;
4109
ea2ba0d4 4110 height = s->height - 2 * box_line_vwidth;
06a2c219
GM
4111
4112 /* Fill background with face under the image. Do it only if row is
4113 taller than image or if image has a clip mask to reduce
4114 flickering. */
4115 s->stippled_p = s->face->stipple != 0;
4116 if (height > s->img->height
22d650b8
GM
4117 || s->img->hmargin
4118 || s->img->vmargin
06a2c219
GM
4119 || s->img->mask
4120 || s->img->pixmap == 0
4121 || s->width != s->background_width)
4122 {
ea2ba0d4
KH
4123 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4124 x = s->x + box_line_hwidth;
06a2c219
GM
4125 else
4126 x = s->x;
4127
ea2ba0d4 4128 y = s->y + box_line_vwidth;
06a2c219
GM
4129
4130 if (s->img->mask)
4131 {
f9b5db02
GM
4132 /* Create a pixmap as large as the glyph string. Fill it
4133 with the background color. Copy the image to it, using
4134 its mask. Copy the temporary pixmap to the display. */
06a2c219
GM
4135 Screen *screen = FRAME_X_SCREEN (s->f);
4136 int depth = DefaultDepthOfScreen (screen);
4137
4138 /* Create a pixmap as large as the glyph string. */
4139 pixmap = XCreatePixmap (s->display, s->window,
4140 s->background_width,
4141 s->height, depth);
4142
4143 /* Don't clip in the following because we're working on the
4144 pixmap. */
4145 XSetClipMask (s->display, s->gc, None);
4146
4147 /* Fill the pixmap with the background color/stipple. */
4148 if (s->stippled_p)
4149 {
4150 /* Fill background with a stipple pattern. */
4151 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4152 XFillRectangle (s->display, pixmap, s->gc,
4153 0, 0, s->background_width, s->height);
4154 XSetFillStyle (s->display, s->gc, FillSolid);
4155 }
4156 else
4157 {
4158 XGCValues xgcv;
4159 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4160 &xgcv);
4161 XSetForeground (s->display, s->gc, xgcv.background);
4162 XFillRectangle (s->display, pixmap, s->gc,
4163 0, 0, s->background_width, s->height);
4164 XSetForeground (s->display, s->gc, xgcv.foreground);
4165 }
4166 }
4167 else
06a2c219
GM
4168 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4169
4170 s->background_filled_p = 1;
4171 }
dc43ef94 4172
06a2c219
GM
4173 /* Draw the foreground. */
4174 if (pixmap != None)
4175 {
4176 x_draw_image_foreground_1 (s, pixmap);
4177 x_set_glyph_string_clipping (s);
4178 XCopyArea (s->display, pixmap, s->window, s->gc,
4179 0, 0, s->background_width, s->height, s->x, s->y);
4180 XFreePixmap (s->display, pixmap);
4181 }
4182 else
4183 x_draw_image_foreground (s);
b5210ea7 4184
06a2c219
GM
4185 /* If we must draw a relief around the image, do it. */
4186 if (s->img->relief
4187 || s->hl == DRAW_IMAGE_RAISED
4188 || s->hl == DRAW_IMAGE_SUNKEN)
4189 x_draw_image_relief (s);
4190}
8c1a6a84 4191
990ba854 4192
06a2c219 4193/* Draw stretch glyph string S. */
dc43ef94 4194
06a2c219
GM
4195static void
4196x_draw_stretch_glyph_string (s)
4197 struct glyph_string *s;
4198{
4199 xassert (s->first_glyph->type == STRETCH_GLYPH);
4200 s->stippled_p = s->face->stipple != 0;
990ba854 4201
06a2c219
GM
4202 if (s->hl == DRAW_CURSOR
4203 && !x_stretch_cursor_p)
4204 {
4205 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4206 as wide as the stretch glyph. */
4207 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4208
06a2c219
GM
4209 /* Draw cursor. */
4210 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4211
06a2c219
GM
4212 /* Clear rest using the GC of the original non-cursor face. */
4213 if (width < s->background_width)
4214 {
4215 GC gc = s->face->gc;
4216 int x = s->x + width, y = s->y;
4217 int w = s->background_width - width, h = s->height;
4218 XRectangle r;
dc43ef94 4219
06a2c219
GM
4220 x_get_glyph_string_clip_rect (s, &r);
4221 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 4222
06a2c219
GM
4223 if (s->face->stipple)
4224 {
4225 /* Fill background with a stipple pattern. */
4226 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4227 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4228 XSetFillStyle (s->display, gc, FillSolid);
4229 }
4230 else
4231 {
4232 XGCValues xgcv;
4233 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4234 XSetForeground (s->display, gc, xgcv.background);
4235 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4236 XSetForeground (s->display, gc, xgcv.foreground);
4237 }
4238 }
4239 }
4240 else
4241 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4242 s->height);
4243
4244 s->background_filled_p = 1;
4245}
4246
4247
4248/* Draw glyph string S. */
4249
4250static void
4251x_draw_glyph_string (s)
4252 struct glyph_string *s;
4253{
4458cf11
KH
4254 int relief_drawn_p = 0;
4255
06a2c219
GM
4256 /* If S draws into the background of its successor, draw the
4257 background of the successor first so that S can draw into it.
4258 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4259 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4260 {
4261 xassert (s->next->img == NULL);
4262 x_set_glyph_string_gc (s->next);
4263 x_set_glyph_string_clipping (s->next);
4264 x_draw_glyph_string_background (s->next, 1);
4265 }
97210f4e 4266
06a2c219
GM
4267 /* Set up S->gc, set clipping and draw S. */
4268 x_set_glyph_string_gc (s);
4269 x_set_glyph_string_clipping (s);
4270
4458cf11
KH
4271 /* Draw relief (if any) in advance for char/composition so that the
4272 glyph string can be drawn over it. */
4273 if (!s->for_overlaps_p
4274 && s->face->box != FACE_NO_BOX
4275 && (s->first_glyph->type == CHAR_GLYPH
4276 || s->first_glyph->type == COMPOSITE_GLYPH))
4277
4278 {
4279 x_draw_glyph_string_background (s, 1);
4280 x_draw_glyph_string_box (s);
4281 relief_drawn_p = 1;
4282 }
4283
06a2c219
GM
4284 switch (s->first_glyph->type)
4285 {
4286 case IMAGE_GLYPH:
4287 x_draw_image_glyph_string (s);
4288 break;
4289
4290 case STRETCH_GLYPH:
4291 x_draw_stretch_glyph_string (s);
4292 break;
4293
4294 case CHAR_GLYPH:
66ac4b0e
GM
4295 if (s->for_overlaps_p)
4296 s->background_filled_p = 1;
4297 else
4298 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4299 x_draw_glyph_string_foreground (s);
4300 break;
4301
b4192550
KH
4302 case COMPOSITE_GLYPH:
4303 if (s->for_overlaps_p || s->gidx > 0)
4304 s->background_filled_p = 1;
4305 else
4306 x_draw_glyph_string_background (s, 1);
4307 x_draw_composite_glyph_string_foreground (s);
4308 break;
4309
06a2c219
GM
4310 default:
4311 abort ();
4312 }
4313
66ac4b0e 4314 if (!s->for_overlaps_p)
06a2c219 4315 {
66ac4b0e
GM
4316 /* Draw underline. */
4317 if (s->face->underline_p)
4318 {
e24e84cc
GM
4319 unsigned long tem, h;
4320 int y;
06a2c219 4321
e24e84cc 4322 /* Get the underline thickness. Default is 1 pixel. */
66ac4b0e
GM
4323 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4324 h = 1;
e24e84cc
GM
4325
4326 /* Get the underline position. This is the recommended
4327 vertical offset in pixels from the baseline to the top of
4328 the underline. This is a signed value according to the
4329 specs, and its default is
4330
4331 ROUND ((maximum descent) / 2), with
4332 ROUND(x) = floor (x + 0.5) */
4333
4334 if (XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem))
4335 y = s->ybase + (long) tem;
4336 else if (s->face->font)
4337 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2;
4338 else
a02f1be0 4339 y = s->y + s->height - h;
06a2c219 4340
66ac4b0e 4341 if (s->face->underline_defaulted_p)
e24e84cc
GM
4342 XFillRectangle (s->display, s->window, s->gc,
4343 s->x, y, s->width, h);
66ac4b0e
GM
4344 else
4345 {
4346 XGCValues xgcv;
4347 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4348 XSetForeground (s->display, s->gc, s->face->underline_color);
e24e84cc
GM
4349 XFillRectangle (s->display, s->window, s->gc,
4350 s->x, y, s->width, h);
66ac4b0e
GM
4351 XSetForeground (s->display, s->gc, xgcv.foreground);
4352 }
dc6f92b8 4353 }
07e34cb0 4354
66ac4b0e
GM
4355 /* Draw overline. */
4356 if (s->face->overline_p)
06a2c219 4357 {
66ac4b0e
GM
4358 unsigned long dy = 0, h = 1;
4359
4360 if (s->face->overline_color_defaulted_p)
4361 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4362 s->width, h);
4363 else
4364 {
4365 XGCValues xgcv;
4366 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4367 XSetForeground (s->display, s->gc, s->face->overline_color);
4368 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4369 s->width, h);
4370 XSetForeground (s->display, s->gc, xgcv.foreground);
4371 }
06a2c219 4372 }
06a2c219 4373
66ac4b0e
GM
4374 /* Draw strike-through. */
4375 if (s->face->strike_through_p)
06a2c219 4376 {
66ac4b0e
GM
4377 unsigned long h = 1;
4378 unsigned long dy = (s->height - h) / 2;
4379
4380 if (s->face->strike_through_color_defaulted_p)
4381 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4382 s->width, h);
4383 else
4384 {
4385 XGCValues xgcv;
4386 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4387 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4388 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4389 s->width, h);
4390 XSetForeground (s->display, s->gc, xgcv.foreground);
4391 }
06a2c219 4392 }
06a2c219 4393
4458cf11
KH
4394 /* Draw relief if not yet drawn. */
4395 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
66ac4b0e
GM
4396 x_draw_glyph_string_box (s);
4397 }
06a2c219
GM
4398
4399 /* Reset clipping. */
4400 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4401}
07e34cb0 4402
06a2c219 4403
b4192550
KH
4404static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4405 struct face **, int));
06a2c219 4406
06a2c219 4407
209f68d9
GM
4408/* Fill glyph string S with composition components specified by S->cmp.
4409
b4192550
KH
4410 FACES is an array of faces for all components of this composition.
4411 S->gidx is the index of the first component for S.
4412 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4413 use its physical height for clipping.
06a2c219 4414
b4192550 4415 Value is the index of a component not in S. */
07e34cb0 4416
b4192550
KH
4417static int
4418x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4419 struct glyph_string *s;
b4192550 4420 struct face **faces;
66ac4b0e 4421 int overlaps_p;
07e34cb0 4422{
b4192550 4423 int i;
06a2c219 4424
b4192550 4425 xassert (s);
06a2c219 4426
b4192550 4427 s->for_overlaps_p = overlaps_p;
06a2c219 4428
b4192550
KH
4429 s->face = faces[s->gidx];
4430 s->font = s->face->font;
4431 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4432
b4192550
KH
4433 /* For all glyphs of this composition, starting at the offset
4434 S->gidx, until we reach the end of the definition or encounter a
4435 glyph that requires the different face, add it to S. */
4436 ++s->nchars;
4437 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4438 ++s->nchars;
06a2c219 4439
b4192550
KH
4440 /* All glyph strings for the same composition has the same width,
4441 i.e. the width set for the first component of the composition. */
06a2c219 4442
06a2c219
GM
4443 s->width = s->first_glyph->pixel_width;
4444
4445 /* If the specified font could not be loaded, use the frame's
4446 default font, but record the fact that we couldn't load it in
4447 the glyph string so that we can draw rectangles for the
4448 characters of the glyph string. */
4449 if (s->font == NULL)
4450 {
4451 s->font_not_found_p = 1;
4452 s->font = FRAME_FONT (s->f);
4453 }
4454
4455 /* Adjust base line for subscript/superscript text. */
4456 s->ybase += s->first_glyph->voffset;
4457
4458 xassert (s->face && s->face->gc);
4459
4460 /* This glyph string must always be drawn with 16-bit functions. */
4461 s->two_byte_p = 1;
b4192550
KH
4462
4463 return s->gidx + s->nchars;
06a2c219
GM
4464}
4465
4466
209f68d9
GM
4467/* Fill glyph string S from a sequence of character glyphs.
4468
06a2c219 4469 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4470 first glyph to consider, END is the index of the last + 1.
4471 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4472 use its physical height for clipping.
66ac4b0e
GM
4473
4474 Value is the index of the first glyph not in S. */
06a2c219
GM
4475
4476static int
66ac4b0e 4477x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4478 struct glyph_string *s;
4479 int face_id;
66ac4b0e 4480 int start, end, overlaps_p;
06a2c219
GM
4481{
4482 struct glyph *glyph, *last;
4483 int voffset;
ee569018 4484 int glyph_not_available_p;
06a2c219 4485
06a2c219
GM
4486 xassert (s->f == XFRAME (s->w->frame));
4487 xassert (s->nchars == 0);
4488 xassert (start >= 0 && end > start);
4489
66ac4b0e 4490 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4491 glyph = s->row->glyphs[s->area] + start;
4492 last = s->row->glyphs[s->area] + end;
4493 voffset = glyph->voffset;
4494
ee569018
KH
4495 glyph_not_available_p = glyph->glyph_not_available_p;
4496
06a2c219
GM
4497 while (glyph < last
4498 && glyph->type == CHAR_GLYPH
4499 && glyph->voffset == voffset
ee569018
KH
4500 /* Same face id implies same font, nowadays. */
4501 && glyph->face_id == face_id
4502 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4503 {
ee569018
KH
4504 int two_byte_p;
4505
06a2c219 4506 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4507 s->char2b + s->nchars,
4508 &two_byte_p);
4509 s->two_byte_p = two_byte_p;
06a2c219
GM
4510 ++s->nchars;
4511 xassert (s->nchars <= end - start);
4512 s->width += glyph->pixel_width;
4513 ++glyph;
4514 }
4515
4516 s->font = s->face->font;
4517 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4518
4519 /* If the specified font could not be loaded, use the frame's font,
4520 but record the fact that we couldn't load it in
4521 S->font_not_found_p so that we can draw rectangles for the
4522 characters of the glyph string. */
ee569018 4523 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4524 {
4525 s->font_not_found_p = 1;
4526 s->font = FRAME_FONT (s->f);
4527 }
4528
4529 /* Adjust base line for subscript/superscript text. */
4530 s->ybase += voffset;
66ac4b0e 4531
06a2c219
GM
4532 xassert (s->face && s->face->gc);
4533 return glyph - s->row->glyphs[s->area];
07e34cb0 4534}
dc6f92b8 4535
06a2c219
GM
4536
4537/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4538
dfcf069d 4539static void
06a2c219
GM
4540x_fill_image_glyph_string (s)
4541 struct glyph_string *s;
4542{
4543 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4544 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4545 xassert (s->img);
43d120d8 4546 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4547 s->font = s->face->font;
4548 s->width = s->first_glyph->pixel_width;
4549
4550 /* Adjust base line for subscript/superscript text. */
4551 s->ybase += s->first_glyph->voffset;
4552}
4553
4554
209f68d9 4555/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4556
209f68d9
GM
4557 ROW is the glyph row in which the glyphs are found, AREA is the
4558 area within the row. START is the index of the first glyph to
4559 consider, END is the index of the last + 1.
4560
4561 Value is the index of the first glyph not in S. */
4562
4563static int
4564x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4565 struct glyph_string *s;
209f68d9
GM
4566 struct glyph_row *row;
4567 enum glyph_row_area area;
4568 int start, end;
06a2c219 4569{
209f68d9
GM
4570 struct glyph *glyph, *last;
4571 int voffset, face_id;
4572
06a2c219 4573 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4574
4575 glyph = s->row->glyphs[s->area] + start;
4576 last = s->row->glyphs[s->area] + end;
4577 face_id = glyph->face_id;
4578 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4579 s->font = s->face->font;
209f68d9
GM
4580 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4581 s->width = glyph->pixel_width;
4582 voffset = glyph->voffset;
4583
4584 for (++glyph;
4585 (glyph < last
4586 && glyph->type == STRETCH_GLYPH
4587 && glyph->voffset == voffset
4588 && glyph->face_id == face_id);
4589 ++glyph)
4590 s->width += glyph->pixel_width;
06a2c219
GM
4591
4592 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4593 s->ybase += voffset;
4594
4595 xassert (s->face && s->face->gc);
4596 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4597}
4598
4599
4600/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4601 of XChar2b structures for S; it can't be allocated in
4602 x_init_glyph_string because it must be allocated via `alloca'. W
4603 is the window on which S is drawn. ROW and AREA are the glyph row
4604 and area within the row from which S is constructed. START is the
4605 index of the first glyph structure covered by S. HL is a
4606 face-override for drawing S. */
4607
4608static void
4609x_init_glyph_string (s, char2b, w, row, area, start, hl)
4610 struct glyph_string *s;
4611 XChar2b *char2b;
4612 struct window *w;
4613 struct glyph_row *row;
4614 enum glyph_row_area area;
4615 int start;
4616 enum draw_glyphs_face hl;
4617{
4618 bzero (s, sizeof *s);
4619 s->w = w;
4620 s->f = XFRAME (w->frame);
4621 s->display = FRAME_X_DISPLAY (s->f);
4622 s->window = FRAME_X_WINDOW (s->f);
4623 s->char2b = char2b;
4624 s->hl = hl;
4625 s->row = row;
4626 s->area = area;
4627 s->first_glyph = row->glyphs[area] + start;
4628 s->height = row->height;
4629 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4630
9ea173e8
GM
4631 /* Display the internal border below the tool-bar window. */
4632 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4633 s->y -= s->f->output_data.x->internal_border_width;
4634
4635 s->ybase = s->y + row->ascent;
4636}
4637
4638
4639/* Set background width of glyph string S. START is the index of the
4640 first glyph following S. LAST_X is the right-most x-position + 1
4641 in the drawing area. */
4642
4643static INLINE void
4644x_set_glyph_string_background_width (s, start, last_x)
4645 struct glyph_string *s;
4646 int start;
4647 int last_x;
4648{
4649 /* If the face of this glyph string has to be drawn to the end of
4650 the drawing area, set S->extends_to_end_of_line_p. */
4651 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4652
4653 if (start == s->row->used[s->area]
4654 && s->hl == DRAW_NORMAL_TEXT
eb79f5cc
GM
4655 && s->area == TEXT_AREA
4656 && (s->row->fill_line_p
06a2c219
GM
4657 || s->face->background != default_face->background
4658 || s->face->stipple != default_face->stipple))
4659 s->extends_to_end_of_line_p = 1;
4660
4661 /* If S extends its face to the end of the line, set its
4662 background_width to the distance to the right edge of the drawing
4663 area. */
4664 if (s->extends_to_end_of_line_p)
1da3fd71 4665 s->background_width = last_x - s->x + 1;
06a2c219
GM
4666 else
4667 s->background_width = s->width;
4668}
4669
4670
4671/* Add a glyph string for a stretch glyph to the list of strings
4672 between HEAD and TAIL. START is the index of the stretch glyph in
4673 row area AREA of glyph row ROW. END is the index of the last glyph
4674 in that glyph row area. X is the current output position assigned
4675 to the new glyph string constructed. HL overrides that face of the
4676 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4677 is the right-most x-position of the drawing area. */
4678
8abee2e1
DL
4679/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4680 and below -- keep them on one line. */
4681#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4682 do \
4683 { \
4684 s = (struct glyph_string *) alloca (sizeof *s); \
4685 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4686 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4687 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4688 s->x = (X); \
4689 } \
4690 while (0)
4691
4692
4693/* Add a glyph string for an image glyph to the list of strings
4694 between HEAD and TAIL. START is the index of the image glyph in
4695 row area AREA of glyph row ROW. END is the index of the last glyph
4696 in that glyph row area. X is the current output position assigned
4697 to the new glyph string constructed. HL overrides that face of the
4698 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4699 is the right-most x-position of the drawing area. */
4700
8abee2e1 4701#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4702 do \
4703 { \
4704 s = (struct glyph_string *) alloca (sizeof *s); \
4705 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4706 x_fill_image_glyph_string (s); \
4707 x_append_glyph_string (&HEAD, &TAIL, s); \
4708 ++START; \
4709 s->x = (X); \
4710 } \
4711 while (0)
4712
4713
4714/* Add a glyph string for a sequence of character glyphs to the list
4715 of strings between HEAD and TAIL. START is the index of the first
4716 glyph in row area AREA of glyph row ROW that is part of the new
4717 glyph string. END is the index of the last glyph in that glyph row
4718 area. X is the current output position assigned to the new glyph
4719 string constructed. HL overrides that face of the glyph; e.g. it
4720 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4721 right-most x-position of the drawing area. */
4722
8abee2e1 4723#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4724 do \
4725 { \
3e71d8f2 4726 int c, face_id; \
06a2c219
GM
4727 XChar2b *char2b; \
4728 \
43d120d8 4729 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4730 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4731 \
b4192550
KH
4732 s = (struct glyph_string *) alloca (sizeof *s); \
4733 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4734 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4735 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4736 s->x = (X); \
4737 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4738 OVERLAPS_P); \
06a2c219
GM
4739 } \
4740 while (0)
4741
4742
b4192550
KH
4743/* Add a glyph string for a composite sequence to the list of strings
4744 between HEAD and TAIL. START is the index of the first glyph in
4745 row area AREA of glyph row ROW that is part of the new glyph
4746 string. END is the index of the last glyph in that glyph row area.
4747 X is the current output position assigned to the new glyph string
4748 constructed. HL overrides that face of the glyph; e.g. it is
4749 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4750 x-position of the drawing area. */
4751
6c27ec25 4752#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4753 do { \
43d120d8
KH
4754 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4755 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4756 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4757 struct composition *cmp = composition_table[cmp_id]; \
4758 int glyph_len = cmp->glyph_len; \
4759 XChar2b *char2b; \
4760 struct face **faces; \
4761 struct glyph_string *first_s = NULL; \
4762 int n; \
4763 \
ee569018 4764 base_face = base_face->ascii_face; \
b4192550
KH
4765 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4766 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4767 /* At first, fill in `char2b' and `faces'. */ \
4768 for (n = 0; n < glyph_len; n++) \
4769 { \
43d120d8 4770 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4771 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4772 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4773 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4774 this_face_id, char2b + n, 1); \
b4192550
KH
4775 } \
4776 \
4777 /* Make glyph_strings for each glyph sequence that is drawable by \
4778 the same face, and append them to HEAD/TAIL. */ \
4779 for (n = 0; n < cmp->glyph_len;) \
4780 { \
4781 s = (struct glyph_string *) alloca (sizeof *s); \
4782 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4783 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4784 s->cmp = cmp; \
4785 s->gidx = n; \
b4192550
KH
4786 s->x = (X); \
4787 \
4788 if (n == 0) \
4789 first_s = s; \
4790 \
4791 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4792 } \
4793 \
4794 ++START; \
4795 s = first_s; \
4796 } while (0)
4797
4798
06a2c219
GM
4799/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4800 of AREA of glyph row ROW on window W between indices START and END.
4801 HL overrides the face for drawing glyph strings, e.g. it is
4802 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4803 x-positions of the drawing area.
4804
4805 This is an ugly monster macro construct because we must use alloca
4806 to allocate glyph strings (because x_draw_glyphs can be called
4807 asynchronously). */
4808
8abee2e1 4809#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4810 do \
4811 { \
4812 HEAD = TAIL = NULL; \
4813 while (START < END) \
4814 { \
4815 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4816 switch (first_glyph->type) \
4817 { \
4818 case CHAR_GLYPH: \
4819 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4820 TAIL, HL, X, LAST_X, \
4821 OVERLAPS_P); \
06a2c219
GM
4822 break; \
4823 \
b4192550
KH
4824 case COMPOSITE_GLYPH: \
4825 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4826 HEAD, TAIL, HL, X, LAST_X,\
4827 OVERLAPS_P); \
4828 break; \
4829 \
06a2c219
GM
4830 case STRETCH_GLYPH: \
4831 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4832 HEAD, TAIL, HL, X, LAST_X); \
4833 break; \
4834 \
4835 case IMAGE_GLYPH: \
4836 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4837 TAIL, HL, X, LAST_X); \
4838 break; \
4839 \
4840 default: \
4841 abort (); \
4842 } \
4843 \
4844 x_set_glyph_string_background_width (s, START, LAST_X); \
4845 (X) += s->width; \
4846 } \
4847 } \
4848 while (0)
4849
4850
4851/* Draw glyphs between START and END in AREA of ROW on window W,
4852 starting at x-position X. X is relative to AREA in W. HL is a
4853 face-override with the following meaning:
4854
4855 DRAW_NORMAL_TEXT draw normally
4856 DRAW_CURSOR draw in cursor face
4857 DRAW_MOUSE_FACE draw in mouse face.
4858 DRAW_INVERSE_VIDEO draw in mode line face
4859 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4860 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4861
4862 If REAL_START is non-null, return in *REAL_START the real starting
4863 position for display. This can be different from START in case
4864 overlapping glyphs must be displayed. If REAL_END is non-null,
4865 return in *REAL_END the real end position for display. This can be
4866 different from END in case overlapping glyphs must be displayed.
4867
66ac4b0e
GM
4868 If OVERLAPS_P is non-zero, draw only the foreground of characters
4869 and clip to the physical height of ROW.
4870
06a2c219
GM
4871 Value is the x-position reached, relative to AREA of W. */
4872
4873static int
66ac4b0e
GM
4874x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4875 overlaps_p)
06a2c219
GM
4876 struct window *w;
4877 int x;
4878 struct glyph_row *row;
4879 enum glyph_row_area area;
4880 int start, end;
4881 enum draw_glyphs_face hl;
4882 int *real_start, *real_end;
66ac4b0e 4883 int overlaps_p;
dc6f92b8 4884{
06a2c219
GM
4885 struct glyph_string *head, *tail;
4886 struct glyph_string *s;
4887 int last_x, area_width;
4888 int x_reached;
4889 int i, j;
4890
4891 /* Let's rather be paranoid than getting a SEGV. */
06a2c219 4892 end = min (end, row->used[area]);
a8710abf
GM
4893 start = max (0, start);
4894 start = min (end, start);
06a2c219
GM
4895 if (real_start)
4896 *real_start = start;
4897 if (real_end)
4898 *real_end = end;
4899
4900 /* Translate X to frame coordinates. Set last_x to the right
4901 end of the drawing area. */
4902 if (row->full_width_p)
4903 {
4904 /* X is relative to the left edge of W, without scroll bars
4905 or flag areas. */
4906 struct frame *f = XFRAME (w->frame);
110859fc 4907 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4908 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4909
06a2c219
GM
4910 x += window_left_x;
4911 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4912 last_x = window_left_x + area_width;
4913
4914 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4915 {
110859fc 4916 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4917 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4918 last_x += width;
4919 else
4920 x -= width;
4921 }
dc6f92b8 4922
b9432a85
GM
4923 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4924 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4925 }
4926 else
dc6f92b8 4927 {
06a2c219
GM
4928 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4929 area_width = window_box_width (w, area);
4930 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4931 }
4932
06a2c219
GM
4933 /* Build a doubly-linked list of glyph_string structures between
4934 head and tail from what we have to draw. Note that the macro
4935 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4936 the reason we use a separate variable `i'. */
4937 i = start;
66ac4b0e
GM
4938 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4939 overlaps_p);
06a2c219
GM
4940 if (tail)
4941 x_reached = tail->x + tail->background_width;
4942 else
4943 x_reached = x;
90e65f07 4944
06a2c219
GM
4945 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4946 the row, redraw some glyphs in front or following the glyph
4947 strings built above. */
a8710abf 4948 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4949 {
4950 int dummy_x = 0;
4951 struct glyph_string *h, *t;
4952
4953 /* Compute overhangs for all glyph strings. */
4954 for (s = head; s; s = s->next)
4955 x_compute_glyph_string_overhangs (s);
4956
4957 /* Prepend glyph strings for glyphs in front of the first glyph
4958 string that are overwritten because of the first glyph
4959 string's left overhang. The background of all strings
4960 prepended must be drawn because the first glyph string
4961 draws over it. */
4962 i = x_left_overwritten (head);
4963 if (i >= 0)
4964 {
4965 j = i;
4966 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4967 DRAW_NORMAL_TEXT, dummy_x, last_x,
4968 overlaps_p);
06a2c219
GM
4969 start = i;
4970 if (real_start)
4971 *real_start = start;
4972 x_compute_overhangs_and_x (t, head->x, 1);
4973 x_prepend_glyph_string_lists (&head, &tail, h, t);
4974 }
58769bee 4975
06a2c219
GM
4976 /* Prepend glyph strings for glyphs in front of the first glyph
4977 string that overwrite that glyph string because of their
4978 right overhang. For these strings, only the foreground must
4979 be drawn, because it draws over the glyph string at `head'.
4980 The background must not be drawn because this would overwrite
4981 right overhangs of preceding glyphs for which no glyph
4982 strings exist. */
4983 i = x_left_overwriting (head);
4984 if (i >= 0)
4985 {
4986 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4987 DRAW_NORMAL_TEXT, dummy_x, last_x,
4988 overlaps_p);
06a2c219
GM
4989 for (s = h; s; s = s->next)
4990 s->background_filled_p = 1;
4991 if (real_start)
4992 *real_start = i;
4993 x_compute_overhangs_and_x (t, head->x, 1);
4994 x_prepend_glyph_string_lists (&head, &tail, h, t);
4995 }
dbcb258a 4996
06a2c219
GM
4997 /* Append glyphs strings for glyphs following the last glyph
4998 string tail that are overwritten by tail. The background of
4999 these strings has to be drawn because tail's foreground draws
5000 over it. */
5001 i = x_right_overwritten (tail);
5002 if (i >= 0)
5003 {
5004 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
5005 DRAW_NORMAL_TEXT, x, last_x,
5006 overlaps_p);
06a2c219
GM
5007 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5008 x_append_glyph_string_lists (&head, &tail, h, t);
5009 if (real_end)
5010 *real_end = i;
5011 }
dc6f92b8 5012
06a2c219
GM
5013 /* Append glyph strings for glyphs following the last glyph
5014 string tail that overwrite tail. The foreground of such
5015 glyphs has to be drawn because it writes into the background
5016 of tail. The background must not be drawn because it could
5017 paint over the foreground of following glyphs. */
5018 i = x_right_overwriting (tail);
5019 if (i >= 0)
5020 {
5021 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
5022 DRAW_NORMAL_TEXT, x, last_x,
5023 overlaps_p);
06a2c219
GM
5024 for (s = h; s; s = s->next)
5025 s->background_filled_p = 1;
5026 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5027 x_append_glyph_string_lists (&head, &tail, h, t);
5028 if (real_end)
5029 *real_end = i;
5030 }
5031 }
58769bee 5032
06a2c219
GM
5033 /* Draw all strings. */
5034 for (s = head; s; s = s->next)
5035 x_draw_glyph_string (s);
dc6f92b8 5036
06a2c219
GM
5037 /* Value is the x-position up to which drawn, relative to AREA of W.
5038 This doesn't include parts drawn because of overhangs. */
5039 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5040 if (!row->full_width_p)
5041 {
5042 if (area > LEFT_MARGIN_AREA)
5043 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5044 if (area > TEXT_AREA)
5045 x_reached -= window_box_width (w, TEXT_AREA);
5046 }
a8710abf 5047
06a2c219
GM
5048 return x_reached;
5049}
dc6f92b8 5050
dc6f92b8 5051
66ac4b0e
GM
5052/* Fix the display of area AREA of overlapping row ROW in window W. */
5053
5054static void
5055x_fix_overlapping_area (w, row, area)
5056 struct window *w;
5057 struct glyph_row *row;
5058 enum glyph_row_area area;
5059{
5060 int i, x;
5061
5062 BLOCK_INPUT;
5063
5064 if (area == LEFT_MARGIN_AREA)
5065 x = 0;
5066 else if (area == TEXT_AREA)
5067 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5068 else
5069 x = (window_box_width (w, LEFT_MARGIN_AREA)
5070 + window_box_width (w, TEXT_AREA));
5071
5072 for (i = 0; i < row->used[area];)
5073 {
5074 if (row->glyphs[area][i].overlaps_vertically_p)
5075 {
5076 int start = i, start_x = x;
5077
5078 do
5079 {
5080 x += row->glyphs[area][i].pixel_width;
5081 ++i;
5082 }
5083 while (i < row->used[area]
5084 && row->glyphs[area][i].overlaps_vertically_p);
5085
5086 x_draw_glyphs (w, start_x, row, area, start, i,
5087 (row->inverse_p
5088 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
5089 NULL, NULL, 1);
5090 }
5091 else
5092 {
5093 x += row->glyphs[area][i].pixel_width;
5094 ++i;
5095 }
5096 }
5097
5098 UNBLOCK_INPUT;
5099}
5100
5101
06a2c219
GM
5102/* Output LEN glyphs starting at START at the nominal cursor position.
5103 Advance the nominal cursor over the text. The global variable
5104 updated_window contains the window being updated, updated_row is
5105 the glyph row being updated, and updated_area is the area of that
5106 row being updated. */
dc6f92b8 5107
06a2c219
GM
5108static void
5109x_write_glyphs (start, len)
5110 struct glyph *start;
5111 int len;
5112{
5113 int x, hpos, real_start, real_end;
d9cdbb3d 5114
06a2c219 5115 xassert (updated_window && updated_row);
dc6f92b8 5116 BLOCK_INPUT;
06a2c219
GM
5117
5118 /* Write glyphs. */
dc6f92b8 5119
06a2c219
GM
5120 hpos = start - updated_row->glyphs[updated_area];
5121 x = x_draw_glyphs (updated_window, output_cursor.x,
5122 updated_row, updated_area,
5123 hpos, hpos + len,
5124 (updated_row->inverse_p
5125 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 5126 &real_start, &real_end, 0);
b30ec466 5127
06a2c219
GM
5128 /* If we drew over the cursor, note that it is not visible any more. */
5129 note_overwritten_text_cursor (updated_window, real_start,
5130 real_end - real_start);
dc6f92b8
JB
5131
5132 UNBLOCK_INPUT;
06a2c219
GM
5133
5134 /* Advance the output cursor. */
5135 output_cursor.hpos += len;
5136 output_cursor.x = x;
dc6f92b8
JB
5137}
5138
0cdd0c9f 5139
06a2c219 5140/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 5141
06a2c219
GM
5142static void
5143x_insert_glyphs (start, len)
5144 struct glyph *start;
5145 register int len;
5146{
5147 struct frame *f;
5148 struct window *w;
5149 int line_height, shift_by_width, shifted_region_width;
5150 struct glyph_row *row;
5151 struct glyph *glyph;
5152 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 5153
06a2c219 5154 xassert (updated_window && updated_row);
0cdd0c9f 5155 BLOCK_INPUT;
06a2c219
GM
5156 w = updated_window;
5157 f = XFRAME (WINDOW_FRAME (w));
5158
5159 /* Get the height of the line we are in. */
5160 row = updated_row;
5161 line_height = row->height;
5162
5163 /* Get the width of the glyphs to insert. */
5164 shift_by_width = 0;
5165 for (glyph = start; glyph < start + len; ++glyph)
5166 shift_by_width += glyph->pixel_width;
5167
5168 /* Get the width of the region to shift right. */
5169 shifted_region_width = (window_box_width (w, updated_area)
5170 - output_cursor.x
5171 - shift_by_width);
5172
5173 /* Shift right. */
bf0ab8a2 5174 frame_x = window_box_left (w, updated_area) + output_cursor.x;
06a2c219
GM
5175 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5176 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5177 f->output_data.x->normal_gc,
5178 frame_x, frame_y,
5179 shifted_region_width, line_height,
5180 frame_x + shift_by_width, frame_y);
5181
5182 /* Write the glyphs. */
5183 hpos = start - row->glyphs[updated_area];
5184 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 5185 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
5186 note_overwritten_text_cursor (w, real_start, real_end - real_start);
5187
5188 /* Advance the output cursor. */
5189 output_cursor.hpos += len;
5190 output_cursor.x += shift_by_width;
0cdd0c9f
RS
5191 UNBLOCK_INPUT;
5192}
0cdd0c9f 5193
0cdd0c9f 5194
06a2c219
GM
5195/* Delete N glyphs at the nominal cursor position. Not implemented
5196 for X frames. */
c83febd7
RS
5197
5198static void
06a2c219
GM
5199x_delete_glyphs (n)
5200 register int n;
c83febd7 5201{
06a2c219 5202 abort ();
c83febd7
RS
5203}
5204
0cdd0c9f 5205
c5e6e06b
GM
5206/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
5207 If they are <= 0, this is probably an error. */
5208
5209void
5210x_clear_area (dpy, window, x, y, width, height, exposures)
5211 Display *dpy;
5212 Window window;
5213 int x, y;
5214 int width, height;
5215 int exposures;
5216{
5217 xassert (width > 0 && height > 0);
5218 XClearArea (dpy, window, x, y, width, height, exposures);
5219}
5220
5221
06a2c219
GM
5222/* Erase the current text line from the nominal cursor position
5223 (inclusive) to pixel column TO_X (exclusive). The idea is that
5224 everything from TO_X onward is already erased.
5225
5226 TO_X is a pixel position relative to updated_area of
5227 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 5228
06a2c219
GM
5229static void
5230x_clear_end_of_line (to_x)
5231 int to_x;
5232{
5233 struct frame *f;
5234 struct window *w = updated_window;
5235 int max_x, min_y, max_y;
5236 int from_x, from_y, to_y;
5237
5238 xassert (updated_window && updated_row);
5239 f = XFRAME (w->frame);
5240
5241 if (updated_row->full_width_p)
5242 {
5243 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5244 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5245 && !w->pseudo_window_p)
5246 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 5247 }
06a2c219
GM
5248 else
5249 max_x = window_box_width (w, updated_area);
5250 max_y = window_text_bottom_y (w);
dc6f92b8 5251
06a2c219
GM
5252 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5253 of window. For TO_X > 0, truncate to end of drawing area. */
5254 if (to_x == 0)
5255 return;
5256 else if (to_x < 0)
5257 to_x = max_x;
5258 else
5259 to_x = min (to_x, max_x);
dbc4e1c1 5260
06a2c219
GM
5261 to_y = min (max_y, output_cursor.y + updated_row->height);
5262
5263 /* Notice if the cursor will be cleared by this operation. */
5264 if (!updated_row->full_width_p)
5265 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 5266
06a2c219
GM
5267 from_x = output_cursor.x;
5268
5269 /* Translate to frame coordinates. */
5270 if (updated_row->full_width_p)
5271 {
5272 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5273 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5274 }
0cdd0c9f
RS
5275 else
5276 {
06a2c219
GM
5277 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5278 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5279 }
5280
045dee35 5281 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5282 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5283 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5284
5285 /* Prevent inadvertently clearing to end of the X window. */
5286 if (to_x > from_x && to_y > from_y)
5287 {
5288 BLOCK_INPUT;
c5e6e06b
GM
5289 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5290 from_x, from_y, to_x - from_x, to_y - from_y,
5291 False);
06a2c219 5292 UNBLOCK_INPUT;
0cdd0c9f 5293 }
0cdd0c9f 5294}
dbc4e1c1 5295
0cdd0c9f 5296
06a2c219 5297/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5298 frame. Otherwise clear the selected frame. */
06a2c219
GM
5299
5300static void
5301x_clear_frame ()
0cdd0c9f 5302{
06a2c219 5303 struct frame *f;
0cdd0c9f 5304
06a2c219
GM
5305 if (updating_frame)
5306 f = updating_frame;
0cdd0c9f 5307 else
b86bd3dd 5308 f = SELECTED_FRAME ();
58769bee 5309
06a2c219
GM
5310 /* Clearing the frame will erase any cursor, so mark them all as no
5311 longer visible. */
5312 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5313 output_cursor.hpos = output_cursor.vpos = 0;
5314 output_cursor.x = -1;
5315
5316 /* We don't set the output cursor here because there will always
5317 follow an explicit cursor_to. */
5318 BLOCK_INPUT;
5319 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5320
5321 /* We have to clear the scroll bars, too. If we have changed
5322 colors or something like that, then they should be notified. */
5323 x_scroll_bar_clear (f);
0cdd0c9f 5324
06a2c219
GM
5325 XFlush (FRAME_X_DISPLAY (f));
5326 UNBLOCK_INPUT;
dc6f92b8 5327}
06a2c219
GM
5328
5329
dc6f92b8 5330\f
dbc4e1c1
JB
5331/* Invert the middle quarter of the frame for .15 sec. */
5332
06a2c219
GM
5333/* We use the select system call to do the waiting, so we have to make
5334 sure it's available. If it isn't, we just won't do visual bells. */
5335
dbc4e1c1
JB
5336#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5337
06a2c219
GM
5338
5339/* Subtract the `struct timeval' values X and Y, storing the result in
5340 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5341
5342static int
5343timeval_subtract (result, x, y)
5344 struct timeval *result, x, y;
5345{
06a2c219
GM
5346 /* Perform the carry for the later subtraction by updating y. This
5347 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5348 if (x.tv_usec < y.tv_usec)
5349 {
5350 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5351 y.tv_usec -= 1000000 * nsec;
5352 y.tv_sec += nsec;
5353 }
06a2c219 5354
dbc4e1c1
JB
5355 if (x.tv_usec - y.tv_usec > 1000000)
5356 {
5357 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5358 y.tv_usec += 1000000 * nsec;
5359 y.tv_sec -= nsec;
5360 }
5361
06a2c219
GM
5362 /* Compute the time remaining to wait. tv_usec is certainly
5363 positive. */
dbc4e1c1
JB
5364 result->tv_sec = x.tv_sec - y.tv_sec;
5365 result->tv_usec = x.tv_usec - y.tv_usec;
5366
06a2c219
GM
5367 /* Return indication of whether the result should be considered
5368 negative. */
dbc4e1c1
JB
5369 return x.tv_sec < y.tv_sec;
5370}
dc6f92b8 5371
dfcf069d 5372void
f676886a
JB
5373XTflash (f)
5374 struct frame *f;
dc6f92b8 5375{
dbc4e1c1 5376 BLOCK_INPUT;
dc6f92b8 5377
dbc4e1c1
JB
5378 {
5379 GC gc;
dc6f92b8 5380
06a2c219
GM
5381 /* Create a GC that will use the GXxor function to flip foreground
5382 pixels into background pixels. */
dbc4e1c1
JB
5383 {
5384 XGCValues values;
dc6f92b8 5385
dbc4e1c1 5386 values.function = GXxor;
7556890b
RS
5387 values.foreground = (f->output_data.x->foreground_pixel
5388 ^ f->output_data.x->background_pixel);
58769bee 5389
334208b7 5390 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5391 GCFunction | GCForeground, &values);
5392 }
dc6f92b8 5393
dbc4e1c1 5394 {
e84e14c3
RS
5395 /* Get the height not including a menu bar widget. */
5396 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5397 /* Height of each line to flash. */
5398 int flash_height = FRAME_LINE_HEIGHT (f);
5399 /* These will be the left and right margins of the rectangles. */
5400 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5401 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5402
5403 int width;
5404
5405 /* Don't flash the area between a scroll bar and the frame
5406 edge it is next to. */
5407 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5408 {
5409 case vertical_scroll_bar_left:
5410 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5411 break;
5412
5413 case vertical_scroll_bar_right:
5414 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5415 break;
06a2c219
GM
5416
5417 default:
5418 break;
e84e14c3
RS
5419 }
5420
5421 width = flash_right - flash_left;
5422
5423 /* If window is tall, flash top and bottom line. */
5424 if (height > 3 * FRAME_LINE_HEIGHT (f))
5425 {
5426 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5427 flash_left,
5428 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5429 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5430 width, flash_height);
5431 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5432 flash_left,
5433 (height - flash_height
5434 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5435 width, flash_height);
5436 }
5437 else
5438 /* If it is short, flash it all. */
5439 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5440 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5441 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5442
06a2c219 5443 x_flush (f);
dc6f92b8 5444
dbc4e1c1 5445 {
06a2c219 5446 struct timeval wakeup;
dc6f92b8 5447
66c30ea1 5448 EMACS_GET_TIME (wakeup);
dc6f92b8 5449
dbc4e1c1
JB
5450 /* Compute time to wait until, propagating carry from usecs. */
5451 wakeup.tv_usec += 150000;
5452 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5453 wakeup.tv_usec %= 1000000;
5454
101922c3
GM
5455 /* Keep waiting until past the time wakeup or any input gets
5456 available. */
5457 while (! detect_input_pending ())
dbc4e1c1 5458 {
101922c3 5459 struct timeval current;
dbc4e1c1
JB
5460 struct timeval timeout;
5461
101922c3 5462 EMACS_GET_TIME (current);
dbc4e1c1 5463
101922c3
GM
5464 /* Break if result would be negative. */
5465 if (timeval_subtract (&current, wakeup, current))
dbc4e1c1
JB
5466 break;
5467
101922c3
GM
5468 /* How long `select' should wait. */
5469 timeout.tv_sec = 0;
5470 timeout.tv_usec = 10000;
5471
dbc4e1c1 5472 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5473 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5474 }
5475 }
58769bee 5476
e84e14c3
RS
5477 /* If window is tall, flash top and bottom line. */
5478 if (height > 3 * FRAME_LINE_HEIGHT (f))
5479 {
5480 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5481 flash_left,
5482 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5483 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5484 width, flash_height);
5485 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5486 flash_left,
5487 (height - flash_height
5488 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5489 width, flash_height);
5490 }
5491 else
5492 /* If it is short, flash it all. */
5493 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5494 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5495 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5496
334208b7 5497 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5498 x_flush (f);
dc6f92b8 5499 }
dbc4e1c1
JB
5500 }
5501
5502 UNBLOCK_INPUT;
dc6f92b8
JB
5503}
5504
06a2c219 5505#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5506
5507
dc6f92b8
JB
5508/* Make audible bell. */
5509
dfcf069d 5510void
dc6f92b8
JB
5511XTring_bell ()
5512{
b86bd3dd
GM
5513 struct frame *f = SELECTED_FRAME ();
5514
5515 if (FRAME_X_DISPLAY (f))
5516 {
dbc4e1c1 5517#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5518 if (visible_bell)
5519 XTflash (f);
5520 else
dbc4e1c1 5521#endif
b86bd3dd
GM
5522 {
5523 BLOCK_INPUT;
5524 XBell (FRAME_X_DISPLAY (f), 0);
5525 XFlush (FRAME_X_DISPLAY (f));
5526 UNBLOCK_INPUT;
5527 }
dc6f92b8
JB
5528 }
5529}
06a2c219 5530
dc6f92b8 5531\f
06a2c219
GM
5532/* Specify how many text lines, from the top of the window,
5533 should be affected by insert-lines and delete-lines operations.
5534 This, and those operations, are used only within an update
5535 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5536
dfcf069d 5537static void
06a2c219
GM
5538XTset_terminal_window (n)
5539 register int n;
dc6f92b8 5540{
06a2c219 5541 /* This function intentionally left blank. */
dc6f92b8
JB
5542}
5543
06a2c219
GM
5544
5545\f
5546/***********************************************************************
5547 Line Dance
5548 ***********************************************************************/
5549
5550/* Perform an insert-lines or delete-lines operation, inserting N
5551 lines or deleting -N lines at vertical position VPOS. */
5552
dfcf069d 5553static void
06a2c219
GM
5554x_ins_del_lines (vpos, n)
5555 int vpos, n;
dc6f92b8
JB
5556{
5557 abort ();
5558}
06a2c219
GM
5559
5560
5561/* Scroll part of the display as described by RUN. */
dc6f92b8 5562
dfcf069d 5563static void
06a2c219
GM
5564x_scroll_run (w, run)
5565 struct window *w;
5566 struct run *run;
dc6f92b8 5567{
06a2c219
GM
5568 struct frame *f = XFRAME (w->frame);
5569 int x, y, width, height, from_y, to_y, bottom_y;
5570
5571 /* Get frame-relative bounding box of the text display area of W,
5572 without mode lines. Include in this box the flags areas to the
5573 left and right of W. */
5574 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5575 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5576 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5577
5578 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5579 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5580 bottom_y = y + height;
dc6f92b8 5581
06a2c219
GM
5582 if (to_y < from_y)
5583 {
5584 /* Scrolling up. Make sure we don't copy part of the mode
5585 line at the bottom. */
5586 if (from_y + run->height > bottom_y)
5587 height = bottom_y - from_y;
5588 else
5589 height = run->height;
5590 }
dc6f92b8 5591 else
06a2c219
GM
5592 {
5593 /* Scolling down. Make sure we don't copy over the mode line.
5594 at the bottom. */
5595 if (to_y + run->height > bottom_y)
5596 height = bottom_y - to_y;
5597 else
5598 height = run->height;
5599 }
7a13e894 5600
06a2c219
GM
5601 BLOCK_INPUT;
5602
5603 /* Cursor off. Will be switched on again in x_update_window_end. */
5604 updated_window = w;
5605 x_clear_cursor (w);
5606
5607 XCopyArea (FRAME_X_DISPLAY (f),
5608 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5609 f->output_data.x->normal_gc,
5610 x, from_y,
5611 width, height,
5612 x, to_y);
5613
5614 UNBLOCK_INPUT;
5615}
dc6f92b8 5616
dc6f92b8 5617
06a2c219
GM
5618\f
5619/***********************************************************************
5620 Exposure Events
5621 ***********************************************************************/
5622
5623/* Redisplay an exposed area of frame F. X and Y are the upper-left
5624 corner of the exposed rectangle. W and H are width and height of
5625 the exposed area. All are pixel values. W or H zero means redraw
5626 the entire frame. */
dc6f92b8 5627
06a2c219
GM
5628static void
5629expose_frame (f, x, y, w, h)
5630 struct frame *f;
5631 int x, y, w, h;
dc6f92b8 5632{
06a2c219 5633 XRectangle r;
dc6f92b8 5634
06a2c219 5635 TRACE ((stderr, "expose_frame "));
dc6f92b8 5636
06a2c219
GM
5637 /* No need to redraw if frame will be redrawn soon. */
5638 if (FRAME_GARBAGED_P (f))
dc6f92b8 5639 {
06a2c219
GM
5640 TRACE ((stderr, " garbaged\n"));
5641 return;
5642 }
5643
5644 /* If basic faces haven't been realized yet, there is no point in
5645 trying to redraw anything. This can happen when we get an expose
5646 event while Emacs is starting, e.g. by moving another window. */
5647 if (FRAME_FACE_CACHE (f) == NULL
5648 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5649 {
5650 TRACE ((stderr, " no faces\n"));
5651 return;
58769bee 5652 }
06a2c219
GM
5653
5654 if (w == 0 || h == 0)
58769bee 5655 {
06a2c219
GM
5656 r.x = r.y = 0;
5657 r.width = CANON_X_UNIT (f) * f->width;
5658 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5659 }
5660 else
5661 {
06a2c219
GM
5662 r.x = x;
5663 r.y = y;
5664 r.width = w;
5665 r.height = h;
5666 }
5667
5668 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5669 expose_window_tree (XWINDOW (f->root_window), &r);
5670
9ea173e8 5671 if (WINDOWP (f->tool_bar_window))
a02f1be0 5672 expose_window (XWINDOW (f->tool_bar_window), &r);
06a2c219
GM
5673
5674#ifndef USE_X_TOOLKIT
5675 if (WINDOWP (f->menu_bar_window))
a02f1be0 5676 expose_window (XWINDOW (f->menu_bar_window), &r);
06a2c219 5677#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5678}
5679
06a2c219
GM
5680
5681/* Redraw (parts) of all windows in the window tree rooted at W that
5682 intersect R. R contains frame pixel coordinates. */
5683
58769bee 5684static void
06a2c219
GM
5685expose_window_tree (w, r)
5686 struct window *w;
5687 XRectangle *r;
dc6f92b8 5688{
06a2c219
GM
5689 while (w)
5690 {
5691 if (!NILP (w->hchild))
5692 expose_window_tree (XWINDOW (w->hchild), r);
5693 else if (!NILP (w->vchild))
5694 expose_window_tree (XWINDOW (w->vchild), r);
5695 else
a02f1be0
GM
5696 expose_window (w, r);
5697 w = NILP (w->next) ? NULL : XWINDOW (w->next);
06a2c219
GM
5698 }
5699}
58769bee 5700
dc6f92b8 5701
06a2c219
GM
5702/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5703 which intersects rectangle R. R is in window-relative coordinates. */
5704
5705static void
5706expose_area (w, row, r, area)
5707 struct window *w;
5708 struct glyph_row *row;
5709 XRectangle *r;
5710 enum glyph_row_area area;
5711{
06a2c219
GM
5712 struct glyph *first = row->glyphs[area];
5713 struct glyph *end = row->glyphs[area] + row->used[area];
5714 struct glyph *last;
4bc6dcc7 5715 int first_x, start_x, x;
06a2c219 5716
6fb13182
GM
5717 if (area == TEXT_AREA && row->fill_line_p)
5718 /* If row extends face to end of line write the whole line. */
4bc6dcc7 5719 x_draw_glyphs (w, 0, row, area,
6fb13182 5720 0, row->used[area],
06a2c219 5721 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5722 NULL, NULL, 0);
6fb13182
GM
5723 else
5724 {
4bc6dcc7
GM
5725 /* Set START_X to the window-relative start position for drawing glyphs of
5726 AREA. The first glyph of the text area can be partially visible.
5727 The first glyphs of other areas cannot. */
5728 if (area == LEFT_MARGIN_AREA)
5729 start_x = 0;
5730 else if (area == TEXT_AREA)
5731 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5732 else
5733 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5734 + window_box_width (w, TEXT_AREA));
5735 x = start_x;
5736
6fb13182
GM
5737 /* Find the first glyph that must be redrawn. */
5738 while (first < end
5739 && x + first->pixel_width < r->x)
5740 {
5741 x += first->pixel_width;
5742 ++first;
5743 }
5744
5745 /* Find the last one. */
5746 last = first;
5747 first_x = x;
5748 while (last < end
5749 && x < r->x + r->width)
5750 {
5751 x += last->pixel_width;
5752 ++last;
5753 }
5754
5755 /* Repaint. */
5756 if (last > first)
4bc6dcc7 5757 x_draw_glyphs (w, first_x - start_x, row, area,
6fb13182
GM
5758 first - row->glyphs[area],
5759 last - row->glyphs[area],
5760 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5761 NULL, NULL, 0);
5762 }
06a2c219
GM
5763}
5764
58769bee 5765
06a2c219
GM
5766/* Redraw the parts of the glyph row ROW on window W intersecting
5767 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5768
06a2c219
GM
5769static void
5770expose_line (w, row, r)
5771 struct window *w;
5772 struct glyph_row *row;
5773 XRectangle *r;
5774{
5775 xassert (row->enabled_p);
5776
5777 if (row->mode_line_p || w->pseudo_window_p)
5778 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5779 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5780 NULL, NULL, 0);
06a2c219
GM
5781 else
5782 {
5783 if (row->used[LEFT_MARGIN_AREA])
5784 expose_area (w, row, r, LEFT_MARGIN_AREA);
5785 if (row->used[TEXT_AREA])
5786 expose_area (w, row, r, TEXT_AREA);
5787 if (row->used[RIGHT_MARGIN_AREA])
5788 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5789 x_draw_row_bitmaps (w, row);
5790 }
5791}
dc6f92b8 5792
58769bee 5793
06a2c219
GM
5794/* Return non-zero if W's cursor intersects rectangle R. */
5795
5796static int
5797x_phys_cursor_in_rect_p (w, r)
5798 struct window *w;
5799 XRectangle *r;
5800{
5801 XRectangle cr, result;
5802 struct glyph *cursor_glyph;
5803
5804 cursor_glyph = get_phys_cursor_glyph (w);
5805 if (cursor_glyph)
5806 {
5807 cr.x = w->phys_cursor.x;
5808 cr.y = w->phys_cursor.y;
5809 cr.width = cursor_glyph->pixel_width;
5810 cr.height = w->phys_cursor_height;
5811 return x_intersect_rectangles (&cr, r, &result);
5812 }
5813 else
5814 return 0;
dc6f92b8 5815}
dc6f92b8 5816
06a2c219 5817
a02f1be0
GM
5818/* Redraw the part of window W intersection rectangle FR. Pixel
5819 coordinates in FR are frame-relative. Call this function with
5820 input blocked. */
dc6f92b8
JB
5821
5822static void
a02f1be0 5823expose_window (w, fr)
06a2c219 5824 struct window *w;
a02f1be0 5825 XRectangle *fr;
dc6f92b8 5826{
a02f1be0 5827 struct frame *f = XFRAME (w->frame);
06a2c219 5828 struct glyph_row *row;
a02f1be0
GM
5829 int y, yb, cursor_cleared_p;
5830 XRectangle wr, r;
dc6f92b8 5831
80c32bcc
GM
5832 /* If window is not yet fully initialized, do nothing. This can
5833 happen when toolkit scroll bars are used and a window is split.
5834 Reconfiguring the scroll bar will generate an expose for a newly
5835 created window. */
c7911417 5836 if (w->current_matrix == NULL || w == updated_window)
80c32bcc
GM
5837 return;
5838
a02f1be0
GM
5839 /* Frame-relative pixel rectangle of W. */
5840 wr.x = XFASTINT (w->left) * CANON_X_UNIT (f);
5841 wr.y = XFASTINT (w->top) * CANON_Y_UNIT (f);
5842 wr.width = XFASTINT (w->width) * CANON_X_UNIT (f);
5843 wr.height = XFASTINT (w->height) * CANON_Y_UNIT (f);
5844
5845 if (!x_intersect_rectangles (fr, &wr, &r))
5846 return;
5847
5848 yb = window_text_bottom_y (w);
5849
06a2c219 5850 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
a02f1be0 5851 r.x, r.y, r.width, r.height));
dc6f92b8 5852
06a2c219 5853 /* Convert to window coordinates. */
a02f1be0
GM
5854 r.x = FRAME_TO_WINDOW_PIXEL_X (w, r.x);
5855 r.y = FRAME_TO_WINDOW_PIXEL_Y (w, r.y);
dc6f92b8 5856
06a2c219
GM
5857 /* Turn off the cursor. */
5858 if (!w->pseudo_window_p
a02f1be0 5859 && x_phys_cursor_in_rect_p (w, &r))
06a2c219
GM
5860 {
5861 x_clear_cursor (w);
5862 cursor_cleared_p = 1;
5863 }
5864 else
5865 cursor_cleared_p = 0;
5866
5867 /* Find the first row intersecting the rectangle R. */
5868 row = w->current_matrix->rows;
5869 y = 0;
5870 while (row->enabled_p
5871 && y < yb
a02f1be0 5872 && y + row->height < r.y)
06a2c219
GM
5873 {
5874 y += row->height;
5875 ++row;
5876 }
5877
dc6f92b8 5878 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5879 while (row->enabled_p
5880 && y < yb
a02f1be0 5881 && y < r.y + r.height)
06a2c219 5882 {
a02f1be0 5883 expose_line (w, row, &r);
06a2c219
GM
5884 y += row->height;
5885 ++row;
5886 }
5887
5888 /* Display the mode line if there is one. */
5889 if (WINDOW_WANTS_MODELINE_P (w)
5890 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5891 row->enabled_p)
a02f1be0
GM
5892 && row->y < r.y + r.height)
5893 expose_line (w, row, &r);
dc6f92b8 5894
06a2c219 5895 if (!w->pseudo_window_p)
dc6f92b8 5896 {
06a2c219
GM
5897 /* Draw border between windows. */
5898 x_draw_vertical_border (w);
5899
5900 /* Turn the cursor on again. */
5901 if (cursor_cleared_p)
5902 x_update_window_cursor (w, 1);
5903 }
5904}
dc6f92b8 5905
dc6f92b8 5906
06a2c219
GM
5907/* Determine the intersection of two rectangles R1 and R2. Return
5908 the intersection in *RESULT. Value is non-zero if RESULT is not
5909 empty. */
5910
5911static int
5912x_intersect_rectangles (r1, r2, result)
5913 XRectangle *r1, *r2, *result;
5914{
5915 XRectangle *left, *right;
5916 XRectangle *upper, *lower;
5917 int intersection_p = 0;
5918
5919 /* Rearrange so that R1 is the left-most rectangle. */
5920 if (r1->x < r2->x)
5921 left = r1, right = r2;
5922 else
5923 left = r2, right = r1;
5924
5925 /* X0 of the intersection is right.x0, if this is inside R1,
5926 otherwise there is no intersection. */
5927 if (right->x <= left->x + left->width)
5928 {
5929 result->x = right->x;
5930
5931 /* The right end of the intersection is the minimum of the
5932 the right ends of left and right. */
5933 result->width = (min (left->x + left->width, right->x + right->width)
5934 - result->x);
5935
5936 /* Same game for Y. */
5937 if (r1->y < r2->y)
5938 upper = r1, lower = r2;
5939 else
5940 upper = r2, lower = r1;
5941
5942 /* The upper end of the intersection is lower.y0, if this is inside
5943 of upper. Otherwise, there is no intersection. */
5944 if (lower->y <= upper->y + upper->height)
dc43ef94 5945 {
06a2c219
GM
5946 result->y = lower->y;
5947
5948 /* The lower end of the intersection is the minimum of the lower
5949 ends of upper and lower. */
5950 result->height = (min (lower->y + lower->height,
5951 upper->y + upper->height)
5952 - result->y);
5953 intersection_p = 1;
dc43ef94 5954 }
dc6f92b8
JB
5955 }
5956
06a2c219 5957 return intersection_p;
dc6f92b8 5958}
06a2c219
GM
5959
5960
5961
5962
dc6f92b8 5963\f
dc6f92b8 5964static void
334208b7
RS
5965frame_highlight (f)
5966 struct frame *f;
dc6f92b8 5967{
b3e1e05c
JB
5968 /* We used to only do this if Vx_no_window_manager was non-nil, but
5969 the ICCCM (section 4.1.6) says that the window's border pixmap
5970 and border pixel are window attributes which are "private to the
5971 client", so we can always change it to whatever we want. */
5972 BLOCK_INPUT;
334208b7 5973 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5974 f->output_data.x->border_pixel);
b3e1e05c 5975 UNBLOCK_INPUT;
5d46f928 5976 x_update_cursor (f, 1);
dc6f92b8
JB
5977}
5978
5979static void
334208b7
RS
5980frame_unhighlight (f)
5981 struct frame *f;
dc6f92b8 5982{
b3e1e05c
JB
5983 /* We used to only do this if Vx_no_window_manager was non-nil, but
5984 the ICCCM (section 4.1.6) says that the window's border pixmap
5985 and border pixel are window attributes which are "private to the
5986 client", so we can always change it to whatever we want. */
5987 BLOCK_INPUT;
334208b7 5988 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5989 f->output_data.x->border_tile);
b3e1e05c 5990 UNBLOCK_INPUT;
5d46f928 5991 x_update_cursor (f, 1);
dc6f92b8 5992}
dc6f92b8 5993
f676886a
JB
5994/* The focus has changed. Update the frames as necessary to reflect
5995 the new situation. Note that we can't change the selected frame
c5acd733 5996 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5997 Each event gets marked with the frame in which it occurred, so the
c5acd733 5998 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5999
6d4238f3 6000static void
0f941935
KH
6001x_new_focus_frame (dpyinfo, frame)
6002 struct x_display_info *dpyinfo;
f676886a 6003 struct frame *frame;
dc6f92b8 6004{
0f941935 6005 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 6006
0f941935 6007 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 6008 {
58769bee 6009 /* Set this before calling other routines, so that they see
f676886a 6010 the correct value of x_focus_frame. */
0f941935 6011 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
6012
6013 if (old_focus && old_focus->auto_lower)
f676886a 6014 x_lower_frame (old_focus);
dc6f92b8
JB
6015
6016#if 0
f676886a 6017 selected_frame = frame;
e0c1aef2
KH
6018 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
6019 selected_frame);
f676886a
JB
6020 Fselect_window (selected_frame->selected_window);
6021 choose_minibuf_frame ();
c118dd06 6022#endif /* ! 0 */
dc6f92b8 6023
0f941935
KH
6024 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
6025 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
6026 else
6027 pending_autoraise_frame = 0;
6d4238f3 6028 }
dc6f92b8 6029
0f941935 6030 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
6031}
6032
37c2c98b
RS
6033/* Handle an event saying the mouse has moved out of an Emacs frame. */
6034
6035void
0f941935
KH
6036x_mouse_leave (dpyinfo)
6037 struct x_display_info *dpyinfo;
37c2c98b 6038{
0f941935 6039 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 6040}
6d4238f3 6041
f451eb13
JB
6042/* The focus has changed, or we have redirected a frame's focus to
6043 another frame (this happens when a frame uses a surrogate
06a2c219 6044 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
6045
6046 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 6047 frame is being highlighted or un-highlighted; we only use it to find
0f941935 6048 the appropriate X display info. */
06a2c219 6049
6d4238f3 6050static void
0f941935
KH
6051XTframe_rehighlight (frame)
6052 struct frame *frame;
6d4238f3 6053{
0f941935
KH
6054 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
6055}
6d4238f3 6056
0f941935
KH
6057static void
6058x_frame_rehighlight (dpyinfo)
6059 struct x_display_info *dpyinfo;
6060{
6061 struct frame *old_highlight = dpyinfo->x_highlight_frame;
6062
6063 if (dpyinfo->x_focus_frame)
6d4238f3 6064 {
0f941935
KH
6065 dpyinfo->x_highlight_frame
6066 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
6067 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
6068 : dpyinfo->x_focus_frame);
6069 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 6070 {
0f941935
KH
6071 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
6072 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 6073 }
dc6f92b8 6074 }
6d4238f3 6075 else
0f941935 6076 dpyinfo->x_highlight_frame = 0;
dc6f92b8 6077
0f941935 6078 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
6079 {
6080 if (old_highlight)
f676886a 6081 frame_unhighlight (old_highlight);
0f941935
KH
6082 if (dpyinfo->x_highlight_frame)
6083 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 6084 }
dc6f92b8 6085}
06a2c219
GM
6086
6087
dc6f92b8 6088\f
06a2c219 6089/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 6090
28430d3c
JB
6091/* Initialize mode_switch_bit and modifier_meaning. */
6092static void
334208b7
RS
6093x_find_modifier_meanings (dpyinfo)
6094 struct x_display_info *dpyinfo;
28430d3c 6095{
f689eb05 6096 int min_code, max_code;
28430d3c
JB
6097 KeySym *syms;
6098 int syms_per_code;
6099 XModifierKeymap *mods;
6100
334208b7
RS
6101 dpyinfo->meta_mod_mask = 0;
6102 dpyinfo->shift_lock_mask = 0;
6103 dpyinfo->alt_mod_mask = 0;
6104 dpyinfo->super_mod_mask = 0;
6105 dpyinfo->hyper_mod_mask = 0;
58769bee 6106
9658a521 6107#ifdef HAVE_X11R4
334208b7 6108 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 6109#else
4a60f8c5
RS
6110 min_code = dpyinfo->display->min_keycode;
6111 max_code = dpyinfo->display->max_keycode;
9658a521
JB
6112#endif
6113
334208b7 6114 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
6115 min_code, max_code - min_code + 1,
6116 &syms_per_code);
334208b7 6117 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 6118
58769bee 6119 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 6120 Alt keysyms are on. */
28430d3c 6121 {
06a2c219 6122 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
6123
6124 for (row = 3; row < 8; row++)
6125 for (col = 0; col < mods->max_keypermod; col++)
6126 {
0299d313
RS
6127 KeyCode code
6128 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 6129
af92970c
KH
6130 /* Zeroes are used for filler. Skip them. */
6131 if (code == 0)
6132 continue;
6133
28430d3c
JB
6134 /* Are any of this keycode's keysyms a meta key? */
6135 {
6136 int code_col;
6137
6138 for (code_col = 0; code_col < syms_per_code; code_col++)
6139 {
f689eb05 6140 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 6141
f689eb05 6142 switch (sym)
28430d3c 6143 {
f689eb05
JB
6144 case XK_Meta_L:
6145 case XK_Meta_R:
334208b7 6146 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 6147 break;
f689eb05
JB
6148
6149 case XK_Alt_L:
6150 case XK_Alt_R:
334208b7 6151 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
6152 break;
6153
6154 case XK_Hyper_L:
6155 case XK_Hyper_R:
334208b7 6156 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
6157 break;
6158
6159 case XK_Super_L:
6160 case XK_Super_R:
334208b7 6161 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 6162 break;
11edeb03
JB
6163
6164 case XK_Shift_Lock:
6165 /* Ignore this if it's not on the lock modifier. */
6166 if ((1 << row) == LockMask)
334208b7 6167 dpyinfo->shift_lock_mask = LockMask;
11edeb03 6168 break;
28430d3c
JB
6169 }
6170 }
6171 }
6172 }
6173 }
6174
f689eb05 6175 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 6176 if (! dpyinfo->meta_mod_mask)
a3c44b14 6177 {
334208b7
RS
6178 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6179 dpyinfo->alt_mod_mask = 0;
a3c44b14 6180 }
f689eb05 6181
148c4b70
RS
6182 /* If some keys are both alt and meta,
6183 make them just meta, not alt. */
334208b7 6184 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 6185 {
334208b7 6186 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 6187 }
58769bee 6188
28430d3c 6189 XFree ((char *) syms);
f689eb05 6190 XFreeModifiermap (mods);
28430d3c
JB
6191}
6192
dfeccd2d
JB
6193/* Convert between the modifier bits X uses and the modifier bits
6194 Emacs uses. */
06a2c219 6195
7c5283e4 6196static unsigned int
334208b7
RS
6197x_x_to_emacs_modifiers (dpyinfo, state)
6198 struct x_display_info *dpyinfo;
dc6f92b8
JB
6199 unsigned int state;
6200{
334208b7
RS
6201 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6202 | ((state & ControlMask) ? ctrl_modifier : 0)
6203 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6204 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6205 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6206 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
6207}
6208
dfeccd2d 6209static unsigned int
334208b7
RS
6210x_emacs_to_x_modifiers (dpyinfo, state)
6211 struct x_display_info *dpyinfo;
dfeccd2d
JB
6212 unsigned int state;
6213{
334208b7
RS
6214 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6215 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6216 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6217 | ((state & shift_modifier) ? ShiftMask : 0)
6218 | ((state & ctrl_modifier) ? ControlMask : 0)
6219 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6220}
d047c4eb
KH
6221
6222/* Convert a keysym to its name. */
6223
6224char *
6225x_get_keysym_name (keysym)
6226 KeySym keysym;
6227{
6228 char *value;
6229
6230 BLOCK_INPUT;
6231 value = XKeysymToString (keysym);
6232 UNBLOCK_INPUT;
6233
6234 return value;
6235}
06a2c219
GM
6236
6237
e4571a43
JB
6238\f
6239/* Mouse clicks and mouse movement. Rah. */
e4571a43 6240
06a2c219
GM
6241/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6242 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6243 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6244 not force the value into range. */
69388238 6245
c8dba240 6246void
69388238 6247pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6248 FRAME_PTR f;
69388238 6249 register int pix_x, pix_y;
e4571a43
JB
6250 register int *x, *y;
6251 XRectangle *bounds;
69388238 6252 int noclip;
e4571a43 6253{
06a2c219 6254 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6255 even for negative values. */
6256 if (pix_x < 0)
7556890b 6257 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6258 if (pix_y < 0)
7556890b 6259 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6260
e4571a43
JB
6261 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6262 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6263
6264 if (bounds)
6265 {
7556890b
RS
6266 bounds->width = FONT_WIDTH (f->output_data.x->font);
6267 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6268 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6269 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6270 }
6271
69388238
RS
6272 if (!noclip)
6273 {
6274 if (pix_x < 0)
6275 pix_x = 0;
3cbd2e0b
RS
6276 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6277 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6278
6279 if (pix_y < 0)
6280 pix_y = 0;
6281 else if (pix_y > f->height)
6282 pix_y = f->height;
6283 }
e4571a43
JB
6284
6285 *x = pix_x;
6286 *y = pix_y;
6287}
6288
06a2c219
GM
6289
6290/* Given HPOS/VPOS in the current matrix of W, return corresponding
6291 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6292 can't tell the positions because W's display is not up to date,
6293 return 0. */
6294
6295int
6296glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6297 struct window *w;
6298 int hpos, vpos;
6299 int *frame_x, *frame_y;
2b5c9e71 6300{
06a2c219
GM
6301 int success_p;
6302
6303 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6304 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6305
6306 if (display_completed)
6307 {
6308 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6309 struct glyph *glyph = row->glyphs[TEXT_AREA];
6310 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6311
6312 *frame_y = row->y;
6313 *frame_x = row->x;
6314 while (glyph < end)
6315 {
6316 *frame_x += glyph->pixel_width;
6317 ++glyph;
6318 }
6319
6320 success_p = 1;
6321 }
6322 else
6323 {
6324 *frame_y = *frame_x = 0;
6325 success_p = 0;
6326 }
6327
6328 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6329 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6330 return success_p;
2b5c9e71
RS
6331}
6332
06a2c219 6333
dc6f92b8
JB
6334/* Prepare a mouse-event in *RESULT for placement in the input queue.
6335
6336 If the event is a button press, then note that we have grabbed
f451eb13 6337 the mouse. */
dc6f92b8
JB
6338
6339static Lisp_Object
f451eb13 6340construct_mouse_click (result, event, f)
dc6f92b8
JB
6341 struct input_event *result;
6342 XButtonEvent *event;
f676886a 6343 struct frame *f;
dc6f92b8 6344{
f451eb13 6345 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6346 otherwise. */
f451eb13 6347 result->kind = mouse_click;
69388238 6348 result->code = event->button - Button1;
1113d9db 6349 result->timestamp = event->time;
334208b7
RS
6350 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6351 event->state)
f689eb05 6352 | (event->type == ButtonRelease
58769bee 6353 ? up_modifier
f689eb05 6354 : down_modifier));
dc6f92b8 6355
06a2c219
GM
6356 XSETINT (result->x, event->x);
6357 XSETINT (result->y, event->y);
6358 XSETFRAME (result->frame_or_window, f);
0f8aabe9 6359 result->arg = Qnil;
06a2c219 6360 return Qnil;
dc6f92b8 6361}
b849c413 6362
69388238 6363\f
90e65f07
JB
6364/* Function to report a mouse movement to the mainstream Emacs code.
6365 The input handler calls this.
6366
6367 We have received a mouse movement event, which is given in *event.
6368 If the mouse is over a different glyph than it was last time, tell
6369 the mainstream emacs code by setting mouse_moved. If not, ask for
6370 another motion event, so we can check again the next time it moves. */
b8009dd1 6371
06a2c219
GM
6372static XMotionEvent last_mouse_motion_event;
6373static Lisp_Object last_mouse_motion_frame;
6374
90e65f07 6375static void
12ba150f 6376note_mouse_movement (frame, event)
f676886a 6377 FRAME_PTR frame;
90e65f07 6378 XMotionEvent *event;
90e65f07 6379{
e5d77022 6380 last_mouse_movement_time = event->time;
06a2c219
GM
6381 last_mouse_motion_event = *event;
6382 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6383
27f338af
RS
6384 if (event->window != FRAME_X_WINDOW (frame))
6385 {
39d8bb4d 6386 frame->mouse_moved = 1;
27f338af 6387 last_mouse_scroll_bar = Qnil;
27f338af 6388 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6389 }
6390
90e65f07 6391 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6392 else if (event->x < last_mouse_glyph.x
6393 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6394 || event->y < last_mouse_glyph.y
6395 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6396 {
39d8bb4d 6397 frame->mouse_moved = 1;
ab648270 6398 last_mouse_scroll_bar = Qnil;
b8009dd1 6399 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6400 }
6401}
6402
bf1c0ba1 6403/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6404
06a2c219
GM
6405 int disable_mouse_highlight;
6406
6407
6408\f
6409/************************************************************************
6410 Mouse Face
6411 ************************************************************************/
6412
6413/* Find the glyph under window-relative coordinates X/Y in window W.
6414 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6415 strings. Return in *HPOS and *VPOS the row and column number of
6416 the glyph found. Return in *AREA the glyph area containing X.
6417 Value is a pointer to the glyph found or null if X/Y is not on
6418 text, or we can't tell because W's current matrix is not up to
6419 date. */
6420
6421static struct glyph *
f9db2310 6422x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
06a2c219
GM
6423 struct window *w;
6424 int x, y;
6425 int *hpos, *vpos, *area;
f9db2310 6426 int buffer_only_p;
06a2c219
GM
6427{
6428 struct glyph *glyph, *end;
3e71d8f2 6429 struct glyph_row *row = NULL;
06a2c219
GM
6430 int x0, i, left_area_width;
6431
6432 /* Find row containing Y. Give up if some row is not enabled. */
6433 for (i = 0; i < w->current_matrix->nrows; ++i)
6434 {
6435 row = MATRIX_ROW (w->current_matrix, i);
6436 if (!row->enabled_p)
6437 return NULL;
6438 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6439 break;
6440 }
6441
6442 *vpos = i;
6443 *hpos = 0;
6444
6445 /* Give up if Y is not in the window. */
6446 if (i == w->current_matrix->nrows)
6447 return NULL;
6448
6449 /* Get the glyph area containing X. */
6450 if (w->pseudo_window_p)
6451 {
6452 *area = TEXT_AREA;
6453 x0 = 0;
6454 }
6455 else
6456 {
6457 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6458 if (x < left_area_width)
6459 {
6460 *area = LEFT_MARGIN_AREA;
6461 x0 = 0;
6462 }
6463 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6464 {
6465 *area = TEXT_AREA;
6466 x0 = row->x + left_area_width;
6467 }
6468 else
6469 {
6470 *area = RIGHT_MARGIN_AREA;
6471 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6472 }
6473 }
6474
6475 /* Find glyph containing X. */
6476 glyph = row->glyphs[*area];
6477 end = glyph + row->used[*area];
6478 while (glyph < end)
6479 {
6480 if (x < x0 + glyph->pixel_width)
6481 {
6482 if (w->pseudo_window_p)
6483 break;
f9db2310 6484 else if (!buffer_only_p || BUFFERP (glyph->object))
06a2c219
GM
6485 break;
6486 }
6487
6488 x0 += glyph->pixel_width;
6489 ++glyph;
6490 }
6491
6492 if (glyph == end)
6493 return NULL;
6494
6495 *hpos = glyph - row->glyphs[*area];
6496 return glyph;
6497}
6498
6499
6500/* Convert frame-relative x/y to coordinates relative to window W.
6501 Takes pseudo-windows into account. */
6502
6503static void
6504frame_to_window_pixel_xy (w, x, y)
6505 struct window *w;
6506 int *x, *y;
6507{
6508 if (w->pseudo_window_p)
6509 {
6510 /* A pseudo-window is always full-width, and starts at the
6511 left edge of the frame, plus a frame border. */
6512 struct frame *f = XFRAME (w->frame);
6513 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6514 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6515 }
6516 else
6517 {
6518 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6519 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6520 }
6521}
6522
6523
e371a781 6524/* Take proper action when mouse has moved to the mode or header line of
06a2c219
GM
6525 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6526 mode line. X is relative to the start of the text display area of
6527 W, so the width of bitmap areas and scroll bars must be subtracted
6528 to get a position relative to the start of the mode line. */
6529
6530static void
6531note_mode_line_highlight (w, x, mode_line_p)
6532 struct window *w;
6533 int x, mode_line_p;
6534{
6535 struct frame *f = XFRAME (w->frame);
6536 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6537 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6538 struct glyph_row *row;
6539
6540 if (mode_line_p)
6541 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6542 else
045dee35 6543 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
e371a781 6544
06a2c219
GM
6545 if (row->enabled_p)
6546 {
6547 struct glyph *glyph, *end;
6548 Lisp_Object help, map;
6549 int x0;
6550
6551 /* Find the glyph under X. */
6552 glyph = row->glyphs[TEXT_AREA];
6553 end = glyph + row->used[TEXT_AREA];
6554 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6555 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
e371a781 6556
06a2c219
GM
6557 while (glyph < end
6558 && x >= x0 + glyph->pixel_width)
6559 {
6560 x0 += glyph->pixel_width;
6561 ++glyph;
6562 }
6563
6564 if (glyph < end
6565 && STRINGP (glyph->object)
6566 && XSTRING (glyph->object)->intervals
6567 && glyph->charpos >= 0
6568 && glyph->charpos < XSTRING (glyph->object)->size)
6569 {
6570 /* If we're on a string with `help-echo' text property,
6571 arrange for the help to be displayed. This is done by
6572 setting the global variable help_echo to the help string. */
6573 help = Fget_text_property (make_number (glyph->charpos),
6574 Qhelp_echo, glyph->object);
b7e80413 6575 if (!NILP (help))
be010514
GM
6576 {
6577 help_echo = help;
7cea38bc 6578 XSETWINDOW (help_echo_window, w);
be010514
GM
6579 help_echo_object = glyph->object;
6580 help_echo_pos = glyph->charpos;
6581 }
06a2c219
GM
6582
6583 /* Change the mouse pointer according to what is under X/Y. */
6584 map = Fget_text_property (make_number (glyph->charpos),
6585 Qlocal_map, glyph->object);
02067692 6586 if (KEYMAPP (map))
06a2c219 6587 cursor = f->output_data.x->nontext_cursor;
be010514
GM
6588 else
6589 {
6590 map = Fget_text_property (make_number (glyph->charpos),
6591 Qkeymap, glyph->object);
02067692 6592 if (KEYMAPP (map))
be010514
GM
6593 cursor = f->output_data.x->nontext_cursor;
6594 }
06a2c219
GM
6595 }
6596 }
6597
6598 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6599}
6600
6601
6602/* Take proper action when the mouse has moved to position X, Y on
6603 frame F as regards highlighting characters that have mouse-face
6604 properties. Also de-highlighting chars where the mouse was before.
27f338af 6605 X and Y can be negative or out of range. */
b8009dd1
RS
6606
6607static void
6608note_mouse_highlight (f, x, y)
06a2c219 6609 struct frame *f;
c32cdd9a 6610 int x, y;
b8009dd1 6611{
06a2c219
GM
6612 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6613 int portion;
b8009dd1
RS
6614 Lisp_Object window;
6615 struct window *w;
6616
06a2c219
GM
6617 /* When a menu is active, don't highlight because this looks odd. */
6618#ifdef USE_X_TOOLKIT
6619 if (popup_activated ())
6620 return;
6621#endif
6622
04fff9c0
GM
6623 if (disable_mouse_highlight
6624 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6625 return;
6626
06a2c219
GM
6627 dpyinfo->mouse_face_mouse_x = x;
6628 dpyinfo->mouse_face_mouse_y = y;
6629 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6630
06a2c219 6631 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6632 return;
6633
514e4681
RS
6634 if (gc_in_progress)
6635 {
06a2c219 6636 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6637 return;
6638 }
6639
b8009dd1 6640 /* Which window is that in? */
06a2c219 6641 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6642
6643 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6644 if (! EQ (window, dpyinfo->mouse_face_window))
6645 clear_mouse_face (dpyinfo);
6646
6647 /* Not on a window -> return. */
6648 if (!WINDOWP (window))
6649 return;
6650
6651 /* Convert to window-relative pixel coordinates. */
6652 w = XWINDOW (window);
6653 frame_to_window_pixel_xy (w, &x, &y);
6654
9ea173e8 6655 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6656 buffer. */
9ea173e8 6657 if (EQ (window, f->tool_bar_window))
06a2c219 6658 {
9ea173e8 6659 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6660 return;
6661 }
6662
6663 if (portion == 1 || portion == 3)
6664 {
6665 /* Mouse is on the mode or top line. */
6666 note_mode_line_highlight (w, x, portion == 1);
6667 return;
6668 }
e371a781
GM
6669 else if (portion == 2)
6670 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6671 f->output_data.x->horizontal_drag_cursor);
06a2c219
GM
6672 else
6673 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6674 f->output_data.x->text_cursor);
b8009dd1 6675
0cdd0c9f
RS
6676 /* Are we in a window whose display is up to date?
6677 And verify the buffer's text has not changed. */
06a2c219
GM
6678 if (/* Within text portion of the window. */
6679 portion == 0
0cdd0c9f 6680 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6681 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6682 && (XFASTINT (w->last_overlay_modified)
6683 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6684 {
06a2c219
GM
6685 int hpos, vpos, pos, i, area;
6686 struct glyph *glyph;
f9db2310 6687 Lisp_Object object;
b8009dd1 6688
06a2c219 6689 /* Find the glyph under X/Y. */
f9db2310 6690 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
06a2c219
GM
6691
6692 /* Clear mouse face if X/Y not over text. */
6693 if (glyph == NULL
6694 || area != TEXT_AREA
6695 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6696 {
06a2c219
GM
6697 clear_mouse_face (dpyinfo);
6698 return;
6699 }
6700
6701 pos = glyph->charpos;
f9db2310
GM
6702 object = glyph->object;
6703 if (!STRINGP (object) && !BUFFERP (object))
6704 return;
06a2c219 6705
06a2c219 6706 {
f9db2310
GM
6707 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6708 Lisp_Object *overlay_vec = NULL;
06a2c219
GM
6709 int len, noverlays;
6710 struct buffer *obuf;
6711 int obegv, ozv;
6712
6713 /* If we get an out-of-range value, return now; avoid an error. */
f9db2310 6714 if (BUFFERP (object) && pos > BUF_Z (XBUFFER (w->buffer)))
06a2c219
GM
6715 return;
6716
6717 /* Make the window's buffer temporarily current for
6718 overlays_at and compute_char_face. */
6719 obuf = current_buffer;
6720 current_buffer = XBUFFER (w->buffer);
6721 obegv = BEGV;
6722 ozv = ZV;
6723 BEGV = BEG;
6724 ZV = Z;
6725
6726 /* Is this char mouse-active or does it have help-echo? */
f9db2310
GM
6727 position = make_number (pos);
6728
6729 if (BUFFERP (object))
06a2c219 6730 {
f9db2310
GM
6731 /* Put all the overlays we want in a vector in overlay_vec.
6732 Store the length in len. If there are more than 10, make
6733 enough space for all, and try again. */
6734 len = 10;
06a2c219 6735 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
f9db2310
GM
6736 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6737 if (noverlays > len)
6738 {
6739 len = noverlays;
6740 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6741 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6742 }
f8349001 6743
f9db2310
GM
6744 /* Sort overlays into increasing priority order. */
6745 noverlays = sort_overlays (overlay_vec, noverlays, w);
6746 }
6747 else
6748 noverlays = 0;
06a2c219
GM
6749
6750 /* Check mouse-face highlighting. */
6751 if (! (EQ (window, dpyinfo->mouse_face_window)
6752 && vpos >= dpyinfo->mouse_face_beg_row
6753 && vpos <= dpyinfo->mouse_face_end_row
6754 && (vpos > dpyinfo->mouse_face_beg_row
6755 || hpos >= dpyinfo->mouse_face_beg_col)
6756 && (vpos < dpyinfo->mouse_face_end_row
6757 || hpos < dpyinfo->mouse_face_end_col
0a61c667
GM
6758 || dpyinfo->mouse_face_past_end))
6759 /* If there exists an overlay with mouse-face overlapping
6760 the one we are currently highlighting, we have to
6761 check if we enter the overlapping overlay, and then
6762 highlight only that. */
6763 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6764 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6765
06a2c219
GM
6766 {
6767 /* Clear the display of the old active region, if any. */
6768 clear_mouse_face (dpyinfo);
6769
f9db2310
GM
6770 /* Find the highest priority overlay that has a mouse-face
6771 property. */
06a2c219 6772 overlay = Qnil;
f9db2310 6773 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
06a2c219
GM
6774 {
6775 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6776 if (!NILP (mouse_face))
f9db2310 6777 overlay = overlay_vec[i];
06a2c219 6778 }
f9db2310
GM
6779 dpyinfo->mouse_face_overlay = overlay;
6780
06a2c219
GM
6781 /* If no overlay applies, get a text property. */
6782 if (NILP (overlay))
f9db2310 6783 mouse_face = Fget_text_property (position, Qmouse_face, object);
06a2c219
GM
6784
6785 /* Handle the overlay case. */
0a61c667 6786 if (!NILP (overlay))
06a2c219
GM
6787 {
6788 /* Find the range of text around this char that
6789 should be active. */
6790 Lisp_Object before, after;
6791 int ignore;
6792
6793 before = Foverlay_start (overlay);
6794 after = Foverlay_end (overlay);
6795 /* Record this as the current active region. */
6796 fast_find_position (w, XFASTINT (before),
6797 &dpyinfo->mouse_face_beg_col,
6798 &dpyinfo->mouse_face_beg_row,
6799 &dpyinfo->mouse_face_beg_x,
6800 &dpyinfo->mouse_face_beg_y);
6801 dpyinfo->mouse_face_past_end
6802 = !fast_find_position (w, XFASTINT (after),
6803 &dpyinfo->mouse_face_end_col,
6804 &dpyinfo->mouse_face_end_row,
6805 &dpyinfo->mouse_face_end_x,
6806 &dpyinfo->mouse_face_end_y);
6807 dpyinfo->mouse_face_window = window;
6808 dpyinfo->mouse_face_face_id
6809 = face_at_buffer_position (w, pos, 0, 0,
6810 &ignore, pos + 1, 1);
6811
6812 /* Display it as active. */
6813 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6814 }
6815 /* Handle the text property case. */
f9db2310 6816 else if (!NILP (mouse_face) && BUFFERP (object))
06a2c219
GM
6817 {
6818 /* Find the range of text around this char that
6819 should be active. */
6820 Lisp_Object before, after, beginning, end;
6821 int ignore;
6822
6823 beginning = Fmarker_position (w->start);
f9db2310
GM
6824 end = make_number (BUF_Z (XBUFFER (object))
6825 - XFASTINT (w->window_end_pos));
06a2c219
GM
6826 before
6827 = Fprevious_single_property_change (make_number (pos + 1),
6828 Qmouse_face,
f9db2310 6829 object, beginning);
06a2c219
GM
6830 after
6831 = Fnext_single_property_change (position, Qmouse_face,
f9db2310
GM
6832 object, end);
6833
06a2c219
GM
6834 /* Record this as the current active region. */
6835 fast_find_position (w, XFASTINT (before),
6836 &dpyinfo->mouse_face_beg_col,
6837 &dpyinfo->mouse_face_beg_row,
6838 &dpyinfo->mouse_face_beg_x,
6839 &dpyinfo->mouse_face_beg_y);
6840 dpyinfo->mouse_face_past_end
6841 = !fast_find_position (w, XFASTINT (after),
6842 &dpyinfo->mouse_face_end_col,
6843 &dpyinfo->mouse_face_end_row,
6844 &dpyinfo->mouse_face_end_x,
6845 &dpyinfo->mouse_face_end_y);
6846 dpyinfo->mouse_face_window = window;
f9db2310
GM
6847
6848 if (BUFFERP (object))
6849 dpyinfo->mouse_face_face_id
6850 = face_at_buffer_position (w, pos, 0, 0,
6851 &ignore, pos + 1, 1);
06a2c219
GM
6852
6853 /* Display it as active. */
6854 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6855 }
f9db2310
GM
6856 else if (!NILP (mouse_face) && STRINGP (object))
6857 {
6858 Lisp_Object b, e;
6859 int ignore;
6860
6861 b = Fprevious_single_property_change (make_number (pos + 1),
6862 Qmouse_face,
6863 object, Qnil);
6864 e = Fnext_single_property_change (position, Qmouse_face,
6865 object, Qnil);
6866 if (NILP (b))
6867 b = make_number (0);
6868 if (NILP (e))
eb49081e 6869 e = make_number (XSTRING (object)->size - 1);
f9db2310
GM
6870 fast_find_string_pos (w, XINT (b), object,
6871 &dpyinfo->mouse_face_beg_col,
6872 &dpyinfo->mouse_face_beg_row,
6873 &dpyinfo->mouse_face_beg_x,
6874 &dpyinfo->mouse_face_beg_y, 0);
6875 fast_find_string_pos (w, XINT (e), object,
6876 &dpyinfo->mouse_face_end_col,
6877 &dpyinfo->mouse_face_end_row,
6878 &dpyinfo->mouse_face_end_x,
6879 &dpyinfo->mouse_face_end_y, 1);
6880 dpyinfo->mouse_face_past_end = 0;
6881 dpyinfo->mouse_face_window = window;
6882 dpyinfo->mouse_face_face_id
6883 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6884 glyph->face_id, 1);
6885 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6886 }
06a2c219
GM
6887 }
6888
6889 /* Look for a `help-echo' property. */
6890 {
743934db 6891 Lisp_Object help, overlay;
06a2c219
GM
6892
6893 /* Check overlays first. */
f9b5db02 6894 help = overlay = Qnil;
f8349001 6895 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
743934db
GM
6896 {
6897 overlay = overlay_vec[i];
6898 help = Foverlay_get (overlay, Qhelp_echo);
6899 }
be010514
GM
6900
6901 if (!NILP (help))
6902 {
6903 help_echo = help;
7cea38bc 6904 help_echo_window = window;
743934db 6905 help_echo_object = overlay;
be010514
GM
6906 help_echo_pos = pos;
6907 }
6908 else
6909 {
7177d86b
GM
6910 Lisp_Object object = glyph->object;
6911 int charpos = glyph->charpos;
6912
be010514 6913 /* Try text properties. */
7177d86b
GM
6914 if (STRINGP (object)
6915 && charpos >= 0
6916 && charpos < XSTRING (object)->size)
6917 {
6918 help = Fget_text_property (make_number (charpos),
6919 Qhelp_echo, object);
6920 if (NILP (help))
6921 {
6922 /* If the string itself doesn't specify a help-echo,
6923 see if the buffer text ``under'' it does. */
6924 struct glyph_row *r
6925 = MATRIX_ROW (w->current_matrix, vpos);
6926 int start = MATRIX_ROW_START_CHARPOS (r);
6927 int pos = string_buffer_position (w, object, start);
6928 if (pos > 0)
6929 {
6930 help = Fget_text_property (make_number (pos),
6931 Qhelp_echo, w->buffer);
6932 if (!NILP (help))
6933 {
6934 charpos = pos;
6935 object = w->buffer;
6936 }
6937 }
6938 }
6939 }
6940 else if (BUFFERP (object)
6941 && charpos >= BEGV
6942 && charpos < ZV)
6943 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6944 object);
06a2c219 6945
be010514
GM
6946 if (!NILP (help))
6947 {
6948 help_echo = help;
7cea38bc 6949 help_echo_window = window;
7177d86b
GM
6950 help_echo_object = object;
6951 help_echo_pos = charpos;
be010514
GM
6952 }
6953 }
06a2c219
GM
6954 }
6955
6956 BEGV = obegv;
6957 ZV = ozv;
6958 current_buffer = obuf;
6959 }
6960 }
6961}
6962
6963static void
6964redo_mouse_highlight ()
6965{
6966 if (!NILP (last_mouse_motion_frame)
6967 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6968 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6969 last_mouse_motion_event.x,
6970 last_mouse_motion_event.y);
6971}
6972
6973
6974\f
6975/***********************************************************************
9ea173e8 6976 Tool-bars
06a2c219
GM
6977 ***********************************************************************/
6978
9ea173e8
GM
6979static int x_tool_bar_item P_ ((struct frame *, int, int,
6980 struct glyph **, int *, int *, int *));
06a2c219 6981
9ea173e8 6982/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6983 or -1. */
6984
9ea173e8 6985static int last_tool_bar_item;
06a2c219
GM
6986
6987
9ea173e8
GM
6988/* Get information about the tool-bar item at position X/Y on frame F.
6989 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6990 the current matrix of the tool-bar window of F, or NULL if not
6991 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8daf1204 6992 item in F->tool_bar_items. Value is
06a2c219 6993
9ea173e8 6994 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6995 0 if X/Y is on the same item that was highlighted before.
6996 1 otherwise. */
6997
6998static int
9ea173e8 6999x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
7000 struct frame *f;
7001 int x, y;
7002 struct glyph **glyph;
7003 int *hpos, *vpos, *prop_idx;
7004{
7005 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 7006 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
7007 int area;
7008
7009 /* Find the glyph under X/Y. */
f9db2310 7010 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
06a2c219
GM
7011 if (*glyph == NULL)
7012 return -1;
7013
9ea173e8 7014 /* Get the start of this tool-bar item's properties in
8daf1204 7015 f->tool_bar_items. */
9ea173e8 7016 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
7017 return -1;
7018
7019 /* Is mouse on the highlighted item? */
9ea173e8 7020 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
7021 && *vpos >= dpyinfo->mouse_face_beg_row
7022 && *vpos <= dpyinfo->mouse_face_end_row
7023 && (*vpos > dpyinfo->mouse_face_beg_row
7024 || *hpos >= dpyinfo->mouse_face_beg_col)
7025 && (*vpos < dpyinfo->mouse_face_end_row
7026 || *hpos < dpyinfo->mouse_face_end_col
7027 || dpyinfo->mouse_face_past_end))
7028 return 0;
7029
7030 return 1;
7031}
7032
7033
9ea173e8 7034/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
7035 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
7036 or ButtonRelase. */
7037
7038static void
9ea173e8 7039x_handle_tool_bar_click (f, button_event)
06a2c219
GM
7040 struct frame *f;
7041 XButtonEvent *button_event;
7042{
7043 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 7044 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
7045 int hpos, vpos, prop_idx;
7046 struct glyph *glyph;
7047 Lisp_Object enabled_p;
7048 int x = button_event->x;
7049 int y = button_event->y;
7050
9ea173e8 7051 /* If not on the highlighted tool-bar item, return. */
06a2c219 7052 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 7053 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
7054 return;
7055
7056 /* If item is disabled, do nothing. */
8daf1204 7057 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
7058 if (NILP (enabled_p))
7059 return;
7060
7061 if (button_event->type == ButtonPress)
7062 {
7063 /* Show item in pressed state. */
7064 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7065 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 7066 last_tool_bar_item = prop_idx;
06a2c219
GM
7067 }
7068 else
7069 {
7070 Lisp_Object key, frame;
7071 struct input_event event;
7072
7073 /* Show item in released state. */
7074 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7075 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7076
8daf1204 7077 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
06a2c219
GM
7078
7079 XSETFRAME (frame, f);
9ea173e8 7080 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7081 event.frame_or_window = frame;
7082 event.arg = frame;
06a2c219
GM
7083 kbd_buffer_store_event (&event);
7084
9ea173e8 7085 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
7086 event.frame_or_window = frame;
7087 event.arg = key;
06a2c219
GM
7088 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
7089 button_event->state);
7090 kbd_buffer_store_event (&event);
9ea173e8 7091 last_tool_bar_item = -1;
06a2c219
GM
7092 }
7093}
7094
7095
9ea173e8
GM
7096/* Possibly highlight a tool-bar item on frame F when mouse moves to
7097 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
7098 note_mouse_highlight. */
7099
7100static void
9ea173e8 7101note_tool_bar_highlight (f, x, y)
06a2c219
GM
7102 struct frame *f;
7103 int x, y;
7104{
9ea173e8 7105 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
7106 struct window *w = XWINDOW (window);
7107 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7108 int hpos, vpos;
7109 struct glyph *glyph;
7110 struct glyph_row *row;
5c187dee 7111 int i;
06a2c219
GM
7112 Lisp_Object enabled_p;
7113 int prop_idx;
140330de 7114 enum draw_glyphs_face draw;
5c187dee 7115 int mouse_down_p, rc;
06a2c219
GM
7116
7117 /* Function note_mouse_highlight is called with negative x(y
7118 values when mouse moves outside of the frame. */
7119 if (x <= 0 || y <= 0)
7120 {
7121 clear_mouse_face (dpyinfo);
7122 return;
7123 }
7124
9ea173e8 7125 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
7126 if (rc < 0)
7127 {
9ea173e8 7128 /* Not on tool-bar item. */
06a2c219
GM
7129 clear_mouse_face (dpyinfo);
7130 return;
7131 }
7132 else if (rc == 0)
06a2c219 7133 goto set_help_echo;
b8009dd1 7134
06a2c219
GM
7135 clear_mouse_face (dpyinfo);
7136
9ea173e8 7137 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
7138 mouse_down_p = (dpyinfo->grabbed
7139 && f == last_mouse_frame
7140 && FRAME_LIVE_P (f));
7141 if (mouse_down_p
9ea173e8 7142 && last_tool_bar_item != prop_idx)
06a2c219
GM
7143 return;
7144
7145 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7146 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7147
9ea173e8 7148 /* If tool-bar item is not enabled, don't highlight it. */
8daf1204 7149 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
06a2c219
GM
7150 if (!NILP (enabled_p))
7151 {
7152 /* Compute the x-position of the glyph. In front and past the
7153 image is a space. We include this is the highlighted area. */
7154 row = MATRIX_ROW (w->current_matrix, vpos);
7155 for (i = x = 0; i < hpos; ++i)
7156 x += row->glyphs[TEXT_AREA][i].pixel_width;
7157
7158 /* Record this as the current active region. */
7159 dpyinfo->mouse_face_beg_col = hpos;
7160 dpyinfo->mouse_face_beg_row = vpos;
7161 dpyinfo->mouse_face_beg_x = x;
7162 dpyinfo->mouse_face_beg_y = row->y;
7163 dpyinfo->mouse_face_past_end = 0;
7164
7165 dpyinfo->mouse_face_end_col = hpos + 1;
7166 dpyinfo->mouse_face_end_row = vpos;
7167 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7168 dpyinfo->mouse_face_end_y = row->y;
7169 dpyinfo->mouse_face_window = window;
9ea173e8 7170 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
7171
7172 /* Display it as active. */
7173 show_mouse_face (dpyinfo, draw);
7174 dpyinfo->mouse_face_image_state = draw;
b8009dd1 7175 }
06a2c219
GM
7176
7177 set_help_echo:
7178
9ea173e8 7179 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 7180 XTread_socket does the rest. */
7cea38bc 7181 help_echo_object = help_echo_window = Qnil;
be010514 7182 help_echo_pos = -1;
8daf1204 7183 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
b7e80413 7184 if (NILP (help_echo))
8daf1204 7185 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
b8009dd1 7186}
4d73d038 7187
06a2c219
GM
7188
7189\f
7190/* Find the glyph matrix position of buffer position POS in window W.
7191 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7192 current glyphs must be up to date. If POS is above window start
7193 return (0, 0, 0, 0). If POS is after end of W, return end of
7194 last line in W. */
b8009dd1
RS
7195
7196static int
06a2c219
GM
7197fast_find_position (w, pos, hpos, vpos, x, y)
7198 struct window *w;
b8009dd1 7199 int pos;
06a2c219 7200 int *hpos, *vpos, *x, *y;
b8009dd1 7201{
b8009dd1 7202 int i;
bf1c0ba1 7203 int lastcol;
06a2c219
GM
7204 int maybe_next_line_p = 0;
7205 int line_start_position;
7206 int yb = window_text_bottom_y (w);
03d1a189
GM
7207 struct glyph_row *row, *best_row;
7208 int row_vpos, best_row_vpos;
06a2c219
GM
7209 int current_x;
7210
03d1a189
GM
7211 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7212 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7213
06a2c219 7214 while (row->y < yb)
b8009dd1 7215 {
06a2c219
GM
7216 if (row->used[TEXT_AREA])
7217 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7218 else
7219 line_start_position = 0;
7220
7221 if (line_start_position > pos)
b8009dd1 7222 break;
77b68646
RS
7223 /* If the position sought is the end of the buffer,
7224 don't include the blank lines at the bottom of the window. */
06a2c219
GM
7225 else if (line_start_position == pos
7226 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 7227 {
06a2c219 7228 maybe_next_line_p = 1;
77b68646
RS
7229 break;
7230 }
06a2c219
GM
7231 else if (line_start_position > 0)
7232 {
7233 best_row = row;
7234 best_row_vpos = row_vpos;
7235 }
4b0bb6f3
GM
7236
7237 if (row->y + row->height >= yb)
7238 break;
06a2c219
GM
7239
7240 ++row;
7241 ++row_vpos;
b8009dd1 7242 }
06a2c219
GM
7243
7244 /* Find the right column within BEST_ROW. */
7245 lastcol = 0;
7246 current_x = best_row->x;
7247 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 7248 {
06a2c219
GM
7249 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7250 int charpos;
7251
7252 charpos = glyph->charpos;
7253 if (charpos == pos)
bf1c0ba1 7254 {
06a2c219
GM
7255 *hpos = i;
7256 *vpos = best_row_vpos;
7257 *x = current_x;
7258 *y = best_row->y;
bf1c0ba1
RS
7259 return 1;
7260 }
06a2c219 7261 else if (charpos > pos)
4d73d038 7262 break;
06a2c219
GM
7263 else if (charpos > 0)
7264 lastcol = i;
7265
7266 current_x += glyph->pixel_width;
bf1c0ba1 7267 }
b8009dd1 7268
77b68646
RS
7269 /* If we're looking for the end of the buffer,
7270 and we didn't find it in the line we scanned,
7271 use the start of the following line. */
06a2c219 7272 if (maybe_next_line_p)
77b68646 7273 {
06a2c219
GM
7274 ++best_row;
7275 ++best_row_vpos;
7276 lastcol = 0;
7277 current_x = best_row->x;
77b68646
RS
7278 }
7279
06a2c219
GM
7280 *vpos = best_row_vpos;
7281 *hpos = lastcol + 1;
7282 *x = current_x;
7283 *y = best_row->y;
b8009dd1
RS
7284 return 0;
7285}
7286
06a2c219 7287
f9db2310
GM
7288/* Find the position of the the glyph for position POS in OBJECT in
7289 window W's current matrix, and return in *X/*Y the pixel
7290 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7291
7292 RIGHT_P non-zero means return the position of the right edge of the
7293 glyph, RIGHT_P zero means return the left edge position.
7294
7295 If no glyph for POS exists in the matrix, return the position of
7296 the glyph with the next smaller position that is in the matrix, if
7297 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7298 exists in the matrix, return the position of the glyph with the
7299 next larger position in OBJECT.
7300
7301 Value is non-zero if a glyph was found. */
7302
7303static int
7304fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7305 struct window *w;
7306 int pos;
7307 Lisp_Object object;
7308 int *hpos, *vpos, *x, *y;
7309 int right_p;
7310{
7311 int yb = window_text_bottom_y (w);
7312 struct glyph_row *r;
7313 struct glyph *best_glyph = NULL;
7314 struct glyph_row *best_row = NULL;
7315 int best_x = 0;
7316
7317 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7318 r->enabled_p && r->y < yb;
7319 ++r)
7320 {
7321 struct glyph *g = r->glyphs[TEXT_AREA];
7322 struct glyph *e = g + r->used[TEXT_AREA];
7323 int gx;
7324
7325 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7326 if (EQ (g->object, object))
7327 {
7328 if (g->charpos == pos)
7329 {
7330 best_glyph = g;
7331 best_x = gx;
7332 best_row = r;
7333 goto found;
7334 }
7335 else if (best_glyph == NULL
7336 || ((abs (g->charpos - pos)
7337 < abs (best_glyph->charpos - pos))
7338 && (right_p
7339 ? g->charpos < pos
7340 : g->charpos > pos)))
7341 {
7342 best_glyph = g;
7343 best_x = gx;
7344 best_row = r;
7345 }
7346 }
7347 }
7348
7349 found:
7350
7351 if (best_glyph)
7352 {
7353 *x = best_x;
7354 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7355
7356 if (right_p)
7357 {
7358 *x += best_glyph->pixel_width;
7359 ++*hpos;
7360 }
7361
7362 *y = best_row->y;
7363 *vpos = best_row - w->current_matrix->rows;
7364 }
7365
7366 return best_glyph != NULL;
7367}
7368
7369
b8009dd1
RS
7370/* Display the active region described by mouse_face_*
7371 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7372
7373static void
06a2c219 7374show_mouse_face (dpyinfo, draw)
7a13e894 7375 struct x_display_info *dpyinfo;
06a2c219 7376 enum draw_glyphs_face draw;
b8009dd1 7377{
7a13e894 7378 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 7379 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 7380 int i;
06a2c219
GM
7381 int cursor_off_p = 0;
7382 struct cursor_pos saved_cursor;
7383
7384 saved_cursor = output_cursor;
7385
7386 /* If window is in the process of being destroyed, don't bother
7387 to do anything. */
7388 if (w->current_matrix == NULL)
7389 goto set_x_cursor;
7390
7391 /* Recognize when we are called to operate on rows that don't exist
7392 anymore. This can happen when a window is split. */
7393 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7394 goto set_x_cursor;
7395
7396 set_output_cursor (&w->phys_cursor);
7397
7398 /* Note that mouse_face_beg_row etc. are window relative. */
7399 for (i = dpyinfo->mouse_face_beg_row;
7400 i <= dpyinfo->mouse_face_end_row;
7401 i++)
7402 {
7403 int start_hpos, end_hpos, start_x;
7404 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7405
7406 /* Don't do anything if row doesn't have valid contents. */
7407 if (!row->enabled_p)
7408 continue;
7409
7410 /* For all but the first row, the highlight starts at column 0. */
7411 if (i == dpyinfo->mouse_face_beg_row)
7412 {
7413 start_hpos = dpyinfo->mouse_face_beg_col;
7414 start_x = dpyinfo->mouse_face_beg_x;
7415 }
7416 else
7417 {
7418 start_hpos = 0;
7419 start_x = 0;
7420 }
7421
7422 if (i == dpyinfo->mouse_face_end_row)
7423 end_hpos = dpyinfo->mouse_face_end_col;
7424 else
7425 end_hpos = row->used[TEXT_AREA];
7426
7427 /* If the cursor's in the text we are about to rewrite, turn the
7428 cursor off. */
7429 if (!w->pseudo_window_p
7430 && i == output_cursor.vpos
7431 && output_cursor.hpos >= start_hpos - 1
7432 && output_cursor.hpos <= end_hpos)
514e4681 7433 {
06a2c219
GM
7434 x_update_window_cursor (w, 0);
7435 cursor_off_p = 1;
514e4681 7436 }
b8009dd1 7437
06a2c219 7438 if (end_hpos > start_hpos)
64f26cf5 7439 {
140330de 7440 row->mouse_face_p = draw == DRAW_MOUSE_FACE || DRAW_IMAGE_RAISED;
64f26cf5
GM
7441 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7442 start_hpos, end_hpos, draw, NULL, NULL, 0);
7443 }
b8009dd1
RS
7444 }
7445
514e4681 7446 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7447 if (cursor_off_p)
7448 x_display_cursor (w, 1,
7449 output_cursor.hpos, output_cursor.vpos,
7450 output_cursor.x, output_cursor.y);
2729a2b5 7451
06a2c219 7452 output_cursor = saved_cursor;
fb3b7de5 7453
06a2c219
GM
7454 set_x_cursor:
7455
7456 /* Change the mouse cursor. */
7457 if (draw == DRAW_NORMAL_TEXT)
7458 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7459 f->output_data.x->text_cursor);
7460 else if (draw == DRAW_MOUSE_FACE)
334208b7 7461 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7462 f->output_data.x->cross_cursor);
27ead1d5 7463 else
334208b7 7464 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7465 f->output_data.x->nontext_cursor);
b8009dd1
RS
7466}
7467
7468/* Clear out the mouse-highlighted active region.
06a2c219 7469 Redraw it un-highlighted first. */
b8009dd1 7470
06a2c219 7471void
7a13e894
RS
7472clear_mouse_face (dpyinfo)
7473 struct x_display_info *dpyinfo;
b8009dd1 7474{
607d9f9f
GM
7475#if 0 /* This prevents redrawing tool bar items when changing from one
7476 to another while a tooltip is open, so don't do it. */
685f4368 7477 if (!NILP (tip_frame))
06a2c219 7478 return;
7948d50a 7479#endif
06a2c219 7480
7a13e894 7481 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7482 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7483
7a13e894
RS
7484 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7485 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7486 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7487}
e687d06e 7488
71b8321e
GM
7489
7490/* Clear any mouse-face on window W. This function is part of the
7491 redisplay interface, and is called from try_window_id and similar
7492 functions to ensure the mouse-highlight is off. */
7493
7494static void
7495x_clear_mouse_face (w)
7496 struct window *w;
7497{
7498 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7499 Lisp_Object window;
7500
2e636f9d 7501 BLOCK_INPUT;
71b8321e
GM
7502 XSETWINDOW (window, w);
7503 if (EQ (window, dpyinfo->mouse_face_window))
7504 clear_mouse_face (dpyinfo);
2e636f9d 7505 UNBLOCK_INPUT;
71b8321e
GM
7506}
7507
7508
e687d06e
RS
7509/* Just discard the mouse face information for frame F, if any.
7510 This is used when the size of F is changed. */
7511
dfcf069d 7512void
e687d06e
RS
7513cancel_mouse_face (f)
7514 FRAME_PTR f;
7515{
7516 Lisp_Object window;
7517 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7518
7519 window = dpyinfo->mouse_face_window;
7520 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7521 {
7522 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7523 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7524 dpyinfo->mouse_face_window = Qnil;
7525 }
7526}
b52b65bd 7527
b8009dd1 7528\f
b52b65bd
GM
7529static int glyph_rect P_ ((struct frame *f, int, int, XRectangle *));
7530
7531
7532/* Try to determine frame pixel position and size of the glyph under
7533 frame pixel coordinates X/Y on frame F . Return the position and
7534 size in *RECT. Value is non-zero if we could compute these
7535 values. */
7536
7537static int
7538glyph_rect (f, x, y, rect)
7539 struct frame *f;
7540 int x, y;
7541 XRectangle *rect;
7542{
7543 Lisp_Object window;
7544 int part, found = 0;
7545
7546 window = window_from_coordinates (f, x, y, &part, 0);
7547 if (!NILP (window))
7548 {
7549 struct window *w = XWINDOW (window);
7550 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7551 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7552 int area;
7553
7554 frame_to_window_pixel_xy (w, &x, &y);
7555
7556 for (; !found && r < end && r->enabled_p; ++r)
7557 if (r->y >= y)
7558 {
7559 struct glyph *g = r->glyphs[TEXT_AREA];
7560 struct glyph *end = g + r->used[TEXT_AREA];
7561 int gx;
7562
7563 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7564 if (gx >= x)
7565 {
7566 rect->width = g->pixel_width;
7567 rect->height = r->height;
7568 rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7569 rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7570 found = 1;
7571 }
7572 }
7573 }
7574
7575 return found;
7576}
7577
12ba150f 7578
90e65f07 7579/* Return the current position of the mouse.
b52b65bd 7580 *FP should be a frame which indicates which display to ask about.
90e65f07 7581
b52b65bd
GM
7582 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
7583 and *PART to the frame, window, and scroll bar part that the mouse
7584 is over. Set *X and *Y to the portion and whole of the mouse's
ab648270 7585 position on the scroll bar.
12ba150f 7586
b52b65bd
GM
7587 If the mouse movement started elsewhere, set *FP to the frame the
7588 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
12ba150f
JB
7589 the mouse is over.
7590
b52b65bd 7591 Set *TIME to the server time-stamp for the time at which the mouse
12ba150f
JB
7592 was at this position.
7593
a135645a
RS
7594 Don't store anything if we don't have a valid set of values to report.
7595
90e65f07 7596 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7597 movement. */
90e65f07
JB
7598
7599static void
1cf412ec 7600XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7601 FRAME_PTR *fp;
1cf412ec 7602 int insist;
12ba150f 7603 Lisp_Object *bar_window;
ab648270 7604 enum scroll_bar_part *part;
90e65f07 7605 Lisp_Object *x, *y;
e5d77022 7606 unsigned long *time;
90e65f07 7607{
a135645a
RS
7608 FRAME_PTR f1;
7609
90e65f07
JB
7610 BLOCK_INPUT;
7611
8bcee03e 7612 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7613 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7614 else
7615 {
12ba150f
JB
7616 Window root;
7617 int root_x, root_y;
90e65f07 7618
12ba150f
JB
7619 Window dummy_window;
7620 int dummy;
7621
39d8bb4d
KH
7622 Lisp_Object frame, tail;
7623
7624 /* Clear the mouse-moved flag for every frame on this display. */
7625 FOR_EACH_FRAME (tail, frame)
7626 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7627 XFRAME (frame)->mouse_moved = 0;
7628
ab648270 7629 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7630
7631 /* Figure out which root window we're on. */
334208b7
RS
7632 XQueryPointer (FRAME_X_DISPLAY (*fp),
7633 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7634
7635 /* The root window which contains the pointer. */
7636 &root,
7637
7638 /* Trash which we can't trust if the pointer is on
7639 a different screen. */
7640 &dummy_window,
7641
7642 /* The position on that root window. */
58769bee 7643 &root_x, &root_y,
12ba150f
JB
7644
7645 /* More trash we can't trust. */
7646 &dummy, &dummy,
7647
7648 /* Modifier keys and pointer buttons, about which
7649 we don't care. */
7650 (unsigned int *) &dummy);
7651
7652 /* Now we have a position on the root; find the innermost window
7653 containing the pointer. */
7654 {
7655 Window win, child;
7656 int win_x, win_y;
06a2c219 7657 int parent_x = 0, parent_y = 0;
e99db5a1 7658 int count;
12ba150f
JB
7659
7660 win = root;
69388238 7661
2d7fc7e8
RS
7662 /* XTranslateCoordinates can get errors if the window
7663 structure is changing at the same time this function
7664 is running. So at least we must not crash from them. */
7665
e99db5a1 7666 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7667
334208b7 7668 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7669 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7670 {
69388238
RS
7671 /* If mouse was grabbed on a frame, give coords for that frame
7672 even if the mouse is now outside it. */
334208b7 7673 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7674
12ba150f 7675 /* From-window, to-window. */
69388238 7676 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7677
7678 /* From-position, to-position. */
7679 root_x, root_y, &win_x, &win_y,
7680
7681 /* Child of win. */
7682 &child);
69388238
RS
7683 f1 = last_mouse_frame;
7684 }
7685 else
7686 {
7687 while (1)
7688 {
334208b7 7689 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7690
69388238
RS
7691 /* From-window, to-window. */
7692 root, win,
12ba150f 7693
69388238
RS
7694 /* From-position, to-position. */
7695 root_x, root_y, &win_x, &win_y,
7696
7697 /* Child of win. */
7698 &child);
7699
9af3143a 7700 if (child == None || child == win)
69388238
RS
7701 break;
7702
7703 win = child;
7704 parent_x = win_x;
7705 parent_y = win_y;
7706 }
12ba150f 7707
69388238
RS
7708 /* Now we know that:
7709 win is the innermost window containing the pointer
7710 (XTC says it has no child containing the pointer),
7711 win_x and win_y are the pointer's position in it
7712 (XTC did this the last time through), and
7713 parent_x and parent_y are the pointer's position in win's parent.
7714 (They are what win_x and win_y were when win was child.
7715 If win is the root window, it has no parent, and
7716 parent_{x,y} are invalid, but that's okay, because we'll
7717 never use them in that case.) */
7718
7719 /* Is win one of our frames? */
19126e11 7720 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
aad0f6ab
GM
7721
7722#ifdef USE_X_TOOLKIT
7723 /* If we end up with the menu bar window, say it's not
7724 on the frame. */
7725 if (f1 != NULL
7726 && f1->output_data.x->menubar_widget
7727 && win == XtWindow (f1->output_data.x->menubar_widget))
7728 f1 = NULL;
7729#endif /* USE_X_TOOLKIT */
69388238 7730 }
58769bee 7731
2d7fc7e8
RS
7732 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7733 f1 = 0;
7734
e99db5a1 7735 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7736
ab648270 7737 /* If not, is it one of our scroll bars? */
a135645a 7738 if (! f1)
12ba150f 7739 {
ab648270 7740 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7741
7742 if (bar)
7743 {
a135645a 7744 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7745 win_x = parent_x;
7746 win_y = parent_y;
7747 }
7748 }
90e65f07 7749
8bcee03e 7750 if (f1 == 0 && insist > 0)
b86bd3dd 7751 f1 = SELECTED_FRAME ();
1cf412ec 7752
a135645a 7753 if (f1)
12ba150f 7754 {
06a2c219
GM
7755 /* Ok, we found a frame. Store all the values.
7756 last_mouse_glyph is a rectangle used to reduce the
7757 generation of mouse events. To not miss any motion
7758 events, we must divide the frame into rectangles of the
7759 size of the smallest character that could be displayed
7760 on it, i.e. into the same rectangles that matrices on
7761 the frame are divided into. */
7762
b52b65bd
GM
7763 int width, height, gx, gy;
7764 XRectangle rect;
7765
7766 if (glyph_rect (f1, win_x, win_y, &rect))
7767 last_mouse_glyph = rect;
7768 else
7769 {
7770 width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7771 height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7772 gx = win_x;
7773 gy = win_y;
06a2c219 7774
b52b65bd
GM
7775 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7776 round down even for negative values. */
7777 if (gx < 0)
7778 gx -= width - 1;
4f00e84d 7779 if (gy < 0)
b52b65bd
GM
7780 gy -= height - 1;
7781 gx = (gx + width - 1) / width * width;
7782 gy = (gy + height - 1) / height * height;
7783
7784 last_mouse_glyph.width = width;
7785 last_mouse_glyph.height = height;
7786 last_mouse_glyph.x = gx;
7787 last_mouse_glyph.y = gy;
7788 }
12ba150f
JB
7789
7790 *bar_window = Qnil;
7791 *part = 0;
334208b7 7792 *fp = f1;
e0c1aef2
KH
7793 XSETINT (*x, win_x);
7794 XSETINT (*y, win_y);
12ba150f
JB
7795 *time = last_mouse_movement_time;
7796 }
7797 }
7798 }
90e65f07
JB
7799
7800 UNBLOCK_INPUT;
7801}
f451eb13 7802
06a2c219 7803
06a2c219 7804#ifdef USE_X_TOOLKIT
bffcfca9
GM
7805
7806/* Atimer callback function for TIMER. Called every 0.1s to process
7807 Xt timeouts, if needed. We must avoid calling XtAppPending as
7808 much as possible because that function does an implicit XFlush
7809 that slows us down. */
7810
7811static void
7812x_process_timeouts (timer)
7813 struct atimer *timer;
7814{
7815 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7816 {
7817 BLOCK_INPUT;
7818 while (XtAppPending (Xt_app_con) & XtIMTimer)
7819 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7820 UNBLOCK_INPUT;
7821 }
06a2c219
GM
7822}
7823
bffcfca9 7824#endif /* USE_X_TOOLKIT */
06a2c219
GM
7825
7826\f
7827/* Scroll bar support. */
7828
7829/* Given an X window ID, find the struct scroll_bar which manages it.
7830 This can be called in GC, so we have to make sure to strip off mark
7831 bits. */
bffcfca9 7832
06a2c219
GM
7833static struct scroll_bar *
7834x_window_to_scroll_bar (window_id)
7835 Window window_id;
7836{
7837 Lisp_Object tail;
7838
7839 for (tail = Vframe_list;
7840 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7841 tail = XCDR (tail))
06a2c219
GM
7842 {
7843 Lisp_Object frame, bar, condemned;
7844
8e713be6 7845 frame = XCAR (tail);
06a2c219
GM
7846 /* All elements of Vframe_list should be frames. */
7847 if (! GC_FRAMEP (frame))
7848 abort ();
7849
7850 /* Scan this frame's scroll bar list for a scroll bar with the
7851 right window ID. */
7852 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7853 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7854 /* This trick allows us to search both the ordinary and
7855 condemned scroll bar lists with one loop. */
7856 ! GC_NILP (bar) || (bar = condemned,
7857 condemned = Qnil,
7858 ! GC_NILP (bar));
7859 bar = XSCROLL_BAR (bar)->next)
7860 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7861 return XSCROLL_BAR (bar);
7862 }
7863
7864 return 0;
7865}
7866
7867
7868\f
7869/************************************************************************
7870 Toolkit scroll bars
7871 ************************************************************************/
7872
eccc05db 7873#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
7874
7875static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7876static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7877static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7878 struct scroll_bar *));
7879static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7880 int, int, int));
7881
7882
7883/* Id of action hook installed for scroll bars. */
7884
7885static XtActionHookId action_hook_id;
7886
7887/* Lisp window being scrolled. Set when starting to interact with
7888 a toolkit scroll bar, reset to nil when ending the interaction. */
7889
7890static Lisp_Object window_being_scrolled;
7891
7892/* Last scroll bar part sent in xm_scroll_callback. */
7893
7894static int last_scroll_bar_part;
7895
ec18280f
SM
7896/* Whether this is an Xaw with arrow-scrollbars. This should imply
7897 that movements of 1/20 of the screen size are mapped to up/down. */
7898
7899static Boolean xaw3d_arrow_scroll;
7900
7901/* Whether the drag scrolling maintains the mouse at the top of the
7902 thumb. If not, resizing the thumb needs to be done more carefully
7903 to avoid jerkyness. */
7904
7905static Boolean xaw3d_pick_top;
7906
06a2c219
GM
7907
7908/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7909 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7910 the user ends an interaction with the scroll bar, and generates
7911 a `end-scroll' scroll_bar_click' event if so. */
7912
7913static void
7914xt_action_hook (widget, client_data, action_name, event, params,
7915 num_params)
7916 Widget widget;
7917 XtPointer client_data;
7918 String action_name;
7919 XEvent *event;
7920 String *params;
7921 Cardinal *num_params;
7922{
7923 int scroll_bar_p;
7924 char *end_action;
7925
7926#ifdef USE_MOTIF
7927 scroll_bar_p = XmIsScrollBar (widget);
7928 end_action = "Release";
ec18280f 7929#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7930 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7931 end_action = "EndScroll";
ec18280f 7932#endif /* USE_MOTIF */
06a2c219 7933
06a2c219
GM
7934 if (scroll_bar_p
7935 && strcmp (action_name, end_action) == 0
7936 && WINDOWP (window_being_scrolled))
7937 {
7938 struct window *w;
7939
7940 x_send_scroll_bar_event (window_being_scrolled,
7941 scroll_bar_end_scroll, 0, 0);
7942 w = XWINDOW (window_being_scrolled);
7943 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7944 window_being_scrolled = Qnil;
7945 last_scroll_bar_part = -1;
bffcfca9
GM
7946
7947 /* Xt timeouts no longer needed. */
7948 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7949 }
7950}
7951
07b3d16e
GM
7952/* A vector of windows used for communication between
7953 x_send_scroll_bar_event and x_scroll_bar_to_input_event. */
7954
7955static struct window **scroll_bar_windows;
7956static int scroll_bar_windows_size;
7957
06a2c219
GM
7958
7959/* Send a client message with message type Xatom_Scrollbar for a
7960 scroll action to the frame of WINDOW. PART is a value identifying
7961 the part of the scroll bar that was clicked on. PORTION is the
7962 amount to scroll of a whole of WHOLE. */
7963
7964static void
7965x_send_scroll_bar_event (window, part, portion, whole)
7966 Lisp_Object window;
7967 int part, portion, whole;
7968{
7969 XEvent event;
7970 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
07b3d16e
GM
7971 struct window *w = XWINDOW (window);
7972 struct frame *f = XFRAME (w->frame);
7973 int i;
06a2c219 7974
07b3d16e
GM
7975 BLOCK_INPUT;
7976
06a2c219
GM
7977 /* Construct a ClientMessage event to send to the frame. */
7978 ev->type = ClientMessage;
7979 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7980 ev->display = FRAME_X_DISPLAY (f);
7981 ev->window = FRAME_X_WINDOW (f);
7982 ev->format = 32;
07b3d16e
GM
7983
7984 /* We can only transfer 32 bits in the XClientMessageEvent, which is
7985 not enough to store a pointer or Lisp_Object on a 64 bit system.
7986 So, store the window in scroll_bar_windows and pass the index
7987 into that array in the event. */
7988 for (i = 0; i < scroll_bar_windows_size; ++i)
7989 if (scroll_bar_windows[i] == NULL)
7990 break;
7991
7992 if (i == scroll_bar_windows_size)
7993 {
7994 int new_size = max (10, 2 * scroll_bar_windows_size);
7995 size_t nbytes = new_size * sizeof *scroll_bar_windows;
7996 size_t old_nbytes = scroll_bar_windows_size * sizeof *scroll_bar_windows;
7997
7998 scroll_bar_windows = (struct window **) xrealloc (scroll_bar_windows,
7999 nbytes);
8000 bzero (&scroll_bar_windows[i], nbytes - old_nbytes);
8001 scroll_bar_windows_size = new_size;
8002 }
8003
8004 scroll_bar_windows[i] = w;
8005 ev->data.l[0] = (long) i;
06a2c219
GM
8006 ev->data.l[1] = (long) part;
8007 ev->data.l[2] = (long) 0;
8008 ev->data.l[3] = (long) portion;
8009 ev->data.l[4] = (long) whole;
8010
bffcfca9
GM
8011 /* Make Xt timeouts work while the scroll bar is active. */
8012 toolkit_scroll_bar_interaction = 1;
8013
06a2c219
GM
8014 /* Setting the event mask to zero means that the message will
8015 be sent to the client that created the window, and if that
8016 window no longer exists, no event will be sent. */
06a2c219
GM
8017 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
8018 UNBLOCK_INPUT;
8019}
8020
8021
8022/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
8023 in *IEVENT. */
8024
8025static void
8026x_scroll_bar_to_input_event (event, ievent)
8027 XEvent *event;
8028 struct input_event *ievent;
8029{
8030 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
8031 Lisp_Object window;
8032 struct frame *f;
07b3d16e
GM
8033 struct window *w;
8034
8035 w = scroll_bar_windows[ev->data.l[0]];
8036 scroll_bar_windows[ev->data.l[0]] = NULL;
52e386c2 8037
07b3d16e
GM
8038 XSETWINDOW (window, w);
8039 f = XFRAME (w->frame);
06a2c219
GM
8040
8041 ievent->kind = scroll_bar_click;
8042 ievent->frame_or_window = window;
0f8aabe9 8043 ievent->arg = Qnil;
06a2c219
GM
8044 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
8045 ievent->part = ev->data.l[1];
8046 ievent->code = ev->data.l[2];
8047 ievent->x = make_number ((int) ev->data.l[3]);
8048 ievent->y = make_number ((int) ev->data.l[4]);
8049 ievent->modifiers = 0;
8050}
8051
8052
8053#ifdef USE_MOTIF
8054
8055/* Minimum and maximum values used for Motif scroll bars. */
8056
8057#define XM_SB_MIN 1
8058#define XM_SB_MAX 10000000
8059#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
8060
8061
8062/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
8063 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
8064 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
8065
8066static void
8067xm_scroll_callback (widget, client_data, call_data)
8068 Widget widget;
8069 XtPointer client_data, call_data;
8070{
8071 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8072 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
8073 double percent;
8074 int part = -1, whole = 0, portion = 0;
8075
8076 switch (cs->reason)
8077 {
8078 case XmCR_DECREMENT:
8079 bar->dragging = Qnil;
8080 part = scroll_bar_up_arrow;
8081 break;
8082
8083 case XmCR_INCREMENT:
8084 bar->dragging = Qnil;
8085 part = scroll_bar_down_arrow;
8086 break;
8087
8088 case XmCR_PAGE_DECREMENT:
8089 bar->dragging = Qnil;
8090 part = scroll_bar_above_handle;
8091 break;
8092
8093 case XmCR_PAGE_INCREMENT:
8094 bar->dragging = Qnil;
8095 part = scroll_bar_below_handle;
8096 break;
8097
8098 case XmCR_TO_TOP:
8099 bar->dragging = Qnil;
8100 part = scroll_bar_to_top;
8101 break;
8102
8103 case XmCR_TO_BOTTOM:
8104 bar->dragging = Qnil;
8105 part = scroll_bar_to_bottom;
8106 break;
8107
8108 case XmCR_DRAG:
8109 {
8110 int slider_size;
8111 int dragging_down_p = (INTEGERP (bar->dragging)
8112 && XINT (bar->dragging) <= cs->value);
8113
8114 /* Get the slider size. */
8115 BLOCK_INPUT;
8116 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
8117 UNBLOCK_INPUT;
8118
8119 /* At the max position of the scroll bar, do a line-wise
23442ae4
GM
8120 movement. Without doing anything, we would be called with
8121 the same cs->value again and again. If we want to make
8122 sure that we can reach the end of the buffer, we have to do
8123 something.
06a2c219
GM
8124
8125 Implementation note: setting bar->dragging always to
8126 cs->value gives a smoother movement at the max position.
8127 Setting it to nil when doing line-wise movement gives
8128 a better slider behavior. */
8129
8130 if (cs->value + slider_size == XM_SB_MAX
8131 || (dragging_down_p
8132 && last_scroll_bar_part == scroll_bar_down_arrow))
8133 {
8134 part = scroll_bar_down_arrow;
8135 bar->dragging = Qnil;
8136 }
8137 else
8138 {
8139 whole = XM_SB_RANGE;
8140 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
8141 part = scroll_bar_handle;
8142 bar->dragging = make_number (cs->value);
8143 }
8144 }
8145 break;
8146
8147 case XmCR_VALUE_CHANGED:
8148 break;
8149 };
8150
8151 if (part >= 0)
8152 {
8153 window_being_scrolled = bar->window;
8154 last_scroll_bar_part = part;
8155 x_send_scroll_bar_event (bar->window, part, portion, whole);
8156 }
8157}
8158
8159
ec18280f 8160#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
8161
8162
ec18280f 8163/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
8164 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
8165 scroll bar struct. CALL_DATA is a pointer to a float saying where
8166 the thumb is. */
8167
8168static void
ec18280f 8169xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
8170 Widget widget;
8171 XtPointer client_data, call_data;
8172{
8173 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8174 float top = *(float *) call_data;
8175 float shown;
ec18280f
SM
8176 int whole, portion, height;
8177 int part;
06a2c219
GM
8178
8179 /* Get the size of the thumb, a value between 0 and 1. */
8180 BLOCK_INPUT;
ec18280f 8181 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
8182 UNBLOCK_INPUT;
8183
8184 whole = 10000000;
8185 portion = shown < 1 ? top * whole : 0;
06a2c219 8186
ec18280f
SM
8187 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
8188 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
8189 the bottom, so we force the scrolling whenever we see that we're
8190 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
8191 we try to ensure that we always stay two pixels away from the
8192 bottom). */
06a2c219
GM
8193 part = scroll_bar_down_arrow;
8194 else
8195 part = scroll_bar_handle;
8196
8197 window_being_scrolled = bar->window;
8198 bar->dragging = make_number (portion);
8199 last_scroll_bar_part = part;
8200 x_send_scroll_bar_event (bar->window, part, portion, whole);
8201}
8202
8203
ec18280f
SM
8204/* Xaw scroll bar callback. Invoked for incremental scrolling.,
8205 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
8206 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
8207 the scroll bar. CALL_DATA is an integer specifying the action that
8208 has taken place. It's magnitude is in the range 0..height of the
8209 scroll bar. Negative values mean scroll towards buffer start.
8210 Values < height of scroll bar mean line-wise movement. */
8211
8212static void
ec18280f 8213xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
8214 Widget widget;
8215 XtPointer client_data, call_data;
8216{
8217 struct scroll_bar *bar = (struct scroll_bar *) client_data;
8218 int position = (int) call_data;
8219 Dimension height;
8220 int part;
8221
8222 /* Get the height of the scroll bar. */
8223 BLOCK_INPUT;
8224 XtVaGetValues (widget, XtNheight, &height, NULL);
8225 UNBLOCK_INPUT;
8226
ec18280f
SM
8227 if (abs (position) >= height)
8228 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
8229
8230 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
8231 it maps line-movement to call_data = max(5, height/20). */
8232 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
8233 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 8234 else
ec18280f 8235 part = scroll_bar_move_ratio;
06a2c219
GM
8236
8237 window_being_scrolled = bar->window;
8238 bar->dragging = Qnil;
8239 last_scroll_bar_part = part;
ec18280f 8240 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
8241}
8242
8243
8244#endif /* not USE_MOTIF */
8245
8246
8247/* Create the widget for scroll bar BAR on frame F. Record the widget
8248 and X window of the scroll bar in BAR. */
8249
8250static void
8251x_create_toolkit_scroll_bar (f, bar)
8252 struct frame *f;
8253 struct scroll_bar *bar;
8254{
8255 Window xwindow;
8256 Widget widget;
8257 Arg av[20];
8258 int ac = 0;
8259 char *scroll_bar_name = "verticalScrollBar";
8260 unsigned long pixel;
8261
8262 BLOCK_INPUT;
8263
8264#ifdef USE_MOTIF
06a2c219
GM
8265 /* Set resources. Create the widget. */
8266 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8267 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
8268 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
8269 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
8270 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
8271 XtSetArg (av[ac], XmNincrement, 1); ++ac;
8272 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
8273
8274 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8275 if (pixel != -1)
8276 {
8277 XtSetArg (av[ac], XmNforeground, pixel);
8278 ++ac;
8279 }
8280
8281 pixel = f->output_data.x->scroll_bar_background_pixel;
8282 if (pixel != -1)
8283 {
8284 XtSetArg (av[ac], XmNbackground, pixel);
8285 ++ac;
8286 }
8287
8288 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
8289 scroll_bar_name, av, ac);
8290
8291 /* Add one callback for everything that can happen. */
8292 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
8293 (XtPointer) bar);
8294 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
8295 (XtPointer) bar);
8296 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
8297 (XtPointer) bar);
8298 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
8299 (XtPointer) bar);
8300 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
8301 (XtPointer) bar);
8302 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
8303 (XtPointer) bar);
8304 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
8305 (XtPointer) bar);
8306
8307 /* Realize the widget. Only after that is the X window created. */
8308 XtRealizeWidget (widget);
8309
8310 /* Set the cursor to an arrow. I didn't find a resource to do that.
8311 And I'm wondering why it hasn't an arrow cursor by default. */
8312 XDefineCursor (XtDisplay (widget), XtWindow (widget),
8313 f->output_data.x->nontext_cursor);
8314
ec18280f 8315#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
8316
8317 /* Set resources. Create the widget. The background of the
8318 Xaw3d scroll bar widget is a little bit light for my taste.
8319 We don't alter it here to let users change it according
8320 to their taste with `emacs*verticalScrollBar.background: xxx'. */
8321 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
8322 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
8323 /* For smoother scrolling with Xaw3d -sm */
8324 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
8325 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
8326
8327 pixel = f->output_data.x->scroll_bar_foreground_pixel;
8328 if (pixel != -1)
8329 {
8330 XtSetArg (av[ac], XtNforeground, pixel);
8331 ++ac;
8332 }
8333
8334 pixel = f->output_data.x->scroll_bar_background_pixel;
8335 if (pixel != -1)
8336 {
8337 XtSetArg (av[ac], XtNbackground, pixel);
8338 ++ac;
8339 }
8340
8341 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
8342 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
8343
8344 {
8345 char *initial = "";
8346 char *val = initial;
8347 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
8348 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
8349 if (val == initial)
8350 { /* ARROW_SCROLL */
8351 xaw3d_arrow_scroll = True;
8352 /* Isn't that just a personal preference ? -sm */
8353 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
8354 }
8355 }
06a2c219
GM
8356
8357 /* Define callbacks. */
ec18280f
SM
8358 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
8359 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
8360 (XtPointer) bar);
8361
8362 /* Realize the widget. Only after that is the X window created. */
8363 XtRealizeWidget (widget);
8364
ec18280f 8365#endif /* !USE_MOTIF */
06a2c219
GM
8366
8367 /* Install an action hook that let's us detect when the user
8368 finishes interacting with a scroll bar. */
8369 if (action_hook_id == 0)
8370 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
8371
8372 /* Remember X window and widget in the scroll bar vector. */
8373 SET_SCROLL_BAR_X_WIDGET (bar, widget);
8374 xwindow = XtWindow (widget);
8375 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
8376
8377 UNBLOCK_INPUT;
8378}
8379
8380
8381/* Set the thumb size and position of scroll bar BAR. We are currently
8382 displaying PORTION out of a whole WHOLE, and our position POSITION. */
8383
8384static void
8385x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
8386 struct scroll_bar *bar;
8387 int portion, position, whole;
f451eb13 8388{
e83dc917
GM
8389 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8390 Widget widget = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
06a2c219 8391 float top, shown;
f451eb13 8392
06a2c219
GM
8393 if (whole == 0)
8394 top = 0, shown = 1;
8395 else
f451eb13 8396 {
06a2c219
GM
8397 top = (float) position / whole;
8398 shown = (float) portion / whole;
8399 }
f451eb13 8400
06a2c219 8401 BLOCK_INPUT;
f451eb13 8402
06a2c219
GM
8403#ifdef USE_MOTIF
8404 {
8405 int size, value;
06a2c219
GM
8406 XmScrollBarWidget sb;
8407
ec18280f 8408 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
8409 is the scroll bar's maximum and MIN is the scroll bar's minimum
8410 value. */
8411 size = shown * XM_SB_RANGE;
8412 size = min (size, XM_SB_RANGE);
8413 size = max (size, 1);
8414
8415 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8416 value = top * XM_SB_RANGE;
8417 value = min (value, XM_SB_MAX - size);
8418 value = max (value, XM_SB_MIN);
8419
06a2c219
GM
8420 if (NILP (bar->dragging))
8421 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8422 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8423 /* This has the negative side effect that the slider value is
ec18280f 8424 not what it would be if we scrolled here using line-wise or
06a2c219
GM
8425 page-wise movement. */
8426 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8427 else
8428 {
8429 /* If currently dragging, only update the slider size.
8430 This reduces flicker effects. */
8431 int old_value, old_size, increment, page_increment;
8432
8433 XmScrollBarGetValues (widget, &old_value, &old_size,
8434 &increment, &page_increment);
8435 XmScrollBarSetValues (widget, old_value,
8436 min (size, XM_SB_RANGE - old_value),
8437 0, 0, False);
8438 }
06a2c219 8439 }
ec18280f 8440#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 8441 {
ec18280f
SM
8442 float old_top, old_shown;
8443 Dimension height;
8444 XtVaGetValues (widget,
8445 XtNtopOfThumb, &old_top,
8446 XtNshown, &old_shown,
8447 XtNheight, &height,
8448 NULL);
8449
8450 /* Massage the top+shown values. */
8451 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8452 top = max (0, min (1, top));
8453 else
8454 top = old_top;
8455 /* Keep two pixels available for moving the thumb down. */
8456 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8457
8458 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8459 check that your system's configuration file contains a define
8460 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8461 if (top != old_top || shown != old_shown)
eb393530 8462 {
ec18280f 8463 if (NILP (bar->dragging))
eb393530 8464 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8465 else
8466 {
ec18280f
SM
8467#ifdef HAVE_XAW3D
8468 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8469 int scroll_mode = 0;
ec18280f
SM
8470
8471 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8472 if (xaw3d_arrow_scroll)
8473 {
8474 /* Xaw3d stupidly ignores resize requests while dragging
8475 so we have to make it believe it's not in dragging mode. */
8476 scroll_mode = sb->scrollbar.scroll_mode;
8477 if (scroll_mode == 2)
8478 sb->scrollbar.scroll_mode = 0;
8479 }
8480#endif
8481 /* Try to make the scrolling a tad smoother. */
8482 if (!xaw3d_pick_top)
8483 shown = min (shown, old_shown);
8484
8485 XawScrollbarSetThumb (widget, top, shown);
8486
8487#ifdef HAVE_XAW3D
8488 if (xaw3d_arrow_scroll && scroll_mode == 2)
8489 sb->scrollbar.scroll_mode = scroll_mode;
8490#endif
06a2c219 8491 }
06a2c219
GM
8492 }
8493 }
ec18280f 8494#endif /* !USE_MOTIF */
06a2c219
GM
8495
8496 UNBLOCK_INPUT;
f451eb13
JB
8497}
8498
06a2c219
GM
8499#endif /* USE_TOOLKIT_SCROLL_BARS */
8500
8501
8502\f
8503/************************************************************************
8504 Scroll bars, general
8505 ************************************************************************/
8506
8507/* Create a scroll bar and return the scroll bar vector for it. W is
8508 the Emacs window on which to create the scroll bar. TOP, LEFT,
8509 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8510 scroll bar. */
8511
ab648270 8512static struct scroll_bar *
06a2c219
GM
8513x_scroll_bar_create (w, top, left, width, height)
8514 struct window *w;
f451eb13
JB
8515 int top, left, width, height;
8516{
06a2c219 8517 struct frame *f = XFRAME (w->frame);
334208b7
RS
8518 struct scroll_bar *bar
8519 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8520
8521 BLOCK_INPUT;
8522
eccc05db 8523#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8524 x_create_toolkit_scroll_bar (f, bar);
8525#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8526 {
8527 XSetWindowAttributes a;
8528 unsigned long mask;
5c187dee 8529 Window window;
06a2c219
GM
8530
8531 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8532 if (a.background_pixel == -1)
8533 a.background_pixel = f->output_data.x->background_pixel;
8534
12ba150f 8535 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8536 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8537 | ExposureMask);
7a13e894 8538 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8539
dbc4e1c1 8540 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8541
06a2c219
GM
8542 /* Clear the area of W that will serve as a scroll bar. This is
8543 for the case that a window has been split horizontally. In
8544 this case, no clear_frame is generated to reduce flickering. */
c5e6e06b
GM
8545 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8546 left, top, width,
8547 window_box_height (w), False);
06a2c219
GM
8548
8549 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8550 /* Position and size of scroll bar. */
8551 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8552 top,
8553 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8554 height,
8555 /* Border width, depth, class, and visual. */
8556 0,
8557 CopyFromParent,
8558 CopyFromParent,
8559 CopyFromParent,
8560 /* Attributes. */
8561 mask, &a);
8562 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8563 }
06a2c219 8564#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8565
06a2c219 8566 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8567 XSETINT (bar->top, top);
8568 XSETINT (bar->left, left);
8569 XSETINT (bar->width, width);
8570 XSETINT (bar->height, height);
8571 XSETINT (bar->start, 0);
8572 XSETINT (bar->end, 0);
12ba150f 8573 bar->dragging = Qnil;
f451eb13
JB
8574
8575 /* Add bar to its frame's list of scroll bars. */
334208b7 8576 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8577 bar->prev = Qnil;
334208b7 8578 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8579 if (!NILP (bar->next))
e0c1aef2 8580 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8581
06a2c219 8582 /* Map the window/widget. */
eccc05db 8583#ifdef USE_TOOLKIT_SCROLL_BARS
f964b4d7
GM
8584 {
8585 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
8586 XtConfigureWidget (scroll_bar,
8587 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8588 top,
8589 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8590 max (height, 1), 0);
8591 XtMapWidget (scroll_bar);
8592 }
06a2c219 8593#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8594 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8595#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8596
8597 UNBLOCK_INPUT;
12ba150f 8598 return bar;
f451eb13
JB
8599}
8600
06a2c219 8601
12ba150f 8602/* Draw BAR's handle in the proper position.
06a2c219 8603
12ba150f
JB
8604 If the handle is already drawn from START to END, don't bother
8605 redrawing it, unless REBUILD is non-zero; in that case, always
8606 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8607 events.)
12ba150f
JB
8608
8609 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8610 fit inside its rectangle, but if the user is dragging the scroll
8611 bar handle, we want to let them drag it down all the way, so that
8612 the bar's top is as far down as it goes; otherwise, there's no way
8613 to move to the very end of the buffer. */
8614
5c187dee
GM
8615#ifndef USE_TOOLKIT_SCROLL_BARS
8616
f451eb13 8617static void
ab648270
JB
8618x_scroll_bar_set_handle (bar, start, end, rebuild)
8619 struct scroll_bar *bar;
f451eb13 8620 int start, end;
12ba150f 8621 int rebuild;
f451eb13 8622{
12ba150f 8623 int dragging = ! NILP (bar->dragging);
ab648270 8624 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8625 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8626 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8627
8628 /* If the display is already accurate, do nothing. */
8629 if (! rebuild
8630 && start == XINT (bar->start)
8631 && end == XINT (bar->end))
8632 return;
8633
f451eb13
JB
8634 BLOCK_INPUT;
8635
8636 {
d9cdbb3d
RS
8637 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8638 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8639 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8640
8641 /* Make sure the values are reasonable, and try to preserve
8642 the distance between start and end. */
12ba150f
JB
8643 {
8644 int length = end - start;
8645
8646 if (start < 0)
8647 start = 0;
8648 else if (start > top_range)
8649 start = top_range;
8650 end = start + length;
8651
8652 if (end < start)
8653 end = start;
8654 else if (end > top_range && ! dragging)
8655 end = top_range;
8656 }
f451eb13 8657
ab648270 8658 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8659 XSETINT (bar->start, start);
8660 XSETINT (bar->end, end);
f451eb13 8661
12ba150f
JB
8662 /* Clip the end position, just for display. */
8663 if (end > top_range)
8664 end = top_range;
f451eb13 8665
ab648270 8666 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8667 below top positions, to make sure the handle is always at least
8668 that many pixels tall. */
ab648270 8669 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8670
12ba150f
JB
8671 /* Draw the empty space above the handle. Note that we can't clear
8672 zero-height areas; that means "clear to end of window." */
8673 if (0 < start)
c5e6e06b
GM
8674 x_clear_area (FRAME_X_DISPLAY (f), w,
8675 /* x, y, width, height, and exposures. */
8676 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8677 VERTICAL_SCROLL_BAR_TOP_BORDER,
8678 inside_width, start,
8679 False);
f451eb13 8680
06a2c219
GM
8681 /* Change to proper foreground color if one is specified. */
8682 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8683 XSetForeground (FRAME_X_DISPLAY (f), gc,
8684 f->output_data.x->scroll_bar_foreground_pixel);
8685
12ba150f 8686 /* Draw the handle itself. */
334208b7 8687 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
12ba150f 8688 /* x, y, width, height */
ab648270
JB
8689 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8690 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8691 inside_width, end - start);
f451eb13 8692
06a2c219
GM
8693 /* Restore the foreground color of the GC if we changed it above. */
8694 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8695 XSetForeground (FRAME_X_DISPLAY (f), gc,
8696 f->output_data.x->foreground_pixel);
f451eb13 8697
12ba150f
JB
8698 /* Draw the empty space below the handle. Note that we can't
8699 clear zero-height areas; that means "clear to end of window." */
8700 if (end < inside_height)
c5e6e06b
GM
8701 x_clear_area (FRAME_X_DISPLAY (f), w,
8702 /* x, y, width, height, and exposures. */
8703 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8704 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
8705 inside_width, inside_height - end,
8706 False);
f451eb13 8707
f451eb13
JB
8708 }
8709
f451eb13
JB
8710 UNBLOCK_INPUT;
8711}
8712
5c187dee 8713#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8714
06a2c219
GM
8715/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8716 nil. */
58769bee 8717
12ba150f 8718static void
ab648270
JB
8719x_scroll_bar_remove (bar)
8720 struct scroll_bar *bar;
12ba150f 8721{
e83dc917 8722 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
8723 BLOCK_INPUT;
8724
eccc05db 8725#ifdef USE_TOOLKIT_SCROLL_BARS
e83dc917
GM
8726 XtDestroyWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar));
8727#else
8728 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8729#endif
06a2c219 8730
ab648270
JB
8731 /* Disassociate this scroll bar from its window. */
8732 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8733
8734 UNBLOCK_INPUT;
8735}
8736
06a2c219 8737
12ba150f
JB
8738/* Set the handle of the vertical scroll bar for WINDOW to indicate
8739 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8740 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8741 create one. */
06a2c219 8742
12ba150f 8743static void
06a2c219
GM
8744XTset_vertical_scroll_bar (w, portion, whole, position)
8745 struct window *w;
f451eb13
JB
8746 int portion, whole, position;
8747{
06a2c219 8748 struct frame *f = XFRAME (w->frame);
ab648270 8749 struct scroll_bar *bar;
3c6ede7b 8750 int top, height, left, sb_left, width, sb_width;
06a2c219 8751 int window_x, window_y, window_width, window_height;
06a2c219 8752
3c6ede7b 8753 /* Get window dimensions. */
06a2c219 8754 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8755 top = window_y;
8756 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8757 height = window_height;
06a2c219 8758
3c6ede7b 8759 /* Compute the left edge of the scroll bar area. */
06a2c219 8760 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8761 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8762 else
8763 left = XFASTINT (w->left);
8764 left *= CANON_X_UNIT (f);
8765 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8766
8767 /* Compute the width of the scroll bar which might be less than
8768 the width of the area reserved for the scroll bar. */
8769 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8770 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8771 else
3c6ede7b 8772 sb_width = width;
12ba150f 8773
3c6ede7b
GM
8774 /* Compute the left edge of the scroll bar. */
8775#ifdef USE_TOOLKIT_SCROLL_BARS
8776 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8777 sb_left = left + width - sb_width - (width - sb_width) / 2;
8778 else
8779 sb_left = left + (width - sb_width) / 2;
8780#else
8781 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8782 sb_left = left + width - sb_width;
8783 else
8784 sb_left = left;
8785#endif
8786
ab648270 8787 /* Does the scroll bar exist yet? */
06a2c219 8788 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8789 {
80c32bcc 8790 BLOCK_INPUT;
f964b4d7
GM
8791 if (width && height)
8792 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8793 left, top, width, height, False);
80c32bcc 8794 UNBLOCK_INPUT;
3c6ede7b
GM
8795 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8796 }
f451eb13 8797 else
12ba150f
JB
8798 {
8799 /* It may just need to be moved and resized. */
06a2c219
GM
8800 unsigned int mask = 0;
8801
8802 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8803
8804 BLOCK_INPUT;
8805
3c6ede7b 8806 if (sb_left != XINT (bar->left))
06a2c219 8807 mask |= CWX;
3c6ede7b 8808 if (top != XINT (bar->top))
06a2c219 8809 mask |= CWY;
3c6ede7b 8810 if (sb_width != XINT (bar->width))
06a2c219 8811 mask |= CWWidth;
3c6ede7b 8812 if (height != XINT (bar->height))
06a2c219
GM
8813 mask |= CWHeight;
8814
8815#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8816
8817 /* Since toolkit scroll bars are smaller than the space reserved
8818 for them on the frame, we have to clear "under" them. */
f964b4d7
GM
8819 if (width && height)
8820 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8821 left, top, width, height, False);
06a2c219
GM
8822
8823 /* Move/size the scroll bar widget. */
8824 if (mask)
e83dc917 8825 XtConfigureWidget (SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar),
3c6ede7b
GM
8826 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8827 top,
8828 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
f964b4d7 8829 max (height, 1), 0);
06a2c219
GM
8830
8831#else /* not USE_TOOLKIT_SCROLL_BARS */
8832
357e7376
GM
8833 /* Clear areas not covered by the scroll bar because of
8834 VERTICAL_SCROLL_BAR_WIDTH_TRIM. */
e1f6572f
RS
8835 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8836 {
c5e6e06b
GM
8837 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8838 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8839 height, False);
8840 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8841 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8842 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8843 height, False);
e1f6572f 8844 }
357e7376
GM
8845
8846 /* Clear areas not covered by the scroll bar because it's not as
8847 wide as the area reserved for it . This makes sure a
8848 previous mode line display is cleared after C-x 2 C-x 1, for
8849 example. */
8850 {
8851 int area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8852 int rest = area_width - sb_width;
8853 if (rest > 0)
8854 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8855 left + area_width - rest, 0,
8856 rest, max (height, 1), False);
8857 }
06a2c219
GM
8858
8859 /* Move/size the scroll bar window. */
8860 if (mask)
8861 {
8862 XWindowChanges wc;
8863
3c6ede7b
GM
8864 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8865 wc.y = top;
8866 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8867 wc.height = height;
06a2c219
GM
8868 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8869 mask, &wc);
8870 }
8871
8872#endif /* not USE_TOOLKIT_SCROLL_BARS */
8873
8874 /* Remember new settings. */
3c6ede7b
GM
8875 XSETINT (bar->left, sb_left);
8876 XSETINT (bar->top, top);
8877 XSETINT (bar->width, sb_width);
8878 XSETINT (bar->height, height);
06a2c219
GM
8879
8880 UNBLOCK_INPUT;
12ba150f 8881 }
f451eb13 8882
eccc05db 8883#ifdef USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
8884 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8885#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8886 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8887 dragged. */
12ba150f 8888 if (NILP (bar->dragging))
f451eb13 8889 {
92857db0 8890 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8891
12ba150f 8892 if (whole == 0)
ab648270 8893 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8894 else
8895 {
43f868f5
JB
8896 int start = ((double) position * top_range) / whole;
8897 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8898 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8899 }
f451eb13 8900 }
06a2c219 8901#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8902
06a2c219 8903 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8904}
8905
12ba150f 8906
f451eb13 8907/* The following three hooks are used when we're doing a thorough
ab648270 8908 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8909 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8910 away is a real pain - "Can you say set-window-configuration, boys
8911 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8912 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8913 from the fiery pit when we actually redisplay its window. */
f451eb13 8914
ab648270
JB
8915/* Arrange for all scroll bars on FRAME to be removed at the next call
8916 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8917 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8918
58769bee 8919static void
ab648270 8920XTcondemn_scroll_bars (frame)
f451eb13
JB
8921 FRAME_PTR frame;
8922{
f9e24cb9
RS
8923 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8924 while (! NILP (FRAME_SCROLL_BARS (frame)))
8925 {
8926 Lisp_Object bar;
8927 bar = FRAME_SCROLL_BARS (frame);
8928 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8929 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8930 XSCROLL_BAR (bar)->prev = Qnil;
8931 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8932 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8933 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8934 }
f451eb13
JB
8935}
8936
fa2dfc30 8937
06a2c219 8938/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8939 Note that WINDOW isn't necessarily condemned at all. */
fa2dfc30 8940
f451eb13 8941static void
ab648270 8942XTredeem_scroll_bar (window)
12ba150f 8943 struct window *window;
f451eb13 8944{
ab648270 8945 struct scroll_bar *bar;
fa2dfc30 8946 struct frame *f;
12ba150f 8947
ab648270
JB
8948 /* We can't redeem this window's scroll bar if it doesn't have one. */
8949 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8950 abort ();
8951
ab648270 8952 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8953
8954 /* Unlink it from the condemned list. */
fa2dfc30
GM
8955 f = XFRAME (WINDOW_FRAME (window));
8956 if (NILP (bar->prev))
8957 {
8958 /* If the prev pointer is nil, it must be the first in one of
8959 the lists. */
8960 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8961 /* It's not condemned. Everything's fine. */
8962 return;
8963 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8964 window->vertical_scroll_bar))
8965 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8966 else
8967 /* If its prev pointer is nil, it must be at the front of
8968 one or the other! */
8969 abort ();
8970 }
8971 else
8972 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f 8973
fa2dfc30
GM
8974 if (! NILP (bar->next))
8975 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8976
fa2dfc30
GM
8977 bar->next = FRAME_SCROLL_BARS (f);
8978 bar->prev = Qnil;
8979 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8980 if (! NILP (bar->next))
8981 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13
JB
8982}
8983
ab648270
JB
8984/* Remove all scroll bars on FRAME that haven't been saved since the
8985 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8986
f451eb13 8987static void
ab648270 8988XTjudge_scroll_bars (f)
12ba150f 8989 FRAME_PTR f;
f451eb13 8990{
12ba150f 8991 Lisp_Object bar, next;
f451eb13 8992
ab648270 8993 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8994
8995 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8996 more events on the hapless scroll bars. */
8997 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8998
8999 for (; ! NILP (bar); bar = next)
f451eb13 9000 {
ab648270 9001 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 9002
ab648270 9003 x_scroll_bar_remove (b);
12ba150f
JB
9004
9005 next = b->next;
9006 b->next = b->prev = Qnil;
f451eb13 9007 }
12ba150f 9008
ab648270 9009 /* Now there should be no references to the condemned scroll bars,
12ba150f 9010 and they should get garbage-collected. */
f451eb13
JB
9011}
9012
9013
06a2c219
GM
9014/* Handle an Expose or GraphicsExpose event on a scroll bar. This
9015 is a no-op when using toolkit scroll bars.
ab648270
JB
9016
9017 This may be called from a signal handler, so we have to ignore GC
9018 mark bits. */
06a2c219 9019
f451eb13 9020static void
ab648270
JB
9021x_scroll_bar_expose (bar, event)
9022 struct scroll_bar *bar;
f451eb13
JB
9023 XEvent *event;
9024{
06a2c219
GM
9025#ifndef USE_TOOLKIT_SCROLL_BARS
9026
ab648270 9027 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 9028 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 9029 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 9030 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 9031
f451eb13
JB
9032 BLOCK_INPUT;
9033
ab648270 9034 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 9035
06a2c219 9036 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 9037 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
9038
9039 /* x, y, width, height */
d9cdbb3d 9040 0, 0,
3cbd2e0b 9041 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
9042 XINT (bar->height) - 1);
9043
f451eb13 9044 UNBLOCK_INPUT;
06a2c219
GM
9045
9046#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
9047}
9048
ab648270
JB
9049/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
9050 is set to something other than no_event, it is enqueued.
9051
9052 This may be called from a signal handler, so we have to ignore GC
9053 mark bits. */
06a2c219 9054
5c187dee
GM
9055#ifndef USE_TOOLKIT_SCROLL_BARS
9056
f451eb13 9057static void
ab648270
JB
9058x_scroll_bar_handle_click (bar, event, emacs_event)
9059 struct scroll_bar *bar;
f451eb13
JB
9060 XEvent *event;
9061 struct input_event *emacs_event;
9062{
0299d313 9063 if (! GC_WINDOWP (bar->window))
12ba150f
JB
9064 abort ();
9065
ab648270 9066 emacs_event->kind = scroll_bar_click;
69388238 9067 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
9068 emacs_event->modifiers
9069 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
9070 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
9071 event->xbutton.state)
9072 | (event->type == ButtonRelease
9073 ? up_modifier
9074 : down_modifier));
12ba150f 9075 emacs_event->frame_or_window = bar->window;
0f8aabe9 9076 emacs_event->arg = Qnil;
f451eb13 9077 emacs_event->timestamp = event->xbutton.time;
12ba150f 9078 {
06a2c219 9079#if 0
d9cdbb3d 9080 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 9081 int internal_height
d9cdbb3d 9082 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 9083#endif
0299d313 9084 int top_range
d9cdbb3d 9085 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 9086 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
9087
9088 if (y < 0) y = 0;
9089 if (y > top_range) y = top_range;
9090
9091 if (y < XINT (bar->start))
ab648270
JB
9092 emacs_event->part = scroll_bar_above_handle;
9093 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9094 emacs_event->part = scroll_bar_handle;
12ba150f 9095 else
ab648270 9096 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
9097
9098 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
9099 they want to drag it. Lisp code needs to be able to decide
9100 whether or not we're dragging. */
929787e1 9101#if 0
12ba150f
JB
9102 /* If the user has just clicked on the handle, record where they're
9103 holding it. */
9104 if (event->type == ButtonPress
ab648270 9105 && emacs_event->part == scroll_bar_handle)
e0c1aef2 9106 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 9107#endif
12ba150f
JB
9108
9109 /* If the user has released the handle, set it to its final position. */
9110 if (event->type == ButtonRelease
9111 && ! NILP (bar->dragging))
9112 {
9113 int new_start = y - XINT (bar->dragging);
9114 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 9115
ab648270 9116 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
9117 bar->dragging = Qnil;
9118 }
f451eb13 9119
5116f055
JB
9120 /* Same deal here as the other #if 0. */
9121#if 0
58769bee 9122 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 9123 the handle. */
ab648270 9124 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
9125 emacs_event->x = bar->start;
9126 else
e0c1aef2 9127 XSETINT (emacs_event->x, y);
5116f055 9128#else
e0c1aef2 9129 XSETINT (emacs_event->x, y);
5116f055 9130#endif
f451eb13 9131
e0c1aef2 9132 XSETINT (emacs_event->y, top_range);
12ba150f
JB
9133 }
9134}
f451eb13 9135
ab648270
JB
9136/* Handle some mouse motion while someone is dragging the scroll bar.
9137
9138 This may be called from a signal handler, so we have to ignore GC
9139 mark bits. */
06a2c219 9140
f451eb13 9141static void
ab648270
JB
9142x_scroll_bar_note_movement (bar, event)
9143 struct scroll_bar *bar;
f451eb13
JB
9144 XEvent *event;
9145{
39d8bb4d
KH
9146 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
9147
f451eb13
JB
9148 last_mouse_movement_time = event->xmotion.time;
9149
39d8bb4d 9150 f->mouse_moved = 1;
e0c1aef2 9151 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
9152
9153 /* If we're dragging the bar, display it. */
ab648270 9154 if (! GC_NILP (bar->dragging))
f451eb13
JB
9155 {
9156 /* Where should the handle be now? */
12ba150f 9157 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 9158
12ba150f 9159 if (new_start != XINT (bar->start))
f451eb13 9160 {
12ba150f 9161 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 9162
ab648270 9163 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
9164 }
9165 }
f451eb13
JB
9166}
9167
5c187dee
GM
9168#endif /* !USE_TOOLKIT_SCROLL_BARS */
9169
12ba150f 9170/* Return information to the user about the current position of the mouse
ab648270 9171 on the scroll bar. */
06a2c219 9172
12ba150f 9173static void
334208b7
RS
9174x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
9175 FRAME_PTR *fp;
12ba150f 9176 Lisp_Object *bar_window;
ab648270 9177 enum scroll_bar_part *part;
12ba150f
JB
9178 Lisp_Object *x, *y;
9179 unsigned long *time;
9180{
ab648270 9181 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
9182 Window w = SCROLL_BAR_X_WINDOW (bar);
9183 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 9184 int win_x, win_y;
559cb2fb
JB
9185 Window dummy_window;
9186 int dummy_coord;
9187 unsigned int dummy_mask;
12ba150f 9188
cf7cb199
JB
9189 BLOCK_INPUT;
9190
ab648270 9191 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 9192 report that. */
334208b7 9193 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 9194
559cb2fb
JB
9195 /* Root, child, root x and root y. */
9196 &dummy_window, &dummy_window,
9197 &dummy_coord, &dummy_coord,
12ba150f 9198
559cb2fb
JB
9199 /* Position relative to scroll bar. */
9200 &win_x, &win_y,
12ba150f 9201
559cb2fb
JB
9202 /* Mouse buttons and modifier keys. */
9203 &dummy_mask))
7a13e894 9204 ;
559cb2fb
JB
9205 else
9206 {
06a2c219 9207#if 0
559cb2fb 9208 int inside_height
d9cdbb3d 9209 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 9210#endif
559cb2fb 9211 int top_range
d9cdbb3d 9212 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
9213
9214 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
9215
9216 if (! NILP (bar->dragging))
9217 win_y -= XINT (bar->dragging);
9218
9219 if (win_y < 0)
9220 win_y = 0;
9221 if (win_y > top_range)
9222 win_y = top_range;
9223
334208b7 9224 *fp = f;
7a13e894 9225 *bar_window = bar->window;
559cb2fb
JB
9226
9227 if (! NILP (bar->dragging))
9228 *part = scroll_bar_handle;
9229 else if (win_y < XINT (bar->start))
9230 *part = scroll_bar_above_handle;
9231 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
9232 *part = scroll_bar_handle;
9233 else
9234 *part = scroll_bar_below_handle;
12ba150f 9235
e0c1aef2
KH
9236 XSETINT (*x, win_y);
9237 XSETINT (*y, top_range);
12ba150f 9238
39d8bb4d 9239 f->mouse_moved = 0;
559cb2fb
JB
9240 last_mouse_scroll_bar = Qnil;
9241 }
12ba150f 9242
559cb2fb 9243 *time = last_mouse_movement_time;
cf7cb199 9244
cf7cb199 9245 UNBLOCK_INPUT;
12ba150f
JB
9246}
9247
f451eb13 9248
dbc4e1c1 9249/* The screen has been cleared so we may have changed foreground or
ab648270
JB
9250 background colors, and the scroll bars may need to be redrawn.
9251 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
9252 redraw them. */
9253
dfcf069d 9254void
ab648270 9255x_scroll_bar_clear (f)
dbc4e1c1
JB
9256 FRAME_PTR f;
9257{
06a2c219 9258#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
9259 Lisp_Object bar;
9260
b80c363e
RS
9261 /* We can have scroll bars even if this is 0,
9262 if we just turned off scroll bar mode.
9263 But in that case we should not clear them. */
9264 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
9265 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
9266 bar = XSCROLL_BAR (bar)->next)
c5e6e06b
GM
9267 XClearArea (FRAME_X_DISPLAY (f),
9268 SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
b80c363e 9269 0, 0, 0, 0, True);
06a2c219 9270#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
9271}
9272
06a2c219 9273/* This processes Expose events from the menu-bar specific X event
19126e11 9274 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 9275 when handling menu-bar or pop-up items. */
3afe33e7 9276
06a2c219 9277int
3afe33e7
RS
9278process_expose_from_menu (event)
9279 XEvent event;
9280{
9281 FRAME_PTR f;
19126e11 9282 struct x_display_info *dpyinfo;
06a2c219 9283 int frame_exposed_p = 0;
3afe33e7 9284
f94397b5
KH
9285 BLOCK_INPUT;
9286
19126e11
KH
9287 dpyinfo = x_display_info_for_display (event.xexpose.display);
9288 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
9289 if (f)
9290 {
9291 if (f->async_visible == 0)
9292 {
9293 f->async_visible = 1;
9294 f->async_iconified = 0;
06c488fd 9295 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
9296 SET_FRAME_GARBAGED (f);
9297 }
9298 else
9299 {
06a2c219
GM
9300 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
9301 event.xexpose.x, event.xexpose.y,
9302 event.xexpose.width, event.xexpose.height);
9303 frame_exposed_p = 1;
3afe33e7
RS
9304 }
9305 }
9306 else
9307 {
9308 struct scroll_bar *bar
9309 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9310
3afe33e7
RS
9311 if (bar)
9312 x_scroll_bar_expose (bar, &event);
9313 }
f94397b5
KH
9314
9315 UNBLOCK_INPUT;
06a2c219 9316 return frame_exposed_p;
3afe33e7 9317}
09756a85
RS
9318\f
9319/* Define a queue to save up SelectionRequest events for later handling. */
9320
9321struct selection_event_queue
9322 {
9323 XEvent event;
9324 struct selection_event_queue *next;
9325 };
9326
9327static struct selection_event_queue *queue;
9328
9329/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 9330
09756a85
RS
9331static int x_queue_selection_requests;
9332
9333/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 9334
09756a85 9335static void
334208b7
RS
9336x_queue_event (f, event)
9337 FRAME_PTR f;
09756a85
RS
9338 XEvent *event;
9339{
9340 struct selection_event_queue *queue_tmp
06a2c219 9341 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 9342
58769bee 9343 if (queue_tmp != NULL)
09756a85
RS
9344 {
9345 queue_tmp->event = *event;
9346 queue_tmp->next = queue;
9347 queue = queue_tmp;
9348 }
9349}
9350
9351/* Take all the queued events and put them back
9352 so that they get processed afresh. */
9353
9354static void
db3906fd
RS
9355x_unqueue_events (display)
9356 Display *display;
09756a85 9357{
58769bee 9358 while (queue != NULL)
09756a85
RS
9359 {
9360 struct selection_event_queue *queue_tmp = queue;
db3906fd 9361 XPutBackEvent (display, &queue_tmp->event);
09756a85 9362 queue = queue_tmp->next;
06a2c219 9363 xfree ((char *)queue_tmp);
09756a85
RS
9364 }
9365}
9366
9367/* Start queuing SelectionRequest events. */
9368
9369void
db3906fd
RS
9370x_start_queuing_selection_requests (display)
9371 Display *display;
09756a85
RS
9372{
9373 x_queue_selection_requests++;
9374}
9375
9376/* Stop queuing SelectionRequest events. */
9377
9378void
db3906fd
RS
9379x_stop_queuing_selection_requests (display)
9380 Display *display;
09756a85
RS
9381{
9382 x_queue_selection_requests--;
db3906fd 9383 x_unqueue_events (display);
09756a85 9384}
f451eb13
JB
9385\f
9386/* The main X event-reading loop - XTread_socket. */
dc6f92b8 9387
06a2c219 9388/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
9389 but we have to put it out here, since static variables within functions
9390 sometimes don't work. */
06a2c219 9391
dc6f92b8
JB
9392static Time enter_timestamp;
9393
11edeb03 9394/* This holds the state XLookupString needs to implement dead keys
58769bee 9395 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
9396 says that a portable program can't use this, but Stephen Gildea assures
9397 me that letting the compiler initialize it to zeros will work okay.
9398
9399 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
9400 given for enter_time stamp, above. */
9401
11edeb03
JB
9402static XComposeStatus compose_status;
9403
10e6549c
RS
9404/* Record the last 100 characters stored
9405 to help debug the loss-of-chars-during-GC problem. */
06a2c219 9406
2224b905
RS
9407static int temp_index;
9408static short temp_buffer[100];
10e6549c 9409
7a13e894
RS
9410/* Set this to nonzero to fake an "X I/O error"
9411 on a particular display. */
06a2c219 9412
7a13e894
RS
9413struct x_display_info *XTread_socket_fake_io_error;
9414
2224b905
RS
9415/* When we find no input here, we occasionally do a no-op command
9416 to verify that the X server is still running and we can still talk with it.
9417 We try all the open displays, one by one.
9418 This variable is used for cycling thru the displays. */
06a2c219 9419
2224b905
RS
9420static struct x_display_info *next_noop_dpyinfo;
9421
06a2c219
GM
9422#define SET_SAVED_MENU_EVENT(size) \
9423 do \
9424 { \
9425 if (f->output_data.x->saved_menu_event == 0) \
9426 f->output_data.x->saved_menu_event \
9427 = (XEvent *) xmalloc (sizeof (XEvent)); \
9428 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9429 if (numchars >= 1) \
9430 { \
9431 bufp->kind = menu_bar_activate_event; \
9432 XSETFRAME (bufp->frame_or_window, f); \
0f8aabe9 9433 bufp->arg = Qnil; \
06a2c219
GM
9434 bufp++; \
9435 count++; \
9436 numchars--; \
9437 } \
9438 } \
9439 while (0)
9440
8805890a 9441#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 9442#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 9443
dc6f92b8
JB
9444/* Read events coming from the X server.
9445 This routine is called by the SIGIO handler.
9446 We return as soon as there are no more events to be read.
9447
9448 Events representing keys are stored in buffer BUFP,
9449 which can hold up to NUMCHARS characters.
9450 We return the number of characters stored into the buffer,
9451 thus pretending to be `read'.
9452
dc6f92b8
JB
9453 EXPECTED is nonzero if the caller knows input is available. */
9454
7c5283e4 9455int
f66868ba 9456XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 9457 register int sd;
8805890a
KH
9458 /* register */ struct input_event *bufp;
9459 /* register */ int numchars;
dc6f92b8
JB
9460 int expected;
9461{
9462 int count = 0;
9463 int nbytes = 0;
dc6f92b8 9464 XEvent event;
f676886a 9465 struct frame *f;
66f55a9d 9466 int event_found = 0;
334208b7 9467 struct x_display_info *dpyinfo;
379b5ac0 9468 struct coding_system coding;
dc6f92b8 9469
9ac0d9e0 9470 if (interrupt_input_blocked)
dc6f92b8 9471 {
9ac0d9e0 9472 interrupt_input_pending = 1;
dc6f92b8
JB
9473 return -1;
9474 }
9475
9ac0d9e0 9476 interrupt_input_pending = 0;
dc6f92b8 9477 BLOCK_INPUT;
c0a04927
RS
9478
9479 /* So people can tell when we have read the available input. */
9480 input_signal_count++;
9481
dc6f92b8 9482 if (numchars <= 0)
06a2c219 9483 abort (); /* Don't think this happens. */
dc6f92b8 9484
bde5503b
GM
9485 ++handling_signal;
9486
379b5ac0
KH
9487 /* The input should be decoded if it is from XIM. Currently the
9488 locale of XIM is the same as that of the system. So, we can use
9489 Vlocale_coding_system which is initialized properly at Emacs
9490 startup time. */
9491 setup_coding_system (Vlocale_coding_system, &coding);
9492 coding.src_multibyte = 0;
9493 coding.dst_multibyte = 1;
9494 /* The input is converted to events, thus we can't handle
9495 composition. Anyway, there's no XIM that gives us composition
9496 information. */
9497 coding.composing = COMPOSITION_DISABLED;
9498
7a13e894
RS
9499 /* Find the display we are supposed to read input for.
9500 It's the one communicating on descriptor SD. */
9501 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9502 {
9503#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9504#ifdef FIOSNBIO
7a13e894
RS
9505 /* If available, Xlib uses FIOSNBIO to make the socket
9506 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9507 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9508 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9509 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9510#endif /* ! defined (FIOSNBIO) */
7a13e894 9511#endif
dc6f92b8 9512
7a13e894
RS
9513#if 0 /* This code can't be made to work, with multiple displays,
9514 and appears not to be used on any system any more.
9515 Also keyboard.c doesn't turn O_NDELAY on and off
9516 for X connections. */
dc6f92b8
JB
9517#ifndef SIGIO
9518#ifndef HAVE_SELECT
7a13e894
RS
9519 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9520 {
9521 extern int read_alarm_should_throw;
9522 read_alarm_should_throw = 1;
9523 XPeekEvent (dpyinfo->display, &event);
9524 read_alarm_should_throw = 0;
9525 }
c118dd06
JB
9526#endif /* HAVE_SELECT */
9527#endif /* SIGIO */
7a13e894 9528#endif
dc6f92b8 9529
7a13e894
RS
9530 /* For debugging, this gives a way to fake an I/O error. */
9531 if (dpyinfo == XTread_socket_fake_io_error)
9532 {
9533 XTread_socket_fake_io_error = 0;
9534 x_io_error_quitter (dpyinfo->display);
9535 }
dc6f92b8 9536
06a2c219 9537 while (XPending (dpyinfo->display))
dc6f92b8 9538 {
7a13e894 9539 XNextEvent (dpyinfo->display, &event);
06a2c219 9540
531483fb 9541#ifdef HAVE_X_I18N
d1bc4182 9542 {
f2be1146
GM
9543 /* Filter events for the current X input method.
9544 XFilterEvent returns non-zero if the input method has
9545 consumed the event. We pass the frame's X window to
9546 XFilterEvent because that's the one for which the IC
9547 was created. */
f5d11644
GM
9548 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9549 event.xclient.window);
9550 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9551 break;
9552 }
0cd6403b 9553#endif
7a13e894
RS
9554 event_found = 1;
9555
9556 switch (event.type)
9557 {
9558 case ClientMessage:
c047688c 9559 {
7a13e894
RS
9560 if (event.xclient.message_type
9561 == dpyinfo->Xatom_wm_protocols
9562 && event.xclient.format == 32)
c047688c 9563 {
7a13e894
RS
9564 if (event.xclient.data.l[0]
9565 == dpyinfo->Xatom_wm_take_focus)
c047688c 9566 {
8c1a6a84
RS
9567 /* Use x_any_window_to_frame because this
9568 could be the shell widget window
9569 if the frame has no title bar. */
9570 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9571#ifdef HAVE_X_I18N
9572 /* Not quite sure this is needed -pd */
8c1a6a84 9573 if (f && FRAME_XIC (f))
6c183ba5
RS
9574 XSetICFocus (FRAME_XIC (f));
9575#endif
f1da8f06
GM
9576#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9577 instructs the WM to set the input focus automatically for
9578 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9579 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9580 it has set the focus. So, XSetInputFocus below is not
9581 needed.
9582
9583 The call to XSetInputFocus below has also caused trouble. In
9584 cases where the XSetInputFocus done by the WM and the one
9585 below are temporally close (on a fast machine), the call
9586 below can generate additional FocusIn events which confuse
9587 Emacs. */
9588
bf7253f4
RS
9589 /* Since we set WM_TAKE_FOCUS, we must call
9590 XSetInputFocus explicitly. But not if f is null,
9591 since that might be an event for a deleted frame. */
7a13e894 9592 if (f)
bf7253f4
RS
9593 {
9594 Display *d = event.xclient.display;
9595 /* Catch and ignore errors, in case window has been
9596 iconified by a window manager such as GWM. */
9597 int count = x_catch_errors (d);
9598 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9599 /* The ICCCM says this is
9600 the only valid choice. */
9601 RevertToParent,
bf7253f4
RS
9602 event.xclient.data.l[1]);
9603 /* This is needed to detect the error
9604 if there is an error. */
9605 XSync (d, False);
9606 x_uncatch_errors (d, count);
9607 }
7a13e894 9608 /* Not certain about handling scroll bars here */
f1da8f06 9609#endif /* 0 */
c047688c 9610 }
7a13e894
RS
9611 else if (event.xclient.data.l[0]
9612 == dpyinfo->Xatom_wm_save_yourself)
9613 {
9614 /* Save state modify the WM_COMMAND property to
06a2c219 9615 something which can reinstate us. This notifies
7a13e894
RS
9616 the session manager, who's looking for such a
9617 PropertyNotify. Can restart processing when
06a2c219 9618 a keyboard or mouse event arrives. */
7a13e894
RS
9619 if (numchars > 0)
9620 {
19126e11
KH
9621 f = x_top_window_to_frame (dpyinfo,
9622 event.xclient.window);
7a13e894
RS
9623
9624 /* This is just so we only give real data once
9625 for a single Emacs process. */
b86bd3dd 9626 if (f == SELECTED_FRAME ())
7a13e894
RS
9627 XSetCommand (FRAME_X_DISPLAY (f),
9628 event.xclient.window,
9629 initial_argv, initial_argc);
f000f5c5 9630 else if (f)
7a13e894
RS
9631 XSetCommand (FRAME_X_DISPLAY (f),
9632 event.xclient.window,
9633 0, 0);
9634 }
9635 }
9636 else if (event.xclient.data.l[0]
9637 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9638 {
19126e11
KH
9639 struct frame *f
9640 = x_any_window_to_frame (dpyinfo,
9641 event.xclient.window);
1fb20991 9642
7a13e894
RS
9643 if (f)
9644 {
9645 if (numchars == 0)
9646 abort ();
1fb20991 9647
7a13e894
RS
9648 bufp->kind = delete_window_event;
9649 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9650 bufp->arg = Qnil;
7a13e894
RS
9651 bufp++;
9652
9653 count += 1;
9654 numchars -= 1;
9655 }
1fb20991 9656 }
c047688c 9657 }
7a13e894
RS
9658 else if (event.xclient.message_type
9659 == dpyinfo->Xatom_wm_configure_denied)
9660 {
9661 }
9662 else if (event.xclient.message_type
9663 == dpyinfo->Xatom_wm_window_moved)
9664 {
9665 int new_x, new_y;
19126e11
KH
9666 struct frame *f
9667 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9668
7a13e894
RS
9669 new_x = event.xclient.data.s[0];
9670 new_y = event.xclient.data.s[1];
1fb20991 9671
7a13e894
RS
9672 if (f)
9673 {
7556890b
RS
9674 f->output_data.x->left_pos = new_x;
9675 f->output_data.x->top_pos = new_y;
7a13e894 9676 }
1fb20991 9677 }
0fdff6bb 9678#ifdef HACK_EDITRES
7a13e894
RS
9679 else if (event.xclient.message_type
9680 == dpyinfo->Xatom_editres)
9681 {
19126e11
KH
9682 struct frame *f
9683 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9684 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9685 &event, NULL);
7a13e894 9686 }
0fdff6bb 9687#endif /* HACK_EDITRES */
06a2c219
GM
9688 else if ((event.xclient.message_type
9689 == dpyinfo->Xatom_DONE)
9690 || (event.xclient.message_type
9691 == dpyinfo->Xatom_PAGE))
9692 {
9693 /* Ghostview job completed. Kill it. We could
9694 reply with "Next" if we received "Page", but we
9695 currently never do because we are interested in
9696 images, only, which should have 1 page. */
06a2c219
GM
9697 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9698 struct frame *f
9699 = x_window_to_frame (dpyinfo, event.xclient.window);
9700 x_kill_gs_process (pixmap, f);
9701 expose_frame (f, 0, 0, 0, 0);
9702 }
9703#ifdef USE_TOOLKIT_SCROLL_BARS
9704 /* Scroll bar callbacks send a ClientMessage from which
9705 we construct an input_event. */
9706 else if (event.xclient.message_type
9707 == dpyinfo->Xatom_Scrollbar)
9708 {
9709 x_scroll_bar_to_input_event (&event, bufp);
9710 ++bufp, ++count, --numchars;
9711 goto out;
9712 }
9713#endif /* USE_TOOLKIT_SCROLL_BARS */
9714 else
9715 goto OTHER;
7a13e894
RS
9716 }
9717 break;
dc6f92b8 9718
7a13e894 9719 case SelectionNotify:
3afe33e7 9720#ifdef USE_X_TOOLKIT
19126e11 9721 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9722 goto OTHER;
3afe33e7 9723#endif /* not USE_X_TOOLKIT */
dfcf069d 9724 x_handle_selection_notify (&event.xselection);
7a13e894 9725 break;
d56a553a 9726
06a2c219 9727 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9728#ifdef USE_X_TOOLKIT
19126e11 9729 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9730 goto OTHER;
3afe33e7 9731#endif /* USE_X_TOOLKIT */
7a13e894
RS
9732 {
9733 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9734
7a13e894
RS
9735 if (numchars == 0)
9736 abort ();
d56a553a 9737
7a13e894
RS
9738 bufp->kind = selection_clear_event;
9739 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9740 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9741 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9742 bufp->frame_or_window = Qnil;
0f8aabe9 9743 bufp->arg = Qnil;
7a13e894 9744 bufp++;
d56a553a 9745
7a13e894
RS
9746 count += 1;
9747 numchars -= 1;
9748 }
9749 break;
dc6f92b8 9750
06a2c219 9751 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9752#ifdef USE_X_TOOLKIT
19126e11 9753 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9754 goto OTHER;
3afe33e7 9755#endif /* USE_X_TOOLKIT */
7a13e894 9756 if (x_queue_selection_requests)
19126e11 9757 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9758 &event);
9759 else
9760 {
9761 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9762
7a13e894
RS
9763 if (numchars == 0)
9764 abort ();
9765
9766 bufp->kind = selection_request_event;
9767 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9768 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9769 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9770 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9771 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9772 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9773 bufp->frame_or_window = Qnil;
0f8aabe9 9774 bufp->arg = Qnil;
7a13e894
RS
9775 bufp++;
9776
9777 count += 1;
9778 numchars -= 1;
9779 }
9780 break;
9781
9782 case PropertyNotify:
3afe33e7 9783#ifdef USE_X_TOOLKIT
19126e11 9784 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9785 goto OTHER;
3afe33e7 9786#endif /* not USE_X_TOOLKIT */
dfcf069d 9787 x_handle_property_notify (&event.xproperty);
7a13e894 9788 break;
dc6f92b8 9789
7a13e894 9790 case ReparentNotify:
19126e11 9791 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9792 if (f)
9793 {
9794 int x, y;
7556890b 9795 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9796 x_real_positions (f, &x, &y);
7556890b
RS
9797 f->output_data.x->left_pos = x;
9798 f->output_data.x->top_pos = y;
7a13e894
RS
9799 }
9800 break;
3bd330d4 9801
7a13e894 9802 case Expose:
19126e11 9803 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9804 if (f)
dc6f92b8 9805 {
7a13e894
RS
9806 if (f->async_visible == 0)
9807 {
9808 f->async_visible = 1;
9809 f->async_iconified = 0;
06c488fd 9810 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9811 SET_FRAME_GARBAGED (f);
9812 }
9813 else
06a2c219
GM
9814 expose_frame (x_window_to_frame (dpyinfo,
9815 event.xexpose.window),
9816 event.xexpose.x, event.xexpose.y,
9817 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9818 }
9819 else
7a13e894 9820 {
06a2c219
GM
9821#ifdef USE_TOOLKIT_SCROLL_BARS
9822 /* Dispatch event to the widget. */
9823 goto OTHER;
9824#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9825 struct scroll_bar *bar
9826 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9827
7a13e894
RS
9828 if (bar)
9829 x_scroll_bar_expose (bar, &event);
3afe33e7 9830#ifdef USE_X_TOOLKIT
7a13e894
RS
9831 else
9832 goto OTHER;
3afe33e7 9833#endif /* USE_X_TOOLKIT */
06a2c219 9834#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9835 }
9836 break;
dc6f92b8 9837
7a13e894
RS
9838 case GraphicsExpose: /* This occurs when an XCopyArea's
9839 source area was obscured or not
9840 available.*/
19126e11 9841 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9842 if (f)
9843 {
06a2c219
GM
9844 expose_frame (f,
9845 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9846 event.xgraphicsexpose.width,
9847 event.xgraphicsexpose.height);
7a13e894 9848 }
3afe33e7 9849#ifdef USE_X_TOOLKIT
7a13e894
RS
9850 else
9851 goto OTHER;
3afe33e7 9852#endif /* USE_X_TOOLKIT */
7a13e894 9853 break;
dc6f92b8 9854
7a13e894 9855 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9856 source area was completely
9857 available */
7a13e894 9858 break;
dc6f92b8 9859
7a13e894 9860 case UnmapNotify:
06a2c219
GM
9861 /* Redo the mouse-highlight after the tooltip has gone. */
9862 if (event.xmap.window == tip_window)
9863 {
9864 tip_window = 0;
9865 redo_mouse_highlight ();
9866 }
9867
91ea2a7a 9868 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9869 if (f) /* F may no longer exist if
9870 the frame was deleted. */
9871 {
9872 /* While a frame is unmapped, display generation is
9873 disabled; you don't want to spend time updating a
9874 display that won't ever be seen. */
9875 f->async_visible = 0;
9876 /* We can't distinguish, from the event, whether the window
9877 has become iconified or invisible. So assume, if it
9878 was previously visible, than now it is iconified.
1aa6072f
RS
9879 But x_make_frame_invisible clears both
9880 the visible flag and the iconified flag;
9881 and that way, we know the window is not iconified now. */
7a13e894 9882 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9883 {
9884 f->async_iconified = 1;
bddd097c 9885
1aa6072f
RS
9886 bufp->kind = iconify_event;
9887 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9888 bufp->arg = Qnil;
1aa6072f
RS
9889 bufp++;
9890 count++;
9891 numchars--;
9892 }
7a13e894 9893 }
7a13e894 9894 goto OTHER;
dc6f92b8 9895
7a13e894 9896 case MapNotify:
06a2c219
GM
9897 if (event.xmap.window == tip_window)
9898 /* The tooltip has been drawn already. Avoid
9899 the SET_FRAME_GARBAGED below. */
9900 goto OTHER;
9901
9902 /* We use x_top_window_to_frame because map events can
9903 come for sub-windows and they don't mean that the
9904 frame is visible. */
19126e11 9905 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9906 if (f)
9907 {
9908 f->async_visible = 1;
9909 f->async_iconified = 0;
06c488fd 9910 f->output_data.x->has_been_visible = 1;
dc6f92b8 9911
7a13e894
RS
9912 /* wait_reading_process_input will notice this and update
9913 the frame's display structures. */
9914 SET_FRAME_GARBAGED (f);
bddd097c 9915
d806e720
RS
9916 if (f->iconified)
9917 {
9918 bufp->kind = deiconify_event;
9919 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9920 bufp->arg = Qnil;
d806e720
RS
9921 bufp++;
9922 count++;
9923 numchars--;
9924 }
e73ec6fa 9925 else if (! NILP (Vframe_list)
8e713be6 9926 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9927 /* Force a redisplay sooner or later
9928 to update the frame titles
9929 in case this is the second frame. */
9930 record_asynch_buffer_change ();
7a13e894 9931 }
7a13e894 9932 goto OTHER;
dc6f92b8 9933
7a13e894 9934 case KeyPress:
19126e11 9935 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9936
eccc05db 9937#if defined USE_MOTIF && defined USE_TOOLKIT_SCROLL_BARS
06a2c219
GM
9938 if (f == 0)
9939 {
2564ea1b
GM
9940 /* Scroll bars consume key events, but we want
9941 the keys to go to the scroll bar's frame. */
06a2c219
GM
9942 Widget widget = XtWindowToWidget (dpyinfo->display,
9943 event.xkey.window);
9944 if (widget && XmIsScrollBar (widget))
9945 {
9946 widget = XtParent (widget);
9947 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9948 }
9949 }
eccc05db 9950#endif /* USE_MOTIF and USE_TOOLKIT_SCROLL_BARS */
06a2c219 9951
7a13e894
RS
9952 if (f != 0)
9953 {
9954 KeySym keysym, orig_keysym;
379b5ac0
KH
9955 /* al%imercury@uunet.uu.net says that making this 81
9956 instead of 80 fixed a bug whereby meta chars made
9957 his Emacs hang.
9958
9959 It seems that some version of XmbLookupString has
9960 a bug of not returning XBufferOverflow in
9961 status_return even if the input is too long to
9962 fit in 81 bytes. So, we must prepare sufficient
9963 bytes for copy_buffer. 513 bytes (256 chars for
9964 two-byte character set) seems to be a faily good
9965 approximation. -- 2000.8.10 handa@etl.go.jp */
9966 unsigned char copy_buffer[513];
9967 unsigned char *copy_bufptr = copy_buffer;
9968 int copy_bufsiz = sizeof (copy_buffer);
7a13e894 9969 int modifiers;
64bb1782 9970
7a13e894
RS
9971 event.xkey.state
9972 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9973 extra_keyboard_modifiers);
9974 modifiers = event.xkey.state;
3a2712f9 9975
7a13e894 9976 /* This will have to go some day... */
752a043f 9977
7a13e894
RS
9978 /* make_lispy_event turns chars into control chars.
9979 Don't do it here because XLookupString is too eager. */
9980 event.xkey.state &= ~ControlMask;
5d46f928
RS
9981 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9982 | dpyinfo->super_mod_mask
9983 | dpyinfo->hyper_mod_mask
9984 | dpyinfo->alt_mod_mask);
9985
1cf4a0d1
RS
9986 /* In case Meta is ComposeCharacter,
9987 clear its status. According to Markus Ehrnsperger
9988 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9989 this enables ComposeCharacter to work whether or
9990 not it is combined with Meta. */
9991 if (modifiers & dpyinfo->meta_mod_mask)
9992 bzero (&compose_status, sizeof (compose_status));
9993
6c183ba5
RS
9994#ifdef HAVE_X_I18N
9995 if (FRAME_XIC (f))
9996 {
f5d11644
GM
9997 Status status_return;
9998
6c183ba5 9999 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
10000 &event.xkey, copy_bufptr,
10001 copy_bufsiz, &keysym,
6c183ba5 10002 &status_return);
f5d11644
GM
10003 if (status_return == XBufferOverflow)
10004 {
10005 copy_bufsiz = nbytes + 1;
10006 copy_bufptr = (char *) alloca (copy_bufsiz);
10007 nbytes = XmbLookupString (FRAME_XIC (f),
10008 &event.xkey, copy_bufptr,
10009 copy_bufsiz, &keysym,
10010 &status_return);
10011 }
10012
1decb680
PE
10013 if (status_return == XLookupNone)
10014 break;
10015 else if (status_return == XLookupChars)
fdd9d55e
GM
10016 {
10017 keysym = NoSymbol;
10018 modifiers = 0;
10019 }
1decb680
PE
10020 else if (status_return != XLookupKeySym
10021 && status_return != XLookupBoth)
10022 abort ();
6c183ba5
RS
10023 }
10024 else
379b5ac0
KH
10025 nbytes = XLookupString (&event.xkey, copy_bufptr,
10026 copy_bufsiz, &keysym,
10027 &compose_status);
6c183ba5 10028#else
379b5ac0
KH
10029 nbytes = XLookupString (&event.xkey, copy_bufptr,
10030 copy_bufsiz, &keysym,
10031 &compose_status);
6c183ba5 10032#endif
dc6f92b8 10033
7a13e894 10034 orig_keysym = keysym;
55123275 10035
7a13e894
RS
10036 if (numchars > 1)
10037 {
10038 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
10039 || keysym == XK_Delete
1097aea0 10040#ifdef XK_ISO_Left_Tab
441affdb 10041 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 10042#endif
852bff8f 10043 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
10044 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
10045 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 10046#ifdef HPUX
7a13e894
RS
10047 /* This recognizes the "extended function keys".
10048 It seems there's no cleaner way.
10049 Test IsModifierKey to avoid handling mode_switch
10050 incorrectly. */
10051 || ((unsigned) (keysym) >= XK_Select
10052 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
10053#endif
10054#ifdef XK_dead_circumflex
7a13e894 10055 || orig_keysym == XK_dead_circumflex
69388238
RS
10056#endif
10057#ifdef XK_dead_grave
7a13e894 10058 || orig_keysym == XK_dead_grave
69388238
RS
10059#endif
10060#ifdef XK_dead_tilde
7a13e894 10061 || orig_keysym == XK_dead_tilde
69388238
RS
10062#endif
10063#ifdef XK_dead_diaeresis
7a13e894 10064 || orig_keysym == XK_dead_diaeresis
69388238
RS
10065#endif
10066#ifdef XK_dead_macron
7a13e894 10067 || orig_keysym == XK_dead_macron
69388238
RS
10068#endif
10069#ifdef XK_dead_degree
7a13e894 10070 || orig_keysym == XK_dead_degree
69388238
RS
10071#endif
10072#ifdef XK_dead_acute
7a13e894 10073 || orig_keysym == XK_dead_acute
69388238
RS
10074#endif
10075#ifdef XK_dead_cedilla
7a13e894 10076 || orig_keysym == XK_dead_cedilla
69388238
RS
10077#endif
10078#ifdef XK_dead_breve
7a13e894 10079 || orig_keysym == XK_dead_breve
69388238
RS
10080#endif
10081#ifdef XK_dead_ogonek
7a13e894 10082 || orig_keysym == XK_dead_ogonek
69388238
RS
10083#endif
10084#ifdef XK_dead_caron
7a13e894 10085 || orig_keysym == XK_dead_caron
69388238
RS
10086#endif
10087#ifdef XK_dead_doubleacute
7a13e894 10088 || orig_keysym == XK_dead_doubleacute
69388238
RS
10089#endif
10090#ifdef XK_dead_abovedot
7a13e894 10091 || orig_keysym == XK_dead_abovedot
c34790e0 10092#endif
7a13e894
RS
10093 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
10094 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
10095 /* Any "vendor-specific" key is ok. */
10096 || (orig_keysym & (1 << 28)))
10097 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
10098#ifndef HAVE_X11R5
10099#ifdef XK_Mode_switch
7a13e894 10100 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
10101#endif
10102#ifdef XK_Num_Lock
7a13e894 10103 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
10104#endif
10105#endif /* not HAVE_X11R5 */
7a13e894 10106 ))
dc6f92b8 10107 {
10e6549c
RS
10108 if (temp_index == sizeof temp_buffer / sizeof (short))
10109 temp_index = 0;
7a13e894
RS
10110 temp_buffer[temp_index++] = keysym;
10111 bufp->kind = non_ascii_keystroke;
10112 bufp->code = keysym;
e0c1aef2 10113 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10114 bufp->arg = Qnil;
334208b7
RS
10115 bufp->modifiers
10116 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10117 modifiers);
1113d9db 10118 bufp->timestamp = event.xkey.time;
dc6f92b8 10119 bufp++;
7a13e894
RS
10120 count++;
10121 numchars--;
dc6f92b8 10122 }
7a13e894
RS
10123 else if (numchars > nbytes)
10124 {
10125 register int i;
379b5ac0 10126 register int c;
379b5ac0 10127 int nchars, len;
7a13e894
RS
10128
10129 for (i = 0; i < nbytes; i++)
10130 {
379b5ac0
KH
10131 if (temp_index == (sizeof temp_buffer
10132 / sizeof (short)))
7a13e894 10133 temp_index = 0;
379b5ac0
KH
10134 temp_buffer[temp_index++] = copy_bufptr[i];
10135 }
10136
10137 if (/* If the event is not from XIM, */
10138 event.xkey.keycode != 0
10139 /* or the current locale doesn't request
10140 decoding of the intup data, ... */
10141 || coding.type == coding_type_raw_text
10142 || coding.type == coding_type_no_conversion)
10143 {
10144 /* ... we can use the input data as is. */
10145 nchars = nbytes;
10146 }
10147 else
10148 {
10149 /* We have to decode the input data. */
10150 int require;
10151 unsigned char *p;
10152
10153 require = decoding_buffer_size (&coding, nbytes);
10154 p = (unsigned char *) alloca (require);
10155 coding.mode |= CODING_MODE_LAST_BLOCK;
10156 decode_coding (&coding, copy_bufptr, p,
10157 nbytes, require);
10158 nbytes = coding.produced;
10159 nchars = coding.produced_char;
10160 copy_bufptr = p;
10161 }
10162
10163 /* Convert the input data to a sequence of
10164 character events. */
10165 for (i = 0; i < nbytes; i += len)
10166 {
10167 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
10168 nbytes - i, len);
10169 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
10170 ? ascii_keystroke
10171 : multibyte_char_keystroke);
10172 bufp->code = c;
7a13e894 10173 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10174 bufp->arg = Qnil;
7a13e894
RS
10175 bufp->modifiers
10176 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
10177 modifiers);
10178 bufp->timestamp = event.xkey.time;
10179 bufp++;
10180 }
10181
379b5ac0
KH
10182 count += nchars;
10183 numchars -= nchars;
1decb680
PE
10184
10185 if (keysym == NoSymbol)
10186 break;
7a13e894
RS
10187 }
10188 else
10189 abort ();
dc6f92b8 10190 }
10e6549c
RS
10191 else
10192 abort ();
dc6f92b8 10193 }
59ddecde
GM
10194#ifdef HAVE_X_I18N
10195 /* Don't dispatch this event since XtDispatchEvent calls
10196 XFilterEvent, and two calls in a row may freeze the
10197 client. */
10198 break;
10199#else
717ca130 10200 goto OTHER;
59ddecde 10201#endif
f451eb13 10202
f5d11644 10203 case KeyRelease:
59ddecde
GM
10204#ifdef HAVE_X_I18N
10205 /* Don't dispatch this event since XtDispatchEvent calls
10206 XFilterEvent, and two calls in a row may freeze the
10207 client. */
10208 break;
10209#else
f5d11644 10210 goto OTHER;
59ddecde 10211#endif
f5d11644 10212
7a13e894 10213 /* Here's a possible interpretation of the whole
06a2c219
GM
10214 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
10215 you get a FocusIn event, you have to get a FocusOut
10216 event before you relinquish the focus. If you
10217 haven't received a FocusIn event, then a mere
10218 LeaveNotify is enough to free you. */
f451eb13 10219
7a13e894 10220 case EnterNotify:
06a2c219 10221 {
06a2c219
GM
10222 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
10223
582c60f8 10224 if (event.xcrossing.focus)
06a2c219
GM
10225 {
10226 /* Avoid nasty pop/raise loops. */
10227 if (f && (!(f->auto_raise)
10228 || !(f->auto_lower)
10229 || (event.xcrossing.time - enter_timestamp) > 500))
10230 {
10231 x_new_focus_frame (dpyinfo, f);
10232 enter_timestamp = event.xcrossing.time;
10233 }
10234 }
10235 else if (f == dpyinfo->x_focus_frame)
10236 x_new_focus_frame (dpyinfo, 0);
10237
10238 /* EnterNotify counts as mouse movement,
10239 so update things that depend on mouse position. */
2533c408 10240 if (f && !f->output_data.x->hourglass_p)
06a2c219
GM
10241 note_mouse_movement (f, &event.xmotion);
10242 goto OTHER;
10243 }
dc6f92b8 10244
7a13e894 10245 case FocusIn:
19126e11 10246 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10247 if (event.xfocus.detail != NotifyPointer)
0f941935 10248 dpyinfo->x_focus_event_frame = f;
7a13e894 10249 if (f)
eb72635f
GM
10250 {
10251 x_new_focus_frame (dpyinfo, f);
10252
10253 /* Don't stop displaying the initial startup message
10254 for a switch-frame event we don't need. */
10255 if (GC_NILP (Vterminal_frame)
10256 && GC_CONSP (Vframe_list)
10257 && !GC_NILP (XCDR (Vframe_list)))
10258 {
10259 bufp->kind = FOCUS_IN_EVENT;
10260 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 10261 bufp->arg = Qnil;
eb72635f
GM
10262 ++bufp, ++count, --numchars;
10263 }
10264 }
f9e24cb9 10265
6c183ba5
RS
10266#ifdef HAVE_X_I18N
10267 if (f && FRAME_XIC (f))
10268 XSetICFocus (FRAME_XIC (f));
10269#endif
10270
7a13e894 10271 goto OTHER;
10c5e63d 10272
7a13e894 10273 case LeaveNotify:
19126e11 10274 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 10275 if (f)
10c5e63d 10276 {
7a13e894 10277 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
10278 {
10279 /* If we move outside the frame, then we're
10280 certainly no longer on any text in the frame. */
10281 clear_mouse_face (dpyinfo);
10282 dpyinfo->mouse_face_mouse_frame = 0;
10283 }
10284
10285 /* Generate a nil HELP_EVENT to cancel a help-echo.
10286 Do it only if there's something to cancel.
10287 Otherwise, the startup message is cleared when
10288 the mouse leaves the frame. */
10289 if (any_help_event_p)
10290 {
be010514
GM
10291 Lisp_Object frame;
10292 int n;
10293
06a2c219 10294 XSETFRAME (frame, f);
82c5d67a 10295 help_echo = Qnil;
5ab2570d
GM
10296 n = gen_help_event (bufp, numchars,
10297 Qnil, frame, Qnil, Qnil, 0);
be010514 10298 bufp += n, count += n, numchars -= n;
06a2c219 10299 }
7a13e894 10300
582c60f8 10301 if (event.xcrossing.focus)
0f941935 10302 x_mouse_leave (dpyinfo);
10c5e63d 10303 else
7a13e894 10304 {
0f941935
KH
10305 if (f == dpyinfo->x_focus_event_frame)
10306 dpyinfo->x_focus_event_frame = 0;
10307 if (f == dpyinfo->x_focus_frame)
10308 x_new_focus_frame (dpyinfo, 0);
7a13e894 10309 }
10c5e63d 10310 }
7a13e894 10311 goto OTHER;
dc6f92b8 10312
7a13e894 10313 case FocusOut:
19126e11 10314 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 10315 if (event.xfocus.detail != NotifyPointer
0f941935
KH
10316 && f == dpyinfo->x_focus_event_frame)
10317 dpyinfo->x_focus_event_frame = 0;
10318 if (f && f == dpyinfo->x_focus_frame)
10319 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 10320
6c183ba5
RS
10321#ifdef HAVE_X_I18N
10322 if (f && FRAME_XIC (f))
10323 XUnsetICFocus (FRAME_XIC (f));
10324#endif
10325
7a13e894 10326 goto OTHER;
dc6f92b8 10327
7a13e894 10328 case MotionNotify:
dc6f92b8 10329 {
06a2c219 10330 previous_help_echo = help_echo;
7cea38bc 10331 help_echo = help_echo_object = help_echo_window = Qnil;
be010514 10332 help_echo_pos = -1;
06a2c219 10333
7a13e894
RS
10334 if (dpyinfo->grabbed && last_mouse_frame
10335 && FRAME_LIVE_P (last_mouse_frame))
10336 f = last_mouse_frame;
10337 else
19126e11 10338 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 10339
7a13e894
RS
10340 if (f)
10341 note_mouse_movement (f, &event.xmotion);
10342 else
10343 {
e88b3c50 10344#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10345 struct scroll_bar *bar
10346 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 10347
7a13e894
RS
10348 if (bar)
10349 x_scroll_bar_note_movement (bar, &event);
e88b3c50 10350#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 10351
06a2c219
GM
10352 /* If we move outside the frame, then we're
10353 certainly no longer on any text in the frame. */
7a13e894
RS
10354 clear_mouse_face (dpyinfo);
10355 }
06a2c219
GM
10356
10357 /* If the contents of the global variable help_echo
10358 has changed, generate a HELP_EVENT. */
b7e80413
SM
10359 if (!NILP (help_echo)
10360 || !NILP (previous_help_echo))
06a2c219
GM
10361 {
10362 Lisp_Object frame;
be010514 10363 int n;
06a2c219
GM
10364
10365 if (f)
10366 XSETFRAME (frame, f);
10367 else
10368 frame = Qnil;
10369
10370 any_help_event_p = 1;
5ab2570d 10371 n = gen_help_event (bufp, numchars, help_echo, frame,
7cea38bc
GM
10372 help_echo_window, help_echo_object,
10373 help_echo_pos);
be010514 10374 bufp += n, count += n, numchars -= n;
06a2c219
GM
10375 }
10376
10377 goto OTHER;
dc6f92b8 10378 }
dc6f92b8 10379
7a13e894 10380 case ConfigureNotify:
9829ddba
RS
10381 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10382 if (f)
af395ec1 10383 {
5c187dee 10384#ifndef USE_X_TOOLKIT
bf1b7b30
KH
10385 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10386 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 10387
2d7fc7e8
RS
10388 /* In the toolkit version, change_frame_size
10389 is called by the code that handles resizing
10390 of the EmacsFrame widget. */
7a13e894 10391
7a13e894
RS
10392 /* Even if the number of character rows and columns has
10393 not changed, the font size may have changed, so we need
10394 to check the pixel dimensions as well. */
10395 if (columns != f->width
10396 || rows != f->height
7556890b
RS
10397 || event.xconfigure.width != f->output_data.x->pixel_width
10398 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 10399 {
7d1e984f 10400 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 10401 SET_FRAME_GARBAGED (f);
e687d06e 10402 cancel_mouse_face (f);
7a13e894 10403 }
2d7fc7e8 10404#endif
af395ec1 10405
7556890b
RS
10406 f->output_data.x->pixel_width = event.xconfigure.width;
10407 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
10408
10409 /* What we have now is the position of Emacs's own window.
10410 Convert that to the position of the window manager window. */
dcb07ae9
RS
10411 x_real_positions (f, &f->output_data.x->left_pos,
10412 &f->output_data.x->top_pos);
10413
f5d11644
GM
10414#ifdef HAVE_X_I18N
10415 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10416 xic_set_statusarea (f);
10417#endif
10418
dcb07ae9
RS
10419 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10420 {
10421 /* Since the WM decorations come below top_pos now,
10422 we must put them below top_pos in the future. */
10423 f->output_data.x->win_gravity = NorthWestGravity;
10424 x_wm_set_size_hint (f, (long) 0, 0);
10425 }
8f08dc93
KH
10426#ifdef USE_MOTIF
10427 /* Some window managers pass (0,0) as the location of
10428 the window, and the Motif event handler stores it
10429 in the emacs widget, which messes up Motif menus. */
10430 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10431 {
10432 event.xconfigure.x = f->output_data.x->widget->core.x;
10433 event.xconfigure.y = f->output_data.x->widget->core.y;
10434 }
06a2c219 10435#endif /* USE_MOTIF */
7a13e894 10436 }
2d7fc7e8 10437 goto OTHER;
dc6f92b8 10438
7a13e894
RS
10439 case ButtonPress:
10440 case ButtonRelease:
10441 {
10442 /* If we decide we want to generate an event to be seen
10443 by the rest of Emacs, we put it here. */
10444 struct input_event emacs_event;
9ea173e8 10445 int tool_bar_p = 0;
06a2c219 10446
7a13e894 10447 emacs_event.kind = no_event;
7a13e894 10448 bzero (&compose_status, sizeof (compose_status));
9b07615b 10449
06a2c219
GM
10450 if (dpyinfo->grabbed
10451 && last_mouse_frame
9f67f20b
RS
10452 && FRAME_LIVE_P (last_mouse_frame))
10453 f = last_mouse_frame;
10454 else
2224b905 10455 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 10456
06a2c219
GM
10457 if (f)
10458 {
9ea173e8
GM
10459 /* Is this in the tool-bar? */
10460 if (WINDOWP (f->tool_bar_window)
10461 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
10462 {
10463 Lisp_Object window;
10464 int p, x, y;
10465
10466 x = event.xbutton.x;
10467 y = event.xbutton.y;
10468
10469 /* Set x and y. */
10470 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 10471 if (EQ (window, f->tool_bar_window))
06a2c219 10472 {
9ea173e8
GM
10473 x_handle_tool_bar_click (f, &event.xbutton);
10474 tool_bar_p = 1;
06a2c219
GM
10475 }
10476 }
10477
9ea173e8 10478 if (!tool_bar_p)
06a2c219
GM
10479 if (!dpyinfo->x_focus_frame
10480 || f == dpyinfo->x_focus_frame)
10481 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
10482 }
10483 else
10484 {
06a2c219 10485#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10486 struct scroll_bar *bar
10487 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 10488
7a13e894
RS
10489 if (bar)
10490 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 10491#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10492 }
10493
10494 if (event.type == ButtonPress)
10495 {
10496 dpyinfo->grabbed |= (1 << event.xbutton.button);
10497 last_mouse_frame = f;
edad46f6
KH
10498 /* Ignore any mouse motion that happened
10499 before this event; any subsequent mouse-movement
10500 Emacs events should reflect only motion after
10501 the ButtonPress. */
a00e91cd
KH
10502 if (f != 0)
10503 f->mouse_moved = 0;
06a2c219 10504
9ea173e8
GM
10505 if (!tool_bar_p)
10506 last_tool_bar_item = -1;
7a13e894 10507 }
3afe33e7
RS
10508 else
10509 {
7a13e894 10510 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10511 }
23faf38f 10512
7a13e894
RS
10513 if (numchars >= 1 && emacs_event.kind != no_event)
10514 {
10515 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10516 bufp++;
10517 count++;
10518 numchars--;
10519 }
3afe33e7
RS
10520
10521#ifdef USE_X_TOOLKIT
2224b905
RS
10522 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10523 /* For a down-event in the menu bar,
10524 don't pass it to Xt right now.
10525 Instead, save it away
10526 and we will pass it to Xt from kbd_buffer_get_event.
10527 That way, we can run some Lisp code first. */
91375f8f
RS
10528 if (f && event.type == ButtonPress
10529 /* Verify the event is really within the menu bar
10530 and not just sent to it due to grabbing. */
10531 && event.xbutton.x >= 0
10532 && event.xbutton.x < f->output_data.x->pixel_width
10533 && event.xbutton.y >= 0
10534 && event.xbutton.y < f->output_data.x->menubar_height
10535 && event.xbutton.same_screen)
2224b905 10536 {
8805890a 10537 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10538 XSETFRAME (last_mouse_press_frame, f);
10539 }
10540 else if (event.type == ButtonPress)
10541 {
10542 last_mouse_press_frame = Qnil;
30e671c3 10543 goto OTHER;
ce89ef46 10544 }
06a2c219 10545
2237cac9
RS
10546#ifdef USE_MOTIF /* This should do not harm for Lucid,
10547 but I am trying to be cautious. */
ce89ef46
RS
10548 else if (event.type == ButtonRelease)
10549 {
2237cac9 10550 if (!NILP (last_mouse_press_frame))
f10ded1c 10551 {
2237cac9
RS
10552 f = XFRAME (last_mouse_press_frame);
10553 if (f->output_data.x)
06a2c219 10554 SET_SAVED_BUTTON_EVENT;
f10ded1c 10555 }
06a2c219 10556 else
30e671c3 10557 goto OTHER;
2224b905 10558 }
2237cac9 10559#endif /* USE_MOTIF */
2224b905
RS
10560 else
10561 goto OTHER;
3afe33e7 10562#endif /* USE_X_TOOLKIT */
7a13e894
RS
10563 }
10564 break;
dc6f92b8 10565
7a13e894 10566 case CirculateNotify:
06a2c219
GM
10567 goto OTHER;
10568
7a13e894 10569 case CirculateRequest:
06a2c219
GM
10570 goto OTHER;
10571
10572 case VisibilityNotify:
10573 goto OTHER;
dc6f92b8 10574
7a13e894
RS
10575 case MappingNotify:
10576 /* Someone has changed the keyboard mapping - update the
10577 local cache. */
10578 switch (event.xmapping.request)
10579 {
10580 case MappingModifier:
10581 x_find_modifier_meanings (dpyinfo);
10582 /* This is meant to fall through. */
10583 case MappingKeyboard:
10584 XRefreshKeyboardMapping (&event.xmapping);
10585 }
7a13e894 10586 goto OTHER;
dc6f92b8 10587
7a13e894 10588 default:
7a13e894 10589 OTHER:
717ca130 10590#ifdef USE_X_TOOLKIT
7a13e894
RS
10591 BLOCK_INPUT;
10592 XtDispatchEvent (&event);
10593 UNBLOCK_INPUT;
3afe33e7 10594#endif /* USE_X_TOOLKIT */
7a13e894
RS
10595 break;
10596 }
dc6f92b8
JB
10597 }
10598 }
10599
06a2c219
GM
10600 out:;
10601
9a5196d0
RS
10602 /* On some systems, an X bug causes Emacs to get no more events
10603 when the window is destroyed. Detect that. (1994.) */
58769bee 10604 if (! event_found)
ef2a22d0 10605 {
ef2a22d0
RS
10606 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10607 One XNOOP in 100 loops will make Emacs terminate.
10608 B. Bretthauer, 1994 */
10609 x_noop_count++;
58769bee 10610 if (x_noop_count >= 100)
ef2a22d0
RS
10611 {
10612 x_noop_count=0;
2224b905
RS
10613
10614 if (next_noop_dpyinfo == 0)
10615 next_noop_dpyinfo = x_display_list;
10616
10617 XNoOp (next_noop_dpyinfo->display);
10618
10619 /* Each time we get here, cycle through the displays now open. */
10620 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10621 }
10622 }
502add23 10623
06a2c219 10624 /* If the focus was just given to an auto-raising frame,
0134a210 10625 raise it now. */
7a13e894 10626 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10627 if (pending_autoraise_frame)
10628 {
10629 x_raise_frame (pending_autoraise_frame);
10630 pending_autoraise_frame = 0;
10631 }
0134a210 10632
dc6f92b8 10633 UNBLOCK_INPUT;
bde5503b 10634 --handling_signal;
dc6f92b8
JB
10635 return count;
10636}
06a2c219
GM
10637
10638
10639
dc6f92b8 10640\f
06a2c219
GM
10641/***********************************************************************
10642 Text Cursor
10643 ***********************************************************************/
10644
10645/* Note if the text cursor of window W has been overwritten by a
10646 drawing operation that outputs N glyphs starting at HPOS in the
10647 line given by output_cursor.vpos. N < 0 means all the rest of the
10648 line after HPOS has been written. */
10649
10650static void
10651note_overwritten_text_cursor (w, hpos, n)
10652 struct window *w;
10653 int hpos, n;
10654{
10655 if (updated_area == TEXT_AREA
10656 && output_cursor.vpos == w->phys_cursor.vpos
10657 && hpos <= w->phys_cursor.hpos
10658 && (n < 0
10659 || hpos + n > w->phys_cursor.hpos))
10660 w->phys_cursor_on_p = 0;
10661}
f451eb13
JB
10662
10663
06a2c219
GM
10664/* Set clipping for output in glyph row ROW. W is the window in which
10665 we operate. GC is the graphics context to set clipping in.
10666 WHOLE_LINE_P non-zero means include the areas used for truncation
10667 mark display and alike in the clipping rectangle.
10668
10669 ROW may be a text row or, e.g., a mode line. Text rows must be
10670 clipped to the interior of the window dedicated to text display,
10671 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10672
10673static void
06a2c219
GM
10674x_clip_to_row (w, row, gc, whole_line_p)
10675 struct window *w;
10676 struct glyph_row *row;
10677 GC gc;
10678 int whole_line_p;
dc6f92b8 10679{
06a2c219
GM
10680 struct frame *f = XFRAME (WINDOW_FRAME (w));
10681 XRectangle clip_rect;
10682 int window_x, window_y, window_width, window_height;
dc6f92b8 10683
06a2c219 10684 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10685
06a2c219
GM
10686 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10687 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10688 clip_rect.y = max (clip_rect.y, window_y);
10689 clip_rect.width = window_width;
10690 clip_rect.height = row->visible_height;
5c1aae96 10691
06a2c219
GM
10692 /* If clipping to the whole line, including trunc marks, extend
10693 the rectangle to the left and increase its width. */
10694 if (whole_line_p)
10695 {
110859fc
GM
10696 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10697 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10698 }
5c1aae96 10699
06a2c219 10700 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10701}
10702
06a2c219
GM
10703
10704/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10705
10706static void
06a2c219
GM
10707x_draw_hollow_cursor (w, row)
10708 struct window *w;
10709 struct glyph_row *row;
dc6f92b8 10710{
06a2c219
GM
10711 struct frame *f = XFRAME (WINDOW_FRAME (w));
10712 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10713 Display *dpy = FRAME_X_DISPLAY (f);
10714 int x, y, wd, h;
10715 XGCValues xgcv;
10716 struct glyph *cursor_glyph;
10717 GC gc;
10718
10719 /* Compute frame-relative coordinates from window-relative
10720 coordinates. */
10721 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10722 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10723 + row->ascent - w->phys_cursor_ascent);
10724 h = row->height - 1;
10725
10726 /* Get the glyph the cursor is on. If we can't tell because
10727 the current matrix is invalid or such, give up. */
10728 cursor_glyph = get_phys_cursor_glyph (w);
10729 if (cursor_glyph == NULL)
dc6f92b8
JB
10730 return;
10731
06a2c219
GM
10732 /* Compute the width of the rectangle to draw. If on a stretch
10733 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10734 rectangle as wide as the glyph, but use a canonical character
10735 width instead. */
10736 wd = cursor_glyph->pixel_width - 1;
10737 if (cursor_glyph->type == STRETCH_GLYPH
10738 && !x_stretch_cursor_p)
10739 wd = min (CANON_X_UNIT (f), wd);
10740
10741 /* The foreground of cursor_gc is typically the same as the normal
10742 background color, which can cause the cursor box to be invisible. */
10743 xgcv.foreground = f->output_data.x->cursor_pixel;
10744 if (dpyinfo->scratch_cursor_gc)
10745 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10746 else
10747 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10748 GCForeground, &xgcv);
10749 gc = dpyinfo->scratch_cursor_gc;
10750
10751 /* Set clipping, draw the rectangle, and reset clipping again. */
10752 x_clip_to_row (w, row, gc, 0);
10753 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10754 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10755}
10756
06a2c219
GM
10757
10758/* Draw a bar cursor on window W in glyph row ROW.
10759
10760 Implementation note: One would like to draw a bar cursor with an
10761 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10762 Unfortunately, I didn't find a font yet that has this property set.
10763 --gerd. */
dc6f92b8
JB
10764
10765static void
f02d8aa0 10766x_draw_bar_cursor (w, row, width)
06a2c219
GM
10767 struct window *w;
10768 struct glyph_row *row;
f02d8aa0 10769 int width;
dc6f92b8 10770{
92f424df
GM
10771 struct frame *f = XFRAME (w->frame);
10772 struct glyph *cursor_glyph;
10773 GC gc;
10774 int x;
10775 unsigned long mask;
10776 XGCValues xgcv;
10777 Display *dpy;
10778 Window window;
06a2c219 10779
92f424df
GM
10780 /* If cursor is out of bounds, don't draw garbage. This can happen
10781 in mini-buffer windows when switching between echo area glyphs
10782 and mini-buffer. */
10783 cursor_glyph = get_phys_cursor_glyph (w);
10784 if (cursor_glyph == NULL)
10785 return;
06a2c219 10786
92f424df
GM
10787 /* If on an image, draw like a normal cursor. That's usually better
10788 visible than drawing a bar, esp. if the image is large so that
10789 the bar might not be in the window. */
10790 if (cursor_glyph->type == IMAGE_GLYPH)
10791 {
10792 struct glyph_row *row;
10793 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10794 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10795 }
10796 else
10797 {
06a2c219
GM
10798 xgcv.background = f->output_data.x->cursor_pixel;
10799 xgcv.foreground = f->output_data.x->cursor_pixel;
10800 xgcv.graphics_exposures = 0;
10801 mask = GCForeground | GCBackground | GCGraphicsExposures;
10802 dpy = FRAME_X_DISPLAY (f);
10803 window = FRAME_X_WINDOW (f);
10804 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
92f424df 10805
06a2c219
GM
10806 if (gc)
10807 XChangeGC (dpy, gc, mask, &xgcv);
10808 else
10809 {
10810 gc = XCreateGC (dpy, window, mask, &xgcv);
10811 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10812 }
92f424df 10813
f02d8aa0
GM
10814 if (width < 0)
10815 width = f->output_data.x->cursor_width;
92f424df 10816
06a2c219
GM
10817 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10818 x_clip_to_row (w, row, gc, 0);
10819 XFillRectangle (dpy, window, gc,
10820 x,
10821 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10822 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10823 row->height);
10824 XSetClipMask (dpy, gc, None);
10825 }
dc6f92b8
JB
10826}
10827
06a2c219
GM
10828
10829/* Clear the cursor of window W to background color, and mark the
10830 cursor as not shown. This is used when the text where the cursor
10831 is is about to be rewritten. */
10832
dc6f92b8 10833static void
06a2c219
GM
10834x_clear_cursor (w)
10835 struct window *w;
dc6f92b8 10836{
06a2c219
GM
10837 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10838 x_update_window_cursor (w, 0);
10839}
90e65f07 10840
dbc4e1c1 10841
06a2c219
GM
10842/* Draw the cursor glyph of window W in glyph row ROW. See the
10843 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10844
06a2c219
GM
10845static void
10846x_draw_phys_cursor_glyph (w, row, hl)
10847 struct window *w;
10848 struct glyph_row *row;
10849 enum draw_glyphs_face hl;
10850{
10851 /* If cursor hpos is out of bounds, don't draw garbage. This can
10852 happen in mini-buffer windows when switching between echo area
10853 glyphs and mini-buffer. */
10854 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10855 {
10856 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10857 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10858 hl, 0, 0, 0);
10859
10860 /* When we erase the cursor, and ROW is overlapped by other
10861 rows, make sure that these overlapping parts of other rows
10862 are redrawn. */
10863 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10864 {
10865 if (row > w->current_matrix->rows
10866 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10867 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10868
10869 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10870 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10871 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10872 }
10873 }
06a2c219 10874}
dbc4e1c1 10875
eea6af04 10876
06a2c219 10877/* Erase the image of a cursor of window W from the screen. */
eea6af04 10878
06a2c219
GM
10879static void
10880x_erase_phys_cursor (w)
10881 struct window *w;
10882{
10883 struct frame *f = XFRAME (w->frame);
10884 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10885 int hpos = w->phys_cursor.hpos;
10886 int vpos = w->phys_cursor.vpos;
10887 int mouse_face_here_p = 0;
10888 struct glyph_matrix *active_glyphs = w->current_matrix;
10889 struct glyph_row *cursor_row;
10890 struct glyph *cursor_glyph;
10891 enum draw_glyphs_face hl;
10892
10893 /* No cursor displayed or row invalidated => nothing to do on the
10894 screen. */
10895 if (w->phys_cursor_type == NO_CURSOR)
10896 goto mark_cursor_off;
10897
10898 /* VPOS >= active_glyphs->nrows means that window has been resized.
10899 Don't bother to erase the cursor. */
10900 if (vpos >= active_glyphs->nrows)
10901 goto mark_cursor_off;
10902
10903 /* If row containing cursor is marked invalid, there is nothing we
10904 can do. */
10905 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10906 if (!cursor_row->enabled_p)
10907 goto mark_cursor_off;
10908
10909 /* This can happen when the new row is shorter than the old one.
10910 In this case, either x_draw_glyphs or clear_end_of_line
10911 should have cleared the cursor. Note that we wouldn't be
10912 able to erase the cursor in this case because we don't have a
10913 cursor glyph at hand. */
10914 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10915 goto mark_cursor_off;
10916
10917 /* If the cursor is in the mouse face area, redisplay that when
10918 we clear the cursor. */
8801a864
KR
10919 if (! NILP (dpyinfo->mouse_face_window)
10920 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10921 && (vpos > dpyinfo->mouse_face_beg_row
10922 || (vpos == dpyinfo->mouse_face_beg_row
10923 && hpos >= dpyinfo->mouse_face_beg_col))
10924 && (vpos < dpyinfo->mouse_face_end_row
10925 || (vpos == dpyinfo->mouse_face_end_row
10926 && hpos < dpyinfo->mouse_face_end_col))
10927 /* Don't redraw the cursor's spot in mouse face if it is at the
10928 end of a line (on a newline). The cursor appears there, but
10929 mouse highlighting does not. */
10930 && cursor_row->used[TEXT_AREA] > hpos)
10931 mouse_face_here_p = 1;
10932
10933 /* Maybe clear the display under the cursor. */
10934 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10935 {
10936 int x;
045dee35 10937 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10938
06a2c219
GM
10939 cursor_glyph = get_phys_cursor_glyph (w);
10940 if (cursor_glyph == NULL)
10941 goto mark_cursor_off;
dbc4e1c1 10942
06a2c219
GM
10943 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10944
c5e6e06b
GM
10945 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10946 x,
10947 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
10948 cursor_row->y)),
10949 cursor_glyph->pixel_width,
10950 cursor_row->visible_height,
10951 False);
dbc4e1c1 10952 }
06a2c219
GM
10953
10954 /* Erase the cursor by redrawing the character underneath it. */
10955 if (mouse_face_here_p)
10956 hl = DRAW_MOUSE_FACE;
10957 else if (cursor_row->inverse_p)
10958 hl = DRAW_INVERSE_VIDEO;
10959 else
10960 hl = DRAW_NORMAL_TEXT;
10961 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10962
06a2c219
GM
10963 mark_cursor_off:
10964 w->phys_cursor_on_p = 0;
10965 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10966}
10967
10968
06a2c219
GM
10969/* Display or clear cursor of window W. If ON is zero, clear the
10970 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10971 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10972
06a2c219
GM
10973void
10974x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10975 struct window *w;
10976 int on, hpos, vpos, x, y;
dbc4e1c1 10977{
06a2c219
GM
10978 struct frame *f = XFRAME (w->frame);
10979 int new_cursor_type;
f02d8aa0 10980 int new_cursor_width;
06a2c219
GM
10981 struct glyph_matrix *current_glyphs;
10982 struct glyph_row *glyph_row;
10983 struct glyph *glyph;
dbc4e1c1 10984
49d838ea 10985 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10986 windows and frames; in the latter case, the frame or window may
10987 be in the midst of changing its size, and x and y may be off the
10988 window. */
10989 if (! FRAME_VISIBLE_P (f)
10990 || FRAME_GARBAGED_P (f)
10991 || vpos >= w->current_matrix->nrows
10992 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10993 return;
10994
10995 /* If cursor is off and we want it off, return quickly. */
06a2c219 10996 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10997 return;
10998
06a2c219
GM
10999 current_glyphs = w->current_matrix;
11000 glyph_row = MATRIX_ROW (current_glyphs, vpos);
11001 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
11002
11003 /* If cursor row is not enabled, we don't really know where to
11004 display the cursor. */
11005 if (!glyph_row->enabled_p)
11006 {
11007 w->phys_cursor_on_p = 0;
11008 return;
11009 }
11010
11011 xassert (interrupt_input_blocked);
11012
11013 /* Set new_cursor_type to the cursor we want to be displayed. In a
11014 mini-buffer window, we want the cursor only to appear if we are
11015 reading input from this window. For the selected window, we want
11016 the cursor type given by the frame parameter. If explicitly
11017 marked off, draw no cursor. In all other cases, we want a hollow
11018 box cursor. */
f02d8aa0 11019 new_cursor_width = -1;
9b4a7047
GM
11020 if (cursor_in_echo_area
11021 && FRAME_HAS_MINIBUF_P (f)
11022 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 11023 {
9b4a7047
GM
11024 if (w == XWINDOW (echo_area_window))
11025 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
11026 else
11027 new_cursor_type = HOLLOW_BOX_CURSOR;
11028 }
06a2c219 11029 else
9b4a7047 11030 {
7a58ab59
GM
11031 if (f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
11032 || w != XWINDOW (f->selected_window))
9b4a7047 11033 {
e55a0b79
GM
11034 extern int cursor_in_non_selected_windows;
11035
5cefa566
GM
11036 if (MINI_WINDOW_P (w)
11037 || !cursor_in_non_selected_windows
11038 || NILP (XBUFFER (w->buffer)->cursor_type))
9b4a7047
GM
11039 new_cursor_type = NO_CURSOR;
11040 else
11041 new_cursor_type = HOLLOW_BOX_CURSOR;
11042 }
11043 else if (w->cursor_off_p)
11044 new_cursor_type = NO_CURSOR;
11045 else
f02d8aa0
GM
11046 {
11047 struct buffer *b = XBUFFER (w->buffer);
11048
11049 if (EQ (b->cursor_type, Qt))
11050 new_cursor_type = FRAME_DESIRED_CURSOR (f);
11051 else
11052 new_cursor_type = x_specified_cursor_type (b->cursor_type,
11053 &new_cursor_width);
11054 }
9b4a7047 11055 }
06a2c219
GM
11056
11057 /* If cursor is currently being shown and we don't want it to be or
11058 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 11059 erase it. */
06a2c219 11060 if (w->phys_cursor_on_p
dc6f92b8 11061 && (!on
06a2c219
GM
11062 || w->phys_cursor.x != x
11063 || w->phys_cursor.y != y
11064 || new_cursor_type != w->phys_cursor_type))
11065 x_erase_phys_cursor (w);
11066
11067 /* If the cursor is now invisible and we want it to be visible,
11068 display it. */
11069 if (on && !w->phys_cursor_on_p)
11070 {
11071 w->phys_cursor_ascent = glyph_row->ascent;
11072 w->phys_cursor_height = glyph_row->height;
11073
11074 /* Set phys_cursor_.* before x_draw_.* is called because some
11075 of them may need the information. */
11076 w->phys_cursor.x = x;
11077 w->phys_cursor.y = glyph_row->y;
11078 w->phys_cursor.hpos = hpos;
11079 w->phys_cursor.vpos = vpos;
11080 w->phys_cursor_type = new_cursor_type;
11081 w->phys_cursor_on_p = 1;
11082
11083 switch (new_cursor_type)
dc6f92b8 11084 {
06a2c219
GM
11085 case HOLLOW_BOX_CURSOR:
11086 x_draw_hollow_cursor (w, glyph_row);
11087 break;
11088
11089 case FILLED_BOX_CURSOR:
11090 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
11091 break;
11092
11093 case BAR_CURSOR:
f02d8aa0 11094 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
11095 break;
11096
11097 case NO_CURSOR:
11098 break;
dc6f92b8 11099
06a2c219
GM
11100 default:
11101 abort ();
11102 }
59ddecde
GM
11103
11104#ifdef HAVE_X_I18N
11105 if (w == XWINDOW (f->selected_window))
11106 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
11107 xic_set_preeditarea (w, x, y);
11108#endif
dc6f92b8
JB
11109 }
11110
06a2c219 11111#ifndef XFlush
f676886a 11112 if (updating_frame != f)
334208b7 11113 XFlush (FRAME_X_DISPLAY (f));
06a2c219 11114#endif
dc6f92b8
JB
11115}
11116
06a2c219
GM
11117
11118/* Display the cursor on window W, or clear it. X and Y are window
11119 relative pixel coordinates. HPOS and VPOS are glyph matrix
11120 positions. If W is not the selected window, display a hollow
11121 cursor. ON non-zero means display the cursor at X, Y which
11122 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 11123
dfcf069d 11124void
06a2c219
GM
11125x_display_cursor (w, on, hpos, vpos, x, y)
11126 struct window *w;
11127 int on, hpos, vpos, x, y;
dc6f92b8 11128{
f94397b5 11129 BLOCK_INPUT;
06a2c219 11130 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
11131 UNBLOCK_INPUT;
11132}
11133
06a2c219
GM
11134
11135/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
11136 Don't change the cursor's position. */
11137
dfcf069d 11138void
06a2c219 11139x_update_cursor (f, on_p)
5d46f928 11140 struct frame *f;
5d46f928 11141{
06a2c219
GM
11142 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
11143}
11144
11145
11146/* Call x_update_window_cursor with parameter ON_P on all leaf windows
11147 in the window tree rooted at W. */
11148
11149static void
11150x_update_cursor_in_window_tree (w, on_p)
11151 struct window *w;
11152 int on_p;
11153{
11154 while (w)
11155 {
11156 if (!NILP (w->hchild))
11157 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
11158 else if (!NILP (w->vchild))
11159 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
11160 else
11161 x_update_window_cursor (w, on_p);
11162
11163 w = NILP (w->next) ? 0 : XWINDOW (w->next);
11164 }
11165}
5d46f928 11166
f94397b5 11167
06a2c219
GM
11168/* Switch the display of W's cursor on or off, according to the value
11169 of ON. */
11170
11171static void
11172x_update_window_cursor (w, on)
11173 struct window *w;
11174 int on;
11175{
16b5d424
GM
11176 /* Don't update cursor in windows whose frame is in the process
11177 of being deleted. */
11178 if (w->current_matrix)
11179 {
11180 BLOCK_INPUT;
11181 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
11182 w->phys_cursor.x, w->phys_cursor.y);
11183 UNBLOCK_INPUT;
11184 }
dc6f92b8 11185}
06a2c219
GM
11186
11187
11188
dc6f92b8
JB
11189\f
11190/* Icons. */
11191
f676886a 11192/* Refresh bitmap kitchen sink icon for frame F
06a2c219 11193 when we get an expose event for it. */
dc6f92b8 11194
dfcf069d 11195void
f676886a
JB
11196refreshicon (f)
11197 struct frame *f;
dc6f92b8 11198{
06a2c219 11199 /* Normally, the window manager handles this function. */
dc6f92b8
JB
11200}
11201
dbc4e1c1 11202/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
11203
11204int
990ba854 11205x_bitmap_icon (f, file)
f676886a 11206 struct frame *f;
990ba854 11207 Lisp_Object file;
dc6f92b8 11208{
06a2c219 11209 int bitmap_id;
dc6f92b8 11210
c118dd06 11211 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11212 return 1;
11213
990ba854 11214 /* Free up our existing icon bitmap if any. */
7556890b
RS
11215 if (f->output_data.x->icon_bitmap > 0)
11216 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11217 f->output_data.x->icon_bitmap = 0;
990ba854
RS
11218
11219 if (STRINGP (file))
7f2ae036
RS
11220 bitmap_id = x_create_bitmap_from_file (f, file);
11221 else
11222 {
990ba854 11223 /* Create the GNU bitmap if necessary. */
5bf01b68 11224 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
11225 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
11226 = x_create_bitmap_from_data (f, gnu_bits,
11227 gnu_width, gnu_height);
990ba854
RS
11228
11229 /* The first time we create the GNU bitmap,
06a2c219 11230 this increments the ref-count one extra time.
990ba854
RS
11231 As a result, the GNU bitmap is never freed.
11232 That way, we don't have to worry about allocating it again. */
334208b7 11233 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 11234
334208b7 11235 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
11236 }
11237
11238 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 11239 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
11240
11241 return 0;
11242}
11243
11244
1be2d067
KH
11245/* Make the x-window of frame F use a rectangle with text.
11246 Use ICON_NAME as the text. */
dc6f92b8
JB
11247
11248int
f676886a
JB
11249x_text_icon (f, icon_name)
11250 struct frame *f;
dc6f92b8
JB
11251 char *icon_name;
11252{
c118dd06 11253 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
11254 return 1;
11255
1be2d067
KH
11256#ifdef HAVE_X11R4
11257 {
11258 XTextProperty text;
11259 text.value = (unsigned char *) icon_name;
11260 text.encoding = XA_STRING;
11261 text.format = 8;
11262 text.nitems = strlen (icon_name);
11263#ifdef USE_X_TOOLKIT
7556890b 11264 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
11265 &text);
11266#else /* not USE_X_TOOLKIT */
11267 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
11268#endif /* not USE_X_TOOLKIT */
11269 }
11270#else /* not HAVE_X11R4 */
11271 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
11272#endif /* not HAVE_X11R4 */
58769bee 11273
7556890b
RS
11274 if (f->output_data.x->icon_bitmap > 0)
11275 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
11276 f->output_data.x->icon_bitmap = 0;
b1c884c3 11277 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
11278
11279 return 0;
11280}
11281\f
e99db5a1
RS
11282#define X_ERROR_MESSAGE_SIZE 200
11283
11284/* If non-nil, this should be a string.
11285 It means catch X errors and store the error message in this string. */
11286
11287static Lisp_Object x_error_message_string;
11288
11289/* An X error handler which stores the error message in
11290 x_error_message_string. This is called from x_error_handler if
11291 x_catch_errors is in effect. */
11292
06a2c219 11293static void
e99db5a1
RS
11294x_error_catcher (display, error)
11295 Display *display;
11296 XErrorEvent *error;
11297{
11298 XGetErrorText (display, error->error_code,
11299 XSTRING (x_error_message_string)->data,
11300 X_ERROR_MESSAGE_SIZE);
11301}
11302
11303/* Begin trapping X errors for display DPY. Actually we trap X errors
11304 for all displays, but DPY should be the display you are actually
11305 operating on.
11306
11307 After calling this function, X protocol errors no longer cause
11308 Emacs to exit; instead, they are recorded in the string
11309 stored in x_error_message_string.
11310
11311 Calling x_check_errors signals an Emacs error if an X error has
11312 occurred since the last call to x_catch_errors or x_check_errors.
11313
11314 Calling x_uncatch_errors resumes the normal error handling. */
11315
11316void x_check_errors ();
11317static Lisp_Object x_catch_errors_unwind ();
11318
11319int
11320x_catch_errors (dpy)
11321 Display *dpy;
11322{
11323 int count = specpdl_ptr - specpdl;
11324
11325 /* Make sure any errors from previous requests have been dealt with. */
11326 XSync (dpy, False);
11327
11328 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
11329
11330 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
11331 XSTRING (x_error_message_string)->data[0] = 0;
11332
11333 return count;
11334}
11335
11336/* Unbind the binding that we made to check for X errors. */
11337
11338static Lisp_Object
11339x_catch_errors_unwind (old_val)
11340 Lisp_Object old_val;
11341{
11342 x_error_message_string = old_val;
11343 return Qnil;
11344}
11345
11346/* If any X protocol errors have arrived since the last call to
11347 x_catch_errors or x_check_errors, signal an Emacs error using
11348 sprintf (a buffer, FORMAT, the x error message text) as the text. */
11349
11350void
11351x_check_errors (dpy, format)
11352 Display *dpy;
11353 char *format;
11354{
11355 /* Make sure to catch any errors incurred so far. */
11356 XSync (dpy, False);
11357
11358 if (XSTRING (x_error_message_string)->data[0])
11359 error (format, XSTRING (x_error_message_string)->data);
11360}
11361
9829ddba
RS
11362/* Nonzero if we had any X protocol errors
11363 since we did x_catch_errors on DPY. */
e99db5a1
RS
11364
11365int
11366x_had_errors_p (dpy)
11367 Display *dpy;
11368{
11369 /* Make sure to catch any errors incurred so far. */
11370 XSync (dpy, False);
11371
11372 return XSTRING (x_error_message_string)->data[0] != 0;
11373}
11374
9829ddba
RS
11375/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11376
06a2c219 11377void
9829ddba
RS
11378x_clear_errors (dpy)
11379 Display *dpy;
11380{
11381 XSTRING (x_error_message_string)->data[0] = 0;
11382}
11383
e99db5a1
RS
11384/* Stop catching X protocol errors and let them make Emacs die.
11385 DPY should be the display that was passed to x_catch_errors.
11386 COUNT should be the value that was returned by
11387 the corresponding call to x_catch_errors. */
11388
11389void
11390x_uncatch_errors (dpy, count)
11391 Display *dpy;
11392 int count;
11393{
11394 unbind_to (count, Qnil);
11395}
11396
11397#if 0
11398static unsigned int x_wire_count;
11399x_trace_wire ()
11400{
11401 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11402}
11403#endif /* ! 0 */
11404
11405\f
11406/* Handle SIGPIPE, which can happen when the connection to a server
11407 simply goes away. SIGPIPE is handled by x_connection_signal.
11408 Don't need to do anything, because the write which caused the
11409 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 11410 which will do the appropriate cleanup for us. */
e99db5a1
RS
11411
11412static SIGTYPE
11413x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 11414 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
11415{
11416#ifdef USG
11417 /* USG systems forget handlers when they are used;
11418 must reestablish each time */
11419 signal (signalnum, x_connection_signal);
11420#endif /* USG */
11421}
0da1ab50 11422
e99db5a1 11423\f
0da1ab50
GM
11424/************************************************************************
11425 Handling X errors
11426 ************************************************************************/
4746118a 11427
0da1ab50
GM
11428/* Handle the loss of connection to display DPY. ERROR_MESSAGE is
11429 the text of an error message that lead to the connection loss. */
16bd92ea 11430
4746118a 11431static SIGTYPE
5978125e
GM
11432x_connection_closed (dpy, error_message)
11433 Display *dpy;
7a13e894 11434 char *error_message;
4746118a 11435{
5978125e 11436 struct x_display_info *dpyinfo = x_display_info_for_display (dpy);
7a13e894 11437 Lisp_Object frame, tail;
0da1ab50
GM
11438 int count;
11439 char *msg;
11440
11441 msg = (char *) alloca (strlen (error_message) + 1);
11442 strcpy (msg, error_message);
1a532e54
GM
11443 handling_signal = 0;
11444
0da1ab50
GM
11445 /* Prevent being called recursively because of an error condition
11446 below. Otherwise, we might end up with printing ``can't find per
11447 display information'' in the recursive call instead of printing
11448 the original message here. */
11449 count = x_catch_errors (dpy);
11450
8a4f36cc
GM
11451 /* We have to close the display to inform Xt that it doesn't
11452 exist anymore. If we don't, Xt will continue to wait for
11453 events from the display. As a consequence, a sequence of
11454
11455 M-x make-frame-on-display RET :1 RET
11456 ...kill the new frame, so that we get an IO error...
11457 M-x make-frame-on-display RET :1 RET
11458
11459 will indefinitely wait in Xt for events for display `:1', opened
11460 in the first class to make-frame-on-display.
6186a4a0 11461
8a4f36cc
GM
11462 Closing the display is reported to lead to a bus error on
11463 OpenWindows in certain situations. I suspect that is a bug
11464 in OpenWindows. I don't know how to cicumvent it here. */
11465
f613a4c8 11466#ifdef USE_X_TOOLKIT
ae24cb3b
GM
11467 /* If DPYINFO is null, this means we didn't open the display
11468 in the first place, so don't try to close it. */
11469 if (dpyinfo)
11470 XtCloseDisplay (dpy);
f613a4c8 11471#endif
adabc3a9 11472
8a4f36cc 11473 /* Indicate that this display is dead. */
9e80b57d
KR
11474 if (dpyinfo)
11475 dpyinfo->display = 0;
6186a4a0 11476
06a2c219 11477 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
11478 that are on the dead display. */
11479 FOR_EACH_FRAME (tail, frame)
11480 {
11481 Lisp_Object minibuf_frame;
11482 minibuf_frame
11483 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
11484 if (FRAME_X_P (XFRAME (frame))
11485 && FRAME_X_P (XFRAME (minibuf_frame))
11486 && ! EQ (frame, minibuf_frame)
11487 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
11488 Fdelete_frame (frame, Qt);
11489 }
11490
11491 /* Now delete all remaining frames on the dead display.
06a2c219 11492 We are now sure none of these is used as the mini-buffer
7a13e894
RS
11493 for another frame that we need to delete. */
11494 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
11495 if (FRAME_X_P (XFRAME (frame))
11496 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
11497 {
11498 /* Set this to t so that Fdelete_frame won't get confused
11499 trying to find a replacement. */
11500 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11501 Fdelete_frame (frame, Qt);
11502 }
7a13e894 11503
482a1bd2
KH
11504 if (dpyinfo)
11505 x_delete_display (dpyinfo);
7a13e894 11506
0da1ab50
GM
11507 x_uncatch_errors (dpy, count);
11508
7a13e894
RS
11509 if (x_display_list == 0)
11510 {
0da1ab50 11511 fprintf (stderr, "%s\n", msg);
7a13e894
RS
11512 shut_down_emacs (0, 0, Qnil);
11513 exit (70);
11514 }
12ba150f 11515
7a13e894
RS
11516 /* Ordinary stack unwind doesn't deal with these. */
11517#ifdef SIGIO
11518 sigunblock (sigmask (SIGIO));
11519#endif
11520 sigunblock (sigmask (SIGALRM));
11521 TOTALLY_UNBLOCK_INPUT;
11522
aa4d9a9e 11523 clear_waiting_for_input ();
0da1ab50 11524 error ("%s", msg);
4746118a
JB
11525}
11526
0da1ab50 11527
7a13e894
RS
11528/* This is the usual handler for X protocol errors.
11529 It kills all frames on the display that we got the error for.
11530 If that was the only one, it prints an error message and kills Emacs. */
11531
06a2c219 11532static void
c118dd06
JB
11533x_error_quitter (display, error)
11534 Display *display;
11535 XErrorEvent *error;
11536{
7a13e894 11537 char buf[256], buf1[356];
dc6f92b8 11538
58769bee 11539 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 11540 original error handler. */
dc6f92b8 11541
c118dd06 11542 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 11543 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 11544 buf, error->request_code);
7a13e894 11545 x_connection_closed (display, buf1);
dc6f92b8
JB
11546}
11547
0da1ab50 11548
e99db5a1
RS
11549/* This is the first-level handler for X protocol errors.
11550 It calls x_error_quitter or x_error_catcher. */
7a13e894 11551
8922af5f 11552static int
e99db5a1 11553x_error_handler (display, error)
8922af5f 11554 Display *display;
e99db5a1 11555 XErrorEvent *error;
8922af5f 11556{
e99db5a1
RS
11557 if (! NILP (x_error_message_string))
11558 x_error_catcher (display, error);
11559 else
11560 x_error_quitter (display, error);
06a2c219 11561 return 0;
f9e24cb9 11562}
c118dd06 11563
e99db5a1
RS
11564/* This is the handler for X IO errors, always.
11565 It kills all frames on the display that we lost touch with.
11566 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 11567
c118dd06 11568static int
e99db5a1 11569x_io_error_quitter (display)
c118dd06 11570 Display *display;
c118dd06 11571{
e99db5a1 11572 char buf[256];
dc6f92b8 11573
e99db5a1
RS
11574 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11575 x_connection_closed (display, buf);
06a2c219 11576 return 0;
dc6f92b8 11577}
dc6f92b8 11578\f
f451eb13
JB
11579/* Changing the font of the frame. */
11580
76bcdf39
RS
11581/* Give frame F the font named FONTNAME as its default font, and
11582 return the full name of that font. FONTNAME may be a wildcard
11583 pattern; in that case, we choose some font that fits the pattern.
11584 The return value shows which font we chose. */
11585
b5cf7a0e 11586Lisp_Object
f676886a
JB
11587x_new_font (f, fontname)
11588 struct frame *f;
dc6f92b8
JB
11589 register char *fontname;
11590{
dc43ef94 11591 struct font_info *fontp
ee569018 11592 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 11593
dc43ef94
KH
11594 if (!fontp)
11595 return Qnil;
2224a5fc 11596
dc43ef94 11597 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11598 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11599 f->output_data.x->fontset = -1;
11600
b2cad826
KH
11601 /* Compute the scroll bar width in character columns. */
11602 if (f->scroll_bar_pixel_width > 0)
11603 {
7556890b 11604 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11605 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11606 }
11607 else
4e61bddf
RS
11608 {
11609 int wid = FONT_WIDTH (f->output_data.x->font);
11610 f->scroll_bar_cols = (14 + wid - 1) / wid;
11611 }
b2cad826 11612
f676886a 11613 /* Now make the frame display the given font. */
c118dd06 11614 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11615 {
7556890b
RS
11616 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11617 f->output_data.x->font->fid);
11618 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11619 f->output_data.x->font->fid);
11620 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11621 f->output_data.x->font->fid);
f676886a 11622
a27f9f86 11623 frame_update_line_height (f);
3497f73e
GM
11624
11625 /* Don't change the size of a tip frame; there's no point in
11626 doing it because it's done in Fx_show_tip, and it leads to
11627 problems because the tip frame has no widget. */
11628 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
11629 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11630 }
a27f9f86
RS
11631 else
11632 /* If we are setting a new frame's font for the first time,
11633 there are no faces yet, so this font's height is the line height. */
7556890b 11634 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11635
dc43ef94
KH
11636 return build_string (fontp->full_name);
11637}
11638
11639/* Give frame F the fontset named FONTSETNAME as its default font, and
11640 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11641 pattern; in that case, we choose some fontset that fits the pattern.
11642 The return value shows which fontset we chose. */
b5cf7a0e 11643
dc43ef94
KH
11644Lisp_Object
11645x_new_fontset (f, fontsetname)
11646 struct frame *f;
11647 char *fontsetname;
11648{
ee569018 11649 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11650 Lisp_Object result;
b5cf7a0e 11651
dc43ef94
KH
11652 if (fontset < 0)
11653 return Qnil;
b5cf7a0e 11654
2da424f1
KH
11655 if (f->output_data.x->fontset == fontset)
11656 /* This fontset is already set in frame F. There's nothing more
11657 to do. */
ee569018 11658 return fontset_name (fontset);
dc43ef94 11659
ee569018 11660 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11661
11662 if (!STRINGP (result))
11663 /* Can't load ASCII font. */
11664 return Qnil;
11665
11666 /* Since x_new_font doesn't update any fontset information, do it now. */
11667 f->output_data.x->fontset = fontset;
dc43ef94 11668
f5d11644
GM
11669#ifdef HAVE_X_I18N
11670 if (FRAME_XIC (f)
11671 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11672 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11673#endif
11674
dc43ef94 11675 return build_string (fontsetname);
dc6f92b8 11676}
f5d11644
GM
11677
11678\f
11679/***********************************************************************
11680 X Input Methods
11681 ***********************************************************************/
11682
11683#ifdef HAVE_X_I18N
11684
11685#ifdef HAVE_X11R6
11686
11687/* XIM destroy callback function, which is called whenever the
11688 connection to input method XIM dies. CLIENT_DATA contains a
11689 pointer to the x_display_info structure corresponding to XIM. */
11690
11691static void
11692xim_destroy_callback (xim, client_data, call_data)
11693 XIM xim;
11694 XPointer client_data;
11695 XPointer call_data;
11696{
11697 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11698 Lisp_Object frame, tail;
11699
11700 BLOCK_INPUT;
11701
11702 /* No need to call XDestroyIC.. */
11703 FOR_EACH_FRAME (tail, frame)
11704 {
11705 struct frame *f = XFRAME (frame);
11706 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11707 {
11708 FRAME_XIC (f) = NULL;
11709 if (FRAME_XIC_FONTSET (f))
11710 {
11711 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11712 FRAME_XIC_FONTSET (f) = NULL;
11713 }
11714 }
11715 }
11716
11717 /* No need to call XCloseIM. */
11718 dpyinfo->xim = NULL;
11719 XFree (dpyinfo->xim_styles);
11720 UNBLOCK_INPUT;
11721}
11722
11723#endif /* HAVE_X11R6 */
11724
11725/* Open the connection to the XIM server on display DPYINFO.
11726 RESOURCE_NAME is the resource name Emacs uses. */
11727
11728static void
11729xim_open_dpy (dpyinfo, resource_name)
11730 struct x_display_info *dpyinfo;
11731 char *resource_name;
11732{
287f7dd6 11733#ifdef USE_XIM
f5d11644
GM
11734 XIM xim;
11735
11736 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11737 dpyinfo->xim = xim;
11738
11739 if (xim)
11740 {
f5d11644
GM
11741#ifdef HAVE_X11R6
11742 XIMCallback destroy;
11743#endif
11744
11745 /* Get supported styles and XIM values. */
11746 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11747
11748#ifdef HAVE_X11R6
11749 destroy.callback = xim_destroy_callback;
11750 destroy.client_data = (XPointer)dpyinfo;
68642df6 11751 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11752 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11753#endif
11754 }
287f7dd6
GM
11755
11756#else /* not USE_XIM */
11757 dpyinfo->xim = NULL;
11758#endif /* not USE_XIM */
f5d11644
GM
11759}
11760
11761
b9de836c 11762#ifdef HAVE_X11R6_XIM
f5d11644
GM
11763
11764struct xim_inst_t
11765{
11766 struct x_display_info *dpyinfo;
11767 char *resource_name;
11768};
11769
11770/* XIM instantiate callback function, which is called whenever an XIM
11771 server is available. DISPLAY is teh display of the XIM.
11772 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11773 when the callback was registered. */
11774
11775static void
11776xim_instantiate_callback (display, client_data, call_data)
11777 Display *display;
11778 XPointer client_data;
11779 XPointer call_data;
11780{
11781 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11782 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11783
11784 /* We don't support multiple XIM connections. */
11785 if (dpyinfo->xim)
11786 return;
11787
11788 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11789
11790 /* Create XIC for the existing frames on the same display, as long
11791 as they have no XIC. */
11792 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11793 {
11794 Lisp_Object tail, frame;
11795
11796 BLOCK_INPUT;
11797 FOR_EACH_FRAME (tail, frame)
11798 {
11799 struct frame *f = XFRAME (frame);
11800
11801 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11802 if (FRAME_XIC (f) == NULL)
11803 {
11804 create_frame_xic (f);
11805 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11806 xic_set_statusarea (f);
11807 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11808 {
11809 struct window *w = XWINDOW (f->selected_window);
11810 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11811 }
11812 }
11813 }
11814
11815 UNBLOCK_INPUT;
11816 }
11817}
11818
b9de836c 11819#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11820
11821
11822/* Open a connection to the XIM server on display DPYINFO.
11823 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11824 connection only at the first time. On X11R6, open the connection
11825 in the XIM instantiate callback function. */
11826
11827static void
11828xim_initialize (dpyinfo, resource_name)
11829 struct x_display_info *dpyinfo;
11830 char *resource_name;
11831{
287f7dd6 11832#ifdef USE_XIM
b9de836c 11833#ifdef HAVE_X11R6_XIM
f5d11644
GM
11834 struct xim_inst_t *xim_inst;
11835 int len;
11836
11837 dpyinfo->xim = NULL;
11838 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11839 xim_inst->dpyinfo = dpyinfo;
11840 len = strlen (resource_name);
11841 xim_inst->resource_name = (char *) xmalloc (len + 1);
11842 bcopy (resource_name, xim_inst->resource_name, len + 1);
11843 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11844 resource_name, EMACS_CLASS,
11845 xim_instantiate_callback,
2ebb2f8b
DL
11846 /* Fixme: This is XPointer in
11847 XFree86 but (XPointer *) on
11848 Tru64, at least. */
11849 (XPointer) xim_inst);
b9de836c 11850#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11851 dpyinfo->xim = NULL;
11852 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11853#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11854
11855#else /* not USE_XIM */
11856 dpyinfo->xim = NULL;
11857#endif /* not USE_XIM */
f5d11644
GM
11858}
11859
11860
11861/* Close the connection to the XIM server on display DPYINFO. */
11862
11863static void
11864xim_close_dpy (dpyinfo)
11865 struct x_display_info *dpyinfo;
11866{
287f7dd6 11867#ifdef USE_XIM
b9de836c 11868#ifdef HAVE_X11R6_XIM
8a4f36cc
GM
11869 if (dpyinfo->display)
11870 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11871 NULL, EMACS_CLASS,
11872 xim_instantiate_callback, NULL);
b9de836c 11873#endif /* not HAVE_X11R6_XIM */
8a4f36cc
GM
11874 if (dpyinfo->display)
11875 XCloseIM (dpyinfo->xim);
f5d11644
GM
11876 dpyinfo->xim = NULL;
11877 XFree (dpyinfo->xim_styles);
287f7dd6 11878#endif /* USE_XIM */
f5d11644
GM
11879}
11880
b9de836c 11881#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11882
11883
dc6f92b8 11884\f
2e365682
RS
11885/* Calculate the absolute position in frame F
11886 from its current recorded position values and gravity. */
11887
dfcf069d 11888void
43bca5d5 11889x_calc_absolute_position (f)
f676886a 11890 struct frame *f;
dc6f92b8 11891{
06a2c219 11892 Window child;
6dba1858 11893 int win_x = 0, win_y = 0;
7556890b 11894 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11895 int this_window;
11896
9829ddba
RS
11897 /* We have nothing to do if the current position
11898 is already for the top-left corner. */
11899 if (! ((flags & XNegative) || (flags & YNegative)))
11900 return;
11901
c81412a0 11902#ifdef USE_X_TOOLKIT
7556890b 11903 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11904#else
11905 this_window = FRAME_X_WINDOW (f);
11906#endif
6dba1858
RS
11907
11908 /* Find the position of the outside upper-left corner of
9829ddba
RS
11909 the inner window, with respect to the outer window.
11910 But do this only if we will need the results. */
7556890b 11911 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11912 {
9829ddba
RS
11913 int count;
11914
6dba1858 11915 BLOCK_INPUT;
9829ddba
RS
11916 count = x_catch_errors (FRAME_X_DISPLAY (f));
11917 while (1)
11918 {
11919 x_clear_errors (FRAME_X_DISPLAY (f));
11920 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11921
11922 /* From-window, to-window. */
11923 this_window,
11924 f->output_data.x->parent_desc,
11925
11926 /* From-position, to-position. */
11927 0, 0, &win_x, &win_y,
11928
11929 /* Child of win. */
11930 &child);
11931 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11932 {
11933 Window newroot, newparent = 0xdeadbeef;
11934 Window *newchildren;
2ebb2f8b 11935 unsigned int nchildren;
9829ddba
RS
11936
11937 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11938 &newparent, &newchildren, &nchildren))
11939 break;
58769bee 11940
7c3c78a3 11941 XFree ((char *) newchildren);
6dba1858 11942
9829ddba
RS
11943 f->output_data.x->parent_desc = newparent;
11944 }
11945 else
11946 break;
11947 }
6dba1858 11948
9829ddba 11949 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11950 UNBLOCK_INPUT;
11951 }
11952
11953 /* Treat negative positions as relative to the leftmost bottommost
11954 position that fits on the screen. */
20f55f9a 11955 if (flags & XNegative)
7556890b 11956 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11957 - 2 * f->output_data.x->border_width - win_x
11958 - PIXEL_WIDTH (f)
11959 + f->output_data.x->left_pos);
dc6f92b8 11960
7708ced0
GM
11961 {
11962 int height = PIXEL_HEIGHT (f);
06a2c219 11963
7708ced0
GM
11964#if defined USE_X_TOOLKIT && defined USE_MOTIF
11965 /* Something is fishy here. When using Motif, starting Emacs with
11966 `-g -0-0', the frame appears too low by a few pixels.
11967
11968 This seems to be so because initially, while Emacs is starting,
11969 the column widget's height and the frame's pixel height are
11970 different. The column widget's height is the right one. In
11971 later invocations, when Emacs is up, the frame's pixel height
11972 is right, though.
11973
11974 It's not obvious where the initial small difference comes from.
11975 2000-12-01, gerd. */
11976
11977 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
06a2c219 11978#endif
2e365682 11979
7708ced0
GM
11980 if (flags & YNegative)
11981 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11982 - 2 * f->output_data.x->border_width
11983 - win_y
11984 - height
11985 + f->output_data.x->top_pos);
11986 }
11987
3a35ab44
RS
11988 /* The left_pos and top_pos
11989 are now relative to the top and left screen edges,
11990 so the flags should correspond. */
7556890b 11991 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11992}
11993
3a35ab44
RS
11994/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11995 to really change the position, and 0 when calling from
11996 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11997 position values). It is -1 when calling from x_set_frame_parameters,
11998 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11999
dfcf069d 12000void
dc05a16b 12001x_set_offset (f, xoff, yoff, change_gravity)
f676886a 12002 struct frame *f;
dc6f92b8 12003 register int xoff, yoff;
dc05a16b 12004 int change_gravity;
dc6f92b8 12005{
4a4cbdd5
KH
12006 int modified_top, modified_left;
12007
aa3ff7c9 12008 if (change_gravity > 0)
3a35ab44 12009 {
7556890b
RS
12010 f->output_data.x->top_pos = yoff;
12011 f->output_data.x->left_pos = xoff;
12012 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 12013 if (xoff < 0)
7556890b 12014 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 12015 if (yoff < 0)
7556890b
RS
12016 f->output_data.x->size_hint_flags |= YNegative;
12017 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 12018 }
43bca5d5 12019 x_calc_absolute_position (f);
dc6f92b8
JB
12020
12021 BLOCK_INPUT;
c32cdd9a 12022 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 12023
7556890b
RS
12024 modified_left = f->output_data.x->left_pos;
12025 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
12026#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
12027 this seems to be unnecessary and incorrect. rms, 4/17/97. */
12028 /* It is a mystery why we need to add the border_width here
12029 when the frame is already visible, but experiment says we do. */
aa3ff7c9 12030 if (change_gravity != 0)
4a4cbdd5 12031 {
7556890b
RS
12032 modified_left += f->output_data.x->border_width;
12033 modified_top += f->output_data.x->border_width;
4a4cbdd5 12034 }
e73ec6fa 12035#endif
4a4cbdd5 12036
3afe33e7 12037#ifdef USE_X_TOOLKIT
7556890b 12038 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 12039 modified_left, modified_top);
3afe33e7 12040#else /* not USE_X_TOOLKIT */
334208b7 12041 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 12042 modified_left, modified_top);
3afe33e7 12043#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12044 UNBLOCK_INPUT;
12045}
12046
dc6f92b8 12047
499b1844
GM
12048/* Change the size of frame F's X window to COLS/ROWS in the case F
12049 doesn't have a widget. If CHANGE_GRAVITY is 1, we change to
12050 top-left-corner window gravity for this size change and subsequent
12051 size changes. Otherwise we leave the window gravity unchanged. */
12052
12053static void
12054x_set_window_size_1 (f, change_gravity, cols, rows)
f676886a 12055 struct frame *f;
bc20ebbf 12056 int change_gravity;
b1c884c3 12057 int cols, rows;
dc6f92b8
JB
12058{
12059 int pixelwidth, pixelheight;
80fd1fe2 12060
b1c884c3 12061 check_frame_size (f, &rows, &cols);
7556890b 12062 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
12063 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
12064 ? 0
12065 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 12066 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 12067 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 12068 f->output_data.x->flags_areas_extra
110859fc 12069 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
12070 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
12071 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 12072
7556890b 12073 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 12074 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 12075
334208b7
RS
12076 XSync (FRAME_X_DISPLAY (f), False);
12077 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
12078 pixelwidth, pixelheight);
b1c884c3
JB
12079
12080 /* Now, strictly speaking, we can't be sure that this is accurate,
12081 but the window manager will get around to dealing with the size
12082 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
12083 ConfigureNotify event gets here.
12084
12085 We could just not bother storing any of this information here,
12086 and let the ConfigureNotify event set everything up, but that
fddd5ceb 12087 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 12088 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
12089 point in the future when the ConfigureNotify event arrives.
12090
12091 We pass 1 for DELAY since we can't run Lisp code inside of
12092 a BLOCK_INPUT. */
7d1e984f 12093 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
12094 PIXEL_WIDTH (f) = pixelwidth;
12095 PIXEL_HEIGHT (f) = pixelheight;
12096
aee9a898
RS
12097 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
12098 receive in the ConfigureNotify event; if we get what we asked
12099 for, then the event won't cause the screen to become garbaged, so
12100 we have to make sure to do it here. */
12101 SET_FRAME_GARBAGED (f);
12102
12103 XFlush (FRAME_X_DISPLAY (f));
499b1844
GM
12104}
12105
12106
12107/* Call this to change the size of frame F's x-window.
12108 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
12109 for this size change and subsequent size changes.
12110 Otherwise we leave the window gravity unchanged. */
aee9a898 12111
499b1844
GM
12112void
12113x_set_window_size (f, change_gravity, cols, rows)
12114 struct frame *f;
12115 int change_gravity;
12116 int cols, rows;
12117{
12118 BLOCK_INPUT;
12119
12120#ifdef USE_X_TOOLKIT
12121
f1f4d345 12122 if (f->output_data.x->widget != NULL)
499b1844
GM
12123 {
12124 /* The x and y position of the widget is clobbered by the
12125 call to XtSetValues within EmacsFrameSetCharSize.
12126 This is a real kludge, but I don't understand Xt so I can't
12127 figure out a correct fix. Can anyone else tell me? -- rms. */
12128 int xpos = f->output_data.x->widget->core.x;
12129 int ypos = f->output_data.x->widget->core.y;
12130 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
12131 f->output_data.x->widget->core.x = xpos;
12132 f->output_data.x->widget->core.y = ypos;
12133 }
12134 else
12135 x_set_window_size_1 (f, change_gravity, cols, rows);
12136
12137#else /* not USE_X_TOOLKIT */
12138
12139 x_set_window_size_1 (f, change_gravity, cols, rows);
12140
aee9a898
RS
12141#endif /* not USE_X_TOOLKIT */
12142
4d73d038 12143 /* If cursor was outside the new size, mark it as off. */
06a2c219 12144 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 12145
aee9a898
RS
12146 /* Clear out any recollection of where the mouse highlighting was,
12147 since it might be in a place that's outside the new frame size.
12148 Actually checking whether it is outside is a pain in the neck,
12149 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 12150 cancel_mouse_face (f);
dbc4e1c1 12151
dc6f92b8
JB
12152 UNBLOCK_INPUT;
12153}
dc6f92b8 12154\f
d047c4eb 12155/* Mouse warping. */
dc6f92b8 12156
9b378208 12157void
f676886a
JB
12158x_set_mouse_position (f, x, y)
12159 struct frame *f;
dc6f92b8
JB
12160 int x, y;
12161{
12162 int pix_x, pix_y;
12163
7556890b
RS
12164 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
12165 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
12166
12167 if (pix_x < 0) pix_x = 0;
12168 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
12169
12170 if (pix_y < 0) pix_y = 0;
12171 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
12172
12173 BLOCK_INPUT;
dc6f92b8 12174
334208b7
RS
12175 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12176 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
12177 UNBLOCK_INPUT;
12178}
12179
9b378208
RS
12180/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
12181
12182void
12183x_set_mouse_pixel_position (f, pix_x, pix_y)
12184 struct frame *f;
12185 int pix_x, pix_y;
12186{
12187 BLOCK_INPUT;
12188
334208b7
RS
12189 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
12190 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
12191 UNBLOCK_INPUT;
12192}
d047c4eb
KH
12193\f
12194/* focus shifting, raising and lowering. */
9b378208 12195
dfcf069d 12196void
f676886a
JB
12197x_focus_on_frame (f)
12198 struct frame *f;
dc6f92b8 12199{
1fb20991 12200#if 0 /* This proves to be unpleasant. */
f676886a 12201 x_raise_frame (f);
1fb20991 12202#endif
6d4238f3
JB
12203#if 0
12204 /* I don't think that the ICCCM allows programs to do things like this
12205 without the interaction of the window manager. Whatever you end up
f676886a 12206 doing with this code, do it to x_unfocus_frame too. */
334208b7 12207 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 12208 RevertToPointerRoot, CurrentTime);
c118dd06 12209#endif /* ! 0 */
dc6f92b8
JB
12210}
12211
dfcf069d 12212void
f676886a
JB
12213x_unfocus_frame (f)
12214 struct frame *f;
dc6f92b8 12215{
6d4238f3 12216#if 0
f676886a 12217 /* Look at the remarks in x_focus_on_frame. */
0f941935 12218 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 12219 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 12220 RevertToPointerRoot, CurrentTime);
c118dd06 12221#endif /* ! 0 */
dc6f92b8
JB
12222}
12223
f676886a 12224/* Raise frame F. */
dc6f92b8 12225
dfcf069d 12226void
f676886a
JB
12227x_raise_frame (f)
12228 struct frame *f;
dc6f92b8 12229{
3a88c238 12230 if (f->async_visible)
dc6f92b8
JB
12231 {
12232 BLOCK_INPUT;
3afe33e7 12233#ifdef USE_X_TOOLKIT
7556890b 12234 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12235#else /* not USE_X_TOOLKIT */
334208b7 12236 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12237#endif /* not USE_X_TOOLKIT */
334208b7 12238 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12239 UNBLOCK_INPUT;
12240 }
12241}
12242
f676886a 12243/* Lower frame F. */
dc6f92b8 12244
dfcf069d 12245void
f676886a
JB
12246x_lower_frame (f)
12247 struct frame *f;
dc6f92b8 12248{
3a88c238 12249 if (f->async_visible)
dc6f92b8
JB
12250 {
12251 BLOCK_INPUT;
3afe33e7 12252#ifdef USE_X_TOOLKIT
7556890b 12253 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 12254#else /* not USE_X_TOOLKIT */
334208b7 12255 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12256#endif /* not USE_X_TOOLKIT */
334208b7 12257 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
12258 UNBLOCK_INPUT;
12259 }
12260}
12261
dbc4e1c1 12262static void
6b0442dc 12263XTframe_raise_lower (f, raise_flag)
dbc4e1c1 12264 FRAME_PTR f;
6b0442dc 12265 int raise_flag;
dbc4e1c1 12266{
6b0442dc 12267 if (raise_flag)
dbc4e1c1
JB
12268 x_raise_frame (f);
12269 else
12270 x_lower_frame (f);
12271}
d047c4eb
KH
12272\f
12273/* Change of visibility. */
dc6f92b8 12274
9382638d
KH
12275/* This tries to wait until the frame is really visible.
12276 However, if the window manager asks the user where to position
12277 the frame, this will return before the user finishes doing that.
12278 The frame will not actually be visible at that time,
12279 but it will become visible later when the window manager
12280 finishes with it. */
12281
dfcf069d 12282void
f676886a
JB
12283x_make_frame_visible (f)
12284 struct frame *f;
dc6f92b8 12285{
990ba854 12286 Lisp_Object type;
1aa6072f 12287 int original_top, original_left;
31be9251
GM
12288 int retry_count = 2;
12289
12290 retry:
dc6f92b8 12291
dc6f92b8 12292 BLOCK_INPUT;
dc6f92b8 12293
990ba854
RS
12294 type = x_icon_type (f);
12295 if (!NILP (type))
12296 x_bitmap_icon (f, type);
bdcd49ba 12297
f676886a 12298 if (! FRAME_VISIBLE_P (f))
90e65f07 12299 {
1aa6072f
RS
12300 /* We test FRAME_GARBAGED_P here to make sure we don't
12301 call x_set_offset a second time
12302 if we get to x_make_frame_visible a second time
12303 before the window gets really visible. */
12304 if (! FRAME_ICONIFIED_P (f)
12305 && ! f->output_data.x->asked_for_visible)
12306 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
12307
12308 f->output_data.x->asked_for_visible = 1;
12309
90e65f07 12310 if (! EQ (Vx_no_window_manager, Qt))
f676886a 12311 x_wm_set_window_state (f, NormalState);
3afe33e7 12312#ifdef USE_X_TOOLKIT
d7a38a2e 12313 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12314 XtMapWidget (f->output_data.x->widget);
3afe33e7 12315#else /* not USE_X_TOOLKIT */
7f9c7f94 12316 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 12317#endif /* not USE_X_TOOLKIT */
0134a210
RS
12318#if 0 /* This seems to bring back scroll bars in the wrong places
12319 if the window configuration has changed. They seem
12320 to come back ok without this. */
ab648270 12321 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 12322 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 12323#endif
90e65f07 12324 }
dc6f92b8 12325
334208b7 12326 XFlush (FRAME_X_DISPLAY (f));
90e65f07 12327
0dacf791
RS
12328 /* Synchronize to ensure Emacs knows the frame is visible
12329 before we do anything else. We do this loop with input not blocked
12330 so that incoming events are handled. */
12331 {
12332 Lisp_Object frame;
12ce2351 12333 int count;
28c01ffe
RS
12334 /* This must be before UNBLOCK_INPUT
12335 since events that arrive in response to the actions above
12336 will set it when they are handled. */
12337 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
12338
12339 original_left = f->output_data.x->left_pos;
12340 original_top = f->output_data.x->top_pos;
c0a04927
RS
12341
12342 /* This must come after we set COUNT. */
12343 UNBLOCK_INPUT;
12344
2745e6c4 12345 /* We unblock here so that arriving X events are processed. */
1aa6072f 12346
dcb07ae9
RS
12347 /* Now move the window back to where it was "supposed to be".
12348 But don't do it if the gravity is negative.
12349 When the gravity is negative, this uses a position
28c01ffe
RS
12350 that is 3 pixels too low. Perhaps that's really the border width.
12351
12352 Don't do this if the window has never been visible before,
12353 because the window manager may choose the position
12354 and we don't want to override it. */
1aa6072f 12355
4d3f5d9a 12356 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 12357 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 12358 && previously_visible)
1aa6072f 12359 {
2745e6c4
RS
12360 Drawable rootw;
12361 int x, y;
12362 unsigned int width, height, border, depth;
06a2c219 12363
1aa6072f 12364 BLOCK_INPUT;
9829ddba 12365
06a2c219
GM
12366 /* On some window managers (such as FVWM) moving an existing
12367 window, even to the same place, causes the window manager
12368 to introduce an offset. This can cause the window to move
12369 to an unexpected location. Check the geometry (a little
12370 slow here) and then verify that the window is in the right
12371 place. If the window is not in the right place, move it
12372 there, and take the potential window manager hit. */
2745e6c4
RS
12373 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12374 &rootw, &x, &y, &width, &height, &border, &depth);
12375
12376 if (original_left != x || original_top != y)
12377 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
12378 original_left, original_top);
12379
1aa6072f
RS
12380 UNBLOCK_INPUT;
12381 }
9829ddba 12382
e0c1aef2 12383 XSETFRAME (frame, f);
c0a04927 12384
12ce2351
GM
12385 /* Wait until the frame is visible. Process X events until a
12386 MapNotify event has been seen, or until we think we won't get a
12387 MapNotify at all.. */
12388 for (count = input_signal_count + 10;
12389 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 12390 {
12ce2351 12391 /* Force processing of queued events. */
334208b7 12392 x_sync (f);
12ce2351
GM
12393
12394 /* Machines that do polling rather than SIGIO have been
12395 observed to go into a busy-wait here. So we'll fake an
12396 alarm signal to let the handler know that there's something
12397 to be read. We used to raise a real alarm, but it seems
12398 that the handler isn't always enabled here. This is
12399 probably a bug. */
8b2f8d4e 12400 if (input_polling_used ())
3b2fa4e6 12401 {
12ce2351
GM
12402 /* It could be confusing if a real alarm arrives while
12403 processing the fake one. Turn it off and let the
12404 handler reset it. */
3e71d8f2 12405 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
12406 int old_poll_suppress_count = poll_suppress_count;
12407 poll_suppress_count = 1;
12408 poll_for_input_1 ();
12409 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 12410 }
12ce2351
GM
12411
12412 /* See if a MapNotify event has been processed. */
12413 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 12414 }
31be9251
GM
12415
12416 /* 2000-09-28: In
12417
12418 (let ((f (selected-frame)))
12419 (iconify-frame f)
12420 (raise-frame f))
12421
12422 the frame is not raised with various window managers on
12423 FreeBSD, Linux and Solaris. It turns out that, for some
12424 unknown reason, the call to XtMapWidget is completely ignored.
12425 Mapping the widget a second time works. */
12426
12427 if (!FRAME_VISIBLE_P (f) && --retry_count > 0)
12428 goto retry;
0dacf791 12429 }
dc6f92b8
JB
12430}
12431
06a2c219 12432/* Change from mapped state to withdrawn state. */
dc6f92b8 12433
d047c4eb
KH
12434/* Make the frame visible (mapped and not iconified). */
12435
dfcf069d 12436void
f676886a
JB
12437x_make_frame_invisible (f)
12438 struct frame *f;
dc6f92b8 12439{
546e6d5b
RS
12440 Window window;
12441
12442#ifdef USE_X_TOOLKIT
12443 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 12444 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
12445#else /* not USE_X_TOOLKIT */
12446 window = FRAME_X_WINDOW (f);
12447#endif /* not USE_X_TOOLKIT */
dc6f92b8 12448
9319ae23 12449 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12450 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12451 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12452
5627c40e 12453#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 12454 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 12455 return;
5627c40e 12456#endif
dc6f92b8
JB
12457
12458 BLOCK_INPUT;
c118dd06 12459
af31d76f
RS
12460 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12461 that the current position of the window is user-specified, rather than
12462 program-specified, so that when the window is mapped again, it will be
12463 placed at the same location, without forcing the user to position it
12464 by hand again (they have already done that once for this window.) */
c32cdd9a 12465 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 12466
c118dd06
JB
12467#ifdef HAVE_X11R4
12468
334208b7
RS
12469 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12470 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
12471 {
12472 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12473 error ("Can't notify window manager of window withdrawal");
c118dd06 12474 }
c118dd06 12475#else /* ! defined (HAVE_X11R4) */
16bd92ea 12476
c118dd06 12477 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
12478 if (! EQ (Vx_no_window_manager, Qt))
12479 {
16bd92ea 12480 XEvent unmap;
dc6f92b8 12481
16bd92ea 12482 unmap.xunmap.type = UnmapNotify;
546e6d5b 12483 unmap.xunmap.window = window;
334208b7 12484 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 12485 unmap.xunmap.from_configure = False;
334208b7
RS
12486 if (! XSendEvent (FRAME_X_DISPLAY (f),
12487 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 12488 False,
06a2c219 12489 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
12490 &unmap))
12491 {
12492 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12493 error ("Can't notify window manager of withdrawal");
16bd92ea 12494 }
dc6f92b8
JB
12495 }
12496
16bd92ea 12497 /* Unmap the window ourselves. Cheeky! */
334208b7 12498 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 12499#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 12500
5627c40e
RS
12501 /* We can't distinguish this from iconification
12502 just by the event that we get from the server.
12503 So we can't win using the usual strategy of letting
12504 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12505 and synchronize with the server to make sure we agree. */
12506 f->visible = 0;
12507 FRAME_ICONIFIED_P (f) = 0;
12508 f->async_visible = 0;
12509 f->async_iconified = 0;
12510
334208b7 12511 x_sync (f);
5627c40e 12512
dc6f92b8
JB
12513 UNBLOCK_INPUT;
12514}
12515
06a2c219 12516/* Change window state from mapped to iconified. */
dc6f92b8 12517
dfcf069d 12518void
f676886a
JB
12519x_iconify_frame (f)
12520 struct frame *f;
dc6f92b8 12521{
3afe33e7 12522 int result;
990ba854 12523 Lisp_Object type;
dc6f92b8 12524
9319ae23 12525 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12526 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12527 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12528
3a88c238 12529 if (f->async_iconified)
dc6f92b8
JB
12530 return;
12531
3afe33e7 12532 BLOCK_INPUT;
546e6d5b 12533
9af3143a
RS
12534 FRAME_SAMPLE_VISIBILITY (f);
12535
990ba854
RS
12536 type = x_icon_type (f);
12537 if (!NILP (type))
12538 x_bitmap_icon (f, type);
bdcd49ba
RS
12539
12540#ifdef USE_X_TOOLKIT
12541
546e6d5b
RS
12542 if (! FRAME_VISIBLE_P (f))
12543 {
12544 if (! EQ (Vx_no_window_manager, Qt))
12545 x_wm_set_window_state (f, IconicState);
12546 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12547 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
12548 /* The server won't give us any event to indicate
12549 that an invisible frame was changed to an icon,
12550 so we have to record it here. */
12551 f->iconified = 1;
1e6bc770 12552 f->visible = 1;
9cf30a30 12553 f->async_iconified = 1;
1e6bc770 12554 f->async_visible = 0;
546e6d5b
RS
12555 UNBLOCK_INPUT;
12556 return;
12557 }
12558
334208b7 12559 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 12560 XtWindow (f->output_data.x->widget),
334208b7 12561 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
12562 UNBLOCK_INPUT;
12563
12564 if (!result)
546e6d5b 12565 error ("Can't notify window manager of iconification");
3afe33e7
RS
12566
12567 f->async_iconified = 1;
1e6bc770
RS
12568 f->async_visible = 0;
12569
8c002a25
KH
12570
12571 BLOCK_INPUT;
334208b7 12572 XFlush (FRAME_X_DISPLAY (f));
8c002a25 12573 UNBLOCK_INPUT;
3afe33e7
RS
12574#else /* not USE_X_TOOLKIT */
12575
fd13dbb2
RS
12576 /* Make sure the X server knows where the window should be positioned,
12577 in case the user deiconifies with the window manager. */
12578 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 12579 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 12580
16bd92ea
JB
12581 /* Since we don't know which revision of X we're running, we'll use both
12582 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12583
12584 /* X11R4: send a ClientMessage to the window manager using the
12585 WM_CHANGE_STATE type. */
12586 {
12587 XEvent message;
58769bee 12588
c118dd06 12589 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 12590 message.xclient.type = ClientMessage;
334208b7 12591 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
12592 message.xclient.format = 32;
12593 message.xclient.data.l[0] = IconicState;
12594
334208b7
RS
12595 if (! XSendEvent (FRAME_X_DISPLAY (f),
12596 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
12597 False,
12598 SubstructureRedirectMask | SubstructureNotifyMask,
12599 &message))
dc6f92b8
JB
12600 {
12601 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12602 error ("Can't notify window manager of iconification");
dc6f92b8 12603 }
16bd92ea 12604 }
dc6f92b8 12605
58769bee 12606 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
12607 IconicState. */
12608 x_wm_set_window_state (f, IconicState);
dc6f92b8 12609
a9c00105
RS
12610 if (!FRAME_VISIBLE_P (f))
12611 {
12612 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 12613 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
12614 }
12615
3a88c238 12616 f->async_iconified = 1;
1e6bc770 12617 f->async_visible = 0;
dc6f92b8 12618
334208b7 12619 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 12620 UNBLOCK_INPUT;
8c002a25 12621#endif /* not USE_X_TOOLKIT */
dc6f92b8 12622}
19f71add 12623
d047c4eb 12624\f
19f71add 12625/* Free X resources of frame F. */
dc6f92b8 12626
dfcf069d 12627void
19f71add 12628x_free_frame_resources (f)
f676886a 12629 struct frame *f;
dc6f92b8 12630{
7f9c7f94
RS
12631 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12632
dc6f92b8 12633 BLOCK_INPUT;
c0ff3fab 12634
6186a4a0
RS
12635 /* If a display connection is dead, don't try sending more
12636 commands to the X server. */
19f71add 12637 if (dpyinfo->display)
6186a4a0 12638 {
19f71add 12639 if (f->output_data.x->icon_desc)
6186a4a0 12640 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
19f71add 12641
31f41daf 12642#ifdef HAVE_X_I18N
f5d11644
GM
12643 if (FRAME_XIC (f))
12644 free_frame_xic (f);
31f41daf 12645#endif
19f71add 12646
2662734b 12647 if (FRAME_X_WINDOW (f))
19f71add
GM
12648 XDestroyWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
12649
3afe33e7 12650#ifdef USE_X_TOOLKIT
06a2c219
GM
12651 if (f->output_data.x->widget)
12652 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12653 free_frame_menubar (f);
3afe33e7
RS
12654#endif /* USE_X_TOOLKIT */
12655
3e71d8f2
GM
12656 unload_color (f, f->output_data.x->foreground_pixel);
12657 unload_color (f, f->output_data.x->background_pixel);
12658 unload_color (f, f->output_data.x->cursor_pixel);
12659 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12660 unload_color (f, f->output_data.x->border_pixel);
12661 unload_color (f, f->output_data.x->mouse_pixel);
19f71add 12662
3e71d8f2
GM
12663 if (f->output_data.x->scroll_bar_background_pixel != -1)
12664 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12665 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12666 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12667 if (f->output_data.x->white_relief.allocated_p)
12668 unload_color (f, f->output_data.x->white_relief.pixel);
12669 if (f->output_data.x->black_relief.allocated_p)
12670 unload_color (f, f->output_data.x->black_relief.pixel);
4ca78676 12671
19f71add
GM
12672 if (FRAME_FACE_CACHE (f))
12673 free_frame_faces (f);
12674
4ca78676 12675 x_free_gcs (f);
6186a4a0
RS
12676 XFlush (FRAME_X_DISPLAY (f));
12677 }
dc6f92b8 12678
df89d8a4 12679 if (f->output_data.x->saved_menu_event)
06a2c219 12680 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12681
7556890b 12682 xfree (f->output_data.x);
19f71add
GM
12683 f->output_data.x = NULL;
12684
0f941935
KH
12685 if (f == dpyinfo->x_focus_frame)
12686 dpyinfo->x_focus_frame = 0;
12687 if (f == dpyinfo->x_focus_event_frame)
12688 dpyinfo->x_focus_event_frame = 0;
12689 if (f == dpyinfo->x_highlight_frame)
12690 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12691
7f9c7f94 12692 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12693 {
7f9c7f94
RS
12694 dpyinfo->mouse_face_beg_row
12695 = dpyinfo->mouse_face_beg_col = -1;
12696 dpyinfo->mouse_face_end_row
12697 = dpyinfo->mouse_face_end_col = -1;
12698 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12699 dpyinfo->mouse_face_deferred_gc = 0;
12700 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12701 }
0134a210 12702
c0ff3fab 12703 UNBLOCK_INPUT;
dc6f92b8 12704}
19f71add
GM
12705
12706
12707/* Destroy the X window of frame F. */
12708
12709void
12710x_destroy_window (f)
12711 struct frame *f;
12712{
12713 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12714
12715 /* If a display connection is dead, don't try sending more
12716 commands to the X server. */
12717 if (dpyinfo->display != 0)
12718 x_free_frame_resources (f);
12719
12720 dpyinfo->reference_count--;
12721}
12722
dc6f92b8 12723\f
f451eb13
JB
12724/* Setting window manager hints. */
12725
af31d76f
RS
12726/* Set the normal size hints for the window manager, for frame F.
12727 FLAGS is the flags word to use--or 0 meaning preserve the flags
12728 that the window now has.
12729 If USER_POSITION is nonzero, we set the USPosition
12730 flag (this is useful when FLAGS is 0). */
6dba1858 12731
dfcf069d 12732void
af31d76f 12733x_wm_set_size_hint (f, flags, user_position)
f676886a 12734 struct frame *f;
af31d76f
RS
12735 long flags;
12736 int user_position;
dc6f92b8
JB
12737{
12738 XSizeHints size_hints;
3afe33e7
RS
12739
12740#ifdef USE_X_TOOLKIT
7e4f2521
FP
12741 Arg al[2];
12742 int ac = 0;
12743 Dimension widget_width, widget_height;
7556890b 12744 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12745#else /* not USE_X_TOOLKIT */
c118dd06 12746 Window window = FRAME_X_WINDOW (f);
3afe33e7 12747#endif /* not USE_X_TOOLKIT */
dc6f92b8 12748
b72a58fd
RS
12749 /* Setting PMaxSize caused various problems. */
12750 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12751
7556890b
RS
12752 size_hints.x = f->output_data.x->left_pos;
12753 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12754
7e4f2521
FP
12755#ifdef USE_X_TOOLKIT
12756 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12757 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12758 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12759 size_hints.height = widget_height;
12760 size_hints.width = widget_width;
12761#else /* not USE_X_TOOLKIT */
f676886a
JB
12762 size_hints.height = PIXEL_HEIGHT (f);
12763 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12764#endif /* not USE_X_TOOLKIT */
7553a6b7 12765
7556890b
RS
12766 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12767 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12768 size_hints.max_width
12769 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12770 size_hints.max_height
12771 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12772
d067ea8b
KH
12773 /* Calculate the base and minimum sizes.
12774
12775 (When we use the X toolkit, we don't do it here.
12776 Instead we copy the values that the widgets are using, below.) */
12777#ifndef USE_X_TOOLKIT
b1c884c3 12778 {
b0342f17 12779 int base_width, base_height;
0134a210 12780 int min_rows = 0, min_cols = 0;
b0342f17 12781
f451eb13
JB
12782 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12783 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12784
0134a210 12785 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12786
0134a210
RS
12787 /* The window manager uses the base width hints to calculate the
12788 current number of rows and columns in the frame while
12789 resizing; min_width and min_height aren't useful for this
12790 purpose, since they might not give the dimensions for a
12791 zero-row, zero-column frame.
58769bee 12792
0134a210
RS
12793 We use the base_width and base_height members if we have
12794 them; otherwise, we set the min_width and min_height members
12795 to the size for a zero x zero frame. */
b0342f17
JB
12796
12797#ifdef HAVE_X11R4
0134a210
RS
12798 size_hints.flags |= PBaseSize;
12799 size_hints.base_width = base_width;
12800 size_hints.base_height = base_height;
12801 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12802 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12803#else
0134a210
RS
12804 size_hints.min_width = base_width;
12805 size_hints.min_height = base_height;
b0342f17 12806#endif
b1c884c3 12807 }
dc6f92b8 12808
d067ea8b 12809 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12810 if (flags)
dc6f92b8 12811 {
d067ea8b
KH
12812 size_hints.flags |= flags;
12813 goto no_read;
12814 }
12815#endif /* not USE_X_TOOLKIT */
12816
12817 {
12818 XSizeHints hints; /* Sometimes I hate X Windows... */
12819 long supplied_return;
12820 int value;
af31d76f
RS
12821
12822#ifdef HAVE_X11R4
d067ea8b
KH
12823 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12824 &supplied_return);
af31d76f 12825#else
d067ea8b 12826 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12827#endif
58769bee 12828
d067ea8b
KH
12829#ifdef USE_X_TOOLKIT
12830 size_hints.base_height = hints.base_height;
12831 size_hints.base_width = hints.base_width;
12832 size_hints.min_height = hints.min_height;
12833 size_hints.min_width = hints.min_width;
12834#endif
12835
12836 if (flags)
12837 size_hints.flags |= flags;
12838 else
12839 {
12840 if (value == 0)
12841 hints.flags = 0;
12842 if (hints.flags & PSize)
12843 size_hints.flags |= PSize;
12844 if (hints.flags & PPosition)
12845 size_hints.flags |= PPosition;
12846 if (hints.flags & USPosition)
12847 size_hints.flags |= USPosition;
12848 if (hints.flags & USSize)
12849 size_hints.flags |= USSize;
12850 }
12851 }
12852
06a2c219 12853#ifndef USE_X_TOOLKIT
d067ea8b 12854 no_read:
06a2c219 12855#endif
0134a210 12856
af31d76f 12857#ifdef PWinGravity
7556890b 12858 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12859 size_hints.flags |= PWinGravity;
dc05a16b 12860
af31d76f 12861 if (user_position)
6dba1858 12862 {
af31d76f
RS
12863 size_hints.flags &= ~ PPosition;
12864 size_hints.flags |= USPosition;
6dba1858 12865 }
2554751d 12866#endif /* PWinGravity */
6dba1858 12867
b0342f17 12868#ifdef HAVE_X11R4
334208b7 12869 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12870#else
334208b7 12871 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12872#endif
dc6f92b8
JB
12873}
12874
12875/* Used for IconicState or NormalState */
06a2c219 12876
dfcf069d 12877void
f676886a
JB
12878x_wm_set_window_state (f, state)
12879 struct frame *f;
dc6f92b8
JB
12880 int state;
12881{
3afe33e7 12882#ifdef USE_X_TOOLKIT
546e6d5b
RS
12883 Arg al[1];
12884
12885 XtSetArg (al[0], XtNinitialState, state);
7556890b 12886 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12887#else /* not USE_X_TOOLKIT */
c118dd06 12888 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12889
7556890b
RS
12890 f->output_data.x->wm_hints.flags |= StateHint;
12891 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12892
7556890b 12893 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12894#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12895}
12896
dfcf069d 12897void
7f2ae036 12898x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12899 struct frame *f;
7f2ae036 12900 int pixmap_id;
dc6f92b8 12901{
d2bd6bc4
RS
12902 Pixmap icon_pixmap;
12903
06a2c219 12904#ifndef USE_X_TOOLKIT
c118dd06 12905 Window window = FRAME_X_WINDOW (f);
75231bad 12906#endif
dc6f92b8 12907
7f2ae036 12908 if (pixmap_id > 0)
dbc4e1c1 12909 {
d2bd6bc4 12910 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12911 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12912 }
12913 else
68568555
RS
12914 {
12915 /* It seems there is no way to turn off use of an icon pixmap.
12916 The following line does it, only if no icon has yet been created,
12917 for some window managers. But with mwm it crashes.
12918 Some people say it should clear the IconPixmapHint bit in this case,
12919 but that doesn't work, and the X consortium said it isn't the
12920 right thing at all. Since there is no way to win,
12921 best to explicitly give up. */
12922#if 0
12923 f->output_data.x->wm_hints.icon_pixmap = None;
12924#else
12925 return;
12926#endif
12927 }
b1c884c3 12928
d2bd6bc4
RS
12929#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12930
12931 {
12932 Arg al[1];
12933 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12934 XtSetValues (f->output_data.x->widget, al, 1);
12935 }
12936
12937#else /* not USE_X_TOOLKIT */
12938
7556890b
RS
12939 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12940 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12941
12942#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12943}
12944
dfcf069d 12945void
f676886a
JB
12946x_wm_set_icon_position (f, icon_x, icon_y)
12947 struct frame *f;
dc6f92b8
JB
12948 int icon_x, icon_y;
12949{
75231bad 12950#ifdef USE_X_TOOLKIT
7556890b 12951 Window window = XtWindow (f->output_data.x->widget);
75231bad 12952#else
c118dd06 12953 Window window = FRAME_X_WINDOW (f);
75231bad 12954#endif
dc6f92b8 12955
7556890b
RS
12956 f->output_data.x->wm_hints.flags |= IconPositionHint;
12957 f->output_data.x->wm_hints.icon_x = icon_x;
12958 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12959
7556890b 12960 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12961}
12962
12963\f
06a2c219
GM
12964/***********************************************************************
12965 Fonts
12966 ***********************************************************************/
dc43ef94
KH
12967
12968/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12969
dc43ef94
KH
12970struct font_info *
12971x_get_font_info (f, font_idx)
12972 FRAME_PTR f;
12973 int font_idx;
12974{
12975 return (FRAME_X_FONT_TABLE (f) + font_idx);
12976}
12977
12978
9c11f79e
GM
12979/* Return a list of names of available fonts matching PATTERN on frame F.
12980
12981 If SIZE is > 0, it is the size (maximum bounds width) of fonts
12982 to be listed.
12983
12984 SIZE < 0 means include scalable fonts.
12985
12986 Frame F null means we have not yet created any frame on X, and
12987 consult the first display in x_display_list. MAXNAMES sets a limit
12988 on how many fonts to match. */
dc43ef94
KH
12989
12990Lisp_Object
12991x_list_fonts (f, pattern, size, maxnames)
9c11f79e 12992 struct frame *f;
dc43ef94
KH
12993 Lisp_Object pattern;
12994 int size;
12995 int maxnames;
12996{
06a2c219
GM
12997 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12998 Lisp_Object tem, second_best;
9c11f79e
GM
12999 struct x_display_info *dpyinfo
13000 = f ? FRAME_X_DISPLAY_INFO (f) : x_display_list;
13001 Display *dpy = dpyinfo->display;
09c6077f 13002 int try_XLoadQueryFont = 0;
53ca4657 13003 int count;
9c11f79e
GM
13004 int allow_scalable_fonts_p = 0;
13005
13006 if (size < 0)
13007 {
13008 allow_scalable_fonts_p = 1;
13009 size = 0;
13010 }
dc43ef94 13011
6b0efe73 13012 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
13013 if (NILP (patterns))
13014 patterns = Fcons (pattern, Qnil);
81ba44e5 13015
09c6077f
KH
13016 if (maxnames == 1 && !size)
13017 /* We can return any single font matching PATTERN. */
13018 try_XLoadQueryFont = 1;
9a32686f 13019
8e713be6 13020 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 13021 {
dc43ef94 13022 int num_fonts;
3e71d8f2 13023 char **names = NULL;
dc43ef94 13024
8e713be6 13025 pattern = XCAR (patterns);
536f4067
RS
13026 /* See if we cached the result for this particular query.
13027 The cache is an alist of the form:
9c11f79e
GM
13028 ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...) */
13029 tem = XCDR (dpyinfo->name_list_element);
13030 key = Fcons (Fcons (pattern, make_number (maxnames)),
13031 allow_scalable_fonts_p ? Qt : Qnil);
13032 list = Fassoc (key, tem);
13033 if (!NILP (list))
b5210ea7
KH
13034 {
13035 list = Fcdr_safe (list);
13036 /* We have a cashed list. Don't have to get the list again. */
13037 goto label_cached;
13038 }
13039
13040 /* At first, put PATTERN in the cache. */
09c6077f 13041
dc43ef94 13042 BLOCK_INPUT;
17d85edc
KH
13043 count = x_catch_errors (dpy);
13044
09c6077f
KH
13045 if (try_XLoadQueryFont)
13046 {
13047 XFontStruct *font;
13048 unsigned long value;
13049
13050 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
13051 if (x_had_errors_p (dpy))
13052 {
13053 /* This error is perhaps due to insufficient memory on X
13054 server. Let's just ignore it. */
13055 font = NULL;
13056 x_clear_errors (dpy);
13057 }
13058
09c6077f
KH
13059 if (font
13060 && XGetFontProperty (font, XA_FONT, &value))
13061 {
13062 char *name = (char *) XGetAtomName (dpy, (Atom) value);
13063 int len = strlen (name);
01c752b5 13064 char *tmp;
09c6077f 13065
6f6512e8
KH
13066 /* If DXPC (a Differential X Protocol Compressor)
13067 Ver.3.7 is running, XGetAtomName will return null
13068 string. We must avoid such a name. */
13069 if (len == 0)
13070 try_XLoadQueryFont = 0;
13071 else
13072 {
13073 num_fonts = 1;
13074 names = (char **) alloca (sizeof (char *));
13075 /* Some systems only allow alloca assigned to a
13076 simple var. */
13077 tmp = (char *) alloca (len + 1); names[0] = tmp;
13078 bcopy (name, names[0], len + 1);
13079 XFree (name);
13080 }
09c6077f
KH
13081 }
13082 else
13083 try_XLoadQueryFont = 0;
a083fd23
RS
13084
13085 if (font)
13086 XFreeFont (dpy, font);
09c6077f
KH
13087 }
13088
13089 if (!try_XLoadQueryFont)
17d85edc
KH
13090 {
13091 /* We try at least 10 fonts because XListFonts will return
13092 auto-scaled fonts at the head. */
13093 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
13094 &num_fonts);
13095 if (x_had_errors_p (dpy))
13096 {
13097 /* This error is perhaps due to insufficient memory on X
13098 server. Let's just ignore it. */
13099 names = NULL;
13100 x_clear_errors (dpy);
13101 }
13102 }
13103
13104 x_uncatch_errors (dpy, count);
dc43ef94
KH
13105 UNBLOCK_INPUT;
13106
13107 if (names)
13108 {
13109 int i;
dc43ef94
KH
13110
13111 /* Make a list of all the fonts we got back.
13112 Store that in the font cache for the display. */
13113 for (i = 0; i < num_fonts; i++)
13114 {
06a2c219 13115 int width = 0;
dc43ef94 13116 char *p = names[i];
06a2c219
GM
13117 int average_width = -1, dashes = 0;
13118
dc43ef94 13119 /* Count the number of dashes in NAMES[I]. If there are
9c11f79e
GM
13120 14 dashes, and the field value following 12th dash
13121 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
13122 is usually too ugly to be used for editing. Let's
13123 ignore it. */
dc43ef94
KH
13124 while (*p)
13125 if (*p++ == '-')
13126 {
13127 dashes++;
13128 if (dashes == 7) /* PIXEL_SIZE field */
13129 width = atoi (p);
13130 else if (dashes == 12) /* AVERAGE_WIDTH field */
13131 average_width = atoi (p);
13132 }
9c11f79e
GM
13133
13134 if (allow_scalable_fonts_p
13135 || dashes < 14 || average_width != 0)
dc43ef94
KH
13136 {
13137 tem = build_string (names[i]);
13138 if (NILP (Fassoc (tem, list)))
13139 {
13140 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
13141 && ((fast_c_string_match_ignore_case
13142 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
13143 >= 0))
13144 /* We can set the value of PIXEL_SIZE to the
b5210ea7 13145 width of this font. */
dc43ef94
KH
13146 list = Fcons (Fcons (tem, make_number (width)), list);
13147 else
13148 /* For the moment, width is not known. */
13149 list = Fcons (Fcons (tem, Qnil), list);
13150 }
13151 }
13152 }
09c6077f
KH
13153 if (!try_XLoadQueryFont)
13154 XFreeFontNames (names);
dc43ef94
KH
13155 }
13156
b5210ea7 13157 /* Now store the result in the cache. */
9c11f79e
GM
13158 XCDR (dpyinfo->name_list_element)
13159 = Fcons (Fcons (key, list), XCDR (dpyinfo->name_list_element));
dc43ef94 13160
b5210ea7
KH
13161 label_cached:
13162 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 13163
b5210ea7
KH
13164 newlist = second_best = Qnil;
13165 /* Make a list of the fonts that have the right width. */
8e713be6 13166 for (; CONSP (list); list = XCDR (list))
b5210ea7 13167 {
536f4067
RS
13168 int found_size;
13169
8e713be6 13170 tem = XCAR (list);
dc43ef94 13171
8e713be6 13172 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
13173 continue;
13174 if (!size)
13175 {
8e713be6 13176 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
13177 continue;
13178 }
dc43ef94 13179
8e713be6 13180 if (!INTEGERP (XCDR (tem)))
dc43ef94 13181 {
b5210ea7 13182 /* Since we have not yet known the size of this font, we
9c11f79e 13183 must try slow function call XLoadQueryFont. */
dc43ef94
KH
13184 XFontStruct *thisinfo;
13185
13186 BLOCK_INPUT;
17d85edc 13187 count = x_catch_errors (dpy);
dc43ef94 13188 thisinfo = XLoadQueryFont (dpy,
8e713be6 13189 XSTRING (XCAR (tem))->data);
17d85edc
KH
13190 if (x_had_errors_p (dpy))
13191 {
13192 /* This error is perhaps due to insufficient memory on X
13193 server. Let's just ignore it. */
13194 thisinfo = NULL;
13195 x_clear_errors (dpy);
13196 }
13197 x_uncatch_errors (dpy, count);
dc43ef94
KH
13198 UNBLOCK_INPUT;
13199
13200 if (thisinfo)
13201 {
8e713be6 13202 XCDR (tem)
536f4067
RS
13203 = (thisinfo->min_bounds.width == 0
13204 ? make_number (0)
13205 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
13206 XFreeFont (dpy, thisinfo);
13207 }
13208 else
b5210ea7 13209 /* For unknown reason, the previous call of XListFont had
06a2c219 13210 returned a font which can't be opened. Record the size
b5210ea7 13211 as 0 not to try to open it again. */
8e713be6 13212 XCDR (tem) = make_number (0);
dc43ef94 13213 }
536f4067 13214
8e713be6 13215 found_size = XINT (XCDR (tem));
536f4067 13216 if (found_size == size)
8e713be6 13217 newlist = Fcons (XCAR (tem), newlist);
536f4067 13218 else if (found_size > 0)
b5210ea7 13219 {
536f4067 13220 if (NILP (second_best))
b5210ea7 13221 second_best = tem;
536f4067
RS
13222 else if (found_size < size)
13223 {
8e713be6
KR
13224 if (XINT (XCDR (second_best)) > size
13225 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
13226 second_best = tem;
13227 }
13228 else
13229 {
8e713be6
KR
13230 if (XINT (XCDR (second_best)) > size
13231 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
13232 second_best = tem;
13233 }
b5210ea7
KH
13234 }
13235 }
13236 if (!NILP (newlist))
13237 break;
13238 else if (!NILP (second_best))
13239 {
8e713be6 13240 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 13241 break;
dc43ef94 13242 }
dc43ef94
KH
13243 }
13244
13245 return newlist;
13246}
13247
06a2c219
GM
13248
13249#if GLYPH_DEBUG
13250
13251/* Check that FONT is valid on frame F. It is if it can be found in F's
13252 font table. */
13253
13254static void
13255x_check_font (f, font)
13256 struct frame *f;
13257 XFontStruct *font;
13258{
13259 int i;
13260 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13261
13262 xassert (font != NULL);
13263
13264 for (i = 0; i < dpyinfo->n_fonts; i++)
13265 if (dpyinfo->font_table[i].name
13266 && font == dpyinfo->font_table[i].font)
13267 break;
13268
13269 xassert (i < dpyinfo->n_fonts);
13270}
13271
13272#endif /* GLYPH_DEBUG != 0 */
13273
13274/* Set *W to the minimum width, *H to the minimum font height of FONT.
13275 Note: There are (broken) X fonts out there with invalid XFontStruct
13276 min_bounds contents. For example, handa@etl.go.jp reports that
13277 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
13278 have font->min_bounds.width == 0. */
13279
13280static INLINE void
13281x_font_min_bounds (font, w, h)
13282 XFontStruct *font;
13283 int *w, *h;
13284{
13285 *h = FONT_HEIGHT (font);
13286 *w = font->min_bounds.width;
13287
13288 /* Try to handle the case where FONT->min_bounds has invalid
13289 contents. Since the only font known to have invalid min_bounds
13290 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
13291 if (*w <= 0)
13292 *w = font->max_bounds.width;
13293}
13294
13295
13296/* Compute the smallest character width and smallest font height over
13297 all fonts available on frame F. Set the members smallest_char_width
13298 and smallest_font_height in F's x_display_info structure to
13299 the values computed. Value is non-zero if smallest_font_height or
13300 smallest_char_width become smaller than they were before. */
13301
13302static int
13303x_compute_min_glyph_bounds (f)
13304 struct frame *f;
13305{
13306 int i;
13307 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13308 XFontStruct *font;
13309 int old_width = dpyinfo->smallest_char_width;
13310 int old_height = dpyinfo->smallest_font_height;
13311
13312 dpyinfo->smallest_font_height = 100000;
13313 dpyinfo->smallest_char_width = 100000;
13314
13315 for (i = 0; i < dpyinfo->n_fonts; ++i)
13316 if (dpyinfo->font_table[i].name)
13317 {
13318 struct font_info *fontp = dpyinfo->font_table + i;
13319 int w, h;
13320
13321 font = (XFontStruct *) fontp->font;
13322 xassert (font != (XFontStruct *) ~0);
13323 x_font_min_bounds (font, &w, &h);
13324
13325 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
13326 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
13327 }
13328
13329 xassert (dpyinfo->smallest_char_width > 0
13330 && dpyinfo->smallest_font_height > 0);
13331
13332 return (dpyinfo->n_fonts == 1
13333 || dpyinfo->smallest_char_width < old_width
13334 || dpyinfo->smallest_font_height < old_height);
13335}
13336
13337
dc43ef94
KH
13338/* Load font named FONTNAME of the size SIZE for frame F, and return a
13339 pointer to the structure font_info while allocating it dynamically.
13340 If SIZE is 0, load any size of font.
13341 If loading is failed, return NULL. */
13342
13343struct font_info *
13344x_load_font (f, fontname, size)
13345 struct frame *f;
13346 register char *fontname;
13347 int size;
13348{
13349 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13350 Lisp_Object font_names;
d645aaa4 13351 int count;
dc43ef94
KH
13352
13353 /* Get a list of all the fonts that match this name. Once we
13354 have a list of matching fonts, we compare them against the fonts
13355 we already have by comparing names. */
09c6077f 13356 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
13357
13358 if (!NILP (font_names))
13359 {
13360 Lisp_Object tail;
13361 int i;
13362
13363 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 13364 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
13365 if (dpyinfo->font_table[i].name
13366 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 13367 XSTRING (XCAR (tail))->data)
06a2c219 13368 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 13369 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
13370 return (dpyinfo->font_table + i);
13371 }
13372
13373 /* Load the font and add it to the table. */
13374 {
13375 char *full_name;
13376 XFontStruct *font;
13377 struct font_info *fontp;
13378 unsigned long value;
06a2c219 13379 int i;
dc43ef94 13380
2da424f1
KH
13381 /* If we have found fonts by x_list_font, load one of them. If
13382 not, we still try to load a font by the name given as FONTNAME
13383 because XListFonts (called in x_list_font) of some X server has
13384 a bug of not finding a font even if the font surely exists and
13385 is loadable by XLoadQueryFont. */
e1d6d5b9 13386 if (size > 0 && !NILP (font_names))
8e713be6 13387 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
13388
13389 BLOCK_INPUT;
d645aaa4 13390 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 13391 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
13392 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
13393 {
13394 /* This error is perhaps due to insufficient memory on X
13395 server. Let's just ignore it. */
13396 font = NULL;
13397 x_clear_errors (FRAME_X_DISPLAY (f));
13398 }
13399 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 13400 UNBLOCK_INPUT;
b5210ea7 13401 if (!font)
dc43ef94
KH
13402 return NULL;
13403
06a2c219
GM
13404 /* Find a free slot in the font table. */
13405 for (i = 0; i < dpyinfo->n_fonts; ++i)
13406 if (dpyinfo->font_table[i].name == NULL)
13407 break;
13408
13409 /* If no free slot found, maybe enlarge the font table. */
13410 if (i == dpyinfo->n_fonts
13411 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 13412 {
06a2c219
GM
13413 int sz;
13414 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
13415 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 13416 dpyinfo->font_table
06a2c219 13417 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
13418 }
13419
06a2c219
GM
13420 fontp = dpyinfo->font_table + i;
13421 if (i == dpyinfo->n_fonts)
13422 ++dpyinfo->n_fonts;
dc43ef94
KH
13423
13424 /* Now fill in the slots of *FONTP. */
13425 BLOCK_INPUT;
13426 fontp->font = font;
06a2c219 13427 fontp->font_idx = i;
dc43ef94
KH
13428 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
13429 bcopy (fontname, fontp->name, strlen (fontname) + 1);
13430
13431 /* Try to get the full name of FONT. Put it in FULL_NAME. */
13432 full_name = 0;
13433 if (XGetFontProperty (font, XA_FONT, &value))
13434 {
13435 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
13436 char *p = name;
13437 int dashes = 0;
13438
13439 /* Count the number of dashes in the "full name".
13440 If it is too few, this isn't really the font's full name,
13441 so don't use it.
13442 In X11R4, the fonts did not come with their canonical names
13443 stored in them. */
13444 while (*p)
13445 {
13446 if (*p == '-')
13447 dashes++;
13448 p++;
13449 }
13450
13451 if (dashes >= 13)
13452 {
13453 full_name = (char *) xmalloc (p - name + 1);
13454 bcopy (name, full_name, p - name + 1);
13455 }
13456
13457 XFree (name);
13458 }
13459
13460 if (full_name != 0)
13461 fontp->full_name = full_name;
13462 else
13463 fontp->full_name = fontp->name;
13464
13465 fontp->size = font->max_bounds.width;
d5749adb 13466 fontp->height = FONT_HEIGHT (font);
dc43ef94 13467
2da424f1
KH
13468 if (NILP (font_names))
13469 {
13470 /* We come here because of a bug of XListFonts mentioned at
13471 the head of this block. Let's store this information in
13472 the cache for x_list_fonts. */
13473 Lisp_Object lispy_name = build_string (fontname);
13474 Lisp_Object lispy_full_name = build_string (fontp->full_name);
9c11f79e
GM
13475 Lisp_Object key = Fcons (Fcons (lispy_name, make_number (256)),
13476 Qnil);
2da424f1 13477
8e713be6 13478 XCDR (dpyinfo->name_list_element)
9c11f79e 13479 = Fcons (Fcons (key,
2da424f1
KH
13480 Fcons (Fcons (lispy_full_name,
13481 make_number (fontp->size)),
13482 Qnil)),
8e713be6 13483 XCDR (dpyinfo->name_list_element));
2da424f1 13484 if (full_name)
9c11f79e
GM
13485 {
13486 key = Fcons (Fcons (lispy_full_name, make_number (256)),
13487 Qnil);
13488 XCDR (dpyinfo->name_list_element)
13489 = Fcons (Fcons (key,
13490 Fcons (Fcons (lispy_full_name,
13491 make_number (fontp->size)),
13492 Qnil)),
13493 XCDR (dpyinfo->name_list_element));
13494 }
2da424f1
KH
13495 }
13496
dc43ef94
KH
13497 /* The slot `encoding' specifies how to map a character
13498 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
13499 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13500 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 13501 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 13502 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
13503 which is never used by any charset. If mapping can't be
13504 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
13505 fontp->encoding[1]
13506 = (font->max_byte1 == 0
13507 /* 1-byte font */
13508 ? (font->min_char_or_byte2 < 0x80
13509 ? (font->max_char_or_byte2 < 0x80
13510 ? 0 /* 0x20..0x7F */
8ff102bd 13511 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
13512 : 1) /* 0xA0..0xFF */
13513 /* 2-byte font */
13514 : (font->min_byte1 < 0x80
13515 ? (font->max_byte1 < 0x80
13516 ? (font->min_char_or_byte2 < 0x80
13517 ? (font->max_char_or_byte2 < 0x80
13518 ? 0 /* 0x2020..0x7F7F */
8ff102bd 13519 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 13520 : 3) /* 0x20A0..0x7FFF */
8ff102bd 13521 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
13522 : (font->min_char_or_byte2 < 0x80
13523 ? (font->max_char_or_byte2 < 0x80
13524 ? 2 /* 0xA020..0xFF7F */
8ff102bd 13525 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
13526 : 1))); /* 0xA0A0..0xFFFF */
13527
13528 fontp->baseline_offset
13529 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13530 ? (long) value : 0);
13531 fontp->relative_compose
13532 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13533 ? (long) value : 0);
f78798df
KH
13534 fontp->default_ascent
13535 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13536 ? (long) value : 0);
dc43ef94 13537
06a2c219
GM
13538 /* Set global flag fonts_changed_p to non-zero if the font loaded
13539 has a character with a smaller width than any other character
13540 before, or if the font loaded has a smalle>r height than any
13541 other font loaded before. If this happens, it will make a
13542 glyph matrix reallocation necessary. */
13543 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 13544 UNBLOCK_INPUT;
dc43ef94
KH
13545 return fontp;
13546 }
13547}
13548
06a2c219
GM
13549
13550/* Return a pointer to struct font_info of a font named FONTNAME for
13551 frame F. If no such font is loaded, return NULL. */
13552
dc43ef94
KH
13553struct font_info *
13554x_query_font (f, fontname)
13555 struct frame *f;
13556 register char *fontname;
13557{
13558 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13559 int i;
13560
13561 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
13562 if (dpyinfo->font_table[i].name
13563 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13564 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
13565 return (dpyinfo->font_table + i);
13566 return NULL;
13567}
13568
06a2c219
GM
13569
13570/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
13571 `encoder' of the structure. */
13572
13573void
13574x_find_ccl_program (fontp)
13575 struct font_info *fontp;
13576{
a42f54e6 13577 Lisp_Object list, elt;
a6582676 13578
f9b5db02 13579 elt = Qnil;
8e713be6 13580 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 13581 {
8e713be6 13582 elt = XCAR (list);
a6582676 13583 if (CONSP (elt)
8e713be6 13584 && STRINGP (XCAR (elt))
9f2feff6
KH
13585 && ((fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
13586 >= 0)
13587 || (fast_c_string_match_ignore_case (XCAR (elt), fontp->full_name)
13588 >= 0)))
a42f54e6
KH
13589 break;
13590 }
f9b5db02 13591
a42f54e6
KH
13592 if (! NILP (list))
13593 {
d27f8ca7
KH
13594 struct ccl_program *ccl
13595 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 13596
8e713be6 13597 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
13598 xfree (ccl);
13599 else
13600 fontp->font_encoder = ccl;
a6582676
KH
13601 }
13602}
13603
06a2c219 13604
dc43ef94 13605\f
06a2c219
GM
13606/***********************************************************************
13607 Initialization
13608 ***********************************************************************/
f451eb13 13609
3afe33e7
RS
13610#ifdef USE_X_TOOLKIT
13611static XrmOptionDescRec emacs_options[] = {
13612 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13613 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13614
13615 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13616 XrmoptionSepArg, NULL},
13617 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13618
13619 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13620 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13621 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13622 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13623 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13624 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13625 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13626};
13627#endif /* USE_X_TOOLKIT */
13628
7a13e894
RS
13629static int x_initialized;
13630
29b38361
KH
13631#ifdef MULTI_KBOARD
13632/* Test whether two display-name strings agree up to the dot that separates
13633 the screen number from the server number. */
13634static int
13635same_x_server (name1, name2)
13636 char *name1, *name2;
13637{
13638 int seen_colon = 0;
cf591cc1
RS
13639 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13640 int system_name_length = strlen (system_name);
13641 int length_until_period = 0;
13642
13643 while (system_name[length_until_period] != 0
13644 && system_name[length_until_period] != '.')
13645 length_until_period++;
13646
13647 /* Treat `unix' like an empty host name. */
13648 if (! strncmp (name1, "unix:", 5))
13649 name1 += 4;
13650 if (! strncmp (name2, "unix:", 5))
13651 name2 += 4;
13652 /* Treat this host's name like an empty host name. */
13653 if (! strncmp (name1, system_name, system_name_length)
13654 && name1[system_name_length] == ':')
13655 name1 += system_name_length;
13656 if (! strncmp (name2, system_name, system_name_length)
13657 && name2[system_name_length] == ':')
13658 name2 += system_name_length;
13659 /* Treat this host's domainless name like an empty host name. */
13660 if (! strncmp (name1, system_name, length_until_period)
13661 && name1[length_until_period] == ':')
13662 name1 += length_until_period;
13663 if (! strncmp (name2, system_name, length_until_period)
13664 && name2[length_until_period] == ':')
13665 name2 += length_until_period;
13666
29b38361
KH
13667 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13668 {
13669 if (*name1 == ':')
13670 seen_colon++;
13671 if (seen_colon && *name1 == '.')
13672 return 1;
13673 }
13674 return (seen_colon
13675 && (*name1 == '.' || *name1 == '\0')
13676 && (*name2 == '.' || *name2 == '\0'));
13677}
13678#endif
13679
334208b7 13680struct x_display_info *
1f8255f2 13681x_term_init (display_name, xrm_option, resource_name)
334208b7 13682 Lisp_Object display_name;
1f8255f2
RS
13683 char *xrm_option;
13684 char *resource_name;
dc6f92b8 13685{
334208b7 13686 int connection;
7a13e894 13687 Display *dpy;
334208b7
RS
13688 struct x_display_info *dpyinfo;
13689 XrmDatabase xrdb;
13690
60439948
KH
13691 BLOCK_INPUT;
13692
7a13e894
RS
13693 if (!x_initialized)
13694 {
13695 x_initialize ();
13696 x_initialized = 1;
13697 }
dc6f92b8 13698
3afe33e7 13699#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13700 /* weiner@footloose.sps.mot.com reports that this causes
13701 errors with X11R5:
13702 X protocol error: BadAtom (invalid Atom parameter)
13703 on protocol request 18skiloaf.
13704 So let's not use it until R6. */
13705#ifdef HAVE_X11XTR6
bdcd49ba
RS
13706 XtSetLanguageProc (NULL, NULL, NULL);
13707#endif
13708
7f9c7f94
RS
13709 {
13710 int argc = 0;
13711 char *argv[3];
13712
13713 argv[0] = "";
13714 argc = 1;
13715 if (xrm_option)
13716 {
13717 argv[argc++] = "-xrm";
13718 argv[argc++] = xrm_option;
13719 }
13720 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13721 resource_name, EMACS_CLASS,
13722 emacs_options, XtNumber (emacs_options),
13723 &argc, argv);
39d8bb4d
KH
13724
13725#ifdef HAVE_X11XTR6
10537cb1 13726 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13727 fixup_locale ();
39d8bb4d 13728#endif
7f9c7f94 13729 }
3afe33e7
RS
13730
13731#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13732#ifdef HAVE_X11R5
13733 XSetLocaleModifiers ("");
13734#endif
7a13e894 13735 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13736#endif /* not USE_X_TOOLKIT */
334208b7 13737
7a13e894
RS
13738 /* Detect failure. */
13739 if (dpy == 0)
60439948
KH
13740 {
13741 UNBLOCK_INPUT;
13742 return 0;
13743 }
7a13e894
RS
13744
13745 /* We have definitely succeeded. Record the new connection. */
13746
13747 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
f04e1297 13748 bzero (dpyinfo, sizeof *dpyinfo);
7a13e894 13749
29b38361
KH
13750#ifdef MULTI_KBOARD
13751 {
13752 struct x_display_info *share;
13753 Lisp_Object tail;
13754
13755 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13756 share = share->next, tail = XCDR (tail))
13757 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13758 XSTRING (display_name)->data))
13759 break;
13760 if (share)
13761 dpyinfo->kboard = share->kboard;
13762 else
13763 {
13764 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13765 init_kboard (dpyinfo->kboard);
59e755be
KH
13766 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13767 {
13768 char *vendor = ServerVendor (dpy);
9b6ed9f3 13769 UNBLOCK_INPUT;
59e755be
KH
13770 dpyinfo->kboard->Vsystem_key_alist
13771 = call1 (Qvendor_specific_keysyms,
13772 build_string (vendor ? vendor : ""));
9b6ed9f3 13773 BLOCK_INPUT;
59e755be
KH
13774 }
13775
29b38361
KH
13776 dpyinfo->kboard->next_kboard = all_kboards;
13777 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13778 /* Don't let the initial kboard remain current longer than necessary.
13779 That would cause problems if a file loaded on startup tries to
06a2c219 13780 prompt in the mini-buffer. */
0ad5446c
KH
13781 if (current_kboard == initial_kboard)
13782 current_kboard = dpyinfo->kboard;
29b38361
KH
13783 }
13784 dpyinfo->kboard->reference_count++;
13785 }
b9737ad3
KH
13786#endif
13787
7a13e894
RS
13788 /* Put this display on the chain. */
13789 dpyinfo->next = x_display_list;
13790 x_display_list = dpyinfo;
13791
13792 /* Put it on x_display_name_list as well, to keep them parallel. */
13793 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13794 x_display_name_list);
8e713be6 13795 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13796
13797 dpyinfo->display = dpy;
dc6f92b8 13798
dc6f92b8 13799#if 0
7a13e894 13800 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13801#endif /* ! 0 */
7a13e894
RS
13802
13803 dpyinfo->x_id_name
fc932ac6
RS
13804 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13805 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13806 + 2);
13807 sprintf (dpyinfo->x_id_name, "%s@%s",
13808 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13809
13810 /* Figure out which modifier bits mean what. */
334208b7 13811 x_find_modifier_meanings (dpyinfo);
f451eb13 13812
ab648270 13813 /* Get the scroll bar cursor. */
7a13e894 13814 dpyinfo->vertical_scroll_bar_cursor
334208b7 13815 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13816
334208b7
RS
13817 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13818 resource_name, EMACS_CLASS);
13819#ifdef HAVE_XRMSETDATABASE
13820 XrmSetDatabase (dpyinfo->display, xrdb);
13821#else
13822 dpyinfo->display->db = xrdb;
13823#endif
547d9db8 13824 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13825 all versions. */
13826 dpyinfo->xrdb = xrdb;
334208b7
RS
13827
13828 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13829 DefaultScreen (dpyinfo->display));
5ff67d81 13830 select_visual (dpyinfo);
43bd1b2b 13831 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13832 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13833 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13834 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13835 dpyinfo->grabbed = 0;
13836 dpyinfo->reference_count = 0;
13837 dpyinfo->icon_bitmap_id = -1;
06a2c219 13838 dpyinfo->font_table = NULL;
7a13e894
RS
13839 dpyinfo->n_fonts = 0;
13840 dpyinfo->font_table_size = 0;
13841 dpyinfo->bitmaps = 0;
13842 dpyinfo->bitmaps_size = 0;
13843 dpyinfo->bitmaps_last = 0;
13844 dpyinfo->scratch_cursor_gc = 0;
13845 dpyinfo->mouse_face_mouse_frame = 0;
13846 dpyinfo->mouse_face_deferred_gc = 0;
13847 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13848 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13849 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894 13850 dpyinfo->mouse_face_window = Qnil;
0a61c667 13851 dpyinfo->mouse_face_overlay = Qnil;
7a13e894
RS
13852 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13853 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13854 dpyinfo->x_focus_frame = 0;
13855 dpyinfo->x_focus_event_frame = 0;
13856 dpyinfo->x_highlight_frame = 0;
06a2c219 13857 dpyinfo->image_cache = make_image_cache ();
334208b7 13858
43bd1b2b 13859 /* See if a private colormap is requested. */
5ff67d81
GM
13860 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13861 {
13862 if (dpyinfo->visual->class == PseudoColor)
13863 {
13864 Lisp_Object value;
13865 value = display_x_get_resource (dpyinfo,
13866 build_string ("privateColormap"),
13867 build_string ("PrivateColormap"),
13868 Qnil, Qnil);
13869 if (STRINGP (value)
13870 && (!strcmp (XSTRING (value)->data, "true")
13871 || !strcmp (XSTRING (value)->data, "on")))
13872 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13873 }
43bd1b2b 13874 }
5ff67d81
GM
13875 else
13876 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13877 dpyinfo->visual, AllocNone);
43bd1b2b 13878
06a2c219
GM
13879 {
13880 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13881 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13882 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13883 dpyinfo->resy = pixels * 25.4 / mm;
13884 pixels = DisplayWidth (dpyinfo->display, screen_number);
13885 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13886 dpyinfo->resx = pixels * 25.4 / mm;
13887 }
13888
334208b7
RS
13889 dpyinfo->Xatom_wm_protocols
13890 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13891 dpyinfo->Xatom_wm_take_focus
13892 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13893 dpyinfo->Xatom_wm_save_yourself
13894 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13895 dpyinfo->Xatom_wm_delete_window
13896 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13897 dpyinfo->Xatom_wm_change_state
13898 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13899 dpyinfo->Xatom_wm_configure_denied
13900 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13901 dpyinfo->Xatom_wm_window_moved
13902 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13903 dpyinfo->Xatom_editres
13904 = XInternAtom (dpyinfo->display, "Editres", False);
13905 dpyinfo->Xatom_CLIPBOARD
13906 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13907 dpyinfo->Xatom_TIMESTAMP
13908 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13909 dpyinfo->Xatom_TEXT
13910 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13911 dpyinfo->Xatom_COMPOUND_TEXT
13912 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13913 dpyinfo->Xatom_DELETE
13914 = XInternAtom (dpyinfo->display, "DELETE", False);
13915 dpyinfo->Xatom_MULTIPLE
13916 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13917 dpyinfo->Xatom_INCR
13918 = XInternAtom (dpyinfo->display, "INCR", False);
13919 dpyinfo->Xatom_EMACS_TMP
13920 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13921 dpyinfo->Xatom_TARGETS
13922 = XInternAtom (dpyinfo->display, "TARGETS", False);
13923 dpyinfo->Xatom_NULL
13924 = XInternAtom (dpyinfo->display, "NULL", False);
13925 dpyinfo->Xatom_ATOM_PAIR
13926 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13927 /* For properties of font. */
13928 dpyinfo->Xatom_PIXEL_SIZE
13929 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13930 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13931 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13932 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13933 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13934 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13935 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13936
06a2c219
GM
13937 /* Ghostscript support. */
13938 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13939 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13940
13941 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13942 False);
13943
547d9db8
KH
13944 dpyinfo->cut_buffers_initialized = 0;
13945
334208b7
RS
13946 connection = ConnectionNumber (dpyinfo->display);
13947 dpyinfo->connection = connection;
13948
dc43ef94 13949 {
5d7cc324
RS
13950 char null_bits[1];
13951
13952 null_bits[0] = 0x00;
dc43ef94
KH
13953
13954 dpyinfo->null_pixel
13955 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13956 null_bits, 1, 1, (long) 0, (long) 0,
13957 1);
13958 }
13959
06a2c219
GM
13960 {
13961 extern int gray_bitmap_width, gray_bitmap_height;
10659c77 13962 extern char *gray_bitmap_bits;
06a2c219
GM
13963 dpyinfo->gray
13964 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13965 gray_bitmap_bits,
13966 gray_bitmap_width, gray_bitmap_height,
13967 (unsigned long) 1, (unsigned long) 0, 1);
13968 }
13969
f5d11644
GM
13970#ifdef HAVE_X_I18N
13971 xim_initialize (dpyinfo, resource_name);
13972#endif
13973
87485d6f
MW
13974#ifdef subprocesses
13975 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13976 if (connection != 0)
7a13e894 13977 add_keyboard_wait_descriptor (connection);
87485d6f 13978#endif
6d4238f3 13979
041b69ac 13980#ifndef F_SETOWN_BUG
dc6f92b8 13981#ifdef F_SETOWN
dc6f92b8 13982#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13983 /* stdin is a socket here */
334208b7 13984 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13985#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13986 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13987#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13988#endif /* ! defined (F_SETOWN) */
041b69ac 13989#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13990
13991#ifdef SIGIO
eee20f6a
KH
13992 if (interrupt_input)
13993 init_sigio (connection);
c118dd06 13994#endif /* ! defined (SIGIO) */
dc6f92b8 13995
51b592fb 13996#ifdef USE_LUCID
f8c39f51 13997#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13998 /* Make sure that we have a valid font for dialog boxes
13999 so that Xt does not crash. */
14000 {
14001 Display *dpy = dpyinfo->display;
14002 XrmValue d, fr, to;
14003 Font font;
e99db5a1 14004 int count;
51b592fb
RS
14005
14006 d.addr = (XPointer)&dpy;
14007 d.size = sizeof (Display *);
14008 fr.addr = XtDefaultFont;
14009 fr.size = sizeof (XtDefaultFont);
14010 to.size = sizeof (Font *);
14011 to.addr = (XPointer)&font;
e99db5a1 14012 count = x_catch_errors (dpy);
51b592fb
RS
14013 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
14014 abort ();
14015 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
14016 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 14017 x_uncatch_errors (dpy, count);
51b592fb
RS
14018 }
14019#endif
f8c39f51 14020#endif
51b592fb 14021
34e23e5a
GM
14022 /* See if we should run in synchronous mode. This is useful
14023 for debugging X code. */
14024 {
14025 Lisp_Object value;
14026 value = display_x_get_resource (dpyinfo,
14027 build_string ("synchronous"),
14028 build_string ("Synchronous"),
14029 Qnil, Qnil);
14030 if (STRINGP (value)
14031 && (!strcmp (XSTRING (value)->data, "true")
14032 || !strcmp (XSTRING (value)->data, "on")))
14033 XSynchronize (dpyinfo->display, True);
14034 }
14035
60439948
KH
14036 UNBLOCK_INPUT;
14037
7a13e894
RS
14038 return dpyinfo;
14039}
14040\f
14041/* Get rid of display DPYINFO, assuming all frames are already gone,
14042 and without sending any more commands to the X server. */
dc6f92b8 14043
7a13e894
RS
14044void
14045x_delete_display (dpyinfo)
14046 struct x_display_info *dpyinfo;
14047{
14048 delete_keyboard_wait_descriptor (dpyinfo->connection);
14049
14050 /* Discard this display from x_display_name_list and x_display_list.
14051 We can't use Fdelq because that can quit. */
14052 if (! NILP (x_display_name_list)
8e713be6
KR
14053 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
14054 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
14055 else
14056 {
14057 Lisp_Object tail;
14058
14059 tail = x_display_name_list;
8e713be6 14060 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 14061 {
bffcfca9 14062 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 14063 {
8e713be6 14064 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
14065 break;
14066 }
8e713be6 14067 tail = XCDR (tail);
7a13e894
RS
14068 }
14069 }
14070
9bda743f
GM
14071 if (next_noop_dpyinfo == dpyinfo)
14072 next_noop_dpyinfo = dpyinfo->next;
14073
7a13e894
RS
14074 if (x_display_list == dpyinfo)
14075 x_display_list = dpyinfo->next;
7f9c7f94
RS
14076 else
14077 {
14078 struct x_display_info *tail;
7a13e894 14079
7f9c7f94
RS
14080 for (tail = x_display_list; tail; tail = tail->next)
14081 if (tail->next == dpyinfo)
14082 tail->next = tail->next->next;
14083 }
7a13e894 14084
0d777288
RS
14085#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
14086#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
14087 XrmDestroyDatabase (dpyinfo->xrdb);
14088#endif
0d777288 14089#endif
29b38361
KH
14090#ifdef MULTI_KBOARD
14091 if (--dpyinfo->kboard->reference_count == 0)
39f79001 14092 delete_kboard (dpyinfo->kboard);
b9737ad3 14093#endif
f5d11644
GM
14094#ifdef HAVE_X_I18N
14095 if (dpyinfo->xim)
14096 xim_close_dpy (dpyinfo);
14097#endif
14098
b9737ad3
KH
14099 xfree (dpyinfo->font_table);
14100 xfree (dpyinfo->x_id_name);
f04e1297 14101 xfree (dpyinfo->color_cells);
b9737ad3 14102 xfree (dpyinfo);
7a13e894 14103}
f04e1297 14104
7a13e894
RS
14105\f
14106/* Set up use of X before we make the first connection. */
14107
06a2c219
GM
14108static struct redisplay_interface x_redisplay_interface =
14109{
14110 x_produce_glyphs,
14111 x_write_glyphs,
14112 x_insert_glyphs,
14113 x_clear_end_of_line,
14114 x_scroll_run,
14115 x_after_update_window_line,
14116 x_update_window_begin,
14117 x_update_window_end,
14118 XTcursor_to,
14119 x_flush,
71b8321e 14120 x_clear_mouse_face,
66ac4b0e
GM
14121 x_get_glyph_overhangs,
14122 x_fix_overlapping_area
06a2c219
GM
14123};
14124
dfcf069d 14125void
7a13e894
RS
14126x_initialize ()
14127{
06a2c219
GM
14128 rif = &x_redisplay_interface;
14129
14130 clear_frame_hook = x_clear_frame;
14131 ins_del_lines_hook = x_ins_del_lines;
14132 change_line_highlight_hook = x_change_line_highlight;
14133 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
14134 ring_bell_hook = XTring_bell;
14135 reset_terminal_modes_hook = XTreset_terminal_modes;
14136 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
14137 update_begin_hook = x_update_begin;
14138 update_end_hook = x_update_end;
dc6f92b8
JB
14139 set_terminal_window_hook = XTset_terminal_window;
14140 read_socket_hook = XTread_socket;
b8009dd1 14141 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 14142 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 14143 mouse_position_hook = XTmouse_position;
f451eb13 14144 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 14145 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
14146 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
14147 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
14148 redeem_scroll_bar_hook = XTredeem_scroll_bar;
14149 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 14150 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 14151
f676886a 14152 scroll_region_ok = 1; /* we'll scroll partial frames */
9017309f 14153 char_ins_del_ok = 1;
dc6f92b8
JB
14154 line_ins_del_ok = 1; /* we'll just blt 'em */
14155 fast_clear_end_of_line = 1; /* X does this well */
58769bee 14156 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
14157 off the bottom */
14158 baud_rate = 19200;
14159
7a13e894 14160 x_noop_count = 0;
9ea173e8 14161 last_tool_bar_item = -1;
06a2c219
GM
14162 any_help_event_p = 0;
14163
b30b24cb
RS
14164 /* Try to use interrupt input; if we can't, then start polling. */
14165 Fset_input_mode (Qt, Qnil, Qt, Qnil);
14166
7f9c7f94
RS
14167#ifdef USE_X_TOOLKIT
14168 XtToolkitInitialize ();
14169 Xt_app_con = XtCreateApplicationContext ();
665881ad 14170 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
14171
14172 /* Install an asynchronous timer that processes Xt timeout events
14173 every 0.1s. This is necessary because some widget sets use
14174 timeouts internally, for example the LessTif menu bar, or the
14175 Xaw3d scroll bar. When Xt timouts aren't processed, these
14176 widgets don't behave normally. */
14177 {
14178 EMACS_TIME interval;
14179 EMACS_SET_SECS_USECS (interval, 0, 100000);
14180 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
14181 }
db74249b 14182#endif
bffcfca9 14183
eccc05db 14184#ifdef USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
14185 xaw3d_arrow_scroll = False;
14186 xaw3d_pick_top = True;
7f9c7f94
RS
14187#endif
14188
58769bee 14189 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 14190 original error handler. */
e99db5a1 14191 XSetErrorHandler (x_error_handler);
334208b7 14192 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 14193
06a2c219 14194 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
14195#ifdef SIGWINCH
14196 signal (SIGWINCH, SIG_DFL);
c118dd06 14197#endif /* ! defined (SIGWINCH) */
dc6f92b8 14198
92e2441b 14199 signal (SIGPIPE, x_connection_signal);
dc6f92b8 14200}
55123275 14201
06a2c219 14202
55123275
JB
14203void
14204syms_of_xterm ()
14205{
e99db5a1
RS
14206 staticpro (&x_error_message_string);
14207 x_error_message_string = Qnil;
14208
7a13e894
RS
14209 staticpro (&x_display_name_list);
14210 x_display_name_list = Qnil;
334208b7 14211
ab648270 14212 staticpro (&last_mouse_scroll_bar);
e53cb100 14213 last_mouse_scroll_bar = Qnil;
59e755be
KH
14214
14215 staticpro (&Qvendor_specific_keysyms);
14216 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
14217
14218 staticpro (&last_mouse_press_frame);
14219 last_mouse_press_frame = Qnil;
06a2c219 14220
06a2c219 14221 help_echo = Qnil;
be010514
GM
14222 staticpro (&help_echo);
14223 help_echo_object = Qnil;
14224 staticpro (&help_echo_object);
7cea38bc
GM
14225 help_echo_window = Qnil;
14226 staticpro (&help_echo_window);
06a2c219 14227 previous_help_echo = Qnil;
be010514
GM
14228 staticpro (&previous_help_echo);
14229 help_echo_pos = -1;
06a2c219
GM
14230
14231 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
14232 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
14233For example, if a block cursor is over a tab, it will be drawn as\n\
14234wide as that tab on the display.");
14235 x_stretch_cursor_p = 0;
14236
5bf04520
GM
14237 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
14238 "What X toolkit scroll bars Emacs uses.\n\
14239A value of nil means Emacs doesn't use X toolkit scroll bars.\n\
14240Otherwise, value is a symbol describing the X toolkit.");
eccc05db 14241#ifdef USE_TOOLKIT_SCROLL_BARS
5bf04520
GM
14242#ifdef USE_MOTIF
14243 Vx_toolkit_scroll_bars = intern ("motif");
14244#elif defined HAVE_XAW3D
14245 Vx_toolkit_scroll_bars = intern ("xaw3d");
14246#else
14247 Vx_toolkit_scroll_bars = intern ("xaw");
14248#endif
06a2c219 14249#else
5bf04520 14250 Vx_toolkit_scroll_bars = Qnil;
06a2c219
GM
14251#endif
14252
06a2c219
GM
14253 staticpro (&last_mouse_motion_frame);
14254 last_mouse_motion_frame = Qnil;
55123275 14255}
6cf0ae86
RS
14256
14257#endif /* not HAVE_X_WINDOWS */