(x_clear_image_1): New function.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
1c7e22fd 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
06a2c219 3 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
06a2c219 22/* New display code by Gerd Moellmann <gerd@gnu.org>. */
3afe33e7
RS
23/* Xt features made by Fred Pierresteguy. */
24
68c45bf0
PE
25#include <config.h>
26
039440c4 27/* On 4.3 these lose if they come after xterm.h. */
039440c4 28/* Putting these at the beginning seems to be standard for other .c files. */
039440c4
RS
29#include <signal.h>
30
4846819e
RS
31#include <stdio.h>
32
dc6f92b8
JB
33#ifdef HAVE_X_WINDOWS
34
35#include "lisp.h"
9ac0d9e0 36#include "blockinput.h"
dc6f92b8 37
ae79c227
AS
38/* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40#include "syssignal.h"
41
dc6f92b8
JB
42/* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44#include "xterm.h"
f451eb13 45#include <X11/cursorfont.h>
dc6f92b8
JB
46
47/* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49#ifndef makedev
50#include <sys/types.h>
c118dd06 51#endif /* makedev */
dc6f92b8 52
6df54671 53#ifdef BSD_SYSTEM
dc6f92b8 54#include <sys/ioctl.h>
6df54671 55#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 56
2d368234 57#include "systty.h"
3a2712f9 58#include "systime.h"
dc6f92b8 59
b8009dd1 60#ifndef INCLUDED_FCNTL
dc6f92b8 61#include <fcntl.h>
b8009dd1 62#endif
dc6f92b8
JB
63#include <ctype.h>
64#include <errno.h>
65#include <setjmp.h>
66#include <sys/stat.h>
a0a7635f
RS
67/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68/* #include <sys/param.h> */
dc6f92b8 69
dc43ef94 70#include "charset.h"
379b5ac0 71#include "coding.h"
dc43ef94 72#include "ccl.h"
7a13e894 73#include "frame.h"
dc6f92b8 74#include "dispextern.h"
ee569018 75#include "fontset.h"
dc6f92b8
JB
76#include "termhooks.h"
77#include "termopts.h"
78#include "termchar.h"
79#if 0
80#include "sink.h"
81#include "sinkmask.h"
c118dd06 82#endif /* ! 0 */
dc6f92b8 83#include "gnu.h"
dc6f92b8 84#include "disptab.h"
dc6f92b8 85#include "buffer.h"
f451eb13 86#include "window.h"
3b2fa4e6 87#include "keyboard.h"
bde7c500 88#include "intervals.h"
dfcf069d 89#include "process.h"
bffcfca9 90#include "atimer.h"
dc6f92b8 91
d2bd6bc4
RS
92#ifdef USE_X_TOOLKIT
93#include <X11/Shell.h>
94#endif
95
06a2c219
GM
96#ifdef HAVE_SYS_TIME_H
97#include <sys/time.h>
98#endif
99#ifdef HAVE_UNISTD_H
100#include <unistd.h>
101#endif
102
3afe33e7 103#ifdef USE_X_TOOLKIT
06a2c219 104
952291d9
GM
105extern void free_frame_menubar P_ ((struct frame *));
106extern struct frame *x_menubar_window_to_frame P_ ((struct x_display_info *,
107 int));
06a2c219 108
0fdff6bb
RS
109#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
110#define HACK_EDITRES
111extern void _XEditResCheckMessages ();
112#endif /* not NO_EDITRES */
06a2c219
GM
113
114/* Include toolkit specific headers for the scroll bar widget. */
115
116#ifdef USE_TOOLKIT_SCROLL_BARS
117#if defined USE_MOTIF
118#include <Xm/Xm.h> /* for LESSTIF_VERSION */
119#include <Xm/ScrollBar.h>
120#include <Xm/ScrollBarP.h>
ec18280f
SM
121#else /* !USE_MOTIF i.e. use Xaw */
122
123#ifdef HAVE_XAW3D
06a2c219 124#include <X11/Xaw3d/Simple.h>
06a2c219
GM
125#include <X11/Xaw3d/Scrollbar.h>
126#define ARROW_SCROLLBAR
127#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
128#else /* !HAVE_XAW3D */
129#include <X11/Xaw/Simple.h>
130#include <X11/Xaw/Scrollbar.h>
131#endif /* !HAVE_XAW3D */
132#ifndef XtNpickTop
133#define XtNpickTop "pickTop"
134#endif /* !XtNpickTop */
135#endif /* !USE_MOTIF */
06a2c219
GM
136#endif /* USE_TOOLKIT_SCROLL_BARS */
137
3afe33e7
RS
138#endif /* USE_X_TOOLKIT */
139
b849c413
RS
140#ifndef USE_X_TOOLKIT
141#define x_any_window_to_frame x_window_to_frame
5627c40e 142#define x_top_window_to_frame x_window_to_frame
b849c413
RS
143#endif
144
546e6d5b 145#ifdef USE_X_TOOLKIT
d067ea8b 146#include "widget.h"
546e6d5b
RS
147#ifndef XtNinitialState
148#define XtNinitialState "initialState"
149#endif
150#endif
151
80528801
KH
152#ifdef SOLARIS2
153/* memmove will be defined as a macro in Xfuncs.h unless
154 <string.h> is included beforehand. The declaration for memmove in
155 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
156#include <string.h>
157#endif
158
e4b68333 159#ifndef min
06a2c219 160#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
161#endif
162#ifndef max
06a2c219
GM
163#define max(a,b) ((a) > (b) ? (a) : (b))
164#endif
165
166#define abs(x) ((x) < 0 ? -(x) : (x))
167
168#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
169
170\f
171/* Bitmaps for truncated lines. */
172
173enum bitmap_type
174{
175 NO_BITMAP,
176 LEFT_TRUNCATION_BITMAP,
177 RIGHT_TRUNCATION_BITMAP,
178 OVERLAY_ARROW_BITMAP,
179 CONTINUED_LINE_BITMAP,
180 CONTINUATION_LINE_BITMAP,
181 ZV_LINE_BITMAP
182};
183
184/* Bitmap drawn to indicate lines not displaying text if
185 `indicate-empty-lines' is non-nil. */
186
187#define zv_width 8
188#define zv_height 8
189static unsigned char zv_bits[] = {
190 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
191
192/* An arrow like this: `<-'. */
193
194#define left_width 8
195#define left_height 8
196static unsigned char left_bits[] = {
197 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
198
110859fc
GM
199/* Right truncation arrow bitmap `->'. */
200
201#define right_width 8
202#define right_height 8
203static unsigned char right_bits[] = {
204 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
205
06a2c219
GM
206/* Marker for continued lines. */
207
208#define continued_width 8
209#define continued_height 8
210static unsigned char continued_bits[] = {
110859fc
GM
211 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
212
213/* Marker for continuation lines. */
06a2c219
GM
214
215#define continuation_width 8
216#define continuation_height 8
217static unsigned char continuation_bits[] = {
110859fc 218 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 219
110859fc 220/* Overlay arrow bitmap. */
06a2c219 221
110859fc
GM
222#if 0
223/* A bomb. */
06a2c219
GM
224#define ov_width 8
225#define ov_height 8
226static unsigned char ov_bits[] = {
227 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 228#else
110859fc 229/* A triangular arrow. */
06a2c219
GM
230#define ov_width 8
231#define ov_height 8
232static unsigned char ov_bits[] = {
110859fc
GM
233 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
234
e4b68333 235#endif
06a2c219
GM
236
237extern Lisp_Object Qhelp_echo;
238
69388238 239\f
06a2c219
GM
240/* Non-zero means Emacs uses toolkit scroll bars. */
241
242int x_toolkit_scroll_bars_p;
243
244/* If a string, XTread_socket generates an event to display that string.
245 (The display is done in read_char.) */
246
247static Lisp_Object help_echo;
7cea38bc 248static Lisp_Object help_echo_window;
be010514
GM
249static Lisp_Object help_echo_object;
250static int help_echo_pos;
06a2c219
GM
251
252/* Temporary variable for XTread_socket. */
253
254static Lisp_Object previous_help_echo;
255
256/* Non-zero means that a HELP_EVENT has been generated since Emacs
257 start. */
258
259static int any_help_event_p;
260
261/* Non-zero means draw block and hollow cursor as wide as the glyph
262 under it. For example, if a block cursor is over a tab, it will be
263 drawn as wide as that tab on the display. */
264
265int x_stretch_cursor_p;
266
267/* This is a chain of structures for all the X displays currently in
268 use. */
269
334208b7 270struct x_display_info *x_display_list;
dc6f92b8 271
06a2c219
GM
272/* This is a list of cons cells, each of the form (NAME
273 . FONT-LIST-CACHE), one for each element of x_display_list and in
274 the same order. NAME is the name of the frame. FONT-LIST-CACHE
275 records previous values returned by x-list-fonts. */
276
7a13e894 277Lisp_Object x_display_name_list;
f451eb13 278
987d2ad1 279/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
280 This is set by update_begin and looked at by all the XT functions.
281 It is zero while not inside an update. In that case, the XT
282 functions assume that `selected_frame' is the frame to apply to. */
283
d0386f2a 284extern struct frame *updating_frame;
dc6f92b8 285
dfcf069d 286extern int waiting_for_input;
0e81d8cd 287
06a2c219
GM
288/* This is a frame waiting to be auto-raised, within XTread_socket. */
289
0134a210
RS
290struct frame *pending_autoraise_frame;
291
7f9c7f94
RS
292#ifdef USE_X_TOOLKIT
293/* The application context for Xt use. */
294XtAppContext Xt_app_con;
06a2c219
GM
295static String Xt_default_resources[] = {0};
296#endif /* USE_X_TOOLKIT */
665881ad 297
06a2c219
GM
298/* Nominal cursor position -- where to draw output.
299 HPOS and VPOS are window relative glyph matrix coordinates.
300 X and Y are window relative pixel coordinates. */
dc6f92b8 301
06a2c219 302struct cursor_pos output_cursor;
dc6f92b8 303
bffcfca9
GM
304/* Non-zero means user is interacting with a toolkit scroll bar. */
305
306static int toolkit_scroll_bar_interaction;
dc6f92b8 307
69388238
RS
308/* Mouse movement.
309
06a2c219 310 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
311 so that we would have to call XQueryPointer after each MotionNotify
312 event to ask for another such event. However, this made mouse tracking
313 slow, and there was a bug that made it eventually stop.
314
315 Simply asking for MotionNotify all the time seems to work better.
316
69388238
RS
317 In order to avoid asking for motion events and then throwing most
318 of them away or busy-polling the server for mouse positions, we ask
319 the server for pointer motion hints. This means that we get only
320 one event per group of mouse movements. "Groups" are delimited by
321 other kinds of events (focus changes and button clicks, for
322 example), or by XQueryPointer calls; when one of these happens, we
323 get another MotionNotify event the next time the mouse moves. This
324 is at least as efficient as getting motion events when mouse
325 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 326 is off. */
69388238
RS
327
328/* Where the mouse was last time we reported a mouse event. */
69388238 329
06a2c219
GM
330FRAME_PTR last_mouse_frame;
331static XRectangle last_mouse_glyph;
2237cac9
RS
332static Lisp_Object last_mouse_press_frame;
333
69388238
RS
334/* The scroll bar in which the last X motion event occurred.
335
06a2c219
GM
336 If the last X motion event occurred in a scroll bar, we set this so
337 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
338 an ordinary motion.
339
06a2c219
GM
340 If the last X motion event didn't occur in a scroll bar, we set
341 this to Qnil, to tell XTmouse_position to return an ordinary motion
342 event. */
343
69388238
RS
344static Lisp_Object last_mouse_scroll_bar;
345
69388238
RS
346/* This is a hack. We would really prefer that XTmouse_position would
347 return the time associated with the position it returns, but there
06a2c219 348 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
349 along with the position query. So, we just keep track of the time
350 of the last movement we received, and return that in hopes that
351 it's somewhat accurate. */
06a2c219 352
69388238
RS
353static Time last_mouse_movement_time;
354
06a2c219
GM
355/* Incremented by XTread_socket whenever it really tries to read
356 events. */
357
c0a04927
RS
358#ifdef __STDC__
359static int volatile input_signal_count;
360#else
361static int input_signal_count;
362#endif
363
7a13e894 364/* Used locally within XTread_socket. */
06a2c219 365
7a13e894 366static int x_noop_count;
dc6f92b8 367
7a13e894 368/* Initial values of argv and argc. */
06a2c219 369
7a13e894
RS
370extern char **initial_argv;
371extern int initial_argc;
dc6f92b8 372
7a13e894 373extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 374
06a2c219 375/* Tells if a window manager is present or not. */
7a13e894
RS
376
377extern Lisp_Object Vx_no_window_manager;
dc6f92b8 378
c2df547c 379extern Lisp_Object Qface, Qmouse_face;
b8009dd1 380
dc6f92b8
JB
381extern int errno;
382
dfeccd2d 383/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 384
64bb1782
RS
385extern int extra_keyboard_modifiers;
386
59e755be
KH
387static Lisp_Object Qvendor_specific_keysyms;
388
952291d9
GM
389extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
390extern Lisp_Object x_icon_type P_ ((struct frame *));
c32cdd9a 391
7a13e894 392
06a2c219
GM
393/* Enumeration for overriding/changing the face to use for drawing
394 glyphs in x_draw_glyphs. */
395
396enum draw_glyphs_face
397{
398 DRAW_NORMAL_TEXT,
399 DRAW_INVERSE_VIDEO,
400 DRAW_CURSOR,
401 DRAW_MOUSE_FACE,
402 DRAW_IMAGE_RAISED,
403 DRAW_IMAGE_SUNKEN
404};
405
71b8321e 406static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
407static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
408void x_delete_display P_ ((struct x_display_info *));
409static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
410 unsigned));
411static int fast_find_position P_ ((struct window *, int, int *, int *,
412 int *, int *));
413static void set_output_cursor P_ ((struct cursor_pos *));
414static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
415 int *, int *, int *));
416static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 417static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
418static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
419static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
420static void show_mouse_face P_ ((struct x_display_info *,
421 enum draw_glyphs_face));
422static int x_io_error_quitter P_ ((Display *));
423int x_catch_errors P_ ((Display *));
424void x_uncatch_errors P_ ((Display *, int));
425void x_lower_frame P_ ((struct frame *));
426void x_scroll_bar_clear P_ ((struct frame *));
427int x_had_errors_p P_ ((Display *));
428void x_wm_set_size_hint P_ ((struct frame *, long, int));
429void x_raise_frame P_ ((struct frame *));
430void x_set_window_size P_ ((struct frame *, int, int, int));
431void x_wm_set_window_state P_ ((struct frame *, int));
432void x_wm_set_icon_pixmap P_ ((struct frame *, int));
433void x_initialize P_ ((void));
434static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
435static int x_compute_min_glyph_bounds P_ ((struct frame *));
436static void x_draw_phys_cursor_glyph P_ ((struct window *,
437 struct glyph_row *,
438 enum draw_glyphs_face));
439static void x_update_end P_ ((struct frame *));
440static void XTframe_up_to_date P_ ((struct frame *));
441static void XTreassert_line_highlight P_ ((int, int));
442static void x_change_line_highlight P_ ((int, int, int, int));
443static void XTset_terminal_modes P_ ((void));
444static void XTreset_terminal_modes P_ ((void));
445static void XTcursor_to P_ ((int, int, int, int));
446static void x_write_glyphs P_ ((struct glyph *, int));
447static void x_clear_end_of_line P_ ((int));
448static void x_clear_frame P_ ((void));
449static void x_clear_cursor P_ ((struct window *));
450static void frame_highlight P_ ((struct frame *));
451static void frame_unhighlight P_ ((struct frame *));
452static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
453static void XTframe_rehighlight P_ ((struct frame *));
454static void x_frame_rehighlight P_ ((struct x_display_info *));
455static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
f02d8aa0 456static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
06a2c219
GM
457static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
458 XRectangle *));
459static void expose_frame P_ ((struct frame *, int, int, int, int));
460static void expose_window_tree P_ ((struct window *, XRectangle *));
461static void expose_window P_ ((struct window *, XRectangle *));
462static void expose_area P_ ((struct window *, struct glyph_row *,
463 XRectangle *, enum glyph_row_area));
464static void expose_line P_ ((struct window *, struct glyph_row *,
465 XRectangle *));
466static void x_update_cursor_in_window_tree P_ ((struct window *, int));
467static void x_update_window_cursor P_ ((struct window *, int));
468static void x_erase_phys_cursor P_ ((struct window *));
469void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
470static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
471 enum bitmap_type));
472
473static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
474 GC, int));
475static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
476static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
477static void note_overwritten_text_cursor P_ ((struct window *, int, int));
478static void x_flush P_ ((struct frame *f));
952291d9
GM
479static void x_update_begin P_ ((struct frame *));
480static void x_update_window_begin P_ ((struct window *));
481static void x_draw_vertical_border P_ ((struct window *));
482static void x_after_update_window_line P_ ((struct glyph_row *));
483static INLINE void take_vertical_position_into_account P_ ((struct it *));
484static void x_produce_stretch_glyph P_ ((struct it *));
485
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
GM
688{
689 if (!w->pseudo_window_p)
690 {
71b8321e
GM
691 struct x_display_info *dpyinfo
692 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
693
06a2c219 694 BLOCK_INPUT;
71b8321e
GM
695
696 /* If a row with mouse-face was overwritten, arrange for
697 XTframe_up_to_date to redisplay the mouse highlight. */
698 if (mouse_face_overwritten_p)
699 {
700 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
701 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
702 dpyinfo->mouse_face_window = Qnil;
703 }
704
06a2c219
GM
705 if (cursor_on_p)
706 x_display_and_set_cursor (w, 1, output_cursor.hpos,
707 output_cursor.vpos,
708 output_cursor.x, output_cursor.y);
71b8321e 709
06a2c219
GM
710 x_draw_vertical_border (w);
711 UNBLOCK_INPUT;
712 }
713
714 updated_window = NULL;
715}
dc6f92b8 716
dc6f92b8 717
06a2c219
GM
718/* End update of frame F. This function is installed as a hook in
719 update_end. */
720
721static void
722x_update_end (f)
723 struct frame *f;
724{
725 /* Mouse highlight may be displayed again. */
aa8bff2e 726 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 727
06a2c219 728 BLOCK_INPUT;
334208b7 729 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
730 UNBLOCK_INPUT;
731}
b8009dd1 732
06a2c219
GM
733
734/* This function is called from various places in xdisp.c whenever a
735 complete update has been performed. The global variable
736 updated_window is not available here. */
b8009dd1 737
dfcf069d 738static void
b8009dd1 739XTframe_up_to_date (f)
06a2c219 740 struct frame *f;
b8009dd1 741{
06a2c219 742 if (FRAME_X_P (f))
514e4681 743 {
06a2c219 744 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
71b8321e 745
06a2c219
GM
746 if (dpyinfo->mouse_face_deferred_gc
747 || f == dpyinfo->mouse_face_mouse_frame)
748 {
749 BLOCK_INPUT;
750 if (dpyinfo->mouse_face_mouse_frame)
751 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
752 dpyinfo->mouse_face_mouse_x,
753 dpyinfo->mouse_face_mouse_y);
754 dpyinfo->mouse_face_deferred_gc = 0;
755 UNBLOCK_INPUT;
756 }
514e4681 757 }
b8009dd1 758}
06a2c219
GM
759
760
761/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
762 arrow bitmaps, or clear the areas where they would be displayed
763 before DESIRED_ROW is made current. The window being updated is
764 found in updated_window. This function It is called from
765 update_window_line only if it is known that there are differences
766 between bitmaps to be drawn between current row and DESIRED_ROW. */
767
768static void
769x_after_update_window_line (desired_row)
770 struct glyph_row *desired_row;
771{
772 struct window *w = updated_window;
773
774 xassert (w);
775
776 if (!desired_row->mode_line_p && !w->pseudo_window_p)
777 {
778 BLOCK_INPUT;
779 x_draw_row_bitmaps (w, desired_row);
780
781 /* When a window has disappeared, make sure that no rest of
782 full-width rows stays visible in the internal border. */
783 if (windows_or_buffers_changed)
784 {
785 struct frame *f = XFRAME (w->frame);
786 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
787 int height = desired_row->visible_height;
110859fc
GM
788 int x = (window_box_right (w, -1)
789 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
790 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
791
792 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
793 x, y, width, height, False);
794 }
795
796 UNBLOCK_INPUT;
797 }
798}
799
800
801/* Draw the bitmap WHICH in one of the areas to the left or right of
802 window W. ROW is the glyph row for which to display the bitmap; it
803 determines the vertical position at which the bitmap has to be
804 drawn. */
805
806static void
807x_draw_bitmap (w, row, which)
808 struct window *w;
809 struct glyph_row *row;
810 enum bitmap_type which;
811{
812 struct frame *f = XFRAME (WINDOW_FRAME (w));
813 Display *display = FRAME_X_DISPLAY (f);
814 Window window = FRAME_X_WINDOW (f);
815 int x, y, wd, h, dy;
816 unsigned char *bits;
817 Pixmap pixmap;
818 GC gc = f->output_data.x->normal_gc;
819 struct face *face;
820 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
821
822 /* Must clip because of partially visible lines. */
823 x_clip_to_row (w, row, gc, 1);
824
825 switch (which)
826 {
827 case LEFT_TRUNCATION_BITMAP:
828 wd = left_width;
829 h = left_height;
830 bits = left_bits;
831 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
832 - wd
110859fc 833 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
834 break;
835
836 case OVERLAY_ARROW_BITMAP:
837 wd = left_width;
838 h = left_height;
839 bits = ov_bits;
840 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
841 - wd
110859fc 842 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
843 break;
844
845 case RIGHT_TRUNCATION_BITMAP:
846 wd = right_width;
847 h = right_height;
848 bits = right_bits;
849 x = window_box_right (w, -1);
110859fc 850 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
851 break;
852
853 case CONTINUED_LINE_BITMAP:
854 wd = right_width;
855 h = right_height;
856 bits = continued_bits;
857 x = window_box_right (w, -1);
110859fc 858 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
859 break;
860
861 case CONTINUATION_LINE_BITMAP:
862 wd = continuation_width;
863 h = continuation_height;
864 bits = continuation_bits;
865 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
866 - wd
110859fc 867 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
868 break;
869
870 case ZV_LINE_BITMAP:
871 wd = zv_width;
872 h = zv_height;
873 bits = zv_bits;
874 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
875 - wd
110859fc 876 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
877 break;
878
879 default:
880 abort ();
881 }
882
883 /* Convert to frame coordinates. Set dy to the offset in the row to
884 start drawing the bitmap. */
885 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
886 dy = (row->height - h) / 2;
887
888 /* Draw the bitmap. I believe these small pixmaps can be cached
889 by the server. */
890 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
891 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
892 face->foreground,
893 face->background, depth);
894 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
895 XFreePixmap (display, pixmap);
896 XSetClipMask (display, gc, None);
897}
898
899
900/* Draw flags bitmaps for glyph row ROW on window W. Call this
901 function with input blocked. */
902
903static void
904x_draw_row_bitmaps (w, row)
905 struct window *w;
906 struct glyph_row *row;
907{
908 struct frame *f = XFRAME (w->frame);
909 enum bitmap_type bitmap;
910 struct face *face;
045dee35 911 int header_line_height = -1;
06a2c219
GM
912
913 xassert (interrupt_input_blocked);
914
915 /* If row is completely invisible, because of vscrolling, we
916 don't have to draw anything. */
917 if (row->visible_height <= 0)
918 return;
919
920 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
921 PREPARE_FACE_FOR_DISPLAY (f, face);
922
923 /* Decide which bitmap to draw at the left side. */
924 if (row->overlay_arrow_p)
925 bitmap = OVERLAY_ARROW_BITMAP;
926 else if (row->truncated_on_left_p)
927 bitmap = LEFT_TRUNCATION_BITMAP;
928 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
929 bitmap = CONTINUATION_LINE_BITMAP;
930 else if (row->indicate_empty_line_p)
931 bitmap = ZV_LINE_BITMAP;
932 else
933 bitmap = NO_BITMAP;
934
935 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
936 the flags area. */
937 if (bitmap == NO_BITMAP
110859fc 938 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
939 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
940 {
941 /* If W has a vertical border to its left, don't draw over it. */
942 int border = ((XFASTINT (w->left) > 0
943 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
944 ? 1 : 0);
945 int left = window_box_left (w, -1);
946
045dee35
GM
947 if (header_line_height < 0)
948 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
949
950 /* In case the same realized face is used for bitmap areas and
951 for something displayed in the text (e.g. face `region' on
952 mono-displays, the fill style may have been changed to
953 FillSolid in x_draw_glyph_string_background. */
954 if (face->stipple)
955 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
956 else
957 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
958
06a2c219
GM
959 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
960 face->gc,
961 (left
110859fc 962 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 963 + border),
045dee35 964 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 965 row->y)),
110859fc 966 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 967 row->visible_height);
dcd08bfb
GM
968 if (!face->stipple)
969 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
970 }
971
972 /* Draw the left bitmap. */
973 if (bitmap != NO_BITMAP)
974 x_draw_bitmap (w, row, bitmap);
975
976 /* Decide which bitmap to draw at the right side. */
977 if (row->truncated_on_right_p)
978 bitmap = RIGHT_TRUNCATION_BITMAP;
979 else if (row->continued_p)
980 bitmap = CONTINUED_LINE_BITMAP;
981 else
982 bitmap = NO_BITMAP;
983
984 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
985 the flags area. */
986 if (bitmap == NO_BITMAP
110859fc 987 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
988 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
989 {
990 int right = window_box_right (w, -1);
991
045dee35
GM
992 if (header_line_height < 0)
993 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
994
995 /* In case the same realized face is used for bitmap areas and
996 for something displayed in the text (e.g. face `region' on
997 mono-displays, the fill style may have been changed to
998 FillSolid in x_draw_glyph_string_background. */
999 if (face->stipple)
1000 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1001 else
1002 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
1003 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
1004 face->gc,
1005 right,
045dee35 1006 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 1007 row->y)),
110859fc 1008 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 1009 row->visible_height);
dcd08bfb
GM
1010 if (!face->stipple)
1011 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
1012 }
1013
1014 /* Draw the right bitmap. */
1015 if (bitmap != NO_BITMAP)
1016 x_draw_bitmap (w, row, bitmap);
1017}
1018
dc6f92b8 1019\f
06a2c219
GM
1020/***********************************************************************
1021 Line Highlighting
1022 ***********************************************************************/
dc6f92b8 1023
06a2c219
GM
1024/* External interface to control of standout mode. Not used for X
1025 frames. Aborts when called. */
1026
1027static void
dc6f92b8
JB
1028XTreassert_line_highlight (new, vpos)
1029 int new, vpos;
1030{
06a2c219 1031 abort ();
dc6f92b8
JB
1032}
1033
06a2c219
GM
1034
1035/* Call this when about to modify line at position VPOS and change
1036 whether it is highlighted. Not used for X frames. Aborts when
1037 called. */
dc6f92b8 1038
dfcf069d 1039static void
06a2c219
GM
1040x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1041 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1042{
06a2c219 1043 abort ();
dc6f92b8
JB
1044}
1045
06a2c219
GM
1046
1047/* This is called when starting Emacs and when restarting after
1048 suspend. When starting Emacs, no X window is mapped. And nothing
1049 must be done to Emacs's own window if it is suspended (though that
1050 rarely happens). */
dc6f92b8 1051
dfcf069d 1052static void
dc6f92b8
JB
1053XTset_terminal_modes ()
1054{
1055}
1056
06a2c219
GM
1057/* This is called when exiting or suspending Emacs. Exiting will make
1058 the X-windows go away, and suspending requires no action. */
dc6f92b8 1059
dfcf069d 1060static void
dc6f92b8
JB
1061XTreset_terminal_modes ()
1062{
dc6f92b8 1063}
06a2c219
GM
1064
1065
dc6f92b8 1066\f
06a2c219
GM
1067/***********************************************************************
1068 Output Cursor
1069 ***********************************************************************/
1070
1071/* Set the global variable output_cursor to CURSOR. All cursor
1072 positions are relative to updated_window. */
dc6f92b8 1073
dfcf069d 1074static void
06a2c219
GM
1075set_output_cursor (cursor)
1076 struct cursor_pos *cursor;
dc6f92b8 1077{
06a2c219
GM
1078 output_cursor.hpos = cursor->hpos;
1079 output_cursor.vpos = cursor->vpos;
1080 output_cursor.x = cursor->x;
1081 output_cursor.y = cursor->y;
1082}
1083
1084
1085/* Set a nominal cursor position.
dc6f92b8 1086
06a2c219
GM
1087 HPOS and VPOS are column/row positions in a window glyph matrix. X
1088 and Y are window text area relative pixel positions.
1089
1090 If this is done during an update, updated_window will contain the
1091 window that is being updated and the position is the future output
1092 cursor position for that window. If updated_window is null, use
1093 selected_window and display the cursor at the given position. */
1094
1095static void
1096XTcursor_to (vpos, hpos, y, x)
1097 int vpos, hpos, y, x;
1098{
1099 struct window *w;
1100
1101 /* If updated_window is not set, work on selected_window. */
1102 if (updated_window)
1103 w = updated_window;
1104 else
1105 w = XWINDOW (selected_window);
dbcb258a 1106
06a2c219
GM
1107 /* Set the output cursor. */
1108 output_cursor.hpos = hpos;
1109 output_cursor.vpos = vpos;
1110 output_cursor.x = x;
1111 output_cursor.y = y;
dc6f92b8 1112
06a2c219
GM
1113 /* If not called as part of an update, really display the cursor.
1114 This will also set the cursor position of W. */
1115 if (updated_window == NULL)
dc6f92b8
JB
1116 {
1117 BLOCK_INPUT;
06a2c219 1118 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1119 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1120 UNBLOCK_INPUT;
1121 }
1122}
dc43ef94 1123
06a2c219
GM
1124
1125\f
1126/***********************************************************************
1127 Display Iterator
1128 ***********************************************************************/
1129
1130/* Function prototypes of this page. */
1131
1132static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1133 struct glyph *,
ee569018
KH
1134 XChar2b *,
1135 int *));
06a2c219
GM
1136static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1137 int, XChar2b *, int));
1138static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1139static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1140static void x_append_glyph P_ ((struct it *));
b4192550 1141static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1142static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1143 int, int, double));
1144static void x_produce_glyphs P_ ((struct it *));
06a2c219 1145static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1146
1147
1148/* Return a pointer to per-char metric information in FONT of a
1149 character pointed by B which is a pointer to an XChar2b. */
1150
1151#define PER_CHAR_METRIC(font, b) \
1152 ((font)->per_char \
1153 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1154 + (((font)->min_byte1 || (font)->max_byte1) \
1155 ? (((b)->byte1 - (font)->min_byte1) \
1156 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1157 : 0)) \
1158 : &((font)->max_bounds))
dc43ef94 1159
dc6f92b8 1160
e2ef8ee6
GM
1161/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1162 is not contained in the font. */
dc43ef94 1163
06a2c219 1164static INLINE XCharStruct *
ee569018 1165x_per_char_metric (font, char2b)
06a2c219
GM
1166 XFontStruct *font;
1167 XChar2b *char2b;
1168{
1169 /* The result metric information. */
1170 XCharStruct *pcm = NULL;
dc6f92b8 1171
06a2c219 1172 xassert (font && char2b);
dc6f92b8 1173
06a2c219 1174 if (font->per_char != NULL)
dc6f92b8 1175 {
06a2c219 1176 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1177 {
06a2c219
GM
1178 /* min_char_or_byte2 specifies the linear character index
1179 corresponding to the first element of the per_char array,
1180 max_char_or_byte2 is the index of the last character. A
1181 character with non-zero CHAR2B->byte1 is not in the font.
1182 A character with byte2 less than min_char_or_byte2 or
1183 greater max_char_or_byte2 is not in the font. */
1184 if (char2b->byte1 == 0
1185 && char2b->byte2 >= font->min_char_or_byte2
1186 && char2b->byte2 <= font->max_char_or_byte2)
1187 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1188 }
06a2c219 1189 else
dc6f92b8 1190 {
06a2c219
GM
1191 /* If either min_byte1 or max_byte1 are nonzero, both
1192 min_char_or_byte2 and max_char_or_byte2 are less than
1193 256, and the 2-byte character index values corresponding
1194 to the per_char array element N (counting from 0) are:
1195
1196 byte1 = N/D + min_byte1
1197 byte2 = N\D + min_char_or_byte2
1198
1199 where:
1200
1201 D = max_char_or_byte2 - min_char_or_byte2 + 1
1202 / = integer division
1203 \ = integer modulus */
1204 if (char2b->byte1 >= font->min_byte1
1205 && char2b->byte1 <= font->max_byte1
1206 && char2b->byte2 >= font->min_char_or_byte2
1207 && char2b->byte2 <= font->max_char_or_byte2)
1208 {
1209 pcm = (font->per_char
1210 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1211 * (char2b->byte1 - font->min_byte1))
1212 + (char2b->byte2 - font->min_char_or_byte2));
1213 }
dc6f92b8 1214 }
06a2c219
GM
1215 }
1216 else
1217 {
1218 /* If the per_char pointer is null, all glyphs between the first
1219 and last character indexes inclusive have the same
1220 information, as given by both min_bounds and max_bounds. */
1221 if (char2b->byte2 >= font->min_char_or_byte2
1222 && char2b->byte2 <= font->max_char_or_byte2)
1223 pcm = &font->max_bounds;
1224 }
dc6f92b8 1225
ee569018 1226 return ((pcm == NULL
3e71d8f2 1227 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1228 ? NULL : pcm);
06a2c219 1229}
b73b6aaf 1230
57b03282 1231
06a2c219
GM
1232/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1233 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1234
06a2c219
GM
1235static INLINE void
1236x_encode_char (c, char2b, font_info)
1237 int c;
1238 XChar2b *char2b;
1239 struct font_info *font_info;
1240{
1241 int charset = CHAR_CHARSET (c);
1242 XFontStruct *font = font_info->font;
1243
1244 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1245 This may be either a program in a special encoder language or a
1246 fixed encoding. */
1247 if (font_info->font_encoder)
1248 {
1249 /* It's a program. */
1250 struct ccl_program *ccl = font_info->font_encoder;
1251
1252 if (CHARSET_DIMENSION (charset) == 1)
1253 {
1254 ccl->reg[0] = charset;
1255 ccl->reg[1] = char2b->byte2;
1256 }
1257 else
1258 {
1259 ccl->reg[0] = charset;
1260 ccl->reg[1] = char2b->byte1;
1261 ccl->reg[2] = char2b->byte2;
1262 }
1263
1264 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1265
1266 /* We assume that MSBs are appropriately set/reset by CCL
1267 program. */
1268 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1269 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1270 else
1271 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1272 }
1273 else if (font_info->encoding[charset])
1274 {
1275 /* Fixed encoding scheme. See fontset.h for the meaning of the
1276 encoding numbers. */
1277 int enc = font_info->encoding[charset];
1278
1279 if ((enc == 1 || enc == 2)
1280 && CHARSET_DIMENSION (charset) == 2)
1281 char2b->byte1 |= 0x80;
1282
1283 if (enc == 1 || enc == 3)
1284 char2b->byte2 |= 0x80;
1285 }
1286}
1287
1288
1289/* Get face and two-byte form of character C in face FACE_ID on frame
1290 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1291 means we want to display multibyte text. Value is a pointer to a
1292 realized face that is ready for display. */
1293
1294static INLINE struct face *
1295x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1296 struct frame *f;
1297 int c, face_id;
1298 XChar2b *char2b;
1299 int multibyte_p;
1300{
1301 struct face *face = FACE_FROM_ID (f, face_id);
1302
1303 if (!multibyte_p)
1304 {
1305 /* Unibyte case. We don't have to encode, but we have to make
1306 sure to use a face suitable for unibyte. */
1307 char2b->byte1 = 0;
1308 char2b->byte2 = c;
ee569018
KH
1309 face_id = FACE_FOR_CHAR (f, face, c);
1310 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1311 }
1312 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1313 {
1314 /* Case of ASCII in a face known to fit ASCII. */
1315 char2b->byte1 = 0;
1316 char2b->byte2 = c;
1317 }
1318 else
1319 {
1320 int c1, c2, charset;
1321
1322 /* Split characters into bytes. If c2 is -1 afterwards, C is
1323 really a one-byte character so that byte1 is zero. */
1324 SPLIT_CHAR (c, charset, c1, c2);
1325 if (c2 > 0)
1326 char2b->byte1 = c1, char2b->byte2 = c2;
1327 else
1328 char2b->byte1 = 0, char2b->byte2 = c1;
1329
06a2c219 1330 /* Maybe encode the character in *CHAR2B. */
ee569018 1331 if (face->font != NULL)
06a2c219
GM
1332 {
1333 struct font_info *font_info
1334 = FONT_INFO_FROM_ID (f, face->font_info_id);
1335 if (font_info)
ee569018 1336 x_encode_char (c, char2b, font_info);
06a2c219
GM
1337 }
1338 }
1339
1340 /* Make sure X resources of the face are allocated. */
1341 xassert (face != NULL);
1342 PREPARE_FACE_FOR_DISPLAY (f, face);
1343
1344 return face;
1345}
1346
1347
1348/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1349 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1350 a pointer to a realized face that is ready for display. */
1351
1352static INLINE struct face *
ee569018 1353x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1354 struct frame *f;
1355 struct glyph *glyph;
1356 XChar2b *char2b;
ee569018 1357 int *two_byte_p;
06a2c219
GM
1358{
1359 struct face *face;
1360
1361 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1362 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1363
ee569018
KH
1364 if (two_byte_p)
1365 *two_byte_p = 0;
1366
06a2c219
GM
1367 if (!glyph->multibyte_p)
1368 {
1369 /* Unibyte case. We don't have to encode, but we have to make
1370 sure to use a face suitable for unibyte. */
1371 char2b->byte1 = 0;
43d120d8 1372 char2b->byte2 = glyph->u.ch;
06a2c219 1373 }
43d120d8
KH
1374 else if (glyph->u.ch < 128
1375 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1376 {
1377 /* Case of ASCII in a face known to fit ASCII. */
1378 char2b->byte1 = 0;
43d120d8 1379 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1380 }
1381 else
1382 {
1383 int c1, c2, charset;
1384
1385 /* Split characters into bytes. If c2 is -1 afterwards, C is
1386 really a one-byte character so that byte1 is zero. */
43d120d8 1387 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1388 if (c2 > 0)
1389 char2b->byte1 = c1, char2b->byte2 = c2;
1390 else
1391 char2b->byte1 = 0, char2b->byte2 = c1;
1392
1393 /* Maybe encode the character in *CHAR2B. */
1394 if (charset != CHARSET_ASCII)
1395 {
1396 struct font_info *font_info
1397 = FONT_INFO_FROM_ID (f, face->font_info_id);
1398 if (font_info)
1399 {
43d120d8 1400 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1401 if (two_byte_p)
1402 *two_byte_p
1403 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1404 }
1405 }
1406 }
1407
1408 /* Make sure X resources of the face are allocated. */
1409 xassert (face != NULL);
1410 PREPARE_FACE_FOR_DISPLAY (f, face);
1411 return face;
1412}
1413
1414
1415/* Store one glyph for IT->char_to_display in IT->glyph_row.
1416 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1417
1418static INLINE void
1419x_append_glyph (it)
1420 struct it *it;
1421{
1422 struct glyph *glyph;
1423 enum glyph_row_area area = it->area;
1424
1425 xassert (it->glyph_row);
1426 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1427
1428 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1429 if (glyph < it->glyph_row->glyphs[area + 1])
1430 {
06a2c219
GM
1431 glyph->charpos = CHARPOS (it->position);
1432 glyph->object = it->object;
88d75730 1433 glyph->pixel_width = it->pixel_width;
06a2c219 1434 glyph->voffset = it->voffset;
88d75730 1435 glyph->type = CHAR_GLYPH;
06a2c219 1436 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1437 glyph->left_box_line_p = it->start_of_box_run_p;
1438 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1439 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1440 || it->phys_descent > it->descent);
88d75730 1441 glyph->padding_p = 0;
ee569018 1442 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1443 glyph->face_id = it->face_id;
1444 glyph->u.ch = it->char_to_display;
06a2c219
GM
1445 ++it->glyph_row->used[area];
1446 }
1447}
1448
b4192550
KH
1449/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1450 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1451
1452static INLINE void
1453x_append_composite_glyph (it)
1454 struct it *it;
1455{
1456 struct glyph *glyph;
1457 enum glyph_row_area area = it->area;
1458
1459 xassert (it->glyph_row);
1460
1461 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1462 if (glyph < it->glyph_row->glyphs[area + 1])
1463 {
b4192550
KH
1464 glyph->charpos = CHARPOS (it->position);
1465 glyph->object = it->object;
88d75730 1466 glyph->pixel_width = it->pixel_width;
b4192550 1467 glyph->voffset = it->voffset;
88d75730 1468 glyph->type = COMPOSITE_GLYPH;
b4192550 1469 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1470 glyph->left_box_line_p = it->start_of_box_run_p;
1471 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1472 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1473 || it->phys_descent > it->descent);
88d75730
GM
1474 glyph->padding_p = 0;
1475 glyph->glyph_not_available_p = 0;
1476 glyph->face_id = it->face_id;
1477 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1478 ++it->glyph_row->used[area];
1479 }
1480}
1481
06a2c219
GM
1482
1483/* Change IT->ascent and IT->height according to the setting of
1484 IT->voffset. */
1485
1486static INLINE void
1487take_vertical_position_into_account (it)
1488 struct it *it;
1489{
1490 if (it->voffset)
1491 {
1492 if (it->voffset < 0)
1493 /* Increase the ascent so that we can display the text higher
1494 in the line. */
1495 it->ascent += abs (it->voffset);
1496 else
1497 /* Increase the descent so that we can display the text lower
1498 in the line. */
1499 it->descent += it->voffset;
1500 }
1501}
1502
1503
1504/* Produce glyphs/get display metrics for the image IT is loaded with.
1505 See the description of struct display_iterator in dispextern.h for
1506 an overview of struct display_iterator. */
1507
1508static void
1509x_produce_image_glyph (it)
1510 struct it *it;
1511{
1512 struct image *img;
1513 struct face *face;
1514
1515 xassert (it->what == IT_IMAGE);
1516
1517 face = FACE_FROM_ID (it->f, it->face_id);
1518 img = IMAGE_FROM_ID (it->f, it->image_id);
1519 xassert (img);
1520
1521 /* Make sure X resources of the face and image are loaded. */
1522 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1523 prepare_image_for_display (it->f, img);
1524
95af8492 1525 it->ascent = it->phys_ascent = image_ascent (img, face);
66ac4b0e 1526 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1527 it->pixel_width = img->width + 2 * img->margin;
1528
1529 it->nglyphs = 1;
1530
1531 if (face->box != FACE_NO_BOX)
1532 {
1533 it->ascent += face->box_line_width;
1534 it->descent += face->box_line_width;
1535
1536 if (it->start_of_box_run_p)
1537 it->pixel_width += face->box_line_width;
1538 if (it->end_of_box_run_p)
1539 it->pixel_width += face->box_line_width;
1540 }
1541
1542 take_vertical_position_into_account (it);
1543
1544 if (it->glyph_row)
1545 {
1546 struct glyph *glyph;
1547 enum glyph_row_area area = it->area;
1548
1549 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1550 if (glyph < it->glyph_row->glyphs[area + 1])
1551 {
06a2c219
GM
1552 glyph->charpos = CHARPOS (it->position);
1553 glyph->object = it->object;
88d75730 1554 glyph->pixel_width = it->pixel_width;
06a2c219 1555 glyph->voffset = it->voffset;
88d75730 1556 glyph->type = IMAGE_GLYPH;
06a2c219 1557 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1558 glyph->left_box_line_p = it->start_of_box_run_p;
1559 glyph->right_box_line_p = it->end_of_box_run_p;
1560 glyph->overlaps_vertically_p = 0;
1561 glyph->padding_p = 0;
1562 glyph->glyph_not_available_p = 0;
1563 glyph->face_id = it->face_id;
1564 glyph->u.img_id = img->id;
06a2c219
GM
1565 ++it->glyph_row->used[area];
1566 }
1567 }
1568}
1569
1570
1571/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1572 of the glyph, WIDTH and HEIGHT are the width and height of the
1573 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1574 ascent of the glyph (0 <= ASCENT <= 1). */
1575
1576static void
1577x_append_stretch_glyph (it, object, width, height, ascent)
1578 struct it *it;
1579 Lisp_Object object;
1580 int width, height;
1581 double ascent;
1582{
1583 struct glyph *glyph;
1584 enum glyph_row_area area = it->area;
1585
1586 xassert (ascent >= 0 && ascent <= 1);
1587
1588 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1589 if (glyph < it->glyph_row->glyphs[area + 1])
1590 {
06a2c219
GM
1591 glyph->charpos = CHARPOS (it->position);
1592 glyph->object = object;
88d75730 1593 glyph->pixel_width = width;
06a2c219 1594 glyph->voffset = it->voffset;
88d75730 1595 glyph->type = STRETCH_GLYPH;
06a2c219 1596 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1597 glyph->left_box_line_p = it->start_of_box_run_p;
1598 glyph->right_box_line_p = it->end_of_box_run_p;
1599 glyph->overlaps_vertically_p = 0;
1600 glyph->padding_p = 0;
1601 glyph->glyph_not_available_p = 0;
1602 glyph->face_id = it->face_id;
1603 glyph->u.stretch.ascent = height * ascent;
1604 glyph->u.stretch.height = height;
06a2c219
GM
1605 ++it->glyph_row->used[area];
1606 }
1607}
1608
1609
1610/* Produce a stretch glyph for iterator IT. IT->object is the value
1611 of the glyph property displayed. The value must be a list
1612 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1613 being recognized:
1614
1615 1. `:width WIDTH' specifies that the space should be WIDTH *
1616 canonical char width wide. WIDTH may be an integer or floating
1617 point number.
1618
1619 2. `:relative-width FACTOR' specifies that the width of the stretch
1620 should be computed from the width of the first character having the
1621 `glyph' property, and should be FACTOR times that width.
1622
1623 3. `:align-to HPOS' specifies that the space should be wide enough
1624 to reach HPOS, a value in canonical character units.
1625
1626 Exactly one of the above pairs must be present.
1627
1628 4. `:height HEIGHT' specifies that the height of the stretch produced
1629 should be HEIGHT, measured in canonical character units.
1630
1631 5. `:relative-height FACTOR' specifies that the height of the the
1632 stretch should be FACTOR times the height of the characters having
1633 the glyph property.
1634
1635 Either none or exactly one of 4 or 5 must be present.
1636
1637 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1638 of the stretch should be used for the ascent of the stretch.
1639 ASCENT must be in the range 0 <= ASCENT <= 100. */
1640
1641#define NUMVAL(X) \
1642 ((INTEGERP (X) || FLOATP (X)) \
1643 ? XFLOATINT (X) \
1644 : - 1)
1645
1646
1647static void
1648x_produce_stretch_glyph (it)
1649 struct it *it;
1650{
1651 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1652#if GLYPH_DEBUG
1653 extern Lisp_Object Qspace;
1654#endif
1655 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1656 extern Lisp_Object QCrelative_width, QCrelative_height;
1657 extern Lisp_Object QCalign_to;
1658 Lisp_Object prop, plist;
1659 double width = 0, height = 0, ascent = 0;
1660 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1661 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1662
1663 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1664
1665 /* List should start with `space'. */
1666 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1667 plist = XCDR (it->object);
1668
1669 /* Compute the width of the stretch. */
1670 if (prop = Fplist_get (plist, QCwidth),
1671 NUMVAL (prop) > 0)
1672 /* Absolute width `:width WIDTH' specified and valid. */
1673 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1674 else if (prop = Fplist_get (plist, QCrelative_width),
1675 NUMVAL (prop) > 0)
1676 {
1677 /* Relative width `:relative-width FACTOR' specified and valid.
1678 Compute the width of the characters having the `glyph'
1679 property. */
1680 struct it it2;
1681 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1682
1683 it2 = *it;
1684 if (it->multibyte_p)
1685 {
1686 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1687 - IT_BYTEPOS (*it));
1688 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1689 }
1690 else
1691 it2.c = *p, it2.len = 1;
1692
1693 it2.glyph_row = NULL;
1694 it2.what = IT_CHARACTER;
1695 x_produce_glyphs (&it2);
1696 width = NUMVAL (prop) * it2.pixel_width;
1697 }
1698 else if (prop = Fplist_get (plist, QCalign_to),
1699 NUMVAL (prop) > 0)
1700 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1701 else
1702 /* Nothing specified -> width defaults to canonical char width. */
1703 width = CANON_X_UNIT (it->f);
1704
1705 /* Compute height. */
1706 if (prop = Fplist_get (plist, QCheight),
1707 NUMVAL (prop) > 0)
1708 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1709 else if (prop = Fplist_get (plist, QCrelative_height),
1710 NUMVAL (prop) > 0)
1711 height = FONT_HEIGHT (font) * NUMVAL (prop);
1712 else
1713 height = FONT_HEIGHT (font);
1714
1715 /* Compute percentage of height used for ascent. If
1716 `:ascent ASCENT' is present and valid, use that. Otherwise,
1717 derive the ascent from the font in use. */
1718 if (prop = Fplist_get (plist, QCascent),
1719 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1720 ascent = NUMVAL (prop) / 100.0;
1721 else
1722 ascent = (double) font->ascent / FONT_HEIGHT (font);
1723
1724 if (width <= 0)
1725 width = 1;
1726 if (height <= 0)
1727 height = 1;
1728
1729 if (it->glyph_row)
1730 {
1731 Lisp_Object object = it->stack[it->sp - 1].string;
1732 if (!STRINGP (object))
1733 object = it->w->buffer;
1734 x_append_stretch_glyph (it, object, width, height, ascent);
1735 }
1736
1737 it->pixel_width = width;
66ac4b0e
GM
1738 it->ascent = it->phys_ascent = height * ascent;
1739 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1740 it->nglyphs = 1;
1741
1742 if (face->box != FACE_NO_BOX)
1743 {
1744 it->ascent += face->box_line_width;
1745 it->descent += face->box_line_width;
1746
1747 if (it->start_of_box_run_p)
1748 it->pixel_width += face->box_line_width;
1749 if (it->end_of_box_run_p)
1750 it->pixel_width += face->box_line_width;
1751 }
1752
1753 take_vertical_position_into_account (it);
1754}
1755
b4192550
KH
1756/* Return proper value to be used as baseline offset of font that has
1757 ASCENT and DESCENT to draw characters by the font at the vertical
1758 center of the line of frame F.
1759
1760 Here, out task is to find the value of BOFF in the following figure;
1761
1762 -------------------------+-----------+-
1763 -+-+---------+-+ | |
1764 | | | | | |
1765 | | | | F_ASCENT F_HEIGHT
1766 | | | ASCENT | |
1767 HEIGHT | | | | |
1768 | | |-|-+------+-----------|------- baseline
1769 | | | | BOFF | |
1770 | |---------|-+-+ | |
1771 | | | DESCENT | |
1772 -+-+---------+-+ F_DESCENT |
1773 -------------------------+-----------+-
1774
1775 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1776 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1777 DESCENT = FONT->descent
1778 HEIGHT = FONT_HEIGHT (FONT)
1779 F_DESCENT = (F->output_data.x->font->descent
1780 - F->output_data.x->baseline_offset)
1781 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1782*/
1783
1784#define VCENTER_BASELINE_OFFSET(FONT, F) \
1785 ((FONT)->descent \
1786 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1787 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1788
1789/* Produce glyphs/get display metrics for the display element IT is
1790 loaded with. See the description of struct display_iterator in
1791 dispextern.h for an overview of struct display_iterator. */
1792
1793static void
1794x_produce_glyphs (it)
1795 struct it *it;
1796{
ee569018
KH
1797 it->glyph_not_available_p = 0;
1798
06a2c219
GM
1799 if (it->what == IT_CHARACTER)
1800 {
1801 XChar2b char2b;
1802 XFontStruct *font;
ee569018 1803 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1804 XCharStruct *pcm;
06a2c219 1805 int font_not_found_p;
b4192550
KH
1806 struct font_info *font_info;
1807 int boff; /* baseline offset */
06a2c219 1808
ee569018
KH
1809 /* Maybe translate single-byte characters to multibyte, or the
1810 other way. */
06a2c219 1811 it->char_to_display = it->c;
ee569018 1812 if (!ASCII_BYTE_P (it->c))
06a2c219 1813 {
ee569018
KH
1814 if (unibyte_display_via_language_environment
1815 && SINGLE_BYTE_CHAR_P (it->c)
1816 && (it->c >= 0240
1817 || !NILP (Vnonascii_translation_table)))
1818 {
1819 it->char_to_display = unibyte_char_to_multibyte (it->c);
1820 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1821 face = FACE_FROM_ID (it->f, it->face_id);
1822 }
1823 else if (!SINGLE_BYTE_CHAR_P (it->c)
1824 && !it->multibyte_p)
1825 {
1826 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1827 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1828 face = FACE_FROM_ID (it->f, it->face_id);
1829 }
06a2c219
GM
1830 }
1831
ee569018
KH
1832 /* Get font to use. Encode IT->char_to_display. */
1833 x_get_char_face_and_encoding (it->f, it->char_to_display,
1834 it->face_id, &char2b,
1835 it->multibyte_p);
06a2c219
GM
1836 font = face->font;
1837
1838 /* When no suitable font found, use the default font. */
1839 font_not_found_p = font == NULL;
1840 if (font_not_found_p)
b4192550
KH
1841 {
1842 font = FRAME_FONT (it->f);
1843 boff = it->f->output_data.x->baseline_offset;
1844 font_info = NULL;
1845 }
1846 else
1847 {
1848 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1849 boff = font_info->baseline_offset;
1850 if (font_info->vertical_centering)
1851 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1852 }
06a2c219
GM
1853
1854 if (it->char_to_display >= ' '
1855 && (!it->multibyte_p || it->char_to_display < 128))
1856 {
1857 /* Either unibyte or ASCII. */
1858 int stretched_p;
1859
1860 it->nglyphs = 1;
06a2c219
GM
1861
1862 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1863 it->ascent = font->ascent + boff;
1864 it->descent = font->descent - boff;
474848ac
GM
1865
1866 if (pcm)
1867 {
1868 it->phys_ascent = pcm->ascent + boff;
1869 it->phys_descent = pcm->descent - boff;
1870 it->pixel_width = pcm->width;
1871 }
1872 else
1873 {
1874 it->glyph_not_available_p = 1;
1875 it->phys_ascent = font->ascent + boff;
1876 it->phys_descent = font->descent - boff;
1877 it->pixel_width = FONT_WIDTH (font);
1878 }
06a2c219
GM
1879
1880 /* If this is a space inside a region of text with
1881 `space-width' property, change its width. */
1882 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1883 if (stretched_p)
1884 it->pixel_width *= XFLOATINT (it->space_width);
1885
1886 /* If face has a box, add the box thickness to the character
1887 height. If character has a box line to the left and/or
1888 right, add the box line width to the character's width. */
1889 if (face->box != FACE_NO_BOX)
1890 {
1891 int thick = face->box_line_width;
1892
1893 it->ascent += thick;
1894 it->descent += thick;
1895
1896 if (it->start_of_box_run_p)
1897 it->pixel_width += thick;
1898 if (it->end_of_box_run_p)
1899 it->pixel_width += thick;
1900 }
1901
1902 /* If face has an overline, add the height of the overline
1903 (1 pixel) and a 1 pixel margin to the character height. */
1904 if (face->overline_p)
1905 it->ascent += 2;
1906
1907 take_vertical_position_into_account (it);
1908
1909 /* If we have to actually produce glyphs, do it. */
1910 if (it->glyph_row)
1911 {
1912 if (stretched_p)
1913 {
1914 /* Translate a space with a `space-width' property
1915 into a stretch glyph. */
1916 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1917 x_append_stretch_glyph (it, it->object, it->pixel_width,
1918 it->ascent + it->descent, ascent);
1919 }
1920 else
1921 x_append_glyph (it);
1922
1923 /* If characters with lbearing or rbearing are displayed
1924 in this line, record that fact in a flag of the
1925 glyph row. This is used to optimize X output code. */
1c7e22fd 1926 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1927 it->glyph_row->contains_overlapping_glyphs_p = 1;
1928 }
1929 }
1930 else if (it->char_to_display == '\n')
1931 {
1932 /* A newline has no width but we need the height of the line. */
1933 it->pixel_width = 0;
1934 it->nglyphs = 0;
b4192550
KH
1935 it->ascent = it->phys_ascent = font->ascent + boff;
1936 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1937
1938 if (face->box != FACE_NO_BOX)
1939 {
1940 int thick = face->box_line_width;
1941 it->ascent += thick;
1942 it->descent += thick;
1943 }
1944 }
1945 else if (it->char_to_display == '\t')
1946 {
1947 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1948 int x = it->current_x + it->continuation_lines_width;
06a2c219 1949 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2a32b5ea
GM
1950
1951 /* If the distance from the current position to the next tab
1952 stop is less than a canonical character width, use the
1953 tab stop after that. */
1954 if (next_tab_x - x < CANON_X_UNIT (it->f))
1955 next_tab_x += tab_width;
06a2c219
GM
1956
1957 it->pixel_width = next_tab_x - x;
1958 it->nglyphs = 1;
b4192550
KH
1959 it->ascent = it->phys_ascent = font->ascent + boff;
1960 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1961
1962 if (it->glyph_row)
1963 {
1964 double ascent = (double) it->ascent / (it->ascent + it->descent);
1965 x_append_stretch_glyph (it, it->object, it->pixel_width,
1966 it->ascent + it->descent, ascent);
1967 }
1968 }
1969 else
1970 {
1971 /* A multi-byte character. Assume that the display width of the
1972 character is the width of the character multiplied by the
b4192550 1973 width of the font. */
06a2c219 1974
b4192550
KH
1975 /* If we found a font, this font should give us the right
1976 metrics. If we didn't find a font, use the frame's
1977 default font and calculate the width of the character
1978 from the charset width; this is what old redisplay code
1979 did. */
1980 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1981 if (font_not_found_p || !pcm)
1982 {
1983 int charset = CHAR_CHARSET (it->char_to_display);
1984
1985 it->glyph_not_available_p = 1;
1986 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1987 * CHARSET_WIDTH (charset));
1988 it->phys_ascent = font->ascent + boff;
1989 it->phys_descent = font->descent - boff;
1990 }
1991 else
1992 {
1993 it->pixel_width = pcm->width;
1994 it->phys_ascent = pcm->ascent + boff;
1995 it->phys_descent = pcm->descent - boff;
1996 if (it->glyph_row
1997 && (pcm->lbearing < 0
1998 || pcm->rbearing > pcm->width))
1999 it->glyph_row->contains_overlapping_glyphs_p = 1;
2000 }
b4192550
KH
2001 it->nglyphs = 1;
2002 it->ascent = font->ascent + boff;
2003 it->descent = font->descent - boff;
06a2c219
GM
2004 if (face->box != FACE_NO_BOX)
2005 {
2006 int thick = face->box_line_width;
2007 it->ascent += thick;
2008 it->descent += thick;
2009
2010 if (it->start_of_box_run_p)
2011 it->pixel_width += thick;
2012 if (it->end_of_box_run_p)
2013 it->pixel_width += thick;
2014 }
2015
2016 /* If face has an overline, add the height of the overline
2017 (1 pixel) and a 1 pixel margin to the character height. */
2018 if (face->overline_p)
2019 it->ascent += 2;
2020
2021 take_vertical_position_into_account (it);
2022
2023 if (it->glyph_row)
2024 x_append_glyph (it);
2025 }
2026 }
b4192550
KH
2027 else if (it->what == IT_COMPOSITION)
2028 {
2029 /* Note: A composition is represented as one glyph in the
2030 glyph matrix. There are no padding glyphs. */
2031 XChar2b char2b;
2032 XFontStruct *font;
ee569018 2033 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2034 XCharStruct *pcm;
2035 int font_not_found_p;
2036 struct font_info *font_info;
2037 int boff; /* baseline offset */
2038 struct composition *cmp = composition_table[it->cmp_id];
2039
2040 /* Maybe translate single-byte characters to multibyte. */
2041 it->char_to_display = it->c;
2042 if (unibyte_display_via_language_environment
2043 && SINGLE_BYTE_CHAR_P (it->c)
2044 && (it->c >= 0240
2045 || (it->c >= 0200
2046 && !NILP (Vnonascii_translation_table))))
2047 {
2048 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2049 }
2050
2051 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2052 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2053 face = FACE_FROM_ID (it->f, it->face_id);
2054 x_get_char_face_and_encoding (it->f, it->char_to_display,
2055 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2056 font = face->font;
2057
2058 /* When no suitable font found, use the default font. */
2059 font_not_found_p = font == NULL;
2060 if (font_not_found_p)
2061 {
2062 font = FRAME_FONT (it->f);
2063 boff = it->f->output_data.x->baseline_offset;
2064 font_info = NULL;
2065 }
2066 else
2067 {
2068 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2069 boff = font_info->baseline_offset;
2070 if (font_info->vertical_centering)
2071 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2072 }
2073
2074 /* There are no padding glyphs, so there is only one glyph to
2075 produce for the composition. Important is that pixel_width,
2076 ascent and descent are the values of what is drawn by
2077 draw_glyphs (i.e. the values of the overall glyphs composed). */
2078 it->nglyphs = 1;
2079
2080 /* If we have not yet calculated pixel size data of glyphs of
2081 the composition for the current face font, calculate them
2082 now. Theoretically, we have to check all fonts for the
2083 glyphs, but that requires much time and memory space. So,
2084 here we check only the font of the first glyph. This leads
2085 to incorrect display very rarely, and C-l (recenter) can
2086 correct the display anyway. */
2087 if (cmp->font != (void *) font)
2088 {
2089 /* Ascent and descent of the font of the first character of
2090 this composition (adjusted by baseline offset). Ascent
2091 and descent of overall glyphs should not be less than
2092 them respectively. */
2093 int font_ascent = font->ascent + boff;
2094 int font_descent = font->descent - boff;
2095 /* Bounding box of the overall glyphs. */
2096 int leftmost, rightmost, lowest, highest;
329bed06 2097 int i, width, ascent, descent;
b4192550
KH
2098
2099 cmp->font = (void *) font;
2100
2101 /* Initialize the bounding box. */
2102 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2103 if (pcm)
2104 {
2105 width = pcm->width;
2106 ascent = pcm->ascent;
2107 descent = pcm->descent;
2108 }
2109 else
2110 {
2111 width = FONT_WIDTH (font);
2112 ascent = font->ascent;
2113 descent = font->descent;
2114 }
2115
2116 rightmost = width;
2117 lowest = - descent + boff;
2118 highest = ascent + boff;
b4192550 2119 leftmost = 0;
329bed06 2120
b4192550
KH
2121 if (font_info
2122 && font_info->default_ascent
2123 && CHAR_TABLE_P (Vuse_default_ascent)
2124 && !NILP (Faref (Vuse_default_ascent,
2125 make_number (it->char_to_display))))
2126 highest = font_info->default_ascent + boff;
2127
2128 /* Draw the first glyph at the normal position. It may be
2129 shifted to right later if some other glyphs are drawn at
2130 the left. */
2131 cmp->offsets[0] = 0;
2132 cmp->offsets[1] = boff;
2133
2134 /* Set cmp->offsets for the remaining glyphs. */
2135 for (i = 1; i < cmp->glyph_len; i++)
2136 {
2137 int left, right, btm, top;
2138 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2139 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2140
2141 face = FACE_FROM_ID (it->f, face_id);
2142 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2143 it->multibyte_p);
b4192550
KH
2144 font = face->font;
2145 if (font == NULL)
2146 {
2147 font = FRAME_FONT (it->f);
2148 boff = it->f->output_data.x->baseline_offset;
2149 font_info = NULL;
2150 }
2151 else
2152 {
2153 font_info
2154 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2155 boff = font_info->baseline_offset;
2156 if (font_info->vertical_centering)
2157 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2158 }
2159
2160 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2161 if (pcm)
2162 {
2163 width = pcm->width;
2164 ascent = pcm->ascent;
2165 descent = pcm->descent;
2166 }
2167 else
2168 {
2169 width = FONT_WIDTH (font);
2170 ascent = font->ascent;
2171 descent = font->descent;
2172 }
b4192550
KH
2173
2174 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2175 {
2176 /* Relative composition with or without
2177 alternate chars. */
329bed06
GM
2178 left = (leftmost + rightmost - width) / 2;
2179 btm = - descent + boff;
b4192550
KH
2180 if (font_info && font_info->relative_compose
2181 && (! CHAR_TABLE_P (Vignore_relative_composition)
2182 || NILP (Faref (Vignore_relative_composition,
2183 make_number (ch)))))
2184 {
2185
329bed06 2186 if (- descent >= font_info->relative_compose)
b4192550
KH
2187 /* One extra pixel between two glyphs. */
2188 btm = highest + 1;
329bed06 2189 else if (ascent <= 0)
b4192550 2190 /* One extra pixel between two glyphs. */
329bed06 2191 btm = lowest - 1 - ascent - descent;
b4192550
KH
2192 }
2193 }
2194 else
2195 {
2196 /* A composition rule is specified by an integer
2197 value that encodes global and new reference
2198 points (GREF and NREF). GREF and NREF are
2199 specified by numbers as below:
2200
2201 0---1---2 -- ascent
2202 | |
2203 | |
2204 | |
2205 9--10--11 -- center
2206 | |
2207 ---3---4---5--- baseline
2208 | |
2209 6---7---8 -- descent
2210 */
2211 int rule = COMPOSITION_RULE (cmp, i);
2212 int gref, nref, grefx, grefy, nrefx, nrefy;
2213
2214 COMPOSITION_DECODE_RULE (rule, gref, nref);
2215 grefx = gref % 3, nrefx = nref % 3;
2216 grefy = gref / 3, nrefy = nref / 3;
2217
2218 left = (leftmost
2219 + grefx * (rightmost - leftmost) / 2
329bed06 2220 - nrefx * width / 2);
b4192550
KH
2221 btm = ((grefy == 0 ? highest
2222 : grefy == 1 ? 0
2223 : grefy == 2 ? lowest
2224 : (highest + lowest) / 2)
329bed06
GM
2225 - (nrefy == 0 ? ascent + descent
2226 : nrefy == 1 ? descent - boff
b4192550 2227 : nrefy == 2 ? 0
329bed06 2228 : (ascent + descent) / 2));
b4192550
KH
2229 }
2230
2231 cmp->offsets[i * 2] = left;
329bed06 2232 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2233
2234 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2235 right = left + width;
2236 top = btm + descent + ascent;
b4192550
KH
2237 if (left < leftmost)
2238 leftmost = left;
2239 if (right > rightmost)
2240 rightmost = right;
2241 if (top > highest)
2242 highest = top;
2243 if (btm < lowest)
2244 lowest = btm;
2245 }
2246
2247 /* If there are glyphs whose x-offsets are negative,
2248 shift all glyphs to the right and make all x-offsets
2249 non-negative. */
2250 if (leftmost < 0)
2251 {
2252 for (i = 0; i < cmp->glyph_len; i++)
2253 cmp->offsets[i * 2] -= leftmost;
2254 rightmost -= leftmost;
2255 }
2256
2257 cmp->pixel_width = rightmost;
2258 cmp->ascent = highest;
2259 cmp->descent = - lowest;
2260 if (cmp->ascent < font_ascent)
2261 cmp->ascent = font_ascent;
2262 if (cmp->descent < font_descent)
2263 cmp->descent = font_descent;
2264 }
2265
2266 it->pixel_width = cmp->pixel_width;
2267 it->ascent = it->phys_ascent = cmp->ascent;
2268 it->descent = it->phys_descent = cmp->descent;
2269
2270 if (face->box != FACE_NO_BOX)
2271 {
2272 int thick = face->box_line_width;
2273 it->ascent += thick;
2274 it->descent += thick;
2275
2276 if (it->start_of_box_run_p)
2277 it->pixel_width += thick;
2278 if (it->end_of_box_run_p)
2279 it->pixel_width += thick;
2280 }
2281
2282 /* If face has an overline, add the height of the overline
2283 (1 pixel) and a 1 pixel margin to the character height. */
2284 if (face->overline_p)
2285 it->ascent += 2;
2286
2287 take_vertical_position_into_account (it);
2288
2289 if (it->glyph_row)
2290 x_append_composite_glyph (it);
2291 }
06a2c219
GM
2292 else if (it->what == IT_IMAGE)
2293 x_produce_image_glyph (it);
2294 else if (it->what == IT_STRETCH)
2295 x_produce_stretch_glyph (it);
2296
3017fdd1
GM
2297 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2298 because this isn't true for images with `:ascent 100'. */
2299 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2300 if (it->area == TEXT_AREA)
2301 it->current_x += it->pixel_width;
66ac4b0e 2302
d365f5bb
GM
2303 it->descent += it->extra_line_spacing;
2304
06a2c219
GM
2305 it->max_ascent = max (it->max_ascent, it->ascent);
2306 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2307 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2308 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2309}
2310
2311
2312/* Estimate the pixel height of the mode or top line on frame F.
2313 FACE_ID specifies what line's height to estimate. */
2314
2315int
2316x_estimate_mode_line_height (f, face_id)
2317 struct frame *f;
2318 enum face_id face_id;
2319{
2320 int height = 1;
2321
2322 /* This function is called so early when Emacs starts that the face
2323 cache and mode line face are not yet initialized. */
2324 if (FRAME_FACE_CACHE (f))
2325 {
2326 struct face *face = FACE_FROM_ID (f, face_id);
2327 if (face)
2328 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2329 }
2330
2331 return height;
2332}
2333
2334\f
2335/***********************************************************************
2336 Glyph display
2337 ***********************************************************************/
2338
2339/* A sequence of glyphs to be drawn in the same face.
2340
2341 This data structure is not really completely X specific, so it
2342 could possibly, at least partially, be useful for other systems. It
2343 is currently not part of the external redisplay interface because
2344 it's not clear what other systems will need. */
2345
2346struct glyph_string
2347{
2348 /* X-origin of the string. */
2349 int x;
2350
2351 /* Y-origin and y-position of the base line of this string. */
2352 int y, ybase;
2353
2354 /* The width of the string, not including a face extension. */
2355 int width;
2356
2357 /* The width of the string, including a face extension. */
2358 int background_width;
2359
2360 /* The height of this string. This is the height of the line this
2361 string is drawn in, and can be different from the height of the
2362 font the string is drawn in. */
2363 int height;
2364
2365 /* Number of pixels this string overwrites in front of its x-origin.
2366 This number is zero if the string has an lbearing >= 0; it is
2367 -lbearing, if the string has an lbearing < 0. */
2368 int left_overhang;
2369
2370 /* Number of pixels this string overwrites past its right-most
2371 nominal x-position, i.e. x + width. Zero if the string's
2372 rbearing is <= its nominal width, rbearing - width otherwise. */
2373 int right_overhang;
2374
2375 /* The frame on which the glyph string is drawn. */
2376 struct frame *f;
2377
2378 /* The window on which the glyph string is drawn. */
2379 struct window *w;
2380
2381 /* X display and window for convenience. */
2382 Display *display;
2383 Window window;
2384
2385 /* The glyph row for which this string was built. It determines the
2386 y-origin and height of the string. */
2387 struct glyph_row *row;
2388
2389 /* The area within row. */
2390 enum glyph_row_area area;
2391
2392 /* Characters to be drawn, and number of characters. */
2393 XChar2b *char2b;
2394 int nchars;
2395
06a2c219
GM
2396 /* A face-override for drawing cursors, mouse face and similar. */
2397 enum draw_glyphs_face hl;
2398
2399 /* Face in which this string is to be drawn. */
2400 struct face *face;
2401
2402 /* Font in which this string is to be drawn. */
2403 XFontStruct *font;
2404
2405 /* Font info for this string. */
2406 struct font_info *font_info;
2407
b4192550
KH
2408 /* Non-null means this string describes (part of) a composition.
2409 All characters from char2b are drawn composed. */
2410 struct composition *cmp;
06a2c219
GM
2411
2412 /* Index of this glyph string's first character in the glyph
b4192550
KH
2413 definition of CMP. If this is zero, this glyph string describes
2414 the first character of a composition. */
06a2c219
GM
2415 int gidx;
2416
2417 /* 1 means this glyph strings face has to be drawn to the right end
2418 of the window's drawing area. */
2419 unsigned extends_to_end_of_line_p : 1;
2420
2421 /* 1 means the background of this string has been drawn. */
2422 unsigned background_filled_p : 1;
2423
2424 /* 1 means glyph string must be drawn with 16-bit functions. */
2425 unsigned two_byte_p : 1;
2426
2427 /* 1 means that the original font determined for drawing this glyph
2428 string could not be loaded. The member `font' has been set to
2429 the frame's default font in this case. */
2430 unsigned font_not_found_p : 1;
2431
2432 /* 1 means that the face in which this glyph string is drawn has a
2433 stipple pattern. */
2434 unsigned stippled_p : 1;
2435
66ac4b0e
GM
2436 /* 1 means only the foreground of this glyph string must be drawn,
2437 and we should use the physical height of the line this glyph
2438 string appears in as clip rect. */
2439 unsigned for_overlaps_p : 1;
2440
06a2c219
GM
2441 /* The GC to use for drawing this glyph string. */
2442 GC gc;
2443
2444 /* A pointer to the first glyph in the string. This glyph
2445 corresponds to char2b[0]. Needed to draw rectangles if
2446 font_not_found_p is 1. */
2447 struct glyph *first_glyph;
2448
2449 /* Image, if any. */
2450 struct image *img;
2451
2452 struct glyph_string *next, *prev;
2453};
2454
2455
5c187dee 2456#if 0
06a2c219
GM
2457
2458static void
2459x_dump_glyph_string (s)
2460 struct glyph_string *s;
2461{
2462 fprintf (stderr, "glyph string\n");
2463 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2464 s->x, s->y, s->width, s->height);
2465 fprintf (stderr, " ybase = %d\n", s->ybase);
2466 fprintf (stderr, " hl = %d\n", s->hl);
2467 fprintf (stderr, " left overhang = %d, right = %d\n",
2468 s->left_overhang, s->right_overhang);
2469 fprintf (stderr, " nchars = %d\n", s->nchars);
2470 fprintf (stderr, " extends to end of line = %d\n",
2471 s->extends_to_end_of_line_p);
2472 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2473 fprintf (stderr, " bg width = %d\n", s->background_width);
2474}
2475
2476#endif /* GLYPH_DEBUG */
2477
2478
2479
2480static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2481 struct glyph_string **,
2482 struct glyph_string *,
2483 struct glyph_string *));
2484static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2485 struct glyph_string **,
2486 struct glyph_string *,
2487 struct glyph_string *));
2488static void x_append_glyph_string P_ ((struct glyph_string **,
2489 struct glyph_string **,
2490 struct glyph_string *));
2491static int x_left_overwritten P_ ((struct glyph_string *));
2492static int x_left_overwriting P_ ((struct glyph_string *));
2493static int x_right_overwritten P_ ((struct glyph_string *));
2494static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2495static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2496 int));
06a2c219
GM
2497static void x_init_glyph_string P_ ((struct glyph_string *,
2498 XChar2b *, struct window *,
2499 struct glyph_row *,
2500 enum glyph_row_area, int,
2501 enum draw_glyphs_face));
2502static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2503 enum glyph_row_area, int, int,
66ac4b0e 2504 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2505static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2506static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2507static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2508 int));
2509static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2510static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2511static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2512static void x_draw_glyph_string P_ ((struct glyph_string *));
2513static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2514static void x_set_cursor_gc P_ ((struct glyph_string *));
2515static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2516static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2517static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2518 int *, int *));
2519static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2520static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2521 unsigned long *, double, int));
06a2c219 2522static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2523 double, int, unsigned long));
06a2c219
GM
2524static void x_setup_relief_colors P_ ((struct glyph_string *));
2525static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2526static void x_draw_image_relief P_ ((struct glyph_string *));
2527static void x_draw_image_foreground P_ ((struct glyph_string *));
2528static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2529static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2530static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2531 int, int, int));
2532static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2533 int, int, int, int, XRectangle *));
2534static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2535 int, int, int, XRectangle *));
66ac4b0e
GM
2536static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2537 enum glyph_row_area));
209f68d9
GM
2538static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2539 struct glyph_row *,
2540 enum glyph_row_area, int, int));
06a2c219 2541
163dcff3
GM
2542#if GLYPH_DEBUG
2543static void x_check_font P_ ((struct frame *, XFontStruct *));
2544#endif
2545
06a2c219 2546
06a2c219
GM
2547/* Append the list of glyph strings with head H and tail T to the list
2548 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2549
2550static INLINE void
2551x_append_glyph_string_lists (head, tail, h, t)
2552 struct glyph_string **head, **tail;
2553 struct glyph_string *h, *t;
2554{
2555 if (h)
2556 {
2557 if (*head)
2558 (*tail)->next = h;
2559 else
2560 *head = h;
2561 h->prev = *tail;
2562 *tail = t;
2563 }
2564}
2565
2566
2567/* Prepend the list of glyph strings with head H and tail T to the
2568 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2569 result. */
2570
2571static INLINE void
2572x_prepend_glyph_string_lists (head, tail, h, t)
2573 struct glyph_string **head, **tail;
2574 struct glyph_string *h, *t;
2575{
2576 if (h)
2577 {
2578 if (*head)
2579 (*head)->prev = t;
2580 else
2581 *tail = t;
2582 t->next = *head;
2583 *head = h;
2584 }
2585}
2586
2587
2588/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2589 Set *HEAD and *TAIL to the resulting list. */
2590
2591static INLINE void
2592x_append_glyph_string (head, tail, s)
2593 struct glyph_string **head, **tail;
2594 struct glyph_string *s;
2595{
2596 s->next = s->prev = NULL;
2597 x_append_glyph_string_lists (head, tail, s, s);
2598}
2599
2600
2601/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2602 face. */
2603
2604static void
2605x_set_cursor_gc (s)
2606 struct glyph_string *s;
2607{
2608 if (s->font == FRAME_FONT (s->f)
2609 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2610 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2611 && !s->cmp)
06a2c219
GM
2612 s->gc = s->f->output_data.x->cursor_gc;
2613 else
2614 {
2615 /* Cursor on non-default face: must merge. */
2616 XGCValues xgcv;
2617 unsigned long mask;
2618
2619 xgcv.background = s->f->output_data.x->cursor_pixel;
2620 xgcv.foreground = s->face->background;
2621
2622 /* If the glyph would be invisible, try a different foreground. */
2623 if (xgcv.foreground == xgcv.background)
2624 xgcv.foreground = s->face->foreground;
2625 if (xgcv.foreground == xgcv.background)
2626 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2627 if (xgcv.foreground == xgcv.background)
2628 xgcv.foreground = s->face->foreground;
2629
2630 /* Make sure the cursor is distinct from text in this face. */
2631 if (xgcv.background == s->face->background
2632 && xgcv.foreground == s->face->foreground)
2633 {
2634 xgcv.background = s->face->foreground;
2635 xgcv.foreground = s->face->background;
2636 }
2637
2638 IF_DEBUG (x_check_font (s->f, s->font));
2639 xgcv.font = s->font->fid;
2640 xgcv.graphics_exposures = False;
2641 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2642
2643 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2644 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2645 mask, &xgcv);
2646 else
2647 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2648 = XCreateGC (s->display, s->window, mask, &xgcv);
2649
2650 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2651 }
2652}
2653
2654
2655/* Set up S->gc of glyph string S for drawing text in mouse face. */
2656
2657static void
2658x_set_mouse_face_gc (s)
2659 struct glyph_string *s;
2660{
2661 int face_id;
ee569018 2662 struct face *face;
06a2c219
GM
2663
2664 /* What face has to be used for the mouse face? */
2665 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2666 face = FACE_FROM_ID (s->f, face_id);
033e3e18
GM
2667 if (s->first_glyph->type == CHAR_GLYPH)
2668 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2669 else
2670 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2671 s->face = FACE_FROM_ID (s->f, face_id);
2672 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2673
2674 /* If font in this face is same as S->font, use it. */
2675 if (s->font == s->face->font)
2676 s->gc = s->face->gc;
2677 else
2678 {
2679 /* Otherwise construct scratch_cursor_gc with values from FACE
2680 but font FONT. */
2681 XGCValues xgcv;
2682 unsigned long mask;
2683
2684 xgcv.background = s->face->background;
2685 xgcv.foreground = s->face->foreground;
2686 IF_DEBUG (x_check_font (s->f, s->font));
2687 xgcv.font = s->font->fid;
2688 xgcv.graphics_exposures = False;
2689 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2690
2691 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2692 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2693 mask, &xgcv);
2694 else
2695 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2696 = XCreateGC (s->display, s->window, mask, &xgcv);
2697
2698 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2699 }
2700
2701 xassert (s->gc != 0);
2702}
2703
2704
2705/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2706 Faces to use in the mode line have already been computed when the
2707 matrix was built, so there isn't much to do, here. */
2708
2709static INLINE void
2710x_set_mode_line_face_gc (s)
2711 struct glyph_string *s;
2712{
2713 s->gc = s->face->gc;
06a2c219
GM
2714}
2715
2716
2717/* Set S->gc of glyph string S for drawing that glyph string. Set
2718 S->stippled_p to a non-zero value if the face of S has a stipple
2719 pattern. */
2720
2721static INLINE void
2722x_set_glyph_string_gc (s)
2723 struct glyph_string *s;
2724{
209f68d9
GM
2725 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2726
06a2c219
GM
2727 if (s->hl == DRAW_NORMAL_TEXT)
2728 {
2729 s->gc = s->face->gc;
2730 s->stippled_p = s->face->stipple != 0;
2731 }
2732 else if (s->hl == DRAW_INVERSE_VIDEO)
2733 {
2734 x_set_mode_line_face_gc (s);
2735 s->stippled_p = s->face->stipple != 0;
2736 }
2737 else if (s->hl == DRAW_CURSOR)
2738 {
2739 x_set_cursor_gc (s);
2740 s->stippled_p = 0;
2741 }
2742 else if (s->hl == DRAW_MOUSE_FACE)
2743 {
2744 x_set_mouse_face_gc (s);
2745 s->stippled_p = s->face->stipple != 0;
2746 }
2747 else if (s->hl == DRAW_IMAGE_RAISED
2748 || s->hl == DRAW_IMAGE_SUNKEN)
2749 {
2750 s->gc = s->face->gc;
2751 s->stippled_p = s->face->stipple != 0;
2752 }
2753 else
2754 {
2755 s->gc = s->face->gc;
2756 s->stippled_p = s->face->stipple != 0;
2757 }
2758
2759 /* GC must have been set. */
2760 xassert (s->gc != 0);
2761}
2762
2763
2764/* Return in *R the clipping rectangle for glyph string S. */
2765
2766static void
2767x_get_glyph_string_clip_rect (s, r)
2768 struct glyph_string *s;
2769 XRectangle *r;
2770{
2771 if (s->row->full_width_p)
2772 {
2773 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2774 int canon_x = CANON_X_UNIT (s->f);
2775
2776 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2777 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2778
2779 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2780 {
1da3fd71 2781 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2782 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2783 r->x -= width;
2784 }
2785
b9432a85 2786 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2787
06a2c219
GM
2788 /* Unless displaying a mode or menu bar line, which are always
2789 fully visible, clip to the visible part of the row. */
2790 if (s->w->pseudo_window_p)
2791 r->height = s->row->visible_height;
2792 else
2793 r->height = s->height;
2794 }
2795 else
2796 {
2797 /* This is a text line that may be partially visible. */
2798 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2799 r->width = window_box_width (s->w, s->area);
2800 r->height = s->row->visible_height;
2801 }
2802
2803 /* Don't use S->y for clipping because it doesn't take partially
2804 visible lines into account. For example, it can be negative for
2805 partially visible lines at the top of a window. */
2806 if (!s->row->full_width_p
2807 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2808 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2809 else
2810 r->y = max (0, s->row->y);
06a2c219 2811
9ea173e8 2812 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2813 at the top of the window. */
9ea173e8 2814 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2815 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2816
2817 /* If S draws overlapping rows, it's sufficient to use the top and
2818 bottom of the window for clipping because this glyph string
2819 intentionally draws over other lines. */
2820 if (s->for_overlaps_p)
2821 {
045dee35 2822 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2823 r->height = window_text_bottom_y (s->w) - r->y;
2824 }
2825
2826 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2827}
2828
2829
2830/* Set clipping for output of glyph string S. S may be part of a mode
2831 line or menu if we don't have X toolkit support. */
2832
2833static INLINE void
2834x_set_glyph_string_clipping (s)
2835 struct glyph_string *s;
2836{
2837 XRectangle r;
2838 x_get_glyph_string_clip_rect (s, &r);
2839 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2840}
2841
2842
2843/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2844 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2845
2846static INLINE void
2847x_compute_glyph_string_overhangs (s)
2848 struct glyph_string *s;
2849{
b4192550 2850 if (s->cmp == NULL
06a2c219
GM
2851 && s->first_glyph->type == CHAR_GLYPH)
2852 {
2853 XCharStruct cs;
2854 int direction, font_ascent, font_descent;
2855 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2856 &font_ascent, &font_descent, &cs);
2857 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2858 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2859 }
2860}
2861
2862
2863/* Compute overhangs and x-positions for glyph string S and its
2864 predecessors, or successors. X is the starting x-position for S.
2865 BACKWARD_P non-zero means process predecessors. */
2866
2867static void
2868x_compute_overhangs_and_x (s, x, backward_p)
2869 struct glyph_string *s;
2870 int x;
2871 int backward_p;
2872{
2873 if (backward_p)
2874 {
2875 while (s)
2876 {
2877 x_compute_glyph_string_overhangs (s);
2878 x -= s->width;
2879 s->x = x;
2880 s = s->prev;
2881 }
2882 }
2883 else
2884 {
2885 while (s)
2886 {
2887 x_compute_glyph_string_overhangs (s);
2888 s->x = x;
2889 x += s->width;
2890 s = s->next;
2891 }
2892 }
2893}
2894
2895
2896/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2897 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2898 assumed to be zero. */
06a2c219
GM
2899
2900static void
2901x_get_glyph_overhangs (glyph, f, left, right)
2902 struct glyph *glyph;
2903 struct frame *f;
2904 int *left, *right;
2905{
06a2c219
GM
2906 *left = *right = 0;
2907
b4192550 2908 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2909 {
2910 XFontStruct *font;
2911 struct face *face;
2912 struct font_info *font_info;
2913 XChar2b char2b;
ee569018
KH
2914 XCharStruct *pcm;
2915
2916 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2917 font = face->font;
2918 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2919 if (font
2920 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2921 {
06a2c219
GM
2922 if (pcm->rbearing > pcm->width)
2923 *right = pcm->rbearing - pcm->width;
2924 if (pcm->lbearing < 0)
2925 *left = -pcm->lbearing;
2926 }
2927 }
2928}
2929
2930
2931/* Return the index of the first glyph preceding glyph string S that
2932 is overwritten by S because of S's left overhang. Value is -1
2933 if no glyphs are overwritten. */
2934
2935static int
2936x_left_overwritten (s)
2937 struct glyph_string *s;
2938{
2939 int k;
2940
2941 if (s->left_overhang)
2942 {
2943 int x = 0, i;
2944 struct glyph *glyphs = s->row->glyphs[s->area];
2945 int first = s->first_glyph - glyphs;
2946
2947 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2948 x -= glyphs[i].pixel_width;
2949
2950 k = i + 1;
2951 }
2952 else
2953 k = -1;
2954
2955 return k;
2956}
2957
2958
2959/* Return the index of the first glyph preceding glyph string S that
2960 is overwriting S because of its right overhang. Value is -1 if no
2961 glyph in front of S overwrites S. */
2962
2963static int
2964x_left_overwriting (s)
2965 struct glyph_string *s;
2966{
2967 int i, k, x;
2968 struct glyph *glyphs = s->row->glyphs[s->area];
2969 int first = s->first_glyph - glyphs;
2970
2971 k = -1;
2972 x = 0;
2973 for (i = first - 1; i >= 0; --i)
2974 {
2975 int left, right;
2976 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2977 if (x + right > 0)
2978 k = i;
2979 x -= glyphs[i].pixel_width;
2980 }
2981
2982 return k;
2983}
2984
2985
2986/* Return the index of the last glyph following glyph string S that is
2987 not overwritten by S because of S's right overhang. Value is -1 if
2988 no such glyph is found. */
2989
2990static int
2991x_right_overwritten (s)
2992 struct glyph_string *s;
2993{
2994 int k = -1;
2995
2996 if (s->right_overhang)
2997 {
2998 int x = 0, i;
2999 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3000 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3001 int end = s->row->used[s->area];
3002
3003 for (i = first; i < end && s->right_overhang > x; ++i)
3004 x += glyphs[i].pixel_width;
3005
3006 k = i;
3007 }
3008
3009 return k;
3010}
3011
3012
3013/* Return the index of the last glyph following glyph string S that
3014 overwrites S because of its left overhang. Value is negative
3015 if no such glyph is found. */
3016
3017static int
3018x_right_overwriting (s)
3019 struct glyph_string *s;
3020{
3021 int i, k, x;
3022 int end = s->row->used[s->area];
3023 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3024 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3025
3026 k = -1;
3027 x = 0;
3028 for (i = first; i < end; ++i)
3029 {
3030 int left, right;
3031 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3032 if (x - left < 0)
3033 k = i;
3034 x += glyphs[i].pixel_width;
3035 }
3036
3037 return k;
3038}
3039
3040
3041/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3042
3043static INLINE void
3044x_clear_glyph_string_rect (s, x, y, w, h)
3045 struct glyph_string *s;
3046 int x, y, w, h;
3047{
3048 XGCValues xgcv;
3049 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3050 XSetForeground (s->display, s->gc, xgcv.background);
3051 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3052 XSetForeground (s->display, s->gc, xgcv.foreground);
3053}
3054
3055
3056/* Draw the background of glyph_string S. If S->background_filled_p
3057 is non-zero don't draw it. FORCE_P non-zero means draw the
3058 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3059 when a string preceding S draws into the background of S, or S
3060 contains the first component of a composition. */
06a2c219
GM
3061
3062static void
3063x_draw_glyph_string_background (s, force_p)
3064 struct glyph_string *s;
3065 int force_p;
3066{
3067 /* Nothing to do if background has already been drawn or if it
3068 shouldn't be drawn in the first place. */
3069 if (!s->background_filled_p)
3070 {
b4192550 3071 if (s->stippled_p)
06a2c219
GM
3072 {
3073 /* Fill background with a stipple pattern. */
3074 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3075 XFillRectangle (s->display, s->window, s->gc, s->x,
3076 s->y + s->face->box_line_width,
3077 s->background_width,
3078 s->height - 2 * s->face->box_line_width);
3079 XSetFillStyle (s->display, s->gc, FillSolid);
3080 s->background_filled_p = 1;
3081 }
3082 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3083 || s->font_not_found_p
3084 || s->extends_to_end_of_line_p
06a2c219
GM
3085 || force_p)
3086 {
3087 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3088 s->background_width,
3089 s->height - 2 * s->face->box_line_width);
3090 s->background_filled_p = 1;
3091 }
3092 }
3093}
3094
3095
3096/* Draw the foreground of glyph string S. */
3097
3098static void
3099x_draw_glyph_string_foreground (s)
3100 struct glyph_string *s;
3101{
3102 int i, x;
3103
3104 /* If first glyph of S has a left box line, start drawing the text
3105 of S to the right of that box line. */
3106 if (s->face->box != FACE_NO_BOX
3107 && s->first_glyph->left_box_line_p)
3108 x = s->x + s->face->box_line_width;
3109 else
3110 x = s->x;
3111
b4192550
KH
3112 /* Draw characters of S as rectangles if S's font could not be
3113 loaded. */
3114 if (s->font_not_found_p)
06a2c219 3115 {
b4192550 3116 for (i = 0; i < s->nchars; ++i)
06a2c219 3117 {
b4192550
KH
3118 struct glyph *g = s->first_glyph + i;
3119 XDrawRectangle (s->display, s->window,
3120 s->gc, x, s->y, g->pixel_width - 1,
3121 s->height - 1);
3122 x += g->pixel_width;
06a2c219
GM
3123 }
3124 }
3125 else
3126 {
b4192550
KH
3127 char *char1b = (char *) s->char2b;
3128 int boff = s->font_info->baseline_offset;
06a2c219 3129
b4192550
KH
3130 if (s->font_info->vertical_centering)
3131 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3132
3133 /* If we can use 8-bit functions, condense S->char2b. */
3134 if (!s->two_byte_p)
3135 for (i = 0; i < s->nchars; ++i)
3136 char1b[i] = s->char2b[i].byte2;
3137
3138 /* Draw text with XDrawString if background has already been
3139 filled. Otherwise, use XDrawImageString. (Note that
3140 XDrawImageString is usually faster than XDrawString.) Always
3141 use XDrawImageString when drawing the cursor so that there is
3142 no chance that characters under a box cursor are invisible. */
3143 if (s->for_overlaps_p
3144 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3145 {
3146 /* Draw characters with 16-bit or 8-bit functions. */
3147 if (s->two_byte_p)
3148 XDrawString16 (s->display, s->window, s->gc, x,
3149 s->ybase - boff, s->char2b, s->nchars);
3150 else
3151 XDrawString (s->display, s->window, s->gc, x,
3152 s->ybase - boff, char1b, s->nchars);
3153 }
06a2c219
GM
3154 else
3155 {
b4192550
KH
3156 if (s->two_byte_p)
3157 XDrawImageString16 (s->display, s->window, s->gc, x,
3158 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3159 else
b4192550
KH
3160 XDrawImageString (s->display, s->window, s->gc, x,
3161 s->ybase - boff, char1b, s->nchars);
3162 }
3163 }
3164}
06a2c219 3165
b4192550 3166/* Draw the foreground of composite glyph string S. */
06a2c219 3167
b4192550
KH
3168static void
3169x_draw_composite_glyph_string_foreground (s)
3170 struct glyph_string *s;
3171{
3172 int i, x;
06a2c219 3173
b4192550
KH
3174 /* If first glyph of S has a left box line, start drawing the text
3175 of S to the right of that box line. */
3176 if (s->face->box != FACE_NO_BOX
3177 && s->first_glyph->left_box_line_p)
3178 x = s->x + s->face->box_line_width;
3179 else
3180 x = s->x;
06a2c219 3181
b4192550
KH
3182 /* S is a glyph string for a composition. S->gidx is the index of
3183 the first character drawn for glyphs of this composition.
3184 S->gidx == 0 means we are drawing the very first character of
3185 this composition. */
06a2c219 3186
b4192550
KH
3187 /* Draw a rectangle for the composition if the font for the very
3188 first character of the composition could not be loaded. */
3189 if (s->font_not_found_p)
3190 {
3191 if (s->gidx == 0)
3192 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3193 s->width - 1, s->height - 1);
3194 }
3195 else
3196 {
3197 for (i = 0; i < s->nchars; i++, ++s->gidx)
3198 XDrawString16 (s->display, s->window, s->gc,
3199 x + s->cmp->offsets[s->gidx * 2],
3200 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3201 s->char2b + i, 1);
06a2c219
GM
3202 }
3203}
3204
3205
80c32bcc
GM
3206#ifdef USE_X_TOOLKIT
3207
3e71d8f2 3208static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3209
3e71d8f2
GM
3210
3211/* Return the frame on which widget WIDGET is used.. Abort if frame
3212 cannot be determined. */
3213
e851c833 3214static struct frame *
3e71d8f2 3215x_frame_of_widget (widget)
80c32bcc 3216 Widget widget;
80c32bcc 3217{
80c32bcc 3218 struct x_display_info *dpyinfo;
5c187dee 3219 Lisp_Object tail;
3e71d8f2
GM
3220 struct frame *f;
3221
80c32bcc
GM
3222 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3223
3224 /* Find the top-level shell of the widget. Note that this function
3225 can be called when the widget is not yet realized, so XtWindow
3226 (widget) == 0. That's the reason we can't simply use
3227 x_any_window_to_frame. */
3228 while (!XtIsTopLevelShell (widget))
3229 widget = XtParent (widget);
3230
3231 /* Look for a frame with that top-level widget. Allocate the color
3232 on that frame to get the right gamma correction value. */
3233 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3234 if (GC_FRAMEP (XCAR (tail))
3235 && (f = XFRAME (XCAR (tail)),
3236 (f->output_data.nothing != 1
3237 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3238 && f->output_data.x->widget == widget)
3e71d8f2 3239 return f;
80c32bcc
GM
3240
3241 abort ();
3242}
3243
3e71d8f2
GM
3244
3245/* Allocate the color COLOR->pixel on the screen and display of
3246 widget WIDGET in colormap CMAP. If an exact match cannot be
3247 allocated, try the nearest color available. Value is non-zero
3248 if successful. This is called from lwlib. */
3249
3250int
3251x_alloc_nearest_color_for_widget (widget, cmap, color)
3252 Widget widget;
3253 Colormap cmap;
3254 XColor *color;
3255{
3256 struct frame *f = x_frame_of_widget (widget);
3257 return x_alloc_nearest_color (f, cmap, color);
3258}
3259
3260
46d516e5
MB
3261/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3262 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3263 If this produces the same color as PIXEL, try a color where all RGB
3264 values have DELTA added. Return the allocated color in *PIXEL.
3265 DISPLAY is the X display, CMAP is the colormap to operate on.
3266 Value is non-zero if successful. */
3267
3268int
3269x_alloc_lighter_color_for_widget (widget, display, cmap, pixel, factor, delta)
3270 Widget widget;
3271 Display *display;
3272 Colormap cmap;
3273 unsigned long *pixel;
3274 double factor;
3275 int delta;
3276{
3277 struct frame *f = x_frame_of_widget (widget);
3278 return x_alloc_lighter_color (f, display, cmap, pixel, factor, delta);
3279}
3280
3281
80c32bcc
GM
3282#endif /* USE_X_TOOLKIT */
3283
3284
06a2c219
GM
3285/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3286 CMAP. If an exact match can't be allocated, try the nearest color
3287 available. Value is non-zero if successful. Set *COLOR to the
3288 color allocated. */
3289
3290int
80c32bcc
GM
3291x_alloc_nearest_color (f, cmap, color)
3292 struct frame *f;
06a2c219
GM
3293 Colormap cmap;
3294 XColor *color;
3295{
80c32bcc
GM
3296 Display *display = FRAME_X_DISPLAY (f);
3297 Screen *screen = FRAME_X_SCREEN (f);
3298 int rc;
3299
3300 gamma_correct (f, color);
3301 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3302 if (rc == 0)
3303 {
3304 /* If we got to this point, the colormap is full, so we're going
3305 to try to get the next closest color. The algorithm used is
3306 a least-squares matching, which is what X uses for closest
3307 color matching with StaticColor visuals. */
3308 int nearest, i;
3309 unsigned long nearest_delta = ~0;
3310 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3311 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3312
3313 for (i = 0; i < ncells; ++i)
3314 cells[i].pixel = i;
3315 XQueryColors (display, cmap, cells, ncells);
3316
3317 for (nearest = i = 0; i < ncells; ++i)
3318 {
3319 long dred = (color->red >> 8) - (cells[i].red >> 8);
3320 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3321 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3322 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3323
3324 if (delta < nearest_delta)
3325 {
3326 nearest = i;
3327 nearest_delta = delta;
3328 }
3329 }
3330
3331 color->red = cells[nearest].red;
3332 color->green = cells[nearest].green;
3333 color->blue = cells[nearest].blue;
3334 rc = XAllocColor (display, cmap, color);
3335 }
3336
d9c545da
GM
3337#ifdef DEBUG_X_COLORS
3338 if (rc)
3339 register_color (color->pixel);
3340#endif /* DEBUG_X_COLORS */
3341
06a2c219
GM
3342 return rc;
3343}
3344
3345
d9c545da
GM
3346/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3347 It's necessary to do this instead of just using PIXEL directly to
3348 get color reference counts right. */
3349
3350unsigned long
3351x_copy_color (f, pixel)
3352 struct frame *f;
3353 unsigned long pixel;
3354{
3355 XColor color;
3356
3357 color.pixel = pixel;
3358 BLOCK_INPUT;
3359 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3360 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3361 UNBLOCK_INPUT;
3362#ifdef DEBUG_X_COLORS
3363 register_color (pixel);
3364#endif
3365 return color.pixel;
3366}
3367
3368
3e71d8f2
GM
3369/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3370 It's necessary to do this instead of just using PIXEL directly to
3371 get color reference counts right. */
3372
3373unsigned long
3374x_copy_dpy_color (dpy, cmap, pixel)
3375 Display *dpy;
3376 Colormap cmap;
3377 unsigned long pixel;
3378{
3379 XColor color;
3380
3381 color.pixel = pixel;
3382 BLOCK_INPUT;
3383 XQueryColor (dpy, cmap, &color);
3384 XAllocColor (dpy, cmap, &color);
3385 UNBLOCK_INPUT;
3386#ifdef DEBUG_X_COLORS
3387 register_color (pixel);
3388#endif
3389 return color.pixel;
3390}
3391
3392
06a2c219
GM
3393/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3394 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3395 If this produces the same color as PIXEL, try a color where all RGB
3396 values have DELTA added. Return the allocated color in *PIXEL.
3397 DISPLAY is the X display, CMAP is the colormap to operate on.
3398 Value is non-zero if successful. */
3399
3400static int
3401x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3402 struct frame *f;
3403 Display *display;
3404 Colormap cmap;
3405 unsigned long *pixel;
68c45bf0 3406 double factor;
06a2c219
GM
3407 int delta;
3408{
3409 XColor color, new;
3410 int success_p;
3411
3412 /* Get RGB color values. */
3413 color.pixel = *pixel;
3414 XQueryColor (display, cmap, &color);
3415
3416 /* Change RGB values by specified FACTOR. Avoid overflow! */
3417 xassert (factor >= 0);
3418 new.red = min (0xffff, factor * color.red);
3419 new.green = min (0xffff, factor * color.green);
3420 new.blue = min (0xffff, factor * color.blue);
3421
3422 /* Try to allocate the color. */
80c32bcc 3423 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3424 if (success_p)
3425 {
3426 if (new.pixel == *pixel)
3427 {
3428 /* If we end up with the same color as before, try adding
3429 delta to the RGB values. */
0d605c67 3430 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3431
3432 new.red = min (0xffff, delta + color.red);
3433 new.green = min (0xffff, delta + color.green);
3434 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3435 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3436 }
3437 else
3438 success_p = 1;
3439 *pixel = new.pixel;
3440 }
3441
3442 return success_p;
3443}
3444
3445
3446/* Set up the foreground color for drawing relief lines of glyph
3447 string S. RELIEF is a pointer to a struct relief containing the GC
3448 with which lines will be drawn. Use a color that is FACTOR or
3449 DELTA lighter or darker than the relief's background which is found
3450 in S->f->output_data.x->relief_background. If such a color cannot
3451 be allocated, use DEFAULT_PIXEL, instead. */
3452
3453static void
3454x_setup_relief_color (f, relief, factor, delta, default_pixel)
3455 struct frame *f;
3456 struct relief *relief;
68c45bf0 3457 double factor;
06a2c219
GM
3458 int delta;
3459 unsigned long default_pixel;
3460{
3461 XGCValues xgcv;
3462 struct x_output *di = f->output_data.x;
3463 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3464 unsigned long pixel;
3465 unsigned long background = di->relief_background;
43bd1b2b 3466 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3467 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3468 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3469
3470 xgcv.graphics_exposures = False;
3471 xgcv.line_width = 1;
3472
3473 /* Free previously allocated color. The color cell will be reused
3474 when it has been freed as many times as it was allocated, so this
3475 doesn't affect faces using the same colors. */
3476 if (relief->gc
3477 && relief->allocated_p)
3478 {
0d605c67 3479 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3480 relief->allocated_p = 0;
3481 }
3482
3483 /* Allocate new color. */
3484 xgcv.foreground = default_pixel;
3485 pixel = background;
dcd08bfb
GM
3486 if (dpyinfo->n_planes != 1
3487 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3488 {
3489 relief->allocated_p = 1;
3490 xgcv.foreground = relief->pixel = pixel;
3491 }
3492
3493 if (relief->gc == 0)
3494 {
dcd08bfb 3495 xgcv.stipple = dpyinfo->gray;
06a2c219 3496 mask |= GCStipple;
dcd08bfb 3497 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3498 }
3499 else
dcd08bfb 3500 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3501}
3502
3503
3504/* Set up colors for the relief lines around glyph string S. */
3505
3506static void
3507x_setup_relief_colors (s)
3508 struct glyph_string *s;
3509{
3510 struct x_output *di = s->f->output_data.x;
3511 unsigned long color;
3512
3513 if (s->face->use_box_color_for_shadows_p)
3514 color = s->face->box_color;
3515 else
3516 {
3517 XGCValues xgcv;
3518
3519 /* Get the background color of the face. */
3520 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3521 color = xgcv.background;
3522 }
3523
3524 if (di->white_relief.gc == 0
3525 || color != di->relief_background)
3526 {
3527 di->relief_background = color;
3528 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3529 WHITE_PIX_DEFAULT (s->f));
3530 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3531 BLACK_PIX_DEFAULT (s->f));
3532 }
3533}
3534
3535
3536/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3537 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3538 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3539 relief. LEFT_P non-zero means draw a relief on the left side of
3540 the rectangle. RIGHT_P non-zero means draw a relief on the right
3541 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3542 when drawing. */
3543
3544static void
3545x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3546 raised_p, left_p, right_p, clip_rect)
3547 struct frame *f;
3548 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3549 XRectangle *clip_rect;
3550{
3551 int i;
3552 GC gc;
3553
3554 if (raised_p)
3555 gc = f->output_data.x->white_relief.gc;
3556 else
3557 gc = f->output_data.x->black_relief.gc;
3558 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3559
3560 /* Top. */
3561 for (i = 0; i < width; ++i)
3562 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3563 left_x + i * left_p, top_y + i,
3564 right_x + 1 - i * right_p, top_y + i);
3565
3566 /* Left. */
3567 if (left_p)
3568 for (i = 0; i < width; ++i)
3569 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3570 left_x + i, top_y + i, left_x + i, bottom_y - i);
3571
3572 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3573 if (raised_p)
3574 gc = f->output_data.x->black_relief.gc;
3575 else
3576 gc = f->output_data.x->white_relief.gc;
3577 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3578
3579 /* Bottom. */
3580 for (i = 0; i < width; ++i)
3581 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3582 left_x + i * left_p, bottom_y - i,
3583 right_x + 1 - i * right_p, bottom_y - i);
3584
3585 /* Right. */
3586 if (right_p)
3587 for (i = 0; i < width; ++i)
3588 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3589 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3590
3591 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3592}
3593
3594
3595/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3596 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3597 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3598 left side of the rectangle. RIGHT_P non-zero means draw a line
3599 on the right side of the rectangle. CLIP_RECT is the clipping
3600 rectangle to use when drawing. */
3601
3602static void
3603x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3604 left_p, right_p, clip_rect)
3605 struct glyph_string *s;
3606 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3607 XRectangle *clip_rect;
3608{
3609 XGCValues xgcv;
3610
3611 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3612 XSetForeground (s->display, s->gc, s->face->box_color);
3613 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3614
3615 /* Top. */
3616 XFillRectangle (s->display, s->window, s->gc,
3617 left_x, top_y, right_x - left_x, width);
3618
3619 /* Left. */
3620 if (left_p)
3621 XFillRectangle (s->display, s->window, s->gc,
3622 left_x, top_y, width, bottom_y - top_y);
3623
3624 /* Bottom. */
3625 XFillRectangle (s->display, s->window, s->gc,
3626 left_x, bottom_y - width, right_x - left_x, width);
3627
3628 /* Right. */
3629 if (right_p)
3630 XFillRectangle (s->display, s->window, s->gc,
3631 right_x - width, top_y, width, bottom_y - top_y);
3632
3633 XSetForeground (s->display, s->gc, xgcv.foreground);
3634 XSetClipMask (s->display, s->gc, None);
3635}
3636
3637
3638/* Draw a box around glyph string S. */
3639
3640static void
3641x_draw_glyph_string_box (s)
3642 struct glyph_string *s;
3643{
3644 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3645 int left_p, right_p;
3646 struct glyph *last_glyph;
3647 XRectangle clip_rect;
3648
3649 last_x = window_box_right (s->w, s->area);
3650 if (s->row->full_width_p
3651 && !s->w->pseudo_window_p)
3652 {
110859fc 3653 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3654 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3655 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3656 }
3657
3658 /* The glyph that may have a right box line. */
b4192550 3659 last_glyph = (s->cmp || s->img
06a2c219
GM
3660 ? s->first_glyph
3661 : s->first_glyph + s->nchars - 1);
3662
3663 width = s->face->box_line_width;
3664 raised_p = s->face->box == FACE_RAISED_BOX;
3665 left_x = s->x;
3666 right_x = ((s->row->full_width_p
1da3fd71 3667 ? last_x - 1
a7aeb2de 3668 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3669 top_y = s->y;
3670 bottom_y = top_y + s->height - 1;
3671
3672 left_p = (s->first_glyph->left_box_line_p
3673 || (s->hl == DRAW_MOUSE_FACE
3674 && (s->prev == NULL
3675 || s->prev->hl != s->hl)));
3676 right_p = (last_glyph->right_box_line_p
3677 || (s->hl == DRAW_MOUSE_FACE
3678 && (s->next == NULL
3679 || s->next->hl != s->hl)));
3680
3681 x_get_glyph_string_clip_rect (s, &clip_rect);
3682
3683 if (s->face->box == FACE_SIMPLE_BOX)
3684 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3685 left_p, right_p, &clip_rect);
3686 else
3687 {
3688 x_setup_relief_colors (s);
3689 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3690 width, raised_p, left_p, right_p, &clip_rect);
3691 }
3692}
3693
3694
3695/* Draw foreground of image glyph string S. */
3696
3697static void
3698x_draw_image_foreground (s)
3699 struct glyph_string *s;
3700{
3701 int x;
95af8492 3702 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3703
3704 /* If first glyph of S has a left box line, start drawing it to the
3705 right of that line. */
3706 if (s->face->box != FACE_NO_BOX
3707 && s->first_glyph->left_box_line_p)
3708 x = s->x + s->face->box_line_width;
3709 else
3710 x = s->x;
3711
3712 /* If there is a margin around the image, adjust x- and y-position
3713 by that margin. */
3714 if (s->img->margin)
3715 {
3716 x += s->img->margin;
3717 y += s->img->margin;
3718 }
3719
3720 if (s->img->pixmap)
3721 {
3722 if (s->img->mask)
3723 {
3724 /* We can't set both a clip mask and use XSetClipRectangles
3725 because the latter also sets a clip mask. We also can't
3726 trust on the shape extension to be available
3727 (XShapeCombineRegion). So, compute the rectangle to draw
3728 manually. */
3729 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3730 | GCFunction);
3731 XGCValues xgcv;
3732 XRectangle clip_rect, image_rect, r;
3733
3734 xgcv.clip_mask = s->img->mask;
3735 xgcv.clip_x_origin = x;
3736 xgcv.clip_y_origin = y;
3737 xgcv.function = GXcopy;
3738 XChangeGC (s->display, s->gc, mask, &xgcv);
3739
3740 x_get_glyph_string_clip_rect (s, &clip_rect);
3741 image_rect.x = x;
3742 image_rect.y = y;
3743 image_rect.width = s->img->width;
3744 image_rect.height = s->img->height;
3745 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3746 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3747 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3748 }
3749 else
3750 {
49ad1d99
GM
3751 unsigned long mask = GCClipXOrigin | GCClipYOrigin | GCFunction;
3752 XGCValues xgcv;
3753 XRectangle clip_rect, image_rect, r;
3754
3755 x_get_glyph_string_clip_rect (s, &clip_rect);
3756 image_rect.x = x;
3757 image_rect.y = y;
3758 image_rect.width = s->img->width;
3759 image_rect.height = s->img->height;
3760 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3761 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3762 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
06a2c219
GM
3763
3764 /* When the image has a mask, we can expect that at
3765 least part of a mouse highlight or a block cursor will
3766 be visible. If the image doesn't have a mask, make
3767 a block cursor visible by drawing a rectangle around
3768 the image. I believe it's looking better if we do
3769 nothing here for mouse-face. */
3770 if (s->hl == DRAW_CURSOR)
3771 XDrawRectangle (s->display, s->window, s->gc, x, y,
3772 s->img->width - 1, s->img->height - 1);
3773 }
3774 }
3775 else
3776 /* Draw a rectangle if image could not be loaded. */
3777 XDrawRectangle (s->display, s->window, s->gc, x, y,
3778 s->img->width - 1, s->img->height - 1);
3779}
3780
3781
3782/* Draw a relief around the image glyph string S. */
3783
3784static void
3785x_draw_image_relief (s)
3786 struct glyph_string *s;
3787{
3788 int x0, y0, x1, y1, thick, raised_p;
3789 XRectangle r;
3790 int x;
95af8492 3791 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3792
3793 /* If first glyph of S has a left box line, start drawing it to the
3794 right of that line. */
3795 if (s->face->box != FACE_NO_BOX
3796 && s->first_glyph->left_box_line_p)
3797 x = s->x + s->face->box_line_width;
3798 else
3799 x = s->x;
3800
3801 /* If there is a margin around the image, adjust x- and y-position
3802 by that margin. */
3803 if (s->img->margin)
3804 {
3805 x += s->img->margin;
3806 y += s->img->margin;
3807 }
3808
3809 if (s->hl == DRAW_IMAGE_SUNKEN
3810 || s->hl == DRAW_IMAGE_RAISED)
3811 {
9ea173e8 3812 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3813 raised_p = s->hl == DRAW_IMAGE_RAISED;
3814 }
3815 else
3816 {
3817 thick = abs (s->img->relief);
3818 raised_p = s->img->relief > 0;
3819 }
3820
3821 x0 = x - thick;
3822 y0 = y - thick;
3823 x1 = x + s->img->width + thick - 1;
3824 y1 = y + s->img->height + thick - 1;
3825
3826 x_setup_relief_colors (s);
3827 x_get_glyph_string_clip_rect (s, &r);
3828 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3829}
3830
3831
3832/* Draw the foreground of image glyph string S to PIXMAP. */
3833
3834static void
3835x_draw_image_foreground_1 (s, pixmap)
3836 struct glyph_string *s;
3837 Pixmap pixmap;
3838{
3839 int x;
95af8492 3840 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3841
3842 /* If first glyph of S has a left box line, start drawing it to the
3843 right of that line. */
3844 if (s->face->box != FACE_NO_BOX
3845 && s->first_glyph->left_box_line_p)
3846 x = s->face->box_line_width;
3847 else
3848 x = 0;
3849
3850 /* If there is a margin around the image, adjust x- and y-position
3851 by that margin. */
3852 if (s->img->margin)
3853 {
3854 x += s->img->margin;
3855 y += s->img->margin;
3856 }
dc43ef94 3857
06a2c219
GM
3858 if (s->img->pixmap)
3859 {
3860 if (s->img->mask)
3861 {
3862 /* We can't set both a clip mask and use XSetClipRectangles
3863 because the latter also sets a clip mask. We also can't
3864 trust on the shape extension to be available
3865 (XShapeCombineRegion). So, compute the rectangle to draw
3866 manually. */
3867 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3868 | GCFunction);
3869 XGCValues xgcv;
3870
3871 xgcv.clip_mask = s->img->mask;
3872 xgcv.clip_x_origin = x;
3873 xgcv.clip_y_origin = y;
3874 xgcv.function = GXcopy;
3875 XChangeGC (s->display, s->gc, mask, &xgcv);
3876
3877 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3878 0, 0, s->img->width, s->img->height, x, y);
3879 XSetClipMask (s->display, s->gc, None);
3880 }
3881 else
3882 {
3883 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3884 0, 0, s->img->width, s->img->height, x, y);
3885
3886 /* When the image has a mask, we can expect that at
3887 least part of a mouse highlight or a block cursor will
3888 be visible. If the image doesn't have a mask, make
3889 a block cursor visible by drawing a rectangle around
3890 the image. I believe it's looking better if we do
3891 nothing here for mouse-face. */
3892 if (s->hl == DRAW_CURSOR)
3893 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3894 s->img->width - 1, s->img->height - 1);
3895 }
3896 }
3897 else
3898 /* Draw a rectangle if image could not be loaded. */
3899 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3900 s->img->width - 1, s->img->height - 1);
3901}
dc43ef94 3902
990ba854 3903
06a2c219
GM
3904/* Draw part of the background of glyph string S. X, Y, W, and H
3905 give the rectangle to draw. */
a9a5b0a5 3906
06a2c219
GM
3907static void
3908x_draw_glyph_string_bg_rect (s, x, y, w, h)
3909 struct glyph_string *s;
3910 int x, y, w, h;
3911{
3912 if (s->stippled_p)
3913 {
3914 /* Fill background with a stipple pattern. */
3915 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3916 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3917 XSetFillStyle (s->display, s->gc, FillSolid);
3918 }
3919 else
3920 x_clear_glyph_string_rect (s, x, y, w, h);
3921}
07e34cb0 3922
b5210ea7 3923
06a2c219 3924/* Draw image glyph string S.
dc43ef94 3925
06a2c219
GM
3926 s->y
3927 s->x +-------------------------
3928 | s->face->box
3929 |
3930 | +-------------------------
3931 | | s->img->margin
3932 | |
3933 | | +-------------------
3934 | | | the image
dc43ef94 3935
06a2c219 3936 */
dc43ef94 3937
06a2c219
GM
3938static void
3939x_draw_image_glyph_string (s)
3940 struct glyph_string *s;
3941{
3942 int x, y;
3943 int box_line_width = s->face->box_line_width;
3944 int margin = s->img->margin;
3945 int height;
3946 Pixmap pixmap = None;
3947
3948 height = s->height - 2 * box_line_width;
3949
3950 /* Fill background with face under the image. Do it only if row is
3951 taller than image or if image has a clip mask to reduce
3952 flickering. */
3953 s->stippled_p = s->face->stipple != 0;
3954 if (height > s->img->height
3955 || margin
3956 || s->img->mask
3957 || s->img->pixmap == 0
3958 || s->width != s->background_width)
3959 {
3960 if (box_line_width && s->first_glyph->left_box_line_p)
3961 x = s->x + box_line_width;
3962 else
3963 x = s->x;
3964
3965 y = s->y + box_line_width;
3966
3967 if (s->img->mask)
3968 {
3969 /* Create a pixmap as large as the glyph string Fill it with
3970 the background color. Copy the image to it, using its
3971 mask. Copy the temporary pixmap to the display. */
3972 Screen *screen = FRAME_X_SCREEN (s->f);
3973 int depth = DefaultDepthOfScreen (screen);
3974
3975 /* Create a pixmap as large as the glyph string. */
3976 pixmap = XCreatePixmap (s->display, s->window,
3977 s->background_width,
3978 s->height, depth);
3979
3980 /* Don't clip in the following because we're working on the
3981 pixmap. */
3982 XSetClipMask (s->display, s->gc, None);
3983
3984 /* Fill the pixmap with the background color/stipple. */
3985 if (s->stippled_p)
3986 {
3987 /* Fill background with a stipple pattern. */
3988 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3989 XFillRectangle (s->display, pixmap, s->gc,
3990 0, 0, s->background_width, s->height);
3991 XSetFillStyle (s->display, s->gc, FillSolid);
3992 }
3993 else
3994 {
3995 XGCValues xgcv;
3996 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3997 &xgcv);
3998 XSetForeground (s->display, s->gc, xgcv.background);
3999 XFillRectangle (s->display, pixmap, s->gc,
4000 0, 0, s->background_width, s->height);
4001 XSetForeground (s->display, s->gc, xgcv.foreground);
4002 }
4003 }
4004 else
4005 /* Implementation idea: Is it possible to construct a mask?
4006 We could look at the color at the margins of the image, and
4007 say that this color is probably the background color of the
4008 image. */
4009 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4010
4011 s->background_filled_p = 1;
4012 }
dc43ef94 4013
06a2c219
GM
4014 /* Draw the foreground. */
4015 if (pixmap != None)
4016 {
4017 x_draw_image_foreground_1 (s, pixmap);
4018 x_set_glyph_string_clipping (s);
4019 XCopyArea (s->display, pixmap, s->window, s->gc,
4020 0, 0, s->background_width, s->height, s->x, s->y);
4021 XFreePixmap (s->display, pixmap);
4022 }
4023 else
4024 x_draw_image_foreground (s);
b5210ea7 4025
06a2c219
GM
4026 /* If we must draw a relief around the image, do it. */
4027 if (s->img->relief
4028 || s->hl == DRAW_IMAGE_RAISED
4029 || s->hl == DRAW_IMAGE_SUNKEN)
4030 x_draw_image_relief (s);
4031}
8c1a6a84 4032
990ba854 4033
06a2c219 4034/* Draw stretch glyph string S. */
dc43ef94 4035
06a2c219
GM
4036static void
4037x_draw_stretch_glyph_string (s)
4038 struct glyph_string *s;
4039{
4040 xassert (s->first_glyph->type == STRETCH_GLYPH);
4041 s->stippled_p = s->face->stipple != 0;
990ba854 4042
06a2c219
GM
4043 if (s->hl == DRAW_CURSOR
4044 && !x_stretch_cursor_p)
4045 {
4046 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4047 as wide as the stretch glyph. */
4048 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4049
06a2c219
GM
4050 /* Draw cursor. */
4051 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4052
06a2c219
GM
4053 /* Clear rest using the GC of the original non-cursor face. */
4054 if (width < s->background_width)
4055 {
4056 GC gc = s->face->gc;
4057 int x = s->x + width, y = s->y;
4058 int w = s->background_width - width, h = s->height;
4059 XRectangle r;
dc43ef94 4060
06a2c219
GM
4061 x_get_glyph_string_clip_rect (s, &r);
4062 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 4063
06a2c219
GM
4064 if (s->face->stipple)
4065 {
4066 /* Fill background with a stipple pattern. */
4067 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4068 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4069 XSetFillStyle (s->display, gc, FillSolid);
4070 }
4071 else
4072 {
4073 XGCValues xgcv;
4074 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4075 XSetForeground (s->display, gc, xgcv.background);
4076 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4077 XSetForeground (s->display, gc, xgcv.foreground);
4078 }
4079 }
4080 }
4081 else
4082 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4083 s->height);
4084
4085 s->background_filled_p = 1;
4086}
4087
4088
4089/* Draw glyph string S. */
4090
4091static void
4092x_draw_glyph_string (s)
4093 struct glyph_string *s;
4094{
4095 /* If S draws into the background of its successor, draw the
4096 background of the successor first so that S can draw into it.
4097 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4098 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4099 {
4100 xassert (s->next->img == NULL);
4101 x_set_glyph_string_gc (s->next);
4102 x_set_glyph_string_clipping (s->next);
4103 x_draw_glyph_string_background (s->next, 1);
4104 }
97210f4e 4105
06a2c219
GM
4106 /* Set up S->gc, set clipping and draw S. */
4107 x_set_glyph_string_gc (s);
4108 x_set_glyph_string_clipping (s);
4109
4110 switch (s->first_glyph->type)
4111 {
4112 case IMAGE_GLYPH:
4113 x_draw_image_glyph_string (s);
4114 break;
4115
4116 case STRETCH_GLYPH:
4117 x_draw_stretch_glyph_string (s);
4118 break;
4119
4120 case CHAR_GLYPH:
66ac4b0e
GM
4121 if (s->for_overlaps_p)
4122 s->background_filled_p = 1;
4123 else
4124 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4125 x_draw_glyph_string_foreground (s);
4126 break;
4127
b4192550
KH
4128 case COMPOSITE_GLYPH:
4129 if (s->for_overlaps_p || s->gidx > 0)
4130 s->background_filled_p = 1;
4131 else
4132 x_draw_glyph_string_background (s, 1);
4133 x_draw_composite_glyph_string_foreground (s);
4134 break;
4135
06a2c219
GM
4136 default:
4137 abort ();
4138 }
4139
66ac4b0e 4140 if (!s->for_overlaps_p)
06a2c219 4141 {
66ac4b0e
GM
4142 /* Draw underline. */
4143 if (s->face->underline_p)
4144 {
4145 unsigned long dy, h;
06a2c219 4146
66ac4b0e
GM
4147 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4148 h = 1;
4149 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4150 dy = s->height - h;
06a2c219 4151
66ac4b0e
GM
4152 if (s->face->underline_defaulted_p)
4153 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4154 s->width, h);
4155 else
4156 {
4157 XGCValues xgcv;
4158 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4159 XSetForeground (s->display, s->gc, s->face->underline_color);
4160 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4161 s->width, h);
4162 XSetForeground (s->display, s->gc, xgcv.foreground);
4163 }
dc6f92b8 4164 }
07e34cb0 4165
66ac4b0e
GM
4166 /* Draw overline. */
4167 if (s->face->overline_p)
06a2c219 4168 {
66ac4b0e
GM
4169 unsigned long dy = 0, h = 1;
4170
4171 if (s->face->overline_color_defaulted_p)
4172 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4173 s->width, h);
4174 else
4175 {
4176 XGCValues xgcv;
4177 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4178 XSetForeground (s->display, s->gc, s->face->overline_color);
4179 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4180 s->width, h);
4181 XSetForeground (s->display, s->gc, xgcv.foreground);
4182 }
06a2c219 4183 }
06a2c219 4184
66ac4b0e
GM
4185 /* Draw strike-through. */
4186 if (s->face->strike_through_p)
06a2c219 4187 {
66ac4b0e
GM
4188 unsigned long h = 1;
4189 unsigned long dy = (s->height - h) / 2;
4190
4191 if (s->face->strike_through_color_defaulted_p)
4192 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4193 s->width, h);
4194 else
4195 {
4196 XGCValues xgcv;
4197 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4198 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4199 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4200 s->width, h);
4201 XSetForeground (s->display, s->gc, xgcv.foreground);
4202 }
06a2c219 4203 }
06a2c219 4204
66ac4b0e
GM
4205 /* Draw relief. */
4206 if (s->face->box != FACE_NO_BOX)
4207 x_draw_glyph_string_box (s);
4208 }
06a2c219
GM
4209
4210 /* Reset clipping. */
4211 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4212}
07e34cb0 4213
06a2c219 4214
b4192550
KH
4215static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4216 struct face **, int));
06a2c219 4217
06a2c219 4218
209f68d9
GM
4219/* Fill glyph string S with composition components specified by S->cmp.
4220
b4192550
KH
4221 FACES is an array of faces for all components of this composition.
4222 S->gidx is the index of the first component for S.
4223 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4224 use its physical height for clipping.
06a2c219 4225
b4192550 4226 Value is the index of a component not in S. */
07e34cb0 4227
b4192550
KH
4228static int
4229x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4230 struct glyph_string *s;
b4192550 4231 struct face **faces;
66ac4b0e 4232 int overlaps_p;
07e34cb0 4233{
b4192550 4234 int i;
06a2c219 4235
b4192550 4236 xassert (s);
06a2c219 4237
b4192550 4238 s->for_overlaps_p = overlaps_p;
06a2c219 4239
b4192550
KH
4240 s->face = faces[s->gidx];
4241 s->font = s->face->font;
4242 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4243
b4192550
KH
4244 /* For all glyphs of this composition, starting at the offset
4245 S->gidx, until we reach the end of the definition or encounter a
4246 glyph that requires the different face, add it to S. */
4247 ++s->nchars;
4248 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4249 ++s->nchars;
06a2c219 4250
b4192550
KH
4251 /* All glyph strings for the same composition has the same width,
4252 i.e. the width set for the first component of the composition. */
06a2c219 4253
06a2c219
GM
4254 s->width = s->first_glyph->pixel_width;
4255
4256 /* If the specified font could not be loaded, use the frame's
4257 default font, but record the fact that we couldn't load it in
4258 the glyph string so that we can draw rectangles for the
4259 characters of the glyph string. */
4260 if (s->font == NULL)
4261 {
4262 s->font_not_found_p = 1;
4263 s->font = FRAME_FONT (s->f);
4264 }
4265
4266 /* Adjust base line for subscript/superscript text. */
4267 s->ybase += s->first_glyph->voffset;
4268
4269 xassert (s->face && s->face->gc);
4270
4271 /* This glyph string must always be drawn with 16-bit functions. */
4272 s->two_byte_p = 1;
b4192550
KH
4273
4274 return s->gidx + s->nchars;
06a2c219
GM
4275}
4276
4277
209f68d9
GM
4278/* Fill glyph string S from a sequence of character glyphs.
4279
06a2c219 4280 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4281 first glyph to consider, END is the index of the last + 1.
4282 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4283 use its physical height for clipping.
66ac4b0e
GM
4284
4285 Value is the index of the first glyph not in S. */
06a2c219
GM
4286
4287static int
66ac4b0e 4288x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4289 struct glyph_string *s;
4290 int face_id;
66ac4b0e 4291 int start, end, overlaps_p;
06a2c219
GM
4292{
4293 struct glyph *glyph, *last;
4294 int voffset;
ee569018 4295 int glyph_not_available_p;
06a2c219 4296
06a2c219
GM
4297 xassert (s->f == XFRAME (s->w->frame));
4298 xassert (s->nchars == 0);
4299 xassert (start >= 0 && end > start);
4300
66ac4b0e 4301 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4302 glyph = s->row->glyphs[s->area] + start;
4303 last = s->row->glyphs[s->area] + end;
4304 voffset = glyph->voffset;
4305
ee569018
KH
4306 glyph_not_available_p = glyph->glyph_not_available_p;
4307
06a2c219
GM
4308 while (glyph < last
4309 && glyph->type == CHAR_GLYPH
4310 && glyph->voffset == voffset
ee569018
KH
4311 /* Same face id implies same font, nowadays. */
4312 && glyph->face_id == face_id
4313 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4314 {
ee569018
KH
4315 int two_byte_p;
4316
06a2c219 4317 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4318 s->char2b + s->nchars,
4319 &two_byte_p);
4320 s->two_byte_p = two_byte_p;
06a2c219
GM
4321 ++s->nchars;
4322 xassert (s->nchars <= end - start);
4323 s->width += glyph->pixel_width;
4324 ++glyph;
4325 }
4326
4327 s->font = s->face->font;
4328 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4329
4330 /* If the specified font could not be loaded, use the frame's font,
4331 but record the fact that we couldn't load it in
4332 S->font_not_found_p so that we can draw rectangles for the
4333 characters of the glyph string. */
ee569018 4334 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4335 {
4336 s->font_not_found_p = 1;
4337 s->font = FRAME_FONT (s->f);
4338 }
4339
4340 /* Adjust base line for subscript/superscript text. */
4341 s->ybase += voffset;
66ac4b0e 4342
06a2c219
GM
4343 xassert (s->face && s->face->gc);
4344 return glyph - s->row->glyphs[s->area];
07e34cb0 4345}
dc6f92b8 4346
06a2c219
GM
4347
4348/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4349
dfcf069d 4350static void
06a2c219
GM
4351x_fill_image_glyph_string (s)
4352 struct glyph_string *s;
4353{
4354 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4355 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4356 xassert (s->img);
43d120d8 4357 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4358 s->font = s->face->font;
4359 s->width = s->first_glyph->pixel_width;
4360
4361 /* Adjust base line for subscript/superscript text. */
4362 s->ybase += s->first_glyph->voffset;
4363}
4364
4365
209f68d9 4366/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4367
209f68d9
GM
4368 ROW is the glyph row in which the glyphs are found, AREA is the
4369 area within the row. START is the index of the first glyph to
4370 consider, END is the index of the last + 1.
4371
4372 Value is the index of the first glyph not in S. */
4373
4374static int
4375x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4376 struct glyph_string *s;
209f68d9
GM
4377 struct glyph_row *row;
4378 enum glyph_row_area area;
4379 int start, end;
06a2c219 4380{
209f68d9
GM
4381 struct glyph *glyph, *last;
4382 int voffset, face_id;
4383
06a2c219 4384 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4385
4386 glyph = s->row->glyphs[s->area] + start;
4387 last = s->row->glyphs[s->area] + end;
4388 face_id = glyph->face_id;
4389 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4390 s->font = s->face->font;
209f68d9
GM
4391 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4392 s->width = glyph->pixel_width;
4393 voffset = glyph->voffset;
4394
4395 for (++glyph;
4396 (glyph < last
4397 && glyph->type == STRETCH_GLYPH
4398 && glyph->voffset == voffset
4399 && glyph->face_id == face_id);
4400 ++glyph)
4401 s->width += glyph->pixel_width;
06a2c219
GM
4402
4403 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4404 s->ybase += voffset;
4405
4406 xassert (s->face && s->face->gc);
4407 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4408}
4409
4410
4411/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4412 of XChar2b structures for S; it can't be allocated in
4413 x_init_glyph_string because it must be allocated via `alloca'. W
4414 is the window on which S is drawn. ROW and AREA are the glyph row
4415 and area within the row from which S is constructed. START is the
4416 index of the first glyph structure covered by S. HL is a
4417 face-override for drawing S. */
4418
4419static void
4420x_init_glyph_string (s, char2b, w, row, area, start, hl)
4421 struct glyph_string *s;
4422 XChar2b *char2b;
4423 struct window *w;
4424 struct glyph_row *row;
4425 enum glyph_row_area area;
4426 int start;
4427 enum draw_glyphs_face hl;
4428{
4429 bzero (s, sizeof *s);
4430 s->w = w;
4431 s->f = XFRAME (w->frame);
4432 s->display = FRAME_X_DISPLAY (s->f);
4433 s->window = FRAME_X_WINDOW (s->f);
4434 s->char2b = char2b;
4435 s->hl = hl;
4436 s->row = row;
4437 s->area = area;
4438 s->first_glyph = row->glyphs[area] + start;
4439 s->height = row->height;
4440 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4441
9ea173e8
GM
4442 /* Display the internal border below the tool-bar window. */
4443 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4444 s->y -= s->f->output_data.x->internal_border_width;
4445
4446 s->ybase = s->y + row->ascent;
4447}
4448
4449
4450/* Set background width of glyph string S. START is the index of the
4451 first glyph following S. LAST_X is the right-most x-position + 1
4452 in the drawing area. */
4453
4454static INLINE void
4455x_set_glyph_string_background_width (s, start, last_x)
4456 struct glyph_string *s;
4457 int start;
4458 int last_x;
4459{
4460 /* If the face of this glyph string has to be drawn to the end of
4461 the drawing area, set S->extends_to_end_of_line_p. */
4462 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4463
4464 if (start == s->row->used[s->area]
4465 && s->hl == DRAW_NORMAL_TEXT
4466 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4467 || s->face->background != default_face->background
4468 || s->face->stipple != default_face->stipple))
4469 s->extends_to_end_of_line_p = 1;
4470
4471 /* If S extends its face to the end of the line, set its
4472 background_width to the distance to the right edge of the drawing
4473 area. */
4474 if (s->extends_to_end_of_line_p)
1da3fd71 4475 s->background_width = last_x - s->x + 1;
06a2c219
GM
4476 else
4477 s->background_width = s->width;
4478}
4479
4480
4481/* Add a glyph string for a stretch glyph to the list of strings
4482 between HEAD and TAIL. START is the index of the stretch glyph in
4483 row area AREA of glyph row ROW. END is the index of the last glyph
4484 in that glyph row area. X is the current output position assigned
4485 to the new glyph string constructed. HL overrides that face of the
4486 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4487 is the right-most x-position of the drawing area. */
4488
8abee2e1
DL
4489/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4490 and below -- keep them on one line. */
4491#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4492 do \
4493 { \
4494 s = (struct glyph_string *) alloca (sizeof *s); \
4495 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4496 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4497 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4498 s->x = (X); \
4499 } \
4500 while (0)
4501
4502
4503/* Add a glyph string for an image glyph to the list of strings
4504 between HEAD and TAIL. START is the index of the image glyph in
4505 row area AREA of glyph row ROW. END is the index of the last glyph
4506 in that glyph row area. X is the current output position assigned
4507 to the new glyph string constructed. HL overrides that face of the
4508 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4509 is the right-most x-position of the drawing area. */
4510
8abee2e1 4511#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4512 do \
4513 { \
4514 s = (struct glyph_string *) alloca (sizeof *s); \
4515 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4516 x_fill_image_glyph_string (s); \
4517 x_append_glyph_string (&HEAD, &TAIL, s); \
4518 ++START; \
4519 s->x = (X); \
4520 } \
4521 while (0)
4522
4523
4524/* Add a glyph string for a sequence of character glyphs to the list
4525 of strings between HEAD and TAIL. START is the index of the first
4526 glyph in row area AREA of glyph row ROW that is part of the new
4527 glyph string. END is the index of the last glyph in that glyph row
4528 area. X is the current output position assigned to the new glyph
4529 string constructed. HL overrides that face of the glyph; e.g. it
4530 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4531 right-most x-position of the drawing area. */
4532
8abee2e1 4533#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4534 do \
4535 { \
3e71d8f2 4536 int c, face_id; \
06a2c219
GM
4537 XChar2b *char2b; \
4538 \
43d120d8 4539 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4540 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4541 \
b4192550
KH
4542 s = (struct glyph_string *) alloca (sizeof *s); \
4543 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4544 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4545 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4546 s->x = (X); \
4547 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4548 OVERLAPS_P); \
06a2c219
GM
4549 } \
4550 while (0)
4551
4552
b4192550
KH
4553/* Add a glyph string for a composite sequence to the list of strings
4554 between HEAD and TAIL. START is the index of the first glyph in
4555 row area AREA of glyph row ROW that is part of the new glyph
4556 string. END is the index of the last glyph in that glyph row area.
4557 X is the current output position assigned to the new glyph string
4558 constructed. HL overrides that face of the glyph; e.g. it is
4559 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4560 x-position of the drawing area. */
4561
6c27ec25 4562#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4563 do { \
43d120d8
KH
4564 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4565 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4566 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4567 struct composition *cmp = composition_table[cmp_id]; \
4568 int glyph_len = cmp->glyph_len; \
4569 XChar2b *char2b; \
4570 struct face **faces; \
4571 struct glyph_string *first_s = NULL; \
4572 int n; \
4573 \
ee569018 4574 base_face = base_face->ascii_face; \
b4192550
KH
4575 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4576 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4577 /* At first, fill in `char2b' and `faces'. */ \
4578 for (n = 0; n < glyph_len; n++) \
4579 { \
43d120d8 4580 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4581 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4582 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4583 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4584 this_face_id, char2b + n, 1); \
b4192550
KH
4585 } \
4586 \
4587 /* Make glyph_strings for each glyph sequence that is drawable by \
4588 the same face, and append them to HEAD/TAIL. */ \
4589 for (n = 0; n < cmp->glyph_len;) \
4590 { \
4591 s = (struct glyph_string *) alloca (sizeof *s); \
4592 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4593 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4594 s->cmp = cmp; \
4595 s->gidx = n; \
b4192550
KH
4596 s->x = (X); \
4597 \
4598 if (n == 0) \
4599 first_s = s; \
4600 \
4601 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4602 } \
4603 \
4604 ++START; \
4605 s = first_s; \
4606 } while (0)
4607
4608
06a2c219
GM
4609/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4610 of AREA of glyph row ROW on window W between indices START and END.
4611 HL overrides the face for drawing glyph strings, e.g. it is
4612 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4613 x-positions of the drawing area.
4614
4615 This is an ugly monster macro construct because we must use alloca
4616 to allocate glyph strings (because x_draw_glyphs can be called
4617 asynchronously). */
4618
8abee2e1 4619#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4620 do \
4621 { \
4622 HEAD = TAIL = NULL; \
4623 while (START < END) \
4624 { \
4625 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4626 switch (first_glyph->type) \
4627 { \
4628 case CHAR_GLYPH: \
4629 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4630 TAIL, HL, X, LAST_X, \
4631 OVERLAPS_P); \
06a2c219
GM
4632 break; \
4633 \
b4192550
KH
4634 case COMPOSITE_GLYPH: \
4635 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4636 HEAD, TAIL, HL, X, LAST_X,\
4637 OVERLAPS_P); \
4638 break; \
4639 \
06a2c219
GM
4640 case STRETCH_GLYPH: \
4641 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4642 HEAD, TAIL, HL, X, LAST_X); \
4643 break; \
4644 \
4645 case IMAGE_GLYPH: \
4646 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4647 TAIL, HL, X, LAST_X); \
4648 break; \
4649 \
4650 default: \
4651 abort (); \
4652 } \
4653 \
4654 x_set_glyph_string_background_width (s, START, LAST_X); \
4655 (X) += s->width; \
4656 } \
4657 } \
4658 while (0)
4659
4660
4661/* Draw glyphs between START and END in AREA of ROW on window W,
4662 starting at x-position X. X is relative to AREA in W. HL is a
4663 face-override with the following meaning:
4664
4665 DRAW_NORMAL_TEXT draw normally
4666 DRAW_CURSOR draw in cursor face
4667 DRAW_MOUSE_FACE draw in mouse face.
4668 DRAW_INVERSE_VIDEO draw in mode line face
4669 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4670 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4671
4672 If REAL_START is non-null, return in *REAL_START the real starting
4673 position for display. This can be different from START in case
4674 overlapping glyphs must be displayed. If REAL_END is non-null,
4675 return in *REAL_END the real end position for display. This can be
4676 different from END in case overlapping glyphs must be displayed.
4677
66ac4b0e
GM
4678 If OVERLAPS_P is non-zero, draw only the foreground of characters
4679 and clip to the physical height of ROW.
4680
06a2c219
GM
4681 Value is the x-position reached, relative to AREA of W. */
4682
4683static int
66ac4b0e
GM
4684x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4685 overlaps_p)
06a2c219
GM
4686 struct window *w;
4687 int x;
4688 struct glyph_row *row;
4689 enum glyph_row_area area;
4690 int start, end;
4691 enum draw_glyphs_face hl;
4692 int *real_start, *real_end;
66ac4b0e 4693 int overlaps_p;
dc6f92b8 4694{
06a2c219
GM
4695 struct glyph_string *head, *tail;
4696 struct glyph_string *s;
4697 int last_x, area_width;
4698 int x_reached;
4699 int i, j;
4700
4701 /* Let's rather be paranoid than getting a SEGV. */
06a2c219 4702 end = min (end, row->used[area]);
a8710abf
GM
4703 start = max (0, start);
4704 start = min (end, start);
06a2c219
GM
4705 if (real_start)
4706 *real_start = start;
4707 if (real_end)
4708 *real_end = end;
4709
4710 /* Translate X to frame coordinates. Set last_x to the right
4711 end of the drawing area. */
4712 if (row->full_width_p)
4713 {
4714 /* X is relative to the left edge of W, without scroll bars
4715 or flag areas. */
4716 struct frame *f = XFRAME (w->frame);
110859fc 4717 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4718 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4719
06a2c219
GM
4720 x += window_left_x;
4721 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4722 last_x = window_left_x + area_width;
4723
4724 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4725 {
110859fc 4726 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4727 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4728 last_x += width;
4729 else
4730 x -= width;
4731 }
dc6f92b8 4732
b9432a85
GM
4733 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4734 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4735 }
4736 else
dc6f92b8 4737 {
06a2c219
GM
4738 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4739 area_width = window_box_width (w, area);
4740 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4741 }
4742
06a2c219
GM
4743 /* Build a doubly-linked list of glyph_string structures between
4744 head and tail from what we have to draw. Note that the macro
4745 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4746 the reason we use a separate variable `i'. */
4747 i = start;
66ac4b0e
GM
4748 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4749 overlaps_p);
06a2c219
GM
4750 if (tail)
4751 x_reached = tail->x + tail->background_width;
4752 else
4753 x_reached = x;
90e65f07 4754
06a2c219
GM
4755 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4756 the row, redraw some glyphs in front or following the glyph
4757 strings built above. */
a8710abf 4758 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4759 {
4760 int dummy_x = 0;
4761 struct glyph_string *h, *t;
4762
4763 /* Compute overhangs for all glyph strings. */
4764 for (s = head; s; s = s->next)
4765 x_compute_glyph_string_overhangs (s);
4766
4767 /* Prepend glyph strings for glyphs in front of the first glyph
4768 string that are overwritten because of the first glyph
4769 string's left overhang. The background of all strings
4770 prepended must be drawn because the first glyph string
4771 draws over it. */
4772 i = x_left_overwritten (head);
4773 if (i >= 0)
4774 {
4775 j = i;
4776 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4777 DRAW_NORMAL_TEXT, dummy_x, last_x,
4778 overlaps_p);
06a2c219
GM
4779 start = i;
4780 if (real_start)
4781 *real_start = start;
4782 x_compute_overhangs_and_x (t, head->x, 1);
4783 x_prepend_glyph_string_lists (&head, &tail, h, t);
4784 }
58769bee 4785
06a2c219
GM
4786 /* Prepend glyph strings for glyphs in front of the first glyph
4787 string that overwrite that glyph string because of their
4788 right overhang. For these strings, only the foreground must
4789 be drawn, because it draws over the glyph string at `head'.
4790 The background must not be drawn because this would overwrite
4791 right overhangs of preceding glyphs for which no glyph
4792 strings exist. */
4793 i = x_left_overwriting (head);
4794 if (i >= 0)
4795 {
4796 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4797 DRAW_NORMAL_TEXT, dummy_x, last_x,
4798 overlaps_p);
06a2c219
GM
4799 for (s = h; s; s = s->next)
4800 s->background_filled_p = 1;
4801 if (real_start)
4802 *real_start = i;
4803 x_compute_overhangs_and_x (t, head->x, 1);
4804 x_prepend_glyph_string_lists (&head, &tail, h, t);
4805 }
dbcb258a 4806
06a2c219
GM
4807 /* Append glyphs strings for glyphs following the last glyph
4808 string tail that are overwritten by tail. The background of
4809 these strings has to be drawn because tail's foreground draws
4810 over it. */
4811 i = x_right_overwritten (tail);
4812 if (i >= 0)
4813 {
4814 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4815 DRAW_NORMAL_TEXT, x, last_x,
4816 overlaps_p);
06a2c219
GM
4817 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4818 x_append_glyph_string_lists (&head, &tail, h, t);
4819 if (real_end)
4820 *real_end = i;
4821 }
dc6f92b8 4822
06a2c219
GM
4823 /* Append glyph strings for glyphs following the last glyph
4824 string tail that overwrite tail. The foreground of such
4825 glyphs has to be drawn because it writes into the background
4826 of tail. The background must not be drawn because it could
4827 paint over the foreground of following glyphs. */
4828 i = x_right_overwriting (tail);
4829 if (i >= 0)
4830 {
4831 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4832 DRAW_NORMAL_TEXT, x, last_x,
4833 overlaps_p);
06a2c219
GM
4834 for (s = h; s; s = s->next)
4835 s->background_filled_p = 1;
4836 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4837 x_append_glyph_string_lists (&head, &tail, h, t);
4838 if (real_end)
4839 *real_end = i;
4840 }
4841 }
58769bee 4842
06a2c219
GM
4843 /* Draw all strings. */
4844 for (s = head; s; s = s->next)
4845 x_draw_glyph_string (s);
dc6f92b8 4846
06a2c219
GM
4847 /* Value is the x-position up to which drawn, relative to AREA of W.
4848 This doesn't include parts drawn because of overhangs. */
4849 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4850 if (!row->full_width_p)
4851 {
4852 if (area > LEFT_MARGIN_AREA)
4853 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4854 if (area > TEXT_AREA)
4855 x_reached -= window_box_width (w, TEXT_AREA);
4856 }
a8710abf 4857
06a2c219
GM
4858 return x_reached;
4859}
dc6f92b8 4860
dc6f92b8 4861
66ac4b0e
GM
4862/* Fix the display of area AREA of overlapping row ROW in window W. */
4863
4864static void
4865x_fix_overlapping_area (w, row, area)
4866 struct window *w;
4867 struct glyph_row *row;
4868 enum glyph_row_area area;
4869{
4870 int i, x;
4871
4872 BLOCK_INPUT;
4873
4874 if (area == LEFT_MARGIN_AREA)
4875 x = 0;
4876 else if (area == TEXT_AREA)
4877 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4878 else
4879 x = (window_box_width (w, LEFT_MARGIN_AREA)
4880 + window_box_width (w, TEXT_AREA));
4881
4882 for (i = 0; i < row->used[area];)
4883 {
4884 if (row->glyphs[area][i].overlaps_vertically_p)
4885 {
4886 int start = i, start_x = x;
4887
4888 do
4889 {
4890 x += row->glyphs[area][i].pixel_width;
4891 ++i;
4892 }
4893 while (i < row->used[area]
4894 && row->glyphs[area][i].overlaps_vertically_p);
4895
4896 x_draw_glyphs (w, start_x, row, area, start, i,
4897 (row->inverse_p
4898 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4899 NULL, NULL, 1);
4900 }
4901 else
4902 {
4903 x += row->glyphs[area][i].pixel_width;
4904 ++i;
4905 }
4906 }
4907
4908 UNBLOCK_INPUT;
4909}
4910
4911
06a2c219
GM
4912/* Output LEN glyphs starting at START at the nominal cursor position.
4913 Advance the nominal cursor over the text. The global variable
4914 updated_window contains the window being updated, updated_row is
4915 the glyph row being updated, and updated_area is the area of that
4916 row being updated. */
dc6f92b8 4917
06a2c219
GM
4918static void
4919x_write_glyphs (start, len)
4920 struct glyph *start;
4921 int len;
4922{
4923 int x, hpos, real_start, real_end;
d9cdbb3d 4924
06a2c219 4925 xassert (updated_window && updated_row);
dc6f92b8 4926 BLOCK_INPUT;
06a2c219
GM
4927
4928 /* Write glyphs. */
dc6f92b8 4929
06a2c219
GM
4930 hpos = start - updated_row->glyphs[updated_area];
4931 x = x_draw_glyphs (updated_window, output_cursor.x,
4932 updated_row, updated_area,
4933 hpos, hpos + len,
4934 (updated_row->inverse_p
4935 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 4936 &real_start, &real_end, 0);
b30ec466 4937
06a2c219
GM
4938 /* If we drew over the cursor, note that it is not visible any more. */
4939 note_overwritten_text_cursor (updated_window, real_start,
4940 real_end - real_start);
dc6f92b8
JB
4941
4942 UNBLOCK_INPUT;
06a2c219
GM
4943
4944 /* Advance the output cursor. */
4945 output_cursor.hpos += len;
4946 output_cursor.x = x;
dc6f92b8
JB
4947}
4948
0cdd0c9f 4949
06a2c219 4950/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4951
06a2c219
GM
4952static void
4953x_insert_glyphs (start, len)
4954 struct glyph *start;
4955 register int len;
4956{
4957 struct frame *f;
4958 struct window *w;
4959 int line_height, shift_by_width, shifted_region_width;
4960 struct glyph_row *row;
4961 struct glyph *glyph;
4962 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4963
06a2c219 4964 xassert (updated_window && updated_row);
0cdd0c9f 4965 BLOCK_INPUT;
06a2c219
GM
4966 w = updated_window;
4967 f = XFRAME (WINDOW_FRAME (w));
4968
4969 /* Get the height of the line we are in. */
4970 row = updated_row;
4971 line_height = row->height;
4972
4973 /* Get the width of the glyphs to insert. */
4974 shift_by_width = 0;
4975 for (glyph = start; glyph < start + len; ++glyph)
4976 shift_by_width += glyph->pixel_width;
4977
4978 /* Get the width of the region to shift right. */
4979 shifted_region_width = (window_box_width (w, updated_area)
4980 - output_cursor.x
4981 - shift_by_width);
4982
4983 /* Shift right. */
4984 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4985 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4986 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4987 f->output_data.x->normal_gc,
4988 frame_x, frame_y,
4989 shifted_region_width, line_height,
4990 frame_x + shift_by_width, frame_y);
4991
4992 /* Write the glyphs. */
4993 hpos = start - row->glyphs[updated_area];
4994 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 4995 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
4996 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4997
4998 /* Advance the output cursor. */
4999 output_cursor.hpos += len;
5000 output_cursor.x += shift_by_width;
0cdd0c9f
RS
5001 UNBLOCK_INPUT;
5002}
0cdd0c9f 5003
0cdd0c9f 5004
06a2c219
GM
5005/* Delete N glyphs at the nominal cursor position. Not implemented
5006 for X frames. */
c83febd7
RS
5007
5008static void
06a2c219
GM
5009x_delete_glyphs (n)
5010 register int n;
c83febd7 5011{
06a2c219 5012 abort ();
c83febd7
RS
5013}
5014
0cdd0c9f 5015
06a2c219
GM
5016/* Erase the current text line from the nominal cursor position
5017 (inclusive) to pixel column TO_X (exclusive). The idea is that
5018 everything from TO_X onward is already erased.
5019
5020 TO_X is a pixel position relative to updated_area of
5021 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 5022
06a2c219
GM
5023static void
5024x_clear_end_of_line (to_x)
5025 int to_x;
5026{
5027 struct frame *f;
5028 struct window *w = updated_window;
5029 int max_x, min_y, max_y;
5030 int from_x, from_y, to_y;
5031
5032 xassert (updated_window && updated_row);
5033 f = XFRAME (w->frame);
5034
5035 if (updated_row->full_width_p)
5036 {
5037 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5038 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5039 && !w->pseudo_window_p)
5040 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 5041 }
06a2c219
GM
5042 else
5043 max_x = window_box_width (w, updated_area);
5044 max_y = window_text_bottom_y (w);
dc6f92b8 5045
06a2c219
GM
5046 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5047 of window. For TO_X > 0, truncate to end of drawing area. */
5048 if (to_x == 0)
5049 return;
5050 else if (to_x < 0)
5051 to_x = max_x;
5052 else
5053 to_x = min (to_x, max_x);
dbc4e1c1 5054
06a2c219
GM
5055 to_y = min (max_y, output_cursor.y + updated_row->height);
5056
5057 /* Notice if the cursor will be cleared by this operation. */
5058 if (!updated_row->full_width_p)
5059 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 5060
06a2c219
GM
5061 from_x = output_cursor.x;
5062
5063 /* Translate to frame coordinates. */
5064 if (updated_row->full_width_p)
5065 {
5066 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5067 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5068 }
0cdd0c9f
RS
5069 else
5070 {
06a2c219
GM
5071 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5072 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5073 }
5074
045dee35 5075 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5076 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5077 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5078
5079 /* Prevent inadvertently clearing to end of the X window. */
5080 if (to_x > from_x && to_y > from_y)
5081 {
5082 BLOCK_INPUT;
5083 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5084 from_x, from_y, to_x - from_x, to_y - from_y,
5085 False);
5086 UNBLOCK_INPUT;
0cdd0c9f 5087 }
0cdd0c9f 5088}
dbc4e1c1 5089
0cdd0c9f 5090
06a2c219 5091/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5092 frame. Otherwise clear the selected frame. */
06a2c219
GM
5093
5094static void
5095x_clear_frame ()
0cdd0c9f 5096{
06a2c219 5097 struct frame *f;
0cdd0c9f 5098
06a2c219
GM
5099 if (updating_frame)
5100 f = updating_frame;
0cdd0c9f 5101 else
b86bd3dd 5102 f = SELECTED_FRAME ();
58769bee 5103
06a2c219
GM
5104 /* Clearing the frame will erase any cursor, so mark them all as no
5105 longer visible. */
5106 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5107 output_cursor.hpos = output_cursor.vpos = 0;
5108 output_cursor.x = -1;
5109
5110 /* We don't set the output cursor here because there will always
5111 follow an explicit cursor_to. */
5112 BLOCK_INPUT;
5113 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5114
5115 /* We have to clear the scroll bars, too. If we have changed
5116 colors or something like that, then they should be notified. */
5117 x_scroll_bar_clear (f);
0cdd0c9f 5118
06a2c219
GM
5119 XFlush (FRAME_X_DISPLAY (f));
5120 UNBLOCK_INPUT;
dc6f92b8 5121}
06a2c219
GM
5122
5123
dc6f92b8 5124\f
dbc4e1c1
JB
5125/* Invert the middle quarter of the frame for .15 sec. */
5126
06a2c219
GM
5127/* We use the select system call to do the waiting, so we have to make
5128 sure it's available. If it isn't, we just won't do visual bells. */
5129
dbc4e1c1
JB
5130#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5131
06a2c219
GM
5132
5133/* Subtract the `struct timeval' values X and Y, storing the result in
5134 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5135
5136static int
5137timeval_subtract (result, x, y)
5138 struct timeval *result, x, y;
5139{
06a2c219
GM
5140 /* Perform the carry for the later subtraction by updating y. This
5141 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5142 if (x.tv_usec < y.tv_usec)
5143 {
5144 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5145 y.tv_usec -= 1000000 * nsec;
5146 y.tv_sec += nsec;
5147 }
06a2c219 5148
dbc4e1c1
JB
5149 if (x.tv_usec - y.tv_usec > 1000000)
5150 {
5151 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5152 y.tv_usec += 1000000 * nsec;
5153 y.tv_sec -= nsec;
5154 }
5155
06a2c219
GM
5156 /* Compute the time remaining to wait. tv_usec is certainly
5157 positive. */
dbc4e1c1
JB
5158 result->tv_sec = x.tv_sec - y.tv_sec;
5159 result->tv_usec = x.tv_usec - y.tv_usec;
5160
06a2c219
GM
5161 /* Return indication of whether the result should be considered
5162 negative. */
dbc4e1c1
JB
5163 return x.tv_sec < y.tv_sec;
5164}
dc6f92b8 5165
dfcf069d 5166void
f676886a
JB
5167XTflash (f)
5168 struct frame *f;
dc6f92b8 5169{
dbc4e1c1 5170 BLOCK_INPUT;
dc6f92b8 5171
dbc4e1c1
JB
5172 {
5173 GC gc;
dc6f92b8 5174
06a2c219
GM
5175 /* Create a GC that will use the GXxor function to flip foreground
5176 pixels into background pixels. */
dbc4e1c1
JB
5177 {
5178 XGCValues values;
dc6f92b8 5179
dbc4e1c1 5180 values.function = GXxor;
7556890b
RS
5181 values.foreground = (f->output_data.x->foreground_pixel
5182 ^ f->output_data.x->background_pixel);
58769bee 5183
334208b7 5184 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5185 GCFunction | GCForeground, &values);
5186 }
dc6f92b8 5187
dbc4e1c1 5188 {
e84e14c3
RS
5189 /* Get the height not including a menu bar widget. */
5190 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5191 /* Height of each line to flash. */
5192 int flash_height = FRAME_LINE_HEIGHT (f);
5193 /* These will be the left and right margins of the rectangles. */
5194 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5195 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5196
5197 int width;
5198
5199 /* Don't flash the area between a scroll bar and the frame
5200 edge it is next to. */
5201 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5202 {
5203 case vertical_scroll_bar_left:
5204 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5205 break;
5206
5207 case vertical_scroll_bar_right:
5208 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5209 break;
06a2c219
GM
5210
5211 default:
5212 break;
e84e14c3
RS
5213 }
5214
5215 width = flash_right - flash_left;
5216
5217 /* If window is tall, flash top and bottom line. */
5218 if (height > 3 * FRAME_LINE_HEIGHT (f))
5219 {
5220 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5221 flash_left,
5222 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5223 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5224 width, flash_height);
5225 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5226 flash_left,
5227 (height - flash_height
5228 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5229 width, flash_height);
5230 }
5231 else
5232 /* If it is short, flash it all. */
5233 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5234 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5235 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5236
06a2c219 5237 x_flush (f);
dc6f92b8 5238
dbc4e1c1 5239 {
06a2c219 5240 struct timeval wakeup;
dc6f92b8 5241
66c30ea1 5242 EMACS_GET_TIME (wakeup);
dc6f92b8 5243
dbc4e1c1
JB
5244 /* Compute time to wait until, propagating carry from usecs. */
5245 wakeup.tv_usec += 150000;
5246 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5247 wakeup.tv_usec %= 1000000;
5248
5249 /* Keep waiting until past the time wakeup. */
5250 while (1)
5251 {
5252 struct timeval timeout;
5253
66c30ea1 5254 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5255
5256 /* In effect, timeout = wakeup - timeout.
5257 Break if result would be negative. */
5258 if (timeval_subtract (&timeout, wakeup, timeout))
5259 break;
5260
5261 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5262 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5263 }
5264 }
58769bee 5265
e84e14c3
RS
5266 /* If window is tall, flash top and bottom line. */
5267 if (height > 3 * FRAME_LINE_HEIGHT (f))
5268 {
5269 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5270 flash_left,
5271 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5272 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5273 width, flash_height);
5274 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5275 flash_left,
5276 (height - flash_height
5277 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5278 width, flash_height);
5279 }
5280 else
5281 /* If it is short, flash it all. */
5282 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5283 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5284 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5285
334208b7 5286 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5287 x_flush (f);
dc6f92b8 5288 }
dbc4e1c1
JB
5289 }
5290
5291 UNBLOCK_INPUT;
dc6f92b8
JB
5292}
5293
06a2c219 5294#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5295
5296
dc6f92b8
JB
5297/* Make audible bell. */
5298
dfcf069d 5299void
dc6f92b8
JB
5300XTring_bell ()
5301{
b86bd3dd
GM
5302 struct frame *f = SELECTED_FRAME ();
5303
5304 if (FRAME_X_DISPLAY (f))
5305 {
dbc4e1c1 5306#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5307 if (visible_bell)
5308 XTflash (f);
5309 else
dbc4e1c1 5310#endif
b86bd3dd
GM
5311 {
5312 BLOCK_INPUT;
5313 XBell (FRAME_X_DISPLAY (f), 0);
5314 XFlush (FRAME_X_DISPLAY (f));
5315 UNBLOCK_INPUT;
5316 }
dc6f92b8
JB
5317 }
5318}
06a2c219 5319
dc6f92b8 5320\f
06a2c219
GM
5321/* Specify how many text lines, from the top of the window,
5322 should be affected by insert-lines and delete-lines operations.
5323 This, and those operations, are used only within an update
5324 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5325
dfcf069d 5326static void
06a2c219
GM
5327XTset_terminal_window (n)
5328 register int n;
dc6f92b8 5329{
06a2c219 5330 /* This function intentionally left blank. */
dc6f92b8
JB
5331}
5332
06a2c219
GM
5333
5334\f
5335/***********************************************************************
5336 Line Dance
5337 ***********************************************************************/
5338
5339/* Perform an insert-lines or delete-lines operation, inserting N
5340 lines or deleting -N lines at vertical position VPOS. */
5341
dfcf069d 5342static void
06a2c219
GM
5343x_ins_del_lines (vpos, n)
5344 int vpos, n;
dc6f92b8
JB
5345{
5346 abort ();
5347}
06a2c219
GM
5348
5349
5350/* Scroll part of the display as described by RUN. */
dc6f92b8 5351
dfcf069d 5352static void
06a2c219
GM
5353x_scroll_run (w, run)
5354 struct window *w;
5355 struct run *run;
dc6f92b8 5356{
06a2c219
GM
5357 struct frame *f = XFRAME (w->frame);
5358 int x, y, width, height, from_y, to_y, bottom_y;
5359
5360 /* Get frame-relative bounding box of the text display area of W,
5361 without mode lines. Include in this box the flags areas to the
5362 left and right of W. */
5363 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5364 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5365 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5366
5367 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5368 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5369 bottom_y = y + height;
dc6f92b8 5370
06a2c219
GM
5371 if (to_y < from_y)
5372 {
5373 /* Scrolling up. Make sure we don't copy part of the mode
5374 line at the bottom. */
5375 if (from_y + run->height > bottom_y)
5376 height = bottom_y - from_y;
5377 else
5378 height = run->height;
5379 }
dc6f92b8 5380 else
06a2c219
GM
5381 {
5382 /* Scolling down. Make sure we don't copy over the mode line.
5383 at the bottom. */
5384 if (to_y + run->height > bottom_y)
5385 height = bottom_y - to_y;
5386 else
5387 height = run->height;
5388 }
7a13e894 5389
06a2c219
GM
5390 BLOCK_INPUT;
5391
5392 /* Cursor off. Will be switched on again in x_update_window_end. */
5393 updated_window = w;
5394 x_clear_cursor (w);
5395
5396 XCopyArea (FRAME_X_DISPLAY (f),
5397 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5398 f->output_data.x->normal_gc,
5399 x, from_y,
5400 width, height,
5401 x, to_y);
5402
5403 UNBLOCK_INPUT;
5404}
dc6f92b8 5405
dc6f92b8 5406
06a2c219
GM
5407\f
5408/***********************************************************************
5409 Exposure Events
5410 ***********************************************************************/
5411
5412/* Redisplay an exposed area of frame F. X and Y are the upper-left
5413 corner of the exposed rectangle. W and H are width and height of
5414 the exposed area. All are pixel values. W or H zero means redraw
5415 the entire frame. */
dc6f92b8 5416
06a2c219
GM
5417static void
5418expose_frame (f, x, y, w, h)
5419 struct frame *f;
5420 int x, y, w, h;
dc6f92b8 5421{
06a2c219 5422 XRectangle r;
dc6f92b8 5423
06a2c219 5424 TRACE ((stderr, "expose_frame "));
dc6f92b8 5425
06a2c219
GM
5426 /* No need to redraw if frame will be redrawn soon. */
5427 if (FRAME_GARBAGED_P (f))
dc6f92b8 5428 {
06a2c219
GM
5429 TRACE ((stderr, " garbaged\n"));
5430 return;
5431 }
5432
5433 /* If basic faces haven't been realized yet, there is no point in
5434 trying to redraw anything. This can happen when we get an expose
5435 event while Emacs is starting, e.g. by moving another window. */
5436 if (FRAME_FACE_CACHE (f) == NULL
5437 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5438 {
5439 TRACE ((stderr, " no faces\n"));
5440 return;
58769bee 5441 }
06a2c219
GM
5442
5443 if (w == 0 || h == 0)
58769bee 5444 {
06a2c219
GM
5445 r.x = r.y = 0;
5446 r.width = CANON_X_UNIT (f) * f->width;
5447 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5448 }
5449 else
5450 {
06a2c219
GM
5451 r.x = x;
5452 r.y = y;
5453 r.width = w;
5454 r.height = h;
5455 }
5456
5457 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5458 expose_window_tree (XWINDOW (f->root_window), &r);
5459
9ea173e8 5460 if (WINDOWP (f->tool_bar_window))
06a2c219 5461 {
9ea173e8 5462 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5463 XRectangle window_rect;
5464 XRectangle intersection_rect;
5465 int window_x, window_y, window_width, window_height;
5466
5467
5468 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5469 window_rect.x = window_x;
5470 window_rect.y = window_y;
5471 window_rect.width = window_width;
5472 window_rect.height = window_height;
5473
5474 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5475 expose_window (w, &intersection_rect);
5476 }
5477
5478#ifndef USE_X_TOOLKIT
5479 if (WINDOWP (f->menu_bar_window))
5480 {
5481 struct window *w = XWINDOW (f->menu_bar_window);
5482 XRectangle window_rect;
5483 XRectangle intersection_rect;
5484 int window_x, window_y, window_width, window_height;
5485
5486
5487 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5488 window_rect.x = window_x;
5489 window_rect.y = window_y;
5490 window_rect.width = window_width;
5491 window_rect.height = window_height;
5492
5493 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5494 expose_window (w, &intersection_rect);
dc6f92b8 5495 }
06a2c219 5496#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5497}
5498
06a2c219
GM
5499
5500/* Redraw (parts) of all windows in the window tree rooted at W that
5501 intersect R. R contains frame pixel coordinates. */
5502
58769bee 5503static void
06a2c219
GM
5504expose_window_tree (w, r)
5505 struct window *w;
5506 XRectangle *r;
dc6f92b8 5507{
06a2c219
GM
5508 while (w)
5509 {
5510 if (!NILP (w->hchild))
5511 expose_window_tree (XWINDOW (w->hchild), r);
5512 else if (!NILP (w->vchild))
5513 expose_window_tree (XWINDOW (w->vchild), r);
5514 else
5515 {
5516 XRectangle window_rect;
5517 XRectangle intersection_rect;
5518 struct frame *f = XFRAME (w->frame);
5519 int window_x, window_y, window_width, window_height;
5520
5521 /* Frame-relative pixel rectangle of W. */
5522 window_box (w, -1, &window_x, &window_y, &window_width,
5523 &window_height);
5524 window_rect.x
5525 = (window_x
110859fc 5526 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5527 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5528 window_rect.y = window_y;
5529 window_rect.width
5530 = (window_width
110859fc 5531 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5532 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5533 window_rect.height
5534 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5535
5536 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5537 expose_window (w, &intersection_rect);
5538 }
58769bee 5539
06a2c219
GM
5540 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5541 }
5542}
58769bee 5543
dc6f92b8 5544
06a2c219
GM
5545/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5546 which intersects rectangle R. R is in window-relative coordinates. */
5547
5548static void
5549expose_area (w, row, r, area)
5550 struct window *w;
5551 struct glyph_row *row;
5552 XRectangle *r;
5553 enum glyph_row_area area;
5554{
5555 int x;
5556 struct glyph *first = row->glyphs[area];
5557 struct glyph *end = row->glyphs[area] + row->used[area];
5558 struct glyph *last;
5559 int first_x;
5560
5561 /* Set x to the window-relative start position for drawing glyphs of
5562 AREA. The first glyph of the text area can be partially visible.
5563 The first glyphs of other areas cannot. */
5564 if (area == LEFT_MARGIN_AREA)
5565 x = 0;
5566 else if (area == TEXT_AREA)
5567 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5568 else
5569 x = (window_box_width (w, LEFT_MARGIN_AREA)
5570 + window_box_width (w, TEXT_AREA));
5571
6fb13182
GM
5572 if (area == TEXT_AREA && row->fill_line_p)
5573 /* If row extends face to end of line write the whole line. */
5574 x_draw_glyphs (w, x, row, area,
5575 0, row->used[area],
06a2c219 5576 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5577 NULL, NULL, 0);
6fb13182
GM
5578 else
5579 {
5580 /* Find the first glyph that must be redrawn. */
5581 while (first < end
5582 && x + first->pixel_width < r->x)
5583 {
5584 x += first->pixel_width;
5585 ++first;
5586 }
5587
5588 /* Find the last one. */
5589 last = first;
5590 first_x = x;
5591 while (last < end
5592 && x < r->x + r->width)
5593 {
5594 x += last->pixel_width;
5595 ++last;
5596 }
5597
5598 /* Repaint. */
5599 if (last > first)
5600 x_draw_glyphs (w, first_x, row, area,
5601 first - row->glyphs[area],
5602 last - row->glyphs[area],
5603 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5604 NULL, NULL, 0);
5605 }
06a2c219
GM
5606}
5607
58769bee 5608
06a2c219
GM
5609/* Redraw the parts of the glyph row ROW on window W intersecting
5610 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5611
06a2c219
GM
5612static void
5613expose_line (w, row, r)
5614 struct window *w;
5615 struct glyph_row *row;
5616 XRectangle *r;
5617{
5618 xassert (row->enabled_p);
5619
5620 if (row->mode_line_p || w->pseudo_window_p)
5621 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5622 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5623 NULL, NULL, 0);
06a2c219
GM
5624 else
5625 {
5626 if (row->used[LEFT_MARGIN_AREA])
5627 expose_area (w, row, r, LEFT_MARGIN_AREA);
5628 if (row->used[TEXT_AREA])
5629 expose_area (w, row, r, TEXT_AREA);
5630 if (row->used[RIGHT_MARGIN_AREA])
5631 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5632 x_draw_row_bitmaps (w, row);
5633 }
5634}
dc6f92b8 5635
58769bee 5636
06a2c219
GM
5637/* Return non-zero if W's cursor intersects rectangle R. */
5638
5639static int
5640x_phys_cursor_in_rect_p (w, r)
5641 struct window *w;
5642 XRectangle *r;
5643{
5644 XRectangle cr, result;
5645 struct glyph *cursor_glyph;
5646
5647 cursor_glyph = get_phys_cursor_glyph (w);
5648 if (cursor_glyph)
5649 {
5650 cr.x = w->phys_cursor.x;
5651 cr.y = w->phys_cursor.y;
5652 cr.width = cursor_glyph->pixel_width;
5653 cr.height = w->phys_cursor_height;
5654 return x_intersect_rectangles (&cr, r, &result);
5655 }
5656 else
5657 return 0;
dc6f92b8 5658}
dc6f92b8 5659
06a2c219
GM
5660
5661/* Redraw a rectangle of window W. R is a rectangle in window
5662 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5663
5664static void
06a2c219
GM
5665expose_window (w, r)
5666 struct window *w;
5667 XRectangle *r;
dc6f92b8 5668{
06a2c219
GM
5669 struct glyph_row *row;
5670 int y;
5671 int yb = window_text_bottom_y (w);
5672 int cursor_cleared_p;
dc6f92b8 5673
80c32bcc
GM
5674 /* If window is not yet fully initialized, do nothing. This can
5675 happen when toolkit scroll bars are used and a window is split.
5676 Reconfiguring the scroll bar will generate an expose for a newly
5677 created window. */
5678 if (w->current_matrix == NULL)
5679 return;
5680
06a2c219
GM
5681 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5682 r->x, r->y, r->width, r->height));
dc6f92b8 5683
06a2c219
GM
5684 /* Convert to window coordinates. */
5685 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5686 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5687
06a2c219
GM
5688 /* Turn off the cursor. */
5689 if (!w->pseudo_window_p
5690 && x_phys_cursor_in_rect_p (w, r))
5691 {
5692 x_clear_cursor (w);
5693 cursor_cleared_p = 1;
5694 }
5695 else
5696 cursor_cleared_p = 0;
5697
5698 /* Find the first row intersecting the rectangle R. */
5699 row = w->current_matrix->rows;
5700 y = 0;
5701 while (row->enabled_p
5702 && y < yb
5703 && y + row->height < r->y)
5704 {
5705 y += row->height;
5706 ++row;
5707 }
5708
dc6f92b8 5709 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5710 while (row->enabled_p
5711 && y < yb
5712 && y < r->y + r->height)
5713 {
5714 expose_line (w, row, r);
5715 y += row->height;
5716 ++row;
5717 }
5718
5719 /* Display the mode line if there is one. */
5720 if (WINDOW_WANTS_MODELINE_P (w)
5721 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5722 row->enabled_p)
5723 && row->y < r->y + r->height)
5724 expose_line (w, row, r);
dc6f92b8 5725
06a2c219 5726 if (!w->pseudo_window_p)
dc6f92b8 5727 {
06a2c219
GM
5728 /* Draw border between windows. */
5729 x_draw_vertical_border (w);
5730
5731 /* Turn the cursor on again. */
5732 if (cursor_cleared_p)
5733 x_update_window_cursor (w, 1);
5734 }
5735}
dc6f92b8 5736
dc6f92b8 5737
06a2c219
GM
5738/* Determine the intersection of two rectangles R1 and R2. Return
5739 the intersection in *RESULT. Value is non-zero if RESULT is not
5740 empty. */
5741
5742static int
5743x_intersect_rectangles (r1, r2, result)
5744 XRectangle *r1, *r2, *result;
5745{
5746 XRectangle *left, *right;
5747 XRectangle *upper, *lower;
5748 int intersection_p = 0;
5749
5750 /* Rearrange so that R1 is the left-most rectangle. */
5751 if (r1->x < r2->x)
5752 left = r1, right = r2;
5753 else
5754 left = r2, right = r1;
5755
5756 /* X0 of the intersection is right.x0, if this is inside R1,
5757 otherwise there is no intersection. */
5758 if (right->x <= left->x + left->width)
5759 {
5760 result->x = right->x;
5761
5762 /* The right end of the intersection is the minimum of the
5763 the right ends of left and right. */
5764 result->width = (min (left->x + left->width, right->x + right->width)
5765 - result->x);
5766
5767 /* Same game for Y. */
5768 if (r1->y < r2->y)
5769 upper = r1, lower = r2;
5770 else
5771 upper = r2, lower = r1;
5772
5773 /* The upper end of the intersection is lower.y0, if this is inside
5774 of upper. Otherwise, there is no intersection. */
5775 if (lower->y <= upper->y + upper->height)
dc43ef94 5776 {
06a2c219
GM
5777 result->y = lower->y;
5778
5779 /* The lower end of the intersection is the minimum of the lower
5780 ends of upper and lower. */
5781 result->height = (min (lower->y + lower->height,
5782 upper->y + upper->height)
5783 - result->y);
5784 intersection_p = 1;
dc43ef94 5785 }
dc6f92b8
JB
5786 }
5787
06a2c219 5788 return intersection_p;
dc6f92b8 5789}
06a2c219
GM
5790
5791
5792
5793
dc6f92b8 5794\f
dc6f92b8 5795static void
334208b7
RS
5796frame_highlight (f)
5797 struct frame *f;
dc6f92b8 5798{
b3e1e05c
JB
5799 /* We used to only do this if Vx_no_window_manager was non-nil, but
5800 the ICCCM (section 4.1.6) says that the window's border pixmap
5801 and border pixel are window attributes which are "private to the
5802 client", so we can always change it to whatever we want. */
5803 BLOCK_INPUT;
334208b7 5804 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5805 f->output_data.x->border_pixel);
b3e1e05c 5806 UNBLOCK_INPUT;
5d46f928 5807 x_update_cursor (f, 1);
dc6f92b8
JB
5808}
5809
5810static void
334208b7
RS
5811frame_unhighlight (f)
5812 struct frame *f;
dc6f92b8 5813{
b3e1e05c
JB
5814 /* We used to only do this if Vx_no_window_manager was non-nil, but
5815 the ICCCM (section 4.1.6) says that the window's border pixmap
5816 and border pixel are window attributes which are "private to the
5817 client", so we can always change it to whatever we want. */
5818 BLOCK_INPUT;
334208b7 5819 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5820 f->output_data.x->border_tile);
b3e1e05c 5821 UNBLOCK_INPUT;
5d46f928 5822 x_update_cursor (f, 1);
dc6f92b8 5823}
dc6f92b8 5824
f676886a
JB
5825/* The focus has changed. Update the frames as necessary to reflect
5826 the new situation. Note that we can't change the selected frame
c5acd733 5827 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5828 Each event gets marked with the frame in which it occurred, so the
c5acd733 5829 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5830
6d4238f3 5831static void
0f941935
KH
5832x_new_focus_frame (dpyinfo, frame)
5833 struct x_display_info *dpyinfo;
f676886a 5834 struct frame *frame;
dc6f92b8 5835{
0f941935 5836 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5837
0f941935 5838 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5839 {
58769bee 5840 /* Set this before calling other routines, so that they see
f676886a 5841 the correct value of x_focus_frame. */
0f941935 5842 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5843
5844 if (old_focus && old_focus->auto_lower)
f676886a 5845 x_lower_frame (old_focus);
dc6f92b8
JB
5846
5847#if 0
f676886a 5848 selected_frame = frame;
e0c1aef2
KH
5849 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5850 selected_frame);
f676886a
JB
5851 Fselect_window (selected_frame->selected_window);
5852 choose_minibuf_frame ();
c118dd06 5853#endif /* ! 0 */
dc6f92b8 5854
0f941935
KH
5855 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5856 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5857 else
5858 pending_autoraise_frame = 0;
6d4238f3 5859 }
dc6f92b8 5860
0f941935 5861 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5862}
5863
37c2c98b
RS
5864/* Handle an event saying the mouse has moved out of an Emacs frame. */
5865
5866void
0f941935
KH
5867x_mouse_leave (dpyinfo)
5868 struct x_display_info *dpyinfo;
37c2c98b 5869{
0f941935 5870 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5871}
6d4238f3 5872
f451eb13
JB
5873/* The focus has changed, or we have redirected a frame's focus to
5874 another frame (this happens when a frame uses a surrogate
06a2c219 5875 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5876
5877 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5878 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5879 the appropriate X display info. */
06a2c219 5880
6d4238f3 5881static void
0f941935
KH
5882XTframe_rehighlight (frame)
5883 struct frame *frame;
6d4238f3 5884{
0f941935
KH
5885 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5886}
6d4238f3 5887
0f941935
KH
5888static void
5889x_frame_rehighlight (dpyinfo)
5890 struct x_display_info *dpyinfo;
5891{
5892 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5893
5894 if (dpyinfo->x_focus_frame)
6d4238f3 5895 {
0f941935
KH
5896 dpyinfo->x_highlight_frame
5897 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5898 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5899 : dpyinfo->x_focus_frame);
5900 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5901 {
0f941935
KH
5902 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5903 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5904 }
dc6f92b8 5905 }
6d4238f3 5906 else
0f941935 5907 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5908
0f941935 5909 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5910 {
5911 if (old_highlight)
f676886a 5912 frame_unhighlight (old_highlight);
0f941935
KH
5913 if (dpyinfo->x_highlight_frame)
5914 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5915 }
dc6f92b8 5916}
06a2c219
GM
5917
5918
dc6f92b8 5919\f
06a2c219 5920/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5921
28430d3c
JB
5922/* Initialize mode_switch_bit and modifier_meaning. */
5923static void
334208b7
RS
5924x_find_modifier_meanings (dpyinfo)
5925 struct x_display_info *dpyinfo;
28430d3c 5926{
f689eb05 5927 int min_code, max_code;
28430d3c
JB
5928 KeySym *syms;
5929 int syms_per_code;
5930 XModifierKeymap *mods;
5931
334208b7
RS
5932 dpyinfo->meta_mod_mask = 0;
5933 dpyinfo->shift_lock_mask = 0;
5934 dpyinfo->alt_mod_mask = 0;
5935 dpyinfo->super_mod_mask = 0;
5936 dpyinfo->hyper_mod_mask = 0;
58769bee 5937
9658a521 5938#ifdef HAVE_X11R4
334208b7 5939 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5940#else
4a60f8c5
RS
5941 min_code = dpyinfo->display->min_keycode;
5942 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5943#endif
5944
334208b7 5945 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5946 min_code, max_code - min_code + 1,
5947 &syms_per_code);
334208b7 5948 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5949
58769bee 5950 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5951 Alt keysyms are on. */
28430d3c 5952 {
06a2c219 5953 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5954
5955 for (row = 3; row < 8; row++)
5956 for (col = 0; col < mods->max_keypermod; col++)
5957 {
0299d313
RS
5958 KeyCode code
5959 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5960
af92970c
KH
5961 /* Zeroes are used for filler. Skip them. */
5962 if (code == 0)
5963 continue;
5964
28430d3c
JB
5965 /* Are any of this keycode's keysyms a meta key? */
5966 {
5967 int code_col;
5968
5969 for (code_col = 0; code_col < syms_per_code; code_col++)
5970 {
f689eb05 5971 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5972
f689eb05 5973 switch (sym)
28430d3c 5974 {
f689eb05
JB
5975 case XK_Meta_L:
5976 case XK_Meta_R:
334208b7 5977 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5978 break;
f689eb05
JB
5979
5980 case XK_Alt_L:
5981 case XK_Alt_R:
334208b7 5982 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5983 break;
5984
5985 case XK_Hyper_L:
5986 case XK_Hyper_R:
334208b7 5987 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5988 break;
5989
5990 case XK_Super_L:
5991 case XK_Super_R:
334208b7 5992 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5993 break;
11edeb03
JB
5994
5995 case XK_Shift_Lock:
5996 /* Ignore this if it's not on the lock modifier. */
5997 if ((1 << row) == LockMask)
334208b7 5998 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5999 break;
28430d3c
JB
6000 }
6001 }
6002 }
6003 }
6004 }
6005
f689eb05 6006 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 6007 if (! dpyinfo->meta_mod_mask)
a3c44b14 6008 {
334208b7
RS
6009 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
6010 dpyinfo->alt_mod_mask = 0;
a3c44b14 6011 }
f689eb05 6012
148c4b70
RS
6013 /* If some keys are both alt and meta,
6014 make them just meta, not alt. */
334208b7 6015 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 6016 {
334208b7 6017 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 6018 }
58769bee 6019
28430d3c 6020 XFree ((char *) syms);
f689eb05 6021 XFreeModifiermap (mods);
28430d3c
JB
6022}
6023
dfeccd2d
JB
6024/* Convert between the modifier bits X uses and the modifier bits
6025 Emacs uses. */
06a2c219 6026
7c5283e4 6027static unsigned int
334208b7
RS
6028x_x_to_emacs_modifiers (dpyinfo, state)
6029 struct x_display_info *dpyinfo;
dc6f92b8
JB
6030 unsigned int state;
6031{
334208b7
RS
6032 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
6033 | ((state & ControlMask) ? ctrl_modifier : 0)
6034 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
6035 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
6036 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
6037 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
6038}
6039
dfeccd2d 6040static unsigned int
334208b7
RS
6041x_emacs_to_x_modifiers (dpyinfo, state)
6042 struct x_display_info *dpyinfo;
dfeccd2d
JB
6043 unsigned int state;
6044{
334208b7
RS
6045 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
6046 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
6047 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
6048 | ((state & shift_modifier) ? ShiftMask : 0)
6049 | ((state & ctrl_modifier) ? ControlMask : 0)
6050 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6051}
d047c4eb
KH
6052
6053/* Convert a keysym to its name. */
6054
6055char *
6056x_get_keysym_name (keysym)
6057 KeySym keysym;
6058{
6059 char *value;
6060
6061 BLOCK_INPUT;
6062 value = XKeysymToString (keysym);
6063 UNBLOCK_INPUT;
6064
6065 return value;
6066}
06a2c219
GM
6067
6068
e4571a43
JB
6069\f
6070/* Mouse clicks and mouse movement. Rah. */
e4571a43 6071
06a2c219
GM
6072/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6073 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6074 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6075 not force the value into range. */
69388238 6076
c8dba240 6077void
69388238 6078pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6079 FRAME_PTR f;
69388238 6080 register int pix_x, pix_y;
e4571a43
JB
6081 register int *x, *y;
6082 XRectangle *bounds;
69388238 6083 int noclip;
e4571a43 6084{
06a2c219 6085 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6086 even for negative values. */
6087 if (pix_x < 0)
7556890b 6088 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6089 if (pix_y < 0)
7556890b 6090 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6091
e4571a43
JB
6092 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6093 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6094
6095 if (bounds)
6096 {
7556890b
RS
6097 bounds->width = FONT_WIDTH (f->output_data.x->font);
6098 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6099 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6100 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6101 }
6102
69388238
RS
6103 if (!noclip)
6104 {
6105 if (pix_x < 0)
6106 pix_x = 0;
3cbd2e0b
RS
6107 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6108 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6109
6110 if (pix_y < 0)
6111 pix_y = 0;
6112 else if (pix_y > f->height)
6113 pix_y = f->height;
6114 }
e4571a43
JB
6115
6116 *x = pix_x;
6117 *y = pix_y;
6118}
6119
06a2c219
GM
6120
6121/* Given HPOS/VPOS in the current matrix of W, return corresponding
6122 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6123 can't tell the positions because W's display is not up to date,
6124 return 0. */
6125
6126int
6127glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6128 struct window *w;
6129 int hpos, vpos;
6130 int *frame_x, *frame_y;
2b5c9e71 6131{
06a2c219
GM
6132 int success_p;
6133
6134 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6135 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6136
6137 if (display_completed)
6138 {
6139 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6140 struct glyph *glyph = row->glyphs[TEXT_AREA];
6141 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6142
6143 *frame_y = row->y;
6144 *frame_x = row->x;
6145 while (glyph < end)
6146 {
6147 *frame_x += glyph->pixel_width;
6148 ++glyph;
6149 }
6150
6151 success_p = 1;
6152 }
6153 else
6154 {
6155 *frame_y = *frame_x = 0;
6156 success_p = 0;
6157 }
6158
6159 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6160 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6161 return success_p;
2b5c9e71
RS
6162}
6163
06a2c219 6164
dc6f92b8
JB
6165/* Prepare a mouse-event in *RESULT for placement in the input queue.
6166
6167 If the event is a button press, then note that we have grabbed
f451eb13 6168 the mouse. */
dc6f92b8
JB
6169
6170static Lisp_Object
f451eb13 6171construct_mouse_click (result, event, f)
dc6f92b8
JB
6172 struct input_event *result;
6173 XButtonEvent *event;
f676886a 6174 struct frame *f;
dc6f92b8 6175{
f451eb13 6176 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6177 otherwise. */
f451eb13 6178 result->kind = mouse_click;
69388238 6179 result->code = event->button - Button1;
1113d9db 6180 result->timestamp = event->time;
334208b7
RS
6181 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6182 event->state)
f689eb05 6183 | (event->type == ButtonRelease
58769bee 6184 ? up_modifier
f689eb05 6185 : down_modifier));
dc6f92b8 6186
06a2c219
GM
6187 XSETINT (result->x, event->x);
6188 XSETINT (result->y, event->y);
6189 XSETFRAME (result->frame_or_window, f);
0f8aabe9 6190 result->arg = Qnil;
06a2c219 6191 return Qnil;
dc6f92b8 6192}
b849c413 6193
69388238 6194\f
90e65f07
JB
6195/* Function to report a mouse movement to the mainstream Emacs code.
6196 The input handler calls this.
6197
6198 We have received a mouse movement event, which is given in *event.
6199 If the mouse is over a different glyph than it was last time, tell
6200 the mainstream emacs code by setting mouse_moved. If not, ask for
6201 another motion event, so we can check again the next time it moves. */
b8009dd1 6202
06a2c219
GM
6203static XMotionEvent last_mouse_motion_event;
6204static Lisp_Object last_mouse_motion_frame;
6205
90e65f07 6206static void
12ba150f 6207note_mouse_movement (frame, event)
f676886a 6208 FRAME_PTR frame;
90e65f07 6209 XMotionEvent *event;
90e65f07 6210{
e5d77022 6211 last_mouse_movement_time = event->time;
06a2c219
GM
6212 last_mouse_motion_event = *event;
6213 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6214
27f338af
RS
6215 if (event->window != FRAME_X_WINDOW (frame))
6216 {
39d8bb4d 6217 frame->mouse_moved = 1;
27f338af 6218 last_mouse_scroll_bar = Qnil;
27f338af 6219 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6220 }
6221
90e65f07 6222 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6223 else if (event->x < last_mouse_glyph.x
6224 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6225 || event->y < last_mouse_glyph.y
6226 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6227 {
39d8bb4d 6228 frame->mouse_moved = 1;
ab648270 6229 last_mouse_scroll_bar = Qnil;
b8009dd1 6230 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6231 }
6232}
6233
bf1c0ba1 6234/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6235
06a2c219
GM
6236 int disable_mouse_highlight;
6237
6238
6239\f
6240/************************************************************************
6241 Mouse Face
6242 ************************************************************************/
6243
6244/* Find the glyph under window-relative coordinates X/Y in window W.
6245 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6246 strings. Return in *HPOS and *VPOS the row and column number of
6247 the glyph found. Return in *AREA the glyph area containing X.
6248 Value is a pointer to the glyph found or null if X/Y is not on
6249 text, or we can't tell because W's current matrix is not up to
6250 date. */
6251
6252static struct glyph *
6253x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6254 struct window *w;
6255 int x, y;
6256 int *hpos, *vpos, *area;
6257{
6258 struct glyph *glyph, *end;
3e71d8f2 6259 struct glyph_row *row = NULL;
06a2c219
GM
6260 int x0, i, left_area_width;
6261
6262 /* Find row containing Y. Give up if some row is not enabled. */
6263 for (i = 0; i < w->current_matrix->nrows; ++i)
6264 {
6265 row = MATRIX_ROW (w->current_matrix, i);
6266 if (!row->enabled_p)
6267 return NULL;
6268 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6269 break;
6270 }
6271
6272 *vpos = i;
6273 *hpos = 0;
6274
6275 /* Give up if Y is not in the window. */
6276 if (i == w->current_matrix->nrows)
6277 return NULL;
6278
6279 /* Get the glyph area containing X. */
6280 if (w->pseudo_window_p)
6281 {
6282 *area = TEXT_AREA;
6283 x0 = 0;
6284 }
6285 else
6286 {
6287 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6288 if (x < left_area_width)
6289 {
6290 *area = LEFT_MARGIN_AREA;
6291 x0 = 0;
6292 }
6293 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6294 {
6295 *area = TEXT_AREA;
6296 x0 = row->x + left_area_width;
6297 }
6298 else
6299 {
6300 *area = RIGHT_MARGIN_AREA;
6301 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6302 }
6303 }
6304
6305 /* Find glyph containing X. */
6306 glyph = row->glyphs[*area];
6307 end = glyph + row->used[*area];
6308 while (glyph < end)
6309 {
6310 if (x < x0 + glyph->pixel_width)
6311 {
6312 if (w->pseudo_window_p)
6313 break;
6314 else if (BUFFERP (glyph->object))
6315 break;
6316 }
6317
6318 x0 += glyph->pixel_width;
6319 ++glyph;
6320 }
6321
6322 if (glyph == end)
6323 return NULL;
6324
6325 *hpos = glyph - row->glyphs[*area];
6326 return glyph;
6327}
6328
6329
6330/* Convert frame-relative x/y to coordinates relative to window W.
6331 Takes pseudo-windows into account. */
6332
6333static void
6334frame_to_window_pixel_xy (w, x, y)
6335 struct window *w;
6336 int *x, *y;
6337{
6338 if (w->pseudo_window_p)
6339 {
6340 /* A pseudo-window is always full-width, and starts at the
6341 left edge of the frame, plus a frame border. */
6342 struct frame *f = XFRAME (w->frame);
6343 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6344 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6345 }
6346 else
6347 {
6348 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6349 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6350 }
6351}
6352
6353
6354/* Take proper action when mouse has moved to the mode or top line of
6355 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6356 mode line. X is relative to the start of the text display area of
6357 W, so the width of bitmap areas and scroll bars must be subtracted
6358 to get a position relative to the start of the mode line. */
6359
6360static void
6361note_mode_line_highlight (w, x, mode_line_p)
6362 struct window *w;
6363 int x, mode_line_p;
6364{
6365 struct frame *f = XFRAME (w->frame);
6366 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6367 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6368 struct glyph_row *row;
6369
6370 if (mode_line_p)
6371 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6372 else
045dee35 6373 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6374
6375 if (row->enabled_p)
6376 {
6377 struct glyph *glyph, *end;
6378 Lisp_Object help, map;
6379 int x0;
6380
6381 /* Find the glyph under X. */
6382 glyph = row->glyphs[TEXT_AREA];
6383 end = glyph + row->used[TEXT_AREA];
6384 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6385 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6386 while (glyph < end
6387 && x >= x0 + glyph->pixel_width)
6388 {
6389 x0 += glyph->pixel_width;
6390 ++glyph;
6391 }
6392
6393 if (glyph < end
6394 && STRINGP (glyph->object)
6395 && XSTRING (glyph->object)->intervals
6396 && glyph->charpos >= 0
6397 && glyph->charpos < XSTRING (glyph->object)->size)
6398 {
6399 /* If we're on a string with `help-echo' text property,
6400 arrange for the help to be displayed. This is done by
6401 setting the global variable help_echo to the help string. */
6402 help = Fget_text_property (make_number (glyph->charpos),
6403 Qhelp_echo, glyph->object);
b7e80413 6404 if (!NILP (help))
be010514
GM
6405 {
6406 help_echo = help;
7cea38bc 6407 XSETWINDOW (help_echo_window, w);
be010514
GM
6408 help_echo_object = glyph->object;
6409 help_echo_pos = glyph->charpos;
6410 }
06a2c219
GM
6411
6412 /* Change the mouse pointer according to what is under X/Y. */
6413 map = Fget_text_property (make_number (glyph->charpos),
6414 Qlocal_map, glyph->object);
6415 if (!NILP (Fkeymapp (map)))
6416 cursor = f->output_data.x->nontext_cursor;
be010514
GM
6417 else
6418 {
6419 map = Fget_text_property (make_number (glyph->charpos),
6420 Qkeymap, glyph->object);
6421 if (!NILP (Fkeymapp (map)))
6422 cursor = f->output_data.x->nontext_cursor;
6423 }
06a2c219
GM
6424 }
6425 }
6426
6427 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6428}
6429
6430
6431/* Take proper action when the mouse has moved to position X, Y on
6432 frame F as regards highlighting characters that have mouse-face
6433 properties. Also de-highlighting chars where the mouse was before.
27f338af 6434 X and Y can be negative or out of range. */
b8009dd1
RS
6435
6436static void
6437note_mouse_highlight (f, x, y)
06a2c219 6438 struct frame *f;
c32cdd9a 6439 int x, y;
b8009dd1 6440{
06a2c219
GM
6441 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6442 int portion;
b8009dd1
RS
6443 Lisp_Object window;
6444 struct window *w;
6445
06a2c219
GM
6446 /* When a menu is active, don't highlight because this looks odd. */
6447#ifdef USE_X_TOOLKIT
6448 if (popup_activated ())
6449 return;
6450#endif
6451
04fff9c0
GM
6452 if (disable_mouse_highlight
6453 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6454 return;
6455
06a2c219
GM
6456 dpyinfo->mouse_face_mouse_x = x;
6457 dpyinfo->mouse_face_mouse_y = y;
6458 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6459
06a2c219 6460 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6461 return;
6462
514e4681
RS
6463 if (gc_in_progress)
6464 {
06a2c219 6465 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6466 return;
6467 }
6468
b8009dd1 6469 /* Which window is that in? */
06a2c219 6470 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6471
6472 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6473 if (! EQ (window, dpyinfo->mouse_face_window))
6474 clear_mouse_face (dpyinfo);
6475
6476 /* Not on a window -> return. */
6477 if (!WINDOWP (window))
6478 return;
6479
6480 /* Convert to window-relative pixel coordinates. */
6481 w = XWINDOW (window);
6482 frame_to_window_pixel_xy (w, &x, &y);
6483
9ea173e8 6484 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6485 buffer. */
9ea173e8 6486 if (EQ (window, f->tool_bar_window))
06a2c219 6487 {
9ea173e8 6488 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6489 return;
6490 }
6491
6492 if (portion == 1 || portion == 3)
6493 {
6494 /* Mouse is on the mode or top line. */
6495 note_mode_line_highlight (w, x, portion == 1);
6496 return;
6497 }
6498 else
6499 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6500 f->output_data.x->text_cursor);
b8009dd1 6501
0cdd0c9f
RS
6502 /* Are we in a window whose display is up to date?
6503 And verify the buffer's text has not changed. */
06a2c219
GM
6504 if (/* Within text portion of the window. */
6505 portion == 0
0cdd0c9f 6506 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6507 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6508 && (XFASTINT (w->last_overlay_modified)
6509 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6510 {
06a2c219
GM
6511 int hpos, vpos, pos, i, area;
6512 struct glyph *glyph;
b8009dd1 6513
06a2c219
GM
6514 /* Find the glyph under X/Y. */
6515 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6516
6517 /* Clear mouse face if X/Y not over text. */
6518 if (glyph == NULL
6519 || area != TEXT_AREA
6520 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6521 {
06a2c219
GM
6522 clear_mouse_face (dpyinfo);
6523 return;
6524 }
6525
6526 pos = glyph->charpos;
6527 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6528
6529 /* Check for mouse-face and help-echo. */
6530 {
6531 Lisp_Object mouse_face, overlay, position;
6532 Lisp_Object *overlay_vec;
6533 int len, noverlays;
6534 struct buffer *obuf;
6535 int obegv, ozv;
6536
6537 /* If we get an out-of-range value, return now; avoid an error. */
6538 if (pos > BUF_Z (XBUFFER (w->buffer)))
6539 return;
6540
6541 /* Make the window's buffer temporarily current for
6542 overlays_at and compute_char_face. */
6543 obuf = current_buffer;
6544 current_buffer = XBUFFER (w->buffer);
6545 obegv = BEGV;
6546 ozv = ZV;
6547 BEGV = BEG;
6548 ZV = Z;
6549
6550 /* Is this char mouse-active or does it have help-echo? */
6551 XSETINT (position, pos);
6552
6553 /* Put all the overlays we want in a vector in overlay_vec.
6554 Store the length in len. If there are more than 10, make
6555 enough space for all, and try again. */
6556 len = 10;
6557 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6558 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
06a2c219
GM
6559 if (noverlays > len)
6560 {
6561 len = noverlays;
6562 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
bc592036 6563 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
06a2c219 6564 }
f8349001
GM
6565
6566 /* Sort overlays into increasing priority order. */
06a2c219
GM
6567 noverlays = sort_overlays (overlay_vec, noverlays, w);
6568
6569 /* Check mouse-face highlighting. */
6570 if (! (EQ (window, dpyinfo->mouse_face_window)
6571 && vpos >= dpyinfo->mouse_face_beg_row
6572 && vpos <= dpyinfo->mouse_face_end_row
6573 && (vpos > dpyinfo->mouse_face_beg_row
6574 || hpos >= dpyinfo->mouse_face_beg_col)
6575 && (vpos < dpyinfo->mouse_face_end_row
6576 || hpos < dpyinfo->mouse_face_end_col
6577 || dpyinfo->mouse_face_past_end)))
6578 {
6579 /* Clear the display of the old active region, if any. */
6580 clear_mouse_face (dpyinfo);
6581
6582 /* Find the highest priority overlay that has a mouse-face prop. */
6583 overlay = Qnil;
f8349001 6584 for (i = noverlays - 1; i >= 0; --i)
06a2c219
GM
6585 {
6586 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6587 if (!NILP (mouse_face))
6588 {
6589 overlay = overlay_vec[i];
6590 break;
6591 }
6592 }
6593
6594 /* If no overlay applies, get a text property. */
6595 if (NILP (overlay))
6596 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6597
6598 /* Handle the overlay case. */
6599 if (! NILP (overlay))
6600 {
6601 /* Find the range of text around this char that
6602 should be active. */
6603 Lisp_Object before, after;
6604 int ignore;
6605
6606 before = Foverlay_start (overlay);
6607 after = Foverlay_end (overlay);
6608 /* Record this as the current active region. */
6609 fast_find_position (w, XFASTINT (before),
6610 &dpyinfo->mouse_face_beg_col,
6611 &dpyinfo->mouse_face_beg_row,
6612 &dpyinfo->mouse_face_beg_x,
6613 &dpyinfo->mouse_face_beg_y);
6614 dpyinfo->mouse_face_past_end
6615 = !fast_find_position (w, XFASTINT (after),
6616 &dpyinfo->mouse_face_end_col,
6617 &dpyinfo->mouse_face_end_row,
6618 &dpyinfo->mouse_face_end_x,
6619 &dpyinfo->mouse_face_end_y);
6620 dpyinfo->mouse_face_window = window;
6621 dpyinfo->mouse_face_face_id
6622 = face_at_buffer_position (w, pos, 0, 0,
6623 &ignore, pos + 1, 1);
6624
6625 /* Display it as active. */
6626 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6627 }
6628 /* Handle the text property case. */
6629 else if (! NILP (mouse_face))
6630 {
6631 /* Find the range of text around this char that
6632 should be active. */
6633 Lisp_Object before, after, beginning, end;
6634 int ignore;
6635
6636 beginning = Fmarker_position (w->start);
6637 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6638 - XFASTINT (w->window_end_pos)));
6639 before
6640 = Fprevious_single_property_change (make_number (pos + 1),
6641 Qmouse_face,
6642 w->buffer, beginning);
6643 after
6644 = Fnext_single_property_change (position, Qmouse_face,
6645 w->buffer, end);
6646 /* Record this as the current active region. */
6647 fast_find_position (w, XFASTINT (before),
6648 &dpyinfo->mouse_face_beg_col,
6649 &dpyinfo->mouse_face_beg_row,
6650 &dpyinfo->mouse_face_beg_x,
6651 &dpyinfo->mouse_face_beg_y);
6652 dpyinfo->mouse_face_past_end
6653 = !fast_find_position (w, XFASTINT (after),
6654 &dpyinfo->mouse_face_end_col,
6655 &dpyinfo->mouse_face_end_row,
6656 &dpyinfo->mouse_face_end_x,
6657 &dpyinfo->mouse_face_end_y);
6658 dpyinfo->mouse_face_window = window;
6659 dpyinfo->mouse_face_face_id
6660 = face_at_buffer_position (w, pos, 0, 0,
6661 &ignore, pos + 1, 1);
6662
6663 /* Display it as active. */
6664 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6665 }
6666 }
6667
6668 /* Look for a `help-echo' property. */
6669 {
743934db 6670 Lisp_Object help, overlay;
06a2c219
GM
6671
6672 /* Check overlays first. */
6673 help = Qnil;
f8349001 6674 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
743934db
GM
6675 {
6676 overlay = overlay_vec[i];
6677 help = Foverlay_get (overlay, Qhelp_echo);
6678 }
be010514
GM
6679
6680 if (!NILP (help))
6681 {
6682 help_echo = help;
7cea38bc 6683 help_echo_window = window;
743934db 6684 help_echo_object = overlay;
be010514
GM
6685 help_echo_pos = pos;
6686 }
6687 else
6688 {
6689 /* Try text properties. */
6690 if ((STRINGP (glyph->object)
06a2c219
GM
6691 && glyph->charpos >= 0
6692 && glyph->charpos < XSTRING (glyph->object)->size)
6693 || (BUFFERP (glyph->object)
6694 && glyph->charpos >= BEGV
be010514
GM
6695 && glyph->charpos < ZV))
6696 help = Fget_text_property (make_number (glyph->charpos),
6697 Qhelp_echo, glyph->object);
06a2c219 6698
be010514
GM
6699 if (!NILP (help))
6700 {
6701 help_echo = help;
7cea38bc 6702 help_echo_window = window;
be010514
GM
6703 help_echo_object = glyph->object;
6704 help_echo_pos = glyph->charpos;
6705 }
6706 }
06a2c219
GM
6707 }
6708
6709 BEGV = obegv;
6710 ZV = ozv;
6711 current_buffer = obuf;
6712 }
6713 }
6714}
6715
6716static void
6717redo_mouse_highlight ()
6718{
6719 if (!NILP (last_mouse_motion_frame)
6720 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6721 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6722 last_mouse_motion_event.x,
6723 last_mouse_motion_event.y);
6724}
6725
6726
6727\f
6728/***********************************************************************
9ea173e8 6729 Tool-bars
06a2c219
GM
6730 ***********************************************************************/
6731
9ea173e8
GM
6732static int x_tool_bar_item P_ ((struct frame *, int, int,
6733 struct glyph **, int *, int *, int *));
06a2c219 6734
9ea173e8 6735/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6736 or -1. */
6737
9ea173e8 6738static int last_tool_bar_item;
06a2c219
GM
6739
6740
9ea173e8
GM
6741/* Get information about the tool-bar item at position X/Y on frame F.
6742 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6743 the current matrix of the tool-bar window of F, or NULL if not
6744 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6745 item in F->current_tool_bar_items. Value is
06a2c219 6746
9ea173e8 6747 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6748 0 if X/Y is on the same item that was highlighted before.
6749 1 otherwise. */
6750
6751static int
9ea173e8 6752x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6753 struct frame *f;
6754 int x, y;
6755 struct glyph **glyph;
6756 int *hpos, *vpos, *prop_idx;
6757{
6758 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6759 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6760 int area;
6761
6762 /* Find the glyph under X/Y. */
6763 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6764 if (*glyph == NULL)
6765 return -1;
6766
9ea173e8
GM
6767 /* Get the start of this tool-bar item's properties in
6768 f->current_tool_bar_items. */
6769 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6770 return -1;
6771
6772 /* Is mouse on the highlighted item? */
9ea173e8 6773 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6774 && *vpos >= dpyinfo->mouse_face_beg_row
6775 && *vpos <= dpyinfo->mouse_face_end_row
6776 && (*vpos > dpyinfo->mouse_face_beg_row
6777 || *hpos >= dpyinfo->mouse_face_beg_col)
6778 && (*vpos < dpyinfo->mouse_face_end_row
6779 || *hpos < dpyinfo->mouse_face_end_col
6780 || dpyinfo->mouse_face_past_end))
6781 return 0;
6782
6783 return 1;
6784}
6785
6786
9ea173e8 6787/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6788 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6789 or ButtonRelase. */
6790
6791static void
9ea173e8 6792x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6793 struct frame *f;
6794 XButtonEvent *button_event;
6795{
6796 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6797 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6798 int hpos, vpos, prop_idx;
6799 struct glyph *glyph;
6800 Lisp_Object enabled_p;
6801 int x = button_event->x;
6802 int y = button_event->y;
6803
9ea173e8 6804 /* If not on the highlighted tool-bar item, return. */
06a2c219 6805 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6806 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6807 return;
6808
6809 /* If item is disabled, do nothing. */
9ea173e8
GM
6810 enabled_p = (XVECTOR (f->current_tool_bar_items)
6811 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6812 if (NILP (enabled_p))
6813 return;
6814
6815 if (button_event->type == ButtonPress)
6816 {
6817 /* Show item in pressed state. */
6818 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6819 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6820 last_tool_bar_item = prop_idx;
06a2c219
GM
6821 }
6822 else
6823 {
6824 Lisp_Object key, frame;
6825 struct input_event event;
6826
6827 /* Show item in released state. */
6828 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6829 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6830
9ea173e8
GM
6831 key = (XVECTOR (f->current_tool_bar_items)
6832 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
6833
6834 XSETFRAME (frame, f);
9ea173e8 6835 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
6836 event.frame_or_window = frame;
6837 event.arg = frame;
06a2c219
GM
6838 kbd_buffer_store_event (&event);
6839
9ea173e8 6840 event.kind = TOOL_BAR_EVENT;
0f1a9b23
GM
6841 event.frame_or_window = frame;
6842 event.arg = key;
06a2c219
GM
6843 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6844 button_event->state);
6845 kbd_buffer_store_event (&event);
9ea173e8 6846 last_tool_bar_item = -1;
06a2c219
GM
6847 }
6848}
6849
6850
9ea173e8
GM
6851/* Possibly highlight a tool-bar item on frame F when mouse moves to
6852 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6853 note_mouse_highlight. */
6854
6855static void
9ea173e8 6856note_tool_bar_highlight (f, x, y)
06a2c219
GM
6857 struct frame *f;
6858 int x, y;
6859{
9ea173e8 6860 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
6861 struct window *w = XWINDOW (window);
6862 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6863 int hpos, vpos;
6864 struct glyph *glyph;
6865 struct glyph_row *row;
5c187dee 6866 int i;
06a2c219
GM
6867 Lisp_Object enabled_p;
6868 int prop_idx;
6869 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 6870 int mouse_down_p, rc;
06a2c219
GM
6871
6872 /* Function note_mouse_highlight is called with negative x(y
6873 values when mouse moves outside of the frame. */
6874 if (x <= 0 || y <= 0)
6875 {
6876 clear_mouse_face (dpyinfo);
6877 return;
6878 }
6879
9ea173e8 6880 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
6881 if (rc < 0)
6882 {
9ea173e8 6883 /* Not on tool-bar item. */
06a2c219
GM
6884 clear_mouse_face (dpyinfo);
6885 return;
6886 }
6887 else if (rc == 0)
9ea173e8 6888 /* On same tool-bar item as before. */
06a2c219 6889 goto set_help_echo;
b8009dd1 6890
06a2c219
GM
6891 clear_mouse_face (dpyinfo);
6892
9ea173e8 6893 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
6894 mouse_down_p = (dpyinfo->grabbed
6895 && f == last_mouse_frame
6896 && FRAME_LIVE_P (f));
6897 if (mouse_down_p
9ea173e8 6898 && last_tool_bar_item != prop_idx)
06a2c219
GM
6899 return;
6900
6901 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6902 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6903
9ea173e8
GM
6904 /* If tool-bar item is not enabled, don't highlight it. */
6905 enabled_p = (XVECTOR (f->current_tool_bar_items)
6906 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6907 if (!NILP (enabled_p))
6908 {
6909 /* Compute the x-position of the glyph. In front and past the
6910 image is a space. We include this is the highlighted area. */
6911 row = MATRIX_ROW (w->current_matrix, vpos);
6912 for (i = x = 0; i < hpos; ++i)
6913 x += row->glyphs[TEXT_AREA][i].pixel_width;
6914
6915 /* Record this as the current active region. */
6916 dpyinfo->mouse_face_beg_col = hpos;
6917 dpyinfo->mouse_face_beg_row = vpos;
6918 dpyinfo->mouse_face_beg_x = x;
6919 dpyinfo->mouse_face_beg_y = row->y;
6920 dpyinfo->mouse_face_past_end = 0;
6921
6922 dpyinfo->mouse_face_end_col = hpos + 1;
6923 dpyinfo->mouse_face_end_row = vpos;
6924 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6925 dpyinfo->mouse_face_end_y = row->y;
6926 dpyinfo->mouse_face_window = window;
9ea173e8 6927 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
6928
6929 /* Display it as active. */
6930 show_mouse_face (dpyinfo, draw);
6931 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6932 }
06a2c219
GM
6933
6934 set_help_echo:
6935
9ea173e8 6936 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 6937 XTread_socket does the rest. */
7cea38bc 6938 help_echo_object = help_echo_window = Qnil;
be010514 6939 help_echo_pos = -1;
9ea173e8
GM
6940 help_echo = (XVECTOR (f->current_tool_bar_items)
6941 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
b7e80413 6942 if (NILP (help_echo))
9ea173e8
GM
6943 help_echo = (XVECTOR (f->current_tool_bar_items)
6944 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 6945}
4d73d038 6946
06a2c219
GM
6947
6948\f
6949/* Find the glyph matrix position of buffer position POS in window W.
6950 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6951 current glyphs must be up to date. If POS is above window start
6952 return (0, 0, 0, 0). If POS is after end of W, return end of
6953 last line in W. */
b8009dd1
RS
6954
6955static int
06a2c219
GM
6956fast_find_position (w, pos, hpos, vpos, x, y)
6957 struct window *w;
b8009dd1 6958 int pos;
06a2c219 6959 int *hpos, *vpos, *x, *y;
b8009dd1 6960{
b8009dd1 6961 int i;
bf1c0ba1 6962 int lastcol;
06a2c219
GM
6963 int maybe_next_line_p = 0;
6964 int line_start_position;
6965 int yb = window_text_bottom_y (w);
6966 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6967 struct glyph_row *best_row = row;
6968 int row_vpos = 0, best_row_vpos = 0;
6969 int current_x;
6970
6971 while (row->y < yb)
b8009dd1 6972 {
06a2c219
GM
6973 if (row->used[TEXT_AREA])
6974 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6975 else
6976 line_start_position = 0;
6977
6978 if (line_start_position > pos)
b8009dd1 6979 break;
77b68646
RS
6980 /* If the position sought is the end of the buffer,
6981 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6982 else if (line_start_position == pos
6983 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6984 {
06a2c219 6985 maybe_next_line_p = 1;
77b68646
RS
6986 break;
6987 }
06a2c219
GM
6988 else if (line_start_position > 0)
6989 {
6990 best_row = row;
6991 best_row_vpos = row_vpos;
6992 }
4b0bb6f3
GM
6993
6994 if (row->y + row->height >= yb)
6995 break;
06a2c219
GM
6996
6997 ++row;
6998 ++row_vpos;
b8009dd1 6999 }
06a2c219
GM
7000
7001 /* Find the right column within BEST_ROW. */
7002 lastcol = 0;
7003 current_x = best_row->x;
7004 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 7005 {
06a2c219
GM
7006 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7007 int charpos;
7008
7009 charpos = glyph->charpos;
7010 if (charpos == pos)
bf1c0ba1 7011 {
06a2c219
GM
7012 *hpos = i;
7013 *vpos = best_row_vpos;
7014 *x = current_x;
7015 *y = best_row->y;
bf1c0ba1
RS
7016 return 1;
7017 }
06a2c219 7018 else if (charpos > pos)
4d73d038 7019 break;
06a2c219
GM
7020 else if (charpos > 0)
7021 lastcol = i;
7022
7023 current_x += glyph->pixel_width;
bf1c0ba1 7024 }
b8009dd1 7025
77b68646
RS
7026 /* If we're looking for the end of the buffer,
7027 and we didn't find it in the line we scanned,
7028 use the start of the following line. */
06a2c219 7029 if (maybe_next_line_p)
77b68646 7030 {
06a2c219
GM
7031 ++best_row;
7032 ++best_row_vpos;
7033 lastcol = 0;
7034 current_x = best_row->x;
77b68646
RS
7035 }
7036
06a2c219
GM
7037 *vpos = best_row_vpos;
7038 *hpos = lastcol + 1;
7039 *x = current_x;
7040 *y = best_row->y;
b8009dd1
RS
7041 return 0;
7042}
7043
06a2c219 7044
b8009dd1
RS
7045/* Display the active region described by mouse_face_*
7046 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7047
7048static void
06a2c219 7049show_mouse_face (dpyinfo, draw)
7a13e894 7050 struct x_display_info *dpyinfo;
06a2c219 7051 enum draw_glyphs_face draw;
b8009dd1 7052{
7a13e894 7053 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 7054 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 7055 int i;
06a2c219
GM
7056 int cursor_off_p = 0;
7057 struct cursor_pos saved_cursor;
7058
7059 saved_cursor = output_cursor;
7060
7061 /* If window is in the process of being destroyed, don't bother
7062 to do anything. */
7063 if (w->current_matrix == NULL)
7064 goto set_x_cursor;
7065
7066 /* Recognize when we are called to operate on rows that don't exist
7067 anymore. This can happen when a window is split. */
7068 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7069 goto set_x_cursor;
7070
7071 set_output_cursor (&w->phys_cursor);
7072
7073 /* Note that mouse_face_beg_row etc. are window relative. */
7074 for (i = dpyinfo->mouse_face_beg_row;
7075 i <= dpyinfo->mouse_face_end_row;
7076 i++)
7077 {
7078 int start_hpos, end_hpos, start_x;
7079 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7080
7081 /* Don't do anything if row doesn't have valid contents. */
7082 if (!row->enabled_p)
7083 continue;
7084
7085 /* For all but the first row, the highlight starts at column 0. */
7086 if (i == dpyinfo->mouse_face_beg_row)
7087 {
7088 start_hpos = dpyinfo->mouse_face_beg_col;
7089 start_x = dpyinfo->mouse_face_beg_x;
7090 }
7091 else
7092 {
7093 start_hpos = 0;
7094 start_x = 0;
7095 }
7096
7097 if (i == dpyinfo->mouse_face_end_row)
7098 end_hpos = dpyinfo->mouse_face_end_col;
7099 else
7100 end_hpos = row->used[TEXT_AREA];
7101
7102 /* If the cursor's in the text we are about to rewrite, turn the
7103 cursor off. */
7104 if (!w->pseudo_window_p
7105 && i == output_cursor.vpos
7106 && output_cursor.hpos >= start_hpos - 1
7107 && output_cursor.hpos <= end_hpos)
514e4681 7108 {
06a2c219
GM
7109 x_update_window_cursor (w, 0);
7110 cursor_off_p = 1;
514e4681 7111 }
b8009dd1 7112
06a2c219 7113 if (end_hpos > start_hpos)
64f26cf5
GM
7114 {
7115 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7116 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7117 start_hpos, end_hpos, draw, NULL, NULL, 0);
7118 }
b8009dd1
RS
7119 }
7120
514e4681 7121 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7122 if (cursor_off_p)
7123 x_display_cursor (w, 1,
7124 output_cursor.hpos, output_cursor.vpos,
7125 output_cursor.x, output_cursor.y);
2729a2b5 7126
06a2c219 7127 output_cursor = saved_cursor;
fb3b7de5 7128
06a2c219
GM
7129 set_x_cursor:
7130
7131 /* Change the mouse cursor. */
7132 if (draw == DRAW_NORMAL_TEXT)
7133 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7134 f->output_data.x->text_cursor);
7135 else if (draw == DRAW_MOUSE_FACE)
334208b7 7136 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7137 f->output_data.x->cross_cursor);
27ead1d5 7138 else
334208b7 7139 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7140 f->output_data.x->nontext_cursor);
b8009dd1
RS
7141}
7142
7143/* Clear out the mouse-highlighted active region.
06a2c219 7144 Redraw it un-highlighted first. */
b8009dd1 7145
06a2c219 7146void
7a13e894
RS
7147clear_mouse_face (dpyinfo)
7148 struct x_display_info *dpyinfo;
b8009dd1 7149{
06a2c219
GM
7150 if (tip_frame)
7151 return;
7152
7a13e894 7153 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7154 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7155
7a13e894
RS
7156 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7157 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7158 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7159}
e687d06e 7160
71b8321e
GM
7161
7162/* Clear any mouse-face on window W. This function is part of the
7163 redisplay interface, and is called from try_window_id and similar
7164 functions to ensure the mouse-highlight is off. */
7165
7166static void
7167x_clear_mouse_face (w)
7168 struct window *w;
7169{
7170 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7171 Lisp_Object window;
7172
7173 XSETWINDOW (window, w);
7174 if (EQ (window, dpyinfo->mouse_face_window))
7175 clear_mouse_face (dpyinfo);
7176}
7177
7178
e687d06e
RS
7179/* Just discard the mouse face information for frame F, if any.
7180 This is used when the size of F is changed. */
7181
dfcf069d 7182void
e687d06e
RS
7183cancel_mouse_face (f)
7184 FRAME_PTR f;
7185{
7186 Lisp_Object window;
7187 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7188
7189 window = dpyinfo->mouse_face_window;
7190 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7191 {
7192 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7193 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7194 dpyinfo->mouse_face_window = Qnil;
7195 }
7196}
b8009dd1 7197\f
ab648270
JB
7198static struct scroll_bar *x_window_to_scroll_bar ();
7199static void x_scroll_bar_report_motion ();
12ba150f 7200
90e65f07 7201/* Return the current position of the mouse.
2d7fc7e8 7202 *fp should be a frame which indicates which display to ask about.
90e65f07 7203
2d7fc7e8 7204 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7205 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7206 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7207 position on the scroll bar.
12ba150f 7208
2d7fc7e8 7209 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7210 mouse is on, *bar_window to nil, and *x and *y to the character cell
7211 the mouse is over.
7212
06a2c219 7213 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7214 was at this position.
7215
a135645a
RS
7216 Don't store anything if we don't have a valid set of values to report.
7217
90e65f07 7218 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7219 movement. */
90e65f07
JB
7220
7221static void
1cf412ec 7222XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7223 FRAME_PTR *fp;
1cf412ec 7224 int insist;
12ba150f 7225 Lisp_Object *bar_window;
ab648270 7226 enum scroll_bar_part *part;
90e65f07 7227 Lisp_Object *x, *y;
e5d77022 7228 unsigned long *time;
90e65f07 7229{
a135645a
RS
7230 FRAME_PTR f1;
7231
90e65f07
JB
7232 BLOCK_INPUT;
7233
8bcee03e 7234 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7235 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7236 else
7237 {
12ba150f
JB
7238 Window root;
7239 int root_x, root_y;
90e65f07 7240
12ba150f
JB
7241 Window dummy_window;
7242 int dummy;
7243
39d8bb4d
KH
7244 Lisp_Object frame, tail;
7245
7246 /* Clear the mouse-moved flag for every frame on this display. */
7247 FOR_EACH_FRAME (tail, frame)
7248 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7249 XFRAME (frame)->mouse_moved = 0;
7250
ab648270 7251 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7252
7253 /* Figure out which root window we're on. */
334208b7
RS
7254 XQueryPointer (FRAME_X_DISPLAY (*fp),
7255 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7256
7257 /* The root window which contains the pointer. */
7258 &root,
7259
7260 /* Trash which we can't trust if the pointer is on
7261 a different screen. */
7262 &dummy_window,
7263
7264 /* The position on that root window. */
58769bee 7265 &root_x, &root_y,
12ba150f
JB
7266
7267 /* More trash we can't trust. */
7268 &dummy, &dummy,
7269
7270 /* Modifier keys and pointer buttons, about which
7271 we don't care. */
7272 (unsigned int *) &dummy);
7273
7274 /* Now we have a position on the root; find the innermost window
7275 containing the pointer. */
7276 {
7277 Window win, child;
7278 int win_x, win_y;
06a2c219 7279 int parent_x = 0, parent_y = 0;
e99db5a1 7280 int count;
12ba150f
JB
7281
7282 win = root;
69388238 7283
2d7fc7e8
RS
7284 /* XTranslateCoordinates can get errors if the window
7285 structure is changing at the same time this function
7286 is running. So at least we must not crash from them. */
7287
e99db5a1 7288 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7289
334208b7 7290 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7291 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7292 {
69388238
RS
7293 /* If mouse was grabbed on a frame, give coords for that frame
7294 even if the mouse is now outside it. */
334208b7 7295 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7296
12ba150f 7297 /* From-window, to-window. */
69388238 7298 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7299
7300 /* From-position, to-position. */
7301 root_x, root_y, &win_x, &win_y,
7302
7303 /* Child of win. */
7304 &child);
69388238
RS
7305 f1 = last_mouse_frame;
7306 }
7307 else
7308 {
7309 while (1)
7310 {
334208b7 7311 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7312
69388238
RS
7313 /* From-window, to-window. */
7314 root, win,
12ba150f 7315
69388238
RS
7316 /* From-position, to-position. */
7317 root_x, root_y, &win_x, &win_y,
7318
7319 /* Child of win. */
7320 &child);
7321
9af3143a 7322 if (child == None || child == win)
69388238
RS
7323 break;
7324
7325 win = child;
7326 parent_x = win_x;
7327 parent_y = win_y;
7328 }
12ba150f 7329
69388238
RS
7330 /* Now we know that:
7331 win is the innermost window containing the pointer
7332 (XTC says it has no child containing the pointer),
7333 win_x and win_y are the pointer's position in it
7334 (XTC did this the last time through), and
7335 parent_x and parent_y are the pointer's position in win's parent.
7336 (They are what win_x and win_y were when win was child.
7337 If win is the root window, it has no parent, and
7338 parent_{x,y} are invalid, but that's okay, because we'll
7339 never use them in that case.) */
7340
7341 /* Is win one of our frames? */
19126e11 7342 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7343 }
58769bee 7344
2d7fc7e8
RS
7345 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7346 f1 = 0;
7347
e99db5a1 7348 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7349
ab648270 7350 /* If not, is it one of our scroll bars? */
a135645a 7351 if (! f1)
12ba150f 7352 {
ab648270 7353 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7354
7355 if (bar)
7356 {
a135645a 7357 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7358 win_x = parent_x;
7359 win_y = parent_y;
7360 }
7361 }
90e65f07 7362
8bcee03e 7363 if (f1 == 0 && insist > 0)
b86bd3dd 7364 f1 = SELECTED_FRAME ();
1cf412ec 7365
a135645a 7366 if (f1)
12ba150f 7367 {
06a2c219
GM
7368 /* Ok, we found a frame. Store all the values.
7369 last_mouse_glyph is a rectangle used to reduce the
7370 generation of mouse events. To not miss any motion
7371 events, we must divide the frame into rectangles of the
7372 size of the smallest character that could be displayed
7373 on it, i.e. into the same rectangles that matrices on
7374 the frame are divided into. */
7375
7376#if OLD_REDISPLAY_CODE
2b5c9e71 7377 int ignore1, ignore2;
2b5c9e71 7378 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7379 &last_mouse_glyph,
1cf412ec
RS
7380 FRAME_X_DISPLAY_INFO (f1)->grabbed
7381 || insist);
06a2c219
GM
7382#else
7383 {
7384 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7385 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7386 int x = win_x;
7387 int y = win_y;
7388
7389 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7390 round down even for negative values. */
7391 if (x < 0)
7392 x -= width - 1;
7393 if (y < 0)
7394 y -= height - 1;
7395
7396 last_mouse_glyph.width = width;
7397 last_mouse_glyph.height = height;
7398 last_mouse_glyph.x = (x + width - 1) / width * width;
7399 last_mouse_glyph.y = (y + height - 1) / height * height;
7400 }
7401#endif
12ba150f
JB
7402
7403 *bar_window = Qnil;
7404 *part = 0;
334208b7 7405 *fp = f1;
e0c1aef2
KH
7406 XSETINT (*x, win_x);
7407 XSETINT (*y, win_y);
12ba150f
JB
7408 *time = last_mouse_movement_time;
7409 }
7410 }
7411 }
90e65f07
JB
7412
7413 UNBLOCK_INPUT;
7414}
f451eb13 7415
06a2c219 7416
06a2c219 7417#ifdef USE_X_TOOLKIT
bffcfca9
GM
7418
7419/* Atimer callback function for TIMER. Called every 0.1s to process
7420 Xt timeouts, if needed. We must avoid calling XtAppPending as
7421 much as possible because that function does an implicit XFlush
7422 that slows us down. */
7423
7424static void
7425x_process_timeouts (timer)
7426 struct atimer *timer;
7427{
7428 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7429 {
7430 BLOCK_INPUT;
7431 while (XtAppPending (Xt_app_con) & XtIMTimer)
7432 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7433 UNBLOCK_INPUT;
7434 }
06a2c219
GM
7435}
7436
bffcfca9 7437#endif /* USE_X_TOOLKIT */
06a2c219
GM
7438
7439\f
7440/* Scroll bar support. */
7441
7442/* Given an X window ID, find the struct scroll_bar which manages it.
7443 This can be called in GC, so we have to make sure to strip off mark
7444 bits. */
bffcfca9 7445
06a2c219
GM
7446static struct scroll_bar *
7447x_window_to_scroll_bar (window_id)
7448 Window window_id;
7449{
7450 Lisp_Object tail;
7451
7452 for (tail = Vframe_list;
7453 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7454 tail = XCDR (tail))
06a2c219
GM
7455 {
7456 Lisp_Object frame, bar, condemned;
7457
8e713be6 7458 frame = XCAR (tail);
06a2c219
GM
7459 /* All elements of Vframe_list should be frames. */
7460 if (! GC_FRAMEP (frame))
7461 abort ();
7462
7463 /* Scan this frame's scroll bar list for a scroll bar with the
7464 right window ID. */
7465 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7466 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7467 /* This trick allows us to search both the ordinary and
7468 condemned scroll bar lists with one loop. */
7469 ! GC_NILP (bar) || (bar = condemned,
7470 condemned = Qnil,
7471 ! GC_NILP (bar));
7472 bar = XSCROLL_BAR (bar)->next)
7473 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7474 return XSCROLL_BAR (bar);
7475 }
7476
7477 return 0;
7478}
7479
7480
7481\f
7482/************************************************************************
7483 Toolkit scroll bars
7484 ************************************************************************/
7485
7486#if USE_TOOLKIT_SCROLL_BARS
7487
7488static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7489static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7490static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7491 struct scroll_bar *));
7492static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7493 int, int, int));
7494
7495
7496/* Id of action hook installed for scroll bars. */
7497
7498static XtActionHookId action_hook_id;
7499
7500/* Lisp window being scrolled. Set when starting to interact with
7501 a toolkit scroll bar, reset to nil when ending the interaction. */
7502
7503static Lisp_Object window_being_scrolled;
7504
7505/* Last scroll bar part sent in xm_scroll_callback. */
7506
7507static int last_scroll_bar_part;
7508
ec18280f
SM
7509/* Whether this is an Xaw with arrow-scrollbars. This should imply
7510 that movements of 1/20 of the screen size are mapped to up/down. */
7511
7512static Boolean xaw3d_arrow_scroll;
7513
7514/* Whether the drag scrolling maintains the mouse at the top of the
7515 thumb. If not, resizing the thumb needs to be done more carefully
7516 to avoid jerkyness. */
7517
7518static Boolean xaw3d_pick_top;
7519
06a2c219
GM
7520
7521/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7522 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7523 the user ends an interaction with the scroll bar, and generates
7524 a `end-scroll' scroll_bar_click' event if so. */
7525
7526static void
7527xt_action_hook (widget, client_data, action_name, event, params,
7528 num_params)
7529 Widget widget;
7530 XtPointer client_data;
7531 String action_name;
7532 XEvent *event;
7533 String *params;
7534 Cardinal *num_params;
7535{
7536 int scroll_bar_p;
7537 char *end_action;
7538
7539#ifdef USE_MOTIF
7540 scroll_bar_p = XmIsScrollBar (widget);
7541 end_action = "Release";
ec18280f 7542#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7543 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7544 end_action = "EndScroll";
ec18280f 7545#endif /* USE_MOTIF */
06a2c219 7546
06a2c219
GM
7547 if (scroll_bar_p
7548 && strcmp (action_name, end_action) == 0
7549 && WINDOWP (window_being_scrolled))
7550 {
7551 struct window *w;
7552
7553 x_send_scroll_bar_event (window_being_scrolled,
7554 scroll_bar_end_scroll, 0, 0);
7555 w = XWINDOW (window_being_scrolled);
7556 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7557 window_being_scrolled = Qnil;
7558 last_scroll_bar_part = -1;
bffcfca9
GM
7559
7560 /* Xt timeouts no longer needed. */
7561 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7562 }
7563}
7564
7565
7566/* Send a client message with message type Xatom_Scrollbar for a
7567 scroll action to the frame of WINDOW. PART is a value identifying
7568 the part of the scroll bar that was clicked on. PORTION is the
7569 amount to scroll of a whole of WHOLE. */
7570
7571static void
7572x_send_scroll_bar_event (window, part, portion, whole)
7573 Lisp_Object window;
7574 int part, portion, whole;
7575{
7576 XEvent event;
7577 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7578 struct frame *f = XFRAME (XWINDOW (window)->frame);
7579
7580 /* Construct a ClientMessage event to send to the frame. */
7581 ev->type = ClientMessage;
7582 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7583 ev->display = FRAME_X_DISPLAY (f);
7584 ev->window = FRAME_X_WINDOW (f);
7585 ev->format = 32;
52e386c2 7586 ev->data.l[0] = (long) XFASTINT (window);
06a2c219
GM
7587 ev->data.l[1] = (long) part;
7588 ev->data.l[2] = (long) 0;
7589 ev->data.l[3] = (long) portion;
7590 ev->data.l[4] = (long) whole;
7591
bffcfca9
GM
7592 /* Make Xt timeouts work while the scroll bar is active. */
7593 toolkit_scroll_bar_interaction = 1;
7594
06a2c219
GM
7595 /* Setting the event mask to zero means that the message will
7596 be sent to the client that created the window, and if that
7597 window no longer exists, no event will be sent. */
7598 BLOCK_INPUT;
7599 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7600 UNBLOCK_INPUT;
7601}
7602
7603
7604/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7605 in *IEVENT. */
7606
7607static void
7608x_scroll_bar_to_input_event (event, ievent)
7609 XEvent *event;
7610 struct input_event *ievent;
7611{
7612 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7613 Lisp_Object window;
7614 struct frame *f;
7615
7616 XSETFASTINT (window, ev->data.l[0]);
7617 f = XFRAME (XWINDOW (window)->frame);
06a2c219
GM
7618
7619 ievent->kind = scroll_bar_click;
7620 ievent->frame_or_window = window;
0f8aabe9 7621 ievent->arg = Qnil;
06a2c219
GM
7622 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7623 ievent->part = ev->data.l[1];
7624 ievent->code = ev->data.l[2];
7625 ievent->x = make_number ((int) ev->data.l[3]);
7626 ievent->y = make_number ((int) ev->data.l[4]);
7627 ievent->modifiers = 0;
7628}
7629
7630
7631#ifdef USE_MOTIF
7632
7633/* Minimum and maximum values used for Motif scroll bars. */
7634
7635#define XM_SB_MIN 1
7636#define XM_SB_MAX 10000000
7637#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7638
7639
7640/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7641 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7642 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7643
7644static void
7645xm_scroll_callback (widget, client_data, call_data)
7646 Widget widget;
7647 XtPointer client_data, call_data;
7648{
7649 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7650 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7651 double percent;
7652 int part = -1, whole = 0, portion = 0;
7653
7654 switch (cs->reason)
7655 {
7656 case XmCR_DECREMENT:
7657 bar->dragging = Qnil;
7658 part = scroll_bar_up_arrow;
7659 break;
7660
7661 case XmCR_INCREMENT:
7662 bar->dragging = Qnil;
7663 part = scroll_bar_down_arrow;
7664 break;
7665
7666 case XmCR_PAGE_DECREMENT:
7667 bar->dragging = Qnil;
7668 part = scroll_bar_above_handle;
7669 break;
7670
7671 case XmCR_PAGE_INCREMENT:
7672 bar->dragging = Qnil;
7673 part = scroll_bar_below_handle;
7674 break;
7675
7676 case XmCR_TO_TOP:
7677 bar->dragging = Qnil;
7678 part = scroll_bar_to_top;
7679 break;
7680
7681 case XmCR_TO_BOTTOM:
7682 bar->dragging = Qnil;
7683 part = scroll_bar_to_bottom;
7684 break;
7685
7686 case XmCR_DRAG:
7687 {
7688 int slider_size;
7689 int dragging_down_p = (INTEGERP (bar->dragging)
7690 && XINT (bar->dragging) <= cs->value);
7691
7692 /* Get the slider size. */
7693 BLOCK_INPUT;
7694 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7695 UNBLOCK_INPUT;
7696
7697 /* At the max position of the scroll bar, do a line-wise
7698 movement. Without doing anything, the LessTif scroll bar
7699 calls us with the same cs->value again and again. If we
7700 want to make sure that we can reach the end of the buffer,
7701 we have to do something.
7702
7703 Implementation note: setting bar->dragging always to
7704 cs->value gives a smoother movement at the max position.
7705 Setting it to nil when doing line-wise movement gives
7706 a better slider behavior. */
7707
7708 if (cs->value + slider_size == XM_SB_MAX
7709 || (dragging_down_p
7710 && last_scroll_bar_part == scroll_bar_down_arrow))
7711 {
7712 part = scroll_bar_down_arrow;
7713 bar->dragging = Qnil;
7714 }
7715 else
7716 {
7717 whole = XM_SB_RANGE;
7718 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7719 part = scroll_bar_handle;
7720 bar->dragging = make_number (cs->value);
7721 }
7722 }
7723 break;
7724
7725 case XmCR_VALUE_CHANGED:
7726 break;
7727 };
7728
7729 if (part >= 0)
7730 {
7731 window_being_scrolled = bar->window;
7732 last_scroll_bar_part = part;
7733 x_send_scroll_bar_event (bar->window, part, portion, whole);
7734 }
7735}
7736
7737
ec18280f 7738#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7739
7740
ec18280f 7741/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7742 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7743 scroll bar struct. CALL_DATA is a pointer to a float saying where
7744 the thumb is. */
7745
7746static void
ec18280f 7747xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7748 Widget widget;
7749 XtPointer client_data, call_data;
7750{
7751 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7752 float top = *(float *) call_data;
7753 float shown;
ec18280f
SM
7754 int whole, portion, height;
7755 int part;
06a2c219
GM
7756
7757 /* Get the size of the thumb, a value between 0 and 1. */
7758 BLOCK_INPUT;
ec18280f 7759 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7760 UNBLOCK_INPUT;
7761
7762 whole = 10000000;
7763 portion = shown < 1 ? top * whole : 0;
06a2c219 7764
ec18280f
SM
7765 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7766 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7767 the bottom, so we force the scrolling whenever we see that we're
7768 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7769 we try to ensure that we always stay two pixels away from the
7770 bottom). */
06a2c219
GM
7771 part = scroll_bar_down_arrow;
7772 else
7773 part = scroll_bar_handle;
7774
7775 window_being_scrolled = bar->window;
7776 bar->dragging = make_number (portion);
7777 last_scroll_bar_part = part;
7778 x_send_scroll_bar_event (bar->window, part, portion, whole);
7779}
7780
7781
ec18280f
SM
7782/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7783 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7784 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7785 the scroll bar. CALL_DATA is an integer specifying the action that
7786 has taken place. It's magnitude is in the range 0..height of the
7787 scroll bar. Negative values mean scroll towards buffer start.
7788 Values < height of scroll bar mean line-wise movement. */
7789
7790static void
ec18280f 7791xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7792 Widget widget;
7793 XtPointer client_data, call_data;
7794{
7795 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7796 int position = (int) call_data;
7797 Dimension height;
7798 int part;
7799
7800 /* Get the height of the scroll bar. */
7801 BLOCK_INPUT;
7802 XtVaGetValues (widget, XtNheight, &height, NULL);
7803 UNBLOCK_INPUT;
7804
ec18280f
SM
7805 if (abs (position) >= height)
7806 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7807
7808 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7809 it maps line-movement to call_data = max(5, height/20). */
7810 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7811 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7812 else
ec18280f 7813 part = scroll_bar_move_ratio;
06a2c219
GM
7814
7815 window_being_scrolled = bar->window;
7816 bar->dragging = Qnil;
7817 last_scroll_bar_part = part;
ec18280f 7818 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7819}
7820
7821
7822#endif /* not USE_MOTIF */
7823
7824
7825/* Create the widget for scroll bar BAR on frame F. Record the widget
7826 and X window of the scroll bar in BAR. */
7827
7828static void
7829x_create_toolkit_scroll_bar (f, bar)
7830 struct frame *f;
7831 struct scroll_bar *bar;
7832{
7833 Window xwindow;
7834 Widget widget;
7835 Arg av[20];
7836 int ac = 0;
7837 char *scroll_bar_name = "verticalScrollBar";
7838 unsigned long pixel;
7839
7840 BLOCK_INPUT;
7841
7842#ifdef USE_MOTIF
7843 /* LessTif 0.85, problems:
7844
7845 1. When the mouse if over the scroll bar, the scroll bar will
7846 get keyboard events. I didn't find a way to turn this off.
7847
7848 2. Do we have to explicitly set the cursor to get an arrow
7849 cursor (see below)? */
7850
7851 /* Set resources. Create the widget. */
7852 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7853 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7854 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7855 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7856 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7857 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7858 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7859
7860 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7861 if (pixel != -1)
7862 {
7863 XtSetArg (av[ac], XmNforeground, pixel);
7864 ++ac;
7865 }
7866
7867 pixel = f->output_data.x->scroll_bar_background_pixel;
7868 if (pixel != -1)
7869 {
7870 XtSetArg (av[ac], XmNbackground, pixel);
7871 ++ac;
7872 }
7873
7874 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7875 scroll_bar_name, av, ac);
7876
7877 /* Add one callback for everything that can happen. */
7878 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7879 (XtPointer) bar);
7880 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7881 (XtPointer) bar);
7882 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7883 (XtPointer) bar);
7884 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7885 (XtPointer) bar);
7886 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7887 (XtPointer) bar);
7888 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7889 (XtPointer) bar);
7890 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7891 (XtPointer) bar);
7892
7893 /* Realize the widget. Only after that is the X window created. */
7894 XtRealizeWidget (widget);
7895
7896 /* Set the cursor to an arrow. I didn't find a resource to do that.
7897 And I'm wondering why it hasn't an arrow cursor by default. */
7898 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7899 f->output_data.x->nontext_cursor);
7900
ec18280f 7901#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7902
7903 /* Set resources. Create the widget. The background of the
7904 Xaw3d scroll bar widget is a little bit light for my taste.
7905 We don't alter it here to let users change it according
7906 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7907 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7908 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
7909 /* For smoother scrolling with Xaw3d -sm */
7910 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7911 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
7912
7913 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7914 if (pixel != -1)
7915 {
7916 XtSetArg (av[ac], XtNforeground, pixel);
7917 ++ac;
7918 }
7919
7920 pixel = f->output_data.x->scroll_bar_background_pixel;
7921 if (pixel != -1)
7922 {
7923 XtSetArg (av[ac], XtNbackground, pixel);
7924 ++ac;
7925 }
7926
7927 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7928 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
7929
7930 {
7931 char *initial = "";
7932 char *val = initial;
7933 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7934 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7935 if (val == initial)
7936 { /* ARROW_SCROLL */
7937 xaw3d_arrow_scroll = True;
7938 /* Isn't that just a personal preference ? -sm */
7939 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7940 }
7941 }
06a2c219
GM
7942
7943 /* Define callbacks. */
ec18280f
SM
7944 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7945 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
7946 (XtPointer) bar);
7947
7948 /* Realize the widget. Only after that is the X window created. */
7949 XtRealizeWidget (widget);
7950
ec18280f 7951#endif /* !USE_MOTIF */
06a2c219
GM
7952
7953 /* Install an action hook that let's us detect when the user
7954 finishes interacting with a scroll bar. */
7955 if (action_hook_id == 0)
7956 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7957
7958 /* Remember X window and widget in the scroll bar vector. */
7959 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7960 xwindow = XtWindow (widget);
7961 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7962
7963 UNBLOCK_INPUT;
7964}
7965
7966
7967/* Set the thumb size and position of scroll bar BAR. We are currently
7968 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7969
7970static void
7971x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7972 struct scroll_bar *bar;
7973 int portion, position, whole;
f451eb13 7974{
06a2c219 7975 float top, shown;
06a2c219 7976 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7977
06a2c219
GM
7978 if (whole == 0)
7979 top = 0, shown = 1;
7980 else
f451eb13 7981 {
06a2c219
GM
7982 top = (float) position / whole;
7983 shown = (float) portion / whole;
7984 }
f451eb13 7985
06a2c219 7986 BLOCK_INPUT;
f451eb13 7987
06a2c219
GM
7988#ifdef USE_MOTIF
7989 {
7990 int size, value;
7991 Boolean arrow1_selected, arrow2_selected;
7992 unsigned char flags;
7993 XmScrollBarWidget sb;
7994
ec18280f 7995 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
7996 is the scroll bar's maximum and MIN is the scroll bar's minimum
7997 value. */
7998 size = shown * XM_SB_RANGE;
7999 size = min (size, XM_SB_RANGE);
8000 size = max (size, 1);
8001
8002 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
8003 value = top * XM_SB_RANGE;
8004 value = min (value, XM_SB_MAX - size);
8005 value = max (value, XM_SB_MIN);
8006
8007 /* LessTif: Calling XmScrollBarSetValues after an increment or
8008 decrement turns off auto-repeat LessTif-internally. This can
8009 be seen in ScrollBar.c which resets Arrow1Selected and
8010 Arrow2Selected. It also sets internal flags so that LessTif
8011 believes the mouse is in the slider. We either have to change
8012 our code, or work around that by accessing private data. */
8013
8014 sb = (XmScrollBarWidget) widget;
8015 arrow1_selected = sb->scrollBar.arrow1_selected;
8016 arrow2_selected = sb->scrollBar.arrow2_selected;
8017 flags = sb->scrollBar.flags;
8018
8019 if (NILP (bar->dragging))
8020 XmScrollBarSetValues (widget, value, size, 0, 0, False);
8021 else if (last_scroll_bar_part == scroll_bar_down_arrow)
8022 /* This has the negative side effect that the slider value is
ec18280f 8023 not what it would be if we scrolled here using line-wise or
06a2c219
GM
8024 page-wise movement. */
8025 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
8026 else
8027 {
8028 /* If currently dragging, only update the slider size.
8029 This reduces flicker effects. */
8030 int old_value, old_size, increment, page_increment;
8031
8032 XmScrollBarGetValues (widget, &old_value, &old_size,
8033 &increment, &page_increment);
8034 XmScrollBarSetValues (widget, old_value,
8035 min (size, XM_SB_RANGE - old_value),
8036 0, 0, False);
8037 }
8038
8039 sb->scrollBar.arrow1_selected = arrow1_selected;
8040 sb->scrollBar.arrow2_selected = arrow2_selected;
8041 sb->scrollBar.flags = flags;
8042 }
ec18280f 8043#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 8044 {
ec18280f
SM
8045 float old_top, old_shown;
8046 Dimension height;
8047 XtVaGetValues (widget,
8048 XtNtopOfThumb, &old_top,
8049 XtNshown, &old_shown,
8050 XtNheight, &height,
8051 NULL);
8052
8053 /* Massage the top+shown values. */
8054 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
8055 top = max (0, min (1, top));
8056 else
8057 top = old_top;
8058 /* Keep two pixels available for moving the thumb down. */
8059 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8060
8061 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8062 check that your system's configuration file contains a define
8063 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8064 if (top != old_top || shown != old_shown)
eb393530 8065 {
ec18280f 8066 if (NILP (bar->dragging))
eb393530 8067 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8068 else
8069 {
ec18280f
SM
8070#ifdef HAVE_XAW3D
8071 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8072 int scroll_mode = 0;
ec18280f
SM
8073
8074 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8075 if (xaw3d_arrow_scroll)
8076 {
8077 /* Xaw3d stupidly ignores resize requests while dragging
8078 so we have to make it believe it's not in dragging mode. */
8079 scroll_mode = sb->scrollbar.scroll_mode;
8080 if (scroll_mode == 2)
8081 sb->scrollbar.scroll_mode = 0;
8082 }
8083#endif
8084 /* Try to make the scrolling a tad smoother. */
8085 if (!xaw3d_pick_top)
8086 shown = min (shown, old_shown);
8087
8088 XawScrollbarSetThumb (widget, top, shown);
8089
8090#ifdef HAVE_XAW3D
8091 if (xaw3d_arrow_scroll && scroll_mode == 2)
8092 sb->scrollbar.scroll_mode = scroll_mode;
8093#endif
06a2c219 8094 }
06a2c219
GM
8095 }
8096 }
ec18280f 8097#endif /* !USE_MOTIF */
06a2c219
GM
8098
8099 UNBLOCK_INPUT;
f451eb13
JB
8100}
8101
06a2c219
GM
8102#endif /* USE_TOOLKIT_SCROLL_BARS */
8103
8104
8105\f
8106/************************************************************************
8107 Scroll bars, general
8108 ************************************************************************/
8109
8110/* Create a scroll bar and return the scroll bar vector for it. W is
8111 the Emacs window on which to create the scroll bar. TOP, LEFT,
8112 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8113 scroll bar. */
8114
ab648270 8115static struct scroll_bar *
06a2c219
GM
8116x_scroll_bar_create (w, top, left, width, height)
8117 struct window *w;
f451eb13
JB
8118 int top, left, width, height;
8119{
06a2c219 8120 struct frame *f = XFRAME (w->frame);
334208b7
RS
8121 struct scroll_bar *bar
8122 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8123
8124 BLOCK_INPUT;
8125
06a2c219
GM
8126#if USE_TOOLKIT_SCROLL_BARS
8127 x_create_toolkit_scroll_bar (f, bar);
8128#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8129 {
8130 XSetWindowAttributes a;
8131 unsigned long mask;
5c187dee 8132 Window window;
06a2c219
GM
8133
8134 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8135 if (a.background_pixel == -1)
8136 a.background_pixel = f->output_data.x->background_pixel;
8137
12ba150f 8138 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8139 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8140 | ExposureMask);
7a13e894 8141 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8142
dbc4e1c1 8143 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8144
06a2c219
GM
8145 /* Clear the area of W that will serve as a scroll bar. This is
8146 for the case that a window has been split horizontally. In
8147 this case, no clear_frame is generated to reduce flickering. */
8148 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8149 left, top, width,
8150 window_box_height (w), False);
8151
8152 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8153 /* Position and size of scroll bar. */
8154 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8155 top,
8156 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8157 height,
8158 /* Border width, depth, class, and visual. */
8159 0,
8160 CopyFromParent,
8161 CopyFromParent,
8162 CopyFromParent,
8163 /* Attributes. */
8164 mask, &a);
8165 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8166 }
06a2c219 8167#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8168
06a2c219 8169 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8170 XSETINT (bar->top, top);
8171 XSETINT (bar->left, left);
8172 XSETINT (bar->width, width);
8173 XSETINT (bar->height, height);
8174 XSETINT (bar->start, 0);
8175 XSETINT (bar->end, 0);
12ba150f 8176 bar->dragging = Qnil;
f451eb13
JB
8177
8178 /* Add bar to its frame's list of scroll bars. */
334208b7 8179 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8180 bar->prev = Qnil;
334208b7 8181 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8182 if (!NILP (bar->next))
e0c1aef2 8183 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8184
06a2c219
GM
8185 /* Map the window/widget. */
8186#if USE_TOOLKIT_SCROLL_BARS
8187 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8188 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8189 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8190 top,
8191 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8192 height, 0);
8193#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8194 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8195#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8196
8197 UNBLOCK_INPUT;
12ba150f 8198 return bar;
f451eb13
JB
8199}
8200
06a2c219 8201
12ba150f 8202/* Draw BAR's handle in the proper position.
06a2c219 8203
12ba150f
JB
8204 If the handle is already drawn from START to END, don't bother
8205 redrawing it, unless REBUILD is non-zero; in that case, always
8206 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8207 events.)
12ba150f
JB
8208
8209 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8210 fit inside its rectangle, but if the user is dragging the scroll
8211 bar handle, we want to let them drag it down all the way, so that
8212 the bar's top is as far down as it goes; otherwise, there's no way
8213 to move to the very end of the buffer. */
8214
5c187dee
GM
8215#ifndef USE_TOOLKIT_SCROLL_BARS
8216
f451eb13 8217static void
ab648270
JB
8218x_scroll_bar_set_handle (bar, start, end, rebuild)
8219 struct scroll_bar *bar;
f451eb13 8220 int start, end;
12ba150f 8221 int rebuild;
f451eb13 8222{
12ba150f 8223 int dragging = ! NILP (bar->dragging);
ab648270 8224 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8225 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8226 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8227
8228 /* If the display is already accurate, do nothing. */
8229 if (! rebuild
8230 && start == XINT (bar->start)
8231 && end == XINT (bar->end))
8232 return;
8233
f451eb13
JB
8234 BLOCK_INPUT;
8235
8236 {
d9cdbb3d
RS
8237 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8238 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8239 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8240
8241 /* Make sure the values are reasonable, and try to preserve
8242 the distance between start and end. */
12ba150f
JB
8243 {
8244 int length = end - start;
8245
8246 if (start < 0)
8247 start = 0;
8248 else if (start > top_range)
8249 start = top_range;
8250 end = start + length;
8251
8252 if (end < start)
8253 end = start;
8254 else if (end > top_range && ! dragging)
8255 end = top_range;
8256 }
f451eb13 8257
ab648270 8258 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8259 XSETINT (bar->start, start);
8260 XSETINT (bar->end, end);
f451eb13 8261
12ba150f
JB
8262 /* Clip the end position, just for display. */
8263 if (end > top_range)
8264 end = top_range;
f451eb13 8265
ab648270 8266 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8267 below top positions, to make sure the handle is always at least
8268 that many pixels tall. */
ab648270 8269 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8270
12ba150f
JB
8271 /* Draw the empty space above the handle. Note that we can't clear
8272 zero-height areas; that means "clear to end of window." */
8273 if (0 < start)
334208b7 8274 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8275
12ba150f 8276 /* x, y, width, height, and exposures. */
ab648270
JB
8277 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8278 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8279 inside_width, start,
8280 False);
f451eb13 8281
06a2c219
GM
8282 /* Change to proper foreground color if one is specified. */
8283 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8284 XSetForeground (FRAME_X_DISPLAY (f), gc,
8285 f->output_data.x->scroll_bar_foreground_pixel);
8286
12ba150f 8287 /* Draw the handle itself. */
334208b7 8288 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8289
12ba150f 8290 /* x, y, width, height */
ab648270
JB
8291 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8292 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8293 inside_width, end - start);
f451eb13 8294
06a2c219
GM
8295 /* Restore the foreground color of the GC if we changed it above. */
8296 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8297 XSetForeground (FRAME_X_DISPLAY (f), gc,
8298 f->output_data.x->foreground_pixel);
f451eb13 8299
12ba150f
JB
8300 /* Draw the empty space below the handle. Note that we can't
8301 clear zero-height areas; that means "clear to end of window." */
8302 if (end < inside_height)
334208b7 8303 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8304
12ba150f 8305 /* x, y, width, height, and exposures. */
ab648270
JB
8306 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8307 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8308 inside_width, inside_height - end,
8309 False);
f451eb13 8310
f451eb13
JB
8311 }
8312
f451eb13
JB
8313 UNBLOCK_INPUT;
8314}
8315
5c187dee 8316#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8317
06a2c219
GM
8318/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8319 nil. */
58769bee 8320
12ba150f 8321static void
ab648270
JB
8322x_scroll_bar_remove (bar)
8323 struct scroll_bar *bar;
12ba150f 8324{
12ba150f
JB
8325 BLOCK_INPUT;
8326
06a2c219
GM
8327#if USE_TOOLKIT_SCROLL_BARS
8328 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8329#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8330 {
8331 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8332 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8333 }
06a2c219
GM
8334#endif /* not USE_TOOLKIT_SCROLL_BARS */
8335
ab648270
JB
8336 /* Disassociate this scroll bar from its window. */
8337 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8338
8339 UNBLOCK_INPUT;
8340}
8341
06a2c219 8342
12ba150f
JB
8343/* Set the handle of the vertical scroll bar for WINDOW to indicate
8344 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8345 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8346 create one. */
06a2c219 8347
12ba150f 8348static void
06a2c219
GM
8349XTset_vertical_scroll_bar (w, portion, whole, position)
8350 struct window *w;
f451eb13
JB
8351 int portion, whole, position;
8352{
06a2c219 8353 struct frame *f = XFRAME (w->frame);
ab648270 8354 struct scroll_bar *bar;
3c6ede7b 8355 int top, height, left, sb_left, width, sb_width;
06a2c219 8356 int window_x, window_y, window_width, window_height;
06a2c219 8357
3c6ede7b 8358 /* Get window dimensions. */
06a2c219 8359 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8360 top = window_y;
8361 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8362 height = window_height;
06a2c219 8363
3c6ede7b 8364 /* Compute the left edge of the scroll bar area. */
06a2c219 8365 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8366 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8367 else
8368 left = XFASTINT (w->left);
8369 left *= CANON_X_UNIT (f);
8370 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8371
8372 /* Compute the width of the scroll bar which might be less than
8373 the width of the area reserved for the scroll bar. */
8374 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8375 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8376 else
3c6ede7b 8377 sb_width = width;
12ba150f 8378
3c6ede7b
GM
8379 /* Compute the left edge of the scroll bar. */
8380#ifdef USE_TOOLKIT_SCROLL_BARS
8381 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8382 sb_left = left + width - sb_width - (width - sb_width) / 2;
8383 else
8384 sb_left = left + (width - sb_width) / 2;
8385#else
8386 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8387 sb_left = left + width - sb_width;
8388 else
8389 sb_left = left;
8390#endif
8391
ab648270 8392 /* Does the scroll bar exist yet? */
06a2c219 8393 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8394 {
80c32bcc 8395 BLOCK_INPUT;
3c6ede7b
GM
8396 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8397 left, top, width, height, False);
80c32bcc 8398 UNBLOCK_INPUT;
3c6ede7b
GM
8399 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8400 }
f451eb13 8401 else
12ba150f
JB
8402 {
8403 /* It may just need to be moved and resized. */
06a2c219
GM
8404 unsigned int mask = 0;
8405
8406 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8407
8408 BLOCK_INPUT;
8409
3c6ede7b 8410 if (sb_left != XINT (bar->left))
06a2c219 8411 mask |= CWX;
3c6ede7b 8412 if (top != XINT (bar->top))
06a2c219 8413 mask |= CWY;
3c6ede7b 8414 if (sb_width != XINT (bar->width))
06a2c219 8415 mask |= CWWidth;
3c6ede7b 8416 if (height != XINT (bar->height))
06a2c219
GM
8417 mask |= CWHeight;
8418
8419#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8420
8421 /* Since toolkit scroll bars are smaller than the space reserved
8422 for them on the frame, we have to clear "under" them. */
8423 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8424 left, top, width, height, False);
06a2c219
GM
8425
8426 /* Move/size the scroll bar widget. */
8427 if (mask)
8428 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8429 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8430 top,
8431 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8432 height, 0);
06a2c219
GM
8433
8434#else /* not USE_TOOLKIT_SCROLL_BARS */
8435
e1f6572f
RS
8436 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8437 {
8438 /* Clear areas not covered by the scroll bar. This makes sure a
8439 previous mode line display is cleared after C-x 2 C-x 1, for
8440 example. Non-toolkit scroll bars are as wide as the area
8441 reserved for scroll bars - trim at both sides. */
8442 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8443 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8444 height, False);
8445 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8446 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8447 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8448 height, False);
8449 }
06a2c219
GM
8450
8451 /* Move/size the scroll bar window. */
8452 if (mask)
8453 {
8454 XWindowChanges wc;
8455
3c6ede7b
GM
8456 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8457 wc.y = top;
8458 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8459 wc.height = height;
06a2c219
GM
8460 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8461 mask, &wc);
8462 }
8463
8464#endif /* not USE_TOOLKIT_SCROLL_BARS */
8465
8466 /* Remember new settings. */
3c6ede7b
GM
8467 XSETINT (bar->left, sb_left);
8468 XSETINT (bar->top, top);
8469 XSETINT (bar->width, sb_width);
8470 XSETINT (bar->height, height);
06a2c219
GM
8471
8472 UNBLOCK_INPUT;
12ba150f 8473 }
f451eb13 8474
06a2c219
GM
8475#if USE_TOOLKIT_SCROLL_BARS
8476 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8477#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8478 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8479 dragged. */
12ba150f 8480 if (NILP (bar->dragging))
f451eb13 8481 {
92857db0 8482 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8483
12ba150f 8484 if (whole == 0)
ab648270 8485 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8486 else
8487 {
43f868f5
JB
8488 int start = ((double) position * top_range) / whole;
8489 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8490 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8491 }
f451eb13 8492 }
06a2c219 8493#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8494
06a2c219 8495 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8496}
8497
12ba150f 8498
f451eb13 8499/* The following three hooks are used when we're doing a thorough
ab648270 8500 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8501 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8502 away is a real pain - "Can you say set-window-configuration, boys
8503 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8504 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8505 from the fiery pit when we actually redisplay its window. */
f451eb13 8506
ab648270
JB
8507/* Arrange for all scroll bars on FRAME to be removed at the next call
8508 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8509 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8510
58769bee 8511static void
ab648270 8512XTcondemn_scroll_bars (frame)
f451eb13
JB
8513 FRAME_PTR frame;
8514{
f9e24cb9
RS
8515 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8516 while (! NILP (FRAME_SCROLL_BARS (frame)))
8517 {
8518 Lisp_Object bar;
8519 bar = FRAME_SCROLL_BARS (frame);
8520 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8521 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8522 XSCROLL_BAR (bar)->prev = Qnil;
8523 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8524 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8525 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8526 }
f451eb13
JB
8527}
8528
06a2c219 8529/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8530 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 8531static void
ab648270 8532XTredeem_scroll_bar (window)
12ba150f 8533 struct window *window;
f451eb13 8534{
ab648270 8535 struct scroll_bar *bar;
12ba150f 8536
ab648270
JB
8537 /* We can't redeem this window's scroll bar if it doesn't have one. */
8538 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8539 abort ();
8540
ab648270 8541 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8542
8543 /* Unlink it from the condemned list. */
8544 {
8545 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8546
8547 if (NILP (bar->prev))
8548 {
8549 /* If the prev pointer is nil, it must be the first in one of
8550 the lists. */
ab648270 8551 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
8552 /* It's not condemned. Everything's fine. */
8553 return;
ab648270
JB
8554 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8555 window->vertical_scroll_bar))
8556 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
8557 else
8558 /* If its prev pointer is nil, it must be at the front of
8559 one or the other! */
8560 abort ();
8561 }
8562 else
ab648270 8563 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
8564
8565 if (! NILP (bar->next))
ab648270 8566 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8567
ab648270 8568 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8569 bar->prev = Qnil;
e0c1aef2 8570 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 8571 if (! NILP (bar->next))
e0c1aef2 8572 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 8573 }
f451eb13
JB
8574}
8575
ab648270
JB
8576/* Remove all scroll bars on FRAME that haven't been saved since the
8577 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8578
f451eb13 8579static void
ab648270 8580XTjudge_scroll_bars (f)
12ba150f 8581 FRAME_PTR f;
f451eb13 8582{
12ba150f 8583 Lisp_Object bar, next;
f451eb13 8584
ab648270 8585 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8586
8587 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8588 more events on the hapless scroll bars. */
8589 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8590
8591 for (; ! NILP (bar); bar = next)
f451eb13 8592 {
ab648270 8593 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8594
ab648270 8595 x_scroll_bar_remove (b);
12ba150f
JB
8596
8597 next = b->next;
8598 b->next = b->prev = Qnil;
f451eb13 8599 }
12ba150f 8600
ab648270 8601 /* Now there should be no references to the condemned scroll bars,
12ba150f 8602 and they should get garbage-collected. */
f451eb13
JB
8603}
8604
8605
06a2c219
GM
8606/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8607 is a no-op when using toolkit scroll bars.
ab648270
JB
8608
8609 This may be called from a signal handler, so we have to ignore GC
8610 mark bits. */
06a2c219 8611
f451eb13 8612static void
ab648270
JB
8613x_scroll_bar_expose (bar, event)
8614 struct scroll_bar *bar;
f451eb13
JB
8615 XEvent *event;
8616{
06a2c219
GM
8617#ifndef USE_TOOLKIT_SCROLL_BARS
8618
ab648270 8619 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8620 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8621 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8622 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8623
f451eb13
JB
8624 BLOCK_INPUT;
8625
ab648270 8626 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8627
06a2c219 8628 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8629 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8630
8631 /* x, y, width, height */
d9cdbb3d 8632 0, 0,
3cbd2e0b 8633 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8634 XINT (bar->height) - 1);
8635
f451eb13 8636 UNBLOCK_INPUT;
06a2c219
GM
8637
8638#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8639}
8640
ab648270
JB
8641/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8642 is set to something other than no_event, it is enqueued.
8643
8644 This may be called from a signal handler, so we have to ignore GC
8645 mark bits. */
06a2c219 8646
5c187dee
GM
8647#ifndef USE_TOOLKIT_SCROLL_BARS
8648
f451eb13 8649static void
ab648270
JB
8650x_scroll_bar_handle_click (bar, event, emacs_event)
8651 struct scroll_bar *bar;
f451eb13
JB
8652 XEvent *event;
8653 struct input_event *emacs_event;
8654{
0299d313 8655 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8656 abort ();
8657
ab648270 8658 emacs_event->kind = scroll_bar_click;
69388238 8659 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8660 emacs_event->modifiers
8661 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8662 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8663 event->xbutton.state)
8664 | (event->type == ButtonRelease
8665 ? up_modifier
8666 : down_modifier));
12ba150f 8667 emacs_event->frame_or_window = bar->window;
0f8aabe9 8668 emacs_event->arg = Qnil;
f451eb13 8669 emacs_event->timestamp = event->xbutton.time;
12ba150f 8670 {
06a2c219 8671#if 0
d9cdbb3d 8672 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8673 int internal_height
d9cdbb3d 8674 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8675#endif
0299d313 8676 int top_range
d9cdbb3d 8677 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8678 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8679
8680 if (y < 0) y = 0;
8681 if (y > top_range) y = top_range;
8682
8683 if (y < XINT (bar->start))
ab648270
JB
8684 emacs_event->part = scroll_bar_above_handle;
8685 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8686 emacs_event->part = scroll_bar_handle;
12ba150f 8687 else
ab648270 8688 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8689
8690 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8691 they want to drag it. Lisp code needs to be able to decide
8692 whether or not we're dragging. */
929787e1 8693#if 0
12ba150f
JB
8694 /* If the user has just clicked on the handle, record where they're
8695 holding it. */
8696 if (event->type == ButtonPress
ab648270 8697 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8698 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8699#endif
12ba150f
JB
8700
8701 /* If the user has released the handle, set it to its final position. */
8702 if (event->type == ButtonRelease
8703 && ! NILP (bar->dragging))
8704 {
8705 int new_start = y - XINT (bar->dragging);
8706 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8707
ab648270 8708 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8709 bar->dragging = Qnil;
8710 }
f451eb13 8711
5116f055
JB
8712 /* Same deal here as the other #if 0. */
8713#if 0
58769bee 8714 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8715 the handle. */
ab648270 8716 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8717 emacs_event->x = bar->start;
8718 else
e0c1aef2 8719 XSETINT (emacs_event->x, y);
5116f055 8720#else
e0c1aef2 8721 XSETINT (emacs_event->x, y);
5116f055 8722#endif
f451eb13 8723
e0c1aef2 8724 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8725 }
8726}
f451eb13 8727
ab648270
JB
8728/* Handle some mouse motion while someone is dragging the scroll bar.
8729
8730 This may be called from a signal handler, so we have to ignore GC
8731 mark bits. */
06a2c219 8732
f451eb13 8733static void
ab648270
JB
8734x_scroll_bar_note_movement (bar, event)
8735 struct scroll_bar *bar;
f451eb13
JB
8736 XEvent *event;
8737{
39d8bb4d
KH
8738 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8739
f451eb13
JB
8740 last_mouse_movement_time = event->xmotion.time;
8741
39d8bb4d 8742 f->mouse_moved = 1;
e0c1aef2 8743 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8744
8745 /* If we're dragging the bar, display it. */
ab648270 8746 if (! GC_NILP (bar->dragging))
f451eb13
JB
8747 {
8748 /* Where should the handle be now? */
12ba150f 8749 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8750
12ba150f 8751 if (new_start != XINT (bar->start))
f451eb13 8752 {
12ba150f 8753 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8754
ab648270 8755 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8756 }
8757 }
f451eb13
JB
8758}
8759
5c187dee
GM
8760#endif /* !USE_TOOLKIT_SCROLL_BARS */
8761
12ba150f 8762/* Return information to the user about the current position of the mouse
ab648270 8763 on the scroll bar. */
06a2c219 8764
12ba150f 8765static void
334208b7
RS
8766x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8767 FRAME_PTR *fp;
12ba150f 8768 Lisp_Object *bar_window;
ab648270 8769 enum scroll_bar_part *part;
12ba150f
JB
8770 Lisp_Object *x, *y;
8771 unsigned long *time;
8772{
ab648270 8773 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8774 Window w = SCROLL_BAR_X_WINDOW (bar);
8775 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8776 int win_x, win_y;
559cb2fb
JB
8777 Window dummy_window;
8778 int dummy_coord;
8779 unsigned int dummy_mask;
12ba150f 8780
cf7cb199
JB
8781 BLOCK_INPUT;
8782
ab648270 8783 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8784 report that. */
334208b7 8785 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8786
559cb2fb
JB
8787 /* Root, child, root x and root y. */
8788 &dummy_window, &dummy_window,
8789 &dummy_coord, &dummy_coord,
12ba150f 8790
559cb2fb
JB
8791 /* Position relative to scroll bar. */
8792 &win_x, &win_y,
12ba150f 8793
559cb2fb
JB
8794 /* Mouse buttons and modifier keys. */
8795 &dummy_mask))
7a13e894 8796 ;
559cb2fb
JB
8797 else
8798 {
06a2c219 8799#if 0
559cb2fb 8800 int inside_height
d9cdbb3d 8801 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8802#endif
559cb2fb 8803 int top_range
d9cdbb3d 8804 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8805
8806 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8807
8808 if (! NILP (bar->dragging))
8809 win_y -= XINT (bar->dragging);
8810
8811 if (win_y < 0)
8812 win_y = 0;
8813 if (win_y > top_range)
8814 win_y = top_range;
8815
334208b7 8816 *fp = f;
7a13e894 8817 *bar_window = bar->window;
559cb2fb
JB
8818
8819 if (! NILP (bar->dragging))
8820 *part = scroll_bar_handle;
8821 else if (win_y < XINT (bar->start))
8822 *part = scroll_bar_above_handle;
8823 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8824 *part = scroll_bar_handle;
8825 else
8826 *part = scroll_bar_below_handle;
12ba150f 8827
e0c1aef2
KH
8828 XSETINT (*x, win_y);
8829 XSETINT (*y, top_range);
12ba150f 8830
39d8bb4d 8831 f->mouse_moved = 0;
559cb2fb
JB
8832 last_mouse_scroll_bar = Qnil;
8833 }
12ba150f 8834
559cb2fb 8835 *time = last_mouse_movement_time;
cf7cb199 8836
cf7cb199 8837 UNBLOCK_INPUT;
12ba150f
JB
8838}
8839
f451eb13 8840
dbc4e1c1 8841/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8842 background colors, and the scroll bars may need to be redrawn.
8843 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8844 redraw them. */
8845
dfcf069d 8846void
ab648270 8847x_scroll_bar_clear (f)
dbc4e1c1
JB
8848 FRAME_PTR f;
8849{
06a2c219 8850#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8851 Lisp_Object bar;
8852
b80c363e
RS
8853 /* We can have scroll bars even if this is 0,
8854 if we just turned off scroll bar mode.
8855 But in that case we should not clear them. */
8856 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8857 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8858 bar = XSCROLL_BAR (bar)->next)
8859 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8860 0, 0, 0, 0, True);
06a2c219 8861#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8862}
8863
06a2c219 8864/* This processes Expose events from the menu-bar specific X event
19126e11 8865 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8866 when handling menu-bar or pop-up items. */
3afe33e7 8867
06a2c219 8868int
3afe33e7
RS
8869process_expose_from_menu (event)
8870 XEvent event;
8871{
8872 FRAME_PTR f;
19126e11 8873 struct x_display_info *dpyinfo;
06a2c219 8874 int frame_exposed_p = 0;
3afe33e7 8875
f94397b5
KH
8876 BLOCK_INPUT;
8877
19126e11
KH
8878 dpyinfo = x_display_info_for_display (event.xexpose.display);
8879 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8880 if (f)
8881 {
8882 if (f->async_visible == 0)
8883 {
8884 f->async_visible = 1;
8885 f->async_iconified = 0;
06c488fd 8886 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8887 SET_FRAME_GARBAGED (f);
8888 }
8889 else
8890 {
06a2c219
GM
8891 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8892 event.xexpose.x, event.xexpose.y,
8893 event.xexpose.width, event.xexpose.height);
8894 frame_exposed_p = 1;
3afe33e7
RS
8895 }
8896 }
8897 else
8898 {
8899 struct scroll_bar *bar
8900 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8901
3afe33e7
RS
8902 if (bar)
8903 x_scroll_bar_expose (bar, &event);
8904 }
f94397b5
KH
8905
8906 UNBLOCK_INPUT;
06a2c219 8907 return frame_exposed_p;
3afe33e7 8908}
09756a85
RS
8909\f
8910/* Define a queue to save up SelectionRequest events for later handling. */
8911
8912struct selection_event_queue
8913 {
8914 XEvent event;
8915 struct selection_event_queue *next;
8916 };
8917
8918static struct selection_event_queue *queue;
8919
8920/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8921
09756a85
RS
8922static int x_queue_selection_requests;
8923
8924/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8925
09756a85 8926static void
334208b7
RS
8927x_queue_event (f, event)
8928 FRAME_PTR f;
09756a85
RS
8929 XEvent *event;
8930{
8931 struct selection_event_queue *queue_tmp
06a2c219 8932 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8933
58769bee 8934 if (queue_tmp != NULL)
09756a85
RS
8935 {
8936 queue_tmp->event = *event;
8937 queue_tmp->next = queue;
8938 queue = queue_tmp;
8939 }
8940}
8941
8942/* Take all the queued events and put them back
8943 so that they get processed afresh. */
8944
8945static void
db3906fd
RS
8946x_unqueue_events (display)
8947 Display *display;
09756a85 8948{
58769bee 8949 while (queue != NULL)
09756a85
RS
8950 {
8951 struct selection_event_queue *queue_tmp = queue;
db3906fd 8952 XPutBackEvent (display, &queue_tmp->event);
09756a85 8953 queue = queue_tmp->next;
06a2c219 8954 xfree ((char *)queue_tmp);
09756a85
RS
8955 }
8956}
8957
8958/* Start queuing SelectionRequest events. */
8959
8960void
db3906fd
RS
8961x_start_queuing_selection_requests (display)
8962 Display *display;
09756a85
RS
8963{
8964 x_queue_selection_requests++;
8965}
8966
8967/* Stop queuing SelectionRequest events. */
8968
8969void
db3906fd
RS
8970x_stop_queuing_selection_requests (display)
8971 Display *display;
09756a85
RS
8972{
8973 x_queue_selection_requests--;
db3906fd 8974 x_unqueue_events (display);
09756a85 8975}
f451eb13
JB
8976\f
8977/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8978
06a2c219 8979/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8980 but we have to put it out here, since static variables within functions
8981 sometimes don't work. */
06a2c219 8982
dc6f92b8
JB
8983static Time enter_timestamp;
8984
11edeb03 8985/* This holds the state XLookupString needs to implement dead keys
58769bee 8986 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8987 says that a portable program can't use this, but Stephen Gildea assures
8988 me that letting the compiler initialize it to zeros will work okay.
8989
8990 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8991 given for enter_time stamp, above. */
8992
11edeb03
JB
8993static XComposeStatus compose_status;
8994
10e6549c
RS
8995/* Record the last 100 characters stored
8996 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8997
2224b905
RS
8998static int temp_index;
8999static short temp_buffer[100];
10e6549c 9000
7a13e894
RS
9001/* Set this to nonzero to fake an "X I/O error"
9002 on a particular display. */
06a2c219 9003
7a13e894
RS
9004struct x_display_info *XTread_socket_fake_io_error;
9005
2224b905
RS
9006/* When we find no input here, we occasionally do a no-op command
9007 to verify that the X server is still running and we can still talk with it.
9008 We try all the open displays, one by one.
9009 This variable is used for cycling thru the displays. */
06a2c219 9010
2224b905
RS
9011static struct x_display_info *next_noop_dpyinfo;
9012
06a2c219
GM
9013#define SET_SAVED_MENU_EVENT(size) \
9014 do \
9015 { \
9016 if (f->output_data.x->saved_menu_event == 0) \
9017 f->output_data.x->saved_menu_event \
9018 = (XEvent *) xmalloc (sizeof (XEvent)); \
9019 bcopy (&event, f->output_data.x->saved_menu_event, size); \
9020 if (numchars >= 1) \
9021 { \
9022 bufp->kind = menu_bar_activate_event; \
9023 XSETFRAME (bufp->frame_or_window, f); \
0f8aabe9 9024 bufp->arg = Qnil; \
06a2c219
GM
9025 bufp++; \
9026 count++; \
9027 numchars--; \
9028 } \
9029 } \
9030 while (0)
9031
8805890a 9032#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 9033#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 9034
dc6f92b8
JB
9035/* Read events coming from the X server.
9036 This routine is called by the SIGIO handler.
9037 We return as soon as there are no more events to be read.
9038
9039 Events representing keys are stored in buffer BUFP,
9040 which can hold up to NUMCHARS characters.
9041 We return the number of characters stored into the buffer,
9042 thus pretending to be `read'.
9043
dc6f92b8
JB
9044 EXPECTED is nonzero if the caller knows input is available. */
9045
7c5283e4 9046int
f66868ba 9047XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 9048 register int sd;
8805890a
KH
9049 /* register */ struct input_event *bufp;
9050 /* register */ int numchars;
dc6f92b8
JB
9051 int expected;
9052{
9053 int count = 0;
9054 int nbytes = 0;
dc6f92b8 9055 XEvent event;
f676886a 9056 struct frame *f;
66f55a9d 9057 int event_found = 0;
334208b7 9058 struct x_display_info *dpyinfo;
379b5ac0 9059 struct coding_system coding;
dc6f92b8 9060
9ac0d9e0 9061 if (interrupt_input_blocked)
dc6f92b8 9062 {
9ac0d9e0 9063 interrupt_input_pending = 1;
dc6f92b8
JB
9064 return -1;
9065 }
9066
9ac0d9e0 9067 interrupt_input_pending = 0;
dc6f92b8 9068 BLOCK_INPUT;
c0a04927
RS
9069
9070 /* So people can tell when we have read the available input. */
9071 input_signal_count++;
9072
dc6f92b8 9073 if (numchars <= 0)
06a2c219 9074 abort (); /* Don't think this happens. */
dc6f92b8 9075
bde5503b
GM
9076 ++handling_signal;
9077
379b5ac0
KH
9078 /* The input should be decoded if it is from XIM. Currently the
9079 locale of XIM is the same as that of the system. So, we can use
9080 Vlocale_coding_system which is initialized properly at Emacs
9081 startup time. */
9082 setup_coding_system (Vlocale_coding_system, &coding);
9083 coding.src_multibyte = 0;
9084 coding.dst_multibyte = 1;
9085 /* The input is converted to events, thus we can't handle
9086 composition. Anyway, there's no XIM that gives us composition
9087 information. */
9088 coding.composing = COMPOSITION_DISABLED;
9089
7a13e894
RS
9090 /* Find the display we are supposed to read input for.
9091 It's the one communicating on descriptor SD. */
9092 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9093 {
9094#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9095#ifdef FIOSNBIO
7a13e894
RS
9096 /* If available, Xlib uses FIOSNBIO to make the socket
9097 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9098 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9099 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9100 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9101#endif /* ! defined (FIOSNBIO) */
7a13e894 9102#endif
dc6f92b8 9103
7a13e894
RS
9104#if 0 /* This code can't be made to work, with multiple displays,
9105 and appears not to be used on any system any more.
9106 Also keyboard.c doesn't turn O_NDELAY on and off
9107 for X connections. */
dc6f92b8
JB
9108#ifndef SIGIO
9109#ifndef HAVE_SELECT
7a13e894
RS
9110 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9111 {
9112 extern int read_alarm_should_throw;
9113 read_alarm_should_throw = 1;
9114 XPeekEvent (dpyinfo->display, &event);
9115 read_alarm_should_throw = 0;
9116 }
c118dd06
JB
9117#endif /* HAVE_SELECT */
9118#endif /* SIGIO */
7a13e894 9119#endif
dc6f92b8 9120
7a13e894
RS
9121 /* For debugging, this gives a way to fake an I/O error. */
9122 if (dpyinfo == XTread_socket_fake_io_error)
9123 {
9124 XTread_socket_fake_io_error = 0;
9125 x_io_error_quitter (dpyinfo->display);
9126 }
dc6f92b8 9127
06a2c219 9128 while (XPending (dpyinfo->display))
dc6f92b8 9129 {
7a13e894 9130 XNextEvent (dpyinfo->display, &event);
06a2c219 9131
531483fb 9132#ifdef HAVE_X_I18N
d1bc4182 9133 {
f2be1146
GM
9134 /* Filter events for the current X input method.
9135 XFilterEvent returns non-zero if the input method has
9136 consumed the event. We pass the frame's X window to
9137 XFilterEvent because that's the one for which the IC
9138 was created. */
f5d11644
GM
9139 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9140 event.xclient.window);
9141 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9142 break;
9143 }
0cd6403b 9144#endif
7a13e894
RS
9145 event_found = 1;
9146
9147 switch (event.type)
9148 {
9149 case ClientMessage:
c047688c 9150 {
7a13e894
RS
9151 if (event.xclient.message_type
9152 == dpyinfo->Xatom_wm_protocols
9153 && event.xclient.format == 32)
c047688c 9154 {
7a13e894
RS
9155 if (event.xclient.data.l[0]
9156 == dpyinfo->Xatom_wm_take_focus)
c047688c 9157 {
8c1a6a84
RS
9158 /* Use x_any_window_to_frame because this
9159 could be the shell widget window
9160 if the frame has no title bar. */
9161 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9162#ifdef HAVE_X_I18N
9163 /* Not quite sure this is needed -pd */
8c1a6a84 9164 if (f && FRAME_XIC (f))
6c183ba5
RS
9165 XSetICFocus (FRAME_XIC (f));
9166#endif
f1da8f06
GM
9167#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9168 instructs the WM to set the input focus automatically for
9169 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9170 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9171 it has set the focus. So, XSetInputFocus below is not
9172 needed.
9173
9174 The call to XSetInputFocus below has also caused trouble. In
9175 cases where the XSetInputFocus done by the WM and the one
9176 below are temporally close (on a fast machine), the call
9177 below can generate additional FocusIn events which confuse
9178 Emacs. */
9179
bf7253f4
RS
9180 /* Since we set WM_TAKE_FOCUS, we must call
9181 XSetInputFocus explicitly. But not if f is null,
9182 since that might be an event for a deleted frame. */
7a13e894 9183 if (f)
bf7253f4
RS
9184 {
9185 Display *d = event.xclient.display;
9186 /* Catch and ignore errors, in case window has been
9187 iconified by a window manager such as GWM. */
9188 int count = x_catch_errors (d);
9189 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9190 /* The ICCCM says this is
9191 the only valid choice. */
9192 RevertToParent,
bf7253f4
RS
9193 event.xclient.data.l[1]);
9194 /* This is needed to detect the error
9195 if there is an error. */
9196 XSync (d, False);
9197 x_uncatch_errors (d, count);
9198 }
7a13e894 9199 /* Not certain about handling scroll bars here */
f1da8f06 9200#endif /* 0 */
c047688c 9201 }
7a13e894
RS
9202 else if (event.xclient.data.l[0]
9203 == dpyinfo->Xatom_wm_save_yourself)
9204 {
9205 /* Save state modify the WM_COMMAND property to
06a2c219 9206 something which can reinstate us. This notifies
7a13e894
RS
9207 the session manager, who's looking for such a
9208 PropertyNotify. Can restart processing when
06a2c219 9209 a keyboard or mouse event arrives. */
7a13e894
RS
9210 if (numchars > 0)
9211 {
19126e11
KH
9212 f = x_top_window_to_frame (dpyinfo,
9213 event.xclient.window);
7a13e894
RS
9214
9215 /* This is just so we only give real data once
9216 for a single Emacs process. */
b86bd3dd 9217 if (f == SELECTED_FRAME ())
7a13e894
RS
9218 XSetCommand (FRAME_X_DISPLAY (f),
9219 event.xclient.window,
9220 initial_argv, initial_argc);
f000f5c5 9221 else if (f)
7a13e894
RS
9222 XSetCommand (FRAME_X_DISPLAY (f),
9223 event.xclient.window,
9224 0, 0);
9225 }
9226 }
9227 else if (event.xclient.data.l[0]
9228 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9229 {
19126e11
KH
9230 struct frame *f
9231 = x_any_window_to_frame (dpyinfo,
9232 event.xclient.window);
1fb20991 9233
7a13e894
RS
9234 if (f)
9235 {
9236 if (numchars == 0)
9237 abort ();
1fb20991 9238
7a13e894
RS
9239 bufp->kind = delete_window_event;
9240 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9241 bufp->arg = Qnil;
7a13e894
RS
9242 bufp++;
9243
9244 count += 1;
9245 numchars -= 1;
9246 }
1fb20991 9247 }
c047688c 9248 }
7a13e894
RS
9249 else if (event.xclient.message_type
9250 == dpyinfo->Xatom_wm_configure_denied)
9251 {
9252 }
9253 else if (event.xclient.message_type
9254 == dpyinfo->Xatom_wm_window_moved)
9255 {
9256 int new_x, new_y;
19126e11
KH
9257 struct frame *f
9258 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9259
7a13e894
RS
9260 new_x = event.xclient.data.s[0];
9261 new_y = event.xclient.data.s[1];
1fb20991 9262
7a13e894
RS
9263 if (f)
9264 {
7556890b
RS
9265 f->output_data.x->left_pos = new_x;
9266 f->output_data.x->top_pos = new_y;
7a13e894 9267 }
1fb20991 9268 }
0fdff6bb 9269#ifdef HACK_EDITRES
7a13e894
RS
9270 else if (event.xclient.message_type
9271 == dpyinfo->Xatom_editres)
9272 {
19126e11
KH
9273 struct frame *f
9274 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9275 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9276 &event, NULL);
7a13e894 9277 }
0fdff6bb 9278#endif /* HACK_EDITRES */
06a2c219
GM
9279 else if ((event.xclient.message_type
9280 == dpyinfo->Xatom_DONE)
9281 || (event.xclient.message_type
9282 == dpyinfo->Xatom_PAGE))
9283 {
9284 /* Ghostview job completed. Kill it. We could
9285 reply with "Next" if we received "Page", but we
9286 currently never do because we are interested in
9287 images, only, which should have 1 page. */
06a2c219
GM
9288 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9289 struct frame *f
9290 = x_window_to_frame (dpyinfo, event.xclient.window);
9291 x_kill_gs_process (pixmap, f);
9292 expose_frame (f, 0, 0, 0, 0);
9293 }
9294#ifdef USE_TOOLKIT_SCROLL_BARS
9295 /* Scroll bar callbacks send a ClientMessage from which
9296 we construct an input_event. */
9297 else if (event.xclient.message_type
9298 == dpyinfo->Xatom_Scrollbar)
9299 {
9300 x_scroll_bar_to_input_event (&event, bufp);
9301 ++bufp, ++count, --numchars;
9302 goto out;
9303 }
9304#endif /* USE_TOOLKIT_SCROLL_BARS */
9305 else
9306 goto OTHER;
7a13e894
RS
9307 }
9308 break;
dc6f92b8 9309
7a13e894 9310 case SelectionNotify:
3afe33e7 9311#ifdef USE_X_TOOLKIT
19126e11 9312 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9313 goto OTHER;
3afe33e7 9314#endif /* not USE_X_TOOLKIT */
dfcf069d 9315 x_handle_selection_notify (&event.xselection);
7a13e894 9316 break;
d56a553a 9317
06a2c219 9318 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9319#ifdef USE_X_TOOLKIT
19126e11 9320 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9321 goto OTHER;
3afe33e7 9322#endif /* USE_X_TOOLKIT */
7a13e894
RS
9323 {
9324 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9325
7a13e894
RS
9326 if (numchars == 0)
9327 abort ();
d56a553a 9328
7a13e894
RS
9329 bufp->kind = selection_clear_event;
9330 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9331 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9332 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9333 bufp->frame_or_window = Qnil;
0f8aabe9 9334 bufp->arg = Qnil;
7a13e894 9335 bufp++;
d56a553a 9336
7a13e894
RS
9337 count += 1;
9338 numchars -= 1;
9339 }
9340 break;
dc6f92b8 9341
06a2c219 9342 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9343#ifdef USE_X_TOOLKIT
19126e11 9344 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9345 goto OTHER;
3afe33e7 9346#endif /* USE_X_TOOLKIT */
7a13e894 9347 if (x_queue_selection_requests)
19126e11 9348 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9349 &event);
9350 else
9351 {
9352 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9353
7a13e894
RS
9354 if (numchars == 0)
9355 abort ();
9356
9357 bufp->kind = selection_request_event;
9358 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9359 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9360 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9361 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9362 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9363 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9364 bufp->frame_or_window = Qnil;
0f8aabe9 9365 bufp->arg = Qnil;
7a13e894
RS
9366 bufp++;
9367
9368 count += 1;
9369 numchars -= 1;
9370 }
9371 break;
9372
9373 case PropertyNotify:
3afe33e7 9374#ifdef USE_X_TOOLKIT
19126e11 9375 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9376 goto OTHER;
3afe33e7 9377#endif /* not USE_X_TOOLKIT */
dfcf069d 9378 x_handle_property_notify (&event.xproperty);
7a13e894 9379 break;
dc6f92b8 9380
7a13e894 9381 case ReparentNotify:
19126e11 9382 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9383 if (f)
9384 {
9385 int x, y;
7556890b 9386 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9387 x_real_positions (f, &x, &y);
7556890b
RS
9388 f->output_data.x->left_pos = x;
9389 f->output_data.x->top_pos = y;
7a13e894
RS
9390 }
9391 break;
3bd330d4 9392
7a13e894 9393 case Expose:
19126e11 9394 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9395 if (f)
dc6f92b8 9396 {
7a13e894
RS
9397 if (f->async_visible == 0)
9398 {
9399 f->async_visible = 1;
9400 f->async_iconified = 0;
06c488fd 9401 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9402 SET_FRAME_GARBAGED (f);
9403 }
9404 else
06a2c219
GM
9405 expose_frame (x_window_to_frame (dpyinfo,
9406 event.xexpose.window),
9407 event.xexpose.x, event.xexpose.y,
9408 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9409 }
9410 else
7a13e894 9411 {
06a2c219
GM
9412#ifdef USE_TOOLKIT_SCROLL_BARS
9413 /* Dispatch event to the widget. */
9414 goto OTHER;
9415#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9416 struct scroll_bar *bar
9417 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9418
7a13e894
RS
9419 if (bar)
9420 x_scroll_bar_expose (bar, &event);
3afe33e7 9421#ifdef USE_X_TOOLKIT
7a13e894
RS
9422 else
9423 goto OTHER;
3afe33e7 9424#endif /* USE_X_TOOLKIT */
06a2c219 9425#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9426 }
9427 break;
dc6f92b8 9428
7a13e894
RS
9429 case GraphicsExpose: /* This occurs when an XCopyArea's
9430 source area was obscured or not
9431 available.*/
19126e11 9432 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9433 if (f)
9434 {
06a2c219
GM
9435 expose_frame (f,
9436 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9437 event.xgraphicsexpose.width,
9438 event.xgraphicsexpose.height);
7a13e894 9439 }
3afe33e7 9440#ifdef USE_X_TOOLKIT
7a13e894
RS
9441 else
9442 goto OTHER;
3afe33e7 9443#endif /* USE_X_TOOLKIT */
7a13e894 9444 break;
dc6f92b8 9445
7a13e894 9446 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9447 source area was completely
9448 available */
7a13e894 9449 break;
dc6f92b8 9450
7a13e894 9451 case UnmapNotify:
06a2c219
GM
9452 /* Redo the mouse-highlight after the tooltip has gone. */
9453 if (event.xmap.window == tip_window)
9454 {
9455 tip_window = 0;
9456 redo_mouse_highlight ();
9457 }
9458
91ea2a7a 9459 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9460 if (f) /* F may no longer exist if
9461 the frame was deleted. */
9462 {
9463 /* While a frame is unmapped, display generation is
9464 disabled; you don't want to spend time updating a
9465 display that won't ever be seen. */
9466 f->async_visible = 0;
9467 /* We can't distinguish, from the event, whether the window
9468 has become iconified or invisible. So assume, if it
9469 was previously visible, than now it is iconified.
1aa6072f
RS
9470 But x_make_frame_invisible clears both
9471 the visible flag and the iconified flag;
9472 and that way, we know the window is not iconified now. */
7a13e894 9473 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9474 {
9475 f->async_iconified = 1;
bddd097c 9476
1aa6072f
RS
9477 bufp->kind = iconify_event;
9478 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9479 bufp->arg = Qnil;
1aa6072f
RS
9480 bufp++;
9481 count++;
9482 numchars--;
9483 }
7a13e894 9484 }
7a13e894 9485 goto OTHER;
dc6f92b8 9486
7a13e894 9487 case MapNotify:
06a2c219
GM
9488 if (event.xmap.window == tip_window)
9489 /* The tooltip has been drawn already. Avoid
9490 the SET_FRAME_GARBAGED below. */
9491 goto OTHER;
9492
9493 /* We use x_top_window_to_frame because map events can
9494 come for sub-windows and they don't mean that the
9495 frame is visible. */
19126e11 9496 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9497 if (f)
9498 {
9499 f->async_visible = 1;
9500 f->async_iconified = 0;
06c488fd 9501 f->output_data.x->has_been_visible = 1;
dc6f92b8 9502
7a13e894
RS
9503 /* wait_reading_process_input will notice this and update
9504 the frame's display structures. */
9505 SET_FRAME_GARBAGED (f);
bddd097c 9506
d806e720
RS
9507 if (f->iconified)
9508 {
9509 bufp->kind = deiconify_event;
9510 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9511 bufp->arg = Qnil;
d806e720
RS
9512 bufp++;
9513 count++;
9514 numchars--;
9515 }
e73ec6fa 9516 else if (! NILP (Vframe_list)
8e713be6 9517 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9518 /* Force a redisplay sooner or later
9519 to update the frame titles
9520 in case this is the second frame. */
9521 record_asynch_buffer_change ();
7a13e894 9522 }
7a13e894 9523 goto OTHER;
dc6f92b8 9524
7a13e894 9525 case KeyPress:
19126e11 9526 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9527
06a2c219
GM
9528#ifdef USE_MOTIF
9529 /* I couldn't find a way to prevent LessTif scroll bars
9530 from consuming key events. */
9531 if (f == 0)
9532 {
9533 Widget widget = XtWindowToWidget (dpyinfo->display,
9534 event.xkey.window);
9535 if (widget && XmIsScrollBar (widget))
9536 {
9537 widget = XtParent (widget);
9538 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9539 }
9540 }
9541#endif /* USE_MOTIF */
9542
7a13e894
RS
9543 if (f != 0)
9544 {
9545 KeySym keysym, orig_keysym;
379b5ac0
KH
9546 /* al%imercury@uunet.uu.net says that making this 81
9547 instead of 80 fixed a bug whereby meta chars made
9548 his Emacs hang.
9549
9550 It seems that some version of XmbLookupString has
9551 a bug of not returning XBufferOverflow in
9552 status_return even if the input is too long to
9553 fit in 81 bytes. So, we must prepare sufficient
9554 bytes for copy_buffer. 513 bytes (256 chars for
9555 two-byte character set) seems to be a faily good
9556 approximation. -- 2000.8.10 handa@etl.go.jp */
9557 unsigned char copy_buffer[513];
9558 unsigned char *copy_bufptr = copy_buffer;
9559 int copy_bufsiz = sizeof (copy_buffer);
7a13e894 9560 int modifiers;
64bb1782 9561
7a13e894
RS
9562 event.xkey.state
9563 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9564 extra_keyboard_modifiers);
9565 modifiers = event.xkey.state;
3a2712f9 9566
7a13e894 9567 /* This will have to go some day... */
752a043f 9568
7a13e894
RS
9569 /* make_lispy_event turns chars into control chars.
9570 Don't do it here because XLookupString is too eager. */
9571 event.xkey.state &= ~ControlMask;
5d46f928
RS
9572 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9573 | dpyinfo->super_mod_mask
9574 | dpyinfo->hyper_mod_mask
9575 | dpyinfo->alt_mod_mask);
9576
1cf4a0d1
RS
9577 /* In case Meta is ComposeCharacter,
9578 clear its status. According to Markus Ehrnsperger
9579 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9580 this enables ComposeCharacter to work whether or
9581 not it is combined with Meta. */
9582 if (modifiers & dpyinfo->meta_mod_mask)
9583 bzero (&compose_status, sizeof (compose_status));
9584
6c183ba5
RS
9585#ifdef HAVE_X_I18N
9586 if (FRAME_XIC (f))
9587 {
f5d11644
GM
9588 Status status_return;
9589
6c183ba5 9590 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9591 &event.xkey, copy_bufptr,
9592 copy_bufsiz, &keysym,
6c183ba5 9593 &status_return);
f5d11644
GM
9594 if (status_return == XBufferOverflow)
9595 {
9596 copy_bufsiz = nbytes + 1;
9597 copy_bufptr = (char *) alloca (copy_bufsiz);
9598 nbytes = XmbLookupString (FRAME_XIC (f),
9599 &event.xkey, copy_bufptr,
9600 copy_bufsiz, &keysym,
9601 &status_return);
9602 }
9603
1decb680
PE
9604 if (status_return == XLookupNone)
9605 break;
9606 else if (status_return == XLookupChars)
fdd9d55e
GM
9607 {
9608 keysym = NoSymbol;
9609 modifiers = 0;
9610 }
1decb680
PE
9611 else if (status_return != XLookupKeySym
9612 && status_return != XLookupBoth)
9613 abort ();
6c183ba5
RS
9614 }
9615 else
379b5ac0
KH
9616 nbytes = XLookupString (&event.xkey, copy_bufptr,
9617 copy_bufsiz, &keysym,
9618 &compose_status);
6c183ba5 9619#else
379b5ac0
KH
9620 nbytes = XLookupString (&event.xkey, copy_bufptr,
9621 copy_bufsiz, &keysym,
9622 &compose_status);
6c183ba5 9623#endif
dc6f92b8 9624
7a13e894 9625 orig_keysym = keysym;
55123275 9626
7a13e894
RS
9627 if (numchars > 1)
9628 {
9629 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9630 || keysym == XK_Delete
1097aea0 9631#ifdef XK_ISO_Left_Tab
441affdb 9632 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9633#endif
852bff8f 9634 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9635 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9636 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9637#ifdef HPUX
7a13e894
RS
9638 /* This recognizes the "extended function keys".
9639 It seems there's no cleaner way.
9640 Test IsModifierKey to avoid handling mode_switch
9641 incorrectly. */
9642 || ((unsigned) (keysym) >= XK_Select
9643 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9644#endif
9645#ifdef XK_dead_circumflex
7a13e894 9646 || orig_keysym == XK_dead_circumflex
69388238
RS
9647#endif
9648#ifdef XK_dead_grave
7a13e894 9649 || orig_keysym == XK_dead_grave
69388238
RS
9650#endif
9651#ifdef XK_dead_tilde
7a13e894 9652 || orig_keysym == XK_dead_tilde
69388238
RS
9653#endif
9654#ifdef XK_dead_diaeresis
7a13e894 9655 || orig_keysym == XK_dead_diaeresis
69388238
RS
9656#endif
9657#ifdef XK_dead_macron
7a13e894 9658 || orig_keysym == XK_dead_macron
69388238
RS
9659#endif
9660#ifdef XK_dead_degree
7a13e894 9661 || orig_keysym == XK_dead_degree
69388238
RS
9662#endif
9663#ifdef XK_dead_acute
7a13e894 9664 || orig_keysym == XK_dead_acute
69388238
RS
9665#endif
9666#ifdef XK_dead_cedilla
7a13e894 9667 || orig_keysym == XK_dead_cedilla
69388238
RS
9668#endif
9669#ifdef XK_dead_breve
7a13e894 9670 || orig_keysym == XK_dead_breve
69388238
RS
9671#endif
9672#ifdef XK_dead_ogonek
7a13e894 9673 || orig_keysym == XK_dead_ogonek
69388238
RS
9674#endif
9675#ifdef XK_dead_caron
7a13e894 9676 || orig_keysym == XK_dead_caron
69388238
RS
9677#endif
9678#ifdef XK_dead_doubleacute
7a13e894 9679 || orig_keysym == XK_dead_doubleacute
69388238
RS
9680#endif
9681#ifdef XK_dead_abovedot
7a13e894 9682 || orig_keysym == XK_dead_abovedot
c34790e0 9683#endif
7a13e894
RS
9684 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9685 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9686 /* Any "vendor-specific" key is ok. */
9687 || (orig_keysym & (1 << 28)))
9688 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9689#ifndef HAVE_X11R5
9690#ifdef XK_Mode_switch
7a13e894 9691 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9692#endif
9693#ifdef XK_Num_Lock
7a13e894 9694 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9695#endif
9696#endif /* not HAVE_X11R5 */
7a13e894 9697 ))
dc6f92b8 9698 {
10e6549c
RS
9699 if (temp_index == sizeof temp_buffer / sizeof (short))
9700 temp_index = 0;
7a13e894
RS
9701 temp_buffer[temp_index++] = keysym;
9702 bufp->kind = non_ascii_keystroke;
9703 bufp->code = keysym;
e0c1aef2 9704 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9705 bufp->arg = Qnil;
334208b7
RS
9706 bufp->modifiers
9707 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9708 modifiers);
1113d9db 9709 bufp->timestamp = event.xkey.time;
dc6f92b8 9710 bufp++;
7a13e894
RS
9711 count++;
9712 numchars--;
dc6f92b8 9713 }
7a13e894
RS
9714 else if (numchars > nbytes)
9715 {
9716 register int i;
379b5ac0
KH
9717 register int c;
9718 unsigned char *p, *pend;
9719 int nchars, len;
7a13e894
RS
9720
9721 for (i = 0; i < nbytes; i++)
9722 {
379b5ac0
KH
9723 if (temp_index == (sizeof temp_buffer
9724 / sizeof (short)))
7a13e894 9725 temp_index = 0;
379b5ac0
KH
9726 temp_buffer[temp_index++] = copy_bufptr[i];
9727 }
9728
9729 if (/* If the event is not from XIM, */
9730 event.xkey.keycode != 0
9731 /* or the current locale doesn't request
9732 decoding of the intup data, ... */
9733 || coding.type == coding_type_raw_text
9734 || coding.type == coding_type_no_conversion)
9735 {
9736 /* ... we can use the input data as is. */
9737 nchars = nbytes;
9738 }
9739 else
9740 {
9741 /* We have to decode the input data. */
9742 int require;
9743 unsigned char *p;
9744
9745 require = decoding_buffer_size (&coding, nbytes);
9746 p = (unsigned char *) alloca (require);
9747 coding.mode |= CODING_MODE_LAST_BLOCK;
9748 decode_coding (&coding, copy_bufptr, p,
9749 nbytes, require);
9750 nbytes = coding.produced;
9751 nchars = coding.produced_char;
9752 copy_bufptr = p;
9753 }
9754
9755 /* Convert the input data to a sequence of
9756 character events. */
9757 for (i = 0; i < nbytes; i += len)
9758 {
9759 c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
9760 nbytes - i, len);
9761 bufp->kind = (SINGLE_BYTE_CHAR_P (c)
9762 ? ascii_keystroke
9763 : multibyte_char_keystroke);
9764 bufp->code = c;
7a13e894 9765 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9766 bufp->arg = Qnil;
7a13e894
RS
9767 bufp->modifiers
9768 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9769 modifiers);
9770 bufp->timestamp = event.xkey.time;
9771 bufp++;
9772 }
9773
379b5ac0
KH
9774 count += nchars;
9775 numchars -= nchars;
1decb680
PE
9776
9777 if (keysym == NoSymbol)
9778 break;
7a13e894
RS
9779 }
9780 else
9781 abort ();
dc6f92b8 9782 }
10e6549c
RS
9783 else
9784 abort ();
dc6f92b8 9785 }
59ddecde
GM
9786#ifdef HAVE_X_I18N
9787 /* Don't dispatch this event since XtDispatchEvent calls
9788 XFilterEvent, and two calls in a row may freeze the
9789 client. */
9790 break;
9791#else
717ca130 9792 goto OTHER;
59ddecde 9793#endif
f451eb13 9794
f5d11644 9795 case KeyRelease:
59ddecde
GM
9796#ifdef HAVE_X_I18N
9797 /* Don't dispatch this event since XtDispatchEvent calls
9798 XFilterEvent, and two calls in a row may freeze the
9799 client. */
9800 break;
9801#else
f5d11644 9802 goto OTHER;
59ddecde 9803#endif
f5d11644 9804
7a13e894 9805 /* Here's a possible interpretation of the whole
06a2c219
GM
9806 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9807 you get a FocusIn event, you have to get a FocusOut
9808 event before you relinquish the focus. If you
9809 haven't received a FocusIn event, then a mere
9810 LeaveNotify is enough to free you. */
f451eb13 9811
7a13e894 9812 case EnterNotify:
06a2c219
GM
9813 {
9814 int from_menu_bar_p = 0;
9815
9816 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9817
9818#ifdef LESSTIF_VERSION
9819 /* When clicking outside of a menu bar popup to close
9820 it, we get a FocusIn/ EnterNotify sequence of
9821 events. The flag event.xcrossing.focus is not set
9822 in the EnterNotify event of that sequence because
9823 the focus is in the menu bar,
9824 event.xcrossing.window is the frame's X window.
9825 Unconditionally setting the focus frame to null in
9826 this case is not the right thing, because no event
9827 follows that could set the focus frame to the right
9828 value.
9829
9830 This could be a LessTif bug, but I wasn't able to
9831 reproduce the behavior in a simple test program.
9832
9833 (gerd, LessTif 0.88.1). */
9834
9835 if (!event.xcrossing.focus
9836 && f
9837 && f->output_data.x->menubar_widget)
9838 {
9839 Window focus;
9840 int revert;
9841
9842 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9843 if (focus == XtWindow (f->output_data.x->menubar_widget))
9844 from_menu_bar_p = 1;
9845 }
9846#endif /* LESSTIF_VERSION */
6d4238f3 9847
06a2c219
GM
9848 if (event.xcrossing.focus || from_menu_bar_p)
9849 {
9850 /* Avoid nasty pop/raise loops. */
9851 if (f && (!(f->auto_raise)
9852 || !(f->auto_lower)
9853 || (event.xcrossing.time - enter_timestamp) > 500))
9854 {
9855 x_new_focus_frame (dpyinfo, f);
9856 enter_timestamp = event.xcrossing.time;
9857 }
9858 }
9859 else if (f == dpyinfo->x_focus_frame)
9860 x_new_focus_frame (dpyinfo, 0);
9861
9862 /* EnterNotify counts as mouse movement,
9863 so update things that depend on mouse position. */
9864 if (f && !f->output_data.x->busy_p)
9865 note_mouse_movement (f, &event.xmotion);
9866 goto OTHER;
9867 }
dc6f92b8 9868
7a13e894 9869 case FocusIn:
19126e11 9870 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9871 if (event.xfocus.detail != NotifyPointer)
0f941935 9872 dpyinfo->x_focus_event_frame = f;
7a13e894 9873 if (f)
eb72635f
GM
9874 {
9875 x_new_focus_frame (dpyinfo, f);
9876
9877 /* Don't stop displaying the initial startup message
9878 for a switch-frame event we don't need. */
9879 if (GC_NILP (Vterminal_frame)
9880 && GC_CONSP (Vframe_list)
9881 && !GC_NILP (XCDR (Vframe_list)))
9882 {
9883 bufp->kind = FOCUS_IN_EVENT;
9884 XSETFRAME (bufp->frame_or_window, f);
0f8aabe9 9885 bufp->arg = Qnil;
eb72635f
GM
9886 ++bufp, ++count, --numchars;
9887 }
9888 }
f9e24cb9 9889
6c183ba5
RS
9890#ifdef HAVE_X_I18N
9891 if (f && FRAME_XIC (f))
9892 XSetICFocus (FRAME_XIC (f));
9893#endif
9894
7a13e894 9895 goto OTHER;
10c5e63d 9896
7a13e894 9897 case LeaveNotify:
19126e11 9898 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9899 if (f)
10c5e63d 9900 {
06a2c219
GM
9901 Lisp_Object frame;
9902 int from_menu_bar_p = 0;
9903
7a13e894 9904 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9905 {
9906 /* If we move outside the frame, then we're
9907 certainly no longer on any text in the frame. */
9908 clear_mouse_face (dpyinfo);
9909 dpyinfo->mouse_face_mouse_frame = 0;
9910 }
9911
9912 /* Generate a nil HELP_EVENT to cancel a help-echo.
9913 Do it only if there's something to cancel.
9914 Otherwise, the startup message is cleared when
9915 the mouse leaves the frame. */
9916 if (any_help_event_p)
9917 {
be010514
GM
9918 Lisp_Object frame;
9919 int n;
9920
06a2c219 9921 XSETFRAME (frame, f);
5ab2570d
GM
9922 n = gen_help_event (bufp, numchars,
9923 Qnil, frame, Qnil, Qnil, 0);
be010514 9924 bufp += n, count += n, numchars -= n;
06a2c219 9925 }
7a13e894 9926
06a2c219
GM
9927#ifdef LESSTIF_VERSION
9928 /* Please see the comment at the start of the
9929 EnterNotify case. */
9930 if (!event.xcrossing.focus
9931 && f->output_data.x->menubar_widget)
9932 {
9933 Window focus;
9934 int revert;
9935 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9936 if (focus == XtWindow (f->output_data.x->menubar_widget))
9937 from_menu_bar_p = 1;
9938 }
9939#endif /* LESSTIF_VERSION */
9940
9941 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9942 x_mouse_leave (dpyinfo);
10c5e63d 9943 else
7a13e894 9944 {
0f941935
KH
9945 if (f == dpyinfo->x_focus_event_frame)
9946 dpyinfo->x_focus_event_frame = 0;
9947 if (f == dpyinfo->x_focus_frame)
9948 x_new_focus_frame (dpyinfo, 0);
7a13e894 9949 }
10c5e63d 9950 }
7a13e894 9951 goto OTHER;
dc6f92b8 9952
7a13e894 9953 case FocusOut:
19126e11 9954 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9955 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9956 && f == dpyinfo->x_focus_event_frame)
9957 dpyinfo->x_focus_event_frame = 0;
9958 if (f && f == dpyinfo->x_focus_frame)
9959 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9960
6c183ba5
RS
9961#ifdef HAVE_X_I18N
9962 if (f && FRAME_XIC (f))
9963 XUnsetICFocus (FRAME_XIC (f));
9964#endif
9965
7a13e894 9966 goto OTHER;
dc6f92b8 9967
7a13e894 9968 case MotionNotify:
dc6f92b8 9969 {
06a2c219 9970 previous_help_echo = help_echo;
7cea38bc 9971 help_echo = help_echo_object = help_echo_window = Qnil;
be010514 9972 help_echo_pos = -1;
06a2c219 9973
7a13e894
RS
9974 if (dpyinfo->grabbed && last_mouse_frame
9975 && FRAME_LIVE_P (last_mouse_frame))
9976 f = last_mouse_frame;
9977 else
19126e11 9978 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9979
7a13e894
RS
9980 if (f)
9981 note_mouse_movement (f, &event.xmotion);
9982 else
9983 {
e88b3c50 9984#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9985 struct scroll_bar *bar
9986 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9987
7a13e894
RS
9988 if (bar)
9989 x_scroll_bar_note_movement (bar, &event);
e88b3c50 9990#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 9991
06a2c219
GM
9992 /* If we move outside the frame, then we're
9993 certainly no longer on any text in the frame. */
7a13e894
RS
9994 clear_mouse_face (dpyinfo);
9995 }
06a2c219
GM
9996
9997 /* If the contents of the global variable help_echo
9998 has changed, generate a HELP_EVENT. */
b7e80413
SM
9999 if (!NILP (help_echo)
10000 || !NILP (previous_help_echo))
06a2c219
GM
10001 {
10002 Lisp_Object frame;
be010514 10003 int n;
06a2c219
GM
10004
10005 if (f)
10006 XSETFRAME (frame, f);
10007 else
10008 frame = Qnil;
10009
10010 any_help_event_p = 1;
5ab2570d 10011 n = gen_help_event (bufp, numchars, help_echo, frame,
7cea38bc
GM
10012 help_echo_window, help_echo_object,
10013 help_echo_pos);
be010514 10014 bufp += n, count += n, numchars -= n;
06a2c219
GM
10015 }
10016
10017 goto OTHER;
dc6f92b8 10018 }
dc6f92b8 10019
7a13e894 10020 case ConfigureNotify:
9829ddba
RS
10021 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
10022 if (f)
af395ec1 10023 {
5c187dee 10024#ifndef USE_X_TOOLKIT
bf1b7b30
KH
10025 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
10026 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 10027
2d7fc7e8
RS
10028 /* In the toolkit version, change_frame_size
10029 is called by the code that handles resizing
10030 of the EmacsFrame widget. */
7a13e894 10031
7a13e894
RS
10032 /* Even if the number of character rows and columns has
10033 not changed, the font size may have changed, so we need
10034 to check the pixel dimensions as well. */
10035 if (columns != f->width
10036 || rows != f->height
7556890b
RS
10037 || event.xconfigure.width != f->output_data.x->pixel_width
10038 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 10039 {
7d1e984f 10040 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 10041 SET_FRAME_GARBAGED (f);
e687d06e 10042 cancel_mouse_face (f);
7a13e894 10043 }
2d7fc7e8 10044#endif
af395ec1 10045
7556890b
RS
10046 f->output_data.x->pixel_width = event.xconfigure.width;
10047 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
10048
10049 /* What we have now is the position of Emacs's own window.
10050 Convert that to the position of the window manager window. */
dcb07ae9
RS
10051 x_real_positions (f, &f->output_data.x->left_pos,
10052 &f->output_data.x->top_pos);
10053
f5d11644
GM
10054#ifdef HAVE_X_I18N
10055 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
10056 xic_set_statusarea (f);
10057#endif
10058
dcb07ae9
RS
10059 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
10060 {
10061 /* Since the WM decorations come below top_pos now,
10062 we must put them below top_pos in the future. */
10063 f->output_data.x->win_gravity = NorthWestGravity;
10064 x_wm_set_size_hint (f, (long) 0, 0);
10065 }
8f08dc93
KH
10066#ifdef USE_MOTIF
10067 /* Some window managers pass (0,0) as the location of
10068 the window, and the Motif event handler stores it
10069 in the emacs widget, which messes up Motif menus. */
10070 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
10071 {
10072 event.xconfigure.x = f->output_data.x->widget->core.x;
10073 event.xconfigure.y = f->output_data.x->widget->core.y;
10074 }
06a2c219 10075#endif /* USE_MOTIF */
7a13e894 10076 }
2d7fc7e8 10077 goto OTHER;
dc6f92b8 10078
7a13e894
RS
10079 case ButtonPress:
10080 case ButtonRelease:
10081 {
10082 /* If we decide we want to generate an event to be seen
10083 by the rest of Emacs, we put it here. */
10084 struct input_event emacs_event;
9ea173e8 10085 int tool_bar_p = 0;
06a2c219 10086
7a13e894 10087 emacs_event.kind = no_event;
7a13e894 10088 bzero (&compose_status, sizeof (compose_status));
9b07615b 10089
06a2c219
GM
10090 if (dpyinfo->grabbed
10091 && last_mouse_frame
9f67f20b
RS
10092 && FRAME_LIVE_P (last_mouse_frame))
10093 f = last_mouse_frame;
10094 else
2224b905 10095 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 10096
06a2c219
GM
10097 if (f)
10098 {
9ea173e8
GM
10099 /* Is this in the tool-bar? */
10100 if (WINDOWP (f->tool_bar_window)
10101 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
10102 {
10103 Lisp_Object window;
10104 int p, x, y;
10105
10106 x = event.xbutton.x;
10107 y = event.xbutton.y;
10108
10109 /* Set x and y. */
10110 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 10111 if (EQ (window, f->tool_bar_window))
06a2c219 10112 {
9ea173e8
GM
10113 x_handle_tool_bar_click (f, &event.xbutton);
10114 tool_bar_p = 1;
06a2c219
GM
10115 }
10116 }
10117
9ea173e8 10118 if (!tool_bar_p)
06a2c219
GM
10119 if (!dpyinfo->x_focus_frame
10120 || f == dpyinfo->x_focus_frame)
10121 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
10122 }
10123 else
10124 {
06a2c219 10125#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
10126 struct scroll_bar *bar
10127 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 10128
7a13e894
RS
10129 if (bar)
10130 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 10131#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
10132 }
10133
10134 if (event.type == ButtonPress)
10135 {
10136 dpyinfo->grabbed |= (1 << event.xbutton.button);
10137 last_mouse_frame = f;
edad46f6
KH
10138 /* Ignore any mouse motion that happened
10139 before this event; any subsequent mouse-movement
10140 Emacs events should reflect only motion after
10141 the ButtonPress. */
a00e91cd
KH
10142 if (f != 0)
10143 f->mouse_moved = 0;
06a2c219 10144
9ea173e8
GM
10145 if (!tool_bar_p)
10146 last_tool_bar_item = -1;
7a13e894 10147 }
3afe33e7
RS
10148 else
10149 {
7a13e894 10150 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10151 }
23faf38f 10152
7a13e894
RS
10153 if (numchars >= 1 && emacs_event.kind != no_event)
10154 {
10155 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10156 bufp++;
10157 count++;
10158 numchars--;
10159 }
3afe33e7
RS
10160
10161#ifdef USE_X_TOOLKIT
2224b905
RS
10162 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10163 /* For a down-event in the menu bar,
10164 don't pass it to Xt right now.
10165 Instead, save it away
10166 and we will pass it to Xt from kbd_buffer_get_event.
10167 That way, we can run some Lisp code first. */
91375f8f
RS
10168 if (f && event.type == ButtonPress
10169 /* Verify the event is really within the menu bar
10170 and not just sent to it due to grabbing. */
10171 && event.xbutton.x >= 0
10172 && event.xbutton.x < f->output_data.x->pixel_width
10173 && event.xbutton.y >= 0
10174 && event.xbutton.y < f->output_data.x->menubar_height
10175 && event.xbutton.same_screen)
2224b905 10176 {
8805890a 10177 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10178 XSETFRAME (last_mouse_press_frame, f);
10179 }
10180 else if (event.type == ButtonPress)
10181 {
10182 last_mouse_press_frame = Qnil;
30e671c3 10183 goto OTHER;
ce89ef46 10184 }
06a2c219 10185
2237cac9
RS
10186#ifdef USE_MOTIF /* This should do not harm for Lucid,
10187 but I am trying to be cautious. */
ce89ef46
RS
10188 else if (event.type == ButtonRelease)
10189 {
2237cac9 10190 if (!NILP (last_mouse_press_frame))
f10ded1c 10191 {
2237cac9
RS
10192 f = XFRAME (last_mouse_press_frame);
10193 if (f->output_data.x)
06a2c219 10194 SET_SAVED_BUTTON_EVENT;
f10ded1c 10195 }
06a2c219 10196 else
30e671c3 10197 goto OTHER;
2224b905 10198 }
2237cac9 10199#endif /* USE_MOTIF */
2224b905
RS
10200 else
10201 goto OTHER;
3afe33e7 10202#endif /* USE_X_TOOLKIT */
7a13e894
RS
10203 }
10204 break;
dc6f92b8 10205
7a13e894 10206 case CirculateNotify:
06a2c219
GM
10207 goto OTHER;
10208
7a13e894 10209 case CirculateRequest:
06a2c219
GM
10210 goto OTHER;
10211
10212 case VisibilityNotify:
10213 goto OTHER;
dc6f92b8 10214
7a13e894
RS
10215 case MappingNotify:
10216 /* Someone has changed the keyboard mapping - update the
10217 local cache. */
10218 switch (event.xmapping.request)
10219 {
10220 case MappingModifier:
10221 x_find_modifier_meanings (dpyinfo);
10222 /* This is meant to fall through. */
10223 case MappingKeyboard:
10224 XRefreshKeyboardMapping (&event.xmapping);
10225 }
7a13e894 10226 goto OTHER;
dc6f92b8 10227
7a13e894 10228 default:
7a13e894 10229 OTHER:
717ca130 10230#ifdef USE_X_TOOLKIT
7a13e894
RS
10231 BLOCK_INPUT;
10232 XtDispatchEvent (&event);
10233 UNBLOCK_INPUT;
3afe33e7 10234#endif /* USE_X_TOOLKIT */
7a13e894
RS
10235 break;
10236 }
dc6f92b8
JB
10237 }
10238 }
10239
06a2c219
GM
10240 out:;
10241
9a5196d0
RS
10242 /* On some systems, an X bug causes Emacs to get no more events
10243 when the window is destroyed. Detect that. (1994.) */
58769bee 10244 if (! event_found)
ef2a22d0 10245 {
ef2a22d0
RS
10246 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10247 One XNOOP in 100 loops will make Emacs terminate.
10248 B. Bretthauer, 1994 */
10249 x_noop_count++;
58769bee 10250 if (x_noop_count >= 100)
ef2a22d0
RS
10251 {
10252 x_noop_count=0;
2224b905
RS
10253
10254 if (next_noop_dpyinfo == 0)
10255 next_noop_dpyinfo = x_display_list;
10256
10257 XNoOp (next_noop_dpyinfo->display);
10258
10259 /* Each time we get here, cycle through the displays now open. */
10260 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10261 }
10262 }
502add23 10263
06a2c219 10264 /* If the focus was just given to an auto-raising frame,
0134a210 10265 raise it now. */
7a13e894 10266 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10267 if (pending_autoraise_frame)
10268 {
10269 x_raise_frame (pending_autoraise_frame);
10270 pending_autoraise_frame = 0;
10271 }
0134a210 10272
dc6f92b8 10273 UNBLOCK_INPUT;
bde5503b 10274 --handling_signal;
dc6f92b8
JB
10275 return count;
10276}
06a2c219
GM
10277
10278
10279
dc6f92b8 10280\f
06a2c219
GM
10281/***********************************************************************
10282 Text Cursor
10283 ***********************************************************************/
10284
10285/* Note if the text cursor of window W has been overwritten by a
10286 drawing operation that outputs N glyphs starting at HPOS in the
10287 line given by output_cursor.vpos. N < 0 means all the rest of the
10288 line after HPOS has been written. */
10289
10290static void
10291note_overwritten_text_cursor (w, hpos, n)
10292 struct window *w;
10293 int hpos, n;
10294{
10295 if (updated_area == TEXT_AREA
10296 && output_cursor.vpos == w->phys_cursor.vpos
10297 && hpos <= w->phys_cursor.hpos
10298 && (n < 0
10299 || hpos + n > w->phys_cursor.hpos))
10300 w->phys_cursor_on_p = 0;
10301}
f451eb13
JB
10302
10303
06a2c219
GM
10304/* Set clipping for output in glyph row ROW. W is the window in which
10305 we operate. GC is the graphics context to set clipping in.
10306 WHOLE_LINE_P non-zero means include the areas used for truncation
10307 mark display and alike in the clipping rectangle.
10308
10309 ROW may be a text row or, e.g., a mode line. Text rows must be
10310 clipped to the interior of the window dedicated to text display,
10311 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10312
10313static void
06a2c219
GM
10314x_clip_to_row (w, row, gc, whole_line_p)
10315 struct window *w;
10316 struct glyph_row *row;
10317 GC gc;
10318 int whole_line_p;
dc6f92b8 10319{
06a2c219
GM
10320 struct frame *f = XFRAME (WINDOW_FRAME (w));
10321 XRectangle clip_rect;
10322 int window_x, window_y, window_width, window_height;
dc6f92b8 10323
06a2c219 10324 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10325
06a2c219
GM
10326 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10327 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10328 clip_rect.y = max (clip_rect.y, window_y);
10329 clip_rect.width = window_width;
10330 clip_rect.height = row->visible_height;
5c1aae96 10331
06a2c219
GM
10332 /* If clipping to the whole line, including trunc marks, extend
10333 the rectangle to the left and increase its width. */
10334 if (whole_line_p)
10335 {
110859fc
GM
10336 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10337 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10338 }
5c1aae96 10339
06a2c219 10340 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10341}
10342
06a2c219
GM
10343
10344/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10345
10346static void
06a2c219
GM
10347x_draw_hollow_cursor (w, row)
10348 struct window *w;
10349 struct glyph_row *row;
dc6f92b8 10350{
06a2c219
GM
10351 struct frame *f = XFRAME (WINDOW_FRAME (w));
10352 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10353 Display *dpy = FRAME_X_DISPLAY (f);
10354 int x, y, wd, h;
10355 XGCValues xgcv;
10356 struct glyph *cursor_glyph;
10357 GC gc;
10358
10359 /* Compute frame-relative coordinates from window-relative
10360 coordinates. */
10361 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10362 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10363 + row->ascent - w->phys_cursor_ascent);
10364 h = row->height - 1;
10365
10366 /* Get the glyph the cursor is on. If we can't tell because
10367 the current matrix is invalid or such, give up. */
10368 cursor_glyph = get_phys_cursor_glyph (w);
10369 if (cursor_glyph == NULL)
dc6f92b8
JB
10370 return;
10371
06a2c219
GM
10372 /* Compute the width of the rectangle to draw. If on a stretch
10373 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10374 rectangle as wide as the glyph, but use a canonical character
10375 width instead. */
10376 wd = cursor_glyph->pixel_width - 1;
10377 if (cursor_glyph->type == STRETCH_GLYPH
10378 && !x_stretch_cursor_p)
10379 wd = min (CANON_X_UNIT (f), wd);
10380
10381 /* The foreground of cursor_gc is typically the same as the normal
10382 background color, which can cause the cursor box to be invisible. */
10383 xgcv.foreground = f->output_data.x->cursor_pixel;
10384 if (dpyinfo->scratch_cursor_gc)
10385 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10386 else
10387 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10388 GCForeground, &xgcv);
10389 gc = dpyinfo->scratch_cursor_gc;
10390
10391 /* Set clipping, draw the rectangle, and reset clipping again. */
10392 x_clip_to_row (w, row, gc, 0);
10393 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10394 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10395}
10396
06a2c219
GM
10397
10398/* Draw a bar cursor on window W in glyph row ROW.
10399
10400 Implementation note: One would like to draw a bar cursor with an
10401 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10402 Unfortunately, I didn't find a font yet that has this property set.
10403 --gerd. */
dc6f92b8
JB
10404
10405static void
f02d8aa0 10406x_draw_bar_cursor (w, row, width)
06a2c219
GM
10407 struct window *w;
10408 struct glyph_row *row;
f02d8aa0 10409 int width;
dc6f92b8 10410{
92f424df
GM
10411 struct frame *f = XFRAME (w->frame);
10412 struct glyph *cursor_glyph;
10413 GC gc;
10414 int x;
10415 unsigned long mask;
10416 XGCValues xgcv;
10417 Display *dpy;
10418 Window window;
06a2c219 10419
92f424df
GM
10420 /* If cursor is out of bounds, don't draw garbage. This can happen
10421 in mini-buffer windows when switching between echo area glyphs
10422 and mini-buffer. */
10423 cursor_glyph = get_phys_cursor_glyph (w);
10424 if (cursor_glyph == NULL)
10425 return;
06a2c219 10426
92f424df
GM
10427 /* If on an image, draw like a normal cursor. That's usually better
10428 visible than drawing a bar, esp. if the image is large so that
10429 the bar might not be in the window. */
10430 if (cursor_glyph->type == IMAGE_GLYPH)
10431 {
10432 struct glyph_row *row;
10433 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
10434 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
10435 }
10436 else
10437 {
06a2c219
GM
10438 xgcv.background = f->output_data.x->cursor_pixel;
10439 xgcv.foreground = f->output_data.x->cursor_pixel;
10440 xgcv.graphics_exposures = 0;
10441 mask = GCForeground | GCBackground | GCGraphicsExposures;
10442 dpy = FRAME_X_DISPLAY (f);
10443 window = FRAME_X_WINDOW (f);
10444 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
92f424df 10445
06a2c219
GM
10446 if (gc)
10447 XChangeGC (dpy, gc, mask, &xgcv);
10448 else
10449 {
10450 gc = XCreateGC (dpy, window, mask, &xgcv);
10451 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10452 }
92f424df 10453
f02d8aa0
GM
10454 if (width < 0)
10455 width = f->output_data.x->cursor_width;
92f424df 10456
06a2c219
GM
10457 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10458 x_clip_to_row (w, row, gc, 0);
10459 XFillRectangle (dpy, window, gc,
10460 x,
10461 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10462 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10463 row->height);
10464 XSetClipMask (dpy, gc, None);
10465 }
dc6f92b8
JB
10466}
10467
06a2c219
GM
10468
10469/* Clear the cursor of window W to background color, and mark the
10470 cursor as not shown. This is used when the text where the cursor
10471 is is about to be rewritten. */
10472
dc6f92b8 10473static void
06a2c219
GM
10474x_clear_cursor (w)
10475 struct window *w;
dc6f92b8 10476{
06a2c219
GM
10477 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10478 x_update_window_cursor (w, 0);
10479}
90e65f07 10480
dbc4e1c1 10481
06a2c219
GM
10482/* Draw the cursor glyph of window W in glyph row ROW. See the
10483 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10484
06a2c219
GM
10485static void
10486x_draw_phys_cursor_glyph (w, row, hl)
10487 struct window *w;
10488 struct glyph_row *row;
10489 enum draw_glyphs_face hl;
10490{
10491 /* If cursor hpos is out of bounds, don't draw garbage. This can
10492 happen in mini-buffer windows when switching between echo area
10493 glyphs and mini-buffer. */
10494 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10495 {
10496 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10497 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10498 hl, 0, 0, 0);
10499
10500 /* When we erase the cursor, and ROW is overlapped by other
10501 rows, make sure that these overlapping parts of other rows
10502 are redrawn. */
10503 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10504 {
10505 if (row > w->current_matrix->rows
10506 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10507 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10508
10509 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10510 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10511 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10512 }
10513 }
06a2c219 10514}
dbc4e1c1 10515
eea6af04 10516
06a2c219 10517/* Erase the image of a cursor of window W from the screen. */
eea6af04 10518
06a2c219
GM
10519static void
10520x_erase_phys_cursor (w)
10521 struct window *w;
10522{
10523 struct frame *f = XFRAME (w->frame);
10524 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10525 int hpos = w->phys_cursor.hpos;
10526 int vpos = w->phys_cursor.vpos;
10527 int mouse_face_here_p = 0;
10528 struct glyph_matrix *active_glyphs = w->current_matrix;
10529 struct glyph_row *cursor_row;
10530 struct glyph *cursor_glyph;
10531 enum draw_glyphs_face hl;
10532
10533 /* No cursor displayed or row invalidated => nothing to do on the
10534 screen. */
10535 if (w->phys_cursor_type == NO_CURSOR)
10536 goto mark_cursor_off;
10537
10538 /* VPOS >= active_glyphs->nrows means that window has been resized.
10539 Don't bother to erase the cursor. */
10540 if (vpos >= active_glyphs->nrows)
10541 goto mark_cursor_off;
10542
10543 /* If row containing cursor is marked invalid, there is nothing we
10544 can do. */
10545 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10546 if (!cursor_row->enabled_p)
10547 goto mark_cursor_off;
10548
10549 /* This can happen when the new row is shorter than the old one.
10550 In this case, either x_draw_glyphs or clear_end_of_line
10551 should have cleared the cursor. Note that we wouldn't be
10552 able to erase the cursor in this case because we don't have a
10553 cursor glyph at hand. */
10554 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10555 goto mark_cursor_off;
10556
10557 /* If the cursor is in the mouse face area, redisplay that when
10558 we clear the cursor. */
8801a864
KR
10559 if (! NILP (dpyinfo->mouse_face_window)
10560 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10561 && (vpos > dpyinfo->mouse_face_beg_row
10562 || (vpos == dpyinfo->mouse_face_beg_row
10563 && hpos >= dpyinfo->mouse_face_beg_col))
10564 && (vpos < dpyinfo->mouse_face_end_row
10565 || (vpos == dpyinfo->mouse_face_end_row
10566 && hpos < dpyinfo->mouse_face_end_col))
10567 /* Don't redraw the cursor's spot in mouse face if it is at the
10568 end of a line (on a newline). The cursor appears there, but
10569 mouse highlighting does not. */
10570 && cursor_row->used[TEXT_AREA] > hpos)
10571 mouse_face_here_p = 1;
10572
10573 /* Maybe clear the display under the cursor. */
10574 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10575 {
10576 int x;
045dee35 10577 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10578
06a2c219
GM
10579 cursor_glyph = get_phys_cursor_glyph (w);
10580 if (cursor_glyph == NULL)
10581 goto mark_cursor_off;
dbc4e1c1 10582
06a2c219
GM
10583 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10584
10585 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10586 x,
045dee35 10587 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10588 cursor_row->y)),
10589 cursor_glyph->pixel_width,
10590 cursor_row->visible_height,
10591 False);
dbc4e1c1 10592 }
06a2c219
GM
10593
10594 /* Erase the cursor by redrawing the character underneath it. */
10595 if (mouse_face_here_p)
10596 hl = DRAW_MOUSE_FACE;
10597 else if (cursor_row->inverse_p)
10598 hl = DRAW_INVERSE_VIDEO;
10599 else
10600 hl = DRAW_NORMAL_TEXT;
10601 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10602
06a2c219
GM
10603 mark_cursor_off:
10604 w->phys_cursor_on_p = 0;
10605 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10606}
10607
10608
06a2c219
GM
10609/* Display or clear cursor of window W. If ON is zero, clear the
10610 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10611 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10612
06a2c219
GM
10613void
10614x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10615 struct window *w;
10616 int on, hpos, vpos, x, y;
dbc4e1c1 10617{
06a2c219
GM
10618 struct frame *f = XFRAME (w->frame);
10619 int new_cursor_type;
f02d8aa0 10620 int new_cursor_width;
06a2c219
GM
10621 struct glyph_matrix *current_glyphs;
10622 struct glyph_row *glyph_row;
10623 struct glyph *glyph;
dbc4e1c1 10624
49d838ea 10625 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10626 windows and frames; in the latter case, the frame or window may
10627 be in the midst of changing its size, and x and y may be off the
10628 window. */
10629 if (! FRAME_VISIBLE_P (f)
10630 || FRAME_GARBAGED_P (f)
10631 || vpos >= w->current_matrix->nrows
10632 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10633 return;
10634
10635 /* If cursor is off and we want it off, return quickly. */
06a2c219 10636 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10637 return;
10638
06a2c219
GM
10639 current_glyphs = w->current_matrix;
10640 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10641 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10642
10643 /* If cursor row is not enabled, we don't really know where to
10644 display the cursor. */
10645 if (!glyph_row->enabled_p)
10646 {
10647 w->phys_cursor_on_p = 0;
10648 return;
10649 }
10650
10651 xassert (interrupt_input_blocked);
10652
10653 /* Set new_cursor_type to the cursor we want to be displayed. In a
10654 mini-buffer window, we want the cursor only to appear if we are
10655 reading input from this window. For the selected window, we want
10656 the cursor type given by the frame parameter. If explicitly
10657 marked off, draw no cursor. In all other cases, we want a hollow
10658 box cursor. */
f02d8aa0 10659 new_cursor_width = -1;
9b4a7047
GM
10660 if (cursor_in_echo_area
10661 && FRAME_HAS_MINIBUF_P (f)
10662 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10663 {
9b4a7047
GM
10664 if (w == XWINDOW (echo_area_window))
10665 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10666 else
10667 new_cursor_type = HOLLOW_BOX_CURSOR;
10668 }
06a2c219 10669 else
9b4a7047
GM
10670 {
10671 if (w != XWINDOW (selected_window)
10672 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10673 {
e55a0b79
GM
10674 extern int cursor_in_non_selected_windows;
10675
10676 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
9b4a7047
GM
10677 new_cursor_type = NO_CURSOR;
10678 else
10679 new_cursor_type = HOLLOW_BOX_CURSOR;
10680 }
10681 else if (w->cursor_off_p)
10682 new_cursor_type = NO_CURSOR;
10683 else
f02d8aa0
GM
10684 {
10685 struct buffer *b = XBUFFER (w->buffer);
10686
10687 if (EQ (b->cursor_type, Qt))
10688 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10689 else
10690 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10691 &new_cursor_width);
10692 }
9b4a7047 10693 }
06a2c219
GM
10694
10695 /* If cursor is currently being shown and we don't want it to be or
10696 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10697 erase it. */
06a2c219 10698 if (w->phys_cursor_on_p
dc6f92b8 10699 && (!on
06a2c219
GM
10700 || w->phys_cursor.x != x
10701 || w->phys_cursor.y != y
10702 || new_cursor_type != w->phys_cursor_type))
10703 x_erase_phys_cursor (w);
10704
10705 /* If the cursor is now invisible and we want it to be visible,
10706 display it. */
10707 if (on && !w->phys_cursor_on_p)
10708 {
10709 w->phys_cursor_ascent = glyph_row->ascent;
10710 w->phys_cursor_height = glyph_row->height;
10711
10712 /* Set phys_cursor_.* before x_draw_.* is called because some
10713 of them may need the information. */
10714 w->phys_cursor.x = x;
10715 w->phys_cursor.y = glyph_row->y;
10716 w->phys_cursor.hpos = hpos;
10717 w->phys_cursor.vpos = vpos;
10718 w->phys_cursor_type = new_cursor_type;
10719 w->phys_cursor_on_p = 1;
10720
10721 switch (new_cursor_type)
dc6f92b8 10722 {
06a2c219
GM
10723 case HOLLOW_BOX_CURSOR:
10724 x_draw_hollow_cursor (w, glyph_row);
10725 break;
10726
10727 case FILLED_BOX_CURSOR:
10728 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10729 break;
10730
10731 case BAR_CURSOR:
f02d8aa0 10732 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10733 break;
10734
10735 case NO_CURSOR:
10736 break;
dc6f92b8 10737
06a2c219
GM
10738 default:
10739 abort ();
10740 }
59ddecde
GM
10741
10742#ifdef HAVE_X_I18N
10743 if (w == XWINDOW (f->selected_window))
10744 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10745 xic_set_preeditarea (w, x, y);
10746#endif
dc6f92b8
JB
10747 }
10748
06a2c219 10749#ifndef XFlush
f676886a 10750 if (updating_frame != f)
334208b7 10751 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10752#endif
dc6f92b8
JB
10753}
10754
06a2c219
GM
10755
10756/* Display the cursor on window W, or clear it. X and Y are window
10757 relative pixel coordinates. HPOS and VPOS are glyph matrix
10758 positions. If W is not the selected window, display a hollow
10759 cursor. ON non-zero means display the cursor at X, Y which
10760 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10761
dfcf069d 10762void
06a2c219
GM
10763x_display_cursor (w, on, hpos, vpos, x, y)
10764 struct window *w;
10765 int on, hpos, vpos, x, y;
dc6f92b8 10766{
f94397b5 10767 BLOCK_INPUT;
06a2c219 10768 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10769 UNBLOCK_INPUT;
10770}
10771
06a2c219
GM
10772
10773/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10774 Don't change the cursor's position. */
10775
dfcf069d 10776void
06a2c219 10777x_update_cursor (f, on_p)
5d46f928 10778 struct frame *f;
5d46f928 10779{
06a2c219
GM
10780 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10781}
10782
10783
10784/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10785 in the window tree rooted at W. */
10786
10787static void
10788x_update_cursor_in_window_tree (w, on_p)
10789 struct window *w;
10790 int on_p;
10791{
10792 while (w)
10793 {
10794 if (!NILP (w->hchild))
10795 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10796 else if (!NILP (w->vchild))
10797 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10798 else
10799 x_update_window_cursor (w, on_p);
10800
10801 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10802 }
10803}
5d46f928 10804
f94397b5 10805
06a2c219
GM
10806/* Switch the display of W's cursor on or off, according to the value
10807 of ON. */
10808
10809static void
10810x_update_window_cursor (w, on)
10811 struct window *w;
10812 int on;
10813{
16b5d424
GM
10814 /* Don't update cursor in windows whose frame is in the process
10815 of being deleted. */
10816 if (w->current_matrix)
10817 {
10818 BLOCK_INPUT;
10819 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10820 w->phys_cursor.x, w->phys_cursor.y);
10821 UNBLOCK_INPUT;
10822 }
dc6f92b8 10823}
06a2c219
GM
10824
10825
10826
dc6f92b8
JB
10827\f
10828/* Icons. */
10829
f676886a 10830/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10831 when we get an expose event for it. */
dc6f92b8 10832
dfcf069d 10833void
f676886a
JB
10834refreshicon (f)
10835 struct frame *f;
dc6f92b8 10836{
06a2c219 10837 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10838}
10839
dbc4e1c1 10840/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10841
10842int
990ba854 10843x_bitmap_icon (f, file)
f676886a 10844 struct frame *f;
990ba854 10845 Lisp_Object file;
dc6f92b8 10846{
06a2c219 10847 int bitmap_id;
dc6f92b8 10848
c118dd06 10849 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10850 return 1;
10851
990ba854 10852 /* Free up our existing icon bitmap if any. */
7556890b
RS
10853 if (f->output_data.x->icon_bitmap > 0)
10854 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10855 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10856
10857 if (STRINGP (file))
7f2ae036
RS
10858 bitmap_id = x_create_bitmap_from_file (f, file);
10859 else
10860 {
990ba854 10861 /* Create the GNU bitmap if necessary. */
5bf01b68 10862 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10863 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10864 = x_create_bitmap_from_data (f, gnu_bits,
10865 gnu_width, gnu_height);
990ba854
RS
10866
10867 /* The first time we create the GNU bitmap,
06a2c219 10868 this increments the ref-count one extra time.
990ba854
RS
10869 As a result, the GNU bitmap is never freed.
10870 That way, we don't have to worry about allocating it again. */
334208b7 10871 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10872
334208b7 10873 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10874 }
10875
10876 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10877 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10878
10879 return 0;
10880}
10881
10882
1be2d067
KH
10883/* Make the x-window of frame F use a rectangle with text.
10884 Use ICON_NAME as the text. */
dc6f92b8
JB
10885
10886int
f676886a
JB
10887x_text_icon (f, icon_name)
10888 struct frame *f;
dc6f92b8
JB
10889 char *icon_name;
10890{
c118dd06 10891 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10892 return 1;
10893
1be2d067
KH
10894#ifdef HAVE_X11R4
10895 {
10896 XTextProperty text;
10897 text.value = (unsigned char *) icon_name;
10898 text.encoding = XA_STRING;
10899 text.format = 8;
10900 text.nitems = strlen (icon_name);
10901#ifdef USE_X_TOOLKIT
7556890b 10902 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10903 &text);
10904#else /* not USE_X_TOOLKIT */
10905 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10906#endif /* not USE_X_TOOLKIT */
10907 }
10908#else /* not HAVE_X11R4 */
10909 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10910#endif /* not HAVE_X11R4 */
58769bee 10911
7556890b
RS
10912 if (f->output_data.x->icon_bitmap > 0)
10913 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10914 f->output_data.x->icon_bitmap = 0;
b1c884c3 10915 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10916
10917 return 0;
10918}
10919\f
e99db5a1
RS
10920#define X_ERROR_MESSAGE_SIZE 200
10921
10922/* If non-nil, this should be a string.
10923 It means catch X errors and store the error message in this string. */
10924
10925static Lisp_Object x_error_message_string;
10926
10927/* An X error handler which stores the error message in
10928 x_error_message_string. This is called from x_error_handler if
10929 x_catch_errors is in effect. */
10930
06a2c219 10931static void
e99db5a1
RS
10932x_error_catcher (display, error)
10933 Display *display;
10934 XErrorEvent *error;
10935{
10936 XGetErrorText (display, error->error_code,
10937 XSTRING (x_error_message_string)->data,
10938 X_ERROR_MESSAGE_SIZE);
10939}
10940
10941/* Begin trapping X errors for display DPY. Actually we trap X errors
10942 for all displays, but DPY should be the display you are actually
10943 operating on.
10944
10945 After calling this function, X protocol errors no longer cause
10946 Emacs to exit; instead, they are recorded in the string
10947 stored in x_error_message_string.
10948
10949 Calling x_check_errors signals an Emacs error if an X error has
10950 occurred since the last call to x_catch_errors or x_check_errors.
10951
10952 Calling x_uncatch_errors resumes the normal error handling. */
10953
10954void x_check_errors ();
10955static Lisp_Object x_catch_errors_unwind ();
10956
10957int
10958x_catch_errors (dpy)
10959 Display *dpy;
10960{
10961 int count = specpdl_ptr - specpdl;
10962
10963 /* Make sure any errors from previous requests have been dealt with. */
10964 XSync (dpy, False);
10965
10966 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10967
10968 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10969 XSTRING (x_error_message_string)->data[0] = 0;
10970
10971 return count;
10972}
10973
10974/* Unbind the binding that we made to check for X errors. */
10975
10976static Lisp_Object
10977x_catch_errors_unwind (old_val)
10978 Lisp_Object old_val;
10979{
10980 x_error_message_string = old_val;
10981 return Qnil;
10982}
10983
10984/* If any X protocol errors have arrived since the last call to
10985 x_catch_errors or x_check_errors, signal an Emacs error using
10986 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10987
10988void
10989x_check_errors (dpy, format)
10990 Display *dpy;
10991 char *format;
10992{
10993 /* Make sure to catch any errors incurred so far. */
10994 XSync (dpy, False);
10995
10996 if (XSTRING (x_error_message_string)->data[0])
10997 error (format, XSTRING (x_error_message_string)->data);
10998}
10999
9829ddba
RS
11000/* Nonzero if we had any X protocol errors
11001 since we did x_catch_errors on DPY. */
e99db5a1
RS
11002
11003int
11004x_had_errors_p (dpy)
11005 Display *dpy;
11006{
11007 /* Make sure to catch any errors incurred so far. */
11008 XSync (dpy, False);
11009
11010 return XSTRING (x_error_message_string)->data[0] != 0;
11011}
11012
9829ddba
RS
11013/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
11014
06a2c219 11015void
9829ddba
RS
11016x_clear_errors (dpy)
11017 Display *dpy;
11018{
11019 XSTRING (x_error_message_string)->data[0] = 0;
11020}
11021
e99db5a1
RS
11022/* Stop catching X protocol errors and let them make Emacs die.
11023 DPY should be the display that was passed to x_catch_errors.
11024 COUNT should be the value that was returned by
11025 the corresponding call to x_catch_errors. */
11026
11027void
11028x_uncatch_errors (dpy, count)
11029 Display *dpy;
11030 int count;
11031{
11032 unbind_to (count, Qnil);
11033}
11034
11035#if 0
11036static unsigned int x_wire_count;
11037x_trace_wire ()
11038{
11039 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
11040}
11041#endif /* ! 0 */
11042
11043\f
11044/* Handle SIGPIPE, which can happen when the connection to a server
11045 simply goes away. SIGPIPE is handled by x_connection_signal.
11046 Don't need to do anything, because the write which caused the
11047 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 11048 which will do the appropriate cleanup for us. */
e99db5a1
RS
11049
11050static SIGTYPE
11051x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 11052 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
11053{
11054#ifdef USG
11055 /* USG systems forget handlers when they are used;
11056 must reestablish each time */
11057 signal (signalnum, x_connection_signal);
11058#endif /* USG */
11059}
11060\f
4746118a
JB
11061/* Handling X errors. */
11062
7a13e894 11063/* Handle the loss of connection to display DISPLAY. */
16bd92ea 11064
4746118a 11065static SIGTYPE
7a13e894
RS
11066x_connection_closed (display, error_message)
11067 Display *display;
11068 char *error_message;
4746118a 11069{
7a13e894
RS
11070 struct x_display_info *dpyinfo = x_display_info_for_display (display);
11071 Lisp_Object frame, tail;
11072
6186a4a0
RS
11073 /* Indicate that this display is dead. */
11074
2e465cdd 11075#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 11076#ifdef USE_X_TOOLKIT
adabc3a9 11077 XtCloseDisplay (display);
2e465cdd 11078#endif
f613a4c8 11079#endif
adabc3a9 11080
9e80b57d
KR
11081 if (dpyinfo)
11082 dpyinfo->display = 0;
6186a4a0 11083
06a2c219 11084 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
11085 that are on the dead display. */
11086 FOR_EACH_FRAME (tail, frame)
11087 {
11088 Lisp_Object minibuf_frame;
11089 minibuf_frame
11090 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
11091 if (FRAME_X_P (XFRAME (frame))
11092 && FRAME_X_P (XFRAME (minibuf_frame))
11093 && ! EQ (frame, minibuf_frame)
11094 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
11095 Fdelete_frame (frame, Qt);
11096 }
11097
11098 /* Now delete all remaining frames on the dead display.
06a2c219 11099 We are now sure none of these is used as the mini-buffer
7a13e894
RS
11100 for another frame that we need to delete. */
11101 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
11102 if (FRAME_X_P (XFRAME (frame))
11103 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
11104 {
11105 /* Set this to t so that Fdelete_frame won't get confused
11106 trying to find a replacement. */
11107 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
11108 Fdelete_frame (frame, Qt);
11109 }
7a13e894 11110
482a1bd2
KH
11111 if (dpyinfo)
11112 x_delete_display (dpyinfo);
7a13e894
RS
11113
11114 if (x_display_list == 0)
11115 {
f8d07b62 11116 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
11117 shut_down_emacs (0, 0, Qnil);
11118 exit (70);
11119 }
12ba150f 11120
7a13e894
RS
11121 /* Ordinary stack unwind doesn't deal with these. */
11122#ifdef SIGIO
11123 sigunblock (sigmask (SIGIO));
11124#endif
11125 sigunblock (sigmask (SIGALRM));
11126 TOTALLY_UNBLOCK_INPUT;
11127
aa4d9a9e 11128 clear_waiting_for_input ();
7a13e894 11129 error ("%s", error_message);
4746118a
JB
11130}
11131
7a13e894
RS
11132/* This is the usual handler for X protocol errors.
11133 It kills all frames on the display that we got the error for.
11134 If that was the only one, it prints an error message and kills Emacs. */
11135
06a2c219 11136static void
c118dd06
JB
11137x_error_quitter (display, error)
11138 Display *display;
11139 XErrorEvent *error;
11140{
7a13e894 11141 char buf[256], buf1[356];
dc6f92b8 11142
58769bee 11143 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 11144 original error handler. */
dc6f92b8 11145
c118dd06 11146 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 11147 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 11148 buf, error->request_code);
7a13e894 11149 x_connection_closed (display, buf1);
dc6f92b8
JB
11150}
11151
e99db5a1
RS
11152/* This is the first-level handler for X protocol errors.
11153 It calls x_error_quitter or x_error_catcher. */
7a13e894 11154
8922af5f 11155static int
e99db5a1 11156x_error_handler (display, error)
8922af5f 11157 Display *display;
e99db5a1 11158 XErrorEvent *error;
8922af5f 11159{
e99db5a1
RS
11160 if (! NILP (x_error_message_string))
11161 x_error_catcher (display, error);
11162 else
11163 x_error_quitter (display, error);
06a2c219 11164 return 0;
f9e24cb9 11165}
c118dd06 11166
e99db5a1
RS
11167/* This is the handler for X IO errors, always.
11168 It kills all frames on the display that we lost touch with.
11169 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 11170
c118dd06 11171static int
e99db5a1 11172x_io_error_quitter (display)
c118dd06 11173 Display *display;
c118dd06 11174{
e99db5a1 11175 char buf[256];
dc6f92b8 11176
e99db5a1
RS
11177 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11178 x_connection_closed (display, buf);
06a2c219 11179 return 0;
dc6f92b8 11180}
dc6f92b8 11181\f
f451eb13
JB
11182/* Changing the font of the frame. */
11183
76bcdf39
RS
11184/* Give frame F the font named FONTNAME as its default font, and
11185 return the full name of that font. FONTNAME may be a wildcard
11186 pattern; in that case, we choose some font that fits the pattern.
11187 The return value shows which font we chose. */
11188
b5cf7a0e 11189Lisp_Object
f676886a
JB
11190x_new_font (f, fontname)
11191 struct frame *f;
dc6f92b8
JB
11192 register char *fontname;
11193{
dc43ef94 11194 struct font_info *fontp
ee569018 11195 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 11196
dc43ef94
KH
11197 if (!fontp)
11198 return Qnil;
2224a5fc 11199
dc43ef94 11200 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11201 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11202 f->output_data.x->fontset = -1;
11203
b2cad826
KH
11204 /* Compute the scroll bar width in character columns. */
11205 if (f->scroll_bar_pixel_width > 0)
11206 {
7556890b 11207 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11208 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11209 }
11210 else
4e61bddf
RS
11211 {
11212 int wid = FONT_WIDTH (f->output_data.x->font);
11213 f->scroll_bar_cols = (14 + wid - 1) / wid;
11214 }
b2cad826 11215
f676886a 11216 /* Now make the frame display the given font. */
c118dd06 11217 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11218 {
7556890b
RS
11219 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11220 f->output_data.x->font->fid);
11221 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11222 f->output_data.x->font->fid);
11223 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11224 f->output_data.x->font->fid);
f676886a 11225
a27f9f86 11226 frame_update_line_height (f);
0134a210 11227 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11228 }
a27f9f86
RS
11229 else
11230 /* If we are setting a new frame's font for the first time,
11231 there are no faces yet, so this font's height is the line height. */
7556890b 11232 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11233
dc43ef94
KH
11234 return build_string (fontp->full_name);
11235}
11236
11237/* Give frame F the fontset named FONTSETNAME as its default font, and
11238 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11239 pattern; in that case, we choose some fontset that fits the pattern.
11240 The return value shows which fontset we chose. */
b5cf7a0e 11241
dc43ef94
KH
11242Lisp_Object
11243x_new_fontset (f, fontsetname)
11244 struct frame *f;
11245 char *fontsetname;
11246{
ee569018 11247 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11248 Lisp_Object result;
b5cf7a0e 11249
dc43ef94
KH
11250 if (fontset < 0)
11251 return Qnil;
b5cf7a0e 11252
2da424f1
KH
11253 if (f->output_data.x->fontset == fontset)
11254 /* This fontset is already set in frame F. There's nothing more
11255 to do. */
ee569018 11256 return fontset_name (fontset);
dc43ef94 11257
ee569018 11258 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11259
11260 if (!STRINGP (result))
11261 /* Can't load ASCII font. */
11262 return Qnil;
11263
11264 /* Since x_new_font doesn't update any fontset information, do it now. */
11265 f->output_data.x->fontset = fontset;
dc43ef94 11266
f5d11644
GM
11267#ifdef HAVE_X_I18N
11268 if (FRAME_XIC (f)
11269 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11270 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11271#endif
11272
dc43ef94 11273 return build_string (fontsetname);
dc6f92b8 11274}
f5d11644
GM
11275
11276\f
11277/***********************************************************************
11278 X Input Methods
11279 ***********************************************************************/
11280
11281#ifdef HAVE_X_I18N
11282
11283#ifdef HAVE_X11R6
11284
11285/* XIM destroy callback function, which is called whenever the
11286 connection to input method XIM dies. CLIENT_DATA contains a
11287 pointer to the x_display_info structure corresponding to XIM. */
11288
11289static void
11290xim_destroy_callback (xim, client_data, call_data)
11291 XIM xim;
11292 XPointer client_data;
11293 XPointer call_data;
11294{
11295 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11296 Lisp_Object frame, tail;
11297
11298 BLOCK_INPUT;
11299
11300 /* No need to call XDestroyIC.. */
11301 FOR_EACH_FRAME (tail, frame)
11302 {
11303 struct frame *f = XFRAME (frame);
11304 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11305 {
11306 FRAME_XIC (f) = NULL;
11307 if (FRAME_XIC_FONTSET (f))
11308 {
11309 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11310 FRAME_XIC_FONTSET (f) = NULL;
11311 }
11312 }
11313 }
11314
11315 /* No need to call XCloseIM. */
11316 dpyinfo->xim = NULL;
11317 XFree (dpyinfo->xim_styles);
11318 UNBLOCK_INPUT;
11319}
11320
11321#endif /* HAVE_X11R6 */
11322
11323/* Open the connection to the XIM server on display DPYINFO.
11324 RESOURCE_NAME is the resource name Emacs uses. */
11325
11326static void
11327xim_open_dpy (dpyinfo, resource_name)
11328 struct x_display_info *dpyinfo;
11329 char *resource_name;
11330{
287f7dd6 11331#ifdef USE_XIM
f5d11644
GM
11332 XIM xim;
11333
11334 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11335 dpyinfo->xim = xim;
11336
11337 if (xim)
11338 {
f5d11644
GM
11339#ifdef HAVE_X11R6
11340 XIMCallback destroy;
11341#endif
11342
11343 /* Get supported styles and XIM values. */
11344 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11345
11346#ifdef HAVE_X11R6
11347 destroy.callback = xim_destroy_callback;
11348 destroy.client_data = (XPointer)dpyinfo;
68642df6 11349 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11350 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11351#endif
11352 }
287f7dd6
GM
11353
11354#else /* not USE_XIM */
11355 dpyinfo->xim = NULL;
11356#endif /* not USE_XIM */
f5d11644
GM
11357}
11358
11359
b9de836c 11360#ifdef HAVE_X11R6_XIM
f5d11644
GM
11361
11362struct xim_inst_t
11363{
11364 struct x_display_info *dpyinfo;
11365 char *resource_name;
11366};
11367
11368/* XIM instantiate callback function, which is called whenever an XIM
11369 server is available. DISPLAY is teh display of the XIM.
11370 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11371 when the callback was registered. */
11372
11373static void
11374xim_instantiate_callback (display, client_data, call_data)
11375 Display *display;
11376 XPointer client_data;
11377 XPointer call_data;
11378{
11379 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11380 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11381
11382 /* We don't support multiple XIM connections. */
11383 if (dpyinfo->xim)
11384 return;
11385
11386 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11387
11388 /* Create XIC for the existing frames on the same display, as long
11389 as they have no XIC. */
11390 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11391 {
11392 Lisp_Object tail, frame;
11393
11394 BLOCK_INPUT;
11395 FOR_EACH_FRAME (tail, frame)
11396 {
11397 struct frame *f = XFRAME (frame);
11398
11399 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11400 if (FRAME_XIC (f) == NULL)
11401 {
11402 create_frame_xic (f);
11403 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11404 xic_set_statusarea (f);
11405 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11406 {
11407 struct window *w = XWINDOW (f->selected_window);
11408 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11409 }
11410 }
11411 }
11412
11413 UNBLOCK_INPUT;
11414 }
11415}
11416
b9de836c 11417#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11418
11419
11420/* Open a connection to the XIM server on display DPYINFO.
11421 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11422 connection only at the first time. On X11R6, open the connection
11423 in the XIM instantiate callback function. */
11424
11425static void
11426xim_initialize (dpyinfo, resource_name)
11427 struct x_display_info *dpyinfo;
11428 char *resource_name;
11429{
287f7dd6 11430#ifdef USE_XIM
b9de836c 11431#ifdef HAVE_X11R6_XIM
f5d11644
GM
11432 struct xim_inst_t *xim_inst;
11433 int len;
11434
11435 dpyinfo->xim = NULL;
11436 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11437 xim_inst->dpyinfo = dpyinfo;
11438 len = strlen (resource_name);
11439 xim_inst->resource_name = (char *) xmalloc (len + 1);
11440 bcopy (resource_name, xim_inst->resource_name, len + 1);
11441 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11442 resource_name, EMACS_CLASS,
11443 xim_instantiate_callback,
2ebb2f8b
DL
11444 /* Fixme: This is XPointer in
11445 XFree86 but (XPointer *) on
11446 Tru64, at least. */
11447 (XPointer) xim_inst);
b9de836c 11448#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11449 dpyinfo->xim = NULL;
11450 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11451#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11452
11453#else /* not USE_XIM */
11454 dpyinfo->xim = NULL;
11455#endif /* not USE_XIM */
f5d11644
GM
11456}
11457
11458
11459/* Close the connection to the XIM server on display DPYINFO. */
11460
11461static void
11462xim_close_dpy (dpyinfo)
11463 struct x_display_info *dpyinfo;
11464{
287f7dd6 11465#ifdef USE_XIM
b9de836c 11466#ifdef HAVE_X11R6_XIM
f5d11644
GM
11467 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11468 NULL, EMACS_CLASS,
11469 xim_instantiate_callback, NULL);
b9de836c 11470#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11471 XCloseIM (dpyinfo->xim);
11472 dpyinfo->xim = NULL;
11473 XFree (dpyinfo->xim_styles);
287f7dd6 11474#endif /* USE_XIM */
f5d11644
GM
11475}
11476
b9de836c 11477#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11478
11479
dc6f92b8 11480\f
2e365682
RS
11481/* Calculate the absolute position in frame F
11482 from its current recorded position values and gravity. */
11483
dfcf069d 11484void
43bca5d5 11485x_calc_absolute_position (f)
f676886a 11486 struct frame *f;
dc6f92b8 11487{
06a2c219 11488 Window child;
6dba1858 11489 int win_x = 0, win_y = 0;
7556890b 11490 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11491 int this_window;
11492
9829ddba
RS
11493 /* We have nothing to do if the current position
11494 is already for the top-left corner. */
11495 if (! ((flags & XNegative) || (flags & YNegative)))
11496 return;
11497
c81412a0 11498#ifdef USE_X_TOOLKIT
7556890b 11499 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11500#else
11501 this_window = FRAME_X_WINDOW (f);
11502#endif
6dba1858
RS
11503
11504 /* Find the position of the outside upper-left corner of
9829ddba
RS
11505 the inner window, with respect to the outer window.
11506 But do this only if we will need the results. */
7556890b 11507 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11508 {
9829ddba
RS
11509 int count;
11510
6dba1858 11511 BLOCK_INPUT;
9829ddba
RS
11512 count = x_catch_errors (FRAME_X_DISPLAY (f));
11513 while (1)
11514 {
11515 x_clear_errors (FRAME_X_DISPLAY (f));
11516 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11517
11518 /* From-window, to-window. */
11519 this_window,
11520 f->output_data.x->parent_desc,
11521
11522 /* From-position, to-position. */
11523 0, 0, &win_x, &win_y,
11524
11525 /* Child of win. */
11526 &child);
11527 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11528 {
11529 Window newroot, newparent = 0xdeadbeef;
11530 Window *newchildren;
2ebb2f8b 11531 unsigned int nchildren;
9829ddba
RS
11532
11533 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11534 &newparent, &newchildren, &nchildren))
11535 break;
58769bee 11536
7c3c78a3 11537 XFree ((char *) newchildren);
6dba1858 11538
9829ddba
RS
11539 f->output_data.x->parent_desc = newparent;
11540 }
11541 else
11542 break;
11543 }
6dba1858 11544
9829ddba 11545 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11546 UNBLOCK_INPUT;
11547 }
11548
11549 /* Treat negative positions as relative to the leftmost bottommost
11550 position that fits on the screen. */
20f55f9a 11551 if (flags & XNegative)
7556890b 11552 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11553 - 2 * f->output_data.x->border_width - win_x
11554 - PIXEL_WIDTH (f)
11555 + f->output_data.x->left_pos);
dc6f92b8 11556
20f55f9a 11557 if (flags & YNegative)
06a2c219
GM
11558 {
11559 int menubar_height = 0;
11560
11561#ifdef USE_X_TOOLKIT
11562 if (f->output_data.x->menubar_widget)
11563 menubar_height
11564 = (f->output_data.x->menubar_widget->core.height
11565 + f->output_data.x->menubar_widget->core.border_width);
11566#endif
11567
11568 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11569 - 2 * f->output_data.x->border_width
11570 - win_y
11571 - PIXEL_HEIGHT (f)
11572 - menubar_height
11573 + f->output_data.x->top_pos);
11574 }
2e365682 11575
3a35ab44
RS
11576 /* The left_pos and top_pos
11577 are now relative to the top and left screen edges,
11578 so the flags should correspond. */
7556890b 11579 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11580}
11581
3a35ab44
RS
11582/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11583 to really change the position, and 0 when calling from
11584 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11585 position values). It is -1 when calling from x_set_frame_parameters,
11586 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11587
dfcf069d 11588void
dc05a16b 11589x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11590 struct frame *f;
dc6f92b8 11591 register int xoff, yoff;
dc05a16b 11592 int change_gravity;
dc6f92b8 11593{
4a4cbdd5
KH
11594 int modified_top, modified_left;
11595
aa3ff7c9 11596 if (change_gravity > 0)
3a35ab44 11597 {
7556890b
RS
11598 f->output_data.x->top_pos = yoff;
11599 f->output_data.x->left_pos = xoff;
11600 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11601 if (xoff < 0)
7556890b 11602 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11603 if (yoff < 0)
7556890b
RS
11604 f->output_data.x->size_hint_flags |= YNegative;
11605 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11606 }
43bca5d5 11607 x_calc_absolute_position (f);
dc6f92b8
JB
11608
11609 BLOCK_INPUT;
c32cdd9a 11610 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11611
7556890b
RS
11612 modified_left = f->output_data.x->left_pos;
11613 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11614#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11615 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11616 /* It is a mystery why we need to add the border_width here
11617 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11618 if (change_gravity != 0)
4a4cbdd5 11619 {
7556890b
RS
11620 modified_left += f->output_data.x->border_width;
11621 modified_top += f->output_data.x->border_width;
4a4cbdd5 11622 }
e73ec6fa 11623#endif
4a4cbdd5 11624
3afe33e7 11625#ifdef USE_X_TOOLKIT
7556890b 11626 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11627 modified_left, modified_top);
3afe33e7 11628#else /* not USE_X_TOOLKIT */
334208b7 11629 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11630 modified_left, modified_top);
3afe33e7 11631#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11632 UNBLOCK_INPUT;
11633}
11634
bc20ebbf
FP
11635/* Call this to change the size of frame F's x-window.
11636 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11637 for this size change and subsequent size changes.
11638 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11639
dfcf069d 11640void
bc20ebbf 11641x_set_window_size (f, change_gravity, cols, rows)
f676886a 11642 struct frame *f;
bc20ebbf 11643 int change_gravity;
b1c884c3 11644 int cols, rows;
dc6f92b8 11645{
06a2c219 11646#ifndef USE_X_TOOLKIT
dc6f92b8 11647 int pixelwidth, pixelheight;
06a2c219 11648#endif
dc6f92b8 11649
80fd1fe2 11650 BLOCK_INPUT;
aee9a898
RS
11651
11652#ifdef USE_X_TOOLKIT
3a20653d
RS
11653 {
11654 /* The x and y position of the widget is clobbered by the
11655 call to XtSetValues within EmacsFrameSetCharSize.
11656 This is a real kludge, but I don't understand Xt so I can't
11657 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11658 int xpos = f->output_data.x->widget->core.x;
11659 int ypos = f->output_data.x->widget->core.y;
11660 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11661 f->output_data.x->widget->core.x = xpos;
11662 f->output_data.x->widget->core.y = ypos;
3a20653d 11663 }
80fd1fe2
FP
11664
11665#else /* not USE_X_TOOLKIT */
11666
b1c884c3 11667 check_frame_size (f, &rows, &cols);
7556890b 11668 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11669 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11670 ? 0
11671 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11672 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11673 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11674 f->output_data.x->flags_areas_extra
110859fc 11675 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11676 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11677 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11678
7556890b 11679 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11680 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11681
334208b7
RS
11682 XSync (FRAME_X_DISPLAY (f), False);
11683 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11684 pixelwidth, pixelheight);
b1c884c3
JB
11685
11686 /* Now, strictly speaking, we can't be sure that this is accurate,
11687 but the window manager will get around to dealing with the size
11688 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11689 ConfigureNotify event gets here.
11690
11691 We could just not bother storing any of this information here,
11692 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11693 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11694 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11695 point in the future when the ConfigureNotify event arrives.
11696
11697 We pass 1 for DELAY since we can't run Lisp code inside of
11698 a BLOCK_INPUT. */
7d1e984f 11699 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11700 PIXEL_WIDTH (f) = pixelwidth;
11701 PIXEL_HEIGHT (f) = pixelheight;
11702
aee9a898
RS
11703 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11704 receive in the ConfigureNotify event; if we get what we asked
11705 for, then the event won't cause the screen to become garbaged, so
11706 we have to make sure to do it here. */
11707 SET_FRAME_GARBAGED (f);
11708
11709 XFlush (FRAME_X_DISPLAY (f));
11710
11711#endif /* not USE_X_TOOLKIT */
11712
4d73d038 11713 /* If cursor was outside the new size, mark it as off. */
06a2c219 11714 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11715
aee9a898
RS
11716 /* Clear out any recollection of where the mouse highlighting was,
11717 since it might be in a place that's outside the new frame size.
11718 Actually checking whether it is outside is a pain in the neck,
11719 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11720 cancel_mouse_face (f);
dbc4e1c1 11721
dc6f92b8
JB
11722 UNBLOCK_INPUT;
11723}
dc6f92b8 11724\f
d047c4eb 11725/* Mouse warping. */
dc6f92b8 11726
9b378208 11727void
f676886a
JB
11728x_set_mouse_position (f, x, y)
11729 struct frame *f;
dc6f92b8
JB
11730 int x, y;
11731{
11732 int pix_x, pix_y;
11733
7556890b
RS
11734 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11735 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11736
11737 if (pix_x < 0) pix_x = 0;
11738 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11739
11740 if (pix_y < 0) pix_y = 0;
11741 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11742
11743 BLOCK_INPUT;
dc6f92b8 11744
334208b7
RS
11745 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11746 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11747 UNBLOCK_INPUT;
11748}
11749
9b378208
RS
11750/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11751
11752void
11753x_set_mouse_pixel_position (f, pix_x, pix_y)
11754 struct frame *f;
11755 int pix_x, pix_y;
11756{
11757 BLOCK_INPUT;
11758
334208b7
RS
11759 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11760 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11761 UNBLOCK_INPUT;
11762}
d047c4eb
KH
11763\f
11764/* focus shifting, raising and lowering. */
9b378208 11765
dfcf069d 11766void
f676886a
JB
11767x_focus_on_frame (f)
11768 struct frame *f;
dc6f92b8 11769{
1fb20991 11770#if 0 /* This proves to be unpleasant. */
f676886a 11771 x_raise_frame (f);
1fb20991 11772#endif
6d4238f3
JB
11773#if 0
11774 /* I don't think that the ICCCM allows programs to do things like this
11775 without the interaction of the window manager. Whatever you end up
f676886a 11776 doing with this code, do it to x_unfocus_frame too. */
334208b7 11777 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11778 RevertToPointerRoot, CurrentTime);
c118dd06 11779#endif /* ! 0 */
dc6f92b8
JB
11780}
11781
dfcf069d 11782void
f676886a
JB
11783x_unfocus_frame (f)
11784 struct frame *f;
dc6f92b8 11785{
6d4238f3 11786#if 0
f676886a 11787 /* Look at the remarks in x_focus_on_frame. */
0f941935 11788 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11789 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11790 RevertToPointerRoot, CurrentTime);
c118dd06 11791#endif /* ! 0 */
dc6f92b8
JB
11792}
11793
f676886a 11794/* Raise frame F. */
dc6f92b8 11795
dfcf069d 11796void
f676886a
JB
11797x_raise_frame (f)
11798 struct frame *f;
dc6f92b8 11799{
3a88c238 11800 if (f->async_visible)
dc6f92b8
JB
11801 {
11802 BLOCK_INPUT;
3afe33e7 11803#ifdef USE_X_TOOLKIT
7556890b 11804 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11805#else /* not USE_X_TOOLKIT */
334208b7 11806 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11807#endif /* not USE_X_TOOLKIT */
334208b7 11808 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11809 UNBLOCK_INPUT;
11810 }
11811}
11812
f676886a 11813/* Lower frame F. */
dc6f92b8 11814
dfcf069d 11815void
f676886a
JB
11816x_lower_frame (f)
11817 struct frame *f;
dc6f92b8 11818{
3a88c238 11819 if (f->async_visible)
dc6f92b8
JB
11820 {
11821 BLOCK_INPUT;
3afe33e7 11822#ifdef USE_X_TOOLKIT
7556890b 11823 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11824#else /* not USE_X_TOOLKIT */
334208b7 11825 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11826#endif /* not USE_X_TOOLKIT */
334208b7 11827 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11828 UNBLOCK_INPUT;
11829 }
11830}
11831
dbc4e1c1 11832static void
6b0442dc 11833XTframe_raise_lower (f, raise_flag)
dbc4e1c1 11834 FRAME_PTR f;
6b0442dc 11835 int raise_flag;
dbc4e1c1 11836{
6b0442dc 11837 if (raise_flag)
dbc4e1c1
JB
11838 x_raise_frame (f);
11839 else
11840 x_lower_frame (f);
11841}
d047c4eb
KH
11842\f
11843/* Change of visibility. */
dc6f92b8 11844
9382638d
KH
11845/* This tries to wait until the frame is really visible.
11846 However, if the window manager asks the user where to position
11847 the frame, this will return before the user finishes doing that.
11848 The frame will not actually be visible at that time,
11849 but it will become visible later when the window manager
11850 finishes with it. */
11851
dfcf069d 11852void
f676886a
JB
11853x_make_frame_visible (f)
11854 struct frame *f;
dc6f92b8 11855{
990ba854 11856 Lisp_Object type;
1aa6072f 11857 int original_top, original_left;
dc6f92b8 11858
dc6f92b8 11859 BLOCK_INPUT;
dc6f92b8 11860
990ba854
RS
11861 type = x_icon_type (f);
11862 if (!NILP (type))
11863 x_bitmap_icon (f, type);
bdcd49ba 11864
f676886a 11865 if (! FRAME_VISIBLE_P (f))
90e65f07 11866 {
1aa6072f
RS
11867 /* We test FRAME_GARBAGED_P here to make sure we don't
11868 call x_set_offset a second time
11869 if we get to x_make_frame_visible a second time
11870 before the window gets really visible. */
11871 if (! FRAME_ICONIFIED_P (f)
11872 && ! f->output_data.x->asked_for_visible)
11873 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11874
11875 f->output_data.x->asked_for_visible = 1;
11876
90e65f07 11877 if (! EQ (Vx_no_window_manager, Qt))
f676886a 11878 x_wm_set_window_state (f, NormalState);
3afe33e7 11879#ifdef USE_X_TOOLKIT
d7a38a2e 11880 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11881 XtMapWidget (f->output_data.x->widget);
3afe33e7 11882#else /* not USE_X_TOOLKIT */
7f9c7f94 11883 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11884#endif /* not USE_X_TOOLKIT */
0134a210
RS
11885#if 0 /* This seems to bring back scroll bars in the wrong places
11886 if the window configuration has changed. They seem
11887 to come back ok without this. */
ab648270 11888 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 11889 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 11890#endif
90e65f07 11891 }
dc6f92b8 11892
334208b7 11893 XFlush (FRAME_X_DISPLAY (f));
90e65f07 11894
0dacf791
RS
11895 /* Synchronize to ensure Emacs knows the frame is visible
11896 before we do anything else. We do this loop with input not blocked
11897 so that incoming events are handled. */
11898 {
11899 Lisp_Object frame;
12ce2351 11900 int count;
28c01ffe
RS
11901 /* This must be before UNBLOCK_INPUT
11902 since events that arrive in response to the actions above
11903 will set it when they are handled. */
11904 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
11905
11906 original_left = f->output_data.x->left_pos;
11907 original_top = f->output_data.x->top_pos;
c0a04927
RS
11908
11909 /* This must come after we set COUNT. */
11910 UNBLOCK_INPUT;
11911
2745e6c4 11912 /* We unblock here so that arriving X events are processed. */
1aa6072f 11913
dcb07ae9
RS
11914 /* Now move the window back to where it was "supposed to be".
11915 But don't do it if the gravity is negative.
11916 When the gravity is negative, this uses a position
28c01ffe
RS
11917 that is 3 pixels too low. Perhaps that's really the border width.
11918
11919 Don't do this if the window has never been visible before,
11920 because the window manager may choose the position
11921 and we don't want to override it. */
1aa6072f 11922
4d3f5d9a 11923 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 11924 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 11925 && previously_visible)
1aa6072f 11926 {
2745e6c4
RS
11927 Drawable rootw;
11928 int x, y;
11929 unsigned int width, height, border, depth;
06a2c219 11930
1aa6072f 11931 BLOCK_INPUT;
9829ddba 11932
06a2c219
GM
11933 /* On some window managers (such as FVWM) moving an existing
11934 window, even to the same place, causes the window manager
11935 to introduce an offset. This can cause the window to move
11936 to an unexpected location. Check the geometry (a little
11937 slow here) and then verify that the window is in the right
11938 place. If the window is not in the right place, move it
11939 there, and take the potential window manager hit. */
2745e6c4
RS
11940 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11941 &rootw, &x, &y, &width, &height, &border, &depth);
11942
11943 if (original_left != x || original_top != y)
11944 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11945 original_left, original_top);
11946
1aa6072f
RS
11947 UNBLOCK_INPUT;
11948 }
9829ddba 11949
e0c1aef2 11950 XSETFRAME (frame, f);
c0a04927 11951
12ce2351
GM
11952 /* Wait until the frame is visible. Process X events until a
11953 MapNotify event has been seen, or until we think we won't get a
11954 MapNotify at all.. */
11955 for (count = input_signal_count + 10;
11956 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 11957 {
12ce2351 11958 /* Force processing of queued events. */
334208b7 11959 x_sync (f);
12ce2351
GM
11960
11961 /* Machines that do polling rather than SIGIO have been
11962 observed to go into a busy-wait here. So we'll fake an
11963 alarm signal to let the handler know that there's something
11964 to be read. We used to raise a real alarm, but it seems
11965 that the handler isn't always enabled here. This is
11966 probably a bug. */
8b2f8d4e 11967 if (input_polling_used ())
3b2fa4e6 11968 {
12ce2351
GM
11969 /* It could be confusing if a real alarm arrives while
11970 processing the fake one. Turn it off and let the
11971 handler reset it. */
3e71d8f2 11972 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
11973 int old_poll_suppress_count = poll_suppress_count;
11974 poll_suppress_count = 1;
11975 poll_for_input_1 ();
11976 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 11977 }
12ce2351
GM
11978
11979 /* See if a MapNotify event has been processed. */
11980 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 11981 }
0dacf791 11982 }
dc6f92b8
JB
11983}
11984
06a2c219 11985/* Change from mapped state to withdrawn state. */
dc6f92b8 11986
d047c4eb
KH
11987/* Make the frame visible (mapped and not iconified). */
11988
dfcf069d 11989void
f676886a
JB
11990x_make_frame_invisible (f)
11991 struct frame *f;
dc6f92b8 11992{
546e6d5b
RS
11993 Window window;
11994
11995#ifdef USE_X_TOOLKIT
11996 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11997 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11998#else /* not USE_X_TOOLKIT */
11999 window = FRAME_X_WINDOW (f);
12000#endif /* not USE_X_TOOLKIT */
dc6f92b8 12001
9319ae23 12002 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12003 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12004 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12005
5627c40e 12006#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 12007 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 12008 return;
5627c40e 12009#endif
dc6f92b8
JB
12010
12011 BLOCK_INPUT;
c118dd06 12012
af31d76f
RS
12013 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
12014 that the current position of the window is user-specified, rather than
12015 program-specified, so that when the window is mapped again, it will be
12016 placed at the same location, without forcing the user to position it
12017 by hand again (they have already done that once for this window.) */
c32cdd9a 12018 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 12019
c118dd06
JB
12020#ifdef HAVE_X11R4
12021
334208b7
RS
12022 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
12023 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
12024 {
12025 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12026 error ("Can't notify window manager of window withdrawal");
c118dd06 12027 }
c118dd06 12028#else /* ! defined (HAVE_X11R4) */
16bd92ea 12029
c118dd06 12030 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
12031 if (! EQ (Vx_no_window_manager, Qt))
12032 {
16bd92ea 12033 XEvent unmap;
dc6f92b8 12034
16bd92ea 12035 unmap.xunmap.type = UnmapNotify;
546e6d5b 12036 unmap.xunmap.window = window;
334208b7 12037 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 12038 unmap.xunmap.from_configure = False;
334208b7
RS
12039 if (! XSendEvent (FRAME_X_DISPLAY (f),
12040 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 12041 False,
06a2c219 12042 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
12043 &unmap))
12044 {
12045 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12046 error ("Can't notify window manager of withdrawal");
16bd92ea 12047 }
dc6f92b8
JB
12048 }
12049
16bd92ea 12050 /* Unmap the window ourselves. Cheeky! */
334208b7 12051 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 12052#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 12053
5627c40e
RS
12054 /* We can't distinguish this from iconification
12055 just by the event that we get from the server.
12056 So we can't win using the usual strategy of letting
12057 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
12058 and synchronize with the server to make sure we agree. */
12059 f->visible = 0;
12060 FRAME_ICONIFIED_P (f) = 0;
12061 f->async_visible = 0;
12062 f->async_iconified = 0;
12063
334208b7 12064 x_sync (f);
5627c40e 12065
dc6f92b8
JB
12066 UNBLOCK_INPUT;
12067}
12068
06a2c219 12069/* Change window state from mapped to iconified. */
dc6f92b8 12070
dfcf069d 12071void
f676886a
JB
12072x_iconify_frame (f)
12073 struct frame *f;
dc6f92b8 12074{
3afe33e7 12075 int result;
990ba854 12076 Lisp_Object type;
dc6f92b8 12077
9319ae23 12078 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
12079 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
12080 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 12081
3a88c238 12082 if (f->async_iconified)
dc6f92b8
JB
12083 return;
12084
3afe33e7 12085 BLOCK_INPUT;
546e6d5b 12086
9af3143a
RS
12087 FRAME_SAMPLE_VISIBILITY (f);
12088
990ba854
RS
12089 type = x_icon_type (f);
12090 if (!NILP (type))
12091 x_bitmap_icon (f, type);
bdcd49ba
RS
12092
12093#ifdef USE_X_TOOLKIT
12094
546e6d5b
RS
12095 if (! FRAME_VISIBLE_P (f))
12096 {
12097 if (! EQ (Vx_no_window_manager, Qt))
12098 x_wm_set_window_state (f, IconicState);
12099 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 12100 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
12101 /* The server won't give us any event to indicate
12102 that an invisible frame was changed to an icon,
12103 so we have to record it here. */
12104 f->iconified = 1;
1e6bc770 12105 f->visible = 1;
9cf30a30 12106 f->async_iconified = 1;
1e6bc770 12107 f->async_visible = 0;
546e6d5b
RS
12108 UNBLOCK_INPUT;
12109 return;
12110 }
12111
334208b7 12112 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 12113 XtWindow (f->output_data.x->widget),
334208b7 12114 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
12115 UNBLOCK_INPUT;
12116
12117 if (!result)
546e6d5b 12118 error ("Can't notify window manager of iconification");
3afe33e7
RS
12119
12120 f->async_iconified = 1;
1e6bc770
RS
12121 f->async_visible = 0;
12122
8c002a25
KH
12123
12124 BLOCK_INPUT;
334208b7 12125 XFlush (FRAME_X_DISPLAY (f));
8c002a25 12126 UNBLOCK_INPUT;
3afe33e7
RS
12127#else /* not USE_X_TOOLKIT */
12128
fd13dbb2
RS
12129 /* Make sure the X server knows where the window should be positioned,
12130 in case the user deiconifies with the window manager. */
12131 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 12132 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 12133
16bd92ea
JB
12134 /* Since we don't know which revision of X we're running, we'll use both
12135 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
12136
12137 /* X11R4: send a ClientMessage to the window manager using the
12138 WM_CHANGE_STATE type. */
12139 {
12140 XEvent message;
58769bee 12141
c118dd06 12142 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 12143 message.xclient.type = ClientMessage;
334208b7 12144 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
12145 message.xclient.format = 32;
12146 message.xclient.data.l[0] = IconicState;
12147
334208b7
RS
12148 if (! XSendEvent (FRAME_X_DISPLAY (f),
12149 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
12150 False,
12151 SubstructureRedirectMask | SubstructureNotifyMask,
12152 &message))
dc6f92b8
JB
12153 {
12154 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12155 error ("Can't notify window manager of iconification");
dc6f92b8 12156 }
16bd92ea 12157 }
dc6f92b8 12158
58769bee 12159 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
12160 IconicState. */
12161 x_wm_set_window_state (f, IconicState);
dc6f92b8 12162
a9c00105
RS
12163 if (!FRAME_VISIBLE_P (f))
12164 {
12165 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 12166 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
12167 }
12168
3a88c238 12169 f->async_iconified = 1;
1e6bc770 12170 f->async_visible = 0;
dc6f92b8 12171
334208b7 12172 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 12173 UNBLOCK_INPUT;
8c002a25 12174#endif /* not USE_X_TOOLKIT */
dc6f92b8 12175}
d047c4eb 12176\f
c0ff3fab 12177/* Destroy the X window of frame F. */
dc6f92b8 12178
dfcf069d 12179void
c0ff3fab 12180x_destroy_window (f)
f676886a 12181 struct frame *f;
dc6f92b8 12182{
7f9c7f94
RS
12183 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12184
dc6f92b8 12185 BLOCK_INPUT;
c0ff3fab 12186
6186a4a0
RS
12187 /* If a display connection is dead, don't try sending more
12188 commands to the X server. */
12189 if (dpyinfo->display != 0)
12190 {
12191 if (f->output_data.x->icon_desc != 0)
12192 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 12193#ifdef HAVE_X_I18N
f5d11644
GM
12194 if (FRAME_XIC (f))
12195 free_frame_xic (f);
31f41daf 12196#endif
6186a4a0 12197 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 12198#ifdef USE_X_TOOLKIT
06a2c219
GM
12199 if (f->output_data.x->widget)
12200 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12201 free_frame_menubar (f);
3afe33e7
RS
12202#endif /* USE_X_TOOLKIT */
12203
3e71d8f2
GM
12204 unload_color (f, f->output_data.x->foreground_pixel);
12205 unload_color (f, f->output_data.x->background_pixel);
12206 unload_color (f, f->output_data.x->cursor_pixel);
12207 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12208 unload_color (f, f->output_data.x->border_pixel);
12209 unload_color (f, f->output_data.x->mouse_pixel);
12210 if (f->output_data.x->scroll_bar_background_pixel != -1)
12211 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12212 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12213 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12214 if (f->output_data.x->white_relief.allocated_p)
12215 unload_color (f, f->output_data.x->white_relief.pixel);
12216 if (f->output_data.x->black_relief.allocated_p)
12217 unload_color (f, f->output_data.x->black_relief.pixel);
12218
6186a4a0
RS
12219 free_frame_faces (f);
12220 XFlush (FRAME_X_DISPLAY (f));
12221 }
dc6f92b8 12222
df89d8a4 12223 if (f->output_data.x->saved_menu_event)
06a2c219 12224 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12225
7556890b
RS
12226 xfree (f->output_data.x);
12227 f->output_data.x = 0;
0f941935
KH
12228 if (f == dpyinfo->x_focus_frame)
12229 dpyinfo->x_focus_frame = 0;
12230 if (f == dpyinfo->x_focus_event_frame)
12231 dpyinfo->x_focus_event_frame = 0;
12232 if (f == dpyinfo->x_highlight_frame)
12233 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12234
7f9c7f94
RS
12235 dpyinfo->reference_count--;
12236
12237 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12238 {
7f9c7f94
RS
12239 dpyinfo->mouse_face_beg_row
12240 = dpyinfo->mouse_face_beg_col = -1;
12241 dpyinfo->mouse_face_end_row
12242 = dpyinfo->mouse_face_end_col = -1;
12243 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12244 dpyinfo->mouse_face_deferred_gc = 0;
12245 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12246 }
0134a210 12247
c0ff3fab 12248 UNBLOCK_INPUT;
dc6f92b8
JB
12249}
12250\f
f451eb13
JB
12251/* Setting window manager hints. */
12252
af31d76f
RS
12253/* Set the normal size hints for the window manager, for frame F.
12254 FLAGS is the flags word to use--or 0 meaning preserve the flags
12255 that the window now has.
12256 If USER_POSITION is nonzero, we set the USPosition
12257 flag (this is useful when FLAGS is 0). */
6dba1858 12258
dfcf069d 12259void
af31d76f 12260x_wm_set_size_hint (f, flags, user_position)
f676886a 12261 struct frame *f;
af31d76f
RS
12262 long flags;
12263 int user_position;
dc6f92b8
JB
12264{
12265 XSizeHints size_hints;
3afe33e7
RS
12266
12267#ifdef USE_X_TOOLKIT
7e4f2521
FP
12268 Arg al[2];
12269 int ac = 0;
12270 Dimension widget_width, widget_height;
7556890b 12271 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12272#else /* not USE_X_TOOLKIT */
c118dd06 12273 Window window = FRAME_X_WINDOW (f);
3afe33e7 12274#endif /* not USE_X_TOOLKIT */
dc6f92b8 12275
b72a58fd
RS
12276 /* Setting PMaxSize caused various problems. */
12277 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12278
7556890b
RS
12279 size_hints.x = f->output_data.x->left_pos;
12280 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12281
7e4f2521
FP
12282#ifdef USE_X_TOOLKIT
12283 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12284 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12285 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12286 size_hints.height = widget_height;
12287 size_hints.width = widget_width;
12288#else /* not USE_X_TOOLKIT */
f676886a
JB
12289 size_hints.height = PIXEL_HEIGHT (f);
12290 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12291#endif /* not USE_X_TOOLKIT */
7553a6b7 12292
7556890b
RS
12293 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12294 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12295 size_hints.max_width
12296 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12297 size_hints.max_height
12298 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12299
d067ea8b
KH
12300 /* Calculate the base and minimum sizes.
12301
12302 (When we use the X toolkit, we don't do it here.
12303 Instead we copy the values that the widgets are using, below.) */
12304#ifndef USE_X_TOOLKIT
b1c884c3 12305 {
b0342f17 12306 int base_width, base_height;
0134a210 12307 int min_rows = 0, min_cols = 0;
b0342f17 12308
f451eb13
JB
12309 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12310 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12311
0134a210 12312 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12313
0134a210
RS
12314 /* The window manager uses the base width hints to calculate the
12315 current number of rows and columns in the frame while
12316 resizing; min_width and min_height aren't useful for this
12317 purpose, since they might not give the dimensions for a
12318 zero-row, zero-column frame.
58769bee 12319
0134a210
RS
12320 We use the base_width and base_height members if we have
12321 them; otherwise, we set the min_width and min_height members
12322 to the size for a zero x zero frame. */
b0342f17
JB
12323
12324#ifdef HAVE_X11R4
0134a210
RS
12325 size_hints.flags |= PBaseSize;
12326 size_hints.base_width = base_width;
12327 size_hints.base_height = base_height;
12328 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12329 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12330#else
0134a210
RS
12331 size_hints.min_width = base_width;
12332 size_hints.min_height = base_height;
b0342f17 12333#endif
b1c884c3 12334 }
dc6f92b8 12335
d067ea8b 12336 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12337 if (flags)
dc6f92b8 12338 {
d067ea8b
KH
12339 size_hints.flags |= flags;
12340 goto no_read;
12341 }
12342#endif /* not USE_X_TOOLKIT */
12343
12344 {
12345 XSizeHints hints; /* Sometimes I hate X Windows... */
12346 long supplied_return;
12347 int value;
af31d76f
RS
12348
12349#ifdef HAVE_X11R4
d067ea8b
KH
12350 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12351 &supplied_return);
af31d76f 12352#else
d067ea8b 12353 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12354#endif
58769bee 12355
d067ea8b
KH
12356#ifdef USE_X_TOOLKIT
12357 size_hints.base_height = hints.base_height;
12358 size_hints.base_width = hints.base_width;
12359 size_hints.min_height = hints.min_height;
12360 size_hints.min_width = hints.min_width;
12361#endif
12362
12363 if (flags)
12364 size_hints.flags |= flags;
12365 else
12366 {
12367 if (value == 0)
12368 hints.flags = 0;
12369 if (hints.flags & PSize)
12370 size_hints.flags |= PSize;
12371 if (hints.flags & PPosition)
12372 size_hints.flags |= PPosition;
12373 if (hints.flags & USPosition)
12374 size_hints.flags |= USPosition;
12375 if (hints.flags & USSize)
12376 size_hints.flags |= USSize;
12377 }
12378 }
12379
06a2c219 12380#ifndef USE_X_TOOLKIT
d067ea8b 12381 no_read:
06a2c219 12382#endif
0134a210 12383
af31d76f 12384#ifdef PWinGravity
7556890b 12385 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12386 size_hints.flags |= PWinGravity;
dc05a16b 12387
af31d76f 12388 if (user_position)
6dba1858 12389 {
af31d76f
RS
12390 size_hints.flags &= ~ PPosition;
12391 size_hints.flags |= USPosition;
6dba1858 12392 }
2554751d 12393#endif /* PWinGravity */
6dba1858 12394
b0342f17 12395#ifdef HAVE_X11R4
334208b7 12396 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12397#else
334208b7 12398 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12399#endif
dc6f92b8
JB
12400}
12401
12402/* Used for IconicState or NormalState */
06a2c219 12403
dfcf069d 12404void
f676886a
JB
12405x_wm_set_window_state (f, state)
12406 struct frame *f;
dc6f92b8
JB
12407 int state;
12408{
3afe33e7 12409#ifdef USE_X_TOOLKIT
546e6d5b
RS
12410 Arg al[1];
12411
12412 XtSetArg (al[0], XtNinitialState, state);
7556890b 12413 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12414#else /* not USE_X_TOOLKIT */
c118dd06 12415 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12416
7556890b
RS
12417 f->output_data.x->wm_hints.flags |= StateHint;
12418 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12419
7556890b 12420 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12421#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12422}
12423
dfcf069d 12424void
7f2ae036 12425x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12426 struct frame *f;
7f2ae036 12427 int pixmap_id;
dc6f92b8 12428{
d2bd6bc4
RS
12429 Pixmap icon_pixmap;
12430
06a2c219 12431#ifndef USE_X_TOOLKIT
c118dd06 12432 Window window = FRAME_X_WINDOW (f);
75231bad 12433#endif
dc6f92b8 12434
7f2ae036 12435 if (pixmap_id > 0)
dbc4e1c1 12436 {
d2bd6bc4 12437 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12438 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12439 }
12440 else
68568555
RS
12441 {
12442 /* It seems there is no way to turn off use of an icon pixmap.
12443 The following line does it, only if no icon has yet been created,
12444 for some window managers. But with mwm it crashes.
12445 Some people say it should clear the IconPixmapHint bit in this case,
12446 but that doesn't work, and the X consortium said it isn't the
12447 right thing at all. Since there is no way to win,
12448 best to explicitly give up. */
12449#if 0
12450 f->output_data.x->wm_hints.icon_pixmap = None;
12451#else
12452 return;
12453#endif
12454 }
b1c884c3 12455
d2bd6bc4
RS
12456#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12457
12458 {
12459 Arg al[1];
12460 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12461 XtSetValues (f->output_data.x->widget, al, 1);
12462 }
12463
12464#else /* not USE_X_TOOLKIT */
12465
7556890b
RS
12466 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12467 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12468
12469#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12470}
12471
dfcf069d 12472void
f676886a
JB
12473x_wm_set_icon_position (f, icon_x, icon_y)
12474 struct frame *f;
dc6f92b8
JB
12475 int icon_x, icon_y;
12476{
75231bad 12477#ifdef USE_X_TOOLKIT
7556890b 12478 Window window = XtWindow (f->output_data.x->widget);
75231bad 12479#else
c118dd06 12480 Window window = FRAME_X_WINDOW (f);
75231bad 12481#endif
dc6f92b8 12482
7556890b
RS
12483 f->output_data.x->wm_hints.flags |= IconPositionHint;
12484 f->output_data.x->wm_hints.icon_x = icon_x;
12485 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12486
7556890b 12487 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12488}
12489
12490\f
06a2c219
GM
12491/***********************************************************************
12492 Fonts
12493 ***********************************************************************/
dc43ef94
KH
12494
12495/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12496
dc43ef94
KH
12497struct font_info *
12498x_get_font_info (f, font_idx)
12499 FRAME_PTR f;
12500 int font_idx;
12501{
12502 return (FRAME_X_FONT_TABLE (f) + font_idx);
12503}
12504
12505
12506/* Return a list of names of available fonts matching PATTERN on frame
12507 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12508 to be listed. Frame F NULL means we have not yet created any
12509 frame on X, and consult the first display in x_display_list.
12510 MAXNAMES sets a limit on how many fonts to match. */
12511
12512Lisp_Object
12513x_list_fonts (f, pattern, size, maxnames)
12514 FRAME_PTR f;
12515 Lisp_Object pattern;
12516 int size;
12517 int maxnames;
12518{
06a2c219
GM
12519 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12520 Lisp_Object tem, second_best;
dc43ef94 12521 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12522 int try_XLoadQueryFont = 0;
53ca4657 12523 int count;
dc43ef94 12524
6b0efe73 12525 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12526 if (NILP (patterns))
12527 patterns = Fcons (pattern, Qnil);
81ba44e5 12528
09c6077f
KH
12529 if (maxnames == 1 && !size)
12530 /* We can return any single font matching PATTERN. */
12531 try_XLoadQueryFont = 1;
9a32686f 12532
8e713be6 12533 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12534 {
dc43ef94 12535 int num_fonts;
3e71d8f2 12536 char **names = NULL;
dc43ef94 12537
8e713be6 12538 pattern = XCAR (patterns);
536f4067
RS
12539 /* See if we cached the result for this particular query.
12540 The cache is an alist of the form:
12541 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12542 */
8e713be6 12543 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12544 key = Fcons (pattern, make_number (maxnames)),
12545 !NILP (list = Fassoc (key, tem))))
12546 {
12547 list = Fcdr_safe (list);
12548 /* We have a cashed list. Don't have to get the list again. */
12549 goto label_cached;
12550 }
12551
12552 /* At first, put PATTERN in the cache. */
09c6077f 12553
dc43ef94 12554 BLOCK_INPUT;
17d85edc
KH
12555 count = x_catch_errors (dpy);
12556
09c6077f
KH
12557 if (try_XLoadQueryFont)
12558 {
12559 XFontStruct *font;
12560 unsigned long value;
12561
12562 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12563 if (x_had_errors_p (dpy))
12564 {
12565 /* This error is perhaps due to insufficient memory on X
12566 server. Let's just ignore it. */
12567 font = NULL;
12568 x_clear_errors (dpy);
12569 }
12570
09c6077f
KH
12571 if (font
12572 && XGetFontProperty (font, XA_FONT, &value))
12573 {
12574 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12575 int len = strlen (name);
01c752b5 12576 char *tmp;
09c6077f 12577
6f6512e8
KH
12578 /* If DXPC (a Differential X Protocol Compressor)
12579 Ver.3.7 is running, XGetAtomName will return null
12580 string. We must avoid such a name. */
12581 if (len == 0)
12582 try_XLoadQueryFont = 0;
12583 else
12584 {
12585 num_fonts = 1;
12586 names = (char **) alloca (sizeof (char *));
12587 /* Some systems only allow alloca assigned to a
12588 simple var. */
12589 tmp = (char *) alloca (len + 1); names[0] = tmp;
12590 bcopy (name, names[0], len + 1);
12591 XFree (name);
12592 }
09c6077f
KH
12593 }
12594 else
12595 try_XLoadQueryFont = 0;
a083fd23
RS
12596
12597 if (font)
12598 XFreeFont (dpy, font);
09c6077f
KH
12599 }
12600
12601 if (!try_XLoadQueryFont)
17d85edc
KH
12602 {
12603 /* We try at least 10 fonts because XListFonts will return
12604 auto-scaled fonts at the head. */
12605 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12606 &num_fonts);
12607 if (x_had_errors_p (dpy))
12608 {
12609 /* This error is perhaps due to insufficient memory on X
12610 server. Let's just ignore it. */
12611 names = NULL;
12612 x_clear_errors (dpy);
12613 }
12614 }
12615
12616 x_uncatch_errors (dpy, count);
dc43ef94
KH
12617 UNBLOCK_INPUT;
12618
12619 if (names)
12620 {
12621 int i;
dc43ef94
KH
12622
12623 /* Make a list of all the fonts we got back.
12624 Store that in the font cache for the display. */
12625 for (i = 0; i < num_fonts; i++)
12626 {
06a2c219 12627 int width = 0;
dc43ef94 12628 char *p = names[i];
06a2c219
GM
12629 int average_width = -1, dashes = 0;
12630
dc43ef94 12631 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12632 14 dashes, and the field value following 12th dash
12633 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12634 is usually too ugly to be used for editing. Let's
12635 ignore it. */
dc43ef94
KH
12636 while (*p)
12637 if (*p++ == '-')
12638 {
12639 dashes++;
12640 if (dashes == 7) /* PIXEL_SIZE field */
12641 width = atoi (p);
12642 else if (dashes == 12) /* AVERAGE_WIDTH field */
12643 average_width = atoi (p);
12644 }
12645 if (dashes < 14 || average_width != 0)
12646 {
12647 tem = build_string (names[i]);
12648 if (NILP (Fassoc (tem, list)))
12649 {
12650 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12651 && ((fast_c_string_match_ignore_case
12652 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12653 >= 0))
12654 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12655 width of this font. */
dc43ef94
KH
12656 list = Fcons (Fcons (tem, make_number (width)), list);
12657 else
12658 /* For the moment, width is not known. */
12659 list = Fcons (Fcons (tem, Qnil), list);
12660 }
12661 }
12662 }
09c6077f
KH
12663 if (!try_XLoadQueryFont)
12664 XFreeFontNames (names);
dc43ef94
KH
12665 }
12666
b5210ea7 12667 /* Now store the result in the cache. */
dc43ef94 12668 if (f != NULL)
8e713be6 12669 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12670 = Fcons (Fcons (key, list),
8e713be6 12671 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12672
b5210ea7
KH
12673 label_cached:
12674 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12675
b5210ea7
KH
12676 newlist = second_best = Qnil;
12677 /* Make a list of the fonts that have the right width. */
8e713be6 12678 for (; CONSP (list); list = XCDR (list))
b5210ea7 12679 {
536f4067
RS
12680 int found_size;
12681
8e713be6 12682 tem = XCAR (list);
dc43ef94 12683
8e713be6 12684 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12685 continue;
12686 if (!size)
12687 {
8e713be6 12688 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12689 continue;
12690 }
dc43ef94 12691
8e713be6 12692 if (!INTEGERP (XCDR (tem)))
dc43ef94 12693 {
b5210ea7
KH
12694 /* Since we have not yet known the size of this font, we
12695 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12696 XFontStruct *thisinfo;
12697
12698 BLOCK_INPUT;
17d85edc 12699 count = x_catch_errors (dpy);
dc43ef94 12700 thisinfo = XLoadQueryFont (dpy,
8e713be6 12701 XSTRING (XCAR (tem))->data);
17d85edc
KH
12702 if (x_had_errors_p (dpy))
12703 {
12704 /* This error is perhaps due to insufficient memory on X
12705 server. Let's just ignore it. */
12706 thisinfo = NULL;
12707 x_clear_errors (dpy);
12708 }
12709 x_uncatch_errors (dpy, count);
dc43ef94
KH
12710 UNBLOCK_INPUT;
12711
12712 if (thisinfo)
12713 {
8e713be6 12714 XCDR (tem)
536f4067
RS
12715 = (thisinfo->min_bounds.width == 0
12716 ? make_number (0)
12717 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12718 XFreeFont (dpy, thisinfo);
12719 }
12720 else
b5210ea7 12721 /* For unknown reason, the previous call of XListFont had
06a2c219 12722 returned a font which can't be opened. Record the size
b5210ea7 12723 as 0 not to try to open it again. */
8e713be6 12724 XCDR (tem) = make_number (0);
dc43ef94 12725 }
536f4067 12726
8e713be6 12727 found_size = XINT (XCDR (tem));
536f4067 12728 if (found_size == size)
8e713be6 12729 newlist = Fcons (XCAR (tem), newlist);
536f4067 12730 else if (found_size > 0)
b5210ea7 12731 {
536f4067 12732 if (NILP (second_best))
b5210ea7 12733 second_best = tem;
536f4067
RS
12734 else if (found_size < size)
12735 {
8e713be6
KR
12736 if (XINT (XCDR (second_best)) > size
12737 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12738 second_best = tem;
12739 }
12740 else
12741 {
8e713be6
KR
12742 if (XINT (XCDR (second_best)) > size
12743 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12744 second_best = tem;
12745 }
b5210ea7
KH
12746 }
12747 }
12748 if (!NILP (newlist))
12749 break;
12750 else if (!NILP (second_best))
12751 {
8e713be6 12752 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12753 break;
dc43ef94 12754 }
dc43ef94
KH
12755 }
12756
12757 return newlist;
12758}
12759
06a2c219
GM
12760
12761#if GLYPH_DEBUG
12762
12763/* Check that FONT is valid on frame F. It is if it can be found in F's
12764 font table. */
12765
12766static void
12767x_check_font (f, font)
12768 struct frame *f;
12769 XFontStruct *font;
12770{
12771 int i;
12772 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12773
12774 xassert (font != NULL);
12775
12776 for (i = 0; i < dpyinfo->n_fonts; i++)
12777 if (dpyinfo->font_table[i].name
12778 && font == dpyinfo->font_table[i].font)
12779 break;
12780
12781 xassert (i < dpyinfo->n_fonts);
12782}
12783
12784#endif /* GLYPH_DEBUG != 0 */
12785
12786/* Set *W to the minimum width, *H to the minimum font height of FONT.
12787 Note: There are (broken) X fonts out there with invalid XFontStruct
12788 min_bounds contents. For example, handa@etl.go.jp reports that
12789 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12790 have font->min_bounds.width == 0. */
12791
12792static INLINE void
12793x_font_min_bounds (font, w, h)
12794 XFontStruct *font;
12795 int *w, *h;
12796{
12797 *h = FONT_HEIGHT (font);
12798 *w = font->min_bounds.width;
12799
12800 /* Try to handle the case where FONT->min_bounds has invalid
12801 contents. Since the only font known to have invalid min_bounds
12802 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12803 if (*w <= 0)
12804 *w = font->max_bounds.width;
12805}
12806
12807
12808/* Compute the smallest character width and smallest font height over
12809 all fonts available on frame F. Set the members smallest_char_width
12810 and smallest_font_height in F's x_display_info structure to
12811 the values computed. Value is non-zero if smallest_font_height or
12812 smallest_char_width become smaller than they were before. */
12813
12814static int
12815x_compute_min_glyph_bounds (f)
12816 struct frame *f;
12817{
12818 int i;
12819 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12820 XFontStruct *font;
12821 int old_width = dpyinfo->smallest_char_width;
12822 int old_height = dpyinfo->smallest_font_height;
12823
12824 dpyinfo->smallest_font_height = 100000;
12825 dpyinfo->smallest_char_width = 100000;
12826
12827 for (i = 0; i < dpyinfo->n_fonts; ++i)
12828 if (dpyinfo->font_table[i].name)
12829 {
12830 struct font_info *fontp = dpyinfo->font_table + i;
12831 int w, h;
12832
12833 font = (XFontStruct *) fontp->font;
12834 xassert (font != (XFontStruct *) ~0);
12835 x_font_min_bounds (font, &w, &h);
12836
12837 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12838 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12839 }
12840
12841 xassert (dpyinfo->smallest_char_width > 0
12842 && dpyinfo->smallest_font_height > 0);
12843
12844 return (dpyinfo->n_fonts == 1
12845 || dpyinfo->smallest_char_width < old_width
12846 || dpyinfo->smallest_font_height < old_height);
12847}
12848
12849
dc43ef94
KH
12850/* Load font named FONTNAME of the size SIZE for frame F, and return a
12851 pointer to the structure font_info while allocating it dynamically.
12852 If SIZE is 0, load any size of font.
12853 If loading is failed, return NULL. */
12854
12855struct font_info *
12856x_load_font (f, fontname, size)
12857 struct frame *f;
12858 register char *fontname;
12859 int size;
12860{
12861 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12862 Lisp_Object font_names;
d645aaa4 12863 int count;
dc43ef94
KH
12864
12865 /* Get a list of all the fonts that match this name. Once we
12866 have a list of matching fonts, we compare them against the fonts
12867 we already have by comparing names. */
09c6077f 12868 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
12869
12870 if (!NILP (font_names))
12871 {
12872 Lisp_Object tail;
12873 int i;
12874
12875 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 12876 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
12877 if (dpyinfo->font_table[i].name
12878 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 12879 XSTRING (XCAR (tail))->data)
06a2c219 12880 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 12881 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
12882 return (dpyinfo->font_table + i);
12883 }
12884
12885 /* Load the font and add it to the table. */
12886 {
12887 char *full_name;
12888 XFontStruct *font;
12889 struct font_info *fontp;
12890 unsigned long value;
06a2c219 12891 int i;
dc43ef94 12892
2da424f1
KH
12893 /* If we have found fonts by x_list_font, load one of them. If
12894 not, we still try to load a font by the name given as FONTNAME
12895 because XListFonts (called in x_list_font) of some X server has
12896 a bug of not finding a font even if the font surely exists and
12897 is loadable by XLoadQueryFont. */
e1d6d5b9 12898 if (size > 0 && !NILP (font_names))
8e713be6 12899 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
12900
12901 BLOCK_INPUT;
d645aaa4 12902 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 12903 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
12904 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12905 {
12906 /* This error is perhaps due to insufficient memory on X
12907 server. Let's just ignore it. */
12908 font = NULL;
12909 x_clear_errors (FRAME_X_DISPLAY (f));
12910 }
12911 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 12912 UNBLOCK_INPUT;
b5210ea7 12913 if (!font)
dc43ef94
KH
12914 return NULL;
12915
06a2c219
GM
12916 /* Find a free slot in the font table. */
12917 for (i = 0; i < dpyinfo->n_fonts; ++i)
12918 if (dpyinfo->font_table[i].name == NULL)
12919 break;
12920
12921 /* If no free slot found, maybe enlarge the font table. */
12922 if (i == dpyinfo->n_fonts
12923 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 12924 {
06a2c219
GM
12925 int sz;
12926 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12927 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 12928 dpyinfo->font_table
06a2c219 12929 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
12930 }
12931
06a2c219
GM
12932 fontp = dpyinfo->font_table + i;
12933 if (i == dpyinfo->n_fonts)
12934 ++dpyinfo->n_fonts;
dc43ef94
KH
12935
12936 /* Now fill in the slots of *FONTP. */
12937 BLOCK_INPUT;
12938 fontp->font = font;
06a2c219 12939 fontp->font_idx = i;
dc43ef94
KH
12940 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12941 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12942
12943 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12944 full_name = 0;
12945 if (XGetFontProperty (font, XA_FONT, &value))
12946 {
12947 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12948 char *p = name;
12949 int dashes = 0;
12950
12951 /* Count the number of dashes in the "full name".
12952 If it is too few, this isn't really the font's full name,
12953 so don't use it.
12954 In X11R4, the fonts did not come with their canonical names
12955 stored in them. */
12956 while (*p)
12957 {
12958 if (*p == '-')
12959 dashes++;
12960 p++;
12961 }
12962
12963 if (dashes >= 13)
12964 {
12965 full_name = (char *) xmalloc (p - name + 1);
12966 bcopy (name, full_name, p - name + 1);
12967 }
12968
12969 XFree (name);
12970 }
12971
12972 if (full_name != 0)
12973 fontp->full_name = full_name;
12974 else
12975 fontp->full_name = fontp->name;
12976
12977 fontp->size = font->max_bounds.width;
d5749adb
KH
12978 fontp->height = FONT_HEIGHT (font);
12979 {
12980 /* For some font, ascent and descent in max_bounds field is
12981 larger than the above value. */
12982 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12983 if (max_height > fontp->height)
74848a96 12984 fontp->height = max_height;
d5749adb 12985 }
dc43ef94 12986
2da424f1
KH
12987 if (NILP (font_names))
12988 {
12989 /* We come here because of a bug of XListFonts mentioned at
12990 the head of this block. Let's store this information in
12991 the cache for x_list_fonts. */
12992 Lisp_Object lispy_name = build_string (fontname);
12993 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12994
8e713be6 12995 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12996 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12997 Fcons (Fcons (lispy_full_name,
12998 make_number (fontp->size)),
12999 Qnil)),
8e713be6 13000 XCDR (dpyinfo->name_list_element));
2da424f1 13001 if (full_name)
8e713be6 13002 XCDR (dpyinfo->name_list_element)
2da424f1
KH
13003 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
13004 Fcons (Fcons (lispy_full_name,
13005 make_number (fontp->size)),
13006 Qnil)),
8e713be6 13007 XCDR (dpyinfo->name_list_element));
2da424f1
KH
13008 }
13009
dc43ef94
KH
13010 /* The slot `encoding' specifies how to map a character
13011 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
13012 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
13013 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 13014 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 13015 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
13016 which is never used by any charset. If mapping can't be
13017 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
13018 fontp->encoding[1]
13019 = (font->max_byte1 == 0
13020 /* 1-byte font */
13021 ? (font->min_char_or_byte2 < 0x80
13022 ? (font->max_char_or_byte2 < 0x80
13023 ? 0 /* 0x20..0x7F */
8ff102bd 13024 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
13025 : 1) /* 0xA0..0xFF */
13026 /* 2-byte font */
13027 : (font->min_byte1 < 0x80
13028 ? (font->max_byte1 < 0x80
13029 ? (font->min_char_or_byte2 < 0x80
13030 ? (font->max_char_or_byte2 < 0x80
13031 ? 0 /* 0x2020..0x7F7F */
8ff102bd 13032 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 13033 : 3) /* 0x20A0..0x7FFF */
8ff102bd 13034 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
13035 : (font->min_char_or_byte2 < 0x80
13036 ? (font->max_char_or_byte2 < 0x80
13037 ? 2 /* 0xA020..0xFF7F */
8ff102bd 13038 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
13039 : 1))); /* 0xA0A0..0xFFFF */
13040
13041 fontp->baseline_offset
13042 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
13043 ? (long) value : 0);
13044 fontp->relative_compose
13045 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
13046 ? (long) value : 0);
f78798df
KH
13047 fontp->default_ascent
13048 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
13049 ? (long) value : 0);
dc43ef94 13050
06a2c219
GM
13051 /* Set global flag fonts_changed_p to non-zero if the font loaded
13052 has a character with a smaller width than any other character
13053 before, or if the font loaded has a smalle>r height than any
13054 other font loaded before. If this happens, it will make a
13055 glyph matrix reallocation necessary. */
13056 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 13057 UNBLOCK_INPUT;
dc43ef94
KH
13058 return fontp;
13059 }
13060}
13061
06a2c219
GM
13062
13063/* Return a pointer to struct font_info of a font named FONTNAME for
13064 frame F. If no such font is loaded, return NULL. */
13065
dc43ef94
KH
13066struct font_info *
13067x_query_font (f, fontname)
13068 struct frame *f;
13069 register char *fontname;
13070{
13071 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
13072 int i;
13073
13074 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
13075 if (dpyinfo->font_table[i].name
13076 && (!strcmp (dpyinfo->font_table[i].name, fontname)
13077 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
13078 return (dpyinfo->font_table + i);
13079 return NULL;
13080}
13081
06a2c219
GM
13082
13083/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
13084 `encoder' of the structure. */
13085
13086void
13087x_find_ccl_program (fontp)
13088 struct font_info *fontp;
13089{
a42f54e6 13090 Lisp_Object list, elt;
a6582676 13091
8e713be6 13092 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 13093 {
8e713be6 13094 elt = XCAR (list);
a6582676 13095 if (CONSP (elt)
8e713be6
KR
13096 && STRINGP (XCAR (elt))
13097 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
a6582676 13098 >= 0))
a42f54e6
KH
13099 break;
13100 }
13101 if (! NILP (list))
13102 {
d27f8ca7
KH
13103 struct ccl_program *ccl
13104 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 13105
8e713be6 13106 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
13107 xfree (ccl);
13108 else
13109 fontp->font_encoder = ccl;
a6582676
KH
13110 }
13111}
13112
06a2c219 13113
dc43ef94 13114\f
06a2c219
GM
13115/***********************************************************************
13116 Initialization
13117 ***********************************************************************/
f451eb13 13118
3afe33e7
RS
13119#ifdef USE_X_TOOLKIT
13120static XrmOptionDescRec emacs_options[] = {
13121 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
13122 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
13123
13124 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
13125 XrmoptionSepArg, NULL},
13126 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
13127
13128 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13129 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13130 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
13131 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13132 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
13133 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
13134 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
13135};
13136#endif /* USE_X_TOOLKIT */
13137
7a13e894
RS
13138static int x_initialized;
13139
29b38361
KH
13140#ifdef MULTI_KBOARD
13141/* Test whether two display-name strings agree up to the dot that separates
13142 the screen number from the server number. */
13143static int
13144same_x_server (name1, name2)
13145 char *name1, *name2;
13146{
13147 int seen_colon = 0;
cf591cc1
RS
13148 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13149 int system_name_length = strlen (system_name);
13150 int length_until_period = 0;
13151
13152 while (system_name[length_until_period] != 0
13153 && system_name[length_until_period] != '.')
13154 length_until_period++;
13155
13156 /* Treat `unix' like an empty host name. */
13157 if (! strncmp (name1, "unix:", 5))
13158 name1 += 4;
13159 if (! strncmp (name2, "unix:", 5))
13160 name2 += 4;
13161 /* Treat this host's name like an empty host name. */
13162 if (! strncmp (name1, system_name, system_name_length)
13163 && name1[system_name_length] == ':')
13164 name1 += system_name_length;
13165 if (! strncmp (name2, system_name, system_name_length)
13166 && name2[system_name_length] == ':')
13167 name2 += system_name_length;
13168 /* Treat this host's domainless name like an empty host name. */
13169 if (! strncmp (name1, system_name, length_until_period)
13170 && name1[length_until_period] == ':')
13171 name1 += length_until_period;
13172 if (! strncmp (name2, system_name, length_until_period)
13173 && name2[length_until_period] == ':')
13174 name2 += length_until_period;
13175
29b38361
KH
13176 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13177 {
13178 if (*name1 == ':')
13179 seen_colon++;
13180 if (seen_colon && *name1 == '.')
13181 return 1;
13182 }
13183 return (seen_colon
13184 && (*name1 == '.' || *name1 == '\0')
13185 && (*name2 == '.' || *name2 == '\0'));
13186}
13187#endif
13188
334208b7 13189struct x_display_info *
1f8255f2 13190x_term_init (display_name, xrm_option, resource_name)
334208b7 13191 Lisp_Object display_name;
1f8255f2
RS
13192 char *xrm_option;
13193 char *resource_name;
dc6f92b8 13194{
334208b7 13195 int connection;
7a13e894 13196 Display *dpy;
334208b7
RS
13197 struct x_display_info *dpyinfo;
13198 XrmDatabase xrdb;
13199
60439948
KH
13200 BLOCK_INPUT;
13201
7a13e894
RS
13202 if (!x_initialized)
13203 {
13204 x_initialize ();
13205 x_initialized = 1;
13206 }
dc6f92b8 13207
3afe33e7 13208#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13209 /* weiner@footloose.sps.mot.com reports that this causes
13210 errors with X11R5:
13211 X protocol error: BadAtom (invalid Atom parameter)
13212 on protocol request 18skiloaf.
13213 So let's not use it until R6. */
13214#ifdef HAVE_X11XTR6
bdcd49ba
RS
13215 XtSetLanguageProc (NULL, NULL, NULL);
13216#endif
13217
7f9c7f94
RS
13218 {
13219 int argc = 0;
13220 char *argv[3];
13221
13222 argv[0] = "";
13223 argc = 1;
13224 if (xrm_option)
13225 {
13226 argv[argc++] = "-xrm";
13227 argv[argc++] = xrm_option;
13228 }
13229 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13230 resource_name, EMACS_CLASS,
13231 emacs_options, XtNumber (emacs_options),
13232 &argc, argv);
39d8bb4d
KH
13233
13234#ifdef HAVE_X11XTR6
10537cb1 13235 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13236 fixup_locale ();
39d8bb4d 13237#endif
7f9c7f94 13238 }
3afe33e7
RS
13239
13240#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13241#ifdef HAVE_X11R5
13242 XSetLocaleModifiers ("");
13243#endif
7a13e894 13244 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13245#endif /* not USE_X_TOOLKIT */
334208b7 13246
7a13e894
RS
13247 /* Detect failure. */
13248 if (dpy == 0)
60439948
KH
13249 {
13250 UNBLOCK_INPUT;
13251 return 0;
13252 }
7a13e894
RS
13253
13254 /* We have definitely succeeded. Record the new connection. */
13255
13256 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13257
29b38361
KH
13258#ifdef MULTI_KBOARD
13259 {
13260 struct x_display_info *share;
13261 Lisp_Object tail;
13262
13263 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13264 share = share->next, tail = XCDR (tail))
13265 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13266 XSTRING (display_name)->data))
13267 break;
13268 if (share)
13269 dpyinfo->kboard = share->kboard;
13270 else
13271 {
13272 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13273 init_kboard (dpyinfo->kboard);
59e755be
KH
13274 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13275 {
13276 char *vendor = ServerVendor (dpy);
9b6ed9f3 13277 UNBLOCK_INPUT;
59e755be
KH
13278 dpyinfo->kboard->Vsystem_key_alist
13279 = call1 (Qvendor_specific_keysyms,
13280 build_string (vendor ? vendor : ""));
9b6ed9f3 13281 BLOCK_INPUT;
59e755be
KH
13282 }
13283
29b38361
KH
13284 dpyinfo->kboard->next_kboard = all_kboards;
13285 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13286 /* Don't let the initial kboard remain current longer than necessary.
13287 That would cause problems if a file loaded on startup tries to
06a2c219 13288 prompt in the mini-buffer. */
0ad5446c
KH
13289 if (current_kboard == initial_kboard)
13290 current_kboard = dpyinfo->kboard;
29b38361
KH
13291 }
13292 dpyinfo->kboard->reference_count++;
13293 }
b9737ad3
KH
13294#endif
13295
7a13e894
RS
13296 /* Put this display on the chain. */
13297 dpyinfo->next = x_display_list;
13298 x_display_list = dpyinfo;
13299
13300 /* Put it on x_display_name_list as well, to keep them parallel. */
13301 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13302 x_display_name_list);
8e713be6 13303 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13304
13305 dpyinfo->display = dpy;
dc6f92b8 13306
dc6f92b8 13307#if 0
7a13e894 13308 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13309#endif /* ! 0 */
7a13e894
RS
13310
13311 dpyinfo->x_id_name
fc932ac6
RS
13312 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13313 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13314 + 2);
13315 sprintf (dpyinfo->x_id_name, "%s@%s",
13316 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13317
13318 /* Figure out which modifier bits mean what. */
334208b7 13319 x_find_modifier_meanings (dpyinfo);
f451eb13 13320
ab648270 13321 /* Get the scroll bar cursor. */
7a13e894 13322 dpyinfo->vertical_scroll_bar_cursor
334208b7 13323 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13324
334208b7
RS
13325 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13326 resource_name, EMACS_CLASS);
13327#ifdef HAVE_XRMSETDATABASE
13328 XrmSetDatabase (dpyinfo->display, xrdb);
13329#else
13330 dpyinfo->display->db = xrdb;
13331#endif
547d9db8 13332 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13333 all versions. */
13334 dpyinfo->xrdb = xrdb;
334208b7
RS
13335
13336 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13337 DefaultScreen (dpyinfo->display));
5ff67d81 13338 select_visual (dpyinfo);
43bd1b2b 13339 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13340 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13341 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13342 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13343 dpyinfo->grabbed = 0;
13344 dpyinfo->reference_count = 0;
13345 dpyinfo->icon_bitmap_id = -1;
06a2c219 13346 dpyinfo->font_table = NULL;
7a13e894
RS
13347 dpyinfo->n_fonts = 0;
13348 dpyinfo->font_table_size = 0;
13349 dpyinfo->bitmaps = 0;
13350 dpyinfo->bitmaps_size = 0;
13351 dpyinfo->bitmaps_last = 0;
13352 dpyinfo->scratch_cursor_gc = 0;
13353 dpyinfo->mouse_face_mouse_frame = 0;
13354 dpyinfo->mouse_face_deferred_gc = 0;
13355 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13356 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13357 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13358 dpyinfo->mouse_face_window = Qnil;
13359 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13360 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13361 dpyinfo->x_focus_frame = 0;
13362 dpyinfo->x_focus_event_frame = 0;
13363 dpyinfo->x_highlight_frame = 0;
06a2c219 13364 dpyinfo->image_cache = make_image_cache ();
334208b7 13365
43bd1b2b 13366 /* See if a private colormap is requested. */
5ff67d81
GM
13367 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13368 {
13369 if (dpyinfo->visual->class == PseudoColor)
13370 {
13371 Lisp_Object value;
13372 value = display_x_get_resource (dpyinfo,
13373 build_string ("privateColormap"),
13374 build_string ("PrivateColormap"),
13375 Qnil, Qnil);
13376 if (STRINGP (value)
13377 && (!strcmp (XSTRING (value)->data, "true")
13378 || !strcmp (XSTRING (value)->data, "on")))
13379 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13380 }
43bd1b2b 13381 }
5ff67d81
GM
13382 else
13383 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13384 dpyinfo->visual, AllocNone);
43bd1b2b 13385
06a2c219
GM
13386 {
13387 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13388 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13389 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13390 dpyinfo->resy = pixels * 25.4 / mm;
13391 pixels = DisplayWidth (dpyinfo->display, screen_number);
13392 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13393 dpyinfo->resx = pixels * 25.4 / mm;
13394 }
13395
334208b7
RS
13396 dpyinfo->Xatom_wm_protocols
13397 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13398 dpyinfo->Xatom_wm_take_focus
13399 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13400 dpyinfo->Xatom_wm_save_yourself
13401 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13402 dpyinfo->Xatom_wm_delete_window
13403 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13404 dpyinfo->Xatom_wm_change_state
13405 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13406 dpyinfo->Xatom_wm_configure_denied
13407 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13408 dpyinfo->Xatom_wm_window_moved
13409 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13410 dpyinfo->Xatom_editres
13411 = XInternAtom (dpyinfo->display, "Editres", False);
13412 dpyinfo->Xatom_CLIPBOARD
13413 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13414 dpyinfo->Xatom_TIMESTAMP
13415 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13416 dpyinfo->Xatom_TEXT
13417 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13418 dpyinfo->Xatom_COMPOUND_TEXT
13419 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13420 dpyinfo->Xatom_DELETE
13421 = XInternAtom (dpyinfo->display, "DELETE", False);
13422 dpyinfo->Xatom_MULTIPLE
13423 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13424 dpyinfo->Xatom_INCR
13425 = XInternAtom (dpyinfo->display, "INCR", False);
13426 dpyinfo->Xatom_EMACS_TMP
13427 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13428 dpyinfo->Xatom_TARGETS
13429 = XInternAtom (dpyinfo->display, "TARGETS", False);
13430 dpyinfo->Xatom_NULL
13431 = XInternAtom (dpyinfo->display, "NULL", False);
13432 dpyinfo->Xatom_ATOM_PAIR
13433 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13434 /* For properties of font. */
13435 dpyinfo->Xatom_PIXEL_SIZE
13436 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13437 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13438 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13439 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13440 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13441 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13442 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13443
06a2c219
GM
13444 /* Ghostscript support. */
13445 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13446 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13447
13448 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13449 False);
13450
547d9db8
KH
13451 dpyinfo->cut_buffers_initialized = 0;
13452
334208b7
RS
13453 connection = ConnectionNumber (dpyinfo->display);
13454 dpyinfo->connection = connection;
13455
dc43ef94 13456 {
5d7cc324
RS
13457 char null_bits[1];
13458
13459 null_bits[0] = 0x00;
dc43ef94
KH
13460
13461 dpyinfo->null_pixel
13462 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13463 null_bits, 1, 1, (long) 0, (long) 0,
13464 1);
13465 }
13466
06a2c219
GM
13467 {
13468 extern int gray_bitmap_width, gray_bitmap_height;
13469 extern unsigned char *gray_bitmap_bits;
13470 dpyinfo->gray
13471 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13472 gray_bitmap_bits,
13473 gray_bitmap_width, gray_bitmap_height,
13474 (unsigned long) 1, (unsigned long) 0, 1);
13475 }
13476
f5d11644
GM
13477#ifdef HAVE_X_I18N
13478 xim_initialize (dpyinfo, resource_name);
13479#endif
13480
87485d6f
MW
13481#ifdef subprocesses
13482 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13483 if (connection != 0)
7a13e894 13484 add_keyboard_wait_descriptor (connection);
87485d6f 13485#endif
6d4238f3 13486
041b69ac 13487#ifndef F_SETOWN_BUG
dc6f92b8 13488#ifdef F_SETOWN
dc6f92b8 13489#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13490 /* stdin is a socket here */
334208b7 13491 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13492#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13493 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13494#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13495#endif /* ! defined (F_SETOWN) */
041b69ac 13496#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13497
13498#ifdef SIGIO
eee20f6a
KH
13499 if (interrupt_input)
13500 init_sigio (connection);
c118dd06 13501#endif /* ! defined (SIGIO) */
dc6f92b8 13502
51b592fb 13503#ifdef USE_LUCID
f8c39f51 13504#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13505 /* Make sure that we have a valid font for dialog boxes
13506 so that Xt does not crash. */
13507 {
13508 Display *dpy = dpyinfo->display;
13509 XrmValue d, fr, to;
13510 Font font;
e99db5a1 13511 int count;
51b592fb
RS
13512
13513 d.addr = (XPointer)&dpy;
13514 d.size = sizeof (Display *);
13515 fr.addr = XtDefaultFont;
13516 fr.size = sizeof (XtDefaultFont);
13517 to.size = sizeof (Font *);
13518 to.addr = (XPointer)&font;
e99db5a1 13519 count = x_catch_errors (dpy);
51b592fb
RS
13520 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13521 abort ();
13522 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13523 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13524 x_uncatch_errors (dpy, count);
51b592fb
RS
13525 }
13526#endif
f8c39f51 13527#endif
51b592fb 13528
34e23e5a
GM
13529 /* See if we should run in synchronous mode. This is useful
13530 for debugging X code. */
13531 {
13532 Lisp_Object value;
13533 value = display_x_get_resource (dpyinfo,
13534 build_string ("synchronous"),
13535 build_string ("Synchronous"),
13536 Qnil, Qnil);
13537 if (STRINGP (value)
13538 && (!strcmp (XSTRING (value)->data, "true")
13539 || !strcmp (XSTRING (value)->data, "on")))
13540 XSynchronize (dpyinfo->display, True);
13541 }
13542
60439948
KH
13543 UNBLOCK_INPUT;
13544
7a13e894
RS
13545 return dpyinfo;
13546}
13547\f
13548/* Get rid of display DPYINFO, assuming all frames are already gone,
13549 and without sending any more commands to the X server. */
dc6f92b8 13550
7a13e894
RS
13551void
13552x_delete_display (dpyinfo)
13553 struct x_display_info *dpyinfo;
13554{
13555 delete_keyboard_wait_descriptor (dpyinfo->connection);
13556
13557 /* Discard this display from x_display_name_list and x_display_list.
13558 We can't use Fdelq because that can quit. */
13559 if (! NILP (x_display_name_list)
8e713be6
KR
13560 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13561 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13562 else
13563 {
13564 Lisp_Object tail;
13565
13566 tail = x_display_name_list;
8e713be6 13567 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13568 {
bffcfca9 13569 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13570 {
8e713be6 13571 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13572 break;
13573 }
8e713be6 13574 tail = XCDR (tail);
7a13e894
RS
13575 }
13576 }
13577
9bda743f
GM
13578 if (next_noop_dpyinfo == dpyinfo)
13579 next_noop_dpyinfo = dpyinfo->next;
13580
7a13e894
RS
13581 if (x_display_list == dpyinfo)
13582 x_display_list = dpyinfo->next;
7f9c7f94
RS
13583 else
13584 {
13585 struct x_display_info *tail;
7a13e894 13586
7f9c7f94
RS
13587 for (tail = x_display_list; tail; tail = tail->next)
13588 if (tail->next == dpyinfo)
13589 tail->next = tail->next->next;
13590 }
7a13e894 13591
0d777288
RS
13592#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13593#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13594 XrmDestroyDatabase (dpyinfo->xrdb);
13595#endif
0d777288 13596#endif
29b38361
KH
13597#ifdef MULTI_KBOARD
13598 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13599 delete_kboard (dpyinfo->kboard);
b9737ad3 13600#endif
f5d11644
GM
13601#ifdef HAVE_X_I18N
13602 if (dpyinfo->xim)
13603 xim_close_dpy (dpyinfo);
13604#endif
13605
b9737ad3
KH
13606 xfree (dpyinfo->font_table);
13607 xfree (dpyinfo->x_id_name);
13608 xfree (dpyinfo);
7a13e894
RS
13609}
13610\f
13611/* Set up use of X before we make the first connection. */
13612
06a2c219
GM
13613static struct redisplay_interface x_redisplay_interface =
13614{
13615 x_produce_glyphs,
13616 x_write_glyphs,
13617 x_insert_glyphs,
13618 x_clear_end_of_line,
13619 x_scroll_run,
13620 x_after_update_window_line,
13621 x_update_window_begin,
13622 x_update_window_end,
13623 XTcursor_to,
13624 x_flush,
71b8321e 13625 x_clear_mouse_face,
66ac4b0e
GM
13626 x_get_glyph_overhangs,
13627 x_fix_overlapping_area
06a2c219
GM
13628};
13629
dfcf069d 13630void
7a13e894
RS
13631x_initialize ()
13632{
06a2c219
GM
13633 rif = &x_redisplay_interface;
13634
13635 clear_frame_hook = x_clear_frame;
13636 ins_del_lines_hook = x_ins_del_lines;
13637 change_line_highlight_hook = x_change_line_highlight;
13638 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13639 ring_bell_hook = XTring_bell;
13640 reset_terminal_modes_hook = XTreset_terminal_modes;
13641 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13642 update_begin_hook = x_update_begin;
13643 update_end_hook = x_update_end;
dc6f92b8
JB
13644 set_terminal_window_hook = XTset_terminal_window;
13645 read_socket_hook = XTread_socket;
b8009dd1 13646 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13647 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13648 mouse_position_hook = XTmouse_position;
f451eb13 13649 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13650 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13651 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13652 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13653 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13654 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13655 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13656
f676886a 13657 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13658 char_ins_del_ok = 0; /* just as fast to write the line */
13659 line_ins_del_ok = 1; /* we'll just blt 'em */
13660 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13661 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13662 off the bottom */
13663 baud_rate = 19200;
13664
7a13e894 13665 x_noop_count = 0;
9ea173e8 13666 last_tool_bar_item = -1;
06a2c219
GM
13667 any_help_event_p = 0;
13668
b30b24cb
RS
13669 /* Try to use interrupt input; if we can't, then start polling. */
13670 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13671
7f9c7f94
RS
13672#ifdef USE_X_TOOLKIT
13673 XtToolkitInitialize ();
13674 Xt_app_con = XtCreateApplicationContext ();
665881ad 13675 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13676
13677 /* Install an asynchronous timer that processes Xt timeout events
13678 every 0.1s. This is necessary because some widget sets use
13679 timeouts internally, for example the LessTif menu bar, or the
13680 Xaw3d scroll bar. When Xt timouts aren't processed, these
13681 widgets don't behave normally. */
13682 {
13683 EMACS_TIME interval;
13684 EMACS_SET_SECS_USECS (interval, 0, 100000);
13685 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13686 }
db74249b 13687#endif
bffcfca9 13688
db74249b 13689#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13690 xaw3d_arrow_scroll = False;
13691 xaw3d_pick_top = True;
7f9c7f94
RS
13692#endif
13693
58769bee 13694 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13695 original error handler. */
e99db5a1 13696 XSetErrorHandler (x_error_handler);
334208b7 13697 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13698
06a2c219 13699 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13700#ifdef SIGWINCH
13701 signal (SIGWINCH, SIG_DFL);
c118dd06 13702#endif /* ! defined (SIGWINCH) */
dc6f92b8 13703
92e2441b 13704 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13705}
55123275 13706
06a2c219 13707
55123275
JB
13708void
13709syms_of_xterm ()
13710{
e99db5a1
RS
13711 staticpro (&x_error_message_string);
13712 x_error_message_string = Qnil;
13713
7a13e894
RS
13714 staticpro (&x_display_name_list);
13715 x_display_name_list = Qnil;
334208b7 13716
ab648270 13717 staticpro (&last_mouse_scroll_bar);
e53cb100 13718 last_mouse_scroll_bar = Qnil;
59e755be
KH
13719
13720 staticpro (&Qvendor_specific_keysyms);
13721 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13722
13723 staticpro (&last_mouse_press_frame);
13724 last_mouse_press_frame = Qnil;
06a2c219 13725
06a2c219 13726 help_echo = Qnil;
be010514
GM
13727 staticpro (&help_echo);
13728 help_echo_object = Qnil;
13729 staticpro (&help_echo_object);
7cea38bc
GM
13730 help_echo_window = Qnil;
13731 staticpro (&help_echo_window);
06a2c219 13732 previous_help_echo = Qnil;
be010514
GM
13733 staticpro (&previous_help_echo);
13734 help_echo_pos = -1;
06a2c219
GM
13735
13736 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13737 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13738For example, if a block cursor is over a tab, it will be drawn as\n\
13739wide as that tab on the display.");
13740 x_stretch_cursor_p = 0;
13741
13742 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13743 "If not nil, Emacs uses toolkit scroll bars.");
13744#if USE_TOOLKIT_SCROLL_BARS
13745 x_toolkit_scroll_bars_p = 1;
13746#else
13747 x_toolkit_scroll_bars_p = 0;
13748#endif
13749
06a2c219
GM
13750 staticpro (&last_mouse_motion_frame);
13751 last_mouse_motion_frame = Qnil;
55123275 13752}
6cf0ae86
RS
13753
13754#endif /* not HAVE_X_WINDOWS */
06a2c219 13755