(COMPILE_FIRST): New macro.
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
06a2c219
GM
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
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 46
16bd92ea 47#ifndef USG
dc6f92b8
JB
48/* Load sys/types.h if not already loaded.
49 In some systems loading it twice is suicidal. */
50#ifndef makedev
51#include <sys/types.h>
c118dd06
JB
52#endif /* makedev */
53#endif /* USG */
dc6f92b8 54
6df54671 55#ifdef BSD_SYSTEM
dc6f92b8 56#include <sys/ioctl.h>
6df54671 57#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 58
2d368234 59#include "systty.h"
3a2712f9 60#include "systime.h"
dc6f92b8 61
b8009dd1 62#ifndef INCLUDED_FCNTL
dc6f92b8 63#include <fcntl.h>
b8009dd1 64#endif
dc6f92b8
JB
65#include <ctype.h>
66#include <errno.h>
67#include <setjmp.h>
68#include <sys/stat.h>
a0a7635f
RS
69/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
70/* #include <sys/param.h> */
dc6f92b8 71
dc43ef94
KH
72#include "charset.h"
73#include "ccl.h"
7a13e894 74#include "frame.h"
dc6f92b8 75#include "dispextern.h"
ee569018 76#include "fontset.h"
dc6f92b8
JB
77#include "termhooks.h"
78#include "termopts.h"
79#include "termchar.h"
80#if 0
81#include "sink.h"
82#include "sinkmask.h"
c118dd06 83#endif /* ! 0 */
dc6f92b8 84#include "gnu.h"
dc6f92b8 85#include "disptab.h"
dc6f92b8 86#include "buffer.h"
f451eb13 87#include "window.h"
3b2fa4e6 88#include "keyboard.h"
bde7c500 89#include "intervals.h"
dfcf069d 90#include "process.h"
bffcfca9 91#include "atimer.h"
dc6f92b8 92
d2bd6bc4
RS
93#ifdef USE_X_TOOLKIT
94#include <X11/Shell.h>
95#endif
96
06a2c219
GM
97#include <sys/types.h>
98#ifdef HAVE_SYS_TIME_H
99#include <sys/time.h>
100#endif
101#ifdef HAVE_UNISTD_H
102#include <unistd.h>
103#endif
104
3afe33e7 105#ifdef USE_X_TOOLKIT
06a2c219 106
9d7e2e3e 107extern void free_frame_menubar ();
2224b905 108extern FRAME_PTR x_menubar_window_to_frame ();
06a2c219 109
0fdff6bb
RS
110#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
111#define HACK_EDITRES
112extern void _XEditResCheckMessages ();
113#endif /* not NO_EDITRES */
06a2c219
GM
114
115/* Include toolkit specific headers for the scroll bar widget. */
116
117#ifdef USE_TOOLKIT_SCROLL_BARS
118#if defined USE_MOTIF
119#include <Xm/Xm.h> /* for LESSTIF_VERSION */
120#include <Xm/ScrollBar.h>
121#include <Xm/ScrollBarP.h>
ec18280f
SM
122#else /* !USE_MOTIF i.e. use Xaw */
123
124#ifdef HAVE_XAW3D
06a2c219 125#include <X11/Xaw3d/Simple.h>
06a2c219
GM
126#include <X11/Xaw3d/Scrollbar.h>
127#define ARROW_SCROLLBAR
128#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
129#else /* !HAVE_XAW3D */
130#include <X11/Xaw/Simple.h>
131#include <X11/Xaw/Scrollbar.h>
132#endif /* !HAVE_XAW3D */
133#ifndef XtNpickTop
134#define XtNpickTop "pickTop"
135#endif /* !XtNpickTop */
136#endif /* !USE_MOTIF */
06a2c219
GM
137#endif /* USE_TOOLKIT_SCROLL_BARS */
138
3afe33e7
RS
139#endif /* USE_X_TOOLKIT */
140
b849c413
RS
141#ifndef USE_X_TOOLKIT
142#define x_any_window_to_frame x_window_to_frame
5627c40e 143#define x_top_window_to_frame x_window_to_frame
b849c413
RS
144#endif
145
546e6d5b 146#ifdef USE_X_TOOLKIT
d067ea8b 147#include "widget.h"
546e6d5b
RS
148#ifndef XtNinitialState
149#define XtNinitialState "initialState"
150#endif
151#endif
152
80528801
KH
153#ifdef SOLARIS2
154/* memmove will be defined as a macro in Xfuncs.h unless
155 <string.h> is included beforehand. The declaration for memmove in
156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
157#include <string.h>
158#endif
159
e4b68333 160#ifndef min
06a2c219 161#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
162#endif
163#ifndef max
06a2c219
GM
164#define max(a,b) ((a) > (b) ? (a) : (b))
165#endif
166
167#define abs(x) ((x) < 0 ? -(x) : (x))
168
169#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
170
171\f
172/* Bitmaps for truncated lines. */
173
174enum bitmap_type
175{
176 NO_BITMAP,
177 LEFT_TRUNCATION_BITMAP,
178 RIGHT_TRUNCATION_BITMAP,
179 OVERLAY_ARROW_BITMAP,
180 CONTINUED_LINE_BITMAP,
181 CONTINUATION_LINE_BITMAP,
182 ZV_LINE_BITMAP
183};
184
185/* Bitmap drawn to indicate lines not displaying text if
186 `indicate-empty-lines' is non-nil. */
187
188#define zv_width 8
189#define zv_height 8
190static unsigned char zv_bits[] = {
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
192
193/* An arrow like this: `<-'. */
194
195#define left_width 8
196#define left_height 8
197static unsigned char left_bits[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
199
110859fc
GM
200/* Right truncation arrow bitmap `->'. */
201
202#define right_width 8
203#define right_height 8
204static unsigned char right_bits[] = {
205 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
206
06a2c219
GM
207/* Marker for continued lines. */
208
209#define continued_width 8
210#define continued_height 8
211static unsigned char continued_bits[] = {
110859fc
GM
212 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
213
214/* Marker for continuation lines. */
06a2c219
GM
215
216#define continuation_width 8
217#define continuation_height 8
218static unsigned char continuation_bits[] = {
110859fc 219 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 220
110859fc 221/* Overlay arrow bitmap. */
06a2c219 222
110859fc
GM
223#if 0
224/* A bomb. */
06a2c219
GM
225#define ov_width 8
226#define ov_height 8
227static unsigned char ov_bits[] = {
228 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 229#else
110859fc 230/* A triangular arrow. */
06a2c219
GM
231#define ov_width 8
232#define ov_height 8
233static unsigned char ov_bits[] = {
110859fc
GM
234 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
235
e4b68333 236#endif
06a2c219
GM
237
238extern Lisp_Object Qhelp_echo;
239
69388238 240\f
06a2c219
GM
241/* Non-zero means Emacs uses toolkit scroll bars. */
242
243int x_toolkit_scroll_bars_p;
244
245/* If a string, XTread_socket generates an event to display that string.
246 (The display is done in read_char.) */
247
248static Lisp_Object help_echo;
249
250/* Temporary variable for XTread_socket. */
251
252static Lisp_Object previous_help_echo;
253
254/* Non-zero means that a HELP_EVENT has been generated since Emacs
255 start. */
256
257static int any_help_event_p;
258
259/* Non-zero means draw block and hollow cursor as wide as the glyph
260 under it. For example, if a block cursor is over a tab, it will be
261 drawn as wide as that tab on the display. */
262
263int x_stretch_cursor_p;
264
265/* This is a chain of structures for all the X displays currently in
266 use. */
267
334208b7 268struct x_display_info *x_display_list;
dc6f92b8 269
06a2c219
GM
270/* This is a list of cons cells, each of the form (NAME
271 . FONT-LIST-CACHE), one for each element of x_display_list and in
272 the same order. NAME is the name of the frame. FONT-LIST-CACHE
273 records previous values returned by x-list-fonts. */
274
7a13e894 275Lisp_Object x_display_name_list;
f451eb13 276
987d2ad1 277/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
278 This is set by update_begin and looked at by all the XT functions.
279 It is zero while not inside an update. In that case, the XT
280 functions assume that `selected_frame' is the frame to apply to. */
281
d0386f2a 282extern struct frame *updating_frame;
dc6f92b8 283
dfcf069d 284extern int waiting_for_input;
0e81d8cd 285
06a2c219
GM
286/* This is a frame waiting to be auto-raised, within XTread_socket. */
287
0134a210
RS
288struct frame *pending_autoraise_frame;
289
7f9c7f94
RS
290#ifdef USE_X_TOOLKIT
291/* The application context for Xt use. */
292XtAppContext Xt_app_con;
06a2c219
GM
293static String Xt_default_resources[] = {0};
294#endif /* USE_X_TOOLKIT */
665881ad 295
06a2c219
GM
296/* Nominal cursor position -- where to draw output.
297 HPOS and VPOS are window relative glyph matrix coordinates.
298 X and Y are window relative pixel coordinates. */
dc6f92b8 299
06a2c219 300struct cursor_pos output_cursor;
dc6f92b8 301
bffcfca9
GM
302/* Non-zero means user is interacting with a toolkit scroll bar. */
303
304static int toolkit_scroll_bar_interaction;
dc6f92b8 305
69388238
RS
306/* Mouse movement.
307
06a2c219 308 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
309 so that we would have to call XQueryPointer after each MotionNotify
310 event to ask for another such event. However, this made mouse tracking
311 slow, and there was a bug that made it eventually stop.
312
313 Simply asking for MotionNotify all the time seems to work better.
314
69388238
RS
315 In order to avoid asking for motion events and then throwing most
316 of them away or busy-polling the server for mouse positions, we ask
317 the server for pointer motion hints. This means that we get only
318 one event per group of mouse movements. "Groups" are delimited by
319 other kinds of events (focus changes and button clicks, for
320 example), or by XQueryPointer calls; when one of these happens, we
321 get another MotionNotify event the next time the mouse moves. This
322 is at least as efficient as getting motion events when mouse
323 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 324 is off. */
69388238
RS
325
326/* Where the mouse was last time we reported a mouse event. */
69388238 327
06a2c219
GM
328FRAME_PTR last_mouse_frame;
329static XRectangle last_mouse_glyph;
2237cac9
RS
330static Lisp_Object last_mouse_press_frame;
331
69388238
RS
332/* The scroll bar in which the last X motion event occurred.
333
06a2c219
GM
334 If the last X motion event occurred in a scroll bar, we set this so
335 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
336 an ordinary motion.
337
06a2c219
GM
338 If the last X motion event didn't occur in a scroll bar, we set
339 this to Qnil, to tell XTmouse_position to return an ordinary motion
340 event. */
341
69388238
RS
342static Lisp_Object last_mouse_scroll_bar;
343
69388238
RS
344/* This is a hack. We would really prefer that XTmouse_position would
345 return the time associated with the position it returns, but there
06a2c219 346 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
347 along with the position query. So, we just keep track of the time
348 of the last movement we received, and return that in hopes that
349 it's somewhat accurate. */
06a2c219 350
69388238
RS
351static Time last_mouse_movement_time;
352
06a2c219
GM
353/* Incremented by XTread_socket whenever it really tries to read
354 events. */
355
c0a04927
RS
356#ifdef __STDC__
357static int volatile input_signal_count;
358#else
359static int input_signal_count;
360#endif
361
7a13e894 362/* Used locally within XTread_socket. */
06a2c219 363
7a13e894 364static int x_noop_count;
dc6f92b8 365
7a13e894 366/* Initial values of argv and argc. */
06a2c219 367
7a13e894
RS
368extern char **initial_argv;
369extern int initial_argc;
dc6f92b8 370
7a13e894 371extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 372
06a2c219 373/* Tells if a window manager is present or not. */
7a13e894
RS
374
375extern Lisp_Object Vx_no_window_manager;
dc6f92b8 376
c2df547c 377extern Lisp_Object Qface, Qmouse_face;
b8009dd1 378
dc6f92b8
JB
379extern int errno;
380
dfeccd2d 381/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 382
64bb1782
RS
383extern int extra_keyboard_modifiers;
384
59e755be
KH
385static Lisp_Object Qvendor_specific_keysyms;
386
334208b7 387extern XrmDatabase x_load_resources ();
c32cdd9a
KH
388extern Lisp_Object x_icon_type ();
389
7a13e894 390
06a2c219
GM
391/* Enumeration for overriding/changing the face to use for drawing
392 glyphs in x_draw_glyphs. */
393
394enum draw_glyphs_face
395{
396 DRAW_NORMAL_TEXT,
397 DRAW_INVERSE_VIDEO,
398 DRAW_CURSOR,
399 DRAW_MOUSE_FACE,
400 DRAW_IMAGE_RAISED,
401 DRAW_IMAGE_SUNKEN
402};
403
404static void x_update_window_end P_ ((struct window *, int));
405static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
406void x_delete_display P_ ((struct x_display_info *));
407static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
408 unsigned));
409static int fast_find_position P_ ((struct window *, int, int *, int *,
410 int *, int *));
411static void set_output_cursor P_ ((struct cursor_pos *));
412static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
413 int *, int *, int *));
414static void note_mode_line_highlight P_ ((struct window *, int, int));
415static void x_check_font P_ ((struct frame *, XFontStruct *));
416static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
417static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
418static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
419static void show_mouse_face P_ ((struct x_display_info *,
420 enum draw_glyphs_face));
421static int x_io_error_quitter P_ ((Display *));
422int x_catch_errors P_ ((Display *));
423void x_uncatch_errors P_ ((Display *, int));
424void x_lower_frame P_ ((struct frame *));
425void x_scroll_bar_clear P_ ((struct frame *));
426int x_had_errors_p P_ ((Display *));
427void x_wm_set_size_hint P_ ((struct frame *, long, int));
428void x_raise_frame P_ ((struct frame *));
429void x_set_window_size P_ ((struct frame *, int, int, int));
430void x_wm_set_window_state P_ ((struct frame *, int));
431void x_wm_set_icon_pixmap P_ ((struct frame *, int));
432void x_initialize P_ ((void));
433static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
434static int x_compute_min_glyph_bounds P_ ((struct frame *));
435static void x_draw_phys_cursor_glyph P_ ((struct window *,
436 struct glyph_row *,
437 enum draw_glyphs_face));
438static void x_update_end P_ ((struct frame *));
439static void XTframe_up_to_date P_ ((struct frame *));
440static void XTreassert_line_highlight P_ ((int, int));
441static void x_change_line_highlight P_ ((int, int, int, int));
442static void XTset_terminal_modes P_ ((void));
443static void XTreset_terminal_modes P_ ((void));
444static void XTcursor_to P_ ((int, int, int, int));
445static void x_write_glyphs P_ ((struct glyph *, int));
446static void x_clear_end_of_line P_ ((int));
447static void x_clear_frame P_ ((void));
448static void x_clear_cursor P_ ((struct window *));
449static void frame_highlight P_ ((struct frame *));
450static void frame_unhighlight P_ ((struct frame *));
451static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
452static void XTframe_rehighlight P_ ((struct frame *));
453static void x_frame_rehighlight P_ ((struct x_display_info *));
454static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
455static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
456static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
457 XRectangle *));
458static void expose_frame P_ ((struct frame *, int, int, int, int));
459static void expose_window_tree P_ ((struct window *, XRectangle *));
460static void expose_window P_ ((struct window *, XRectangle *));
461static void expose_area P_ ((struct window *, struct glyph_row *,
462 XRectangle *, enum glyph_row_area));
463static void expose_line P_ ((struct window *, struct glyph_row *,
464 XRectangle *));
465static void x_update_cursor_in_window_tree P_ ((struct window *, int));
466static void x_update_window_cursor P_ ((struct window *, int));
467static void x_erase_phys_cursor P_ ((struct window *));
468void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
469static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
470 enum bitmap_type));
471
472static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
473 GC, int));
474static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
475static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
476static void note_overwritten_text_cursor P_ ((struct window *, int, int));
477static void x_flush P_ ((struct frame *f));
478
479
480/* Flush display of frame F, or of all frames if F is null. */
481
482static void
483x_flush (f)
484 struct frame *f;
485{
486 BLOCK_INPUT;
487 if (f == NULL)
488 {
489 Lisp_Object rest, frame;
490 FOR_EACH_FRAME (rest, frame)
491 x_flush (XFRAME (frame));
492 }
493 else if (FRAME_X_P (f))
494 XFlush (FRAME_X_DISPLAY (f));
495 UNBLOCK_INPUT;
496}
497
dc6f92b8 498
06a2c219
GM
499/* Remove calls to XFlush by defining XFlush to an empty replacement.
500 Calls to XFlush should be unnecessary because the X output buffer
501 is flushed automatically as needed by calls to XPending,
502 XNextEvent, or XWindowEvent according to the XFlush man page.
503 XTread_socket calls XPending. Removing XFlush improves
504 performance. */
505
506#define XFlush(DISPLAY) (void) 0
b8009dd1 507
334208b7 508\f
06a2c219
GM
509/***********************************************************************
510 Debugging
511 ***********************************************************************/
512
9382638d 513#if 0
06a2c219
GM
514
515/* This is a function useful for recording debugging information about
516 the sequence of occurrences in this file. */
9382638d
KH
517
518struct record
519{
520 char *locus;
521 int type;
522};
523
524struct record event_record[100];
525
526int event_record_index;
527
528record_event (locus, type)
529 char *locus;
530 int type;
531{
532 if (event_record_index == sizeof (event_record) / sizeof (struct record))
533 event_record_index = 0;
534
535 event_record[event_record_index].locus = locus;
536 event_record[event_record_index].type = type;
537 event_record_index++;
538}
539
540#endif /* 0 */
06a2c219
GM
541
542
9382638d 543\f
334208b7
RS
544/* Return the struct x_display_info corresponding to DPY. */
545
546struct x_display_info *
547x_display_info_for_display (dpy)
548 Display *dpy;
549{
550 struct x_display_info *dpyinfo;
551
552 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
553 if (dpyinfo->display == dpy)
554 return dpyinfo;
16bd92ea 555
334208b7
RS
556 return 0;
557}
f451eb13 558
06a2c219
GM
559
560\f
561/***********************************************************************
562 Starting and ending an update
563 ***********************************************************************/
564
565/* Start an update of frame F. This function is installed as a hook
566 for update_begin, i.e. it is called when update_begin is called.
567 This function is called prior to calls to x_update_window_begin for
568 each window being updated. Currently, there is nothing to do here
569 because all interesting stuff is done on a window basis. */
dc6f92b8 570
dfcf069d 571static void
06a2c219 572x_update_begin (f)
f676886a 573 struct frame *f;
58769bee 574{
06a2c219
GM
575 /* Nothing to do. */
576}
dc6f92b8 577
dc6f92b8 578
06a2c219
GM
579/* Start update of window W. Set the global variable updated_window
580 to the window being updated and set output_cursor to the cursor
581 position of W. */
dc6f92b8 582
06a2c219
GM
583static void
584x_update_window_begin (w)
585 struct window *w;
586{
587 struct frame *f = XFRAME (WINDOW_FRAME (w));
588 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
589
590 updated_window = w;
591 set_output_cursor (&w->cursor);
b8009dd1 592
06a2c219 593 BLOCK_INPUT;
d1bc4182 594
06a2c219 595 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 596 {
514e4681 597 /* Don't do highlighting for mouse motion during the update. */
06a2c219 598 display_info->mouse_face_defer = 1;
37c2c98b 599
06a2c219
GM
600 /* If F needs to be redrawn, simply forget about any prior mouse
601 highlighting. */
9f67f20b 602 if (FRAME_GARBAGED_P (f))
06a2c219
GM
603 display_info->mouse_face_window = Qnil;
604
605 /* Can we tell that this update does not affect the window
606 where the mouse highlight is? If so, no need to turn off.
607 Likewise, don't do anything if the frame is garbaged;
608 in that case, the frame's current matrix that we would use
609 is all wrong, and we will redisplay that line anyway. */
610 if (!NILP (display_info->mouse_face_window)
611 && w == XWINDOW (display_info->mouse_face_window))
514e4681 612 {
06a2c219 613 int i;
514e4681 614
06a2c219
GM
615 for (i = 0; i < w->desired_matrix->nrows; ++i)
616 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
617 break;
618
06a2c219
GM
619 if (i < w->desired_matrix->nrows)
620 clear_mouse_face (display_info);
514e4681 621 }
b8009dd1 622 }
6ccf47d1 623
dc6f92b8
JB
624 UNBLOCK_INPUT;
625}
626
06a2c219
GM
627
628/* Draw a vertical window border to the right of window W if W doesn't
629 have vertical scroll bars. */
630
dfcf069d 631static void
06a2c219
GM
632x_draw_vertical_border (w)
633 struct window *w;
58769bee 634{
06a2c219
GM
635 struct frame *f = XFRAME (WINDOW_FRAME (w));
636
637 /* Redraw borders between horizontally adjacent windows. Don't
638 do it for frames with vertical scroll bars because either the
639 right scroll bar of a window, or the left scroll bar of its
640 neighbor will suffice as a border. */
641 if (!WINDOW_RIGHTMOST_P (w)
642 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
643 {
644 int x0, x1, y0, y1;
dc6f92b8 645
06a2c219 646 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 647 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
648 y1 -= 1;
649
650 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
651 f->output_data.x->normal_gc, x1, y0, x1, y1);
652 }
653}
654
655
656/* End update of window W (which is equal to updated_window). Draw
657 vertical borders between horizontally adjacent windows, and display
658 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
659 pseudo-window in case we don't have X toolkit support. Such
660 windows don't have a cursor, so don't display it here. */
661
662static void
663x_update_window_end (w, cursor_on_p)
664 struct window *w;
665 int cursor_on_p;
666{
667 if (!w->pseudo_window_p)
668 {
669 BLOCK_INPUT;
670 if (cursor_on_p)
671 x_display_and_set_cursor (w, 1, output_cursor.hpos,
672 output_cursor.vpos,
673 output_cursor.x, output_cursor.y);
674 x_draw_vertical_border (w);
675 UNBLOCK_INPUT;
676 }
677
678 updated_window = NULL;
679}
dc6f92b8 680
dc6f92b8 681
06a2c219
GM
682/* End update of frame F. This function is installed as a hook in
683 update_end. */
684
685static void
686x_update_end (f)
687 struct frame *f;
688{
689 /* Mouse highlight may be displayed again. */
aa8bff2e 690 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 691
06a2c219 692 BLOCK_INPUT;
334208b7 693 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
694 UNBLOCK_INPUT;
695}
b8009dd1 696
06a2c219
GM
697
698/* This function is called from various places in xdisp.c whenever a
699 complete update has been performed. The global variable
700 updated_window is not available here. */
b8009dd1 701
dfcf069d 702static void
b8009dd1 703XTframe_up_to_date (f)
06a2c219 704 struct frame *f;
b8009dd1 705{
06a2c219 706 if (FRAME_X_P (f))
514e4681 707 {
06a2c219
GM
708 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
709 if (dpyinfo->mouse_face_deferred_gc
710 || f == dpyinfo->mouse_face_mouse_frame)
711 {
712 BLOCK_INPUT;
713 if (dpyinfo->mouse_face_mouse_frame)
714 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
715 dpyinfo->mouse_face_mouse_x,
716 dpyinfo->mouse_face_mouse_y);
717 dpyinfo->mouse_face_deferred_gc = 0;
718 UNBLOCK_INPUT;
719 }
514e4681 720 }
b8009dd1 721}
06a2c219
GM
722
723
724/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
725 arrow bitmaps, or clear the areas where they would be displayed
726 before DESIRED_ROW is made current. The window being updated is
727 found in updated_window. This function It is called from
728 update_window_line only if it is known that there are differences
729 between bitmaps to be drawn between current row and DESIRED_ROW. */
730
731static void
732x_after_update_window_line (desired_row)
733 struct glyph_row *desired_row;
734{
735 struct window *w = updated_window;
736
737 xassert (w);
738
739 if (!desired_row->mode_line_p && !w->pseudo_window_p)
740 {
741 BLOCK_INPUT;
742 x_draw_row_bitmaps (w, desired_row);
743
744 /* When a window has disappeared, make sure that no rest of
745 full-width rows stays visible in the internal border. */
746 if (windows_or_buffers_changed)
747 {
748 struct frame *f = XFRAME (w->frame);
749 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
750 int height = desired_row->visible_height;
110859fc
GM
751 int x = (window_box_right (w, -1)
752 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
753 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
754
755 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
756 x, y, width, height, False);
757 }
758
759 UNBLOCK_INPUT;
760 }
761}
762
763
764/* Draw the bitmap WHICH in one of the areas to the left or right of
765 window W. ROW is the glyph row for which to display the bitmap; it
766 determines the vertical position at which the bitmap has to be
767 drawn. */
768
769static void
770x_draw_bitmap (w, row, which)
771 struct window *w;
772 struct glyph_row *row;
773 enum bitmap_type which;
774{
775 struct frame *f = XFRAME (WINDOW_FRAME (w));
776 Display *display = FRAME_X_DISPLAY (f);
777 Window window = FRAME_X_WINDOW (f);
778 int x, y, wd, h, dy;
779 unsigned char *bits;
780 Pixmap pixmap;
781 GC gc = f->output_data.x->normal_gc;
782 struct face *face;
783 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
784
785 /* Must clip because of partially visible lines. */
786 x_clip_to_row (w, row, gc, 1);
787
788 switch (which)
789 {
790 case LEFT_TRUNCATION_BITMAP:
791 wd = left_width;
792 h = left_height;
793 bits = left_bits;
794 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
795 - wd
110859fc 796 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
797 break;
798
799 case OVERLAY_ARROW_BITMAP:
800 wd = left_width;
801 h = left_height;
802 bits = ov_bits;
803 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
804 - wd
110859fc 805 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
806 break;
807
808 case RIGHT_TRUNCATION_BITMAP:
809 wd = right_width;
810 h = right_height;
811 bits = right_bits;
812 x = window_box_right (w, -1);
110859fc 813 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
814 break;
815
816 case CONTINUED_LINE_BITMAP:
817 wd = right_width;
818 h = right_height;
819 bits = continued_bits;
820 x = window_box_right (w, -1);
110859fc 821 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
822 break;
823
824 case CONTINUATION_LINE_BITMAP:
825 wd = continuation_width;
826 h = continuation_height;
827 bits = continuation_bits;
828 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
829 - wd
110859fc 830 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
831 break;
832
833 case ZV_LINE_BITMAP:
834 wd = zv_width;
835 h = zv_height;
836 bits = zv_bits;
837 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
838 - wd
110859fc 839 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
840 break;
841
842 default:
843 abort ();
844 }
845
846 /* Convert to frame coordinates. Set dy to the offset in the row to
847 start drawing the bitmap. */
848 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
849 dy = (row->height - h) / 2;
850
851 /* Draw the bitmap. I believe these small pixmaps can be cached
852 by the server. */
853 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
854 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
855 face->foreground,
856 face->background, depth);
857 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
858 XFreePixmap (display, pixmap);
859 XSetClipMask (display, gc, None);
860}
861
862
863/* Draw flags bitmaps for glyph row ROW on window W. Call this
864 function with input blocked. */
865
866static void
867x_draw_row_bitmaps (w, row)
868 struct window *w;
869 struct glyph_row *row;
870{
871 struct frame *f = XFRAME (w->frame);
872 enum bitmap_type bitmap;
873 struct face *face;
045dee35 874 int header_line_height = -1;
06a2c219
GM
875
876 xassert (interrupt_input_blocked);
877
878 /* If row is completely invisible, because of vscrolling, we
879 don't have to draw anything. */
880 if (row->visible_height <= 0)
881 return;
882
883 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
884 PREPARE_FACE_FOR_DISPLAY (f, face);
885
886 /* Decide which bitmap to draw at the left side. */
887 if (row->overlay_arrow_p)
888 bitmap = OVERLAY_ARROW_BITMAP;
889 else if (row->truncated_on_left_p)
890 bitmap = LEFT_TRUNCATION_BITMAP;
891 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
892 bitmap = CONTINUATION_LINE_BITMAP;
893 else if (row->indicate_empty_line_p)
894 bitmap = ZV_LINE_BITMAP;
895 else
896 bitmap = NO_BITMAP;
897
898 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
899 the flags area. */
900 if (bitmap == NO_BITMAP
110859fc 901 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
902 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
903 {
904 /* If W has a vertical border to its left, don't draw over it. */
905 int border = ((XFASTINT (w->left) > 0
906 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
907 ? 1 : 0);
908 int left = window_box_left (w, -1);
909
045dee35
GM
910 if (header_line_height < 0)
911 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
912
913 /* In case the same realized face is used for bitmap areas and
914 for something displayed in the text (e.g. face `region' on
915 mono-displays, the fill style may have been changed to
916 FillSolid in x_draw_glyph_string_background. */
917 if (face->stipple)
918 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
919 else
920 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
921
06a2c219
GM
922 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
923 face->gc,
924 (left
110859fc 925 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 926 + border),
045dee35 927 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 928 row->y)),
110859fc 929 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 930 row->visible_height);
dcd08bfb
GM
931 if (!face->stipple)
932 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
933 }
934
935 /* Draw the left bitmap. */
936 if (bitmap != NO_BITMAP)
937 x_draw_bitmap (w, row, bitmap);
938
939 /* Decide which bitmap to draw at the right side. */
940 if (row->truncated_on_right_p)
941 bitmap = RIGHT_TRUNCATION_BITMAP;
942 else if (row->continued_p)
943 bitmap = CONTINUED_LINE_BITMAP;
944 else
945 bitmap = NO_BITMAP;
946
947 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
948 the flags area. */
949 if (bitmap == NO_BITMAP
110859fc 950 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
951 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
952 {
953 int right = window_box_right (w, -1);
954
045dee35
GM
955 if (header_line_height < 0)
956 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
957
958 /* In case the same realized face is used for bitmap areas and
959 for something displayed in the text (e.g. face `region' on
960 mono-displays, the fill style may have been changed to
961 FillSolid in x_draw_glyph_string_background. */
962 if (face->stipple)
963 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
964 else
965 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
966 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
967 face->gc,
968 right,
045dee35 969 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 970 row->y)),
110859fc 971 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 972 row->visible_height);
dcd08bfb
GM
973 if (!face->stipple)
974 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
975 }
976
977 /* Draw the right bitmap. */
978 if (bitmap != NO_BITMAP)
979 x_draw_bitmap (w, row, bitmap);
980}
981
dc6f92b8 982\f
06a2c219
GM
983/***********************************************************************
984 Line Highlighting
985 ***********************************************************************/
dc6f92b8 986
06a2c219
GM
987/* External interface to control of standout mode. Not used for X
988 frames. Aborts when called. */
989
990static void
dc6f92b8
JB
991XTreassert_line_highlight (new, vpos)
992 int new, vpos;
993{
06a2c219 994 abort ();
dc6f92b8
JB
995}
996
06a2c219
GM
997
998/* Call this when about to modify line at position VPOS and change
999 whether it is highlighted. Not used for X frames. Aborts when
1000 called. */
dc6f92b8 1001
dfcf069d 1002static void
06a2c219
GM
1003x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1004 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1005{
06a2c219 1006 abort ();
dc6f92b8
JB
1007}
1008
06a2c219
GM
1009
1010/* This is called when starting Emacs and when restarting after
1011 suspend. When starting Emacs, no X window is mapped. And nothing
1012 must be done to Emacs's own window if it is suspended (though that
1013 rarely happens). */
dc6f92b8 1014
dfcf069d 1015static void
dc6f92b8
JB
1016XTset_terminal_modes ()
1017{
1018}
1019
06a2c219
GM
1020/* This is called when exiting or suspending Emacs. Exiting will make
1021 the X-windows go away, and suspending requires no action. */
dc6f92b8 1022
dfcf069d 1023static void
dc6f92b8
JB
1024XTreset_terminal_modes ()
1025{
dc6f92b8 1026}
06a2c219
GM
1027
1028
dc6f92b8 1029\f
06a2c219
GM
1030/***********************************************************************
1031 Output Cursor
1032 ***********************************************************************/
1033
1034/* Set the global variable output_cursor to CURSOR. All cursor
1035 positions are relative to updated_window. */
dc6f92b8 1036
dfcf069d 1037static void
06a2c219
GM
1038set_output_cursor (cursor)
1039 struct cursor_pos *cursor;
dc6f92b8 1040{
06a2c219
GM
1041 output_cursor.hpos = cursor->hpos;
1042 output_cursor.vpos = cursor->vpos;
1043 output_cursor.x = cursor->x;
1044 output_cursor.y = cursor->y;
1045}
1046
1047
1048/* Set a nominal cursor position.
dc6f92b8 1049
06a2c219
GM
1050 HPOS and VPOS are column/row positions in a window glyph matrix. X
1051 and Y are window text area relative pixel positions.
1052
1053 If this is done during an update, updated_window will contain the
1054 window that is being updated and the position is the future output
1055 cursor position for that window. If updated_window is null, use
1056 selected_window and display the cursor at the given position. */
1057
1058static void
1059XTcursor_to (vpos, hpos, y, x)
1060 int vpos, hpos, y, x;
1061{
1062 struct window *w;
1063
1064 /* If updated_window is not set, work on selected_window. */
1065 if (updated_window)
1066 w = updated_window;
1067 else
1068 w = XWINDOW (selected_window);
dbcb258a 1069
06a2c219
GM
1070 /* Set the output cursor. */
1071 output_cursor.hpos = hpos;
1072 output_cursor.vpos = vpos;
1073 output_cursor.x = x;
1074 output_cursor.y = y;
dc6f92b8 1075
06a2c219
GM
1076 /* If not called as part of an update, really display the cursor.
1077 This will also set the cursor position of W. */
1078 if (updated_window == NULL)
dc6f92b8
JB
1079 {
1080 BLOCK_INPUT;
06a2c219 1081 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1082 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1083 UNBLOCK_INPUT;
1084 }
1085}
dc43ef94 1086
06a2c219
GM
1087
1088\f
1089/***********************************************************************
1090 Display Iterator
1091 ***********************************************************************/
1092
1093/* Function prototypes of this page. */
1094
1095static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1096 struct glyph *,
ee569018
KH
1097 XChar2b *,
1098 int *));
06a2c219
GM
1099static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1100 int, XChar2b *, int));
1101static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1102static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1103static void x_append_glyph P_ ((struct it *));
b4192550 1104static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1105static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1106 int, int, double));
1107static void x_produce_glyphs P_ ((struct it *));
06a2c219 1108static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1109
1110
1111/* Return a pointer to per-char metric information in FONT of a
1112 character pointed by B which is a pointer to an XChar2b. */
1113
1114#define PER_CHAR_METRIC(font, b) \
1115 ((font)->per_char \
1116 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1117 + (((font)->min_byte1 || (font)->max_byte1) \
1118 ? (((b)->byte1 - (font)->min_byte1) \
1119 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1120 : 0)) \
1121 : &((font)->max_bounds))
dc43ef94 1122
dc6f92b8 1123
e2ef8ee6
GM
1124/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1125 is not contained in the font. */
dc43ef94 1126
06a2c219 1127static INLINE XCharStruct *
ee569018 1128x_per_char_metric (font, char2b)
06a2c219
GM
1129 XFontStruct *font;
1130 XChar2b *char2b;
1131{
1132 /* The result metric information. */
1133 XCharStruct *pcm = NULL;
dc6f92b8 1134
06a2c219 1135 xassert (font && char2b);
dc6f92b8 1136
06a2c219 1137 if (font->per_char != NULL)
dc6f92b8 1138 {
06a2c219 1139 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1140 {
06a2c219
GM
1141 /* min_char_or_byte2 specifies the linear character index
1142 corresponding to the first element of the per_char array,
1143 max_char_or_byte2 is the index of the last character. A
1144 character with non-zero CHAR2B->byte1 is not in the font.
1145 A character with byte2 less than min_char_or_byte2 or
1146 greater max_char_or_byte2 is not in the font. */
1147 if (char2b->byte1 == 0
1148 && char2b->byte2 >= font->min_char_or_byte2
1149 && char2b->byte2 <= font->max_char_or_byte2)
1150 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1151 }
06a2c219 1152 else
dc6f92b8 1153 {
06a2c219
GM
1154 /* If either min_byte1 or max_byte1 are nonzero, both
1155 min_char_or_byte2 and max_char_or_byte2 are less than
1156 256, and the 2-byte character index values corresponding
1157 to the per_char array element N (counting from 0) are:
1158
1159 byte1 = N/D + min_byte1
1160 byte2 = N\D + min_char_or_byte2
1161
1162 where:
1163
1164 D = max_char_or_byte2 - min_char_or_byte2 + 1
1165 / = integer division
1166 \ = integer modulus */
1167 if (char2b->byte1 >= font->min_byte1
1168 && char2b->byte1 <= font->max_byte1
1169 && char2b->byte2 >= font->min_char_or_byte2
1170 && char2b->byte2 <= font->max_char_or_byte2)
1171 {
1172 pcm = (font->per_char
1173 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1174 * (char2b->byte1 - font->min_byte1))
1175 + (char2b->byte2 - font->min_char_or_byte2));
1176 }
dc6f92b8 1177 }
06a2c219
GM
1178 }
1179 else
1180 {
1181 /* If the per_char pointer is null, all glyphs between the first
1182 and last character indexes inclusive have the same
1183 information, as given by both min_bounds and max_bounds. */
1184 if (char2b->byte2 >= font->min_char_or_byte2
1185 && char2b->byte2 <= font->max_char_or_byte2)
1186 pcm = &font->max_bounds;
1187 }
dc6f92b8 1188
ee569018
KH
1189 return ((pcm == NULL
1190 || pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1191 ? NULL : pcm);
06a2c219 1192}
b73b6aaf 1193
57b03282 1194
06a2c219
GM
1195/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1196 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1197
06a2c219
GM
1198static INLINE void
1199x_encode_char (c, char2b, font_info)
1200 int c;
1201 XChar2b *char2b;
1202 struct font_info *font_info;
1203{
1204 int charset = CHAR_CHARSET (c);
1205 XFontStruct *font = font_info->font;
1206
1207 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1208 This may be either a program in a special encoder language or a
1209 fixed encoding. */
1210 if (font_info->font_encoder)
1211 {
1212 /* It's a program. */
1213 struct ccl_program *ccl = font_info->font_encoder;
1214
1215 if (CHARSET_DIMENSION (charset) == 1)
1216 {
1217 ccl->reg[0] = charset;
1218 ccl->reg[1] = char2b->byte2;
1219 }
1220 else
1221 {
1222 ccl->reg[0] = charset;
1223 ccl->reg[1] = char2b->byte1;
1224 ccl->reg[2] = char2b->byte2;
1225 }
1226
1227 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1228
1229 /* We assume that MSBs are appropriately set/reset by CCL
1230 program. */
1231 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1232 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1233 else
1234 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1235 }
1236 else if (font_info->encoding[charset])
1237 {
1238 /* Fixed encoding scheme. See fontset.h for the meaning of the
1239 encoding numbers. */
1240 int enc = font_info->encoding[charset];
1241
1242 if ((enc == 1 || enc == 2)
1243 && CHARSET_DIMENSION (charset) == 2)
1244 char2b->byte1 |= 0x80;
1245
1246 if (enc == 1 || enc == 3)
1247 char2b->byte2 |= 0x80;
1248 }
1249}
1250
1251
1252/* Get face and two-byte form of character C in face FACE_ID on frame
1253 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1254 means we want to display multibyte text. Value is a pointer to a
1255 realized face that is ready for display. */
1256
1257static INLINE struct face *
1258x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1259 struct frame *f;
1260 int c, face_id;
1261 XChar2b *char2b;
1262 int multibyte_p;
1263{
1264 struct face *face = FACE_FROM_ID (f, face_id);
1265
1266 if (!multibyte_p)
1267 {
1268 /* Unibyte case. We don't have to encode, but we have to make
1269 sure to use a face suitable for unibyte. */
1270 char2b->byte1 = 0;
1271 char2b->byte2 = c;
ee569018
KH
1272 face_id = FACE_FOR_CHAR (f, face, c);
1273 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1274 }
1275 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1276 {
1277 /* Case of ASCII in a face known to fit ASCII. */
1278 char2b->byte1 = 0;
1279 char2b->byte2 = c;
1280 }
1281 else
1282 {
1283 int c1, c2, charset;
1284
1285 /* Split characters into bytes. If c2 is -1 afterwards, C is
1286 really a one-byte character so that byte1 is zero. */
1287 SPLIT_CHAR (c, charset, c1, c2);
1288 if (c2 > 0)
1289 char2b->byte1 = c1, char2b->byte2 = c2;
1290 else
1291 char2b->byte1 = 0, char2b->byte2 = c1;
1292
06a2c219 1293 /* Maybe encode the character in *CHAR2B. */
ee569018 1294 if (face->font != NULL)
06a2c219
GM
1295 {
1296 struct font_info *font_info
1297 = FONT_INFO_FROM_ID (f, face->font_info_id);
1298 if (font_info)
ee569018 1299 x_encode_char (c, char2b, font_info);
06a2c219
GM
1300 }
1301 }
1302
1303 /* Make sure X resources of the face are allocated. */
1304 xassert (face != NULL);
1305 PREPARE_FACE_FOR_DISPLAY (f, face);
1306
1307 return face;
1308}
1309
1310
1311/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1312 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1313 a pointer to a realized face that is ready for display. */
1314
1315static INLINE struct face *
ee569018 1316x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1317 struct frame *f;
1318 struct glyph *glyph;
1319 XChar2b *char2b;
ee569018 1320 int *two_byte_p;
06a2c219
GM
1321{
1322 struct face *face;
1323
1324 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1325 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1326
ee569018
KH
1327 if (two_byte_p)
1328 *two_byte_p = 0;
1329
06a2c219
GM
1330 if (!glyph->multibyte_p)
1331 {
1332 /* Unibyte case. We don't have to encode, but we have to make
1333 sure to use a face suitable for unibyte. */
1334 char2b->byte1 = 0;
43d120d8 1335 char2b->byte2 = glyph->u.ch;
06a2c219 1336 }
43d120d8
KH
1337 else if (glyph->u.ch < 128
1338 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1339 {
1340 /* Case of ASCII in a face known to fit ASCII. */
1341 char2b->byte1 = 0;
43d120d8 1342 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1343 }
1344 else
1345 {
1346 int c1, c2, charset;
1347
1348 /* Split characters into bytes. If c2 is -1 afterwards, C is
1349 really a one-byte character so that byte1 is zero. */
43d120d8 1350 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1351 if (c2 > 0)
1352 char2b->byte1 = c1, char2b->byte2 = c2;
1353 else
1354 char2b->byte1 = 0, char2b->byte2 = c1;
1355
1356 /* Maybe encode the character in *CHAR2B. */
1357 if (charset != CHARSET_ASCII)
1358 {
1359 struct font_info *font_info
1360 = FONT_INFO_FROM_ID (f, face->font_info_id);
1361 if (font_info)
1362 {
43d120d8 1363 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1364 if (two_byte_p)
1365 *two_byte_p
1366 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1367 }
1368 }
1369 }
1370
1371 /* Make sure X resources of the face are allocated. */
1372 xassert (face != NULL);
1373 PREPARE_FACE_FOR_DISPLAY (f, face);
1374 return face;
1375}
1376
1377
1378/* Store one glyph for IT->char_to_display in IT->glyph_row.
1379 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1380
1381static INLINE void
1382x_append_glyph (it)
1383 struct it *it;
1384{
1385 struct glyph *glyph;
1386 enum glyph_row_area area = it->area;
1387
1388 xassert (it->glyph_row);
1389 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1390
1391 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1392 if (glyph < it->glyph_row->glyphs[area + 1])
1393 {
1394 /* Play it safe. If sub-structures of the glyph are not all the
1395 same size, it otherwise be that some bits stay set. This
1396 would prevent a comparison with GLYPH_EQUAL_P. */
1397 glyph->u.val = 0;
1398
1399 glyph->type = CHAR_GLYPH;
1400 glyph->pixel_width = it->pixel_width;
43d120d8
KH
1401 glyph->u.ch = it->char_to_display;
1402 glyph->face_id = it->face_id;
06a2c219
GM
1403 glyph->charpos = CHARPOS (it->position);
1404 glyph->object = it->object;
1405 glyph->left_box_line_p = it->start_of_box_run_p;
1406 glyph->right_box_line_p = it->end_of_box_run_p;
1407 glyph->voffset = it->voffset;
1408 glyph->multibyte_p = it->multibyte_p;
66ac4b0e
GM
1409 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1410 || it->phys_descent > it->descent);
ee569018 1411 glyph->glyph_not_available_p = it->glyph_not_available_p;
06a2c219
GM
1412 ++it->glyph_row->used[area];
1413 }
1414}
1415
b4192550
KH
1416/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1417 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1418
1419static INLINE void
1420x_append_composite_glyph (it)
1421 struct it *it;
1422{
1423 struct glyph *glyph;
1424 enum glyph_row_area area = it->area;
1425
1426 xassert (it->glyph_row);
1427
1428 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1429 if (glyph < it->glyph_row->glyphs[area + 1])
1430 {
1431 /* Play it safe. If sub-structures of the glyph are not all the
1432 same size, it otherwise be that some bits stay set. This
1433 would prevent a comparison with GLYPH_EQUAL_P. */
1434 glyph->u.val = 0;
1435
1436 glyph->type = COMPOSITE_GLYPH;
1437 glyph->pixel_width = it->pixel_width;
43d120d8
KH
1438 glyph->u.cmp_id = it->cmp_id;
1439 glyph->face_id = it->face_id;
b4192550
KH
1440 glyph->charpos = CHARPOS (it->position);
1441 glyph->object = it->object;
1442 glyph->left_box_line_p = it->start_of_box_run_p;
1443 glyph->right_box_line_p = it->end_of_box_run_p;
1444 glyph->voffset = it->voffset;
1445 glyph->multibyte_p = it->multibyte_p;
1446 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1447 || it->phys_descent > it->descent);
1448 ++it->glyph_row->used[area];
1449 }
1450}
1451
06a2c219
GM
1452
1453/* Change IT->ascent and IT->height according to the setting of
1454 IT->voffset. */
1455
1456static INLINE void
1457take_vertical_position_into_account (it)
1458 struct it *it;
1459{
1460 if (it->voffset)
1461 {
1462 if (it->voffset < 0)
1463 /* Increase the ascent so that we can display the text higher
1464 in the line. */
1465 it->ascent += abs (it->voffset);
1466 else
1467 /* Increase the descent so that we can display the text lower
1468 in the line. */
1469 it->descent += it->voffset;
1470 }
1471}
1472
1473
1474/* Produce glyphs/get display metrics for the image IT is loaded with.
1475 See the description of struct display_iterator in dispextern.h for
1476 an overview of struct display_iterator. */
1477
1478static void
1479x_produce_image_glyph (it)
1480 struct it *it;
1481{
1482 struct image *img;
1483 struct face *face;
1484
1485 xassert (it->what == IT_IMAGE);
1486
1487 face = FACE_FROM_ID (it->f, it->face_id);
1488 img = IMAGE_FROM_ID (it->f, it->image_id);
1489 xassert (img);
1490
1491 /* Make sure X resources of the face and image are loaded. */
1492 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1493 prepare_image_for_display (it->f, img);
1494
66ac4b0e
GM
1495 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1496 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1497 it->pixel_width = img->width + 2 * img->margin;
1498
1499 it->nglyphs = 1;
1500
1501 if (face->box != FACE_NO_BOX)
1502 {
1503 it->ascent += face->box_line_width;
1504 it->descent += face->box_line_width;
1505
1506 if (it->start_of_box_run_p)
1507 it->pixel_width += face->box_line_width;
1508 if (it->end_of_box_run_p)
1509 it->pixel_width += face->box_line_width;
1510 }
1511
1512 take_vertical_position_into_account (it);
1513
1514 if (it->glyph_row)
1515 {
1516 struct glyph *glyph;
1517 enum glyph_row_area area = it->area;
1518
1519 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1520 if (glyph < it->glyph_row->glyphs[area + 1])
1521 {
1522 glyph->type = IMAGE_GLYPH;
43d120d8
KH
1523 glyph->u.img_id = img->id;
1524 glyph->face_id = it->face_id;
06a2c219
GM
1525 glyph->pixel_width = it->pixel_width;
1526 glyph->charpos = CHARPOS (it->position);
1527 glyph->object = it->object;
1528 glyph->left_box_line_p = it->start_of_box_run_p;
1529 glyph->right_box_line_p = it->end_of_box_run_p;
1530 glyph->voffset = it->voffset;
1531 glyph->multibyte_p = it->multibyte_p;
1532 ++it->glyph_row->used[area];
1533 }
1534 }
1535}
1536
1537
1538/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1539 of the glyph, WIDTH and HEIGHT are the width and height of the
1540 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1541 ascent of the glyph (0 <= ASCENT <= 1). */
1542
1543static void
1544x_append_stretch_glyph (it, object, width, height, ascent)
1545 struct it *it;
1546 Lisp_Object object;
1547 int width, height;
1548 double ascent;
1549{
1550 struct glyph *glyph;
1551 enum glyph_row_area area = it->area;
1552
1553 xassert (ascent >= 0 && ascent <= 1);
1554
1555 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1556 if (glyph < it->glyph_row->glyphs[area + 1])
1557 {
1558 glyph->type = STRETCH_GLYPH;
1559 glyph->u.stretch.ascent = height * ascent;
1560 glyph->u.stretch.height = height;
43d120d8 1561 glyph->face_id = it->face_id;
06a2c219
GM
1562 glyph->pixel_width = width;
1563 glyph->charpos = CHARPOS (it->position);
1564 glyph->object = object;
1565 glyph->left_box_line_p = it->start_of_box_run_p;
1566 glyph->right_box_line_p = it->end_of_box_run_p;
1567 glyph->voffset = it->voffset;
1568 glyph->multibyte_p = it->multibyte_p;
1569 ++it->glyph_row->used[area];
1570 }
1571}
1572
1573
1574/* Produce a stretch glyph for iterator IT. IT->object is the value
1575 of the glyph property displayed. The value must be a list
1576 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1577 being recognized:
1578
1579 1. `:width WIDTH' specifies that the space should be WIDTH *
1580 canonical char width wide. WIDTH may be an integer or floating
1581 point number.
1582
1583 2. `:relative-width FACTOR' specifies that the width of the stretch
1584 should be computed from the width of the first character having the
1585 `glyph' property, and should be FACTOR times that width.
1586
1587 3. `:align-to HPOS' specifies that the space should be wide enough
1588 to reach HPOS, a value in canonical character units.
1589
1590 Exactly one of the above pairs must be present.
1591
1592 4. `:height HEIGHT' specifies that the height of the stretch produced
1593 should be HEIGHT, measured in canonical character units.
1594
1595 5. `:relative-height FACTOR' specifies that the height of the the
1596 stretch should be FACTOR times the height of the characters having
1597 the glyph property.
1598
1599 Either none or exactly one of 4 or 5 must be present.
1600
1601 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1602 of the stretch should be used for the ascent of the stretch.
1603 ASCENT must be in the range 0 <= ASCENT <= 100. */
1604
1605#define NUMVAL(X) \
1606 ((INTEGERP (X) || FLOATP (X)) \
1607 ? XFLOATINT (X) \
1608 : - 1)
1609
1610
1611static void
1612x_produce_stretch_glyph (it)
1613 struct it *it;
1614{
1615 /* (space :width WIDTH :height HEIGHT. */
1616 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1617 extern Lisp_Object QCrelative_width, QCrelative_height;
1618 extern Lisp_Object QCalign_to;
1619 Lisp_Object prop, plist;
1620 double width = 0, height = 0, ascent = 0;
1621 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1622 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1623
1624 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1625
1626 /* List should start with `space'. */
1627 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1628 plist = XCDR (it->object);
1629
1630 /* Compute the width of the stretch. */
1631 if (prop = Fplist_get (plist, QCwidth),
1632 NUMVAL (prop) > 0)
1633 /* Absolute width `:width WIDTH' specified and valid. */
1634 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1635 else if (prop = Fplist_get (plist, QCrelative_width),
1636 NUMVAL (prop) > 0)
1637 {
1638 /* Relative width `:relative-width FACTOR' specified and valid.
1639 Compute the width of the characters having the `glyph'
1640 property. */
1641 struct it it2;
1642 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1643
1644 it2 = *it;
1645 if (it->multibyte_p)
1646 {
1647 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1648 - IT_BYTEPOS (*it));
1649 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1650 }
1651 else
1652 it2.c = *p, it2.len = 1;
1653
1654 it2.glyph_row = NULL;
1655 it2.what = IT_CHARACTER;
1656 x_produce_glyphs (&it2);
1657 width = NUMVAL (prop) * it2.pixel_width;
1658 }
1659 else if (prop = Fplist_get (plist, QCalign_to),
1660 NUMVAL (prop) > 0)
1661 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1662 else
1663 /* Nothing specified -> width defaults to canonical char width. */
1664 width = CANON_X_UNIT (it->f);
1665
1666 /* Compute height. */
1667 if (prop = Fplist_get (plist, QCheight),
1668 NUMVAL (prop) > 0)
1669 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1670 else if (prop = Fplist_get (plist, QCrelative_height),
1671 NUMVAL (prop) > 0)
1672 height = FONT_HEIGHT (font) * NUMVAL (prop);
1673 else
1674 height = FONT_HEIGHT (font);
1675
1676 /* Compute percentage of height used for ascent. If
1677 `:ascent ASCENT' is present and valid, use that. Otherwise,
1678 derive the ascent from the font in use. */
1679 if (prop = Fplist_get (plist, QCascent),
1680 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1681 ascent = NUMVAL (prop) / 100.0;
1682 else
1683 ascent = (double) font->ascent / FONT_HEIGHT (font);
1684
1685 if (width <= 0)
1686 width = 1;
1687 if (height <= 0)
1688 height = 1;
1689
1690 if (it->glyph_row)
1691 {
1692 Lisp_Object object = it->stack[it->sp - 1].string;
1693 if (!STRINGP (object))
1694 object = it->w->buffer;
1695 x_append_stretch_glyph (it, object, width, height, ascent);
1696 }
1697
1698 it->pixel_width = width;
66ac4b0e
GM
1699 it->ascent = it->phys_ascent = height * ascent;
1700 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1701 it->nglyphs = 1;
1702
1703 if (face->box != FACE_NO_BOX)
1704 {
1705 it->ascent += face->box_line_width;
1706 it->descent += face->box_line_width;
1707
1708 if (it->start_of_box_run_p)
1709 it->pixel_width += face->box_line_width;
1710 if (it->end_of_box_run_p)
1711 it->pixel_width += face->box_line_width;
1712 }
1713
1714 take_vertical_position_into_account (it);
1715}
1716
b4192550
KH
1717/* Return proper value to be used as baseline offset of font that has
1718 ASCENT and DESCENT to draw characters by the font at the vertical
1719 center of the line of frame F.
1720
1721 Here, out task is to find the value of BOFF in the following figure;
1722
1723 -------------------------+-----------+-
1724 -+-+---------+-+ | |
1725 | | | | | |
1726 | | | | F_ASCENT F_HEIGHT
1727 | | | ASCENT | |
1728 HEIGHT | | | | |
1729 | | |-|-+------+-----------|------- baseline
1730 | | | | BOFF | |
1731 | |---------|-+-+ | |
1732 | | | DESCENT | |
1733 -+-+---------+-+ F_DESCENT |
1734 -------------------------+-----------+-
1735
1736 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1737 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1738 DESCENT = FONT->descent
1739 HEIGHT = FONT_HEIGHT (FONT)
1740 F_DESCENT = (F->output_data.x->font->descent
1741 - F->output_data.x->baseline_offset)
1742 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1743*/
1744
1745#define VCENTER_BASELINE_OFFSET(FONT, F) \
1746 ((FONT)->descent \
1747 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1748 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1749
1750/* Produce glyphs/get display metrics for the display element IT is
1751 loaded with. See the description of struct display_iterator in
1752 dispextern.h for an overview of struct display_iterator. */
1753
1754static void
1755x_produce_glyphs (it)
1756 struct it *it;
1757{
ee569018
KH
1758 it->glyph_not_available_p = 0;
1759
06a2c219
GM
1760 if (it->what == IT_CHARACTER)
1761 {
1762 XChar2b char2b;
1763 XFontStruct *font;
ee569018 1764 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1765 XCharStruct *pcm;
06a2c219 1766 int font_not_found_p;
b4192550
KH
1767 struct font_info *font_info;
1768 int boff; /* baseline offset */
06a2c219 1769
ee569018
KH
1770 /* Maybe translate single-byte characters to multibyte, or the
1771 other way. */
06a2c219 1772 it->char_to_display = it->c;
ee569018 1773 if (!ASCII_BYTE_P (it->c))
06a2c219 1774 {
ee569018
KH
1775 if (unibyte_display_via_language_environment
1776 && SINGLE_BYTE_CHAR_P (it->c)
1777 && (it->c >= 0240
1778 || !NILP (Vnonascii_translation_table)))
1779 {
1780 it->char_to_display = unibyte_char_to_multibyte (it->c);
1781 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1782 face = FACE_FROM_ID (it->f, it->face_id);
1783 }
1784 else if (!SINGLE_BYTE_CHAR_P (it->c)
1785 && !it->multibyte_p)
1786 {
1787 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1788 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1789 face = FACE_FROM_ID (it->f, it->face_id);
1790 }
06a2c219
GM
1791 }
1792
ee569018
KH
1793 /* Get font to use. Encode IT->char_to_display. */
1794 x_get_char_face_and_encoding (it->f, it->char_to_display,
1795 it->face_id, &char2b,
1796 it->multibyte_p);
06a2c219
GM
1797 font = face->font;
1798
1799 /* When no suitable font found, use the default font. */
1800 font_not_found_p = font == NULL;
1801 if (font_not_found_p)
b4192550
KH
1802 {
1803 font = FRAME_FONT (it->f);
1804 boff = it->f->output_data.x->baseline_offset;
1805 font_info = NULL;
1806 }
1807 else
1808 {
1809 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1810 boff = font_info->baseline_offset;
1811 if (font_info->vertical_centering)
1812 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1813 }
06a2c219
GM
1814
1815 if (it->char_to_display >= ' '
1816 && (!it->multibyte_p || it->char_to_display < 128))
1817 {
1818 /* Either unibyte or ASCII. */
1819 int stretched_p;
1820
1821 it->nglyphs = 1;
06a2c219
GM
1822
1823 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1824 it->ascent = font->ascent + boff;
1825 it->descent = font->descent - boff;
1826 it->phys_ascent = pcm->ascent + boff;
1827 it->phys_descent = pcm->descent - boff;
06a2c219
GM
1828 it->pixel_width = pcm->width;
1829
1830 /* If this is a space inside a region of text with
1831 `space-width' property, change its width. */
1832 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1833 if (stretched_p)
1834 it->pixel_width *= XFLOATINT (it->space_width);
1835
1836 /* If face has a box, add the box thickness to the character
1837 height. If character has a box line to the left and/or
1838 right, add the box line width to the character's width. */
1839 if (face->box != FACE_NO_BOX)
1840 {
1841 int thick = face->box_line_width;
1842
1843 it->ascent += thick;
1844 it->descent += thick;
1845
1846 if (it->start_of_box_run_p)
1847 it->pixel_width += thick;
1848 if (it->end_of_box_run_p)
1849 it->pixel_width += thick;
1850 }
1851
1852 /* If face has an overline, add the height of the overline
1853 (1 pixel) and a 1 pixel margin to the character height. */
1854 if (face->overline_p)
1855 it->ascent += 2;
1856
1857 take_vertical_position_into_account (it);
1858
1859 /* If we have to actually produce glyphs, do it. */
1860 if (it->glyph_row)
1861 {
1862 if (stretched_p)
1863 {
1864 /* Translate a space with a `space-width' property
1865 into a stretch glyph. */
1866 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1867 x_append_stretch_glyph (it, it->object, it->pixel_width,
1868 it->ascent + it->descent, ascent);
1869 }
1870 else
1871 x_append_glyph (it);
1872
1873 /* If characters with lbearing or rbearing are displayed
1874 in this line, record that fact in a flag of the
1875 glyph row. This is used to optimize X output code. */
1876 if (pcm->lbearing < 0
1877 || pcm->rbearing > pcm->width)
1878 it->glyph_row->contains_overlapping_glyphs_p = 1;
1879 }
1880 }
1881 else if (it->char_to_display == '\n')
1882 {
1883 /* A newline has no width but we need the height of the line. */
1884 it->pixel_width = 0;
1885 it->nglyphs = 0;
b4192550
KH
1886 it->ascent = it->phys_ascent = font->ascent + boff;
1887 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1888
1889 if (face->box != FACE_NO_BOX)
1890 {
1891 int thick = face->box_line_width;
1892 it->ascent += thick;
1893 it->descent += thick;
1894 }
1895 }
1896 else if (it->char_to_display == '\t')
1897 {
1898 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1899 int x = (it->current_x
1900 - it->prompt_width
1901 + it->continuation_lines_width);
1902 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1903
1904 it->pixel_width = next_tab_x - x;
1905 it->nglyphs = 1;
b4192550
KH
1906 it->ascent = it->phys_ascent = font->ascent + boff;
1907 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1908
1909 if (it->glyph_row)
1910 {
1911 double ascent = (double) it->ascent / (it->ascent + it->descent);
1912 x_append_stretch_glyph (it, it->object, it->pixel_width,
1913 it->ascent + it->descent, ascent);
1914 }
1915 }
1916 else
1917 {
1918 /* A multi-byte character. Assume that the display width of the
1919 character is the width of the character multiplied by the
b4192550 1920 width of the font. */
06a2c219 1921
b4192550
KH
1922 /* If we found a font, this font should give us the right
1923 metrics. If we didn't find a font, use the frame's
1924 default font and calculate the width of the character
1925 from the charset width; this is what old redisplay code
1926 did. */
1927 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1928 if (font_not_found_p || !pcm)
1929 {
1930 int charset = CHAR_CHARSET (it->char_to_display);
1931
1932 it->glyph_not_available_p = 1;
1933 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1934 * CHARSET_WIDTH (charset));
1935 it->phys_ascent = font->ascent + boff;
1936 it->phys_descent = font->descent - boff;
1937 }
1938 else
1939 {
1940 it->pixel_width = pcm->width;
1941 it->phys_ascent = pcm->ascent + boff;
1942 it->phys_descent = pcm->descent - boff;
1943 if (it->glyph_row
1944 && (pcm->lbearing < 0
1945 || pcm->rbearing > pcm->width))
1946 it->glyph_row->contains_overlapping_glyphs_p = 1;
1947 }
b4192550
KH
1948 it->nglyphs = 1;
1949 it->ascent = font->ascent + boff;
1950 it->descent = font->descent - boff;
06a2c219
GM
1951 if (face->box != FACE_NO_BOX)
1952 {
1953 int thick = face->box_line_width;
1954 it->ascent += thick;
1955 it->descent += thick;
1956
1957 if (it->start_of_box_run_p)
1958 it->pixel_width += thick;
1959 if (it->end_of_box_run_p)
1960 it->pixel_width += thick;
1961 }
1962
1963 /* If face has an overline, add the height of the overline
1964 (1 pixel) and a 1 pixel margin to the character height. */
1965 if (face->overline_p)
1966 it->ascent += 2;
1967
1968 take_vertical_position_into_account (it);
1969
1970 if (it->glyph_row)
1971 x_append_glyph (it);
1972 }
1973 }
b4192550
KH
1974 else if (it->what == IT_COMPOSITION)
1975 {
1976 /* Note: A composition is represented as one glyph in the
1977 glyph matrix. There are no padding glyphs. */
1978 XChar2b char2b;
1979 XFontStruct *font;
ee569018 1980 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
1981 XCharStruct *pcm;
1982 int font_not_found_p;
1983 struct font_info *font_info;
1984 int boff; /* baseline offset */
1985 struct composition *cmp = composition_table[it->cmp_id];
1986
1987 /* Maybe translate single-byte characters to multibyte. */
1988 it->char_to_display = it->c;
1989 if (unibyte_display_via_language_environment
1990 && SINGLE_BYTE_CHAR_P (it->c)
1991 && (it->c >= 0240
1992 || (it->c >= 0200
1993 && !NILP (Vnonascii_translation_table))))
1994 {
1995 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
1996 }
1997
1998 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
1999 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2000 face = FACE_FROM_ID (it->f, it->face_id);
2001 x_get_char_face_and_encoding (it->f, it->char_to_display,
2002 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2003 font = face->font;
2004
2005 /* When no suitable font found, use the default font. */
2006 font_not_found_p = font == NULL;
2007 if (font_not_found_p)
2008 {
2009 font = FRAME_FONT (it->f);
2010 boff = it->f->output_data.x->baseline_offset;
2011 font_info = NULL;
2012 }
2013 else
2014 {
2015 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2016 boff = font_info->baseline_offset;
2017 if (font_info->vertical_centering)
2018 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2019 }
2020
2021 /* There are no padding glyphs, so there is only one glyph to
2022 produce for the composition. Important is that pixel_width,
2023 ascent and descent are the values of what is drawn by
2024 draw_glyphs (i.e. the values of the overall glyphs composed). */
2025 it->nglyphs = 1;
2026
2027 /* If we have not yet calculated pixel size data of glyphs of
2028 the composition for the current face font, calculate them
2029 now. Theoretically, we have to check all fonts for the
2030 glyphs, but that requires much time and memory space. So,
2031 here we check only the font of the first glyph. This leads
2032 to incorrect display very rarely, and C-l (recenter) can
2033 correct the display anyway. */
2034 if (cmp->font != (void *) font)
2035 {
2036 /* Ascent and descent of the font of the first character of
2037 this composition (adjusted by baseline offset). Ascent
2038 and descent of overall glyphs should not be less than
2039 them respectively. */
2040 int font_ascent = font->ascent + boff;
2041 int font_descent = font->descent - boff;
2042 /* Bounding box of the overall glyphs. */
2043 int leftmost, rightmost, lowest, highest;
2044 int i;
2045
2046 cmp->font = (void *) font;
2047
2048 /* Initialize the bounding box. */
2049 pcm = x_per_char_metric (font, &char2b);
2050 leftmost = 0;
2051 rightmost = pcm->width;
2052 lowest = - pcm->descent + boff;
2053 highest = pcm->ascent + boff;
2054 if (font_info
2055 && font_info->default_ascent
2056 && CHAR_TABLE_P (Vuse_default_ascent)
2057 && !NILP (Faref (Vuse_default_ascent,
2058 make_number (it->char_to_display))))
2059 highest = font_info->default_ascent + boff;
2060
2061 /* Draw the first glyph at the normal position. It may be
2062 shifted to right later if some other glyphs are drawn at
2063 the left. */
2064 cmp->offsets[0] = 0;
2065 cmp->offsets[1] = boff;
2066
2067 /* Set cmp->offsets for the remaining glyphs. */
2068 for (i = 1; i < cmp->glyph_len; i++)
2069 {
2070 int left, right, btm, top;
2071 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2072 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2073
2074 face = FACE_FROM_ID (it->f, face_id);
2075 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2076 it->multibyte_p);
b4192550
KH
2077 font = face->font;
2078 if (font == NULL)
2079 {
2080 font = FRAME_FONT (it->f);
2081 boff = it->f->output_data.x->baseline_offset;
2082 font_info = NULL;
2083 }
2084 else
2085 {
2086 font_info
2087 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2088 boff = font_info->baseline_offset;
2089 if (font_info->vertical_centering)
2090 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2091 }
2092
2093 pcm = x_per_char_metric (font, &char2b);
2094
2095 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2096 {
2097 /* Relative composition with or without
2098 alternate chars. */
2099 left = (leftmost + rightmost - pcm->width) / 2;
2100 btm = - pcm->descent + boff;
2101 if (font_info && font_info->relative_compose
2102 && (! CHAR_TABLE_P (Vignore_relative_composition)
2103 || NILP (Faref (Vignore_relative_composition,
2104 make_number (ch)))))
2105 {
2106
2107 if (- pcm->descent
2108 >= font_info->relative_compose)
2109 /* One extra pixel between two glyphs. */
2110 btm = highest + 1;
2111 else if (pcm->ascent <= 0)
2112 /* One extra pixel between two glyphs. */
2113 btm = lowest - 1 - pcm->ascent - pcm->descent;
2114 }
2115 }
2116 else
2117 {
2118 /* A composition rule is specified by an integer
2119 value that encodes global and new reference
2120 points (GREF and NREF). GREF and NREF are
2121 specified by numbers as below:
2122
2123 0---1---2 -- ascent
2124 | |
2125 | |
2126 | |
2127 9--10--11 -- center
2128 | |
2129 ---3---4---5--- baseline
2130 | |
2131 6---7---8 -- descent
2132 */
2133 int rule = COMPOSITION_RULE (cmp, i);
2134 int gref, nref, grefx, grefy, nrefx, nrefy;
2135
2136 COMPOSITION_DECODE_RULE (rule, gref, nref);
2137 grefx = gref % 3, nrefx = nref % 3;
2138 grefy = gref / 3, nrefy = nref / 3;
2139
2140 left = (leftmost
2141 + grefx * (rightmost - leftmost) / 2
2142 - nrefx * pcm->width / 2);
2143 btm = ((grefy == 0 ? highest
2144 : grefy == 1 ? 0
2145 : grefy == 2 ? lowest
2146 : (highest + lowest) / 2)
2147 - (nrefy == 0 ? pcm->ascent + pcm->descent
2148 : nrefy == 1 ? pcm->descent - boff
2149 : nrefy == 2 ? 0
2150 : (pcm->ascent + pcm->descent) / 2));
2151 }
2152
2153 cmp->offsets[i * 2] = left;
2154 cmp->offsets[i * 2 + 1] = btm + pcm->descent;
2155
2156 /* Update the bounding box of the overall glyphs. */
2157 right = left + pcm->width;
2158 top = btm + pcm->descent + pcm->ascent;
2159 if (left < leftmost)
2160 leftmost = left;
2161 if (right > rightmost)
2162 rightmost = right;
2163 if (top > highest)
2164 highest = top;
2165 if (btm < lowest)
2166 lowest = btm;
2167 }
2168
2169 /* If there are glyphs whose x-offsets are negative,
2170 shift all glyphs to the right and make all x-offsets
2171 non-negative. */
2172 if (leftmost < 0)
2173 {
2174 for (i = 0; i < cmp->glyph_len; i++)
2175 cmp->offsets[i * 2] -= leftmost;
2176 rightmost -= leftmost;
2177 }
2178
2179 cmp->pixel_width = rightmost;
2180 cmp->ascent = highest;
2181 cmp->descent = - lowest;
2182 if (cmp->ascent < font_ascent)
2183 cmp->ascent = font_ascent;
2184 if (cmp->descent < font_descent)
2185 cmp->descent = font_descent;
2186 }
2187
2188 it->pixel_width = cmp->pixel_width;
2189 it->ascent = it->phys_ascent = cmp->ascent;
2190 it->descent = it->phys_descent = cmp->descent;
2191
2192 if (face->box != FACE_NO_BOX)
2193 {
2194 int thick = face->box_line_width;
2195 it->ascent += thick;
2196 it->descent += thick;
2197
2198 if (it->start_of_box_run_p)
2199 it->pixel_width += thick;
2200 if (it->end_of_box_run_p)
2201 it->pixel_width += thick;
2202 }
2203
2204 /* If face has an overline, add the height of the overline
2205 (1 pixel) and a 1 pixel margin to the character height. */
2206 if (face->overline_p)
2207 it->ascent += 2;
2208
2209 take_vertical_position_into_account (it);
2210
2211 if (it->glyph_row)
2212 x_append_composite_glyph (it);
2213 }
06a2c219
GM
2214 else if (it->what == IT_IMAGE)
2215 x_produce_image_glyph (it);
2216 else if (it->what == IT_STRETCH)
2217 x_produce_stretch_glyph (it);
2218
2219 /* Accumulate dimensions. */
2220 xassert (it->ascent >= 0 && it->descent > 0);
2221 if (it->area == TEXT_AREA)
2222 it->current_x += it->pixel_width;
66ac4b0e 2223
06a2c219
GM
2224 it->max_ascent = max (it->max_ascent, it->ascent);
2225 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2226 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2227 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2228}
2229
2230
2231/* Estimate the pixel height of the mode or top line on frame F.
2232 FACE_ID specifies what line's height to estimate. */
2233
2234int
2235x_estimate_mode_line_height (f, face_id)
2236 struct frame *f;
2237 enum face_id face_id;
2238{
2239 int height = 1;
2240
2241 /* This function is called so early when Emacs starts that the face
2242 cache and mode line face are not yet initialized. */
2243 if (FRAME_FACE_CACHE (f))
2244 {
2245 struct face *face = FACE_FROM_ID (f, face_id);
2246 if (face)
2247 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2248 }
2249
2250 return height;
2251}
2252
2253\f
2254/***********************************************************************
2255 Glyph display
2256 ***********************************************************************/
2257
2258/* A sequence of glyphs to be drawn in the same face.
2259
2260 This data structure is not really completely X specific, so it
2261 could possibly, at least partially, be useful for other systems. It
2262 is currently not part of the external redisplay interface because
2263 it's not clear what other systems will need. */
2264
2265struct glyph_string
2266{
2267 /* X-origin of the string. */
2268 int x;
2269
2270 /* Y-origin and y-position of the base line of this string. */
2271 int y, ybase;
2272
2273 /* The width of the string, not including a face extension. */
2274 int width;
2275
2276 /* The width of the string, including a face extension. */
2277 int background_width;
2278
2279 /* The height of this string. This is the height of the line this
2280 string is drawn in, and can be different from the height of the
2281 font the string is drawn in. */
2282 int height;
2283
2284 /* Number of pixels this string overwrites in front of its x-origin.
2285 This number is zero if the string has an lbearing >= 0; it is
2286 -lbearing, if the string has an lbearing < 0. */
2287 int left_overhang;
2288
2289 /* Number of pixels this string overwrites past its right-most
2290 nominal x-position, i.e. x + width. Zero if the string's
2291 rbearing is <= its nominal width, rbearing - width otherwise. */
2292 int right_overhang;
2293
2294 /* The frame on which the glyph string is drawn. */
2295 struct frame *f;
2296
2297 /* The window on which the glyph string is drawn. */
2298 struct window *w;
2299
2300 /* X display and window for convenience. */
2301 Display *display;
2302 Window window;
2303
2304 /* The glyph row for which this string was built. It determines the
2305 y-origin and height of the string. */
2306 struct glyph_row *row;
2307
2308 /* The area within row. */
2309 enum glyph_row_area area;
2310
2311 /* Characters to be drawn, and number of characters. */
2312 XChar2b *char2b;
2313 int nchars;
2314
06a2c219
GM
2315 /* A face-override for drawing cursors, mouse face and similar. */
2316 enum draw_glyphs_face hl;
2317
2318 /* Face in which this string is to be drawn. */
2319 struct face *face;
2320
2321 /* Font in which this string is to be drawn. */
2322 XFontStruct *font;
2323
2324 /* Font info for this string. */
2325 struct font_info *font_info;
2326
b4192550
KH
2327 /* Non-null means this string describes (part of) a composition.
2328 All characters from char2b are drawn composed. */
2329 struct composition *cmp;
06a2c219
GM
2330
2331 /* Index of this glyph string's first character in the glyph
b4192550
KH
2332 definition of CMP. If this is zero, this glyph string describes
2333 the first character of a composition. */
06a2c219
GM
2334 int gidx;
2335
2336 /* 1 means this glyph strings face has to be drawn to the right end
2337 of the window's drawing area. */
2338 unsigned extends_to_end_of_line_p : 1;
2339
2340 /* 1 means the background of this string has been drawn. */
2341 unsigned background_filled_p : 1;
2342
2343 /* 1 means glyph string must be drawn with 16-bit functions. */
2344 unsigned two_byte_p : 1;
2345
2346 /* 1 means that the original font determined for drawing this glyph
2347 string could not be loaded. The member `font' has been set to
2348 the frame's default font in this case. */
2349 unsigned font_not_found_p : 1;
2350
2351 /* 1 means that the face in which this glyph string is drawn has a
2352 stipple pattern. */
2353 unsigned stippled_p : 1;
2354
66ac4b0e
GM
2355 /* 1 means only the foreground of this glyph string must be drawn,
2356 and we should use the physical height of the line this glyph
2357 string appears in as clip rect. */
2358 unsigned for_overlaps_p : 1;
2359
06a2c219
GM
2360 /* The GC to use for drawing this glyph string. */
2361 GC gc;
2362
2363 /* A pointer to the first glyph in the string. This glyph
2364 corresponds to char2b[0]. Needed to draw rectangles if
2365 font_not_found_p is 1. */
2366 struct glyph *first_glyph;
2367
2368 /* Image, if any. */
2369 struct image *img;
2370
2371 struct glyph_string *next, *prev;
2372};
2373
2374
5c187dee 2375#if 0
06a2c219
GM
2376
2377static void
2378x_dump_glyph_string (s)
2379 struct glyph_string *s;
2380{
2381 fprintf (stderr, "glyph string\n");
2382 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2383 s->x, s->y, s->width, s->height);
2384 fprintf (stderr, " ybase = %d\n", s->ybase);
2385 fprintf (stderr, " hl = %d\n", s->hl);
2386 fprintf (stderr, " left overhang = %d, right = %d\n",
2387 s->left_overhang, s->right_overhang);
2388 fprintf (stderr, " nchars = %d\n", s->nchars);
2389 fprintf (stderr, " extends to end of line = %d\n",
2390 s->extends_to_end_of_line_p);
2391 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2392 fprintf (stderr, " bg width = %d\n", s->background_width);
2393}
2394
2395#endif /* GLYPH_DEBUG */
2396
2397
2398
2399static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2400 struct glyph_string **,
2401 struct glyph_string *,
2402 struct glyph_string *));
2403static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2404 struct glyph_string **,
2405 struct glyph_string *,
2406 struct glyph_string *));
2407static void x_append_glyph_string P_ ((struct glyph_string **,
2408 struct glyph_string **,
2409 struct glyph_string *));
2410static int x_left_overwritten P_ ((struct glyph_string *));
2411static int x_left_overwriting P_ ((struct glyph_string *));
2412static int x_right_overwritten P_ ((struct glyph_string *));
2413static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2414static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2415 int));
06a2c219
GM
2416static void x_init_glyph_string P_ ((struct glyph_string *,
2417 XChar2b *, struct window *,
2418 struct glyph_row *,
2419 enum glyph_row_area, int,
2420 enum draw_glyphs_face));
2421static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2422 enum glyph_row_area, int, int,
66ac4b0e 2423 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2424static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2425static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2426static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2427 int));
2428static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2429static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2430static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2431static void x_draw_glyph_string P_ ((struct glyph_string *));
2432static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2433static void x_set_cursor_gc P_ ((struct glyph_string *));
2434static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2435static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2436static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2437 int *, int *));
2438static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2439static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2440 unsigned long *, double, int));
06a2c219 2441static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2442 double, int, unsigned long));
06a2c219
GM
2443static void x_setup_relief_colors P_ ((struct glyph_string *));
2444static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2445static void x_draw_image_relief P_ ((struct glyph_string *));
2446static void x_draw_image_foreground P_ ((struct glyph_string *));
2447static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2448static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2449static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2450 int, int, int));
2451static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2452 int, int, int, int, XRectangle *));
2453static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2454 int, int, int, XRectangle *));
66ac4b0e
GM
2455static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2456 enum glyph_row_area));
06a2c219
GM
2457
2458
06a2c219
GM
2459/* Append the list of glyph strings with head H and tail T to the list
2460 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2461
2462static INLINE void
2463x_append_glyph_string_lists (head, tail, h, t)
2464 struct glyph_string **head, **tail;
2465 struct glyph_string *h, *t;
2466{
2467 if (h)
2468 {
2469 if (*head)
2470 (*tail)->next = h;
2471 else
2472 *head = h;
2473 h->prev = *tail;
2474 *tail = t;
2475 }
2476}
2477
2478
2479/* Prepend the list of glyph strings with head H and tail T to the
2480 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2481 result. */
2482
2483static INLINE void
2484x_prepend_glyph_string_lists (head, tail, h, t)
2485 struct glyph_string **head, **tail;
2486 struct glyph_string *h, *t;
2487{
2488 if (h)
2489 {
2490 if (*head)
2491 (*head)->prev = t;
2492 else
2493 *tail = t;
2494 t->next = *head;
2495 *head = h;
2496 }
2497}
2498
2499
2500/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2501 Set *HEAD and *TAIL to the resulting list. */
2502
2503static INLINE void
2504x_append_glyph_string (head, tail, s)
2505 struct glyph_string **head, **tail;
2506 struct glyph_string *s;
2507{
2508 s->next = s->prev = NULL;
2509 x_append_glyph_string_lists (head, tail, s, s);
2510}
2511
2512
2513/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2514 face. */
2515
2516static void
2517x_set_cursor_gc (s)
2518 struct glyph_string *s;
2519{
2520 if (s->font == FRAME_FONT (s->f)
2521 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2522 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2523 && !s->cmp)
06a2c219
GM
2524 s->gc = s->f->output_data.x->cursor_gc;
2525 else
2526 {
2527 /* Cursor on non-default face: must merge. */
2528 XGCValues xgcv;
2529 unsigned long mask;
2530
2531 xgcv.background = s->f->output_data.x->cursor_pixel;
2532 xgcv.foreground = s->face->background;
2533
2534 /* If the glyph would be invisible, try a different foreground. */
2535 if (xgcv.foreground == xgcv.background)
2536 xgcv.foreground = s->face->foreground;
2537 if (xgcv.foreground == xgcv.background)
2538 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2539 if (xgcv.foreground == xgcv.background)
2540 xgcv.foreground = s->face->foreground;
2541
2542 /* Make sure the cursor is distinct from text in this face. */
2543 if (xgcv.background == s->face->background
2544 && xgcv.foreground == s->face->foreground)
2545 {
2546 xgcv.background = s->face->foreground;
2547 xgcv.foreground = s->face->background;
2548 }
2549
2550 IF_DEBUG (x_check_font (s->f, s->font));
2551 xgcv.font = s->font->fid;
2552 xgcv.graphics_exposures = False;
2553 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2554
2555 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2556 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2557 mask, &xgcv);
2558 else
2559 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2560 = XCreateGC (s->display, s->window, mask, &xgcv);
2561
2562 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2563 }
2564}
2565
2566
2567/* Set up S->gc of glyph string S for drawing text in mouse face. */
2568
2569static void
2570x_set_mouse_face_gc (s)
2571 struct glyph_string *s;
2572{
2573 int face_id;
ee569018 2574 struct face *face;
06a2c219
GM
2575
2576 /* What face has to be used for the mouse face? */
2577 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018
KH
2578 face = FACE_FROM_ID (s->f, face_id);
2579 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
06a2c219
GM
2580 s->face = FACE_FROM_ID (s->f, face_id);
2581 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2582
2583 /* If font in this face is same as S->font, use it. */
2584 if (s->font == s->face->font)
2585 s->gc = s->face->gc;
2586 else
2587 {
2588 /* Otherwise construct scratch_cursor_gc with values from FACE
2589 but font FONT. */
2590 XGCValues xgcv;
2591 unsigned long mask;
2592
2593 xgcv.background = s->face->background;
2594 xgcv.foreground = s->face->foreground;
2595 IF_DEBUG (x_check_font (s->f, s->font));
2596 xgcv.font = s->font->fid;
2597 xgcv.graphics_exposures = False;
2598 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2599
2600 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2601 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2602 mask, &xgcv);
2603 else
2604 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2605 = XCreateGC (s->display, s->window, mask, &xgcv);
2606
2607 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2608 }
2609
2610 xassert (s->gc != 0);
2611}
2612
2613
2614/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2615 Faces to use in the mode line have already been computed when the
2616 matrix was built, so there isn't much to do, here. */
2617
2618static INLINE void
2619x_set_mode_line_face_gc (s)
2620 struct glyph_string *s;
2621{
2622 s->gc = s->face->gc;
2623 xassert (s->gc != 0);
2624}
2625
2626
2627/* Set S->gc of glyph string S for drawing that glyph string. Set
2628 S->stippled_p to a non-zero value if the face of S has a stipple
2629 pattern. */
2630
2631static INLINE void
2632x_set_glyph_string_gc (s)
2633 struct glyph_string *s;
2634{
2635 if (s->hl == DRAW_NORMAL_TEXT)
2636 {
2637 s->gc = s->face->gc;
2638 s->stippled_p = s->face->stipple != 0;
2639 }
2640 else if (s->hl == DRAW_INVERSE_VIDEO)
2641 {
2642 x_set_mode_line_face_gc (s);
2643 s->stippled_p = s->face->stipple != 0;
2644 }
2645 else if (s->hl == DRAW_CURSOR)
2646 {
2647 x_set_cursor_gc (s);
2648 s->stippled_p = 0;
2649 }
2650 else if (s->hl == DRAW_MOUSE_FACE)
2651 {
2652 x_set_mouse_face_gc (s);
2653 s->stippled_p = s->face->stipple != 0;
2654 }
2655 else if (s->hl == DRAW_IMAGE_RAISED
2656 || s->hl == DRAW_IMAGE_SUNKEN)
2657 {
2658 s->gc = s->face->gc;
2659 s->stippled_p = s->face->stipple != 0;
2660 }
2661 else
2662 {
2663 s->gc = s->face->gc;
2664 s->stippled_p = s->face->stipple != 0;
2665 }
2666
2667 /* GC must have been set. */
2668 xassert (s->gc != 0);
2669}
2670
2671
2672/* Return in *R the clipping rectangle for glyph string S. */
2673
2674static void
2675x_get_glyph_string_clip_rect (s, r)
2676 struct glyph_string *s;
2677 XRectangle *r;
2678{
2679 if (s->row->full_width_p)
2680 {
2681 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2682 int canon_x = CANON_X_UNIT (s->f);
2683
2684 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2685 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2686
2687 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2688 {
1da3fd71 2689 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2690 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2691 r->x -= width;
2692 }
2693
b9432a85 2694 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2695
06a2c219
GM
2696 /* Unless displaying a mode or menu bar line, which are always
2697 fully visible, clip to the visible part of the row. */
2698 if (s->w->pseudo_window_p)
2699 r->height = s->row->visible_height;
2700 else
2701 r->height = s->height;
2702 }
2703 else
2704 {
2705 /* This is a text line that may be partially visible. */
2706 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2707 r->width = window_box_width (s->w, s->area);
2708 r->height = s->row->visible_height;
2709 }
2710
2711 /* Don't use S->y for clipping because it doesn't take partially
2712 visible lines into account. For example, it can be negative for
2713 partially visible lines at the top of a window. */
2714 if (!s->row->full_width_p
2715 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2716 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2717 else
2718 r->y = max (0, s->row->y);
06a2c219 2719
9ea173e8 2720 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2721 at the top of the window. */
9ea173e8 2722 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2723 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2724
2725 /* If S draws overlapping rows, it's sufficient to use the top and
2726 bottom of the window for clipping because this glyph string
2727 intentionally draws over other lines. */
2728 if (s->for_overlaps_p)
2729 {
045dee35 2730 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2731 r->height = window_text_bottom_y (s->w) - r->y;
2732 }
2733
2734 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2735}
2736
2737
2738/* Set clipping for output of glyph string S. S may be part of a mode
2739 line or menu if we don't have X toolkit support. */
2740
2741static INLINE void
2742x_set_glyph_string_clipping (s)
2743 struct glyph_string *s;
2744{
2745 XRectangle r;
2746 x_get_glyph_string_clip_rect (s, &r);
2747 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2748}
2749
2750
2751/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2752 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2753
2754static INLINE void
2755x_compute_glyph_string_overhangs (s)
2756 struct glyph_string *s;
2757{
b4192550 2758 if (s->cmp == NULL
06a2c219
GM
2759 && s->first_glyph->type == CHAR_GLYPH)
2760 {
2761 XCharStruct cs;
2762 int direction, font_ascent, font_descent;
2763 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2764 &font_ascent, &font_descent, &cs);
2765 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2766 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2767 }
2768}
2769
2770
2771/* Compute overhangs and x-positions for glyph string S and its
2772 predecessors, or successors. X is the starting x-position for S.
2773 BACKWARD_P non-zero means process predecessors. */
2774
2775static void
2776x_compute_overhangs_and_x (s, x, backward_p)
2777 struct glyph_string *s;
2778 int x;
2779 int backward_p;
2780{
2781 if (backward_p)
2782 {
2783 while (s)
2784 {
2785 x_compute_glyph_string_overhangs (s);
2786 x -= s->width;
2787 s->x = x;
2788 s = s->prev;
2789 }
2790 }
2791 else
2792 {
2793 while (s)
2794 {
2795 x_compute_glyph_string_overhangs (s);
2796 s->x = x;
2797 x += s->width;
2798 s = s->next;
2799 }
2800 }
2801}
2802
2803
2804/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2805 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2806 assumed to be zero. */
06a2c219
GM
2807
2808static void
2809x_get_glyph_overhangs (glyph, f, left, right)
2810 struct glyph *glyph;
2811 struct frame *f;
2812 int *left, *right;
2813{
2814 int c;
2815
2816 *left = *right = 0;
2817
b4192550 2818 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2819 {
2820 XFontStruct *font;
2821 struct face *face;
2822 struct font_info *font_info;
2823 XChar2b char2b;
ee569018
KH
2824 XCharStruct *pcm;
2825
2826 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2827 font = face->font;
2828 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2829 if (font
2830 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2831 {
06a2c219
GM
2832 if (pcm->rbearing > pcm->width)
2833 *right = pcm->rbearing - pcm->width;
2834 if (pcm->lbearing < 0)
2835 *left = -pcm->lbearing;
2836 }
2837 }
2838}
2839
2840
2841/* Return the index of the first glyph preceding glyph string S that
2842 is overwritten by S because of S's left overhang. Value is -1
2843 if no glyphs are overwritten. */
2844
2845static int
2846x_left_overwritten (s)
2847 struct glyph_string *s;
2848{
2849 int k;
2850
2851 if (s->left_overhang)
2852 {
2853 int x = 0, i;
2854 struct glyph *glyphs = s->row->glyphs[s->area];
2855 int first = s->first_glyph - glyphs;
2856
2857 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2858 x -= glyphs[i].pixel_width;
2859
2860 k = i + 1;
2861 }
2862 else
2863 k = -1;
2864
2865 return k;
2866}
2867
2868
2869/* Return the index of the first glyph preceding glyph string S that
2870 is overwriting S because of its right overhang. Value is -1 if no
2871 glyph in front of S overwrites S. */
2872
2873static int
2874x_left_overwriting (s)
2875 struct glyph_string *s;
2876{
2877 int i, k, x;
2878 struct glyph *glyphs = s->row->glyphs[s->area];
2879 int first = s->first_glyph - glyphs;
2880
2881 k = -1;
2882 x = 0;
2883 for (i = first - 1; i >= 0; --i)
2884 {
2885 int left, right;
2886 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2887 if (x + right > 0)
2888 k = i;
2889 x -= glyphs[i].pixel_width;
2890 }
2891
2892 return k;
2893}
2894
2895
2896/* Return the index of the last glyph following glyph string S that is
2897 not overwritten by S because of S's right overhang. Value is -1 if
2898 no such glyph is found. */
2899
2900static int
2901x_right_overwritten (s)
2902 struct glyph_string *s;
2903{
2904 int k = -1;
2905
2906 if (s->right_overhang)
2907 {
2908 int x = 0, i;
2909 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2910 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2911 int end = s->row->used[s->area];
2912
2913 for (i = first; i < end && s->right_overhang > x; ++i)
2914 x += glyphs[i].pixel_width;
2915
2916 k = i;
2917 }
2918
2919 return k;
2920}
2921
2922
2923/* Return the index of the last glyph following glyph string S that
2924 overwrites S because of its left overhang. Value is negative
2925 if no such glyph is found. */
2926
2927static int
2928x_right_overwriting (s)
2929 struct glyph_string *s;
2930{
2931 int i, k, x;
2932 int end = s->row->used[s->area];
2933 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2934 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2935
2936 k = -1;
2937 x = 0;
2938 for (i = first; i < end; ++i)
2939 {
2940 int left, right;
2941 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2942 if (x - left < 0)
2943 k = i;
2944 x += glyphs[i].pixel_width;
2945 }
2946
2947 return k;
2948}
2949
2950
2951/* Fill rectangle X, Y, W, H with background color of glyph string S. */
2952
2953static INLINE void
2954x_clear_glyph_string_rect (s, x, y, w, h)
2955 struct glyph_string *s;
2956 int x, y, w, h;
2957{
2958 XGCValues xgcv;
2959 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
2960 XSetForeground (s->display, s->gc, xgcv.background);
2961 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2962 XSetForeground (s->display, s->gc, xgcv.foreground);
2963}
2964
2965
2966/* Draw the background of glyph_string S. If S->background_filled_p
2967 is non-zero don't draw it. FORCE_P non-zero means draw the
2968 background even if it wouldn't be drawn normally. This is used
b4192550
KH
2969 when a string preceding S draws into the background of S, or S
2970 contains the first component of a composition. */
06a2c219
GM
2971
2972static void
2973x_draw_glyph_string_background (s, force_p)
2974 struct glyph_string *s;
2975 int force_p;
2976{
2977 /* Nothing to do if background has already been drawn or if it
2978 shouldn't be drawn in the first place. */
2979 if (!s->background_filled_p)
2980 {
b4192550 2981 if (s->stippled_p)
06a2c219
GM
2982 {
2983 /* Fill background with a stipple pattern. */
2984 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2985 XFillRectangle (s->display, s->window, s->gc, s->x,
2986 s->y + s->face->box_line_width,
2987 s->background_width,
2988 s->height - 2 * s->face->box_line_width);
2989 XSetFillStyle (s->display, s->gc, FillSolid);
2990 s->background_filled_p = 1;
2991 }
2992 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2993 || s->font_not_found_p
2994 || s->extends_to_end_of_line_p
06a2c219
GM
2995 || force_p)
2996 {
2997 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2998 s->background_width,
2999 s->height - 2 * s->face->box_line_width);
3000 s->background_filled_p = 1;
3001 }
3002 }
3003}
3004
3005
3006/* Draw the foreground of glyph string S. */
3007
3008static void
3009x_draw_glyph_string_foreground (s)
3010 struct glyph_string *s;
3011{
3012 int i, x;
3013
3014 /* If first glyph of S has a left box line, start drawing the text
3015 of S to the right of that box line. */
3016 if (s->face->box != FACE_NO_BOX
3017 && s->first_glyph->left_box_line_p)
3018 x = s->x + s->face->box_line_width;
3019 else
3020 x = s->x;
3021
b4192550
KH
3022 /* Draw characters of S as rectangles if S's font could not be
3023 loaded. */
3024 if (s->font_not_found_p)
06a2c219 3025 {
b4192550 3026 for (i = 0; i < s->nchars; ++i)
06a2c219 3027 {
b4192550
KH
3028 struct glyph *g = s->first_glyph + i;
3029 XDrawRectangle (s->display, s->window,
3030 s->gc, x, s->y, g->pixel_width - 1,
3031 s->height - 1);
3032 x += g->pixel_width;
06a2c219
GM
3033 }
3034 }
3035 else
3036 {
b4192550
KH
3037 char *char1b = (char *) s->char2b;
3038 int boff = s->font_info->baseline_offset;
06a2c219 3039
b4192550
KH
3040 if (s->font_info->vertical_centering)
3041 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3042
3043 /* If we can use 8-bit functions, condense S->char2b. */
3044 if (!s->two_byte_p)
3045 for (i = 0; i < s->nchars; ++i)
3046 char1b[i] = s->char2b[i].byte2;
3047
3048 /* Draw text with XDrawString if background has already been
3049 filled. Otherwise, use XDrawImageString. (Note that
3050 XDrawImageString is usually faster than XDrawString.) Always
3051 use XDrawImageString when drawing the cursor so that there is
3052 no chance that characters under a box cursor are invisible. */
3053 if (s->for_overlaps_p
3054 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3055 {
3056 /* Draw characters with 16-bit or 8-bit functions. */
3057 if (s->two_byte_p)
3058 XDrawString16 (s->display, s->window, s->gc, x,
3059 s->ybase - boff, s->char2b, s->nchars);
3060 else
3061 XDrawString (s->display, s->window, s->gc, x,
3062 s->ybase - boff, char1b, s->nchars);
3063 }
06a2c219
GM
3064 else
3065 {
b4192550
KH
3066 if (s->two_byte_p)
3067 XDrawImageString16 (s->display, s->window, s->gc, x,
3068 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3069 else
b4192550
KH
3070 XDrawImageString (s->display, s->window, s->gc, x,
3071 s->ybase - boff, char1b, s->nchars);
3072 }
3073 }
3074}
06a2c219 3075
b4192550 3076/* Draw the foreground of composite glyph string S. */
06a2c219 3077
b4192550
KH
3078static void
3079x_draw_composite_glyph_string_foreground (s)
3080 struct glyph_string *s;
3081{
3082 int i, x;
06a2c219 3083
b4192550
KH
3084 /* If first glyph of S has a left box line, start drawing the text
3085 of S to the right of that box line. */
3086 if (s->face->box != FACE_NO_BOX
3087 && s->first_glyph->left_box_line_p)
3088 x = s->x + s->face->box_line_width;
3089 else
3090 x = s->x;
06a2c219 3091
b4192550
KH
3092 /* S is a glyph string for a composition. S->gidx is the index of
3093 the first character drawn for glyphs of this composition.
3094 S->gidx == 0 means we are drawing the very first character of
3095 this composition. */
06a2c219 3096
b4192550
KH
3097 /* Draw a rectangle for the composition if the font for the very
3098 first character of the composition could not be loaded. */
3099 if (s->font_not_found_p)
3100 {
3101 if (s->gidx == 0)
3102 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3103 s->width - 1, s->height - 1);
3104 }
3105 else
3106 {
3107 for (i = 0; i < s->nchars; i++, ++s->gidx)
3108 XDrawString16 (s->display, s->window, s->gc,
3109 x + s->cmp->offsets[s->gidx * 2],
3110 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3111 s->char2b + i, 1);
06a2c219
GM
3112 }
3113}
3114
3115
80c32bcc
GM
3116#ifdef USE_X_TOOLKIT
3117
3118/* Allocate the color COLOR->pixel on the screen and display of
3119 widget WIDGET in colormap CMAP. If an exact match cannot be
3120 allocated, try the nearest color available. Value is non-zero
3121 if successful. This is called from lwlib. */
3122
3123int
3124x_alloc_nearest_color_for_widget (widget, cmap, color)
3125 Widget widget;
3126 Colormap cmap;
3127 XColor *color;
3128{
3129 struct frame *f;
3130 struct x_display_info *dpyinfo;
5c187dee 3131 Lisp_Object tail;
80c32bcc
GM
3132
3133 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3134
3135 /* Find the top-level shell of the widget. Note that this function
3136 can be called when the widget is not yet realized, so XtWindow
3137 (widget) == 0. That's the reason we can't simply use
3138 x_any_window_to_frame. */
3139 while (!XtIsTopLevelShell (widget))
3140 widget = XtParent (widget);
3141
3142 /* Look for a frame with that top-level widget. Allocate the color
3143 on that frame to get the right gamma correction value. */
3144 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3145 if (GC_FRAMEP (XCAR (tail))
3146 && (f = XFRAME (XCAR (tail)),
3147 (f->output_data.nothing != 1
3148 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3149 && f->output_data.x->widget == widget)
3150 return x_alloc_nearest_color (f, cmap, color);
3151
3152 abort ();
3153}
3154
3155#endif /* USE_X_TOOLKIT */
3156
3157
06a2c219
GM
3158/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3159 CMAP. If an exact match can't be allocated, try the nearest color
3160 available. Value is non-zero if successful. Set *COLOR to the
3161 color allocated. */
3162
3163int
80c32bcc
GM
3164x_alloc_nearest_color (f, cmap, color)
3165 struct frame *f;
06a2c219
GM
3166 Colormap cmap;
3167 XColor *color;
3168{
80c32bcc
GM
3169 Display *display = FRAME_X_DISPLAY (f);
3170 Screen *screen = FRAME_X_SCREEN (f);
3171 int rc;
3172
3173 gamma_correct (f, color);
3174 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3175 if (rc == 0)
3176 {
3177 /* If we got to this point, the colormap is full, so we're going
3178 to try to get the next closest color. The algorithm used is
3179 a least-squares matching, which is what X uses for closest
3180 color matching with StaticColor visuals. */
3181 int nearest, i;
3182 unsigned long nearest_delta = ~0;
3183 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3184 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3185
3186 for (i = 0; i < ncells; ++i)
3187 cells[i].pixel = i;
3188 XQueryColors (display, cmap, cells, ncells);
3189
3190 for (nearest = i = 0; i < ncells; ++i)
3191 {
3192 long dred = (color->red >> 8) - (cells[i].red >> 8);
3193 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3194 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3195 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3196
3197 if (delta < nearest_delta)
3198 {
3199 nearest = i;
3200 nearest_delta = delta;
3201 }
3202 }
3203
3204 color->red = cells[nearest].red;
3205 color->green = cells[nearest].green;
3206 color->blue = cells[nearest].blue;
3207 rc = XAllocColor (display, cmap, color);
3208 }
3209
3210 return rc;
3211}
3212
3213
3214/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3215 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3216 If this produces the same color as PIXEL, try a color where all RGB
3217 values have DELTA added. Return the allocated color in *PIXEL.
3218 DISPLAY is the X display, CMAP is the colormap to operate on.
3219 Value is non-zero if successful. */
3220
3221static int
3222x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3223 struct frame *f;
3224 Display *display;
3225 Colormap cmap;
3226 unsigned long *pixel;
68c45bf0 3227 double factor;
06a2c219
GM
3228 int delta;
3229{
3230 XColor color, new;
3231 int success_p;
3232
3233 /* Get RGB color values. */
3234 color.pixel = *pixel;
3235 XQueryColor (display, cmap, &color);
3236
3237 /* Change RGB values by specified FACTOR. Avoid overflow! */
3238 xassert (factor >= 0);
3239 new.red = min (0xffff, factor * color.red);
3240 new.green = min (0xffff, factor * color.green);
3241 new.blue = min (0xffff, factor * color.blue);
3242
3243 /* Try to allocate the color. */
80c32bcc 3244 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3245 if (success_p)
3246 {
3247 if (new.pixel == *pixel)
3248 {
3249 /* If we end up with the same color as before, try adding
3250 delta to the RGB values. */
0d605c67 3251 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3252
3253 new.red = min (0xffff, delta + color.red);
3254 new.green = min (0xffff, delta + color.green);
3255 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3256 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3257 }
3258 else
3259 success_p = 1;
3260 *pixel = new.pixel;
3261 }
3262
3263 return success_p;
3264}
3265
3266
3267/* Set up the foreground color for drawing relief lines of glyph
3268 string S. RELIEF is a pointer to a struct relief containing the GC
3269 with which lines will be drawn. Use a color that is FACTOR or
3270 DELTA lighter or darker than the relief's background which is found
3271 in S->f->output_data.x->relief_background. If such a color cannot
3272 be allocated, use DEFAULT_PIXEL, instead. */
3273
3274static void
3275x_setup_relief_color (f, relief, factor, delta, default_pixel)
3276 struct frame *f;
3277 struct relief *relief;
68c45bf0 3278 double factor;
06a2c219
GM
3279 int delta;
3280 unsigned long default_pixel;
3281{
3282 XGCValues xgcv;
3283 struct x_output *di = f->output_data.x;
3284 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3285 unsigned long pixel;
3286 unsigned long background = di->relief_background;
43bd1b2b 3287 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3288 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3289 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3290
3291 xgcv.graphics_exposures = False;
3292 xgcv.line_width = 1;
3293
3294 /* Free previously allocated color. The color cell will be reused
3295 when it has been freed as many times as it was allocated, so this
3296 doesn't affect faces using the same colors. */
3297 if (relief->gc
3298 && relief->allocated_p)
3299 {
3300 /* If display has an immutable color map, freeing colors is not
3301 necessary and some servers don't allow it. So don't do it. */
0d605c67 3302 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3303 relief->allocated_p = 0;
3304 }
3305
3306 /* Allocate new color. */
3307 xgcv.foreground = default_pixel;
3308 pixel = background;
dcd08bfb
GM
3309 if (dpyinfo->n_planes != 1
3310 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3311 {
3312 relief->allocated_p = 1;
3313 xgcv.foreground = relief->pixel = pixel;
3314 }
3315
3316 if (relief->gc == 0)
3317 {
dcd08bfb 3318 xgcv.stipple = dpyinfo->gray;
06a2c219 3319 mask |= GCStipple;
dcd08bfb 3320 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3321 }
3322 else
dcd08bfb 3323 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3324}
3325
3326
3327/* Set up colors for the relief lines around glyph string S. */
3328
3329static void
3330x_setup_relief_colors (s)
3331 struct glyph_string *s;
3332{
3333 struct x_output *di = s->f->output_data.x;
3334 unsigned long color;
3335
3336 if (s->face->use_box_color_for_shadows_p)
3337 color = s->face->box_color;
3338 else
3339 {
3340 XGCValues xgcv;
3341
3342 /* Get the background color of the face. */
3343 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3344 color = xgcv.background;
3345 }
3346
3347 if (di->white_relief.gc == 0
3348 || color != di->relief_background)
3349 {
3350 di->relief_background = color;
3351 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3352 WHITE_PIX_DEFAULT (s->f));
3353 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3354 BLACK_PIX_DEFAULT (s->f));
3355 }
3356}
3357
3358
3359/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3360 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3361 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3362 relief. LEFT_P non-zero means draw a relief on the left side of
3363 the rectangle. RIGHT_P non-zero means draw a relief on the right
3364 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3365 when drawing. */
3366
3367static void
3368x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3369 raised_p, left_p, right_p, clip_rect)
3370 struct frame *f;
3371 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3372 XRectangle *clip_rect;
3373{
3374 int i;
3375 GC gc;
3376
3377 if (raised_p)
3378 gc = f->output_data.x->white_relief.gc;
3379 else
3380 gc = f->output_data.x->black_relief.gc;
3381 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3382
3383 /* Top. */
3384 for (i = 0; i < width; ++i)
3385 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3386 left_x + i * left_p, top_y + i,
3387 right_x + 1 - i * right_p, top_y + i);
3388
3389 /* Left. */
3390 if (left_p)
3391 for (i = 0; i < width; ++i)
3392 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3393 left_x + i, top_y + i, left_x + i, bottom_y - i);
3394
3395 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3396 if (raised_p)
3397 gc = f->output_data.x->black_relief.gc;
3398 else
3399 gc = f->output_data.x->white_relief.gc;
3400 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3401
3402 /* Bottom. */
3403 for (i = 0; i < width; ++i)
3404 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3405 left_x + i * left_p, bottom_y - i,
3406 right_x + 1 - i * right_p, bottom_y - i);
3407
3408 /* Right. */
3409 if (right_p)
3410 for (i = 0; i < width; ++i)
3411 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3412 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3413
3414 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3415}
3416
3417
3418/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3419 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3420 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3421 left side of the rectangle. RIGHT_P non-zero means draw a line
3422 on the right side of the rectangle. CLIP_RECT is the clipping
3423 rectangle to use when drawing. */
3424
3425static void
3426x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3427 left_p, right_p, clip_rect)
3428 struct glyph_string *s;
3429 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3430 XRectangle *clip_rect;
3431{
3432 XGCValues xgcv;
3433
3434 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3435 XSetForeground (s->display, s->gc, s->face->box_color);
3436 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3437
3438 /* Top. */
3439 XFillRectangle (s->display, s->window, s->gc,
3440 left_x, top_y, right_x - left_x, width);
3441
3442 /* Left. */
3443 if (left_p)
3444 XFillRectangle (s->display, s->window, s->gc,
3445 left_x, top_y, width, bottom_y - top_y);
3446
3447 /* Bottom. */
3448 XFillRectangle (s->display, s->window, s->gc,
3449 left_x, bottom_y - width, right_x - left_x, width);
3450
3451 /* Right. */
3452 if (right_p)
3453 XFillRectangle (s->display, s->window, s->gc,
3454 right_x - width, top_y, width, bottom_y - top_y);
3455
3456 XSetForeground (s->display, s->gc, xgcv.foreground);
3457 XSetClipMask (s->display, s->gc, None);
3458}
3459
3460
3461/* Draw a box around glyph string S. */
3462
3463static void
3464x_draw_glyph_string_box (s)
3465 struct glyph_string *s;
3466{
3467 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3468 int left_p, right_p;
3469 struct glyph *last_glyph;
3470 XRectangle clip_rect;
3471
3472 last_x = window_box_right (s->w, s->area);
3473 if (s->row->full_width_p
3474 && !s->w->pseudo_window_p)
3475 {
110859fc 3476 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3477 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3478 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3479 }
3480
3481 /* The glyph that may have a right box line. */
b4192550 3482 last_glyph = (s->cmp || s->img
06a2c219
GM
3483 ? s->first_glyph
3484 : s->first_glyph + s->nchars - 1);
3485
3486 width = s->face->box_line_width;
3487 raised_p = s->face->box == FACE_RAISED_BOX;
3488 left_x = s->x;
3489 right_x = ((s->row->full_width_p
1da3fd71 3490 ? last_x - 1
a7aeb2de 3491 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3492 top_y = s->y;
3493 bottom_y = top_y + s->height - 1;
3494
3495 left_p = (s->first_glyph->left_box_line_p
3496 || (s->hl == DRAW_MOUSE_FACE
3497 && (s->prev == NULL
3498 || s->prev->hl != s->hl)));
3499 right_p = (last_glyph->right_box_line_p
3500 || (s->hl == DRAW_MOUSE_FACE
3501 && (s->next == NULL
3502 || s->next->hl != s->hl)));
3503
3504 x_get_glyph_string_clip_rect (s, &clip_rect);
3505
3506 if (s->face->box == FACE_SIMPLE_BOX)
3507 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3508 left_p, right_p, &clip_rect);
3509 else
3510 {
3511 x_setup_relief_colors (s);
3512 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3513 width, raised_p, left_p, right_p, &clip_rect);
3514 }
3515}
3516
3517
3518/* Draw foreground of image glyph string S. */
3519
3520static void
3521x_draw_image_foreground (s)
3522 struct glyph_string *s;
3523{
3524 int x;
3525 int y = s->ybase - IMAGE_ASCENT (s->img);
3526
3527 /* If first glyph of S has a left box line, start drawing it to the
3528 right of that line. */
3529 if (s->face->box != FACE_NO_BOX
3530 && s->first_glyph->left_box_line_p)
3531 x = s->x + s->face->box_line_width;
3532 else
3533 x = s->x;
3534
3535 /* If there is a margin around the image, adjust x- and y-position
3536 by that margin. */
3537 if (s->img->margin)
3538 {
3539 x += s->img->margin;
3540 y += s->img->margin;
3541 }
3542
3543 if (s->img->pixmap)
3544 {
3545 if (s->img->mask)
3546 {
3547 /* We can't set both a clip mask and use XSetClipRectangles
3548 because the latter also sets a clip mask. We also can't
3549 trust on the shape extension to be available
3550 (XShapeCombineRegion). So, compute the rectangle to draw
3551 manually. */
3552 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3553 | GCFunction);
3554 XGCValues xgcv;
3555 XRectangle clip_rect, image_rect, r;
3556
3557 xgcv.clip_mask = s->img->mask;
3558 xgcv.clip_x_origin = x;
3559 xgcv.clip_y_origin = y;
3560 xgcv.function = GXcopy;
3561 XChangeGC (s->display, s->gc, mask, &xgcv);
3562
3563 x_get_glyph_string_clip_rect (s, &clip_rect);
3564 image_rect.x = x;
3565 image_rect.y = y;
3566 image_rect.width = s->img->width;
3567 image_rect.height = s->img->height;
3568 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3569 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3570 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3571 }
3572 else
3573 {
3574 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3575 0, 0, s->img->width, s->img->height, x, y);
3576
3577 /* When the image has a mask, we can expect that at
3578 least part of a mouse highlight or a block cursor will
3579 be visible. If the image doesn't have a mask, make
3580 a block cursor visible by drawing a rectangle around
3581 the image. I believe it's looking better if we do
3582 nothing here for mouse-face. */
3583 if (s->hl == DRAW_CURSOR)
3584 XDrawRectangle (s->display, s->window, s->gc, x, y,
3585 s->img->width - 1, s->img->height - 1);
3586 }
3587 }
3588 else
3589 /* Draw a rectangle if image could not be loaded. */
3590 XDrawRectangle (s->display, s->window, s->gc, x, y,
3591 s->img->width - 1, s->img->height - 1);
3592}
3593
3594
3595/* Draw a relief around the image glyph string S. */
3596
3597static void
3598x_draw_image_relief (s)
3599 struct glyph_string *s;
3600{
3601 int x0, y0, x1, y1, thick, raised_p;
3602 XRectangle r;
3603 int x;
3604 int y = s->ybase - IMAGE_ASCENT (s->img);
3605
3606 /* If first glyph of S has a left box line, start drawing it to the
3607 right of that line. */
3608 if (s->face->box != FACE_NO_BOX
3609 && s->first_glyph->left_box_line_p)
3610 x = s->x + s->face->box_line_width;
3611 else
3612 x = s->x;
3613
3614 /* If there is a margin around the image, adjust x- and y-position
3615 by that margin. */
3616 if (s->img->margin)
3617 {
3618 x += s->img->margin;
3619 y += s->img->margin;
3620 }
3621
3622 if (s->hl == DRAW_IMAGE_SUNKEN
3623 || s->hl == DRAW_IMAGE_RAISED)
3624 {
9ea173e8 3625 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3626 raised_p = s->hl == DRAW_IMAGE_RAISED;
3627 }
3628 else
3629 {
3630 thick = abs (s->img->relief);
3631 raised_p = s->img->relief > 0;
3632 }
3633
3634 x0 = x - thick;
3635 y0 = y - thick;
3636 x1 = x + s->img->width + thick - 1;
3637 y1 = y + s->img->height + thick - 1;
3638
3639 x_setup_relief_colors (s);
3640 x_get_glyph_string_clip_rect (s, &r);
3641 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3642}
3643
3644
3645/* Draw the foreground of image glyph string S to PIXMAP. */
3646
3647static void
3648x_draw_image_foreground_1 (s, pixmap)
3649 struct glyph_string *s;
3650 Pixmap pixmap;
3651{
3652 int x;
3653 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3654
3655 /* If first glyph of S has a left box line, start drawing it to the
3656 right of that line. */
3657 if (s->face->box != FACE_NO_BOX
3658 && s->first_glyph->left_box_line_p)
3659 x = s->face->box_line_width;
3660 else
3661 x = 0;
3662
3663 /* If there is a margin around the image, adjust x- and y-position
3664 by that margin. */
3665 if (s->img->margin)
3666 {
3667 x += s->img->margin;
3668 y += s->img->margin;
3669 }
dc43ef94 3670
06a2c219
GM
3671 if (s->img->pixmap)
3672 {
3673 if (s->img->mask)
3674 {
3675 /* We can't set both a clip mask and use XSetClipRectangles
3676 because the latter also sets a clip mask. We also can't
3677 trust on the shape extension to be available
3678 (XShapeCombineRegion). So, compute the rectangle to draw
3679 manually. */
3680 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3681 | GCFunction);
3682 XGCValues xgcv;
3683
3684 xgcv.clip_mask = s->img->mask;
3685 xgcv.clip_x_origin = x;
3686 xgcv.clip_y_origin = y;
3687 xgcv.function = GXcopy;
3688 XChangeGC (s->display, s->gc, mask, &xgcv);
3689
3690 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3691 0, 0, s->img->width, s->img->height, x, y);
3692 XSetClipMask (s->display, s->gc, None);
3693 }
3694 else
3695 {
3696 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3697 0, 0, s->img->width, s->img->height, x, y);
3698
3699 /* When the image has a mask, we can expect that at
3700 least part of a mouse highlight or a block cursor will
3701 be visible. If the image doesn't have a mask, make
3702 a block cursor visible by drawing a rectangle around
3703 the image. I believe it's looking better if we do
3704 nothing here for mouse-face. */
3705 if (s->hl == DRAW_CURSOR)
3706 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3707 s->img->width - 1, s->img->height - 1);
3708 }
3709 }
3710 else
3711 /* Draw a rectangle if image could not be loaded. */
3712 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3713 s->img->width - 1, s->img->height - 1);
3714}
dc43ef94 3715
990ba854 3716
06a2c219
GM
3717/* Draw part of the background of glyph string S. X, Y, W, and H
3718 give the rectangle to draw. */
a9a5b0a5 3719
06a2c219
GM
3720static void
3721x_draw_glyph_string_bg_rect (s, x, y, w, h)
3722 struct glyph_string *s;
3723 int x, y, w, h;
3724{
3725 if (s->stippled_p)
3726 {
3727 /* Fill background with a stipple pattern. */
3728 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3729 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3730 XSetFillStyle (s->display, s->gc, FillSolid);
3731 }
3732 else
3733 x_clear_glyph_string_rect (s, x, y, w, h);
3734}
07e34cb0 3735
b5210ea7 3736
06a2c219 3737/* Draw image glyph string S.
dc43ef94 3738
06a2c219
GM
3739 s->y
3740 s->x +-------------------------
3741 | s->face->box
3742 |
3743 | +-------------------------
3744 | | s->img->margin
3745 | |
3746 | | +-------------------
3747 | | | the image
dc43ef94 3748
06a2c219 3749 */
dc43ef94 3750
06a2c219
GM
3751static void
3752x_draw_image_glyph_string (s)
3753 struct glyph_string *s;
3754{
3755 int x, y;
3756 int box_line_width = s->face->box_line_width;
3757 int margin = s->img->margin;
3758 int height;
3759 Pixmap pixmap = None;
3760
3761 height = s->height - 2 * box_line_width;
3762
3763 /* Fill background with face under the image. Do it only if row is
3764 taller than image or if image has a clip mask to reduce
3765 flickering. */
3766 s->stippled_p = s->face->stipple != 0;
3767 if (height > s->img->height
3768 || margin
3769 || s->img->mask
3770 || s->img->pixmap == 0
3771 || s->width != s->background_width)
3772 {
3773 if (box_line_width && s->first_glyph->left_box_line_p)
3774 x = s->x + box_line_width;
3775 else
3776 x = s->x;
3777
3778 y = s->y + box_line_width;
3779
3780 if (s->img->mask)
3781 {
3782 /* Create a pixmap as large as the glyph string Fill it with
3783 the background color. Copy the image to it, using its
3784 mask. Copy the temporary pixmap to the display. */
3785 Screen *screen = FRAME_X_SCREEN (s->f);
3786 int depth = DefaultDepthOfScreen (screen);
3787
3788 /* Create a pixmap as large as the glyph string. */
3789 pixmap = XCreatePixmap (s->display, s->window,
3790 s->background_width,
3791 s->height, depth);
3792
3793 /* Don't clip in the following because we're working on the
3794 pixmap. */
3795 XSetClipMask (s->display, s->gc, None);
3796
3797 /* Fill the pixmap with the background color/stipple. */
3798 if (s->stippled_p)
3799 {
3800 /* Fill background with a stipple pattern. */
3801 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3802 XFillRectangle (s->display, pixmap, s->gc,
3803 0, 0, s->background_width, s->height);
3804 XSetFillStyle (s->display, s->gc, FillSolid);
3805 }
3806 else
3807 {
3808 XGCValues xgcv;
3809 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3810 &xgcv);
3811 XSetForeground (s->display, s->gc, xgcv.background);
3812 XFillRectangle (s->display, pixmap, s->gc,
3813 0, 0, s->background_width, s->height);
3814 XSetForeground (s->display, s->gc, xgcv.foreground);
3815 }
3816 }
3817 else
3818 /* Implementation idea: Is it possible to construct a mask?
3819 We could look at the color at the margins of the image, and
3820 say that this color is probably the background color of the
3821 image. */
3822 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3823
3824 s->background_filled_p = 1;
3825 }
dc43ef94 3826
06a2c219
GM
3827 /* Draw the foreground. */
3828 if (pixmap != None)
3829 {
3830 x_draw_image_foreground_1 (s, pixmap);
3831 x_set_glyph_string_clipping (s);
3832 XCopyArea (s->display, pixmap, s->window, s->gc,
3833 0, 0, s->background_width, s->height, s->x, s->y);
3834 XFreePixmap (s->display, pixmap);
3835 }
3836 else
3837 x_draw_image_foreground (s);
b5210ea7 3838
06a2c219
GM
3839 /* If we must draw a relief around the image, do it. */
3840 if (s->img->relief
3841 || s->hl == DRAW_IMAGE_RAISED
3842 || s->hl == DRAW_IMAGE_SUNKEN)
3843 x_draw_image_relief (s);
3844}
8c1a6a84 3845
990ba854 3846
06a2c219 3847/* Draw stretch glyph string S. */
dc43ef94 3848
06a2c219
GM
3849static void
3850x_draw_stretch_glyph_string (s)
3851 struct glyph_string *s;
3852{
3853 xassert (s->first_glyph->type == STRETCH_GLYPH);
3854 s->stippled_p = s->face->stipple != 0;
990ba854 3855
06a2c219
GM
3856 if (s->hl == DRAW_CURSOR
3857 && !x_stretch_cursor_p)
3858 {
3859 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3860 as wide as the stretch glyph. */
3861 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 3862
06a2c219
GM
3863 /* Draw cursor. */
3864 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 3865
06a2c219
GM
3866 /* Clear rest using the GC of the original non-cursor face. */
3867 if (width < s->background_width)
3868 {
3869 GC gc = s->face->gc;
3870 int x = s->x + width, y = s->y;
3871 int w = s->background_width - width, h = s->height;
3872 XRectangle r;
dc43ef94 3873
06a2c219
GM
3874 x_get_glyph_string_clip_rect (s, &r);
3875 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 3876
06a2c219
GM
3877 if (s->face->stipple)
3878 {
3879 /* Fill background with a stipple pattern. */
3880 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3881 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3882 XSetFillStyle (s->display, gc, FillSolid);
3883 }
3884 else
3885 {
3886 XGCValues xgcv;
3887 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3888 XSetForeground (s->display, gc, xgcv.background);
3889 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3890 XSetForeground (s->display, gc, xgcv.foreground);
3891 }
3892 }
3893 }
3894 else
3895 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3896 s->height);
3897
3898 s->background_filled_p = 1;
3899}
3900
3901
3902/* Draw glyph string S. */
3903
3904static void
3905x_draw_glyph_string (s)
3906 struct glyph_string *s;
3907{
3908 /* If S draws into the background of its successor, draw the
3909 background of the successor first so that S can draw into it.
3910 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 3911 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
3912 {
3913 xassert (s->next->img == NULL);
3914 x_set_glyph_string_gc (s->next);
3915 x_set_glyph_string_clipping (s->next);
3916 x_draw_glyph_string_background (s->next, 1);
3917 }
97210f4e 3918
06a2c219
GM
3919 /* Set up S->gc, set clipping and draw S. */
3920 x_set_glyph_string_gc (s);
3921 x_set_glyph_string_clipping (s);
3922
3923 switch (s->first_glyph->type)
3924 {
3925 case IMAGE_GLYPH:
3926 x_draw_image_glyph_string (s);
3927 break;
3928
3929 case STRETCH_GLYPH:
3930 x_draw_stretch_glyph_string (s);
3931 break;
3932
3933 case CHAR_GLYPH:
66ac4b0e
GM
3934 if (s->for_overlaps_p)
3935 s->background_filled_p = 1;
3936 else
3937 x_draw_glyph_string_background (s, 0);
06a2c219
GM
3938 x_draw_glyph_string_foreground (s);
3939 break;
3940
b4192550
KH
3941 case COMPOSITE_GLYPH:
3942 if (s->for_overlaps_p || s->gidx > 0)
3943 s->background_filled_p = 1;
3944 else
3945 x_draw_glyph_string_background (s, 1);
3946 x_draw_composite_glyph_string_foreground (s);
3947 break;
3948
06a2c219
GM
3949 default:
3950 abort ();
3951 }
3952
66ac4b0e 3953 if (!s->for_overlaps_p)
06a2c219 3954 {
66ac4b0e
GM
3955 /* Draw underline. */
3956 if (s->face->underline_p)
3957 {
3958 unsigned long dy, h;
06a2c219 3959
66ac4b0e
GM
3960 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3961 h = 1;
3962 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
3963 dy = s->height - h;
06a2c219 3964
66ac4b0e
GM
3965 if (s->face->underline_defaulted_p)
3966 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3967 s->width, h);
3968 else
3969 {
3970 XGCValues xgcv;
3971 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3972 XSetForeground (s->display, s->gc, s->face->underline_color);
3973 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3974 s->width, h);
3975 XSetForeground (s->display, s->gc, xgcv.foreground);
3976 }
dc6f92b8 3977 }
07e34cb0 3978
66ac4b0e
GM
3979 /* Draw overline. */
3980 if (s->face->overline_p)
06a2c219 3981 {
66ac4b0e
GM
3982 unsigned long dy = 0, h = 1;
3983
3984 if (s->face->overline_color_defaulted_p)
3985 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3986 s->width, h);
3987 else
3988 {
3989 XGCValues xgcv;
3990 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3991 XSetForeground (s->display, s->gc, s->face->overline_color);
3992 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3993 s->width, h);
3994 XSetForeground (s->display, s->gc, xgcv.foreground);
3995 }
06a2c219 3996 }
06a2c219 3997
66ac4b0e
GM
3998 /* Draw strike-through. */
3999 if (s->face->strike_through_p)
06a2c219 4000 {
66ac4b0e
GM
4001 unsigned long h = 1;
4002 unsigned long dy = (s->height - h) / 2;
4003
4004 if (s->face->strike_through_color_defaulted_p)
4005 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4006 s->width, h);
4007 else
4008 {
4009 XGCValues xgcv;
4010 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4011 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4012 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4013 s->width, h);
4014 XSetForeground (s->display, s->gc, xgcv.foreground);
4015 }
06a2c219 4016 }
06a2c219 4017
66ac4b0e
GM
4018 /* Draw relief. */
4019 if (s->face->box != FACE_NO_BOX)
4020 x_draw_glyph_string_box (s);
4021 }
06a2c219
GM
4022
4023 /* Reset clipping. */
4024 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4025}
07e34cb0 4026
06a2c219 4027
b4192550
KH
4028static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4029 struct face **, int));
06a2c219 4030
06a2c219 4031
b4192550
KH
4032/* Load glyph string S with a composition components specified by S->cmp.
4033 FACES is an array of faces for all components of this composition.
4034 S->gidx is the index of the first component for S.
4035 OVERLAPS_P non-zero means S should draw the foreground only, and
4036 use its lines physical height for clipping.
06a2c219 4037
b4192550 4038 Value is the index of a component not in S. */
07e34cb0 4039
b4192550
KH
4040static int
4041x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4042 struct glyph_string *s;
b4192550 4043 struct face **faces;
66ac4b0e 4044 int overlaps_p;
07e34cb0 4045{
b4192550 4046 int i;
06a2c219 4047
b4192550 4048 xassert (s);
06a2c219 4049
b4192550 4050 s->for_overlaps_p = overlaps_p;
06a2c219 4051
b4192550
KH
4052 s->face = faces[s->gidx];
4053 s->font = s->face->font;
4054 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4055
b4192550
KH
4056 /* For all glyphs of this composition, starting at the offset
4057 S->gidx, until we reach the end of the definition or encounter a
4058 glyph that requires the different face, add it to S. */
4059 ++s->nchars;
4060 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4061 ++s->nchars;
06a2c219 4062
b4192550
KH
4063 /* All glyph strings for the same composition has the same width,
4064 i.e. the width set for the first component of the composition. */
06a2c219 4065
06a2c219
GM
4066 s->width = s->first_glyph->pixel_width;
4067
4068 /* If the specified font could not be loaded, use the frame's
4069 default font, but record the fact that we couldn't load it in
4070 the glyph string so that we can draw rectangles for the
4071 characters of the glyph string. */
4072 if (s->font == NULL)
4073 {
4074 s->font_not_found_p = 1;
4075 s->font = FRAME_FONT (s->f);
4076 }
4077
4078 /* Adjust base line for subscript/superscript text. */
4079 s->ybase += s->first_glyph->voffset;
4080
4081 xassert (s->face && s->face->gc);
4082
4083 /* This glyph string must always be drawn with 16-bit functions. */
4084 s->two_byte_p = 1;
b4192550
KH
4085
4086 return s->gidx + s->nchars;
06a2c219
GM
4087}
4088
4089
b4192550 4090/* Load glyph string S with a sequence characters.
06a2c219 4091 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4092 first glyph to consider, END is the index of the last + 1.
4093 OVERLAPS_P non-zero means S should draw the foreground only, and
4094 use its lines physical height for clipping.
4095
4096 Value is the index of the first glyph not in S. */
06a2c219
GM
4097
4098static int
66ac4b0e 4099x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4100 struct glyph_string *s;
4101 int face_id;
66ac4b0e 4102 int start, end, overlaps_p;
06a2c219
GM
4103{
4104 struct glyph *glyph, *last;
4105 int voffset;
ee569018 4106 int glyph_not_available_p;
06a2c219 4107
06a2c219
GM
4108 xassert (s->f == XFRAME (s->w->frame));
4109 xassert (s->nchars == 0);
4110 xassert (start >= 0 && end > start);
4111
66ac4b0e 4112 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4113 glyph = s->row->glyphs[s->area] + start;
4114 last = s->row->glyphs[s->area] + end;
4115 voffset = glyph->voffset;
4116
ee569018
KH
4117 glyph_not_available_p = glyph->glyph_not_available_p;
4118
06a2c219
GM
4119 while (glyph < last
4120 && glyph->type == CHAR_GLYPH
4121 && glyph->voffset == voffset
ee569018
KH
4122 /* Same face id implies same font, nowadays. */
4123 && glyph->face_id == face_id
4124 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4125 {
ee569018
KH
4126 int two_byte_p;
4127
06a2c219 4128 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4129 s->char2b + s->nchars,
4130 &two_byte_p);
4131 s->two_byte_p = two_byte_p;
06a2c219
GM
4132 ++s->nchars;
4133 xassert (s->nchars <= end - start);
4134 s->width += glyph->pixel_width;
4135 ++glyph;
4136 }
4137
4138 s->font = s->face->font;
4139 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4140
4141 /* If the specified font could not be loaded, use the frame's font,
4142 but record the fact that we couldn't load it in
4143 S->font_not_found_p so that we can draw rectangles for the
4144 characters of the glyph string. */
ee569018 4145 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4146 {
4147 s->font_not_found_p = 1;
4148 s->font = FRAME_FONT (s->f);
4149 }
4150
4151 /* Adjust base line for subscript/superscript text. */
4152 s->ybase += voffset;
66ac4b0e 4153
06a2c219
GM
4154 xassert (s->face && s->face->gc);
4155 return glyph - s->row->glyphs[s->area];
07e34cb0 4156}
dc6f92b8 4157
06a2c219
GM
4158
4159/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4160
dfcf069d 4161static void
06a2c219
GM
4162x_fill_image_glyph_string (s)
4163 struct glyph_string *s;
4164{
4165 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4166 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4167 xassert (s->img);
43d120d8 4168 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4169 s->font = s->face->font;
4170 s->width = s->first_glyph->pixel_width;
4171
4172 /* Adjust base line for subscript/superscript text. */
4173 s->ybase += s->first_glyph->voffset;
4174}
4175
4176
4177/* Fill glyph string S from stretch glyph S->first_glyph. */
4178
4179static void
4180x_fill_stretch_glyph_string (s)
4181 struct glyph_string *s;
4182{
4183 xassert (s->first_glyph->type == STRETCH_GLYPH);
43d120d8 4184 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4185 s->font = s->face->font;
4186 s->width = s->first_glyph->pixel_width;
4187
4188 /* Adjust base line for subscript/superscript text. */
4189 s->ybase += s->first_glyph->voffset;
4190}
4191
4192
4193/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4194 of XChar2b structures for S; it can't be allocated in
4195 x_init_glyph_string because it must be allocated via `alloca'. W
4196 is the window on which S is drawn. ROW and AREA are the glyph row
4197 and area within the row from which S is constructed. START is the
4198 index of the first glyph structure covered by S. HL is a
4199 face-override for drawing S. */
4200
4201static void
4202x_init_glyph_string (s, char2b, w, row, area, start, hl)
4203 struct glyph_string *s;
4204 XChar2b *char2b;
4205 struct window *w;
4206 struct glyph_row *row;
4207 enum glyph_row_area area;
4208 int start;
4209 enum draw_glyphs_face hl;
4210{
4211 bzero (s, sizeof *s);
4212 s->w = w;
4213 s->f = XFRAME (w->frame);
4214 s->display = FRAME_X_DISPLAY (s->f);
4215 s->window = FRAME_X_WINDOW (s->f);
4216 s->char2b = char2b;
4217 s->hl = hl;
4218 s->row = row;
4219 s->area = area;
4220 s->first_glyph = row->glyphs[area] + start;
4221 s->height = row->height;
4222 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4223
9ea173e8
GM
4224 /* Display the internal border below the tool-bar window. */
4225 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4226 s->y -= s->f->output_data.x->internal_border_width;
4227
4228 s->ybase = s->y + row->ascent;
4229}
4230
4231
4232/* Set background width of glyph string S. START is the index of the
4233 first glyph following S. LAST_X is the right-most x-position + 1
4234 in the drawing area. */
4235
4236static INLINE void
4237x_set_glyph_string_background_width (s, start, last_x)
4238 struct glyph_string *s;
4239 int start;
4240 int last_x;
4241{
4242 /* If the face of this glyph string has to be drawn to the end of
4243 the drawing area, set S->extends_to_end_of_line_p. */
4244 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4245
4246 if (start == s->row->used[s->area]
4247 && s->hl == DRAW_NORMAL_TEXT
4248 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4249 || s->face->background != default_face->background
4250 || s->face->stipple != default_face->stipple))
4251 s->extends_to_end_of_line_p = 1;
4252
4253 /* If S extends its face to the end of the line, set its
4254 background_width to the distance to the right edge of the drawing
4255 area. */
4256 if (s->extends_to_end_of_line_p)
1da3fd71 4257 s->background_width = last_x - s->x + 1;
06a2c219
GM
4258 else
4259 s->background_width = s->width;
4260}
4261
4262
4263/* Add a glyph string for a stretch glyph to the list of strings
4264 between HEAD and TAIL. START is the index of the stretch glyph in
4265 row area AREA of glyph row ROW. END is the index of the last glyph
4266 in that glyph row area. X is the current output position assigned
4267 to the new glyph string constructed. HL overrides that face of the
4268 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4269 is the right-most x-position of the drawing area. */
4270
8abee2e1
DL
4271/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4272 and below -- keep them on one line. */
4273#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4274 do \
4275 { \
4276 s = (struct glyph_string *) alloca (sizeof *s); \
4277 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4278 x_fill_stretch_glyph_string (s); \
4279 x_append_glyph_string (&HEAD, &TAIL, s); \
4280 ++START; \
4281 s->x = (X); \
4282 } \
4283 while (0)
4284
4285
4286/* Add a glyph string for an image glyph to the list of strings
4287 between HEAD and TAIL. START is the index of the image glyph in
4288 row area AREA of glyph row ROW. END is the index of the last glyph
4289 in that glyph row area. X is the current output position assigned
4290 to the new glyph string constructed. HL overrides that face of the
4291 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4292 is the right-most x-position of the drawing area. */
4293
8abee2e1 4294#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4295 do \
4296 { \
4297 s = (struct glyph_string *) alloca (sizeof *s); \
4298 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4299 x_fill_image_glyph_string (s); \
4300 x_append_glyph_string (&HEAD, &TAIL, s); \
4301 ++START; \
4302 s->x = (X); \
4303 } \
4304 while (0)
4305
4306
4307/* Add a glyph string for a sequence of character glyphs to the list
4308 of strings between HEAD and TAIL. START is the index of the first
4309 glyph in row area AREA of glyph row ROW that is part of the new
4310 glyph string. END is the index of the last glyph in that glyph row
4311 area. X is the current output position assigned to the new glyph
4312 string constructed. HL overrides that face of the glyph; e.g. it
4313 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4314 right-most x-position of the drawing area. */
4315
8abee2e1 4316#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4317 do \
4318 { \
4319 int c, charset, face_id; \
4320 XChar2b *char2b; \
4321 \
43d120d8 4322 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4323 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4324 \
b4192550
KH
4325 s = (struct glyph_string *) alloca (sizeof *s); \
4326 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4327 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4328 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4329 s->x = (X); \
4330 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4331 OVERLAPS_P); \
06a2c219
GM
4332 } \
4333 while (0)
4334
4335
b4192550
KH
4336/* Add a glyph string for a composite sequence to the list of strings
4337 between HEAD and TAIL. START is the index of the first glyph in
4338 row area AREA of glyph row ROW that is part of the new glyph
4339 string. END is the index of the last glyph in that glyph row area.
4340 X is the current output position assigned to the new glyph string
4341 constructed. HL overrides that face of the glyph; e.g. it is
4342 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4343 x-position of the drawing area. */
4344
6c27ec25 4345#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4346 do { \
43d120d8
KH
4347 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4348 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4349 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4350 struct composition *cmp = composition_table[cmp_id]; \
4351 int glyph_len = cmp->glyph_len; \
4352 XChar2b *char2b; \
4353 struct face **faces; \
4354 struct glyph_string *first_s = NULL; \
4355 int n; \
4356 \
ee569018 4357 base_face = base_face->ascii_face; \
b4192550
KH
4358 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4359 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4360 /* At first, fill in `char2b' and `faces'. */ \
4361 for (n = 0; n < glyph_len; n++) \
4362 { \
43d120d8 4363 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4364 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4365 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4366 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4367 this_face_id, char2b + n, 1); \
b4192550
KH
4368 } \
4369 \
4370 /* Make glyph_strings for each glyph sequence that is drawable by \
4371 the same face, and append them to HEAD/TAIL. */ \
4372 for (n = 0; n < cmp->glyph_len;) \
4373 { \
4374 s = (struct glyph_string *) alloca (sizeof *s); \
4375 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4376 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4377 s->cmp = cmp; \
4378 s->gidx = n; \
b4192550
KH
4379 s->x = (X); \
4380 \
4381 if (n == 0) \
4382 first_s = s; \
4383 \
4384 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4385 } \
4386 \
4387 ++START; \
4388 s = first_s; \
4389 } while (0)
4390
4391
06a2c219
GM
4392/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4393 of AREA of glyph row ROW on window W between indices START and END.
4394 HL overrides the face for drawing glyph strings, e.g. it is
4395 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4396 x-positions of the drawing area.
4397
4398 This is an ugly monster macro construct because we must use alloca
4399 to allocate glyph strings (because x_draw_glyphs can be called
4400 asynchronously). */
4401
8abee2e1 4402#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4403 do \
4404 { \
4405 HEAD = TAIL = NULL; \
4406 while (START < END) \
4407 { \
4408 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4409 switch (first_glyph->type) \
4410 { \
4411 case CHAR_GLYPH: \
4412 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4413 TAIL, HL, X, LAST_X, \
4414 OVERLAPS_P); \
06a2c219
GM
4415 break; \
4416 \
b4192550
KH
4417 case COMPOSITE_GLYPH: \
4418 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4419 HEAD, TAIL, HL, X, LAST_X,\
4420 OVERLAPS_P); \
4421 break; \
4422 \
06a2c219
GM
4423 case STRETCH_GLYPH: \
4424 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4425 HEAD, TAIL, HL, X, LAST_X); \
4426 break; \
4427 \
4428 case IMAGE_GLYPH: \
4429 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4430 TAIL, HL, X, LAST_X); \
4431 break; \
4432 \
4433 default: \
4434 abort (); \
4435 } \
4436 \
4437 x_set_glyph_string_background_width (s, START, LAST_X); \
4438 (X) += s->width; \
4439 } \
4440 } \
4441 while (0)
4442
4443
4444/* Draw glyphs between START and END in AREA of ROW on window W,
4445 starting at x-position X. X is relative to AREA in W. HL is a
4446 face-override with the following meaning:
4447
4448 DRAW_NORMAL_TEXT draw normally
4449 DRAW_CURSOR draw in cursor face
4450 DRAW_MOUSE_FACE draw in mouse face.
4451 DRAW_INVERSE_VIDEO draw in mode line face
4452 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4453 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4454
4455 If REAL_START is non-null, return in *REAL_START the real starting
4456 position for display. This can be different from START in case
4457 overlapping glyphs must be displayed. If REAL_END is non-null,
4458 return in *REAL_END the real end position for display. This can be
4459 different from END in case overlapping glyphs must be displayed.
4460
66ac4b0e
GM
4461 If OVERLAPS_P is non-zero, draw only the foreground of characters
4462 and clip to the physical height of ROW.
4463
06a2c219
GM
4464 Value is the x-position reached, relative to AREA of W. */
4465
4466static int
66ac4b0e
GM
4467x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4468 overlaps_p)
06a2c219
GM
4469 struct window *w;
4470 int x;
4471 struct glyph_row *row;
4472 enum glyph_row_area area;
4473 int start, end;
4474 enum draw_glyphs_face hl;
4475 int *real_start, *real_end;
66ac4b0e 4476 int overlaps_p;
dc6f92b8 4477{
06a2c219
GM
4478 struct glyph_string *head, *tail;
4479 struct glyph_string *s;
4480 int last_x, area_width;
4481 int x_reached;
4482 int i, j;
4483
4484 /* Let's rather be paranoid than getting a SEGV. */
4485 start = max (0, start);
4486 end = min (end, row->used[area]);
4487 if (real_start)
4488 *real_start = start;
4489 if (real_end)
4490 *real_end = end;
4491
4492 /* Translate X to frame coordinates. Set last_x to the right
4493 end of the drawing area. */
4494 if (row->full_width_p)
4495 {
4496 /* X is relative to the left edge of W, without scroll bars
4497 or flag areas. */
4498 struct frame *f = XFRAME (w->frame);
110859fc 4499 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4500 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4501
06a2c219
GM
4502 x += window_left_x;
4503 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4504 last_x = window_left_x + area_width;
4505
4506 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4507 {
110859fc 4508 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4509 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4510 last_x += width;
4511 else
4512 x -= width;
4513 }
dc6f92b8 4514
b9432a85
GM
4515 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4516 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4517 }
4518 else
dc6f92b8 4519 {
06a2c219
GM
4520 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4521 area_width = window_box_width (w, area);
4522 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4523 }
4524
06a2c219
GM
4525 /* Build a doubly-linked list of glyph_string structures between
4526 head and tail from what we have to draw. Note that the macro
4527 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4528 the reason we use a separate variable `i'. */
4529 i = start;
66ac4b0e
GM
4530 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4531 overlaps_p);
06a2c219
GM
4532 if (tail)
4533 x_reached = tail->x + tail->background_width;
4534 else
4535 x_reached = x;
90e65f07 4536
06a2c219
GM
4537 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4538 the row, redraw some glyphs in front or following the glyph
4539 strings built above. */
66ac4b0e 4540 if (!overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4541 {
4542 int dummy_x = 0;
4543 struct glyph_string *h, *t;
4544
4545 /* Compute overhangs for all glyph strings. */
4546 for (s = head; s; s = s->next)
4547 x_compute_glyph_string_overhangs (s);
4548
4549 /* Prepend glyph strings for glyphs in front of the first glyph
4550 string that are overwritten because of the first glyph
4551 string's left overhang. The background of all strings
4552 prepended must be drawn because the first glyph string
4553 draws over it. */
4554 i = x_left_overwritten (head);
4555 if (i >= 0)
4556 {
4557 j = i;
4558 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4559 DRAW_NORMAL_TEXT, dummy_x, last_x,
4560 overlaps_p);
06a2c219
GM
4561 start = i;
4562 if (real_start)
4563 *real_start = start;
4564 x_compute_overhangs_and_x (t, head->x, 1);
4565 x_prepend_glyph_string_lists (&head, &tail, h, t);
4566 }
58769bee 4567
06a2c219
GM
4568 /* Prepend glyph strings for glyphs in front of the first glyph
4569 string that overwrite that glyph string because of their
4570 right overhang. For these strings, only the foreground must
4571 be drawn, because it draws over the glyph string at `head'.
4572 The background must not be drawn because this would overwrite
4573 right overhangs of preceding glyphs for which no glyph
4574 strings exist. */
4575 i = x_left_overwriting (head);
4576 if (i >= 0)
4577 {
4578 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4579 DRAW_NORMAL_TEXT, dummy_x, last_x,
4580 overlaps_p);
06a2c219
GM
4581 for (s = h; s; s = s->next)
4582 s->background_filled_p = 1;
4583 if (real_start)
4584 *real_start = i;
4585 x_compute_overhangs_and_x (t, head->x, 1);
4586 x_prepend_glyph_string_lists (&head, &tail, h, t);
4587 }
dbcb258a 4588
06a2c219
GM
4589 /* Append glyphs strings for glyphs following the last glyph
4590 string tail that are overwritten by tail. The background of
4591 these strings has to be drawn because tail's foreground draws
4592 over it. */
4593 i = x_right_overwritten (tail);
4594 if (i >= 0)
4595 {
4596 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4597 DRAW_NORMAL_TEXT, x, last_x,
4598 overlaps_p);
06a2c219
GM
4599 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4600 x_append_glyph_string_lists (&head, &tail, h, t);
4601 if (real_end)
4602 *real_end = i;
4603 }
dc6f92b8 4604
06a2c219
GM
4605 /* Append glyph strings for glyphs following the last glyph
4606 string tail that overwrite tail. The foreground of such
4607 glyphs has to be drawn because it writes into the background
4608 of tail. The background must not be drawn because it could
4609 paint over the foreground of following glyphs. */
4610 i = x_right_overwriting (tail);
4611 if (i >= 0)
4612 {
4613 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4614 DRAW_NORMAL_TEXT, x, last_x,
4615 overlaps_p);
06a2c219
GM
4616 for (s = h; s; s = s->next)
4617 s->background_filled_p = 1;
4618 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4619 x_append_glyph_string_lists (&head, &tail, h, t);
4620 if (real_end)
4621 *real_end = i;
4622 }
4623 }
58769bee 4624
06a2c219
GM
4625 /* Draw all strings. */
4626 for (s = head; s; s = s->next)
4627 x_draw_glyph_string (s);
dc6f92b8 4628
06a2c219
GM
4629 /* Value is the x-position up to which drawn, relative to AREA of W.
4630 This doesn't include parts drawn because of overhangs. */
4631 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4632 if (!row->full_width_p)
4633 {
4634 if (area > LEFT_MARGIN_AREA)
4635 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4636 if (area > TEXT_AREA)
4637 x_reached -= window_box_width (w, TEXT_AREA);
4638 }
4639 return x_reached;
4640}
dc6f92b8 4641
dc6f92b8 4642
66ac4b0e
GM
4643/* Fix the display of area AREA of overlapping row ROW in window W. */
4644
4645static void
4646x_fix_overlapping_area (w, row, area)
4647 struct window *w;
4648 struct glyph_row *row;
4649 enum glyph_row_area area;
4650{
4651 int i, x;
4652
4653 BLOCK_INPUT;
4654
4655 if (area == LEFT_MARGIN_AREA)
4656 x = 0;
4657 else if (area == TEXT_AREA)
4658 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4659 else
4660 x = (window_box_width (w, LEFT_MARGIN_AREA)
4661 + window_box_width (w, TEXT_AREA));
4662
4663 for (i = 0; i < row->used[area];)
4664 {
4665 if (row->glyphs[area][i].overlaps_vertically_p)
4666 {
4667 int start = i, start_x = x;
4668
4669 do
4670 {
4671 x += row->glyphs[area][i].pixel_width;
4672 ++i;
4673 }
4674 while (i < row->used[area]
4675 && row->glyphs[area][i].overlaps_vertically_p);
4676
4677 x_draw_glyphs (w, start_x, row, area, start, i,
4678 (row->inverse_p
4679 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4680 NULL, NULL, 1);
4681 }
4682 else
4683 {
4684 x += row->glyphs[area][i].pixel_width;
4685 ++i;
4686 }
4687 }
4688
4689 UNBLOCK_INPUT;
4690}
4691
4692
06a2c219
GM
4693/* Output LEN glyphs starting at START at the nominal cursor position.
4694 Advance the nominal cursor over the text. The global variable
4695 updated_window contains the window being updated, updated_row is
4696 the glyph row being updated, and updated_area is the area of that
4697 row being updated. */
dc6f92b8 4698
06a2c219
GM
4699static void
4700x_write_glyphs (start, len)
4701 struct glyph *start;
4702 int len;
4703{
4704 int x, hpos, real_start, real_end;
d9cdbb3d 4705
06a2c219 4706 xassert (updated_window && updated_row);
dc6f92b8 4707 BLOCK_INPUT;
06a2c219
GM
4708
4709 /* Write glyphs. */
dc6f92b8 4710
06a2c219
GM
4711 hpos = start - updated_row->glyphs[updated_area];
4712 x = x_draw_glyphs (updated_window, output_cursor.x,
4713 updated_row, updated_area,
4714 hpos, hpos + len,
4715 (updated_row->inverse_p
4716 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 4717 &real_start, &real_end, 0);
b30ec466 4718
06a2c219
GM
4719 /* If we drew over the cursor, note that it is not visible any more. */
4720 note_overwritten_text_cursor (updated_window, real_start,
4721 real_end - real_start);
dc6f92b8
JB
4722
4723 UNBLOCK_INPUT;
06a2c219
GM
4724
4725 /* Advance the output cursor. */
4726 output_cursor.hpos += len;
4727 output_cursor.x = x;
dc6f92b8
JB
4728}
4729
0cdd0c9f 4730
06a2c219 4731/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4732
06a2c219
GM
4733static void
4734x_insert_glyphs (start, len)
4735 struct glyph *start;
4736 register int len;
4737{
4738 struct frame *f;
4739 struct window *w;
4740 int line_height, shift_by_width, shifted_region_width;
4741 struct glyph_row *row;
4742 struct glyph *glyph;
4743 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4744
06a2c219 4745 xassert (updated_window && updated_row);
0cdd0c9f 4746 BLOCK_INPUT;
06a2c219
GM
4747 w = updated_window;
4748 f = XFRAME (WINDOW_FRAME (w));
4749
4750 /* Get the height of the line we are in. */
4751 row = updated_row;
4752 line_height = row->height;
4753
4754 /* Get the width of the glyphs to insert. */
4755 shift_by_width = 0;
4756 for (glyph = start; glyph < start + len; ++glyph)
4757 shift_by_width += glyph->pixel_width;
4758
4759 /* Get the width of the region to shift right. */
4760 shifted_region_width = (window_box_width (w, updated_area)
4761 - output_cursor.x
4762 - shift_by_width);
4763
4764 /* Shift right. */
4765 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4766 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4767 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4768 f->output_data.x->normal_gc,
4769 frame_x, frame_y,
4770 shifted_region_width, line_height,
4771 frame_x + shift_by_width, frame_y);
4772
4773 /* Write the glyphs. */
4774 hpos = start - row->glyphs[updated_area];
4775 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 4776 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
4777 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4778
4779 /* Advance the output cursor. */
4780 output_cursor.hpos += len;
4781 output_cursor.x += shift_by_width;
0cdd0c9f
RS
4782 UNBLOCK_INPUT;
4783}
0cdd0c9f 4784
0cdd0c9f 4785
06a2c219
GM
4786/* Delete N glyphs at the nominal cursor position. Not implemented
4787 for X frames. */
c83febd7
RS
4788
4789static void
06a2c219
GM
4790x_delete_glyphs (n)
4791 register int n;
c83febd7 4792{
06a2c219 4793 abort ();
c83febd7
RS
4794}
4795
0cdd0c9f 4796
06a2c219
GM
4797/* Erase the current text line from the nominal cursor position
4798 (inclusive) to pixel column TO_X (exclusive). The idea is that
4799 everything from TO_X onward is already erased.
4800
4801 TO_X is a pixel position relative to updated_area of
4802 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 4803
06a2c219
GM
4804static void
4805x_clear_end_of_line (to_x)
4806 int to_x;
4807{
4808 struct frame *f;
4809 struct window *w = updated_window;
4810 int max_x, min_y, max_y;
4811 int from_x, from_y, to_y;
4812
4813 xassert (updated_window && updated_row);
4814 f = XFRAME (w->frame);
4815
4816 if (updated_row->full_width_p)
4817 {
4818 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4819 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4820 && !w->pseudo_window_p)
4821 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 4822 }
06a2c219
GM
4823 else
4824 max_x = window_box_width (w, updated_area);
4825 max_y = window_text_bottom_y (w);
dc6f92b8 4826
06a2c219
GM
4827 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4828 of window. For TO_X > 0, truncate to end of drawing area. */
4829 if (to_x == 0)
4830 return;
4831 else if (to_x < 0)
4832 to_x = max_x;
4833 else
4834 to_x = min (to_x, max_x);
dbc4e1c1 4835
06a2c219
GM
4836 to_y = min (max_y, output_cursor.y + updated_row->height);
4837
4838 /* Notice if the cursor will be cleared by this operation. */
4839 if (!updated_row->full_width_p)
4840 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 4841
06a2c219
GM
4842 from_x = output_cursor.x;
4843
4844 /* Translate to frame coordinates. */
4845 if (updated_row->full_width_p)
4846 {
4847 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4848 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4849 }
0cdd0c9f
RS
4850 else
4851 {
06a2c219
GM
4852 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4853 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4854 }
4855
045dee35 4856 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
4857 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4858 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4859
4860 /* Prevent inadvertently clearing to end of the X window. */
4861 if (to_x > from_x && to_y > from_y)
4862 {
4863 BLOCK_INPUT;
4864 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4865 from_x, from_y, to_x - from_x, to_y - from_y,
4866 False);
4867 UNBLOCK_INPUT;
0cdd0c9f 4868 }
0cdd0c9f 4869}
dbc4e1c1 4870
0cdd0c9f 4871
06a2c219 4872/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 4873 frame. Otherwise clear the selected frame. */
06a2c219
GM
4874
4875static void
4876x_clear_frame ()
0cdd0c9f 4877{
06a2c219 4878 struct frame *f;
0cdd0c9f 4879
06a2c219
GM
4880 if (updating_frame)
4881 f = updating_frame;
0cdd0c9f 4882 else
b86bd3dd 4883 f = SELECTED_FRAME ();
58769bee 4884
06a2c219
GM
4885 /* Clearing the frame will erase any cursor, so mark them all as no
4886 longer visible. */
4887 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4888 output_cursor.hpos = output_cursor.vpos = 0;
4889 output_cursor.x = -1;
4890
4891 /* We don't set the output cursor here because there will always
4892 follow an explicit cursor_to. */
4893 BLOCK_INPUT;
4894 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4895
4896 /* We have to clear the scroll bars, too. If we have changed
4897 colors or something like that, then they should be notified. */
4898 x_scroll_bar_clear (f);
0cdd0c9f 4899
06a2c219
GM
4900 XFlush (FRAME_X_DISPLAY (f));
4901 UNBLOCK_INPUT;
dc6f92b8 4902}
06a2c219
GM
4903
4904
dc6f92b8 4905\f
dbc4e1c1
JB
4906/* Invert the middle quarter of the frame for .15 sec. */
4907
06a2c219
GM
4908/* We use the select system call to do the waiting, so we have to make
4909 sure it's available. If it isn't, we just won't do visual bells. */
4910
dbc4e1c1
JB
4911#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4912
06a2c219
GM
4913
4914/* Subtract the `struct timeval' values X and Y, storing the result in
4915 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
4916
4917static int
4918timeval_subtract (result, x, y)
4919 struct timeval *result, x, y;
4920{
06a2c219
GM
4921 /* Perform the carry for the later subtraction by updating y. This
4922 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
4923 if (x.tv_usec < y.tv_usec)
4924 {
4925 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4926 y.tv_usec -= 1000000 * nsec;
4927 y.tv_sec += nsec;
4928 }
06a2c219 4929
dbc4e1c1
JB
4930 if (x.tv_usec - y.tv_usec > 1000000)
4931 {
4932 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4933 y.tv_usec += 1000000 * nsec;
4934 y.tv_sec -= nsec;
4935 }
4936
06a2c219
GM
4937 /* Compute the time remaining to wait. tv_usec is certainly
4938 positive. */
dbc4e1c1
JB
4939 result->tv_sec = x.tv_sec - y.tv_sec;
4940 result->tv_usec = x.tv_usec - y.tv_usec;
4941
06a2c219
GM
4942 /* Return indication of whether the result should be considered
4943 negative. */
dbc4e1c1
JB
4944 return x.tv_sec < y.tv_sec;
4945}
dc6f92b8 4946
dfcf069d 4947void
f676886a
JB
4948XTflash (f)
4949 struct frame *f;
dc6f92b8 4950{
dbc4e1c1 4951 BLOCK_INPUT;
dc6f92b8 4952
dbc4e1c1
JB
4953 {
4954 GC gc;
dc6f92b8 4955
06a2c219
GM
4956 /* Create a GC that will use the GXxor function to flip foreground
4957 pixels into background pixels. */
dbc4e1c1
JB
4958 {
4959 XGCValues values;
dc6f92b8 4960
dbc4e1c1 4961 values.function = GXxor;
7556890b
RS
4962 values.foreground = (f->output_data.x->foreground_pixel
4963 ^ f->output_data.x->background_pixel);
58769bee 4964
334208b7 4965 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
4966 GCFunction | GCForeground, &values);
4967 }
dc6f92b8 4968
dbc4e1c1 4969 {
e84e14c3
RS
4970 /* Get the height not including a menu bar widget. */
4971 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
4972 /* Height of each line to flash. */
4973 int flash_height = FRAME_LINE_HEIGHT (f);
4974 /* These will be the left and right margins of the rectangles. */
4975 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4976 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4977
4978 int width;
4979
4980 /* Don't flash the area between a scroll bar and the frame
4981 edge it is next to. */
4982 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4983 {
4984 case vertical_scroll_bar_left:
4985 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4986 break;
4987
4988 case vertical_scroll_bar_right:
4989 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4990 break;
06a2c219
GM
4991
4992 default:
4993 break;
e84e14c3
RS
4994 }
4995
4996 width = flash_right - flash_left;
4997
4998 /* If window is tall, flash top and bottom line. */
4999 if (height > 3 * FRAME_LINE_HEIGHT (f))
5000 {
5001 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5002 flash_left,
5003 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5004 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5005 width, flash_height);
5006 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5007 flash_left,
5008 (height - flash_height
5009 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5010 width, flash_height);
5011 }
5012 else
5013 /* If it is short, flash it all. */
5014 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5015 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5016 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5017
06a2c219 5018 x_flush (f);
dc6f92b8 5019
dbc4e1c1 5020 {
06a2c219 5021 struct timeval wakeup;
dc6f92b8 5022
66c30ea1 5023 EMACS_GET_TIME (wakeup);
dc6f92b8 5024
dbc4e1c1
JB
5025 /* Compute time to wait until, propagating carry from usecs. */
5026 wakeup.tv_usec += 150000;
5027 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5028 wakeup.tv_usec %= 1000000;
5029
5030 /* Keep waiting until past the time wakeup. */
5031 while (1)
5032 {
5033 struct timeval timeout;
5034
66c30ea1 5035 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5036
5037 /* In effect, timeout = wakeup - timeout.
5038 Break if result would be negative. */
5039 if (timeval_subtract (&timeout, wakeup, timeout))
5040 break;
5041
5042 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5043 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5044 }
5045 }
58769bee 5046
e84e14c3
RS
5047 /* If window is tall, flash top and bottom line. */
5048 if (height > 3 * FRAME_LINE_HEIGHT (f))
5049 {
5050 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5051 flash_left,
5052 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5053 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5054 width, flash_height);
5055 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5056 flash_left,
5057 (height - flash_height
5058 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5059 width, flash_height);
5060 }
5061 else
5062 /* If it is short, flash it all. */
5063 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5064 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5065 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5066
334208b7 5067 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5068 x_flush (f);
dc6f92b8 5069 }
dbc4e1c1
JB
5070 }
5071
5072 UNBLOCK_INPUT;
dc6f92b8
JB
5073}
5074
06a2c219 5075#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5076
5077
dc6f92b8
JB
5078/* Make audible bell. */
5079
dfcf069d 5080void
dc6f92b8
JB
5081XTring_bell ()
5082{
b86bd3dd
GM
5083 struct frame *f = SELECTED_FRAME ();
5084
5085 if (FRAME_X_DISPLAY (f))
5086 {
dbc4e1c1 5087#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5088 if (visible_bell)
5089 XTflash (f);
5090 else
dbc4e1c1 5091#endif
b86bd3dd
GM
5092 {
5093 BLOCK_INPUT;
5094 XBell (FRAME_X_DISPLAY (f), 0);
5095 XFlush (FRAME_X_DISPLAY (f));
5096 UNBLOCK_INPUT;
5097 }
dc6f92b8
JB
5098 }
5099}
06a2c219 5100
dc6f92b8 5101\f
06a2c219
GM
5102/* Specify how many text lines, from the top of the window,
5103 should be affected by insert-lines and delete-lines operations.
5104 This, and those operations, are used only within an update
5105 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5106
dfcf069d 5107static void
06a2c219
GM
5108XTset_terminal_window (n)
5109 register int n;
dc6f92b8 5110{
06a2c219 5111 /* This function intentionally left blank. */
dc6f92b8
JB
5112}
5113
06a2c219
GM
5114
5115\f
5116/***********************************************************************
5117 Line Dance
5118 ***********************************************************************/
5119
5120/* Perform an insert-lines or delete-lines operation, inserting N
5121 lines or deleting -N lines at vertical position VPOS. */
5122
dfcf069d 5123static void
06a2c219
GM
5124x_ins_del_lines (vpos, n)
5125 int vpos, n;
dc6f92b8
JB
5126{
5127 abort ();
5128}
06a2c219
GM
5129
5130
5131/* Scroll part of the display as described by RUN. */
dc6f92b8 5132
dfcf069d 5133static void
06a2c219
GM
5134x_scroll_run (w, run)
5135 struct window *w;
5136 struct run *run;
dc6f92b8 5137{
06a2c219
GM
5138 struct frame *f = XFRAME (w->frame);
5139 int x, y, width, height, from_y, to_y, bottom_y;
5140
5141 /* Get frame-relative bounding box of the text display area of W,
5142 without mode lines. Include in this box the flags areas to the
5143 left and right of W. */
5144 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5145 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5146 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5147
5148 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5149 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5150 bottom_y = y + height;
dc6f92b8 5151
06a2c219
GM
5152 if (to_y < from_y)
5153 {
5154 /* Scrolling up. Make sure we don't copy part of the mode
5155 line at the bottom. */
5156 if (from_y + run->height > bottom_y)
5157 height = bottom_y - from_y;
5158 else
5159 height = run->height;
5160 }
dc6f92b8 5161 else
06a2c219
GM
5162 {
5163 /* Scolling down. Make sure we don't copy over the mode line.
5164 at the bottom. */
5165 if (to_y + run->height > bottom_y)
5166 height = bottom_y - to_y;
5167 else
5168 height = run->height;
5169 }
7a13e894 5170
06a2c219
GM
5171 BLOCK_INPUT;
5172
5173 /* Cursor off. Will be switched on again in x_update_window_end. */
5174 updated_window = w;
5175 x_clear_cursor (w);
5176
5177 XCopyArea (FRAME_X_DISPLAY (f),
5178 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5179 f->output_data.x->normal_gc,
5180 x, from_y,
5181 width, height,
5182 x, to_y);
5183
5184 UNBLOCK_INPUT;
5185}
dc6f92b8 5186
dc6f92b8 5187
06a2c219
GM
5188\f
5189/***********************************************************************
5190 Exposure Events
5191 ***********************************************************************/
5192
5193/* Redisplay an exposed area of frame F. X and Y are the upper-left
5194 corner of the exposed rectangle. W and H are width and height of
5195 the exposed area. All are pixel values. W or H zero means redraw
5196 the entire frame. */
dc6f92b8 5197
06a2c219
GM
5198static void
5199expose_frame (f, x, y, w, h)
5200 struct frame *f;
5201 int x, y, w, h;
dc6f92b8 5202{
06a2c219 5203 XRectangle r;
dc6f92b8 5204
06a2c219 5205 TRACE ((stderr, "expose_frame "));
dc6f92b8 5206
06a2c219
GM
5207 /* No need to redraw if frame will be redrawn soon. */
5208 if (FRAME_GARBAGED_P (f))
dc6f92b8 5209 {
06a2c219
GM
5210 TRACE ((stderr, " garbaged\n"));
5211 return;
5212 }
5213
5214 /* If basic faces haven't been realized yet, there is no point in
5215 trying to redraw anything. This can happen when we get an expose
5216 event while Emacs is starting, e.g. by moving another window. */
5217 if (FRAME_FACE_CACHE (f) == NULL
5218 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5219 {
5220 TRACE ((stderr, " no faces\n"));
5221 return;
58769bee 5222 }
06a2c219
GM
5223
5224 if (w == 0 || h == 0)
58769bee 5225 {
06a2c219
GM
5226 r.x = r.y = 0;
5227 r.width = CANON_X_UNIT (f) * f->width;
5228 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5229 }
5230 else
5231 {
06a2c219
GM
5232 r.x = x;
5233 r.y = y;
5234 r.width = w;
5235 r.height = h;
5236 }
5237
5238 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5239 expose_window_tree (XWINDOW (f->root_window), &r);
5240
9ea173e8 5241 if (WINDOWP (f->tool_bar_window))
06a2c219 5242 {
9ea173e8 5243 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5244 XRectangle window_rect;
5245 XRectangle intersection_rect;
5246 int window_x, window_y, window_width, window_height;
5247
5248
5249 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5250 window_rect.x = window_x;
5251 window_rect.y = window_y;
5252 window_rect.width = window_width;
5253 window_rect.height = window_height;
5254
5255 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5256 expose_window (w, &intersection_rect);
5257 }
5258
5259#ifndef USE_X_TOOLKIT
5260 if (WINDOWP (f->menu_bar_window))
5261 {
5262 struct window *w = XWINDOW (f->menu_bar_window);
5263 XRectangle window_rect;
5264 XRectangle intersection_rect;
5265 int window_x, window_y, window_width, window_height;
5266
5267
5268 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5269 window_rect.x = window_x;
5270 window_rect.y = window_y;
5271 window_rect.width = window_width;
5272 window_rect.height = window_height;
5273
5274 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5275 expose_window (w, &intersection_rect);
dc6f92b8 5276 }
06a2c219 5277#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5278}
5279
06a2c219
GM
5280
5281/* Redraw (parts) of all windows in the window tree rooted at W that
5282 intersect R. R contains frame pixel coordinates. */
5283
58769bee 5284static void
06a2c219
GM
5285expose_window_tree (w, r)
5286 struct window *w;
5287 XRectangle *r;
dc6f92b8 5288{
06a2c219
GM
5289 while (w)
5290 {
5291 if (!NILP (w->hchild))
5292 expose_window_tree (XWINDOW (w->hchild), r);
5293 else if (!NILP (w->vchild))
5294 expose_window_tree (XWINDOW (w->vchild), r);
5295 else
5296 {
5297 XRectangle window_rect;
5298 XRectangle intersection_rect;
5299 struct frame *f = XFRAME (w->frame);
5300 int window_x, window_y, window_width, window_height;
5301
5302 /* Frame-relative pixel rectangle of W. */
5303 window_box (w, -1, &window_x, &window_y, &window_width,
5304 &window_height);
5305 window_rect.x
5306 = (window_x
110859fc 5307 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5308 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5309 window_rect.y = window_y;
5310 window_rect.width
5311 = (window_width
110859fc 5312 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5313 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5314 window_rect.height
5315 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5316
5317 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5318 expose_window (w, &intersection_rect);
5319 }
58769bee 5320
06a2c219
GM
5321 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5322 }
5323}
58769bee 5324
dc6f92b8 5325
06a2c219
GM
5326/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5327 which intersects rectangle R. R is in window-relative coordinates. */
5328
5329static void
5330expose_area (w, row, r, area)
5331 struct window *w;
5332 struct glyph_row *row;
5333 XRectangle *r;
5334 enum glyph_row_area area;
5335{
5336 int x;
5337 struct glyph *first = row->glyphs[area];
5338 struct glyph *end = row->glyphs[area] + row->used[area];
5339 struct glyph *last;
5340 int first_x;
5341
5342 /* Set x to the window-relative start position for drawing glyphs of
5343 AREA. The first glyph of the text area can be partially visible.
5344 The first glyphs of other areas cannot. */
5345 if (area == LEFT_MARGIN_AREA)
5346 x = 0;
5347 else if (area == TEXT_AREA)
5348 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5349 else
5350 x = (window_box_width (w, LEFT_MARGIN_AREA)
5351 + window_box_width (w, TEXT_AREA));
5352
6fb13182
GM
5353 if (area == TEXT_AREA && row->fill_line_p)
5354 /* If row extends face to end of line write the whole line. */
5355 x_draw_glyphs (w, x, row, area,
5356 0, row->used[area],
06a2c219 5357 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5358 NULL, NULL, 0);
6fb13182
GM
5359 else
5360 {
5361 /* Find the first glyph that must be redrawn. */
5362 while (first < end
5363 && x + first->pixel_width < r->x)
5364 {
5365 x += first->pixel_width;
5366 ++first;
5367 }
5368
5369 /* Find the last one. */
5370 last = first;
5371 first_x = x;
5372 while (last < end
5373 && x < r->x + r->width)
5374 {
5375 x += last->pixel_width;
5376 ++last;
5377 }
5378
5379 /* Repaint. */
5380 if (last > first)
5381 x_draw_glyphs (w, first_x, row, area,
5382 first - row->glyphs[area],
5383 last - row->glyphs[area],
5384 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5385 NULL, NULL, 0);
5386 }
06a2c219
GM
5387}
5388
58769bee 5389
06a2c219
GM
5390/* Redraw the parts of the glyph row ROW on window W intersecting
5391 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5392
06a2c219
GM
5393static void
5394expose_line (w, row, r)
5395 struct window *w;
5396 struct glyph_row *row;
5397 XRectangle *r;
5398{
5399 xassert (row->enabled_p);
5400
5401 if (row->mode_line_p || w->pseudo_window_p)
5402 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5403 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5404 NULL, NULL, 0);
06a2c219
GM
5405 else
5406 {
5407 if (row->used[LEFT_MARGIN_AREA])
5408 expose_area (w, row, r, LEFT_MARGIN_AREA);
5409 if (row->used[TEXT_AREA])
5410 expose_area (w, row, r, TEXT_AREA);
5411 if (row->used[RIGHT_MARGIN_AREA])
5412 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5413 x_draw_row_bitmaps (w, row);
5414 }
5415}
dc6f92b8 5416
58769bee 5417
06a2c219
GM
5418/* Return non-zero if W's cursor intersects rectangle R. */
5419
5420static int
5421x_phys_cursor_in_rect_p (w, r)
5422 struct window *w;
5423 XRectangle *r;
5424{
5425 XRectangle cr, result;
5426 struct glyph *cursor_glyph;
5427
5428 cursor_glyph = get_phys_cursor_glyph (w);
5429 if (cursor_glyph)
5430 {
5431 cr.x = w->phys_cursor.x;
5432 cr.y = w->phys_cursor.y;
5433 cr.width = cursor_glyph->pixel_width;
5434 cr.height = w->phys_cursor_height;
5435 return x_intersect_rectangles (&cr, r, &result);
5436 }
5437 else
5438 return 0;
dc6f92b8 5439}
dc6f92b8 5440
06a2c219
GM
5441
5442/* Redraw a rectangle of window W. R is a rectangle in window
5443 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5444
5445static void
06a2c219
GM
5446expose_window (w, r)
5447 struct window *w;
5448 XRectangle *r;
dc6f92b8 5449{
06a2c219
GM
5450 struct glyph_row *row;
5451 int y;
5452 int yb = window_text_bottom_y (w);
5453 int cursor_cleared_p;
dc6f92b8 5454
80c32bcc
GM
5455 /* If window is not yet fully initialized, do nothing. This can
5456 happen when toolkit scroll bars are used and a window is split.
5457 Reconfiguring the scroll bar will generate an expose for a newly
5458 created window. */
5459 if (w->current_matrix == NULL)
5460 return;
5461
06a2c219
GM
5462 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5463 r->x, r->y, r->width, r->height));
dc6f92b8 5464
06a2c219
GM
5465 /* Convert to window coordinates. */
5466 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5467 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5468
06a2c219
GM
5469 /* Turn off the cursor. */
5470 if (!w->pseudo_window_p
5471 && x_phys_cursor_in_rect_p (w, r))
5472 {
5473 x_clear_cursor (w);
5474 cursor_cleared_p = 1;
5475 }
5476 else
5477 cursor_cleared_p = 0;
5478
5479 /* Find the first row intersecting the rectangle R. */
5480 row = w->current_matrix->rows;
5481 y = 0;
5482 while (row->enabled_p
5483 && y < yb
5484 && y + row->height < r->y)
5485 {
5486 y += row->height;
5487 ++row;
5488 }
5489
dc6f92b8 5490 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5491 while (row->enabled_p
5492 && y < yb
5493 && y < r->y + r->height)
5494 {
5495 expose_line (w, row, r);
5496 y += row->height;
5497 ++row;
5498 }
5499
5500 /* Display the mode line if there is one. */
5501 if (WINDOW_WANTS_MODELINE_P (w)
5502 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5503 row->enabled_p)
5504 && row->y < r->y + r->height)
5505 expose_line (w, row, r);
dc6f92b8 5506
06a2c219 5507 if (!w->pseudo_window_p)
dc6f92b8 5508 {
06a2c219
GM
5509 /* Draw border between windows. */
5510 x_draw_vertical_border (w);
5511
5512 /* Turn the cursor on again. */
5513 if (cursor_cleared_p)
5514 x_update_window_cursor (w, 1);
5515 }
5516}
dc6f92b8 5517
dc6f92b8 5518
06a2c219
GM
5519/* Determine the intersection of two rectangles R1 and R2. Return
5520 the intersection in *RESULT. Value is non-zero if RESULT is not
5521 empty. */
5522
5523static int
5524x_intersect_rectangles (r1, r2, result)
5525 XRectangle *r1, *r2, *result;
5526{
5527 XRectangle *left, *right;
5528 XRectangle *upper, *lower;
5529 int intersection_p = 0;
5530
5531 /* Rearrange so that R1 is the left-most rectangle. */
5532 if (r1->x < r2->x)
5533 left = r1, right = r2;
5534 else
5535 left = r2, right = r1;
5536
5537 /* X0 of the intersection is right.x0, if this is inside R1,
5538 otherwise there is no intersection. */
5539 if (right->x <= left->x + left->width)
5540 {
5541 result->x = right->x;
5542
5543 /* The right end of the intersection is the minimum of the
5544 the right ends of left and right. */
5545 result->width = (min (left->x + left->width, right->x + right->width)
5546 - result->x);
5547
5548 /* Same game for Y. */
5549 if (r1->y < r2->y)
5550 upper = r1, lower = r2;
5551 else
5552 upper = r2, lower = r1;
5553
5554 /* The upper end of the intersection is lower.y0, if this is inside
5555 of upper. Otherwise, there is no intersection. */
5556 if (lower->y <= upper->y + upper->height)
dc43ef94 5557 {
06a2c219
GM
5558 result->y = lower->y;
5559
5560 /* The lower end of the intersection is the minimum of the lower
5561 ends of upper and lower. */
5562 result->height = (min (lower->y + lower->height,
5563 upper->y + upper->height)
5564 - result->y);
5565 intersection_p = 1;
dc43ef94 5566 }
dc6f92b8
JB
5567 }
5568
06a2c219 5569 return intersection_p;
dc6f92b8 5570}
06a2c219
GM
5571
5572
5573
5574
dc6f92b8 5575\f
dc6f92b8 5576static void
334208b7
RS
5577frame_highlight (f)
5578 struct frame *f;
dc6f92b8 5579{
b3e1e05c
JB
5580 /* We used to only do this if Vx_no_window_manager was non-nil, but
5581 the ICCCM (section 4.1.6) says that the window's border pixmap
5582 and border pixel are window attributes which are "private to the
5583 client", so we can always change it to whatever we want. */
5584 BLOCK_INPUT;
334208b7 5585 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5586 f->output_data.x->border_pixel);
b3e1e05c 5587 UNBLOCK_INPUT;
5d46f928 5588 x_update_cursor (f, 1);
dc6f92b8
JB
5589}
5590
5591static void
334208b7
RS
5592frame_unhighlight (f)
5593 struct frame *f;
dc6f92b8 5594{
b3e1e05c
JB
5595 /* We used to only do this if Vx_no_window_manager was non-nil, but
5596 the ICCCM (section 4.1.6) says that the window's border pixmap
5597 and border pixel are window attributes which are "private to the
5598 client", so we can always change it to whatever we want. */
5599 BLOCK_INPUT;
334208b7 5600 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5601 f->output_data.x->border_tile);
b3e1e05c 5602 UNBLOCK_INPUT;
5d46f928 5603 x_update_cursor (f, 1);
dc6f92b8 5604}
dc6f92b8 5605
f676886a
JB
5606/* The focus has changed. Update the frames as necessary to reflect
5607 the new situation. Note that we can't change the selected frame
c5acd733 5608 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5609 Each event gets marked with the frame in which it occurred, so the
c5acd733 5610 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5611
6d4238f3 5612static void
0f941935
KH
5613x_new_focus_frame (dpyinfo, frame)
5614 struct x_display_info *dpyinfo;
f676886a 5615 struct frame *frame;
dc6f92b8 5616{
0f941935 5617 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5618
0f941935 5619 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5620 {
58769bee 5621 /* Set this before calling other routines, so that they see
f676886a 5622 the correct value of x_focus_frame. */
0f941935 5623 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5624
5625 if (old_focus && old_focus->auto_lower)
f676886a 5626 x_lower_frame (old_focus);
dc6f92b8
JB
5627
5628#if 0
f676886a 5629 selected_frame = frame;
e0c1aef2
KH
5630 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5631 selected_frame);
f676886a
JB
5632 Fselect_window (selected_frame->selected_window);
5633 choose_minibuf_frame ();
c118dd06 5634#endif /* ! 0 */
dc6f92b8 5635
0f941935
KH
5636 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5637 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5638 else
5639 pending_autoraise_frame = 0;
6d4238f3 5640 }
dc6f92b8 5641
0f941935 5642 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5643}
5644
37c2c98b
RS
5645/* Handle an event saying the mouse has moved out of an Emacs frame. */
5646
5647void
0f941935
KH
5648x_mouse_leave (dpyinfo)
5649 struct x_display_info *dpyinfo;
37c2c98b 5650{
0f941935 5651 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5652}
6d4238f3 5653
f451eb13
JB
5654/* The focus has changed, or we have redirected a frame's focus to
5655 another frame (this happens when a frame uses a surrogate
06a2c219 5656 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5657
5658 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5659 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5660 the appropriate X display info. */
06a2c219 5661
6d4238f3 5662static void
0f941935
KH
5663XTframe_rehighlight (frame)
5664 struct frame *frame;
6d4238f3 5665{
0f941935
KH
5666 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5667}
6d4238f3 5668
0f941935
KH
5669static void
5670x_frame_rehighlight (dpyinfo)
5671 struct x_display_info *dpyinfo;
5672{
5673 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5674
5675 if (dpyinfo->x_focus_frame)
6d4238f3 5676 {
0f941935
KH
5677 dpyinfo->x_highlight_frame
5678 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5679 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5680 : dpyinfo->x_focus_frame);
5681 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5682 {
0f941935
KH
5683 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5684 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5685 }
dc6f92b8 5686 }
6d4238f3 5687 else
0f941935 5688 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5689
0f941935 5690 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5691 {
5692 if (old_highlight)
f676886a 5693 frame_unhighlight (old_highlight);
0f941935
KH
5694 if (dpyinfo->x_highlight_frame)
5695 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5696 }
dc6f92b8 5697}
06a2c219
GM
5698
5699
dc6f92b8 5700\f
06a2c219 5701/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5702
28430d3c
JB
5703/* Initialize mode_switch_bit and modifier_meaning. */
5704static void
334208b7
RS
5705x_find_modifier_meanings (dpyinfo)
5706 struct x_display_info *dpyinfo;
28430d3c 5707{
f689eb05 5708 int min_code, max_code;
28430d3c
JB
5709 KeySym *syms;
5710 int syms_per_code;
5711 XModifierKeymap *mods;
5712
334208b7
RS
5713 dpyinfo->meta_mod_mask = 0;
5714 dpyinfo->shift_lock_mask = 0;
5715 dpyinfo->alt_mod_mask = 0;
5716 dpyinfo->super_mod_mask = 0;
5717 dpyinfo->hyper_mod_mask = 0;
58769bee 5718
9658a521 5719#ifdef HAVE_X11R4
334208b7 5720 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5721#else
4a60f8c5
RS
5722 min_code = dpyinfo->display->min_keycode;
5723 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5724#endif
5725
334208b7 5726 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5727 min_code, max_code - min_code + 1,
5728 &syms_per_code);
334208b7 5729 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5730
58769bee 5731 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5732 Alt keysyms are on. */
28430d3c 5733 {
06a2c219 5734 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5735
5736 for (row = 3; row < 8; row++)
5737 for (col = 0; col < mods->max_keypermod; col++)
5738 {
0299d313
RS
5739 KeyCode code
5740 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5741
af92970c
KH
5742 /* Zeroes are used for filler. Skip them. */
5743 if (code == 0)
5744 continue;
5745
28430d3c
JB
5746 /* Are any of this keycode's keysyms a meta key? */
5747 {
5748 int code_col;
5749
5750 for (code_col = 0; code_col < syms_per_code; code_col++)
5751 {
f689eb05 5752 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5753
f689eb05 5754 switch (sym)
28430d3c 5755 {
f689eb05
JB
5756 case XK_Meta_L:
5757 case XK_Meta_R:
334208b7 5758 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5759 break;
f689eb05
JB
5760
5761 case XK_Alt_L:
5762 case XK_Alt_R:
334208b7 5763 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5764 break;
5765
5766 case XK_Hyper_L:
5767 case XK_Hyper_R:
334208b7 5768 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5769 break;
5770
5771 case XK_Super_L:
5772 case XK_Super_R:
334208b7 5773 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5774 break;
11edeb03
JB
5775
5776 case XK_Shift_Lock:
5777 /* Ignore this if it's not on the lock modifier. */
5778 if ((1 << row) == LockMask)
334208b7 5779 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5780 break;
28430d3c
JB
5781 }
5782 }
5783 }
5784 }
5785 }
5786
f689eb05 5787 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 5788 if (! dpyinfo->meta_mod_mask)
a3c44b14 5789 {
334208b7
RS
5790 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5791 dpyinfo->alt_mod_mask = 0;
a3c44b14 5792 }
f689eb05 5793
148c4b70
RS
5794 /* If some keys are both alt and meta,
5795 make them just meta, not alt. */
334208b7 5796 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 5797 {
334208b7 5798 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 5799 }
58769bee 5800
28430d3c 5801 XFree ((char *) syms);
f689eb05 5802 XFreeModifiermap (mods);
28430d3c
JB
5803}
5804
dfeccd2d
JB
5805/* Convert between the modifier bits X uses and the modifier bits
5806 Emacs uses. */
06a2c219 5807
7c5283e4 5808static unsigned int
334208b7
RS
5809x_x_to_emacs_modifiers (dpyinfo, state)
5810 struct x_display_info *dpyinfo;
dc6f92b8
JB
5811 unsigned int state;
5812{
334208b7
RS
5813 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5814 | ((state & ControlMask) ? ctrl_modifier : 0)
5815 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5816 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5817 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5818 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
5819}
5820
dfeccd2d 5821static unsigned int
334208b7
RS
5822x_emacs_to_x_modifiers (dpyinfo, state)
5823 struct x_display_info *dpyinfo;
dfeccd2d
JB
5824 unsigned int state;
5825{
334208b7
RS
5826 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5827 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5828 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5829 | ((state & shift_modifier) ? ShiftMask : 0)
5830 | ((state & ctrl_modifier) ? ControlMask : 0)
5831 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 5832}
d047c4eb
KH
5833
5834/* Convert a keysym to its name. */
5835
5836char *
5837x_get_keysym_name (keysym)
5838 KeySym keysym;
5839{
5840 char *value;
5841
5842 BLOCK_INPUT;
5843 value = XKeysymToString (keysym);
5844 UNBLOCK_INPUT;
5845
5846 return value;
5847}
06a2c219
GM
5848
5849
e4571a43
JB
5850\f
5851/* Mouse clicks and mouse movement. Rah. */
e4571a43 5852
06a2c219
GM
5853/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5854 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5855 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5856 not force the value into range. */
69388238 5857
c8dba240 5858void
69388238 5859pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 5860 FRAME_PTR f;
69388238 5861 register int pix_x, pix_y;
e4571a43
JB
5862 register int *x, *y;
5863 XRectangle *bounds;
69388238 5864 int noclip;
e4571a43 5865{
06a2c219 5866 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
5867 even for negative values. */
5868 if (pix_x < 0)
7556890b 5869 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 5870 if (pix_y < 0)
7556890b 5871 pix_y -= (f)->output_data.x->line_height - 1;
69388238 5872
e4571a43
JB
5873 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5874 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5875
5876 if (bounds)
5877 {
7556890b
RS
5878 bounds->width = FONT_WIDTH (f->output_data.x->font);
5879 bounds->height = f->output_data.x->line_height;
e4571a43
JB
5880 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5881 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5882 }
5883
69388238
RS
5884 if (!noclip)
5885 {
5886 if (pix_x < 0)
5887 pix_x = 0;
3cbd2e0b
RS
5888 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5889 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
5890
5891 if (pix_y < 0)
5892 pix_y = 0;
5893 else if (pix_y > f->height)
5894 pix_y = f->height;
5895 }
e4571a43
JB
5896
5897 *x = pix_x;
5898 *y = pix_y;
5899}
5900
06a2c219
GM
5901
5902/* Given HPOS/VPOS in the current matrix of W, return corresponding
5903 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5904 can't tell the positions because W's display is not up to date,
5905 return 0. */
5906
5907int
5908glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5909 struct window *w;
5910 int hpos, vpos;
5911 int *frame_x, *frame_y;
2b5c9e71 5912{
06a2c219
GM
5913 int success_p;
5914
5915 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5916 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5917
5918 if (display_completed)
5919 {
5920 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5921 struct glyph *glyph = row->glyphs[TEXT_AREA];
5922 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5923
5924 *frame_y = row->y;
5925 *frame_x = row->x;
5926 while (glyph < end)
5927 {
5928 *frame_x += glyph->pixel_width;
5929 ++glyph;
5930 }
5931
5932 success_p = 1;
5933 }
5934 else
5935 {
5936 *frame_y = *frame_x = 0;
5937 success_p = 0;
5938 }
5939
5940 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5941 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5942 return success_p;
2b5c9e71
RS
5943}
5944
06a2c219 5945
dc6f92b8
JB
5946/* Prepare a mouse-event in *RESULT for placement in the input queue.
5947
5948 If the event is a button press, then note that we have grabbed
f451eb13 5949 the mouse. */
dc6f92b8
JB
5950
5951static Lisp_Object
f451eb13 5952construct_mouse_click (result, event, f)
dc6f92b8
JB
5953 struct input_event *result;
5954 XButtonEvent *event;
f676886a 5955 struct frame *f;
dc6f92b8 5956{
f451eb13 5957 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 5958 otherwise. */
f451eb13 5959 result->kind = mouse_click;
69388238 5960 result->code = event->button - Button1;
1113d9db 5961 result->timestamp = event->time;
334208b7
RS
5962 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5963 event->state)
f689eb05 5964 | (event->type == ButtonRelease
58769bee 5965 ? up_modifier
f689eb05 5966 : down_modifier));
dc6f92b8 5967
06a2c219
GM
5968 XSETINT (result->x, event->x);
5969 XSETINT (result->y, event->y);
5970 XSETFRAME (result->frame_or_window, f);
5971 return Qnil;
dc6f92b8 5972}
b849c413 5973
06a2c219
GM
5974#if 0 /* This function isn't called. --gerd */
5975
b849c413
RS
5976/* Prepare a menu-event in *RESULT for placement in the input queue. */
5977
5978static Lisp_Object
5979construct_menu_click (result, event, f)
5980 struct input_event *result;
5981 XButtonEvent *event;
5982 struct frame *f;
5983{
5984 /* Make the event type no_event; we'll change that when we decide
5985 otherwise. */
5986 result->kind = mouse_click;
26459b28 5987 result->code = event->button - Button1;
b849c413 5988 result->timestamp = event->time;
334208b7
RS
5989 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5990 event->state)
b849c413 5991 | (event->type == ButtonRelease
58769bee 5992 ? up_modifier
b849c413
RS
5993 : down_modifier));
5994
e0c1aef2
KH
5995 XSETINT (result->x, event->x);
5996 XSETINT (result->y, -1);
5997 XSETFRAME (result->frame_or_window, f);
b849c413 5998}
06a2c219
GM
5999
6000#endif /* 0 */
6001
69388238 6002\f
90e65f07
JB
6003/* Function to report a mouse movement to the mainstream Emacs code.
6004 The input handler calls this.
6005
6006 We have received a mouse movement event, which is given in *event.
6007 If the mouse is over a different glyph than it was last time, tell
6008 the mainstream emacs code by setting mouse_moved. If not, ask for
6009 another motion event, so we can check again the next time it moves. */
b8009dd1 6010
06a2c219
GM
6011static XMotionEvent last_mouse_motion_event;
6012static Lisp_Object last_mouse_motion_frame;
6013
90e65f07 6014static void
12ba150f 6015note_mouse_movement (frame, event)
f676886a 6016 FRAME_PTR frame;
90e65f07 6017 XMotionEvent *event;
90e65f07 6018{
e5d77022 6019 last_mouse_movement_time = event->time;
06a2c219
GM
6020 last_mouse_motion_event = *event;
6021 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6022
27f338af
RS
6023 if (event->window != FRAME_X_WINDOW (frame))
6024 {
39d8bb4d 6025 frame->mouse_moved = 1;
27f338af 6026 last_mouse_scroll_bar = Qnil;
27f338af 6027 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6028 }
6029
90e65f07 6030 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6031 else if (event->x < last_mouse_glyph.x
6032 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6033 || event->y < last_mouse_glyph.y
6034 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6035 {
39d8bb4d 6036 frame->mouse_moved = 1;
ab648270 6037 last_mouse_scroll_bar = Qnil;
b8009dd1 6038 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6039 }
6040}
6041
bf1c0ba1 6042/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6043
06a2c219
GM
6044 int disable_mouse_highlight;
6045
6046
6047\f
6048/************************************************************************
6049 Mouse Face
6050 ************************************************************************/
6051
6052/* Find the glyph under window-relative coordinates X/Y in window W.
6053 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6054 strings. Return in *HPOS and *VPOS the row and column number of
6055 the glyph found. Return in *AREA the glyph area containing X.
6056 Value is a pointer to the glyph found or null if X/Y is not on
6057 text, or we can't tell because W's current matrix is not up to
6058 date. */
6059
6060static struct glyph *
6061x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6062 struct window *w;
6063 int x, y;
6064 int *hpos, *vpos, *area;
6065{
6066 struct glyph *glyph, *end;
6067 struct glyph_row *row;
6068 int x0, i, left_area_width;
6069
6070 /* Find row containing Y. Give up if some row is not enabled. */
6071 for (i = 0; i < w->current_matrix->nrows; ++i)
6072 {
6073 row = MATRIX_ROW (w->current_matrix, i);
6074 if (!row->enabled_p)
6075 return NULL;
6076 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6077 break;
6078 }
6079
6080 *vpos = i;
6081 *hpos = 0;
6082
6083 /* Give up if Y is not in the window. */
6084 if (i == w->current_matrix->nrows)
6085 return NULL;
6086
6087 /* Get the glyph area containing X. */
6088 if (w->pseudo_window_p)
6089 {
6090 *area = TEXT_AREA;
6091 x0 = 0;
6092 }
6093 else
6094 {
6095 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6096 if (x < left_area_width)
6097 {
6098 *area = LEFT_MARGIN_AREA;
6099 x0 = 0;
6100 }
6101 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6102 {
6103 *area = TEXT_AREA;
6104 x0 = row->x + left_area_width;
6105 }
6106 else
6107 {
6108 *area = RIGHT_MARGIN_AREA;
6109 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6110 }
6111 }
6112
6113 /* Find glyph containing X. */
6114 glyph = row->glyphs[*area];
6115 end = glyph + row->used[*area];
6116 while (glyph < end)
6117 {
6118 if (x < x0 + glyph->pixel_width)
6119 {
6120 if (w->pseudo_window_p)
6121 break;
6122 else if (BUFFERP (glyph->object))
6123 break;
6124 }
6125
6126 x0 += glyph->pixel_width;
6127 ++glyph;
6128 }
6129
6130 if (glyph == end)
6131 return NULL;
6132
6133 *hpos = glyph - row->glyphs[*area];
6134 return glyph;
6135}
6136
6137
6138/* Convert frame-relative x/y to coordinates relative to window W.
6139 Takes pseudo-windows into account. */
6140
6141static void
6142frame_to_window_pixel_xy (w, x, y)
6143 struct window *w;
6144 int *x, *y;
6145{
6146 if (w->pseudo_window_p)
6147 {
6148 /* A pseudo-window is always full-width, and starts at the
6149 left edge of the frame, plus a frame border. */
6150 struct frame *f = XFRAME (w->frame);
6151 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6152 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6153 }
6154 else
6155 {
6156 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6157 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6158 }
6159}
6160
6161
6162/* Take proper action when mouse has moved to the mode or top line of
6163 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6164 mode line. X is relative to the start of the text display area of
6165 W, so the width of bitmap areas and scroll bars must be subtracted
6166 to get a position relative to the start of the mode line. */
6167
6168static void
6169note_mode_line_highlight (w, x, mode_line_p)
6170 struct window *w;
6171 int x, mode_line_p;
6172{
6173 struct frame *f = XFRAME (w->frame);
6174 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6175 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6176 struct glyph_row *row;
6177
6178 if (mode_line_p)
6179 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6180 else
045dee35 6181 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6182
6183 if (row->enabled_p)
6184 {
6185 struct glyph *glyph, *end;
6186 Lisp_Object help, map;
6187 int x0;
6188
6189 /* Find the glyph under X. */
6190 glyph = row->glyphs[TEXT_AREA];
6191 end = glyph + row->used[TEXT_AREA];
6192 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6193 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6194 while (glyph < end
6195 && x >= x0 + glyph->pixel_width)
6196 {
6197 x0 += glyph->pixel_width;
6198 ++glyph;
6199 }
6200
6201 if (glyph < end
6202 && STRINGP (glyph->object)
6203 && XSTRING (glyph->object)->intervals
6204 && glyph->charpos >= 0
6205 && glyph->charpos < XSTRING (glyph->object)->size)
6206 {
6207 /* If we're on a string with `help-echo' text property,
6208 arrange for the help to be displayed. This is done by
6209 setting the global variable help_echo to the help string. */
6210 help = Fget_text_property (make_number (glyph->charpos),
6211 Qhelp_echo, glyph->object);
6212 if (STRINGP (help))
6213 help_echo = help;
6214
6215 /* Change the mouse pointer according to what is under X/Y. */
6216 map = Fget_text_property (make_number (glyph->charpos),
6217 Qlocal_map, glyph->object);
6218 if (!NILP (Fkeymapp (map)))
6219 cursor = f->output_data.x->nontext_cursor;
6220 }
6221 }
6222
6223 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6224}
6225
6226
6227/* Take proper action when the mouse has moved to position X, Y on
6228 frame F as regards highlighting characters that have mouse-face
6229 properties. Also de-highlighting chars where the mouse was before.
27f338af 6230 X and Y can be negative or out of range. */
b8009dd1
RS
6231
6232static void
6233note_mouse_highlight (f, x, y)
06a2c219 6234 struct frame *f;
c32cdd9a 6235 int x, y;
b8009dd1 6236{
06a2c219
GM
6237 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6238 int portion;
b8009dd1
RS
6239 Lisp_Object window;
6240 struct window *w;
6241
06a2c219
GM
6242 /* When a menu is active, don't highlight because this looks odd. */
6243#ifdef USE_X_TOOLKIT
6244 if (popup_activated ())
6245 return;
6246#endif
6247
04fff9c0
GM
6248 if (disable_mouse_highlight
6249 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6250 return;
6251
06a2c219
GM
6252 dpyinfo->mouse_face_mouse_x = x;
6253 dpyinfo->mouse_face_mouse_y = y;
6254 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6255
06a2c219 6256 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6257 return;
6258
514e4681
RS
6259 if (gc_in_progress)
6260 {
06a2c219 6261 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6262 return;
6263 }
6264
b8009dd1 6265 /* Which window is that in? */
06a2c219 6266 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6267
6268 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6269 if (! EQ (window, dpyinfo->mouse_face_window))
6270 clear_mouse_face (dpyinfo);
6271
6272 /* Not on a window -> return. */
6273 if (!WINDOWP (window))
6274 return;
6275
6276 /* Convert to window-relative pixel coordinates. */
6277 w = XWINDOW (window);
6278 frame_to_window_pixel_xy (w, &x, &y);
6279
9ea173e8 6280 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6281 buffer. */
9ea173e8 6282 if (EQ (window, f->tool_bar_window))
06a2c219 6283 {
9ea173e8 6284 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6285 return;
6286 }
6287
6288 if (portion == 1 || portion == 3)
6289 {
6290 /* Mouse is on the mode or top line. */
6291 note_mode_line_highlight (w, x, portion == 1);
6292 return;
6293 }
6294 else
6295 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6296 f->output_data.x->text_cursor);
b8009dd1 6297
0cdd0c9f
RS
6298 /* Are we in a window whose display is up to date?
6299 And verify the buffer's text has not changed. */
06a2c219
GM
6300 if (/* Within text portion of the window. */
6301 portion == 0
0cdd0c9f 6302 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6303 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6304 && (XFASTINT (w->last_overlay_modified)
6305 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6306 {
06a2c219
GM
6307 int hpos, vpos, pos, i, area;
6308 struct glyph *glyph;
b8009dd1 6309
06a2c219
GM
6310 /* Find the glyph under X/Y. */
6311 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6312
6313 /* Clear mouse face if X/Y not over text. */
6314 if (glyph == NULL
6315 || area != TEXT_AREA
6316 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6317 {
06a2c219
GM
6318 clear_mouse_face (dpyinfo);
6319 return;
6320 }
6321
6322 pos = glyph->charpos;
6323 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6324
6325 /* Check for mouse-face and help-echo. */
6326 {
6327 Lisp_Object mouse_face, overlay, position;
6328 Lisp_Object *overlay_vec;
6329 int len, noverlays;
6330 struct buffer *obuf;
6331 int obegv, ozv;
6332
6333 /* If we get an out-of-range value, return now; avoid an error. */
6334 if (pos > BUF_Z (XBUFFER (w->buffer)))
6335 return;
6336
6337 /* Make the window's buffer temporarily current for
6338 overlays_at and compute_char_face. */
6339 obuf = current_buffer;
6340 current_buffer = XBUFFER (w->buffer);
6341 obegv = BEGV;
6342 ozv = ZV;
6343 BEGV = BEG;
6344 ZV = Z;
6345
6346 /* Is this char mouse-active or does it have help-echo? */
6347 XSETINT (position, pos);
6348
6349 /* Put all the overlays we want in a vector in overlay_vec.
6350 Store the length in len. If there are more than 10, make
6351 enough space for all, and try again. */
6352 len = 10;
6353 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6354 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6355 if (noverlays > len)
6356 {
6357 len = noverlays;
6358 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6359 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6360 }
6361
6362 noverlays = sort_overlays (overlay_vec, noverlays, w);
6363
6364 /* Check mouse-face highlighting. */
6365 if (! (EQ (window, dpyinfo->mouse_face_window)
6366 && vpos >= dpyinfo->mouse_face_beg_row
6367 && vpos <= dpyinfo->mouse_face_end_row
6368 && (vpos > dpyinfo->mouse_face_beg_row
6369 || hpos >= dpyinfo->mouse_face_beg_col)
6370 && (vpos < dpyinfo->mouse_face_end_row
6371 || hpos < dpyinfo->mouse_face_end_col
6372 || dpyinfo->mouse_face_past_end)))
6373 {
6374 /* Clear the display of the old active region, if any. */
6375 clear_mouse_face (dpyinfo);
6376
6377 /* Find the highest priority overlay that has a mouse-face prop. */
6378 overlay = Qnil;
6379 for (i = 0; i < noverlays; i++)
6380 {
6381 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6382 if (!NILP (mouse_face))
6383 {
6384 overlay = overlay_vec[i];
6385 break;
6386 }
6387 }
6388
6389 /* If no overlay applies, get a text property. */
6390 if (NILP (overlay))
6391 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6392
6393 /* Handle the overlay case. */
6394 if (! NILP (overlay))
6395 {
6396 /* Find the range of text around this char that
6397 should be active. */
6398 Lisp_Object before, after;
6399 int ignore;
6400
6401 before = Foverlay_start (overlay);
6402 after = Foverlay_end (overlay);
6403 /* Record this as the current active region. */
6404 fast_find_position (w, XFASTINT (before),
6405 &dpyinfo->mouse_face_beg_col,
6406 &dpyinfo->mouse_face_beg_row,
6407 &dpyinfo->mouse_face_beg_x,
6408 &dpyinfo->mouse_face_beg_y);
6409 dpyinfo->mouse_face_past_end
6410 = !fast_find_position (w, XFASTINT (after),
6411 &dpyinfo->mouse_face_end_col,
6412 &dpyinfo->mouse_face_end_row,
6413 &dpyinfo->mouse_face_end_x,
6414 &dpyinfo->mouse_face_end_y);
6415 dpyinfo->mouse_face_window = window;
6416 dpyinfo->mouse_face_face_id
6417 = face_at_buffer_position (w, pos, 0, 0,
6418 &ignore, pos + 1, 1);
6419
6420 /* Display it as active. */
6421 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6422 }
6423 /* Handle the text property case. */
6424 else if (! NILP (mouse_face))
6425 {
6426 /* Find the range of text around this char that
6427 should be active. */
6428 Lisp_Object before, after, beginning, end;
6429 int ignore;
6430
6431 beginning = Fmarker_position (w->start);
6432 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6433 - XFASTINT (w->window_end_pos)));
6434 before
6435 = Fprevious_single_property_change (make_number (pos + 1),
6436 Qmouse_face,
6437 w->buffer, beginning);
6438 after
6439 = Fnext_single_property_change (position, Qmouse_face,
6440 w->buffer, end);
6441 /* Record this as the current active region. */
6442 fast_find_position (w, XFASTINT (before),
6443 &dpyinfo->mouse_face_beg_col,
6444 &dpyinfo->mouse_face_beg_row,
6445 &dpyinfo->mouse_face_beg_x,
6446 &dpyinfo->mouse_face_beg_y);
6447 dpyinfo->mouse_face_past_end
6448 = !fast_find_position (w, XFASTINT (after),
6449 &dpyinfo->mouse_face_end_col,
6450 &dpyinfo->mouse_face_end_row,
6451 &dpyinfo->mouse_face_end_x,
6452 &dpyinfo->mouse_face_end_y);
6453 dpyinfo->mouse_face_window = window;
6454 dpyinfo->mouse_face_face_id
6455 = face_at_buffer_position (w, pos, 0, 0,
6456 &ignore, pos + 1, 1);
6457
6458 /* Display it as active. */
6459 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6460 }
6461 }
6462
6463 /* Look for a `help-echo' property. */
6464 {
6465 Lisp_Object help;
6466
6467 /* Check overlays first. */
6468 help = Qnil;
6469 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6470 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6471
6472 /* Try text properties. */
6473 if (!STRINGP (help)
6474 && ((STRINGP (glyph->object)
6475 && glyph->charpos >= 0
6476 && glyph->charpos < XSTRING (glyph->object)->size)
6477 || (BUFFERP (glyph->object)
6478 && glyph->charpos >= BEGV
6479 && glyph->charpos < ZV)))
6480 help = Fget_text_property (make_number (glyph->charpos),
6481 Qhelp_echo, glyph->object);
6482
6483 if (STRINGP (help))
6484 help_echo = help;
6485 }
6486
6487 BEGV = obegv;
6488 ZV = ozv;
6489 current_buffer = obuf;
6490 }
6491 }
6492}
6493
6494static void
6495redo_mouse_highlight ()
6496{
6497 if (!NILP (last_mouse_motion_frame)
6498 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6499 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6500 last_mouse_motion_event.x,
6501 last_mouse_motion_event.y);
6502}
6503
6504
6505\f
6506/***********************************************************************
9ea173e8 6507 Tool-bars
06a2c219
GM
6508 ***********************************************************************/
6509
9ea173e8
GM
6510static int x_tool_bar_item P_ ((struct frame *, int, int,
6511 struct glyph **, int *, int *, int *));
06a2c219 6512
9ea173e8 6513/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6514 or -1. */
6515
9ea173e8 6516static int last_tool_bar_item;
06a2c219
GM
6517
6518
9ea173e8
GM
6519/* Get information about the tool-bar item at position X/Y on frame F.
6520 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6521 the current matrix of the tool-bar window of F, or NULL if not
6522 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6523 item in F->current_tool_bar_items. Value is
06a2c219 6524
9ea173e8 6525 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6526 0 if X/Y is on the same item that was highlighted before.
6527 1 otherwise. */
6528
6529static int
9ea173e8 6530x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6531 struct frame *f;
6532 int x, y;
6533 struct glyph **glyph;
6534 int *hpos, *vpos, *prop_idx;
6535{
6536 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6537 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6538 int area;
6539
6540 /* Find the glyph under X/Y. */
6541 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6542 if (*glyph == NULL)
6543 return -1;
6544
9ea173e8
GM
6545 /* Get the start of this tool-bar item's properties in
6546 f->current_tool_bar_items. */
6547 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6548 return -1;
6549
6550 /* Is mouse on the highlighted item? */
9ea173e8 6551 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6552 && *vpos >= dpyinfo->mouse_face_beg_row
6553 && *vpos <= dpyinfo->mouse_face_end_row
6554 && (*vpos > dpyinfo->mouse_face_beg_row
6555 || *hpos >= dpyinfo->mouse_face_beg_col)
6556 && (*vpos < dpyinfo->mouse_face_end_row
6557 || *hpos < dpyinfo->mouse_face_end_col
6558 || dpyinfo->mouse_face_past_end))
6559 return 0;
6560
6561 return 1;
6562}
6563
6564
9ea173e8 6565/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6566 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6567 or ButtonRelase. */
6568
6569static void
9ea173e8 6570x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6571 struct frame *f;
6572 XButtonEvent *button_event;
6573{
6574 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6575 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6576 int hpos, vpos, prop_idx;
6577 struct glyph *glyph;
6578 Lisp_Object enabled_p;
6579 int x = button_event->x;
6580 int y = button_event->y;
6581
9ea173e8 6582 /* If not on the highlighted tool-bar item, return. */
06a2c219 6583 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6584 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6585 return;
6586
6587 /* If item is disabled, do nothing. */
9ea173e8
GM
6588 enabled_p = (XVECTOR (f->current_tool_bar_items)
6589 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6590 if (NILP (enabled_p))
6591 return;
6592
6593 if (button_event->type == ButtonPress)
6594 {
6595 /* Show item in pressed state. */
6596 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6597 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6598 last_tool_bar_item = prop_idx;
06a2c219
GM
6599 }
6600 else
6601 {
6602 Lisp_Object key, frame;
6603 struct input_event event;
6604
6605 /* Show item in released state. */
6606 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6607 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6608
9ea173e8
GM
6609 key = (XVECTOR (f->current_tool_bar_items)
6610 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
6611
6612 XSETFRAME (frame, f);
9ea173e8
GM
6613 event.kind = TOOL_BAR_EVENT;
6614 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
06a2c219
GM
6615 kbd_buffer_store_event (&event);
6616
9ea173e8 6617 event.kind = TOOL_BAR_EVENT;
06a2c219
GM
6618 event.frame_or_window = Fcons (frame, key);
6619 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6620 button_event->state);
6621 kbd_buffer_store_event (&event);
9ea173e8 6622 last_tool_bar_item = -1;
06a2c219
GM
6623 }
6624}
6625
6626
9ea173e8
GM
6627/* Possibly highlight a tool-bar item on frame F when mouse moves to
6628 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6629 note_mouse_highlight. */
6630
6631static void
9ea173e8 6632note_tool_bar_highlight (f, x, y)
06a2c219
GM
6633 struct frame *f;
6634 int x, y;
6635{
9ea173e8 6636 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
6637 struct window *w = XWINDOW (window);
6638 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6639 int hpos, vpos;
6640 struct glyph *glyph;
6641 struct glyph_row *row;
5c187dee 6642 int i;
06a2c219
GM
6643 Lisp_Object enabled_p;
6644 int prop_idx;
6645 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 6646 int mouse_down_p, rc;
06a2c219
GM
6647
6648 /* Function note_mouse_highlight is called with negative x(y
6649 values when mouse moves outside of the frame. */
6650 if (x <= 0 || y <= 0)
6651 {
6652 clear_mouse_face (dpyinfo);
6653 return;
6654 }
6655
9ea173e8 6656 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
6657 if (rc < 0)
6658 {
9ea173e8 6659 /* Not on tool-bar item. */
06a2c219
GM
6660 clear_mouse_face (dpyinfo);
6661 return;
6662 }
6663 else if (rc == 0)
9ea173e8 6664 /* On same tool-bar item as before. */
06a2c219 6665 goto set_help_echo;
b8009dd1 6666
06a2c219
GM
6667 clear_mouse_face (dpyinfo);
6668
9ea173e8 6669 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
6670 mouse_down_p = (dpyinfo->grabbed
6671 && f == last_mouse_frame
6672 && FRAME_LIVE_P (f));
6673 if (mouse_down_p
9ea173e8 6674 && last_tool_bar_item != prop_idx)
06a2c219
GM
6675 return;
6676
6677 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6678 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6679
9ea173e8
GM
6680 /* If tool-bar item is not enabled, don't highlight it. */
6681 enabled_p = (XVECTOR (f->current_tool_bar_items)
6682 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6683 if (!NILP (enabled_p))
6684 {
6685 /* Compute the x-position of the glyph. In front and past the
6686 image is a space. We include this is the highlighted area. */
6687 row = MATRIX_ROW (w->current_matrix, vpos);
6688 for (i = x = 0; i < hpos; ++i)
6689 x += row->glyphs[TEXT_AREA][i].pixel_width;
6690
6691 /* Record this as the current active region. */
6692 dpyinfo->mouse_face_beg_col = hpos;
6693 dpyinfo->mouse_face_beg_row = vpos;
6694 dpyinfo->mouse_face_beg_x = x;
6695 dpyinfo->mouse_face_beg_y = row->y;
6696 dpyinfo->mouse_face_past_end = 0;
6697
6698 dpyinfo->mouse_face_end_col = hpos + 1;
6699 dpyinfo->mouse_face_end_row = vpos;
6700 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6701 dpyinfo->mouse_face_end_y = row->y;
6702 dpyinfo->mouse_face_window = window;
9ea173e8 6703 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
6704
6705 /* Display it as active. */
6706 show_mouse_face (dpyinfo, draw);
6707 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6708 }
06a2c219
GM
6709
6710 set_help_echo:
6711
9ea173e8 6712 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 6713 XTread_socket does the rest. */
9ea173e8
GM
6714 help_echo = (XVECTOR (f->current_tool_bar_items)
6715 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
06a2c219 6716 if (!STRINGP (help_echo))
9ea173e8
GM
6717 help_echo = (XVECTOR (f->current_tool_bar_items)
6718 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 6719}
4d73d038 6720
06a2c219
GM
6721
6722\f
6723/* Find the glyph matrix position of buffer position POS in window W.
6724 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6725 current glyphs must be up to date. If POS is above window start
6726 return (0, 0, 0, 0). If POS is after end of W, return end of
6727 last line in W. */
b8009dd1
RS
6728
6729static int
06a2c219
GM
6730fast_find_position (w, pos, hpos, vpos, x, y)
6731 struct window *w;
b8009dd1 6732 int pos;
06a2c219 6733 int *hpos, *vpos, *x, *y;
b8009dd1 6734{
b8009dd1 6735 int i;
bf1c0ba1 6736 int lastcol;
06a2c219
GM
6737 int maybe_next_line_p = 0;
6738 int line_start_position;
6739 int yb = window_text_bottom_y (w);
6740 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6741 struct glyph_row *best_row = row;
6742 int row_vpos = 0, best_row_vpos = 0;
6743 int current_x;
6744
6745 while (row->y < yb)
b8009dd1 6746 {
06a2c219
GM
6747 if (row->used[TEXT_AREA])
6748 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6749 else
6750 line_start_position = 0;
6751
6752 if (line_start_position > pos)
b8009dd1 6753 break;
77b68646
RS
6754 /* If the position sought is the end of the buffer,
6755 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6756 else if (line_start_position == pos
6757 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6758 {
06a2c219 6759 maybe_next_line_p = 1;
77b68646
RS
6760 break;
6761 }
06a2c219
GM
6762 else if (line_start_position > 0)
6763 {
6764 best_row = row;
6765 best_row_vpos = row_vpos;
6766 }
4b0bb6f3
GM
6767
6768 if (row->y + row->height >= yb)
6769 break;
06a2c219
GM
6770
6771 ++row;
6772 ++row_vpos;
b8009dd1 6773 }
06a2c219
GM
6774
6775 /* Find the right column within BEST_ROW. */
6776 lastcol = 0;
6777 current_x = best_row->x;
6778 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 6779 {
06a2c219
GM
6780 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6781 int charpos;
6782
6783 charpos = glyph->charpos;
6784 if (charpos == pos)
bf1c0ba1 6785 {
06a2c219
GM
6786 *hpos = i;
6787 *vpos = best_row_vpos;
6788 *x = current_x;
6789 *y = best_row->y;
bf1c0ba1
RS
6790 return 1;
6791 }
06a2c219 6792 else if (charpos > pos)
4d73d038 6793 break;
06a2c219
GM
6794 else if (charpos > 0)
6795 lastcol = i;
6796
6797 current_x += glyph->pixel_width;
bf1c0ba1 6798 }
b8009dd1 6799
77b68646
RS
6800 /* If we're looking for the end of the buffer,
6801 and we didn't find it in the line we scanned,
6802 use the start of the following line. */
06a2c219 6803 if (maybe_next_line_p)
77b68646 6804 {
06a2c219
GM
6805 ++best_row;
6806 ++best_row_vpos;
6807 lastcol = 0;
6808 current_x = best_row->x;
77b68646
RS
6809 }
6810
06a2c219
GM
6811 *vpos = best_row_vpos;
6812 *hpos = lastcol + 1;
6813 *x = current_x;
6814 *y = best_row->y;
b8009dd1
RS
6815 return 0;
6816}
6817
06a2c219 6818
b8009dd1
RS
6819/* Display the active region described by mouse_face_*
6820 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6821
6822static void
06a2c219 6823show_mouse_face (dpyinfo, draw)
7a13e894 6824 struct x_display_info *dpyinfo;
06a2c219 6825 enum draw_glyphs_face draw;
b8009dd1 6826{
7a13e894 6827 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 6828 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 6829 int i;
06a2c219
GM
6830 int cursor_off_p = 0;
6831 struct cursor_pos saved_cursor;
6832
6833 saved_cursor = output_cursor;
6834
6835 /* If window is in the process of being destroyed, don't bother
6836 to do anything. */
6837 if (w->current_matrix == NULL)
6838 goto set_x_cursor;
6839
6840 /* Recognize when we are called to operate on rows that don't exist
6841 anymore. This can happen when a window is split. */
6842 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6843 goto set_x_cursor;
6844
6845 set_output_cursor (&w->phys_cursor);
6846
6847 /* Note that mouse_face_beg_row etc. are window relative. */
6848 for (i = dpyinfo->mouse_face_beg_row;
6849 i <= dpyinfo->mouse_face_end_row;
6850 i++)
6851 {
6852 int start_hpos, end_hpos, start_x;
6853 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6854
6855 /* Don't do anything if row doesn't have valid contents. */
6856 if (!row->enabled_p)
6857 continue;
6858
6859 /* For all but the first row, the highlight starts at column 0. */
6860 if (i == dpyinfo->mouse_face_beg_row)
6861 {
6862 start_hpos = dpyinfo->mouse_face_beg_col;
6863 start_x = dpyinfo->mouse_face_beg_x;
6864 }
6865 else
6866 {
6867 start_hpos = 0;
6868 start_x = 0;
6869 }
6870
6871 if (i == dpyinfo->mouse_face_end_row)
6872 end_hpos = dpyinfo->mouse_face_end_col;
6873 else
6874 end_hpos = row->used[TEXT_AREA];
6875
6876 /* If the cursor's in the text we are about to rewrite, turn the
6877 cursor off. */
6878 if (!w->pseudo_window_p
6879 && i == output_cursor.vpos
6880 && output_cursor.hpos >= start_hpos - 1
6881 && output_cursor.hpos <= end_hpos)
514e4681 6882 {
06a2c219
GM
6883 x_update_window_cursor (w, 0);
6884 cursor_off_p = 1;
514e4681 6885 }
b8009dd1 6886
06a2c219 6887 if (end_hpos > start_hpos)
54a91a0f 6888 x_draw_glyphs (w, start_x, row, TEXT_AREA,
66ac4b0e 6889 start_hpos, end_hpos, draw, NULL, NULL, 0);
b8009dd1
RS
6890 }
6891
514e4681 6892 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
6893 if (cursor_off_p)
6894 x_display_cursor (w, 1,
6895 output_cursor.hpos, output_cursor.vpos,
6896 output_cursor.x, output_cursor.y);
2729a2b5 6897
06a2c219 6898 output_cursor = saved_cursor;
fb3b7de5 6899
06a2c219
GM
6900 set_x_cursor:
6901
6902 /* Change the mouse cursor. */
6903 if (draw == DRAW_NORMAL_TEXT)
6904 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6905 f->output_data.x->text_cursor);
6906 else if (draw == DRAW_MOUSE_FACE)
334208b7 6907 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 6908 f->output_data.x->cross_cursor);
27ead1d5 6909 else
334208b7 6910 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 6911 f->output_data.x->nontext_cursor);
b8009dd1
RS
6912}
6913
6914/* Clear out the mouse-highlighted active region.
06a2c219 6915 Redraw it un-highlighted first. */
b8009dd1 6916
06a2c219 6917void
7a13e894
RS
6918clear_mouse_face (dpyinfo)
6919 struct x_display_info *dpyinfo;
b8009dd1 6920{
06a2c219
GM
6921 if (tip_frame)
6922 return;
6923
7a13e894 6924 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 6925 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 6926
7a13e894
RS
6927 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6928 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6929 dpyinfo->mouse_face_window = Qnil;
b8009dd1 6930}
e687d06e
RS
6931
6932/* Just discard the mouse face information for frame F, if any.
6933 This is used when the size of F is changed. */
6934
dfcf069d 6935void
e687d06e
RS
6936cancel_mouse_face (f)
6937 FRAME_PTR f;
6938{
6939 Lisp_Object window;
6940 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6941
6942 window = dpyinfo->mouse_face_window;
6943 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6944 {
6945 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6946 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6947 dpyinfo->mouse_face_window = Qnil;
6948 }
6949}
b8009dd1 6950\f
ab648270
JB
6951static struct scroll_bar *x_window_to_scroll_bar ();
6952static void x_scroll_bar_report_motion ();
12ba150f 6953
90e65f07 6954/* Return the current position of the mouse.
2d7fc7e8 6955 *fp should be a frame which indicates which display to ask about.
90e65f07 6956
2d7fc7e8 6957 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 6958 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 6959 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 6960 position on the scroll bar.
12ba150f 6961
2d7fc7e8 6962 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
6963 mouse is on, *bar_window to nil, and *x and *y to the character cell
6964 the mouse is over.
6965
06a2c219 6966 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
6967 was at this position.
6968
a135645a
RS
6969 Don't store anything if we don't have a valid set of values to report.
6970
90e65f07 6971 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 6972 movement. */
90e65f07
JB
6973
6974static void
1cf412ec 6975XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 6976 FRAME_PTR *fp;
1cf412ec 6977 int insist;
12ba150f 6978 Lisp_Object *bar_window;
ab648270 6979 enum scroll_bar_part *part;
90e65f07 6980 Lisp_Object *x, *y;
e5d77022 6981 unsigned long *time;
90e65f07 6982{
a135645a
RS
6983 FRAME_PTR f1;
6984
90e65f07
JB
6985 BLOCK_INPUT;
6986
8bcee03e 6987 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 6988 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
6989 else
6990 {
12ba150f
JB
6991 Window root;
6992 int root_x, root_y;
90e65f07 6993
12ba150f
JB
6994 Window dummy_window;
6995 int dummy;
6996
39d8bb4d
KH
6997 Lisp_Object frame, tail;
6998
6999 /* Clear the mouse-moved flag for every frame on this display. */
7000 FOR_EACH_FRAME (tail, frame)
7001 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7002 XFRAME (frame)->mouse_moved = 0;
7003
ab648270 7004 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7005
7006 /* Figure out which root window we're on. */
334208b7
RS
7007 XQueryPointer (FRAME_X_DISPLAY (*fp),
7008 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7009
7010 /* The root window which contains the pointer. */
7011 &root,
7012
7013 /* Trash which we can't trust if the pointer is on
7014 a different screen. */
7015 &dummy_window,
7016
7017 /* The position on that root window. */
58769bee 7018 &root_x, &root_y,
12ba150f
JB
7019
7020 /* More trash we can't trust. */
7021 &dummy, &dummy,
7022
7023 /* Modifier keys and pointer buttons, about which
7024 we don't care. */
7025 (unsigned int *) &dummy);
7026
7027 /* Now we have a position on the root; find the innermost window
7028 containing the pointer. */
7029 {
7030 Window win, child;
7031 int win_x, win_y;
06a2c219 7032 int parent_x = 0, parent_y = 0;
e99db5a1 7033 int count;
12ba150f
JB
7034
7035 win = root;
69388238 7036
2d7fc7e8
RS
7037 /* XTranslateCoordinates can get errors if the window
7038 structure is changing at the same time this function
7039 is running. So at least we must not crash from them. */
7040
e99db5a1 7041 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7042
334208b7 7043 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7044 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7045 {
69388238
RS
7046 /* If mouse was grabbed on a frame, give coords for that frame
7047 even if the mouse is now outside it. */
334208b7 7048 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7049
12ba150f 7050 /* From-window, to-window. */
69388238 7051 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7052
7053 /* From-position, to-position. */
7054 root_x, root_y, &win_x, &win_y,
7055
7056 /* Child of win. */
7057 &child);
69388238
RS
7058 f1 = last_mouse_frame;
7059 }
7060 else
7061 {
7062 while (1)
7063 {
334208b7 7064 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7065
69388238
RS
7066 /* From-window, to-window. */
7067 root, win,
12ba150f 7068
69388238
RS
7069 /* From-position, to-position. */
7070 root_x, root_y, &win_x, &win_y,
7071
7072 /* Child of win. */
7073 &child);
7074
9af3143a 7075 if (child == None || child == win)
69388238
RS
7076 break;
7077
7078 win = child;
7079 parent_x = win_x;
7080 parent_y = win_y;
7081 }
12ba150f 7082
69388238
RS
7083 /* Now we know that:
7084 win is the innermost window containing the pointer
7085 (XTC says it has no child containing the pointer),
7086 win_x and win_y are the pointer's position in it
7087 (XTC did this the last time through), and
7088 parent_x and parent_y are the pointer's position in win's parent.
7089 (They are what win_x and win_y were when win was child.
7090 If win is the root window, it has no parent, and
7091 parent_{x,y} are invalid, but that's okay, because we'll
7092 never use them in that case.) */
7093
7094 /* Is win one of our frames? */
19126e11 7095 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7096 }
58769bee 7097
2d7fc7e8
RS
7098 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7099 f1 = 0;
7100
e99db5a1 7101 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7102
ab648270 7103 /* If not, is it one of our scroll bars? */
a135645a 7104 if (! f1)
12ba150f 7105 {
ab648270 7106 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7107
7108 if (bar)
7109 {
a135645a 7110 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7111 win_x = parent_x;
7112 win_y = parent_y;
7113 }
7114 }
90e65f07 7115
8bcee03e 7116 if (f1 == 0 && insist > 0)
b86bd3dd 7117 f1 = SELECTED_FRAME ();
1cf412ec 7118
a135645a 7119 if (f1)
12ba150f 7120 {
06a2c219
GM
7121 /* Ok, we found a frame. Store all the values.
7122 last_mouse_glyph is a rectangle used to reduce the
7123 generation of mouse events. To not miss any motion
7124 events, we must divide the frame into rectangles of the
7125 size of the smallest character that could be displayed
7126 on it, i.e. into the same rectangles that matrices on
7127 the frame are divided into. */
7128
7129#if OLD_REDISPLAY_CODE
2b5c9e71 7130 int ignore1, ignore2;
2b5c9e71 7131 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7132 &last_mouse_glyph,
1cf412ec
RS
7133 FRAME_X_DISPLAY_INFO (f1)->grabbed
7134 || insist);
06a2c219
GM
7135#else
7136 {
7137 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7138 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7139 int x = win_x;
7140 int y = win_y;
7141
7142 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7143 round down even for negative values. */
7144 if (x < 0)
7145 x -= width - 1;
7146 if (y < 0)
7147 y -= height - 1;
7148
7149 last_mouse_glyph.width = width;
7150 last_mouse_glyph.height = height;
7151 last_mouse_glyph.x = (x + width - 1) / width * width;
7152 last_mouse_glyph.y = (y + height - 1) / height * height;
7153 }
7154#endif
12ba150f
JB
7155
7156 *bar_window = Qnil;
7157 *part = 0;
334208b7 7158 *fp = f1;
e0c1aef2
KH
7159 XSETINT (*x, win_x);
7160 XSETINT (*y, win_y);
12ba150f
JB
7161 *time = last_mouse_movement_time;
7162 }
7163 }
7164 }
90e65f07
JB
7165
7166 UNBLOCK_INPUT;
7167}
f451eb13 7168
06a2c219 7169
06a2c219 7170#ifdef USE_X_TOOLKIT
bffcfca9
GM
7171
7172/* Atimer callback function for TIMER. Called every 0.1s to process
7173 Xt timeouts, if needed. We must avoid calling XtAppPending as
7174 much as possible because that function does an implicit XFlush
7175 that slows us down. */
7176
7177static void
7178x_process_timeouts (timer)
7179 struct atimer *timer;
7180{
7181 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7182 {
7183 BLOCK_INPUT;
7184 while (XtAppPending (Xt_app_con) & XtIMTimer)
7185 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7186 UNBLOCK_INPUT;
7187 }
06a2c219
GM
7188}
7189
bffcfca9 7190#endif /* USE_X_TOOLKIT */
06a2c219
GM
7191
7192\f
7193/* Scroll bar support. */
7194
7195/* Given an X window ID, find the struct scroll_bar which manages it.
7196 This can be called in GC, so we have to make sure to strip off mark
7197 bits. */
bffcfca9 7198
06a2c219
GM
7199static struct scroll_bar *
7200x_window_to_scroll_bar (window_id)
7201 Window window_id;
7202{
7203 Lisp_Object tail;
7204
7205 for (tail = Vframe_list;
7206 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7207 tail = XCDR (tail))
06a2c219
GM
7208 {
7209 Lisp_Object frame, bar, condemned;
7210
8e713be6 7211 frame = XCAR (tail);
06a2c219
GM
7212 /* All elements of Vframe_list should be frames. */
7213 if (! GC_FRAMEP (frame))
7214 abort ();
7215
7216 /* Scan this frame's scroll bar list for a scroll bar with the
7217 right window ID. */
7218 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7219 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7220 /* This trick allows us to search both the ordinary and
7221 condemned scroll bar lists with one loop. */
7222 ! GC_NILP (bar) || (bar = condemned,
7223 condemned = Qnil,
7224 ! GC_NILP (bar));
7225 bar = XSCROLL_BAR (bar)->next)
7226 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7227 return XSCROLL_BAR (bar);
7228 }
7229
7230 return 0;
7231}
7232
7233
7234\f
7235/************************************************************************
7236 Toolkit scroll bars
7237 ************************************************************************/
7238
7239#if USE_TOOLKIT_SCROLL_BARS
7240
7241static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7242static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7243static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7244 struct scroll_bar *));
7245static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7246 int, int, int));
7247
7248
7249/* Id of action hook installed for scroll bars. */
7250
7251static XtActionHookId action_hook_id;
7252
7253/* Lisp window being scrolled. Set when starting to interact with
7254 a toolkit scroll bar, reset to nil when ending the interaction. */
7255
7256static Lisp_Object window_being_scrolled;
7257
7258/* Last scroll bar part sent in xm_scroll_callback. */
7259
7260static int last_scroll_bar_part;
7261
ec18280f
SM
7262/* Whether this is an Xaw with arrow-scrollbars. This should imply
7263 that movements of 1/20 of the screen size are mapped to up/down. */
7264
7265static Boolean xaw3d_arrow_scroll;
7266
7267/* Whether the drag scrolling maintains the mouse at the top of the
7268 thumb. If not, resizing the thumb needs to be done more carefully
7269 to avoid jerkyness. */
7270
7271static Boolean xaw3d_pick_top;
7272
06a2c219
GM
7273
7274/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7275 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7276 the user ends an interaction with the scroll bar, and generates
7277 a `end-scroll' scroll_bar_click' event if so. */
7278
7279static void
7280xt_action_hook (widget, client_data, action_name, event, params,
7281 num_params)
7282 Widget widget;
7283 XtPointer client_data;
7284 String action_name;
7285 XEvent *event;
7286 String *params;
7287 Cardinal *num_params;
7288{
7289 int scroll_bar_p;
7290 char *end_action;
7291
7292#ifdef USE_MOTIF
7293 scroll_bar_p = XmIsScrollBar (widget);
7294 end_action = "Release";
ec18280f 7295#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7296 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7297 end_action = "EndScroll";
ec18280f 7298#endif /* USE_MOTIF */
06a2c219 7299
06a2c219
GM
7300 if (scroll_bar_p
7301 && strcmp (action_name, end_action) == 0
7302 && WINDOWP (window_being_scrolled))
7303 {
7304 struct window *w;
7305
7306 x_send_scroll_bar_event (window_being_scrolled,
7307 scroll_bar_end_scroll, 0, 0);
7308 w = XWINDOW (window_being_scrolled);
7309 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7310 window_being_scrolled = Qnil;
7311 last_scroll_bar_part = -1;
bffcfca9
GM
7312
7313 /* Xt timeouts no longer needed. */
7314 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7315 }
7316}
7317
7318
7319/* Send a client message with message type Xatom_Scrollbar for a
7320 scroll action to the frame of WINDOW. PART is a value identifying
7321 the part of the scroll bar that was clicked on. PORTION is the
7322 amount to scroll of a whole of WHOLE. */
7323
7324static void
7325x_send_scroll_bar_event (window, part, portion, whole)
7326 Lisp_Object window;
7327 int part, portion, whole;
7328{
7329 XEvent event;
7330 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7331 struct frame *f = XFRAME (XWINDOW (window)->frame);
7332
7333 /* Construct a ClientMessage event to send to the frame. */
7334 ev->type = ClientMessage;
7335 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7336 ev->display = FRAME_X_DISPLAY (f);
7337 ev->window = FRAME_X_WINDOW (f);
7338 ev->format = 32;
7339 ev->data.l[0] = (long) window;
7340 ev->data.l[1] = (long) part;
7341 ev->data.l[2] = (long) 0;
7342 ev->data.l[3] = (long) portion;
7343 ev->data.l[4] = (long) whole;
7344
bffcfca9
GM
7345 /* Make Xt timeouts work while the scroll bar is active. */
7346 toolkit_scroll_bar_interaction = 1;
7347
06a2c219
GM
7348 /* Setting the event mask to zero means that the message will
7349 be sent to the client that created the window, and if that
7350 window no longer exists, no event will be sent. */
7351 BLOCK_INPUT;
7352 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7353 UNBLOCK_INPUT;
7354}
7355
7356
7357/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7358 in *IEVENT. */
7359
7360static void
7361x_scroll_bar_to_input_event (event, ievent)
7362 XEvent *event;
7363 struct input_event *ievent;
7364{
7365 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7366 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7367 struct frame *f = XFRAME (XWINDOW (window)->frame);
7368
7369 ievent->kind = scroll_bar_click;
7370 ievent->frame_or_window = window;
7371 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7372 ievent->part = ev->data.l[1];
7373 ievent->code = ev->data.l[2];
7374 ievent->x = make_number ((int) ev->data.l[3]);
7375 ievent->y = make_number ((int) ev->data.l[4]);
7376 ievent->modifiers = 0;
7377}
7378
7379
7380#ifdef USE_MOTIF
7381
7382/* Minimum and maximum values used for Motif scroll bars. */
7383
7384#define XM_SB_MIN 1
7385#define XM_SB_MAX 10000000
7386#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7387
7388
7389/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7390 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7391 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7392
7393static void
7394xm_scroll_callback (widget, client_data, call_data)
7395 Widget widget;
7396 XtPointer client_data, call_data;
7397{
7398 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7399 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7400 double percent;
7401 int part = -1, whole = 0, portion = 0;
7402
7403 switch (cs->reason)
7404 {
7405 case XmCR_DECREMENT:
7406 bar->dragging = Qnil;
7407 part = scroll_bar_up_arrow;
7408 break;
7409
7410 case XmCR_INCREMENT:
7411 bar->dragging = Qnil;
7412 part = scroll_bar_down_arrow;
7413 break;
7414
7415 case XmCR_PAGE_DECREMENT:
7416 bar->dragging = Qnil;
7417 part = scroll_bar_above_handle;
7418 break;
7419
7420 case XmCR_PAGE_INCREMENT:
7421 bar->dragging = Qnil;
7422 part = scroll_bar_below_handle;
7423 break;
7424
7425 case XmCR_TO_TOP:
7426 bar->dragging = Qnil;
7427 part = scroll_bar_to_top;
7428 break;
7429
7430 case XmCR_TO_BOTTOM:
7431 bar->dragging = Qnil;
7432 part = scroll_bar_to_bottom;
7433 break;
7434
7435 case XmCR_DRAG:
7436 {
7437 int slider_size;
7438 int dragging_down_p = (INTEGERP (bar->dragging)
7439 && XINT (bar->dragging) <= cs->value);
7440
7441 /* Get the slider size. */
7442 BLOCK_INPUT;
7443 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7444 UNBLOCK_INPUT;
7445
7446 /* At the max position of the scroll bar, do a line-wise
7447 movement. Without doing anything, the LessTif scroll bar
7448 calls us with the same cs->value again and again. If we
7449 want to make sure that we can reach the end of the buffer,
7450 we have to do something.
7451
7452 Implementation note: setting bar->dragging always to
7453 cs->value gives a smoother movement at the max position.
7454 Setting it to nil when doing line-wise movement gives
7455 a better slider behavior. */
7456
7457 if (cs->value + slider_size == XM_SB_MAX
7458 || (dragging_down_p
7459 && last_scroll_bar_part == scroll_bar_down_arrow))
7460 {
7461 part = scroll_bar_down_arrow;
7462 bar->dragging = Qnil;
7463 }
7464 else
7465 {
7466 whole = XM_SB_RANGE;
7467 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7468 part = scroll_bar_handle;
7469 bar->dragging = make_number (cs->value);
7470 }
7471 }
7472 break;
7473
7474 case XmCR_VALUE_CHANGED:
7475 break;
7476 };
7477
7478 if (part >= 0)
7479 {
7480 window_being_scrolled = bar->window;
7481 last_scroll_bar_part = part;
7482 x_send_scroll_bar_event (bar->window, part, portion, whole);
7483 }
7484}
7485
7486
ec18280f 7487#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7488
7489
ec18280f 7490/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7491 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7492 scroll bar struct. CALL_DATA is a pointer to a float saying where
7493 the thumb is. */
7494
7495static void
ec18280f 7496xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7497 Widget widget;
7498 XtPointer client_data, call_data;
7499{
7500 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7501 float top = *(float *) call_data;
7502 float shown;
ec18280f
SM
7503 int whole, portion, height;
7504 int part;
06a2c219
GM
7505
7506 /* Get the size of the thumb, a value between 0 and 1. */
7507 BLOCK_INPUT;
ec18280f 7508 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7509 UNBLOCK_INPUT;
7510
7511 whole = 10000000;
7512 portion = shown < 1 ? top * whole : 0;
06a2c219 7513
ec18280f
SM
7514 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7515 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7516 the bottom, so we force the scrolling whenever we see that we're
7517 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7518 we try to ensure that we always stay two pixels away from the
7519 bottom). */
06a2c219
GM
7520 part = scroll_bar_down_arrow;
7521 else
7522 part = scroll_bar_handle;
7523
7524 window_being_scrolled = bar->window;
7525 bar->dragging = make_number (portion);
7526 last_scroll_bar_part = part;
7527 x_send_scroll_bar_event (bar->window, part, portion, whole);
7528}
7529
7530
ec18280f
SM
7531/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7532 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7533 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7534 the scroll bar. CALL_DATA is an integer specifying the action that
7535 has taken place. It's magnitude is in the range 0..height of the
7536 scroll bar. Negative values mean scroll towards buffer start.
7537 Values < height of scroll bar mean line-wise movement. */
7538
7539static void
ec18280f 7540xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7541 Widget widget;
7542 XtPointer client_data, call_data;
7543{
7544 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7545 int position = (int) call_data;
7546 Dimension height;
7547 int part;
7548
7549 /* Get the height of the scroll bar. */
7550 BLOCK_INPUT;
7551 XtVaGetValues (widget, XtNheight, &height, NULL);
7552 UNBLOCK_INPUT;
7553
ec18280f
SM
7554 if (abs (position) >= height)
7555 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7556
7557 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7558 it maps line-movement to call_data = max(5, height/20). */
7559 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7560 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7561 else
ec18280f 7562 part = scroll_bar_move_ratio;
06a2c219
GM
7563
7564 window_being_scrolled = bar->window;
7565 bar->dragging = Qnil;
7566 last_scroll_bar_part = part;
ec18280f 7567 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7568}
7569
7570
7571#endif /* not USE_MOTIF */
7572
7573
7574/* Create the widget for scroll bar BAR on frame F. Record the widget
7575 and X window of the scroll bar in BAR. */
7576
7577static void
7578x_create_toolkit_scroll_bar (f, bar)
7579 struct frame *f;
7580 struct scroll_bar *bar;
7581{
7582 Window xwindow;
7583 Widget widget;
7584 Arg av[20];
7585 int ac = 0;
7586 char *scroll_bar_name = "verticalScrollBar";
7587 unsigned long pixel;
7588
7589 BLOCK_INPUT;
7590
7591#ifdef USE_MOTIF
7592 /* LessTif 0.85, problems:
7593
7594 1. When the mouse if over the scroll bar, the scroll bar will
7595 get keyboard events. I didn't find a way to turn this off.
7596
7597 2. Do we have to explicitly set the cursor to get an arrow
7598 cursor (see below)? */
7599
7600 /* Set resources. Create the widget. */
7601 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7602 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7603 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7604 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7605 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7606 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7607 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7608
7609 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7610 if (pixel != -1)
7611 {
7612 XtSetArg (av[ac], XmNforeground, pixel);
7613 ++ac;
7614 }
7615
7616 pixel = f->output_data.x->scroll_bar_background_pixel;
7617 if (pixel != -1)
7618 {
7619 XtSetArg (av[ac], XmNbackground, pixel);
7620 ++ac;
7621 }
7622
7623 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7624 scroll_bar_name, av, ac);
7625
7626 /* Add one callback for everything that can happen. */
7627 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7628 (XtPointer) bar);
7629 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7630 (XtPointer) bar);
7631 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7632 (XtPointer) bar);
7633 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7634 (XtPointer) bar);
7635 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7636 (XtPointer) bar);
7637 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7638 (XtPointer) bar);
7639 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7640 (XtPointer) bar);
7641
7642 /* Realize the widget. Only after that is the X window created. */
7643 XtRealizeWidget (widget);
7644
7645 /* Set the cursor to an arrow. I didn't find a resource to do that.
7646 And I'm wondering why it hasn't an arrow cursor by default. */
7647 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7648 f->output_data.x->nontext_cursor);
7649
ec18280f 7650#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7651
7652 /* Set resources. Create the widget. The background of the
7653 Xaw3d scroll bar widget is a little bit light for my taste.
7654 We don't alter it here to let users change it according
7655 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7656 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7657 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
7658 /* For smoother scrolling with Xaw3d -sm */
7659 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7660 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
7661
7662 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7663 if (pixel != -1)
7664 {
7665 XtSetArg (av[ac], XtNforeground, pixel);
7666 ++ac;
7667 }
7668
7669 pixel = f->output_data.x->scroll_bar_background_pixel;
7670 if (pixel != -1)
7671 {
7672 XtSetArg (av[ac], XtNbackground, pixel);
7673 ++ac;
7674 }
7675
7676 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7677 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
7678
7679 {
7680 char *initial = "";
7681 char *val = initial;
7682 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7683 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7684 if (val == initial)
7685 { /* ARROW_SCROLL */
7686 xaw3d_arrow_scroll = True;
7687 /* Isn't that just a personal preference ? -sm */
7688 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7689 }
7690 }
06a2c219
GM
7691
7692 /* Define callbacks. */
ec18280f
SM
7693 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7694 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
7695 (XtPointer) bar);
7696
7697 /* Realize the widget. Only after that is the X window created. */
7698 XtRealizeWidget (widget);
7699
ec18280f 7700#endif /* !USE_MOTIF */
06a2c219
GM
7701
7702 /* Install an action hook that let's us detect when the user
7703 finishes interacting with a scroll bar. */
7704 if (action_hook_id == 0)
7705 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7706
7707 /* Remember X window and widget in the scroll bar vector. */
7708 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7709 xwindow = XtWindow (widget);
7710 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7711
7712 UNBLOCK_INPUT;
7713}
7714
7715
7716/* Set the thumb size and position of scroll bar BAR. We are currently
7717 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7718
7719static void
7720x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7721 struct scroll_bar *bar;
7722 int portion, position, whole;
f451eb13 7723{
06a2c219 7724 float top, shown;
06a2c219 7725 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7726
06a2c219
GM
7727 if (whole == 0)
7728 top = 0, shown = 1;
7729 else
f451eb13 7730 {
06a2c219
GM
7731 top = (float) position / whole;
7732 shown = (float) portion / whole;
7733 }
f451eb13 7734
06a2c219 7735 BLOCK_INPUT;
f451eb13 7736
06a2c219
GM
7737#ifdef USE_MOTIF
7738 {
7739 int size, value;
7740 Boolean arrow1_selected, arrow2_selected;
7741 unsigned char flags;
7742 XmScrollBarWidget sb;
7743
ec18280f 7744 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
7745 is the scroll bar's maximum and MIN is the scroll bar's minimum
7746 value. */
7747 size = shown * XM_SB_RANGE;
7748 size = min (size, XM_SB_RANGE);
7749 size = max (size, 1);
7750
7751 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7752 value = top * XM_SB_RANGE;
7753 value = min (value, XM_SB_MAX - size);
7754 value = max (value, XM_SB_MIN);
7755
7756 /* LessTif: Calling XmScrollBarSetValues after an increment or
7757 decrement turns off auto-repeat LessTif-internally. This can
7758 be seen in ScrollBar.c which resets Arrow1Selected and
7759 Arrow2Selected. It also sets internal flags so that LessTif
7760 believes the mouse is in the slider. We either have to change
7761 our code, or work around that by accessing private data. */
7762
7763 sb = (XmScrollBarWidget) widget;
7764 arrow1_selected = sb->scrollBar.arrow1_selected;
7765 arrow2_selected = sb->scrollBar.arrow2_selected;
7766 flags = sb->scrollBar.flags;
7767
7768 if (NILP (bar->dragging))
7769 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7770 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7771 /* This has the negative side effect that the slider value is
ec18280f 7772 not what it would be if we scrolled here using line-wise or
06a2c219
GM
7773 page-wise movement. */
7774 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7775 else
7776 {
7777 /* If currently dragging, only update the slider size.
7778 This reduces flicker effects. */
7779 int old_value, old_size, increment, page_increment;
7780
7781 XmScrollBarGetValues (widget, &old_value, &old_size,
7782 &increment, &page_increment);
7783 XmScrollBarSetValues (widget, old_value,
7784 min (size, XM_SB_RANGE - old_value),
7785 0, 0, False);
7786 }
7787
7788 sb->scrollBar.arrow1_selected = arrow1_selected;
7789 sb->scrollBar.arrow2_selected = arrow2_selected;
7790 sb->scrollBar.flags = flags;
7791 }
ec18280f 7792#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 7793 {
ec18280f
SM
7794 float old_top, old_shown;
7795 Dimension height;
7796 XtVaGetValues (widget,
7797 XtNtopOfThumb, &old_top,
7798 XtNshown, &old_shown,
7799 XtNheight, &height,
7800 NULL);
7801
7802 /* Massage the top+shown values. */
7803 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7804 top = max (0, min (1, top));
7805 else
7806 top = old_top;
7807 /* Keep two pixels available for moving the thumb down. */
7808 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
7809
7810 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7811 check that your system's configuration file contains a define
7812 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 7813 if (top != old_top || shown != old_shown)
eb393530 7814 {
ec18280f 7815 if (NILP (bar->dragging))
eb393530 7816 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
7817 else
7818 {
ec18280f
SM
7819#ifdef HAVE_XAW3D
7820 ScrollbarWidget sb = (ScrollbarWidget) widget;
7821 int scroll_mode;
7822
7823 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7824 if (xaw3d_arrow_scroll)
7825 {
7826 /* Xaw3d stupidly ignores resize requests while dragging
7827 so we have to make it believe it's not in dragging mode. */
7828 scroll_mode = sb->scrollbar.scroll_mode;
7829 if (scroll_mode == 2)
7830 sb->scrollbar.scroll_mode = 0;
7831 }
7832#endif
7833 /* Try to make the scrolling a tad smoother. */
7834 if (!xaw3d_pick_top)
7835 shown = min (shown, old_shown);
7836
7837 XawScrollbarSetThumb (widget, top, shown);
7838
7839#ifdef HAVE_XAW3D
7840 if (xaw3d_arrow_scroll && scroll_mode == 2)
7841 sb->scrollbar.scroll_mode = scroll_mode;
7842#endif
06a2c219 7843 }
06a2c219
GM
7844 }
7845 }
ec18280f 7846#endif /* !USE_MOTIF */
06a2c219
GM
7847
7848 UNBLOCK_INPUT;
f451eb13
JB
7849}
7850
06a2c219
GM
7851#endif /* USE_TOOLKIT_SCROLL_BARS */
7852
7853
7854\f
7855/************************************************************************
7856 Scroll bars, general
7857 ************************************************************************/
7858
7859/* Create a scroll bar and return the scroll bar vector for it. W is
7860 the Emacs window on which to create the scroll bar. TOP, LEFT,
7861 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7862 scroll bar. */
7863
ab648270 7864static struct scroll_bar *
06a2c219
GM
7865x_scroll_bar_create (w, top, left, width, height)
7866 struct window *w;
f451eb13
JB
7867 int top, left, width, height;
7868{
06a2c219 7869 struct frame *f = XFRAME (w->frame);
334208b7
RS
7870 struct scroll_bar *bar
7871 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
7872
7873 BLOCK_INPUT;
7874
06a2c219
GM
7875#if USE_TOOLKIT_SCROLL_BARS
7876 x_create_toolkit_scroll_bar (f, bar);
7877#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7878 {
7879 XSetWindowAttributes a;
7880 unsigned long mask;
5c187dee 7881 Window window;
06a2c219
GM
7882
7883 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7884 if (a.background_pixel == -1)
7885 a.background_pixel = f->output_data.x->background_pixel;
7886
12ba150f 7887 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 7888 | ButtonMotionMask | PointerMotionHintMask
12ba150f 7889 | ExposureMask);
7a13e894 7890 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 7891
dbc4e1c1 7892 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 7893
06a2c219
GM
7894 /* Clear the area of W that will serve as a scroll bar. This is
7895 for the case that a window has been split horizontally. In
7896 this case, no clear_frame is generated to reduce flickering. */
7897 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7898 left, top, width,
7899 window_box_height (w), False);
7900
7901 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7902 /* Position and size of scroll bar. */
7903 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7904 top,
7905 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7906 height,
7907 /* Border width, depth, class, and visual. */
7908 0,
7909 CopyFromParent,
7910 CopyFromParent,
7911 CopyFromParent,
7912 /* Attributes. */
7913 mask, &a);
7914 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 7915 }
06a2c219 7916#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 7917
06a2c219 7918 XSETWINDOW (bar->window, w);
e0c1aef2
KH
7919 XSETINT (bar->top, top);
7920 XSETINT (bar->left, left);
7921 XSETINT (bar->width, width);
7922 XSETINT (bar->height, height);
7923 XSETINT (bar->start, 0);
7924 XSETINT (bar->end, 0);
12ba150f 7925 bar->dragging = Qnil;
f451eb13
JB
7926
7927 /* Add bar to its frame's list of scroll bars. */
334208b7 7928 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 7929 bar->prev = Qnil;
334208b7 7930 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 7931 if (!NILP (bar->next))
e0c1aef2 7932 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 7933
06a2c219
GM
7934 /* Map the window/widget. */
7935#if USE_TOOLKIT_SCROLL_BARS
7936 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
7937 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7938 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7939 top,
7940 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7941 height, 0);
7942#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 7943 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 7944#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7945
7946 UNBLOCK_INPUT;
12ba150f 7947 return bar;
f451eb13
JB
7948}
7949
06a2c219 7950
12ba150f 7951/* Draw BAR's handle in the proper position.
06a2c219 7952
12ba150f
JB
7953 If the handle is already drawn from START to END, don't bother
7954 redrawing it, unless REBUILD is non-zero; in that case, always
7955 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 7956 events.)
12ba150f
JB
7957
7958 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
7959 fit inside its rectangle, but if the user is dragging the scroll
7960 bar handle, we want to let them drag it down all the way, so that
7961 the bar's top is as far down as it goes; otherwise, there's no way
7962 to move to the very end of the buffer. */
7963
5c187dee
GM
7964#ifndef USE_TOOLKIT_SCROLL_BARS
7965
f451eb13 7966static void
ab648270
JB
7967x_scroll_bar_set_handle (bar, start, end, rebuild)
7968 struct scroll_bar *bar;
f451eb13 7969 int start, end;
12ba150f 7970 int rebuild;
f451eb13 7971{
12ba150f 7972 int dragging = ! NILP (bar->dragging);
ab648270 7973 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 7974 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 7975 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
7976
7977 /* If the display is already accurate, do nothing. */
7978 if (! rebuild
7979 && start == XINT (bar->start)
7980 && end == XINT (bar->end))
7981 return;
7982
f451eb13
JB
7983 BLOCK_INPUT;
7984
7985 {
d9cdbb3d
RS
7986 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
7987 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
7988 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
7989
7990 /* Make sure the values are reasonable, and try to preserve
7991 the distance between start and end. */
12ba150f
JB
7992 {
7993 int length = end - start;
7994
7995 if (start < 0)
7996 start = 0;
7997 else if (start > top_range)
7998 start = top_range;
7999 end = start + length;
8000
8001 if (end < start)
8002 end = start;
8003 else if (end > top_range && ! dragging)
8004 end = top_range;
8005 }
f451eb13 8006
ab648270 8007 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8008 XSETINT (bar->start, start);
8009 XSETINT (bar->end, end);
f451eb13 8010
12ba150f
JB
8011 /* Clip the end position, just for display. */
8012 if (end > top_range)
8013 end = top_range;
f451eb13 8014
ab648270 8015 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8016 below top positions, to make sure the handle is always at least
8017 that many pixels tall. */
ab648270 8018 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8019
12ba150f
JB
8020 /* Draw the empty space above the handle. Note that we can't clear
8021 zero-height areas; that means "clear to end of window." */
8022 if (0 < start)
334208b7 8023 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8024
12ba150f 8025 /* x, y, width, height, and exposures. */
ab648270
JB
8026 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8027 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8028 inside_width, start,
8029 False);
f451eb13 8030
06a2c219
GM
8031 /* Change to proper foreground color if one is specified. */
8032 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8033 XSetForeground (FRAME_X_DISPLAY (f), gc,
8034 f->output_data.x->scroll_bar_foreground_pixel);
8035
12ba150f 8036 /* Draw the handle itself. */
334208b7 8037 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8038
12ba150f 8039 /* x, y, width, height */
ab648270
JB
8040 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8041 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8042 inside_width, end - start);
f451eb13 8043
06a2c219
GM
8044 /* Restore the foreground color of the GC if we changed it above. */
8045 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8046 XSetForeground (FRAME_X_DISPLAY (f), gc,
8047 f->output_data.x->foreground_pixel);
f451eb13 8048
12ba150f
JB
8049 /* Draw the empty space below the handle. Note that we can't
8050 clear zero-height areas; that means "clear to end of window." */
8051 if (end < inside_height)
334208b7 8052 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8053
12ba150f 8054 /* x, y, width, height, and exposures. */
ab648270
JB
8055 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8056 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8057 inside_width, inside_height - end,
8058 False);
f451eb13 8059
f451eb13
JB
8060 }
8061
f451eb13
JB
8062 UNBLOCK_INPUT;
8063}
8064
5c187dee 8065#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8066
06a2c219
GM
8067/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8068 nil. */
58769bee 8069
12ba150f 8070static void
ab648270
JB
8071x_scroll_bar_remove (bar)
8072 struct scroll_bar *bar;
12ba150f 8073{
12ba150f
JB
8074 BLOCK_INPUT;
8075
06a2c219
GM
8076#if USE_TOOLKIT_SCROLL_BARS
8077 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8078#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8079 {
8080 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8081 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8082 }
06a2c219
GM
8083#endif /* not USE_TOOLKIT_SCROLL_BARS */
8084
ab648270
JB
8085 /* Disassociate this scroll bar from its window. */
8086 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8087
8088 UNBLOCK_INPUT;
8089}
8090
06a2c219 8091
12ba150f
JB
8092/* Set the handle of the vertical scroll bar for WINDOW to indicate
8093 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8094 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8095 create one. */
06a2c219 8096
12ba150f 8097static void
06a2c219
GM
8098XTset_vertical_scroll_bar (w, portion, whole, position)
8099 struct window *w;
f451eb13
JB
8100 int portion, whole, position;
8101{
06a2c219 8102 struct frame *f = XFRAME (w->frame);
ab648270 8103 struct scroll_bar *bar;
3c6ede7b 8104 int top, height, left, sb_left, width, sb_width;
06a2c219 8105 int window_x, window_y, window_width, window_height;
06a2c219 8106
3c6ede7b 8107 /* Get window dimensions. */
06a2c219 8108 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8109 top = window_y;
8110 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8111 height = window_height;
06a2c219 8112
3c6ede7b 8113 /* Compute the left edge of the scroll bar area. */
06a2c219 8114 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8115 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8116 else
8117 left = XFASTINT (w->left);
8118 left *= CANON_X_UNIT (f);
8119 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8120
8121 /* Compute the width of the scroll bar which might be less than
8122 the width of the area reserved for the scroll bar. */
8123 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8124 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8125 else
3c6ede7b 8126 sb_width = width;
12ba150f 8127
3c6ede7b
GM
8128 /* Compute the left edge of the scroll bar. */
8129#ifdef USE_TOOLKIT_SCROLL_BARS
8130 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8131 sb_left = left + width - sb_width - (width - sb_width) / 2;
8132 else
8133 sb_left = left + (width - sb_width) / 2;
8134#else
8135 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8136 sb_left = left + width - sb_width;
8137 else
8138 sb_left = left;
8139#endif
8140
ab648270 8141 /* Does the scroll bar exist yet? */
06a2c219 8142 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8143 {
80c32bcc 8144 BLOCK_INPUT;
3c6ede7b
GM
8145 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8146 left, top, width, height, False);
80c32bcc 8147 UNBLOCK_INPUT;
3c6ede7b
GM
8148 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8149 }
f451eb13 8150 else
12ba150f
JB
8151 {
8152 /* It may just need to be moved and resized. */
06a2c219
GM
8153 unsigned int mask = 0;
8154
8155 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8156
8157 BLOCK_INPUT;
8158
3c6ede7b 8159 if (sb_left != XINT (bar->left))
06a2c219 8160 mask |= CWX;
3c6ede7b 8161 if (top != XINT (bar->top))
06a2c219 8162 mask |= CWY;
3c6ede7b 8163 if (sb_width != XINT (bar->width))
06a2c219 8164 mask |= CWWidth;
3c6ede7b 8165 if (height != XINT (bar->height))
06a2c219
GM
8166 mask |= CWHeight;
8167
8168#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8169
8170 /* Since toolkit scroll bars are smaller than the space reserved
8171 for them on the frame, we have to clear "under" them. */
8172 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8173 left, top, width, height, False);
06a2c219
GM
8174
8175 /* Move/size the scroll bar widget. */
8176 if (mask)
8177 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8178 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8179 top,
8180 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8181 height, 0);
06a2c219
GM
8182
8183#else /* not USE_TOOLKIT_SCROLL_BARS */
8184
e1f6572f
RS
8185 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8186 {
8187 /* Clear areas not covered by the scroll bar. This makes sure a
8188 previous mode line display is cleared after C-x 2 C-x 1, for
8189 example. Non-toolkit scroll bars are as wide as the area
8190 reserved for scroll bars - trim at both sides. */
8191 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8192 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8193 height, False);
8194 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8195 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8196 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8197 height, False);
8198 }
06a2c219
GM
8199
8200 /* Move/size the scroll bar window. */
8201 if (mask)
8202 {
8203 XWindowChanges wc;
8204
3c6ede7b
GM
8205 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8206 wc.y = top;
8207 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8208 wc.height = height;
06a2c219
GM
8209 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8210 mask, &wc);
8211 }
8212
8213#endif /* not USE_TOOLKIT_SCROLL_BARS */
8214
8215 /* Remember new settings. */
3c6ede7b
GM
8216 XSETINT (bar->left, sb_left);
8217 XSETINT (bar->top, top);
8218 XSETINT (bar->width, sb_width);
8219 XSETINT (bar->height, height);
06a2c219
GM
8220
8221 UNBLOCK_INPUT;
12ba150f 8222 }
f451eb13 8223
06a2c219
GM
8224#if USE_TOOLKIT_SCROLL_BARS
8225 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8226#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8227 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8228 dragged. */
12ba150f 8229 if (NILP (bar->dragging))
f451eb13 8230 {
92857db0 8231 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8232
12ba150f 8233 if (whole == 0)
ab648270 8234 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8235 else
8236 {
43f868f5
JB
8237 int start = ((double) position * top_range) / whole;
8238 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8239 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8240 }
f451eb13 8241 }
06a2c219 8242#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8243
06a2c219 8244 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8245}
8246
12ba150f 8247
f451eb13 8248/* The following three hooks are used when we're doing a thorough
ab648270 8249 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8250 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8251 away is a real pain - "Can you say set-window-configuration, boys
8252 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8253 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8254 from the fiery pit when we actually redisplay its window. */
f451eb13 8255
ab648270
JB
8256/* Arrange for all scroll bars on FRAME to be removed at the next call
8257 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8258 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8259
58769bee 8260static void
ab648270 8261XTcondemn_scroll_bars (frame)
f451eb13
JB
8262 FRAME_PTR frame;
8263{
f9e24cb9
RS
8264 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8265 while (! NILP (FRAME_SCROLL_BARS (frame)))
8266 {
8267 Lisp_Object bar;
8268 bar = FRAME_SCROLL_BARS (frame);
8269 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8270 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8271 XSCROLL_BAR (bar)->prev = Qnil;
8272 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8273 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8274 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8275 }
f451eb13
JB
8276}
8277
06a2c219 8278/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8279 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 8280static void
ab648270 8281XTredeem_scroll_bar (window)
12ba150f 8282 struct window *window;
f451eb13 8283{
ab648270 8284 struct scroll_bar *bar;
12ba150f 8285
ab648270
JB
8286 /* We can't redeem this window's scroll bar if it doesn't have one. */
8287 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8288 abort ();
8289
ab648270 8290 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8291
8292 /* Unlink it from the condemned list. */
8293 {
8294 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8295
8296 if (NILP (bar->prev))
8297 {
8298 /* If the prev pointer is nil, it must be the first in one of
8299 the lists. */
ab648270 8300 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
8301 /* It's not condemned. Everything's fine. */
8302 return;
ab648270
JB
8303 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8304 window->vertical_scroll_bar))
8305 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
8306 else
8307 /* If its prev pointer is nil, it must be at the front of
8308 one or the other! */
8309 abort ();
8310 }
8311 else
ab648270 8312 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
8313
8314 if (! NILP (bar->next))
ab648270 8315 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8316
ab648270 8317 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8318 bar->prev = Qnil;
e0c1aef2 8319 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 8320 if (! NILP (bar->next))
e0c1aef2 8321 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 8322 }
f451eb13
JB
8323}
8324
ab648270
JB
8325/* Remove all scroll bars on FRAME that haven't been saved since the
8326 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8327
f451eb13 8328static void
ab648270 8329XTjudge_scroll_bars (f)
12ba150f 8330 FRAME_PTR f;
f451eb13 8331{
12ba150f 8332 Lisp_Object bar, next;
f451eb13 8333
ab648270 8334 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8335
8336 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8337 more events on the hapless scroll bars. */
8338 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8339
8340 for (; ! NILP (bar); bar = next)
f451eb13 8341 {
ab648270 8342 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8343
ab648270 8344 x_scroll_bar_remove (b);
12ba150f
JB
8345
8346 next = b->next;
8347 b->next = b->prev = Qnil;
f451eb13 8348 }
12ba150f 8349
ab648270 8350 /* Now there should be no references to the condemned scroll bars,
12ba150f 8351 and they should get garbage-collected. */
f451eb13
JB
8352}
8353
8354
06a2c219
GM
8355/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8356 is a no-op when using toolkit scroll bars.
ab648270
JB
8357
8358 This may be called from a signal handler, so we have to ignore GC
8359 mark bits. */
06a2c219 8360
f451eb13 8361static void
ab648270
JB
8362x_scroll_bar_expose (bar, event)
8363 struct scroll_bar *bar;
f451eb13
JB
8364 XEvent *event;
8365{
06a2c219
GM
8366#ifndef USE_TOOLKIT_SCROLL_BARS
8367
ab648270 8368 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8369 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8370 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8371 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8372
f451eb13
JB
8373 BLOCK_INPUT;
8374
ab648270 8375 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8376
06a2c219 8377 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8378 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8379
8380 /* x, y, width, height */
d9cdbb3d 8381 0, 0,
3cbd2e0b 8382 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8383 XINT (bar->height) - 1);
8384
f451eb13 8385 UNBLOCK_INPUT;
06a2c219
GM
8386
8387#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8388}
8389
ab648270
JB
8390/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8391 is set to something other than no_event, it is enqueued.
8392
8393 This may be called from a signal handler, so we have to ignore GC
8394 mark bits. */
06a2c219 8395
5c187dee
GM
8396#ifndef USE_TOOLKIT_SCROLL_BARS
8397
f451eb13 8398static void
ab648270
JB
8399x_scroll_bar_handle_click (bar, event, emacs_event)
8400 struct scroll_bar *bar;
f451eb13
JB
8401 XEvent *event;
8402 struct input_event *emacs_event;
8403{
0299d313 8404 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8405 abort ();
8406
ab648270 8407 emacs_event->kind = scroll_bar_click;
69388238 8408 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8409 emacs_event->modifiers
8410 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8411 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8412 event->xbutton.state)
8413 | (event->type == ButtonRelease
8414 ? up_modifier
8415 : down_modifier));
12ba150f 8416 emacs_event->frame_or_window = bar->window;
f451eb13 8417 emacs_event->timestamp = event->xbutton.time;
12ba150f 8418 {
06a2c219 8419#if 0
d9cdbb3d 8420 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8421 int internal_height
d9cdbb3d 8422 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8423#endif
0299d313 8424 int top_range
d9cdbb3d 8425 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8426 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8427
8428 if (y < 0) y = 0;
8429 if (y > top_range) y = top_range;
8430
8431 if (y < XINT (bar->start))
ab648270
JB
8432 emacs_event->part = scroll_bar_above_handle;
8433 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8434 emacs_event->part = scroll_bar_handle;
12ba150f 8435 else
ab648270 8436 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8437
8438 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8439 they want to drag it. Lisp code needs to be able to decide
8440 whether or not we're dragging. */
929787e1 8441#if 0
12ba150f
JB
8442 /* If the user has just clicked on the handle, record where they're
8443 holding it. */
8444 if (event->type == ButtonPress
ab648270 8445 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8446 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8447#endif
12ba150f
JB
8448
8449 /* If the user has released the handle, set it to its final position. */
8450 if (event->type == ButtonRelease
8451 && ! NILP (bar->dragging))
8452 {
8453 int new_start = y - XINT (bar->dragging);
8454 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8455
ab648270 8456 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8457 bar->dragging = Qnil;
8458 }
f451eb13 8459
5116f055
JB
8460 /* Same deal here as the other #if 0. */
8461#if 0
58769bee 8462 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8463 the handle. */
ab648270 8464 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8465 emacs_event->x = bar->start;
8466 else
e0c1aef2 8467 XSETINT (emacs_event->x, y);
5116f055 8468#else
e0c1aef2 8469 XSETINT (emacs_event->x, y);
5116f055 8470#endif
f451eb13 8471
e0c1aef2 8472 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8473 }
8474}
f451eb13 8475
ab648270
JB
8476/* Handle some mouse motion while someone is dragging the scroll bar.
8477
8478 This may be called from a signal handler, so we have to ignore GC
8479 mark bits. */
06a2c219 8480
f451eb13 8481static void
ab648270
JB
8482x_scroll_bar_note_movement (bar, event)
8483 struct scroll_bar *bar;
f451eb13
JB
8484 XEvent *event;
8485{
39d8bb4d
KH
8486 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8487
f451eb13
JB
8488 last_mouse_movement_time = event->xmotion.time;
8489
39d8bb4d 8490 f->mouse_moved = 1;
e0c1aef2 8491 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8492
8493 /* If we're dragging the bar, display it. */
ab648270 8494 if (! GC_NILP (bar->dragging))
f451eb13
JB
8495 {
8496 /* Where should the handle be now? */
12ba150f 8497 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8498
12ba150f 8499 if (new_start != XINT (bar->start))
f451eb13 8500 {
12ba150f 8501 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8502
ab648270 8503 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8504 }
8505 }
f451eb13
JB
8506}
8507
5c187dee
GM
8508#endif /* !USE_TOOLKIT_SCROLL_BARS */
8509
12ba150f 8510/* Return information to the user about the current position of the mouse
ab648270 8511 on the scroll bar. */
06a2c219 8512
12ba150f 8513static void
334208b7
RS
8514x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8515 FRAME_PTR *fp;
12ba150f 8516 Lisp_Object *bar_window;
ab648270 8517 enum scroll_bar_part *part;
12ba150f
JB
8518 Lisp_Object *x, *y;
8519 unsigned long *time;
8520{
ab648270 8521 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8522 Window w = SCROLL_BAR_X_WINDOW (bar);
8523 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8524 int win_x, win_y;
559cb2fb
JB
8525 Window dummy_window;
8526 int dummy_coord;
8527 unsigned int dummy_mask;
12ba150f 8528
cf7cb199
JB
8529 BLOCK_INPUT;
8530
ab648270 8531 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8532 report that. */
334208b7 8533 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8534
559cb2fb
JB
8535 /* Root, child, root x and root y. */
8536 &dummy_window, &dummy_window,
8537 &dummy_coord, &dummy_coord,
12ba150f 8538
559cb2fb
JB
8539 /* Position relative to scroll bar. */
8540 &win_x, &win_y,
12ba150f 8541
559cb2fb
JB
8542 /* Mouse buttons and modifier keys. */
8543 &dummy_mask))
7a13e894 8544 ;
559cb2fb
JB
8545 else
8546 {
06a2c219 8547#if 0
559cb2fb 8548 int inside_height
d9cdbb3d 8549 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8550#endif
559cb2fb 8551 int top_range
d9cdbb3d 8552 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8553
8554 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8555
8556 if (! NILP (bar->dragging))
8557 win_y -= XINT (bar->dragging);
8558
8559 if (win_y < 0)
8560 win_y = 0;
8561 if (win_y > top_range)
8562 win_y = top_range;
8563
334208b7 8564 *fp = f;
7a13e894 8565 *bar_window = bar->window;
559cb2fb
JB
8566
8567 if (! NILP (bar->dragging))
8568 *part = scroll_bar_handle;
8569 else if (win_y < XINT (bar->start))
8570 *part = scroll_bar_above_handle;
8571 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8572 *part = scroll_bar_handle;
8573 else
8574 *part = scroll_bar_below_handle;
12ba150f 8575
e0c1aef2
KH
8576 XSETINT (*x, win_y);
8577 XSETINT (*y, top_range);
12ba150f 8578
39d8bb4d 8579 f->mouse_moved = 0;
559cb2fb
JB
8580 last_mouse_scroll_bar = Qnil;
8581 }
12ba150f 8582
559cb2fb 8583 *time = last_mouse_movement_time;
cf7cb199 8584
cf7cb199 8585 UNBLOCK_INPUT;
12ba150f
JB
8586}
8587
f451eb13 8588
dbc4e1c1 8589/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8590 background colors, and the scroll bars may need to be redrawn.
8591 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8592 redraw them. */
8593
dfcf069d 8594void
ab648270 8595x_scroll_bar_clear (f)
dbc4e1c1
JB
8596 FRAME_PTR f;
8597{
06a2c219 8598#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8599 Lisp_Object bar;
8600
b80c363e
RS
8601 /* We can have scroll bars even if this is 0,
8602 if we just turned off scroll bar mode.
8603 But in that case we should not clear them. */
8604 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8605 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8606 bar = XSCROLL_BAR (bar)->next)
8607 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8608 0, 0, 0, 0, True);
06a2c219 8609#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8610}
8611
06a2c219 8612/* This processes Expose events from the menu-bar specific X event
19126e11 8613 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8614 when handling menu-bar or pop-up items. */
3afe33e7 8615
06a2c219 8616int
3afe33e7
RS
8617process_expose_from_menu (event)
8618 XEvent event;
8619{
8620 FRAME_PTR f;
19126e11 8621 struct x_display_info *dpyinfo;
06a2c219 8622 int frame_exposed_p = 0;
3afe33e7 8623
f94397b5
KH
8624 BLOCK_INPUT;
8625
19126e11
KH
8626 dpyinfo = x_display_info_for_display (event.xexpose.display);
8627 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8628 if (f)
8629 {
8630 if (f->async_visible == 0)
8631 {
8632 f->async_visible = 1;
8633 f->async_iconified = 0;
06c488fd 8634 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8635 SET_FRAME_GARBAGED (f);
8636 }
8637 else
8638 {
06a2c219
GM
8639 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8640 event.xexpose.x, event.xexpose.y,
8641 event.xexpose.width, event.xexpose.height);
8642 frame_exposed_p = 1;
3afe33e7
RS
8643 }
8644 }
8645 else
8646 {
8647 struct scroll_bar *bar
8648 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8649
3afe33e7
RS
8650 if (bar)
8651 x_scroll_bar_expose (bar, &event);
8652 }
f94397b5
KH
8653
8654 UNBLOCK_INPUT;
06a2c219 8655 return frame_exposed_p;
3afe33e7 8656}
09756a85
RS
8657\f
8658/* Define a queue to save up SelectionRequest events for later handling. */
8659
8660struct selection_event_queue
8661 {
8662 XEvent event;
8663 struct selection_event_queue *next;
8664 };
8665
8666static struct selection_event_queue *queue;
8667
8668/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8669
09756a85
RS
8670static int x_queue_selection_requests;
8671
8672/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8673
09756a85 8674static void
334208b7
RS
8675x_queue_event (f, event)
8676 FRAME_PTR f;
09756a85
RS
8677 XEvent *event;
8678{
8679 struct selection_event_queue *queue_tmp
06a2c219 8680 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8681
58769bee 8682 if (queue_tmp != NULL)
09756a85
RS
8683 {
8684 queue_tmp->event = *event;
8685 queue_tmp->next = queue;
8686 queue = queue_tmp;
8687 }
8688}
8689
8690/* Take all the queued events and put them back
8691 so that they get processed afresh. */
8692
8693static void
db3906fd
RS
8694x_unqueue_events (display)
8695 Display *display;
09756a85 8696{
58769bee 8697 while (queue != NULL)
09756a85
RS
8698 {
8699 struct selection_event_queue *queue_tmp = queue;
db3906fd 8700 XPutBackEvent (display, &queue_tmp->event);
09756a85 8701 queue = queue_tmp->next;
06a2c219 8702 xfree ((char *)queue_tmp);
09756a85
RS
8703 }
8704}
8705
8706/* Start queuing SelectionRequest events. */
8707
8708void
db3906fd
RS
8709x_start_queuing_selection_requests (display)
8710 Display *display;
09756a85
RS
8711{
8712 x_queue_selection_requests++;
8713}
8714
8715/* Stop queuing SelectionRequest events. */
8716
8717void
db3906fd
RS
8718x_stop_queuing_selection_requests (display)
8719 Display *display;
09756a85
RS
8720{
8721 x_queue_selection_requests--;
db3906fd 8722 x_unqueue_events (display);
09756a85 8723}
f451eb13
JB
8724\f
8725/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8726
06a2c219 8727/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8728 but we have to put it out here, since static variables within functions
8729 sometimes don't work. */
06a2c219 8730
dc6f92b8
JB
8731static Time enter_timestamp;
8732
11edeb03 8733/* This holds the state XLookupString needs to implement dead keys
58769bee 8734 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8735 says that a portable program can't use this, but Stephen Gildea assures
8736 me that letting the compiler initialize it to zeros will work okay.
8737
8738 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8739 given for enter_time stamp, above. */
8740
11edeb03
JB
8741static XComposeStatus compose_status;
8742
10e6549c
RS
8743/* Record the last 100 characters stored
8744 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8745
2224b905
RS
8746static int temp_index;
8747static short temp_buffer[100];
10e6549c 8748
7a13e894
RS
8749/* Set this to nonzero to fake an "X I/O error"
8750 on a particular display. */
06a2c219 8751
7a13e894
RS
8752struct x_display_info *XTread_socket_fake_io_error;
8753
2224b905
RS
8754/* When we find no input here, we occasionally do a no-op command
8755 to verify that the X server is still running and we can still talk with it.
8756 We try all the open displays, one by one.
8757 This variable is used for cycling thru the displays. */
06a2c219 8758
2224b905
RS
8759static struct x_display_info *next_noop_dpyinfo;
8760
06a2c219
GM
8761#define SET_SAVED_MENU_EVENT(size) \
8762 do \
8763 { \
8764 if (f->output_data.x->saved_menu_event == 0) \
8765 f->output_data.x->saved_menu_event \
8766 = (XEvent *) xmalloc (sizeof (XEvent)); \
8767 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8768 if (numchars >= 1) \
8769 { \
8770 bufp->kind = menu_bar_activate_event; \
8771 XSETFRAME (bufp->frame_or_window, f); \
8772 bufp++; \
8773 count++; \
8774 numchars--; \
8775 } \
8776 } \
8777 while (0)
8778
8805890a 8779#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 8780#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 8781
dc6f92b8
JB
8782/* Read events coming from the X server.
8783 This routine is called by the SIGIO handler.
8784 We return as soon as there are no more events to be read.
8785
8786 Events representing keys are stored in buffer BUFP,
8787 which can hold up to NUMCHARS characters.
8788 We return the number of characters stored into the buffer,
8789 thus pretending to be `read'.
8790
dc6f92b8
JB
8791 EXPECTED is nonzero if the caller knows input is available. */
8792
7c5283e4 8793int
f66868ba 8794XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 8795 register int sd;
8805890a
KH
8796 /* register */ struct input_event *bufp;
8797 /* register */ int numchars;
dc6f92b8
JB
8798 int expected;
8799{
8800 int count = 0;
8801 int nbytes = 0;
dc6f92b8 8802 XEvent event;
f676886a 8803 struct frame *f;
66f55a9d 8804 int event_found = 0;
334208b7 8805 struct x_display_info *dpyinfo;
dc6f92b8 8806
9ac0d9e0 8807 if (interrupt_input_blocked)
dc6f92b8 8808 {
9ac0d9e0 8809 interrupt_input_pending = 1;
dc6f92b8
JB
8810 return -1;
8811 }
8812
9ac0d9e0 8813 interrupt_input_pending = 0;
dc6f92b8 8814 BLOCK_INPUT;
c0a04927
RS
8815
8816 /* So people can tell when we have read the available input. */
8817 input_signal_count++;
8818
dc6f92b8 8819 if (numchars <= 0)
06a2c219 8820 abort (); /* Don't think this happens. */
dc6f92b8 8821
7a13e894
RS
8822 /* Find the display we are supposed to read input for.
8823 It's the one communicating on descriptor SD. */
8824 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8825 {
8826#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 8827#ifdef FIOSNBIO
7a13e894
RS
8828 /* If available, Xlib uses FIOSNBIO to make the socket
8829 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 8830 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 8831 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 8832 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 8833#endif /* ! defined (FIOSNBIO) */
7a13e894 8834#endif
dc6f92b8 8835
7a13e894
RS
8836#if 0 /* This code can't be made to work, with multiple displays,
8837 and appears not to be used on any system any more.
8838 Also keyboard.c doesn't turn O_NDELAY on and off
8839 for X connections. */
dc6f92b8
JB
8840#ifndef SIGIO
8841#ifndef HAVE_SELECT
7a13e894
RS
8842 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8843 {
8844 extern int read_alarm_should_throw;
8845 read_alarm_should_throw = 1;
8846 XPeekEvent (dpyinfo->display, &event);
8847 read_alarm_should_throw = 0;
8848 }
c118dd06
JB
8849#endif /* HAVE_SELECT */
8850#endif /* SIGIO */
7a13e894 8851#endif
dc6f92b8 8852
7a13e894
RS
8853 /* For debugging, this gives a way to fake an I/O error. */
8854 if (dpyinfo == XTread_socket_fake_io_error)
8855 {
8856 XTread_socket_fake_io_error = 0;
8857 x_io_error_quitter (dpyinfo->display);
8858 }
dc6f92b8 8859
06a2c219 8860 while (XPending (dpyinfo->display))
dc6f92b8 8861 {
7a13e894 8862 XNextEvent (dpyinfo->display, &event);
06a2c219 8863
531483fb 8864#ifdef HAVE_X_I18N
d1bc4182 8865 {
f2be1146
GM
8866 /* Filter events for the current X input method.
8867 XFilterEvent returns non-zero if the input method has
8868 consumed the event. We pass the frame's X window to
8869 XFilterEvent because that's the one for which the IC
8870 was created. */
f5d11644
GM
8871 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8872 event.xclient.window);
8873 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
8874 break;
8875 }
0cd6403b 8876#endif
7a13e894
RS
8877 event_found = 1;
8878
8879 switch (event.type)
8880 {
8881 case ClientMessage:
c047688c 8882 {
7a13e894
RS
8883 if (event.xclient.message_type
8884 == dpyinfo->Xatom_wm_protocols
8885 && event.xclient.format == 32)
c047688c 8886 {
7a13e894
RS
8887 if (event.xclient.data.l[0]
8888 == dpyinfo->Xatom_wm_take_focus)
c047688c 8889 {
8c1a6a84
RS
8890 /* Use x_any_window_to_frame because this
8891 could be the shell widget window
8892 if the frame has no title bar. */
8893 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
8894#ifdef HAVE_X_I18N
8895 /* Not quite sure this is needed -pd */
8c1a6a84 8896 if (f && FRAME_XIC (f))
6c183ba5
RS
8897 XSetICFocus (FRAME_XIC (f));
8898#endif
f1da8f06
GM
8899#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
8900 instructs the WM to set the input focus automatically for
8901 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
8902 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
8903 it has set the focus. So, XSetInputFocus below is not
8904 needed.
8905
8906 The call to XSetInputFocus below has also caused trouble. In
8907 cases where the XSetInputFocus done by the WM and the one
8908 below are temporally close (on a fast machine), the call
8909 below can generate additional FocusIn events which confuse
8910 Emacs. */
8911
bf7253f4
RS
8912 /* Since we set WM_TAKE_FOCUS, we must call
8913 XSetInputFocus explicitly. But not if f is null,
8914 since that might be an event for a deleted frame. */
7a13e894 8915 if (f)
bf7253f4
RS
8916 {
8917 Display *d = event.xclient.display;
8918 /* Catch and ignore errors, in case window has been
8919 iconified by a window manager such as GWM. */
8920 int count = x_catch_errors (d);
8921 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
8922 /* The ICCCM says this is
8923 the only valid choice. */
8924 RevertToParent,
bf7253f4
RS
8925 event.xclient.data.l[1]);
8926 /* This is needed to detect the error
8927 if there is an error. */
8928 XSync (d, False);
8929 x_uncatch_errors (d, count);
8930 }
7a13e894 8931 /* Not certain about handling scroll bars here */
f1da8f06 8932#endif /* 0 */
c047688c 8933 }
7a13e894
RS
8934 else if (event.xclient.data.l[0]
8935 == dpyinfo->Xatom_wm_save_yourself)
8936 {
8937 /* Save state modify the WM_COMMAND property to
06a2c219 8938 something which can reinstate us. This notifies
7a13e894
RS
8939 the session manager, who's looking for such a
8940 PropertyNotify. Can restart processing when
06a2c219 8941 a keyboard or mouse event arrives. */
7a13e894
RS
8942 if (numchars > 0)
8943 {
19126e11
KH
8944 f = x_top_window_to_frame (dpyinfo,
8945 event.xclient.window);
7a13e894
RS
8946
8947 /* This is just so we only give real data once
8948 for a single Emacs process. */
b86bd3dd 8949 if (f == SELECTED_FRAME ())
7a13e894
RS
8950 XSetCommand (FRAME_X_DISPLAY (f),
8951 event.xclient.window,
8952 initial_argv, initial_argc);
f000f5c5 8953 else if (f)
7a13e894
RS
8954 XSetCommand (FRAME_X_DISPLAY (f),
8955 event.xclient.window,
8956 0, 0);
8957 }
8958 }
8959 else if (event.xclient.data.l[0]
8960 == dpyinfo->Xatom_wm_delete_window)
1fb20991 8961 {
19126e11
KH
8962 struct frame *f
8963 = x_any_window_to_frame (dpyinfo,
8964 event.xclient.window);
1fb20991 8965
7a13e894
RS
8966 if (f)
8967 {
8968 if (numchars == 0)
8969 abort ();
1fb20991 8970
7a13e894
RS
8971 bufp->kind = delete_window_event;
8972 XSETFRAME (bufp->frame_or_window, f);
8973 bufp++;
8974
8975 count += 1;
8976 numchars -= 1;
8977 }
1fb20991 8978 }
c047688c 8979 }
7a13e894
RS
8980 else if (event.xclient.message_type
8981 == dpyinfo->Xatom_wm_configure_denied)
8982 {
8983 }
8984 else if (event.xclient.message_type
8985 == dpyinfo->Xatom_wm_window_moved)
8986 {
8987 int new_x, new_y;
19126e11
KH
8988 struct frame *f
8989 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 8990
7a13e894
RS
8991 new_x = event.xclient.data.s[0];
8992 new_y = event.xclient.data.s[1];
1fb20991 8993
7a13e894
RS
8994 if (f)
8995 {
7556890b
RS
8996 f->output_data.x->left_pos = new_x;
8997 f->output_data.x->top_pos = new_y;
7a13e894 8998 }
1fb20991 8999 }
0fdff6bb 9000#ifdef HACK_EDITRES
7a13e894
RS
9001 else if (event.xclient.message_type
9002 == dpyinfo->Xatom_editres)
9003 {
19126e11
KH
9004 struct frame *f
9005 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9006 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9007 &event, NULL);
7a13e894 9008 }
0fdff6bb 9009#endif /* HACK_EDITRES */
06a2c219
GM
9010 else if ((event.xclient.message_type
9011 == dpyinfo->Xatom_DONE)
9012 || (event.xclient.message_type
9013 == dpyinfo->Xatom_PAGE))
9014 {
9015 /* Ghostview job completed. Kill it. We could
9016 reply with "Next" if we received "Page", but we
9017 currently never do because we are interested in
9018 images, only, which should have 1 page. */
06a2c219
GM
9019 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9020 struct frame *f
9021 = x_window_to_frame (dpyinfo, event.xclient.window);
9022 x_kill_gs_process (pixmap, f);
9023 expose_frame (f, 0, 0, 0, 0);
9024 }
9025#ifdef USE_TOOLKIT_SCROLL_BARS
9026 /* Scroll bar callbacks send a ClientMessage from which
9027 we construct an input_event. */
9028 else if (event.xclient.message_type
9029 == dpyinfo->Xatom_Scrollbar)
9030 {
9031 x_scroll_bar_to_input_event (&event, bufp);
9032 ++bufp, ++count, --numchars;
9033 goto out;
9034 }
9035#endif /* USE_TOOLKIT_SCROLL_BARS */
9036 else
9037 goto OTHER;
7a13e894
RS
9038 }
9039 break;
dc6f92b8 9040
7a13e894 9041 case SelectionNotify:
3afe33e7 9042#ifdef USE_X_TOOLKIT
19126e11 9043 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9044 goto OTHER;
3afe33e7 9045#endif /* not USE_X_TOOLKIT */
dfcf069d 9046 x_handle_selection_notify (&event.xselection);
7a13e894 9047 break;
d56a553a 9048
06a2c219 9049 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9050#ifdef USE_X_TOOLKIT
19126e11 9051 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9052 goto OTHER;
3afe33e7 9053#endif /* USE_X_TOOLKIT */
7a13e894
RS
9054 {
9055 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9056
7a13e894
RS
9057 if (numchars == 0)
9058 abort ();
d56a553a 9059
7a13e894
RS
9060 bufp->kind = selection_clear_event;
9061 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9062 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9063 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9064 bufp->frame_or_window = Qnil;
7a13e894 9065 bufp++;
d56a553a 9066
7a13e894
RS
9067 count += 1;
9068 numchars -= 1;
9069 }
9070 break;
dc6f92b8 9071
06a2c219 9072 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9073#ifdef USE_X_TOOLKIT
19126e11 9074 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9075 goto OTHER;
3afe33e7 9076#endif /* USE_X_TOOLKIT */
7a13e894 9077 if (x_queue_selection_requests)
19126e11 9078 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9079 &event);
9080 else
9081 {
9082 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9083
7a13e894
RS
9084 if (numchars == 0)
9085 abort ();
9086
9087 bufp->kind = selection_request_event;
9088 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9089 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9090 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9091 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9092 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9093 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9094 bufp->frame_or_window = Qnil;
7a13e894
RS
9095 bufp++;
9096
9097 count += 1;
9098 numchars -= 1;
9099 }
9100 break;
9101
9102 case PropertyNotify:
3afe33e7 9103#ifdef USE_X_TOOLKIT
19126e11 9104 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9105 goto OTHER;
3afe33e7 9106#endif /* not USE_X_TOOLKIT */
dfcf069d 9107 x_handle_property_notify (&event.xproperty);
7a13e894 9108 break;
dc6f92b8 9109
7a13e894 9110 case ReparentNotify:
19126e11 9111 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9112 if (f)
9113 {
9114 int x, y;
7556890b 9115 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9116 x_real_positions (f, &x, &y);
7556890b
RS
9117 f->output_data.x->left_pos = x;
9118 f->output_data.x->top_pos = y;
7a13e894
RS
9119 }
9120 break;
3bd330d4 9121
7a13e894 9122 case Expose:
19126e11 9123 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9124 if (f)
dc6f92b8 9125 {
7a13e894
RS
9126 if (f->async_visible == 0)
9127 {
9128 f->async_visible = 1;
9129 f->async_iconified = 0;
06c488fd 9130 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9131 SET_FRAME_GARBAGED (f);
9132 }
9133 else
06a2c219
GM
9134 expose_frame (x_window_to_frame (dpyinfo,
9135 event.xexpose.window),
9136 event.xexpose.x, event.xexpose.y,
9137 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9138 }
9139 else
7a13e894 9140 {
06a2c219
GM
9141#ifdef USE_TOOLKIT_SCROLL_BARS
9142 /* Dispatch event to the widget. */
9143 goto OTHER;
9144#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9145 struct scroll_bar *bar
9146 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9147
7a13e894
RS
9148 if (bar)
9149 x_scroll_bar_expose (bar, &event);
3afe33e7 9150#ifdef USE_X_TOOLKIT
7a13e894
RS
9151 else
9152 goto OTHER;
3afe33e7 9153#endif /* USE_X_TOOLKIT */
06a2c219 9154#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9155 }
9156 break;
dc6f92b8 9157
7a13e894
RS
9158 case GraphicsExpose: /* This occurs when an XCopyArea's
9159 source area was obscured or not
9160 available.*/
19126e11 9161 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9162 if (f)
9163 {
06a2c219
GM
9164 expose_frame (f,
9165 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9166 event.xgraphicsexpose.width,
9167 event.xgraphicsexpose.height);
7a13e894 9168 }
3afe33e7 9169#ifdef USE_X_TOOLKIT
7a13e894
RS
9170 else
9171 goto OTHER;
3afe33e7 9172#endif /* USE_X_TOOLKIT */
7a13e894 9173 break;
dc6f92b8 9174
7a13e894 9175 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9176 source area was completely
9177 available */
7a13e894 9178 break;
dc6f92b8 9179
7a13e894 9180 case UnmapNotify:
06a2c219
GM
9181 /* Redo the mouse-highlight after the tooltip has gone. */
9182 if (event.xmap.window == tip_window)
9183 {
9184 tip_window = 0;
9185 redo_mouse_highlight ();
9186 }
9187
91ea2a7a 9188 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9189 if (f) /* F may no longer exist if
9190 the frame was deleted. */
9191 {
9192 /* While a frame is unmapped, display generation is
9193 disabled; you don't want to spend time updating a
9194 display that won't ever be seen. */
9195 f->async_visible = 0;
9196 /* We can't distinguish, from the event, whether the window
9197 has become iconified or invisible. So assume, if it
9198 was previously visible, than now it is iconified.
1aa6072f
RS
9199 But x_make_frame_invisible clears both
9200 the visible flag and the iconified flag;
9201 and that way, we know the window is not iconified now. */
7a13e894 9202 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9203 {
9204 f->async_iconified = 1;
bddd097c 9205
1aa6072f
RS
9206 bufp->kind = iconify_event;
9207 XSETFRAME (bufp->frame_or_window, f);
9208 bufp++;
9209 count++;
9210 numchars--;
9211 }
7a13e894 9212 }
7a13e894 9213 goto OTHER;
dc6f92b8 9214
7a13e894 9215 case MapNotify:
06a2c219
GM
9216 if (event.xmap.window == tip_window)
9217 /* The tooltip has been drawn already. Avoid
9218 the SET_FRAME_GARBAGED below. */
9219 goto OTHER;
9220
9221 /* We use x_top_window_to_frame because map events can
9222 come for sub-windows and they don't mean that the
9223 frame is visible. */
19126e11 9224 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9225 if (f)
9226 {
9227 f->async_visible = 1;
9228 f->async_iconified = 0;
06c488fd 9229 f->output_data.x->has_been_visible = 1;
dc6f92b8 9230
7a13e894
RS
9231 /* wait_reading_process_input will notice this and update
9232 the frame's display structures. */
9233 SET_FRAME_GARBAGED (f);
bddd097c 9234
d806e720
RS
9235 if (f->iconified)
9236 {
9237 bufp->kind = deiconify_event;
9238 XSETFRAME (bufp->frame_or_window, f);
9239 bufp++;
9240 count++;
9241 numchars--;
9242 }
e73ec6fa 9243 else if (! NILP (Vframe_list)
8e713be6 9244 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9245 /* Force a redisplay sooner or later
9246 to update the frame titles
9247 in case this is the second frame. */
9248 record_asynch_buffer_change ();
7a13e894 9249 }
7a13e894 9250 goto OTHER;
dc6f92b8 9251
7a13e894 9252 case KeyPress:
19126e11 9253 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9254
06a2c219
GM
9255#ifdef USE_MOTIF
9256 /* I couldn't find a way to prevent LessTif scroll bars
9257 from consuming key events. */
9258 if (f == 0)
9259 {
9260 Widget widget = XtWindowToWidget (dpyinfo->display,
9261 event.xkey.window);
9262 if (widget && XmIsScrollBar (widget))
9263 {
9264 widget = XtParent (widget);
9265 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9266 }
9267 }
9268#endif /* USE_MOTIF */
9269
7a13e894
RS
9270 if (f != 0)
9271 {
9272 KeySym keysym, orig_keysym;
9273 /* al%imercury@uunet.uu.net says that making this 81 instead of
9274 80 fixed a bug whereby meta chars made his Emacs hang. */
9275 unsigned char copy_buffer[81];
9276 int modifiers;
64bb1782 9277
7a13e894
RS
9278 event.xkey.state
9279 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9280 extra_keyboard_modifiers);
9281 modifiers = event.xkey.state;
3a2712f9 9282
7a13e894 9283 /* This will have to go some day... */
752a043f 9284
7a13e894
RS
9285 /* make_lispy_event turns chars into control chars.
9286 Don't do it here because XLookupString is too eager. */
9287 event.xkey.state &= ~ControlMask;
5d46f928
RS
9288 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9289 | dpyinfo->super_mod_mask
9290 | dpyinfo->hyper_mod_mask
9291 | dpyinfo->alt_mod_mask);
9292
1cf4a0d1
RS
9293 /* In case Meta is ComposeCharacter,
9294 clear its status. According to Markus Ehrnsperger
9295 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9296 this enables ComposeCharacter to work whether or
9297 not it is combined with Meta. */
9298 if (modifiers & dpyinfo->meta_mod_mask)
9299 bzero (&compose_status, sizeof (compose_status));
9300
6c183ba5
RS
9301#ifdef HAVE_X_I18N
9302 if (FRAME_XIC (f))
9303 {
f5d11644
GM
9304 unsigned char *copy_bufptr = copy_buffer;
9305 int copy_bufsiz = sizeof (copy_buffer);
9306 Status status_return;
9307
6c183ba5 9308 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9309 &event.xkey, copy_bufptr,
9310 copy_bufsiz, &keysym,
6c183ba5 9311 &status_return);
f5d11644
GM
9312 if (status_return == XBufferOverflow)
9313 {
9314 copy_bufsiz = nbytes + 1;
9315 copy_bufptr = (char *) alloca (copy_bufsiz);
9316 nbytes = XmbLookupString (FRAME_XIC (f),
9317 &event.xkey, copy_bufptr,
9318 copy_bufsiz, &keysym,
9319 &status_return);
9320 }
9321
1decb680
PE
9322 if (status_return == XLookupNone)
9323 break;
9324 else if (status_return == XLookupChars)
9325 keysym = NoSymbol;
9326 else if (status_return != XLookupKeySym
9327 && status_return != XLookupBoth)
9328 abort ();
6c183ba5
RS
9329 }
9330 else
9331 nbytes = XLookupString (&event.xkey, copy_buffer,
9332 80, &keysym, &compose_status);
9333#else
0299d313
RS
9334 nbytes = XLookupString (&event.xkey, copy_buffer,
9335 80, &keysym, &compose_status);
6c183ba5 9336#endif
dc6f92b8 9337
7a13e894 9338 orig_keysym = keysym;
55123275 9339
7a13e894
RS
9340 if (numchars > 1)
9341 {
9342 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9343 || keysym == XK_Delete
1097aea0 9344#ifdef XK_ISO_Left_Tab
441affdb 9345 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9346#endif
852bff8f 9347 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9348 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9349 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9350#ifdef HPUX
7a13e894
RS
9351 /* This recognizes the "extended function keys".
9352 It seems there's no cleaner way.
9353 Test IsModifierKey to avoid handling mode_switch
9354 incorrectly. */
9355 || ((unsigned) (keysym) >= XK_Select
9356 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9357#endif
9358#ifdef XK_dead_circumflex
7a13e894 9359 || orig_keysym == XK_dead_circumflex
69388238
RS
9360#endif
9361#ifdef XK_dead_grave
7a13e894 9362 || orig_keysym == XK_dead_grave
69388238
RS
9363#endif
9364#ifdef XK_dead_tilde
7a13e894 9365 || orig_keysym == XK_dead_tilde
69388238
RS
9366#endif
9367#ifdef XK_dead_diaeresis
7a13e894 9368 || orig_keysym == XK_dead_diaeresis
69388238
RS
9369#endif
9370#ifdef XK_dead_macron
7a13e894 9371 || orig_keysym == XK_dead_macron
69388238
RS
9372#endif
9373#ifdef XK_dead_degree
7a13e894 9374 || orig_keysym == XK_dead_degree
69388238
RS
9375#endif
9376#ifdef XK_dead_acute
7a13e894 9377 || orig_keysym == XK_dead_acute
69388238
RS
9378#endif
9379#ifdef XK_dead_cedilla
7a13e894 9380 || orig_keysym == XK_dead_cedilla
69388238
RS
9381#endif
9382#ifdef XK_dead_breve
7a13e894 9383 || orig_keysym == XK_dead_breve
69388238
RS
9384#endif
9385#ifdef XK_dead_ogonek
7a13e894 9386 || orig_keysym == XK_dead_ogonek
69388238
RS
9387#endif
9388#ifdef XK_dead_caron
7a13e894 9389 || orig_keysym == XK_dead_caron
69388238
RS
9390#endif
9391#ifdef XK_dead_doubleacute
7a13e894 9392 || orig_keysym == XK_dead_doubleacute
69388238
RS
9393#endif
9394#ifdef XK_dead_abovedot
7a13e894 9395 || orig_keysym == XK_dead_abovedot
c34790e0 9396#endif
7a13e894
RS
9397 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9398 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9399 /* Any "vendor-specific" key is ok. */
9400 || (orig_keysym & (1 << 28)))
9401 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9402#ifndef HAVE_X11R5
9403#ifdef XK_Mode_switch
7a13e894 9404 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9405#endif
9406#ifdef XK_Num_Lock
7a13e894 9407 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9408#endif
9409#endif /* not HAVE_X11R5 */
7a13e894 9410 ))
dc6f92b8 9411 {
10e6549c
RS
9412 if (temp_index == sizeof temp_buffer / sizeof (short))
9413 temp_index = 0;
7a13e894
RS
9414 temp_buffer[temp_index++] = keysym;
9415 bufp->kind = non_ascii_keystroke;
9416 bufp->code = keysym;
e0c1aef2 9417 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
9418 bufp->modifiers
9419 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9420 modifiers);
1113d9db 9421 bufp->timestamp = event.xkey.time;
dc6f92b8 9422 bufp++;
7a13e894
RS
9423 count++;
9424 numchars--;
dc6f92b8 9425 }
7a13e894
RS
9426 else if (numchars > nbytes)
9427 {
9428 register int i;
9429
9430 for (i = 0; i < nbytes; i++)
9431 {
9432 if (temp_index == sizeof temp_buffer / sizeof (short))
9433 temp_index = 0;
9434 temp_buffer[temp_index++] = copy_buffer[i];
9435 bufp->kind = ascii_keystroke;
9436 bufp->code = copy_buffer[i];
9437 XSETFRAME (bufp->frame_or_window, f);
9438 bufp->modifiers
9439 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9440 modifiers);
9441 bufp->timestamp = event.xkey.time;
9442 bufp++;
9443 }
9444
9445 count += nbytes;
9446 numchars -= nbytes;
1decb680
PE
9447
9448 if (keysym == NoSymbol)
9449 break;
7a13e894
RS
9450 }
9451 else
9452 abort ();
dc6f92b8 9453 }
10e6549c
RS
9454 else
9455 abort ();
dc6f92b8 9456 }
59ddecde
GM
9457#ifdef HAVE_X_I18N
9458 /* Don't dispatch this event since XtDispatchEvent calls
9459 XFilterEvent, and two calls in a row may freeze the
9460 client. */
9461 break;
9462#else
717ca130 9463 goto OTHER;
59ddecde 9464#endif
f451eb13 9465
f5d11644 9466 case KeyRelease:
59ddecde
GM
9467#ifdef HAVE_X_I18N
9468 /* Don't dispatch this event since XtDispatchEvent calls
9469 XFilterEvent, and two calls in a row may freeze the
9470 client. */
9471 break;
9472#else
f5d11644 9473 goto OTHER;
59ddecde 9474#endif
f5d11644 9475
7a13e894 9476 /* Here's a possible interpretation of the whole
06a2c219
GM
9477 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9478 you get a FocusIn event, you have to get a FocusOut
9479 event before you relinquish the focus. If you
9480 haven't received a FocusIn event, then a mere
9481 LeaveNotify is enough to free you. */
f451eb13 9482
7a13e894 9483 case EnterNotify:
06a2c219
GM
9484 {
9485 int from_menu_bar_p = 0;
9486
9487 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9488
9489#ifdef LESSTIF_VERSION
9490 /* When clicking outside of a menu bar popup to close
9491 it, we get a FocusIn/ EnterNotify sequence of
9492 events. The flag event.xcrossing.focus is not set
9493 in the EnterNotify event of that sequence because
9494 the focus is in the menu bar,
9495 event.xcrossing.window is the frame's X window.
9496 Unconditionally setting the focus frame to null in
9497 this case is not the right thing, because no event
9498 follows that could set the focus frame to the right
9499 value.
9500
9501 This could be a LessTif bug, but I wasn't able to
9502 reproduce the behavior in a simple test program.
9503
9504 (gerd, LessTif 0.88.1). */
9505
9506 if (!event.xcrossing.focus
9507 && f
9508 && f->output_data.x->menubar_widget)
9509 {
9510 Window focus;
9511 int revert;
9512
9513 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9514 if (focus == XtWindow (f->output_data.x->menubar_widget))
9515 from_menu_bar_p = 1;
9516 }
9517#endif /* LESSTIF_VERSION */
6d4238f3 9518
06a2c219
GM
9519 if (event.xcrossing.focus || from_menu_bar_p)
9520 {
9521 /* Avoid nasty pop/raise loops. */
9522 if (f && (!(f->auto_raise)
9523 || !(f->auto_lower)
9524 || (event.xcrossing.time - enter_timestamp) > 500))
9525 {
9526 x_new_focus_frame (dpyinfo, f);
9527 enter_timestamp = event.xcrossing.time;
9528 }
9529 }
9530 else if (f == dpyinfo->x_focus_frame)
9531 x_new_focus_frame (dpyinfo, 0);
9532
9533 /* EnterNotify counts as mouse movement,
9534 so update things that depend on mouse position. */
9535 if (f && !f->output_data.x->busy_p)
9536 note_mouse_movement (f, &event.xmotion);
9537 goto OTHER;
9538 }
dc6f92b8 9539
7a13e894 9540 case FocusIn:
19126e11 9541 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9542 if (event.xfocus.detail != NotifyPointer)
0f941935 9543 dpyinfo->x_focus_event_frame = f;
7a13e894 9544 if (f)
0f941935 9545 x_new_focus_frame (dpyinfo, f);
f9e24cb9 9546
6c183ba5
RS
9547#ifdef HAVE_X_I18N
9548 if (f && FRAME_XIC (f))
9549 XSetICFocus (FRAME_XIC (f));
9550#endif
9551
7a13e894 9552 goto OTHER;
10c5e63d 9553
7a13e894 9554 case LeaveNotify:
19126e11 9555 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9556 if (f)
10c5e63d 9557 {
06a2c219
GM
9558 Lisp_Object frame;
9559 int from_menu_bar_p = 0;
9560
7a13e894 9561 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9562 {
9563 /* If we move outside the frame, then we're
9564 certainly no longer on any text in the frame. */
9565 clear_mouse_face (dpyinfo);
9566 dpyinfo->mouse_face_mouse_frame = 0;
9567 }
9568
9569 /* Generate a nil HELP_EVENT to cancel a help-echo.
9570 Do it only if there's something to cancel.
9571 Otherwise, the startup message is cleared when
9572 the mouse leaves the frame. */
9573 if (any_help_event_p)
9574 {
9575 XSETFRAME (frame, f);
9576 bufp->kind = HELP_EVENT;
9577 bufp->frame_or_window = Fcons (frame, Qnil);
9578 ++bufp, ++count, --numchars;
9579 }
7a13e894 9580
06a2c219
GM
9581#ifdef LESSTIF_VERSION
9582 /* Please see the comment at the start of the
9583 EnterNotify case. */
9584 if (!event.xcrossing.focus
9585 && f->output_data.x->menubar_widget)
9586 {
9587 Window focus;
9588 int revert;
9589 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9590 if (focus == XtWindow (f->output_data.x->menubar_widget))
9591 from_menu_bar_p = 1;
9592 }
9593#endif /* LESSTIF_VERSION */
9594
9595 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9596 x_mouse_leave (dpyinfo);
10c5e63d 9597 else
7a13e894 9598 {
0f941935
KH
9599 if (f == dpyinfo->x_focus_event_frame)
9600 dpyinfo->x_focus_event_frame = 0;
9601 if (f == dpyinfo->x_focus_frame)
9602 x_new_focus_frame (dpyinfo, 0);
7a13e894 9603 }
10c5e63d 9604 }
7a13e894 9605 goto OTHER;
dc6f92b8 9606
7a13e894 9607 case FocusOut:
19126e11 9608 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9609 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9610 && f == dpyinfo->x_focus_event_frame)
9611 dpyinfo->x_focus_event_frame = 0;
9612 if (f && f == dpyinfo->x_focus_frame)
9613 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9614
6c183ba5
RS
9615#ifdef HAVE_X_I18N
9616 if (f && FRAME_XIC (f))
9617 XUnsetICFocus (FRAME_XIC (f));
9618#endif
9619
7a13e894 9620 goto OTHER;
dc6f92b8 9621
7a13e894 9622 case MotionNotify:
dc6f92b8 9623 {
06a2c219
GM
9624 previous_help_echo = help_echo;
9625 help_echo = Qnil;
9626
7a13e894
RS
9627 if (dpyinfo->grabbed && last_mouse_frame
9628 && FRAME_LIVE_P (last_mouse_frame))
9629 f = last_mouse_frame;
9630 else
19126e11 9631 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9632
7a13e894
RS
9633 if (f)
9634 note_mouse_movement (f, &event.xmotion);
9635 else
9636 {
e88b3c50 9637#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9638 struct scroll_bar *bar
9639 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9640
7a13e894
RS
9641 if (bar)
9642 x_scroll_bar_note_movement (bar, &event);
e88b3c50 9643#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 9644
06a2c219
GM
9645 /* If we move outside the frame, then we're
9646 certainly no longer on any text in the frame. */
7a13e894
RS
9647 clear_mouse_face (dpyinfo);
9648 }
06a2c219
GM
9649
9650 /* If the contents of the global variable help_echo
9651 has changed, generate a HELP_EVENT. */
9652 if (STRINGP (help_echo)
9653 || STRINGP (previous_help_echo))
9654 {
9655 Lisp_Object frame;
9656
9657 if (f)
9658 XSETFRAME (frame, f);
9659 else
9660 frame = Qnil;
9661
9662 any_help_event_p = 1;
9663 bufp->kind = HELP_EVENT;
9664 bufp->frame_or_window = Fcons (frame, help_echo);
9665 ++bufp, ++count, --numchars;
9666 }
9667
9668 goto OTHER;
dc6f92b8 9669 }
dc6f92b8 9670
7a13e894 9671 case ConfigureNotify:
9829ddba
RS
9672 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9673 if (f)
af395ec1 9674 {
5c187dee 9675#ifndef USE_X_TOOLKIT
bf1b7b30
KH
9676 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9677 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 9678
2d7fc7e8
RS
9679 /* In the toolkit version, change_frame_size
9680 is called by the code that handles resizing
9681 of the EmacsFrame widget. */
7a13e894 9682
7a13e894
RS
9683 /* Even if the number of character rows and columns has
9684 not changed, the font size may have changed, so we need
9685 to check the pixel dimensions as well. */
9686 if (columns != f->width
9687 || rows != f->height
7556890b
RS
9688 || event.xconfigure.width != f->output_data.x->pixel_width
9689 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 9690 {
7d1e984f 9691 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 9692 SET_FRAME_GARBAGED (f);
e687d06e 9693 cancel_mouse_face (f);
7a13e894 9694 }
2d7fc7e8 9695#endif
af395ec1 9696
7556890b
RS
9697 f->output_data.x->pixel_width = event.xconfigure.width;
9698 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
9699
9700 /* What we have now is the position of Emacs's own window.
9701 Convert that to the position of the window manager window. */
dcb07ae9
RS
9702 x_real_positions (f, &f->output_data.x->left_pos,
9703 &f->output_data.x->top_pos);
9704
f5d11644
GM
9705#ifdef HAVE_X_I18N
9706 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9707 xic_set_statusarea (f);
9708#endif
9709
dcb07ae9
RS
9710 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9711 {
9712 /* Since the WM decorations come below top_pos now,
9713 we must put them below top_pos in the future. */
9714 f->output_data.x->win_gravity = NorthWestGravity;
9715 x_wm_set_size_hint (f, (long) 0, 0);
9716 }
8f08dc93
KH
9717#ifdef USE_MOTIF
9718 /* Some window managers pass (0,0) as the location of
9719 the window, and the Motif event handler stores it
9720 in the emacs widget, which messes up Motif menus. */
9721 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9722 {
9723 event.xconfigure.x = f->output_data.x->widget->core.x;
9724 event.xconfigure.y = f->output_data.x->widget->core.y;
9725 }
06a2c219 9726#endif /* USE_MOTIF */
7a13e894 9727 }
2d7fc7e8 9728 goto OTHER;
dc6f92b8 9729
7a13e894
RS
9730 case ButtonPress:
9731 case ButtonRelease:
9732 {
9733 /* If we decide we want to generate an event to be seen
9734 by the rest of Emacs, we put it here. */
9735 struct input_event emacs_event;
9ea173e8 9736 int tool_bar_p = 0;
06a2c219 9737
7a13e894 9738 emacs_event.kind = no_event;
7a13e894 9739 bzero (&compose_status, sizeof (compose_status));
9b07615b 9740
06a2c219
GM
9741 if (dpyinfo->grabbed
9742 && last_mouse_frame
9f67f20b
RS
9743 && FRAME_LIVE_P (last_mouse_frame))
9744 f = last_mouse_frame;
9745 else
2224b905 9746 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 9747
06a2c219
GM
9748 if (f)
9749 {
9ea173e8
GM
9750 /* Is this in the tool-bar? */
9751 if (WINDOWP (f->tool_bar_window)
9752 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
9753 {
9754 Lisp_Object window;
9755 int p, x, y;
9756
9757 x = event.xbutton.x;
9758 y = event.xbutton.y;
9759
9760 /* Set x and y. */
9761 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 9762 if (EQ (window, f->tool_bar_window))
06a2c219 9763 {
9ea173e8
GM
9764 x_handle_tool_bar_click (f, &event.xbutton);
9765 tool_bar_p = 1;
06a2c219
GM
9766 }
9767 }
9768
9ea173e8 9769 if (!tool_bar_p)
06a2c219
GM
9770 if (!dpyinfo->x_focus_frame
9771 || f == dpyinfo->x_focus_frame)
9772 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
9773 }
9774 else
9775 {
06a2c219 9776#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9777 struct scroll_bar *bar
9778 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 9779
7a13e894
RS
9780 if (bar)
9781 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 9782#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9783 }
9784
9785 if (event.type == ButtonPress)
9786 {
9787 dpyinfo->grabbed |= (1 << event.xbutton.button);
9788 last_mouse_frame = f;
edad46f6
KH
9789 /* Ignore any mouse motion that happened
9790 before this event; any subsequent mouse-movement
9791 Emacs events should reflect only motion after
9792 the ButtonPress. */
a00e91cd
KH
9793 if (f != 0)
9794 f->mouse_moved = 0;
06a2c219 9795
9ea173e8
GM
9796 if (!tool_bar_p)
9797 last_tool_bar_item = -1;
7a13e894 9798 }
3afe33e7
RS
9799 else
9800 {
7a13e894 9801 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 9802 }
23faf38f 9803
7a13e894
RS
9804 if (numchars >= 1 && emacs_event.kind != no_event)
9805 {
9806 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9807 bufp++;
9808 count++;
9809 numchars--;
9810 }
3afe33e7
RS
9811
9812#ifdef USE_X_TOOLKIT
2224b905
RS
9813 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9814 /* For a down-event in the menu bar,
9815 don't pass it to Xt right now.
9816 Instead, save it away
9817 and we will pass it to Xt from kbd_buffer_get_event.
9818 That way, we can run some Lisp code first. */
91375f8f
RS
9819 if (f && event.type == ButtonPress
9820 /* Verify the event is really within the menu bar
9821 and not just sent to it due to grabbing. */
9822 && event.xbutton.x >= 0
9823 && event.xbutton.x < f->output_data.x->pixel_width
9824 && event.xbutton.y >= 0
9825 && event.xbutton.y < f->output_data.x->menubar_height
9826 && event.xbutton.same_screen)
2224b905 9827 {
8805890a 9828 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
9829 XSETFRAME (last_mouse_press_frame, f);
9830 }
9831 else if (event.type == ButtonPress)
9832 {
9833 last_mouse_press_frame = Qnil;
30e671c3 9834 goto OTHER;
ce89ef46 9835 }
06a2c219 9836
2237cac9
RS
9837#ifdef USE_MOTIF /* This should do not harm for Lucid,
9838 but I am trying to be cautious. */
ce89ef46
RS
9839 else if (event.type == ButtonRelease)
9840 {
2237cac9 9841 if (!NILP (last_mouse_press_frame))
f10ded1c 9842 {
2237cac9
RS
9843 f = XFRAME (last_mouse_press_frame);
9844 if (f->output_data.x)
06a2c219 9845 SET_SAVED_BUTTON_EVENT;
f10ded1c 9846 }
06a2c219 9847 else
30e671c3 9848 goto OTHER;
2224b905 9849 }
2237cac9 9850#endif /* USE_MOTIF */
2224b905
RS
9851 else
9852 goto OTHER;
3afe33e7 9853#endif /* USE_X_TOOLKIT */
7a13e894
RS
9854 }
9855 break;
dc6f92b8 9856
7a13e894 9857 case CirculateNotify:
06a2c219
GM
9858 goto OTHER;
9859
7a13e894 9860 case CirculateRequest:
06a2c219
GM
9861 goto OTHER;
9862
9863 case VisibilityNotify:
9864 goto OTHER;
dc6f92b8 9865
7a13e894
RS
9866 case MappingNotify:
9867 /* Someone has changed the keyboard mapping - update the
9868 local cache. */
9869 switch (event.xmapping.request)
9870 {
9871 case MappingModifier:
9872 x_find_modifier_meanings (dpyinfo);
9873 /* This is meant to fall through. */
9874 case MappingKeyboard:
9875 XRefreshKeyboardMapping (&event.xmapping);
9876 }
7a13e894 9877 goto OTHER;
dc6f92b8 9878
7a13e894 9879 default:
7a13e894 9880 OTHER:
717ca130 9881#ifdef USE_X_TOOLKIT
7a13e894
RS
9882 BLOCK_INPUT;
9883 XtDispatchEvent (&event);
9884 UNBLOCK_INPUT;
3afe33e7 9885#endif /* USE_X_TOOLKIT */
7a13e894
RS
9886 break;
9887 }
dc6f92b8
JB
9888 }
9889 }
9890
06a2c219
GM
9891 out:;
9892
9a5196d0
RS
9893 /* On some systems, an X bug causes Emacs to get no more events
9894 when the window is destroyed. Detect that. (1994.) */
58769bee 9895 if (! event_found)
ef2a22d0 9896 {
ef2a22d0
RS
9897 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9898 One XNOOP in 100 loops will make Emacs terminate.
9899 B. Bretthauer, 1994 */
9900 x_noop_count++;
58769bee 9901 if (x_noop_count >= 100)
ef2a22d0
RS
9902 {
9903 x_noop_count=0;
2224b905
RS
9904
9905 if (next_noop_dpyinfo == 0)
9906 next_noop_dpyinfo = x_display_list;
9907
9908 XNoOp (next_noop_dpyinfo->display);
9909
9910 /* Each time we get here, cycle through the displays now open. */
9911 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
9912 }
9913 }
502add23 9914
06a2c219 9915 /* If the focus was just given to an auto-raising frame,
0134a210 9916 raise it now. */
7a13e894 9917 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
9918 if (pending_autoraise_frame)
9919 {
9920 x_raise_frame (pending_autoraise_frame);
9921 pending_autoraise_frame = 0;
9922 }
0134a210 9923
dc6f92b8
JB
9924 UNBLOCK_INPUT;
9925 return count;
9926}
06a2c219
GM
9927
9928
9929
dc6f92b8 9930\f
06a2c219
GM
9931/***********************************************************************
9932 Text Cursor
9933 ***********************************************************************/
9934
9935/* Note if the text cursor of window W has been overwritten by a
9936 drawing operation that outputs N glyphs starting at HPOS in the
9937 line given by output_cursor.vpos. N < 0 means all the rest of the
9938 line after HPOS has been written. */
9939
9940static void
9941note_overwritten_text_cursor (w, hpos, n)
9942 struct window *w;
9943 int hpos, n;
9944{
9945 if (updated_area == TEXT_AREA
9946 && output_cursor.vpos == w->phys_cursor.vpos
9947 && hpos <= w->phys_cursor.hpos
9948 && (n < 0
9949 || hpos + n > w->phys_cursor.hpos))
9950 w->phys_cursor_on_p = 0;
9951}
f451eb13
JB
9952
9953
06a2c219
GM
9954/* Set clipping for output in glyph row ROW. W is the window in which
9955 we operate. GC is the graphics context to set clipping in.
9956 WHOLE_LINE_P non-zero means include the areas used for truncation
9957 mark display and alike in the clipping rectangle.
9958
9959 ROW may be a text row or, e.g., a mode line. Text rows must be
9960 clipped to the interior of the window dedicated to text display,
9961 mode lines must be clipped to the whole window. */
dc6f92b8
JB
9962
9963static void
06a2c219
GM
9964x_clip_to_row (w, row, gc, whole_line_p)
9965 struct window *w;
9966 struct glyph_row *row;
9967 GC gc;
9968 int whole_line_p;
dc6f92b8 9969{
06a2c219
GM
9970 struct frame *f = XFRAME (WINDOW_FRAME (w));
9971 XRectangle clip_rect;
9972 int window_x, window_y, window_width, window_height;
dc6f92b8 9973
06a2c219 9974 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 9975
06a2c219
GM
9976 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9977 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9978 clip_rect.y = max (clip_rect.y, window_y);
9979 clip_rect.width = window_width;
9980 clip_rect.height = row->visible_height;
5c1aae96 9981
06a2c219
GM
9982 /* If clipping to the whole line, including trunc marks, extend
9983 the rectangle to the left and increase its width. */
9984 if (whole_line_p)
9985 {
110859fc
GM
9986 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
9987 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 9988 }
5c1aae96 9989
06a2c219 9990 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
9991}
9992
06a2c219
GM
9993
9994/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
9995
9996static void
06a2c219
GM
9997x_draw_hollow_cursor (w, row)
9998 struct window *w;
9999 struct glyph_row *row;
dc6f92b8 10000{
06a2c219
GM
10001 struct frame *f = XFRAME (WINDOW_FRAME (w));
10002 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10003 Display *dpy = FRAME_X_DISPLAY (f);
10004 int x, y, wd, h;
10005 XGCValues xgcv;
10006 struct glyph *cursor_glyph;
10007 GC gc;
10008
10009 /* Compute frame-relative coordinates from window-relative
10010 coordinates. */
10011 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10012 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10013 + row->ascent - w->phys_cursor_ascent);
10014 h = row->height - 1;
10015
10016 /* Get the glyph the cursor is on. If we can't tell because
10017 the current matrix is invalid or such, give up. */
10018 cursor_glyph = get_phys_cursor_glyph (w);
10019 if (cursor_glyph == NULL)
dc6f92b8
JB
10020 return;
10021
06a2c219
GM
10022 /* Compute the width of the rectangle to draw. If on a stretch
10023 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10024 rectangle as wide as the glyph, but use a canonical character
10025 width instead. */
10026 wd = cursor_glyph->pixel_width - 1;
10027 if (cursor_glyph->type == STRETCH_GLYPH
10028 && !x_stretch_cursor_p)
10029 wd = min (CANON_X_UNIT (f), wd);
10030
10031 /* The foreground of cursor_gc is typically the same as the normal
10032 background color, which can cause the cursor box to be invisible. */
10033 xgcv.foreground = f->output_data.x->cursor_pixel;
10034 if (dpyinfo->scratch_cursor_gc)
10035 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10036 else
10037 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10038 GCForeground, &xgcv);
10039 gc = dpyinfo->scratch_cursor_gc;
10040
10041 /* Set clipping, draw the rectangle, and reset clipping again. */
10042 x_clip_to_row (w, row, gc, 0);
10043 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10044 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10045}
10046
06a2c219
GM
10047
10048/* Draw a bar cursor on window W in glyph row ROW.
10049
10050 Implementation note: One would like to draw a bar cursor with an
10051 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10052 Unfortunately, I didn't find a font yet that has this property set.
10053 --gerd. */
dc6f92b8
JB
10054
10055static void
06a2c219
GM
10056x_draw_bar_cursor (w, row)
10057 struct window *w;
10058 struct glyph_row *row;
dc6f92b8 10059{
06a2c219
GM
10060 /* If cursor hpos is out of bounds, don't draw garbage. This can
10061 happen in mini-buffer windows when switching between echo area
10062 glyphs and mini-buffer. */
10063 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10064 {
10065 struct frame *f = XFRAME (w->frame);
10066 struct glyph *cursor_glyph;
10067 GC gc;
10068 int x;
10069 unsigned long mask;
10070 XGCValues xgcv;
10071 Display *dpy;
10072 Window window;
10073
10074 cursor_glyph = get_phys_cursor_glyph (w);
10075 if (cursor_glyph == NULL)
10076 return;
10077
10078 xgcv.background = f->output_data.x->cursor_pixel;
10079 xgcv.foreground = f->output_data.x->cursor_pixel;
10080 xgcv.graphics_exposures = 0;
10081 mask = GCForeground | GCBackground | GCGraphicsExposures;
10082 dpy = FRAME_X_DISPLAY (f);
10083 window = FRAME_X_WINDOW (f);
10084 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10085
10086 if (gc)
10087 XChangeGC (dpy, gc, mask, &xgcv);
10088 else
10089 {
10090 gc = XCreateGC (dpy, window, mask, &xgcv);
10091 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10092 }
10093
10094 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10095 x_clip_to_row (w, row, gc, 0);
10096 XFillRectangle (dpy, window, gc,
10097 x,
10098 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
10099 min (cursor_glyph->pixel_width,
10100 f->output_data.x->cursor_width),
10101 row->height);
10102 XSetClipMask (dpy, gc, None);
10103 }
dc6f92b8
JB
10104}
10105
06a2c219
GM
10106
10107/* Clear the cursor of window W to background color, and mark the
10108 cursor as not shown. This is used when the text where the cursor
10109 is is about to be rewritten. */
10110
dc6f92b8 10111static void
06a2c219
GM
10112x_clear_cursor (w)
10113 struct window *w;
dc6f92b8 10114{
06a2c219
GM
10115 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10116 x_update_window_cursor (w, 0);
10117}
90e65f07 10118
dbc4e1c1 10119
06a2c219
GM
10120/* Draw the cursor glyph of window W in glyph row ROW. See the
10121 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10122
06a2c219
GM
10123static void
10124x_draw_phys_cursor_glyph (w, row, hl)
10125 struct window *w;
10126 struct glyph_row *row;
10127 enum draw_glyphs_face hl;
10128{
10129 /* If cursor hpos is out of bounds, don't draw garbage. This can
10130 happen in mini-buffer windows when switching between echo area
10131 glyphs and mini-buffer. */
10132 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10133 {
10134 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10135 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10136 hl, 0, 0, 0);
10137
10138 /* When we erase the cursor, and ROW is overlapped by other
10139 rows, make sure that these overlapping parts of other rows
10140 are redrawn. */
10141 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10142 {
10143 if (row > w->current_matrix->rows
10144 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10145 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10146
10147 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10148 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10149 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10150 }
10151 }
06a2c219 10152}
dbc4e1c1 10153
eea6af04 10154
06a2c219 10155/* Erase the image of a cursor of window W from the screen. */
eea6af04 10156
06a2c219
GM
10157static void
10158x_erase_phys_cursor (w)
10159 struct window *w;
10160{
10161 struct frame *f = XFRAME (w->frame);
10162 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10163 int hpos = w->phys_cursor.hpos;
10164 int vpos = w->phys_cursor.vpos;
10165 int mouse_face_here_p = 0;
10166 struct glyph_matrix *active_glyphs = w->current_matrix;
10167 struct glyph_row *cursor_row;
10168 struct glyph *cursor_glyph;
10169 enum draw_glyphs_face hl;
10170
10171 /* No cursor displayed or row invalidated => nothing to do on the
10172 screen. */
10173 if (w->phys_cursor_type == NO_CURSOR)
10174 goto mark_cursor_off;
10175
10176 /* VPOS >= active_glyphs->nrows means that window has been resized.
10177 Don't bother to erase the cursor. */
10178 if (vpos >= active_glyphs->nrows)
10179 goto mark_cursor_off;
10180
10181 /* If row containing cursor is marked invalid, there is nothing we
10182 can do. */
10183 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10184 if (!cursor_row->enabled_p)
10185 goto mark_cursor_off;
10186
10187 /* This can happen when the new row is shorter than the old one.
10188 In this case, either x_draw_glyphs or clear_end_of_line
10189 should have cleared the cursor. Note that we wouldn't be
10190 able to erase the cursor in this case because we don't have a
10191 cursor glyph at hand. */
10192 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10193 goto mark_cursor_off;
10194
10195 /* If the cursor is in the mouse face area, redisplay that when
10196 we clear the cursor. */
10197 if (w == XWINDOW (dpyinfo->mouse_face_window)
10198 && (vpos > dpyinfo->mouse_face_beg_row
10199 || (vpos == dpyinfo->mouse_face_beg_row
10200 && hpos >= dpyinfo->mouse_face_beg_col))
10201 && (vpos < dpyinfo->mouse_face_end_row
10202 || (vpos == dpyinfo->mouse_face_end_row
10203 && hpos < dpyinfo->mouse_face_end_col))
10204 /* Don't redraw the cursor's spot in mouse face if it is at the
10205 end of a line (on a newline). The cursor appears there, but
10206 mouse highlighting does not. */
10207 && cursor_row->used[TEXT_AREA] > hpos)
10208 mouse_face_here_p = 1;
10209
10210 /* Maybe clear the display under the cursor. */
10211 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10212 {
10213 int x;
045dee35 10214 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10215
06a2c219
GM
10216 cursor_glyph = get_phys_cursor_glyph (w);
10217 if (cursor_glyph == NULL)
10218 goto mark_cursor_off;
dbc4e1c1 10219
06a2c219
GM
10220 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10221
10222 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10223 x,
045dee35 10224 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10225 cursor_row->y)),
10226 cursor_glyph->pixel_width,
10227 cursor_row->visible_height,
10228 False);
dbc4e1c1 10229 }
06a2c219
GM
10230
10231 /* Erase the cursor by redrawing the character underneath it. */
10232 if (mouse_face_here_p)
10233 hl = DRAW_MOUSE_FACE;
10234 else if (cursor_row->inverse_p)
10235 hl = DRAW_INVERSE_VIDEO;
10236 else
10237 hl = DRAW_NORMAL_TEXT;
10238 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10239
06a2c219
GM
10240 mark_cursor_off:
10241 w->phys_cursor_on_p = 0;
10242 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10243}
10244
10245
06a2c219
GM
10246/* Display or clear cursor of window W. If ON is zero, clear the
10247 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10248 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10249
06a2c219
GM
10250void
10251x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10252 struct window *w;
10253 int on, hpos, vpos, x, y;
dbc4e1c1 10254{
06a2c219
GM
10255 struct frame *f = XFRAME (w->frame);
10256 int new_cursor_type;
10257 struct glyph_matrix *current_glyphs;
10258 struct glyph_row *glyph_row;
10259 struct glyph *glyph;
dbc4e1c1 10260
49d838ea 10261 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10262 windows and frames; in the latter case, the frame or window may
10263 be in the midst of changing its size, and x and y may be off the
10264 window. */
10265 if (! FRAME_VISIBLE_P (f)
10266 || FRAME_GARBAGED_P (f)
10267 || vpos >= w->current_matrix->nrows
10268 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10269 return;
10270
10271 /* If cursor is off and we want it off, return quickly. */
06a2c219 10272 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10273 return;
10274
06a2c219
GM
10275 current_glyphs = w->current_matrix;
10276 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10277 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10278
10279 /* If cursor row is not enabled, we don't really know where to
10280 display the cursor. */
10281 if (!glyph_row->enabled_p)
10282 {
10283 w->phys_cursor_on_p = 0;
10284 return;
10285 }
10286
10287 xassert (interrupt_input_blocked);
10288
10289 /* Set new_cursor_type to the cursor we want to be displayed. In a
10290 mini-buffer window, we want the cursor only to appear if we are
10291 reading input from this window. For the selected window, we want
10292 the cursor type given by the frame parameter. If explicitly
10293 marked off, draw no cursor. In all other cases, we want a hollow
10294 box cursor. */
9b4a7047
GM
10295 if (cursor_in_echo_area
10296 && FRAME_HAS_MINIBUF_P (f)
10297 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10298 {
9b4a7047
GM
10299 if (w == XWINDOW (echo_area_window))
10300 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10301 else
10302 new_cursor_type = HOLLOW_BOX_CURSOR;
10303 }
06a2c219 10304 else
9b4a7047
GM
10305 {
10306 if (w != XWINDOW (selected_window)
10307 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10308 {
e55a0b79
GM
10309 extern int cursor_in_non_selected_windows;
10310
10311 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
9b4a7047
GM
10312 new_cursor_type = NO_CURSOR;
10313 else
10314 new_cursor_type = HOLLOW_BOX_CURSOR;
10315 }
10316 else if (w->cursor_off_p)
10317 new_cursor_type = NO_CURSOR;
10318 else
10319 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10320 }
06a2c219
GM
10321
10322 /* If cursor is currently being shown and we don't want it to be or
10323 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10324 erase it. */
06a2c219 10325 if (w->phys_cursor_on_p
dc6f92b8 10326 && (!on
06a2c219
GM
10327 || w->phys_cursor.x != x
10328 || w->phys_cursor.y != y
10329 || new_cursor_type != w->phys_cursor_type))
10330 x_erase_phys_cursor (w);
10331
10332 /* If the cursor is now invisible and we want it to be visible,
10333 display it. */
10334 if (on && !w->phys_cursor_on_p)
10335 {
10336 w->phys_cursor_ascent = glyph_row->ascent;
10337 w->phys_cursor_height = glyph_row->height;
10338
10339 /* Set phys_cursor_.* before x_draw_.* is called because some
10340 of them may need the information. */
10341 w->phys_cursor.x = x;
10342 w->phys_cursor.y = glyph_row->y;
10343 w->phys_cursor.hpos = hpos;
10344 w->phys_cursor.vpos = vpos;
10345 w->phys_cursor_type = new_cursor_type;
10346 w->phys_cursor_on_p = 1;
10347
10348 switch (new_cursor_type)
dc6f92b8 10349 {
06a2c219
GM
10350 case HOLLOW_BOX_CURSOR:
10351 x_draw_hollow_cursor (w, glyph_row);
10352 break;
10353
10354 case FILLED_BOX_CURSOR:
10355 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10356 break;
10357
10358 case BAR_CURSOR:
10359 x_draw_bar_cursor (w, glyph_row);
10360 break;
10361
10362 case NO_CURSOR:
10363 break;
dc6f92b8 10364
06a2c219
GM
10365 default:
10366 abort ();
10367 }
59ddecde
GM
10368
10369#ifdef HAVE_X_I18N
10370 if (w == XWINDOW (f->selected_window))
10371 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10372 xic_set_preeditarea (w, x, y);
10373#endif
dc6f92b8
JB
10374 }
10375
06a2c219 10376#ifndef XFlush
f676886a 10377 if (updating_frame != f)
334208b7 10378 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10379#endif
dc6f92b8
JB
10380}
10381
06a2c219
GM
10382
10383/* Display the cursor on window W, or clear it. X and Y are window
10384 relative pixel coordinates. HPOS and VPOS are glyph matrix
10385 positions. If W is not the selected window, display a hollow
10386 cursor. ON non-zero means display the cursor at X, Y which
10387 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10388
dfcf069d 10389void
06a2c219
GM
10390x_display_cursor (w, on, hpos, vpos, x, y)
10391 struct window *w;
10392 int on, hpos, vpos, x, y;
dc6f92b8 10393{
f94397b5 10394 BLOCK_INPUT;
06a2c219 10395 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10396 UNBLOCK_INPUT;
10397}
10398
06a2c219
GM
10399
10400/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10401 Don't change the cursor's position. */
10402
dfcf069d 10403void
06a2c219 10404x_update_cursor (f, on_p)
5d46f928 10405 struct frame *f;
5d46f928 10406{
06a2c219
GM
10407 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10408}
10409
10410
10411/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10412 in the window tree rooted at W. */
10413
10414static void
10415x_update_cursor_in_window_tree (w, on_p)
10416 struct window *w;
10417 int on_p;
10418{
10419 while (w)
10420 {
10421 if (!NILP (w->hchild))
10422 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10423 else if (!NILP (w->vchild))
10424 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10425 else
10426 x_update_window_cursor (w, on_p);
10427
10428 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10429 }
10430}
5d46f928 10431
f94397b5 10432
06a2c219
GM
10433/* Switch the display of W's cursor on or off, according to the value
10434 of ON. */
10435
10436static void
10437x_update_window_cursor (w, on)
10438 struct window *w;
10439 int on;
10440{
16b5d424
GM
10441 /* Don't update cursor in windows whose frame is in the process
10442 of being deleted. */
10443 if (w->current_matrix)
10444 {
10445 BLOCK_INPUT;
10446 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10447 w->phys_cursor.x, w->phys_cursor.y);
10448 UNBLOCK_INPUT;
10449 }
dc6f92b8 10450}
06a2c219
GM
10451
10452
10453
dc6f92b8
JB
10454\f
10455/* Icons. */
10456
f676886a 10457/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10458 when we get an expose event for it. */
dc6f92b8 10459
dfcf069d 10460void
f676886a
JB
10461refreshicon (f)
10462 struct frame *f;
dc6f92b8 10463{
06a2c219 10464 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10465}
10466
dbc4e1c1 10467/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10468
10469int
990ba854 10470x_bitmap_icon (f, file)
f676886a 10471 struct frame *f;
990ba854 10472 Lisp_Object file;
dc6f92b8 10473{
06a2c219 10474 int bitmap_id;
dc6f92b8 10475
c118dd06 10476 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10477 return 1;
10478
990ba854 10479 /* Free up our existing icon bitmap if any. */
7556890b
RS
10480 if (f->output_data.x->icon_bitmap > 0)
10481 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10482 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10483
10484 if (STRINGP (file))
7f2ae036
RS
10485 bitmap_id = x_create_bitmap_from_file (f, file);
10486 else
10487 {
990ba854 10488 /* Create the GNU bitmap if necessary. */
5bf01b68 10489 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10490 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10491 = x_create_bitmap_from_data (f, gnu_bits,
10492 gnu_width, gnu_height);
990ba854
RS
10493
10494 /* The first time we create the GNU bitmap,
06a2c219 10495 this increments the ref-count one extra time.
990ba854
RS
10496 As a result, the GNU bitmap is never freed.
10497 That way, we don't have to worry about allocating it again. */
334208b7 10498 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10499
334208b7 10500 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10501 }
10502
10503 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10504 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10505
10506 return 0;
10507}
10508
10509
1be2d067
KH
10510/* Make the x-window of frame F use a rectangle with text.
10511 Use ICON_NAME as the text. */
dc6f92b8
JB
10512
10513int
f676886a
JB
10514x_text_icon (f, icon_name)
10515 struct frame *f;
dc6f92b8
JB
10516 char *icon_name;
10517{
c118dd06 10518 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10519 return 1;
10520
1be2d067
KH
10521#ifdef HAVE_X11R4
10522 {
10523 XTextProperty text;
10524 text.value = (unsigned char *) icon_name;
10525 text.encoding = XA_STRING;
10526 text.format = 8;
10527 text.nitems = strlen (icon_name);
10528#ifdef USE_X_TOOLKIT
7556890b 10529 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10530 &text);
10531#else /* not USE_X_TOOLKIT */
10532 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10533#endif /* not USE_X_TOOLKIT */
10534 }
10535#else /* not HAVE_X11R4 */
10536 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10537#endif /* not HAVE_X11R4 */
58769bee 10538
7556890b
RS
10539 if (f->output_data.x->icon_bitmap > 0)
10540 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10541 f->output_data.x->icon_bitmap = 0;
b1c884c3 10542 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10543
10544 return 0;
10545}
10546\f
e99db5a1
RS
10547#define X_ERROR_MESSAGE_SIZE 200
10548
10549/* If non-nil, this should be a string.
10550 It means catch X errors and store the error message in this string. */
10551
10552static Lisp_Object x_error_message_string;
10553
10554/* An X error handler which stores the error message in
10555 x_error_message_string. This is called from x_error_handler if
10556 x_catch_errors is in effect. */
10557
06a2c219 10558static void
e99db5a1
RS
10559x_error_catcher (display, error)
10560 Display *display;
10561 XErrorEvent *error;
10562{
10563 XGetErrorText (display, error->error_code,
10564 XSTRING (x_error_message_string)->data,
10565 X_ERROR_MESSAGE_SIZE);
10566}
10567
10568/* Begin trapping X errors for display DPY. Actually we trap X errors
10569 for all displays, but DPY should be the display you are actually
10570 operating on.
10571
10572 After calling this function, X protocol errors no longer cause
10573 Emacs to exit; instead, they are recorded in the string
10574 stored in x_error_message_string.
10575
10576 Calling x_check_errors signals an Emacs error if an X error has
10577 occurred since the last call to x_catch_errors or x_check_errors.
10578
10579 Calling x_uncatch_errors resumes the normal error handling. */
10580
10581void x_check_errors ();
10582static Lisp_Object x_catch_errors_unwind ();
10583
10584int
10585x_catch_errors (dpy)
10586 Display *dpy;
10587{
10588 int count = specpdl_ptr - specpdl;
10589
10590 /* Make sure any errors from previous requests have been dealt with. */
10591 XSync (dpy, False);
10592
10593 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10594
10595 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10596 XSTRING (x_error_message_string)->data[0] = 0;
10597
10598 return count;
10599}
10600
10601/* Unbind the binding that we made to check for X errors. */
10602
10603static Lisp_Object
10604x_catch_errors_unwind (old_val)
10605 Lisp_Object old_val;
10606{
10607 x_error_message_string = old_val;
10608 return Qnil;
10609}
10610
10611/* If any X protocol errors have arrived since the last call to
10612 x_catch_errors or x_check_errors, signal an Emacs error using
10613 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10614
10615void
10616x_check_errors (dpy, format)
10617 Display *dpy;
10618 char *format;
10619{
10620 /* Make sure to catch any errors incurred so far. */
10621 XSync (dpy, False);
10622
10623 if (XSTRING (x_error_message_string)->data[0])
10624 error (format, XSTRING (x_error_message_string)->data);
10625}
10626
9829ddba
RS
10627/* Nonzero if we had any X protocol errors
10628 since we did x_catch_errors on DPY. */
e99db5a1
RS
10629
10630int
10631x_had_errors_p (dpy)
10632 Display *dpy;
10633{
10634 /* Make sure to catch any errors incurred so far. */
10635 XSync (dpy, False);
10636
10637 return XSTRING (x_error_message_string)->data[0] != 0;
10638}
10639
9829ddba
RS
10640/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10641
06a2c219 10642void
9829ddba
RS
10643x_clear_errors (dpy)
10644 Display *dpy;
10645{
10646 XSTRING (x_error_message_string)->data[0] = 0;
10647}
10648
e99db5a1
RS
10649/* Stop catching X protocol errors and let them make Emacs die.
10650 DPY should be the display that was passed to x_catch_errors.
10651 COUNT should be the value that was returned by
10652 the corresponding call to x_catch_errors. */
10653
10654void
10655x_uncatch_errors (dpy, count)
10656 Display *dpy;
10657 int count;
10658{
10659 unbind_to (count, Qnil);
10660}
10661
10662#if 0
10663static unsigned int x_wire_count;
10664x_trace_wire ()
10665{
10666 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10667}
10668#endif /* ! 0 */
10669
10670\f
10671/* Handle SIGPIPE, which can happen when the connection to a server
10672 simply goes away. SIGPIPE is handled by x_connection_signal.
10673 Don't need to do anything, because the write which caused the
10674 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 10675 which will do the appropriate cleanup for us. */
e99db5a1
RS
10676
10677static SIGTYPE
10678x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 10679 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
10680{
10681#ifdef USG
10682 /* USG systems forget handlers when they are used;
10683 must reestablish each time */
10684 signal (signalnum, x_connection_signal);
10685#endif /* USG */
10686}
10687\f
4746118a
JB
10688/* Handling X errors. */
10689
7a13e894 10690/* Handle the loss of connection to display DISPLAY. */
16bd92ea 10691
4746118a 10692static SIGTYPE
7a13e894
RS
10693x_connection_closed (display, error_message)
10694 Display *display;
10695 char *error_message;
4746118a 10696{
7a13e894
RS
10697 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10698 Lisp_Object frame, tail;
10699
6186a4a0
RS
10700 /* Indicate that this display is dead. */
10701
2e465cdd 10702#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 10703#ifdef USE_X_TOOLKIT
adabc3a9 10704 XtCloseDisplay (display);
2e465cdd 10705#endif
f613a4c8 10706#endif
adabc3a9 10707
6186a4a0
RS
10708 dpyinfo->display = 0;
10709
06a2c219 10710 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
10711 that are on the dead display. */
10712 FOR_EACH_FRAME (tail, frame)
10713 {
10714 Lisp_Object minibuf_frame;
10715 minibuf_frame
10716 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
10717 if (FRAME_X_P (XFRAME (frame))
10718 && FRAME_X_P (XFRAME (minibuf_frame))
10719 && ! EQ (frame, minibuf_frame)
10720 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
10721 Fdelete_frame (frame, Qt);
10722 }
10723
10724 /* Now delete all remaining frames on the dead display.
06a2c219 10725 We are now sure none of these is used as the mini-buffer
7a13e894
RS
10726 for another frame that we need to delete. */
10727 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
10728 if (FRAME_X_P (XFRAME (frame))
10729 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
10730 {
10731 /* Set this to t so that Fdelete_frame won't get confused
10732 trying to find a replacement. */
10733 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10734 Fdelete_frame (frame, Qt);
10735 }
7a13e894 10736
482a1bd2
KH
10737 if (dpyinfo)
10738 x_delete_display (dpyinfo);
7a13e894
RS
10739
10740 if (x_display_list == 0)
10741 {
f8d07b62 10742 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
10743 shut_down_emacs (0, 0, Qnil);
10744 exit (70);
10745 }
12ba150f 10746
7a13e894
RS
10747 /* Ordinary stack unwind doesn't deal with these. */
10748#ifdef SIGIO
10749 sigunblock (sigmask (SIGIO));
10750#endif
10751 sigunblock (sigmask (SIGALRM));
10752 TOTALLY_UNBLOCK_INPUT;
10753
aa4d9a9e 10754 clear_waiting_for_input ();
7a13e894 10755 error ("%s", error_message);
4746118a
JB
10756}
10757
7a13e894
RS
10758/* This is the usual handler for X protocol errors.
10759 It kills all frames on the display that we got the error for.
10760 If that was the only one, it prints an error message and kills Emacs. */
10761
06a2c219 10762static void
c118dd06
JB
10763x_error_quitter (display, error)
10764 Display *display;
10765 XErrorEvent *error;
10766{
7a13e894 10767 char buf[256], buf1[356];
dc6f92b8 10768
58769bee 10769 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 10770 original error handler. */
dc6f92b8 10771
c118dd06 10772 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 10773 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 10774 buf, error->request_code);
7a13e894 10775 x_connection_closed (display, buf1);
dc6f92b8
JB
10776}
10777
e99db5a1
RS
10778/* This is the first-level handler for X protocol errors.
10779 It calls x_error_quitter or x_error_catcher. */
7a13e894 10780
8922af5f 10781static int
e99db5a1 10782x_error_handler (display, error)
8922af5f 10783 Display *display;
e99db5a1 10784 XErrorEvent *error;
8922af5f 10785{
e99db5a1
RS
10786 if (! NILP (x_error_message_string))
10787 x_error_catcher (display, error);
10788 else
10789 x_error_quitter (display, error);
06a2c219 10790 return 0;
f9e24cb9 10791}
c118dd06 10792
e99db5a1
RS
10793/* This is the handler for X IO errors, always.
10794 It kills all frames on the display that we lost touch with.
10795 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 10796
c118dd06 10797static int
e99db5a1 10798x_io_error_quitter (display)
c118dd06 10799 Display *display;
c118dd06 10800{
e99db5a1 10801 char buf[256];
dc6f92b8 10802
e99db5a1
RS
10803 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10804 x_connection_closed (display, buf);
06a2c219 10805 return 0;
dc6f92b8 10806}
dc6f92b8 10807\f
f451eb13
JB
10808/* Changing the font of the frame. */
10809
76bcdf39
RS
10810/* Give frame F the font named FONTNAME as its default font, and
10811 return the full name of that font. FONTNAME may be a wildcard
10812 pattern; in that case, we choose some font that fits the pattern.
10813 The return value shows which font we chose. */
10814
b5cf7a0e 10815Lisp_Object
f676886a
JB
10816x_new_font (f, fontname)
10817 struct frame *f;
dc6f92b8
JB
10818 register char *fontname;
10819{
dc43ef94 10820 struct font_info *fontp
ee569018 10821 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 10822
dc43ef94
KH
10823 if (!fontp)
10824 return Qnil;
2224a5fc 10825
dc43ef94 10826 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 10827 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
10828 f->output_data.x->fontset = -1;
10829
b2cad826
KH
10830 /* Compute the scroll bar width in character columns. */
10831 if (f->scroll_bar_pixel_width > 0)
10832 {
7556890b 10833 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
10834 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10835 }
10836 else
4e61bddf
RS
10837 {
10838 int wid = FONT_WIDTH (f->output_data.x->font);
10839 f->scroll_bar_cols = (14 + wid - 1) / wid;
10840 }
b2cad826 10841
f676886a 10842 /* Now make the frame display the given font. */
c118dd06 10843 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 10844 {
7556890b
RS
10845 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10846 f->output_data.x->font->fid);
10847 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10848 f->output_data.x->font->fid);
10849 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10850 f->output_data.x->font->fid);
f676886a 10851
a27f9f86 10852 frame_update_line_height (f);
0134a210 10853 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 10854 }
a27f9f86
RS
10855 else
10856 /* If we are setting a new frame's font for the first time,
10857 there are no faces yet, so this font's height is the line height. */
7556890b 10858 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 10859
dc43ef94
KH
10860 return build_string (fontp->full_name);
10861}
10862
10863/* Give frame F the fontset named FONTSETNAME as its default font, and
10864 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
10865 pattern; in that case, we choose some fontset that fits the pattern.
10866 The return value shows which fontset we chose. */
b5cf7a0e 10867
dc43ef94
KH
10868Lisp_Object
10869x_new_fontset (f, fontsetname)
10870 struct frame *f;
10871 char *fontsetname;
10872{
ee569018 10873 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 10874 Lisp_Object result;
ee569018 10875 char *fontname;
b5cf7a0e 10876
dc43ef94
KH
10877 if (fontset < 0)
10878 return Qnil;
b5cf7a0e 10879
2da424f1
KH
10880 if (f->output_data.x->fontset == fontset)
10881 /* This fontset is already set in frame F. There's nothing more
10882 to do. */
ee569018 10883 return fontset_name (fontset);
dc43ef94 10884
ee569018 10885 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
10886
10887 if (!STRINGP (result))
10888 /* Can't load ASCII font. */
10889 return Qnil;
10890
10891 /* Since x_new_font doesn't update any fontset information, do it now. */
10892 f->output_data.x->fontset = fontset;
dc43ef94 10893
f5d11644
GM
10894#ifdef HAVE_X_I18N
10895 if (FRAME_XIC (f)
10896 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 10897 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
10898#endif
10899
dc43ef94 10900 return build_string (fontsetname);
dc6f92b8 10901}
f5d11644
GM
10902
10903\f
10904/***********************************************************************
10905 X Input Methods
10906 ***********************************************************************/
10907
10908#ifdef HAVE_X_I18N
10909
10910#ifdef HAVE_X11R6
10911
10912/* XIM destroy callback function, which is called whenever the
10913 connection to input method XIM dies. CLIENT_DATA contains a
10914 pointer to the x_display_info structure corresponding to XIM. */
10915
10916static void
10917xim_destroy_callback (xim, client_data, call_data)
10918 XIM xim;
10919 XPointer client_data;
10920 XPointer call_data;
10921{
10922 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
10923 Lisp_Object frame, tail;
10924
10925 BLOCK_INPUT;
10926
10927 /* No need to call XDestroyIC.. */
10928 FOR_EACH_FRAME (tail, frame)
10929 {
10930 struct frame *f = XFRAME (frame);
10931 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
10932 {
10933 FRAME_XIC (f) = NULL;
10934 if (FRAME_XIC_FONTSET (f))
10935 {
10936 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
10937 FRAME_XIC_FONTSET (f) = NULL;
10938 }
10939 }
10940 }
10941
10942 /* No need to call XCloseIM. */
10943 dpyinfo->xim = NULL;
10944 XFree (dpyinfo->xim_styles);
10945 UNBLOCK_INPUT;
10946}
10947
10948#endif /* HAVE_X11R6 */
10949
10950/* Open the connection to the XIM server on display DPYINFO.
10951 RESOURCE_NAME is the resource name Emacs uses. */
10952
10953static void
10954xim_open_dpy (dpyinfo, resource_name)
10955 struct x_display_info *dpyinfo;
10956 char *resource_name;
10957{
10958 XIM xim;
10959
10960 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
10961 dpyinfo->xim = xim;
10962
10963 if (xim)
10964 {
f5d11644
GM
10965#ifdef HAVE_X11R6
10966 XIMCallback destroy;
10967#endif
10968
10969 /* Get supported styles and XIM values. */
10970 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
10971
10972#ifdef HAVE_X11R6
10973 destroy.callback = xim_destroy_callback;
10974 destroy.client_data = (XPointer)dpyinfo;
10975 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
10976#endif
10977 }
10978}
10979
10980
b9de836c 10981#ifdef HAVE_X11R6_XIM
f5d11644
GM
10982
10983struct xim_inst_t
10984{
10985 struct x_display_info *dpyinfo;
10986 char *resource_name;
10987};
10988
10989/* XIM instantiate callback function, which is called whenever an XIM
10990 server is available. DISPLAY is teh display of the XIM.
10991 CLIENT_DATA contains a pointer to an xim_inst_t structure created
10992 when the callback was registered. */
10993
10994static void
10995xim_instantiate_callback (display, client_data, call_data)
10996 Display *display;
10997 XPointer client_data;
10998 XPointer call_data;
10999{
11000 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11001 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11002
11003 /* We don't support multiple XIM connections. */
11004 if (dpyinfo->xim)
11005 return;
11006
11007 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11008
11009 /* Create XIC for the existing frames on the same display, as long
11010 as they have no XIC. */
11011 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11012 {
11013 Lisp_Object tail, frame;
11014
11015 BLOCK_INPUT;
11016 FOR_EACH_FRAME (tail, frame)
11017 {
11018 struct frame *f = XFRAME (frame);
11019
11020 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11021 if (FRAME_XIC (f) == NULL)
11022 {
11023 create_frame_xic (f);
11024 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11025 xic_set_statusarea (f);
11026 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11027 {
11028 struct window *w = XWINDOW (f->selected_window);
11029 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11030 }
11031 }
11032 }
11033
11034 UNBLOCK_INPUT;
11035 }
11036}
11037
b9de836c 11038#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11039
11040
11041/* Open a connection to the XIM server on display DPYINFO.
11042 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11043 connection only at the first time. On X11R6, open the connection
11044 in the XIM instantiate callback function. */
11045
11046static void
11047xim_initialize (dpyinfo, resource_name)
11048 struct x_display_info *dpyinfo;
11049 char *resource_name;
11050{
b9de836c 11051#ifdef HAVE_X11R6_XIM
f5d11644
GM
11052 struct xim_inst_t *xim_inst;
11053 int len;
11054
11055 dpyinfo->xim = NULL;
11056 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11057 xim_inst->dpyinfo = dpyinfo;
11058 len = strlen (resource_name);
11059 xim_inst->resource_name = (char *) xmalloc (len + 1);
11060 bcopy (resource_name, xim_inst->resource_name, len + 1);
11061 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11062 resource_name, EMACS_CLASS,
11063 xim_instantiate_callback,
11064 (XPointer)xim_inst);
b9de836c 11065#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11066 dpyinfo->xim = NULL;
11067 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11068#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11069}
11070
11071
11072/* Close the connection to the XIM server on display DPYINFO. */
11073
11074static void
11075xim_close_dpy (dpyinfo)
11076 struct x_display_info *dpyinfo;
11077{
b9de836c 11078#ifdef HAVE_X11R6_XIM
f5d11644
GM
11079 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11080 NULL, EMACS_CLASS,
11081 xim_instantiate_callback, NULL);
b9de836c 11082#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11083 XCloseIM (dpyinfo->xim);
11084 dpyinfo->xim = NULL;
11085 XFree (dpyinfo->xim_styles);
11086}
11087
b9de836c 11088#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11089
11090
dc6f92b8 11091\f
2e365682
RS
11092/* Calculate the absolute position in frame F
11093 from its current recorded position values and gravity. */
11094
dfcf069d 11095void
43bca5d5 11096x_calc_absolute_position (f)
f676886a 11097 struct frame *f;
dc6f92b8 11098{
06a2c219 11099 Window child;
6dba1858 11100 int win_x = 0, win_y = 0;
7556890b 11101 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11102 int this_window;
11103
9829ddba
RS
11104 /* We have nothing to do if the current position
11105 is already for the top-left corner. */
11106 if (! ((flags & XNegative) || (flags & YNegative)))
11107 return;
11108
c81412a0 11109#ifdef USE_X_TOOLKIT
7556890b 11110 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11111#else
11112 this_window = FRAME_X_WINDOW (f);
11113#endif
6dba1858
RS
11114
11115 /* Find the position of the outside upper-left corner of
9829ddba
RS
11116 the inner window, with respect to the outer window.
11117 But do this only if we will need the results. */
7556890b 11118 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11119 {
9829ddba
RS
11120 int count;
11121
6dba1858 11122 BLOCK_INPUT;
9829ddba
RS
11123 count = x_catch_errors (FRAME_X_DISPLAY (f));
11124 while (1)
11125 {
11126 x_clear_errors (FRAME_X_DISPLAY (f));
11127 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11128
11129 /* From-window, to-window. */
11130 this_window,
11131 f->output_data.x->parent_desc,
11132
11133 /* From-position, to-position. */
11134 0, 0, &win_x, &win_y,
11135
11136 /* Child of win. */
11137 &child);
11138 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11139 {
11140 Window newroot, newparent = 0xdeadbeef;
11141 Window *newchildren;
11142 int nchildren;
11143
11144 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11145 &newparent, &newchildren, &nchildren))
11146 break;
58769bee 11147
7c3c78a3 11148 XFree ((char *) newchildren);
6dba1858 11149
9829ddba
RS
11150 f->output_data.x->parent_desc = newparent;
11151 }
11152 else
11153 break;
11154 }
6dba1858 11155
9829ddba 11156 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11157 UNBLOCK_INPUT;
11158 }
11159
11160 /* Treat negative positions as relative to the leftmost bottommost
11161 position that fits on the screen. */
20f55f9a 11162 if (flags & XNegative)
7556890b 11163 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11164 - 2 * f->output_data.x->border_width - win_x
11165 - PIXEL_WIDTH (f)
11166 + f->output_data.x->left_pos);
dc6f92b8 11167
20f55f9a 11168 if (flags & YNegative)
06a2c219
GM
11169 {
11170 int menubar_height = 0;
11171
11172#ifdef USE_X_TOOLKIT
11173 if (f->output_data.x->menubar_widget)
11174 menubar_height
11175 = (f->output_data.x->menubar_widget->core.height
11176 + f->output_data.x->menubar_widget->core.border_width);
11177#endif
11178
11179 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11180 - 2 * f->output_data.x->border_width
11181 - win_y
11182 - PIXEL_HEIGHT (f)
11183 - menubar_height
11184 + f->output_data.x->top_pos);
11185 }
2e365682 11186
3a35ab44
RS
11187 /* The left_pos and top_pos
11188 are now relative to the top and left screen edges,
11189 so the flags should correspond. */
7556890b 11190 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11191}
11192
3a35ab44
RS
11193/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11194 to really change the position, and 0 when calling from
11195 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11196 position values). It is -1 when calling from x_set_frame_parameters,
11197 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11198
dfcf069d 11199void
dc05a16b 11200x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11201 struct frame *f;
dc6f92b8 11202 register int xoff, yoff;
dc05a16b 11203 int change_gravity;
dc6f92b8 11204{
4a4cbdd5
KH
11205 int modified_top, modified_left;
11206
aa3ff7c9 11207 if (change_gravity > 0)
3a35ab44 11208 {
7556890b
RS
11209 f->output_data.x->top_pos = yoff;
11210 f->output_data.x->left_pos = xoff;
11211 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11212 if (xoff < 0)
7556890b 11213 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11214 if (yoff < 0)
7556890b
RS
11215 f->output_data.x->size_hint_flags |= YNegative;
11216 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11217 }
43bca5d5 11218 x_calc_absolute_position (f);
dc6f92b8
JB
11219
11220 BLOCK_INPUT;
c32cdd9a 11221 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11222
7556890b
RS
11223 modified_left = f->output_data.x->left_pos;
11224 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11225#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11226 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11227 /* It is a mystery why we need to add the border_width here
11228 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11229 if (change_gravity != 0)
4a4cbdd5 11230 {
7556890b
RS
11231 modified_left += f->output_data.x->border_width;
11232 modified_top += f->output_data.x->border_width;
4a4cbdd5 11233 }
e73ec6fa 11234#endif
4a4cbdd5 11235
3afe33e7 11236#ifdef USE_X_TOOLKIT
7556890b 11237 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11238 modified_left, modified_top);
3afe33e7 11239#else /* not USE_X_TOOLKIT */
334208b7 11240 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11241 modified_left, modified_top);
3afe33e7 11242#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11243 UNBLOCK_INPUT;
11244}
11245
bc20ebbf
FP
11246/* Call this to change the size of frame F's x-window.
11247 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11248 for this size change and subsequent size changes.
11249 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11250
dfcf069d 11251void
bc20ebbf 11252x_set_window_size (f, change_gravity, cols, rows)
f676886a 11253 struct frame *f;
bc20ebbf 11254 int change_gravity;
b1c884c3 11255 int cols, rows;
dc6f92b8 11256{
06a2c219 11257#ifndef USE_X_TOOLKIT
dc6f92b8 11258 int pixelwidth, pixelheight;
06a2c219 11259#endif
dc6f92b8 11260
80fd1fe2 11261 BLOCK_INPUT;
aee9a898
RS
11262
11263#ifdef USE_X_TOOLKIT
3a20653d
RS
11264 {
11265 /* The x and y position of the widget is clobbered by the
11266 call to XtSetValues within EmacsFrameSetCharSize.
11267 This is a real kludge, but I don't understand Xt so I can't
11268 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11269 int xpos = f->output_data.x->widget->core.x;
11270 int ypos = f->output_data.x->widget->core.y;
11271 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11272 f->output_data.x->widget->core.x = xpos;
11273 f->output_data.x->widget->core.y = ypos;
3a20653d 11274 }
80fd1fe2
FP
11275
11276#else /* not USE_X_TOOLKIT */
11277
b1c884c3 11278 check_frame_size (f, &rows, &cols);
7556890b 11279 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11280 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11281 ? 0
11282 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11283 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11284 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11285 f->output_data.x->flags_areas_extra
110859fc 11286 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11287 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11288 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11289
7556890b 11290 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11291 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11292
334208b7
RS
11293 XSync (FRAME_X_DISPLAY (f), False);
11294 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11295 pixelwidth, pixelheight);
b1c884c3
JB
11296
11297 /* Now, strictly speaking, we can't be sure that this is accurate,
11298 but the window manager will get around to dealing with the size
11299 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11300 ConfigureNotify event gets here.
11301
11302 We could just not bother storing any of this information here,
11303 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11304 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11305 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11306 point in the future when the ConfigureNotify event arrives.
11307
11308 We pass 1 for DELAY since we can't run Lisp code inside of
11309 a BLOCK_INPUT. */
7d1e984f 11310 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11311 PIXEL_WIDTH (f) = pixelwidth;
11312 PIXEL_HEIGHT (f) = pixelheight;
11313
aee9a898
RS
11314 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11315 receive in the ConfigureNotify event; if we get what we asked
11316 for, then the event won't cause the screen to become garbaged, so
11317 we have to make sure to do it here. */
11318 SET_FRAME_GARBAGED (f);
11319
11320 XFlush (FRAME_X_DISPLAY (f));
11321
11322#endif /* not USE_X_TOOLKIT */
11323
4d73d038 11324 /* If cursor was outside the new size, mark it as off. */
06a2c219 11325 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11326
aee9a898
RS
11327 /* Clear out any recollection of where the mouse highlighting was,
11328 since it might be in a place that's outside the new frame size.
11329 Actually checking whether it is outside is a pain in the neck,
11330 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11331 cancel_mouse_face (f);
dbc4e1c1 11332
dc6f92b8
JB
11333 UNBLOCK_INPUT;
11334}
dc6f92b8 11335\f
d047c4eb 11336/* Mouse warping. */
dc6f92b8 11337
9b378208 11338void
f676886a
JB
11339x_set_mouse_position (f, x, y)
11340 struct frame *f;
dc6f92b8
JB
11341 int x, y;
11342{
11343 int pix_x, pix_y;
11344
7556890b
RS
11345 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11346 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11347
11348 if (pix_x < 0) pix_x = 0;
11349 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11350
11351 if (pix_y < 0) pix_y = 0;
11352 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11353
11354 BLOCK_INPUT;
dc6f92b8 11355
334208b7
RS
11356 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11357 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11358 UNBLOCK_INPUT;
11359}
11360
9b378208
RS
11361/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11362
11363void
11364x_set_mouse_pixel_position (f, pix_x, pix_y)
11365 struct frame *f;
11366 int pix_x, pix_y;
11367{
11368 BLOCK_INPUT;
11369
334208b7
RS
11370 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11371 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11372 UNBLOCK_INPUT;
11373}
d047c4eb
KH
11374\f
11375/* focus shifting, raising and lowering. */
9b378208 11376
dfcf069d 11377void
f676886a
JB
11378x_focus_on_frame (f)
11379 struct frame *f;
dc6f92b8 11380{
1fb20991 11381#if 0 /* This proves to be unpleasant. */
f676886a 11382 x_raise_frame (f);
1fb20991 11383#endif
6d4238f3
JB
11384#if 0
11385 /* I don't think that the ICCCM allows programs to do things like this
11386 without the interaction of the window manager. Whatever you end up
f676886a 11387 doing with this code, do it to x_unfocus_frame too. */
334208b7 11388 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11389 RevertToPointerRoot, CurrentTime);
c118dd06 11390#endif /* ! 0 */
dc6f92b8
JB
11391}
11392
dfcf069d 11393void
f676886a
JB
11394x_unfocus_frame (f)
11395 struct frame *f;
dc6f92b8 11396{
6d4238f3 11397#if 0
f676886a 11398 /* Look at the remarks in x_focus_on_frame. */
0f941935 11399 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11400 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11401 RevertToPointerRoot, CurrentTime);
c118dd06 11402#endif /* ! 0 */
dc6f92b8
JB
11403}
11404
f676886a 11405/* Raise frame F. */
dc6f92b8 11406
dfcf069d 11407void
f676886a
JB
11408x_raise_frame (f)
11409 struct frame *f;
dc6f92b8 11410{
3a88c238 11411 if (f->async_visible)
dc6f92b8
JB
11412 {
11413 BLOCK_INPUT;
3afe33e7 11414#ifdef USE_X_TOOLKIT
7556890b 11415 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11416#else /* not USE_X_TOOLKIT */
334208b7 11417 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11418#endif /* not USE_X_TOOLKIT */
334208b7 11419 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11420 UNBLOCK_INPUT;
11421 }
11422}
11423
f676886a 11424/* Lower frame F. */
dc6f92b8 11425
dfcf069d 11426void
f676886a
JB
11427x_lower_frame (f)
11428 struct frame *f;
dc6f92b8 11429{
3a88c238 11430 if (f->async_visible)
dc6f92b8
JB
11431 {
11432 BLOCK_INPUT;
3afe33e7 11433#ifdef USE_X_TOOLKIT
7556890b 11434 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11435#else /* not USE_X_TOOLKIT */
334208b7 11436 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11437#endif /* not USE_X_TOOLKIT */
334208b7 11438 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11439 UNBLOCK_INPUT;
11440 }
11441}
11442
dbc4e1c1 11443static void
6b0442dc 11444XTframe_raise_lower (f, raise_flag)
dbc4e1c1 11445 FRAME_PTR f;
6b0442dc 11446 int raise_flag;
dbc4e1c1 11447{
6b0442dc 11448 if (raise_flag)
dbc4e1c1
JB
11449 x_raise_frame (f);
11450 else
11451 x_lower_frame (f);
11452}
d047c4eb
KH
11453\f
11454/* Change of visibility. */
dc6f92b8 11455
9382638d
KH
11456/* This tries to wait until the frame is really visible.
11457 However, if the window manager asks the user where to position
11458 the frame, this will return before the user finishes doing that.
11459 The frame will not actually be visible at that time,
11460 but it will become visible later when the window manager
11461 finishes with it. */
11462
dfcf069d 11463void
f676886a
JB
11464x_make_frame_visible (f)
11465 struct frame *f;
dc6f92b8 11466{
990ba854 11467 Lisp_Object type;
1aa6072f 11468 int original_top, original_left;
dc6f92b8 11469
dc6f92b8 11470 BLOCK_INPUT;
dc6f92b8 11471
990ba854
RS
11472 type = x_icon_type (f);
11473 if (!NILP (type))
11474 x_bitmap_icon (f, type);
bdcd49ba 11475
f676886a 11476 if (! FRAME_VISIBLE_P (f))
90e65f07 11477 {
1aa6072f
RS
11478 /* We test FRAME_GARBAGED_P here to make sure we don't
11479 call x_set_offset a second time
11480 if we get to x_make_frame_visible a second time
11481 before the window gets really visible. */
11482 if (! FRAME_ICONIFIED_P (f)
11483 && ! f->output_data.x->asked_for_visible)
11484 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11485
11486 f->output_data.x->asked_for_visible = 1;
11487
90e65f07 11488 if (! EQ (Vx_no_window_manager, Qt))
f676886a 11489 x_wm_set_window_state (f, NormalState);
3afe33e7 11490#ifdef USE_X_TOOLKIT
d7a38a2e 11491 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11492 XtMapWidget (f->output_data.x->widget);
3afe33e7 11493#else /* not USE_X_TOOLKIT */
7f9c7f94 11494 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11495#endif /* not USE_X_TOOLKIT */
0134a210
RS
11496#if 0 /* This seems to bring back scroll bars in the wrong places
11497 if the window configuration has changed. They seem
11498 to come back ok without this. */
ab648270 11499 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 11500 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 11501#endif
90e65f07 11502 }
dc6f92b8 11503
334208b7 11504 XFlush (FRAME_X_DISPLAY (f));
90e65f07 11505
0dacf791
RS
11506 /* Synchronize to ensure Emacs knows the frame is visible
11507 before we do anything else. We do this loop with input not blocked
11508 so that incoming events are handled. */
11509 {
11510 Lisp_Object frame;
12ce2351 11511 int count;
28c01ffe
RS
11512 /* This must be before UNBLOCK_INPUT
11513 since events that arrive in response to the actions above
11514 will set it when they are handled. */
11515 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
11516
11517 original_left = f->output_data.x->left_pos;
11518 original_top = f->output_data.x->top_pos;
c0a04927
RS
11519
11520 /* This must come after we set COUNT. */
11521 UNBLOCK_INPUT;
11522
2745e6c4 11523 /* We unblock here so that arriving X events are processed. */
1aa6072f 11524
dcb07ae9
RS
11525 /* Now move the window back to where it was "supposed to be".
11526 But don't do it if the gravity is negative.
11527 When the gravity is negative, this uses a position
28c01ffe
RS
11528 that is 3 pixels too low. Perhaps that's really the border width.
11529
11530 Don't do this if the window has never been visible before,
11531 because the window manager may choose the position
11532 and we don't want to override it. */
1aa6072f 11533
4d3f5d9a 11534 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 11535 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 11536 && previously_visible)
1aa6072f 11537 {
2745e6c4
RS
11538 Drawable rootw;
11539 int x, y;
11540 unsigned int width, height, border, depth;
06a2c219 11541
1aa6072f 11542 BLOCK_INPUT;
9829ddba 11543
06a2c219
GM
11544 /* On some window managers (such as FVWM) moving an existing
11545 window, even to the same place, causes the window manager
11546 to introduce an offset. This can cause the window to move
11547 to an unexpected location. Check the geometry (a little
11548 slow here) and then verify that the window is in the right
11549 place. If the window is not in the right place, move it
11550 there, and take the potential window manager hit. */
2745e6c4
RS
11551 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11552 &rootw, &x, &y, &width, &height, &border, &depth);
11553
11554 if (original_left != x || original_top != y)
11555 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11556 original_left, original_top);
11557
1aa6072f
RS
11558 UNBLOCK_INPUT;
11559 }
9829ddba 11560
e0c1aef2 11561 XSETFRAME (frame, f);
c0a04927 11562
12ce2351
GM
11563 /* Wait until the frame is visible. Process X events until a
11564 MapNotify event has been seen, or until we think we won't get a
11565 MapNotify at all.. */
11566 for (count = input_signal_count + 10;
11567 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 11568 {
12ce2351 11569 /* Force processing of queued events. */
334208b7 11570 x_sync (f);
12ce2351
GM
11571
11572 /* Machines that do polling rather than SIGIO have been
11573 observed to go into a busy-wait here. So we'll fake an
11574 alarm signal to let the handler know that there's something
11575 to be read. We used to raise a real alarm, but it seems
11576 that the handler isn't always enabled here. This is
11577 probably a bug. */
8b2f8d4e 11578 if (input_polling_used ())
3b2fa4e6 11579 {
12ce2351
GM
11580 /* It could be confusing if a real alarm arrives while
11581 processing the fake one. Turn it off and let the
11582 handler reset it. */
bffcfca9
GM
11583 int old_poll_suppress_count = poll_suppress_count;
11584 poll_suppress_count = 1;
11585 poll_for_input_1 ();
11586 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 11587 }
12ce2351
GM
11588
11589 /* See if a MapNotify event has been processed. */
11590 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 11591 }
0dacf791 11592 }
dc6f92b8
JB
11593}
11594
06a2c219 11595/* Change from mapped state to withdrawn state. */
dc6f92b8 11596
d047c4eb
KH
11597/* Make the frame visible (mapped and not iconified). */
11598
dfcf069d 11599void
f676886a
JB
11600x_make_frame_invisible (f)
11601 struct frame *f;
dc6f92b8 11602{
546e6d5b
RS
11603 Window window;
11604
11605#ifdef USE_X_TOOLKIT
11606 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11607 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11608#else /* not USE_X_TOOLKIT */
11609 window = FRAME_X_WINDOW (f);
11610#endif /* not USE_X_TOOLKIT */
dc6f92b8 11611
9319ae23 11612 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11613 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11614 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11615
5627c40e 11616#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 11617 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 11618 return;
5627c40e 11619#endif
dc6f92b8
JB
11620
11621 BLOCK_INPUT;
c118dd06 11622
af31d76f
RS
11623 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11624 that the current position of the window is user-specified, rather than
11625 program-specified, so that when the window is mapped again, it will be
11626 placed at the same location, without forcing the user to position it
11627 by hand again (they have already done that once for this window.) */
c32cdd9a 11628 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 11629
c118dd06
JB
11630#ifdef HAVE_X11R4
11631
334208b7
RS
11632 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11633 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
11634 {
11635 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11636 error ("Can't notify window manager of window withdrawal");
c118dd06 11637 }
c118dd06 11638#else /* ! defined (HAVE_X11R4) */
16bd92ea 11639
c118dd06 11640 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
11641 if (! EQ (Vx_no_window_manager, Qt))
11642 {
16bd92ea 11643 XEvent unmap;
dc6f92b8 11644
16bd92ea 11645 unmap.xunmap.type = UnmapNotify;
546e6d5b 11646 unmap.xunmap.window = window;
334208b7 11647 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 11648 unmap.xunmap.from_configure = False;
334208b7
RS
11649 if (! XSendEvent (FRAME_X_DISPLAY (f),
11650 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 11651 False,
06a2c219 11652 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
11653 &unmap))
11654 {
11655 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11656 error ("Can't notify window manager of withdrawal");
16bd92ea 11657 }
dc6f92b8
JB
11658 }
11659
16bd92ea 11660 /* Unmap the window ourselves. Cheeky! */
334208b7 11661 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 11662#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 11663
5627c40e
RS
11664 /* We can't distinguish this from iconification
11665 just by the event that we get from the server.
11666 So we can't win using the usual strategy of letting
11667 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11668 and synchronize with the server to make sure we agree. */
11669 f->visible = 0;
11670 FRAME_ICONIFIED_P (f) = 0;
11671 f->async_visible = 0;
11672 f->async_iconified = 0;
11673
334208b7 11674 x_sync (f);
5627c40e 11675
dc6f92b8
JB
11676 UNBLOCK_INPUT;
11677}
11678
06a2c219 11679/* Change window state from mapped to iconified. */
dc6f92b8 11680
dfcf069d 11681void
f676886a
JB
11682x_iconify_frame (f)
11683 struct frame *f;
dc6f92b8 11684{
3afe33e7 11685 int result;
990ba854 11686 Lisp_Object type;
dc6f92b8 11687
9319ae23 11688 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11689 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11690 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11691
3a88c238 11692 if (f->async_iconified)
dc6f92b8
JB
11693 return;
11694
3afe33e7 11695 BLOCK_INPUT;
546e6d5b 11696
9af3143a
RS
11697 FRAME_SAMPLE_VISIBILITY (f);
11698
990ba854
RS
11699 type = x_icon_type (f);
11700 if (!NILP (type))
11701 x_bitmap_icon (f, type);
bdcd49ba
RS
11702
11703#ifdef USE_X_TOOLKIT
11704
546e6d5b
RS
11705 if (! FRAME_VISIBLE_P (f))
11706 {
11707 if (! EQ (Vx_no_window_manager, Qt))
11708 x_wm_set_window_state (f, IconicState);
11709 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11710 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
11711 /* The server won't give us any event to indicate
11712 that an invisible frame was changed to an icon,
11713 so we have to record it here. */
11714 f->iconified = 1;
1e6bc770 11715 f->visible = 1;
9cf30a30 11716 f->async_iconified = 1;
1e6bc770 11717 f->async_visible = 0;
546e6d5b
RS
11718 UNBLOCK_INPUT;
11719 return;
11720 }
11721
334208b7 11722 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 11723 XtWindow (f->output_data.x->widget),
334208b7 11724 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
11725 UNBLOCK_INPUT;
11726
11727 if (!result)
546e6d5b 11728 error ("Can't notify window manager of iconification");
3afe33e7
RS
11729
11730 f->async_iconified = 1;
1e6bc770
RS
11731 f->async_visible = 0;
11732
8c002a25
KH
11733
11734 BLOCK_INPUT;
334208b7 11735 XFlush (FRAME_X_DISPLAY (f));
8c002a25 11736 UNBLOCK_INPUT;
3afe33e7
RS
11737#else /* not USE_X_TOOLKIT */
11738
fd13dbb2
RS
11739 /* Make sure the X server knows where the window should be positioned,
11740 in case the user deiconifies with the window manager. */
11741 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 11742 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 11743
16bd92ea
JB
11744 /* Since we don't know which revision of X we're running, we'll use both
11745 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11746
11747 /* X11R4: send a ClientMessage to the window manager using the
11748 WM_CHANGE_STATE type. */
11749 {
11750 XEvent message;
58769bee 11751
c118dd06 11752 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 11753 message.xclient.type = ClientMessage;
334208b7 11754 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
11755 message.xclient.format = 32;
11756 message.xclient.data.l[0] = IconicState;
11757
334208b7
RS
11758 if (! XSendEvent (FRAME_X_DISPLAY (f),
11759 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
11760 False,
11761 SubstructureRedirectMask | SubstructureNotifyMask,
11762 &message))
dc6f92b8
JB
11763 {
11764 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11765 error ("Can't notify window manager of iconification");
dc6f92b8 11766 }
16bd92ea 11767 }
dc6f92b8 11768
58769bee 11769 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
11770 IconicState. */
11771 x_wm_set_window_state (f, IconicState);
dc6f92b8 11772
a9c00105
RS
11773 if (!FRAME_VISIBLE_P (f))
11774 {
11775 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 11776 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
11777 }
11778
3a88c238 11779 f->async_iconified = 1;
1e6bc770 11780 f->async_visible = 0;
dc6f92b8 11781
334208b7 11782 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 11783 UNBLOCK_INPUT;
8c002a25 11784#endif /* not USE_X_TOOLKIT */
dc6f92b8 11785}
d047c4eb 11786\f
c0ff3fab 11787/* Destroy the X window of frame F. */
dc6f92b8 11788
dfcf069d 11789void
c0ff3fab 11790x_destroy_window (f)
f676886a 11791 struct frame *f;
dc6f92b8 11792{
7f9c7f94
RS
11793 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11794
dc6f92b8 11795 BLOCK_INPUT;
c0ff3fab 11796
6186a4a0
RS
11797 /* If a display connection is dead, don't try sending more
11798 commands to the X server. */
11799 if (dpyinfo->display != 0)
11800 {
11801 if (f->output_data.x->icon_desc != 0)
11802 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 11803#ifdef HAVE_X_I18N
f5d11644
GM
11804 if (FRAME_XIC (f))
11805 free_frame_xic (f);
31f41daf 11806#endif
6186a4a0 11807 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 11808#ifdef USE_X_TOOLKIT
06a2c219
GM
11809 if (f->output_data.x->widget)
11810 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 11811 free_frame_menubar (f);
3afe33e7
RS
11812#endif /* USE_X_TOOLKIT */
11813
6186a4a0
RS
11814 free_frame_faces (f);
11815 XFlush (FRAME_X_DISPLAY (f));
11816 }
dc6f92b8 11817
df89d8a4 11818 if (f->output_data.x->saved_menu_event)
06a2c219 11819 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 11820
7556890b
RS
11821 xfree (f->output_data.x);
11822 f->output_data.x = 0;
0f941935
KH
11823 if (f == dpyinfo->x_focus_frame)
11824 dpyinfo->x_focus_frame = 0;
11825 if (f == dpyinfo->x_focus_event_frame)
11826 dpyinfo->x_focus_event_frame = 0;
11827 if (f == dpyinfo->x_highlight_frame)
11828 dpyinfo->x_highlight_frame = 0;
c0ff3fab 11829
7f9c7f94
RS
11830 dpyinfo->reference_count--;
11831
11832 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 11833 {
7f9c7f94
RS
11834 dpyinfo->mouse_face_beg_row
11835 = dpyinfo->mouse_face_beg_col = -1;
11836 dpyinfo->mouse_face_end_row
11837 = dpyinfo->mouse_face_end_col = -1;
11838 dpyinfo->mouse_face_window = Qnil;
21323706
RS
11839 dpyinfo->mouse_face_deferred_gc = 0;
11840 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 11841 }
0134a210 11842
c0ff3fab 11843 UNBLOCK_INPUT;
dc6f92b8
JB
11844}
11845\f
f451eb13
JB
11846/* Setting window manager hints. */
11847
af31d76f
RS
11848/* Set the normal size hints for the window manager, for frame F.
11849 FLAGS is the flags word to use--or 0 meaning preserve the flags
11850 that the window now has.
11851 If USER_POSITION is nonzero, we set the USPosition
11852 flag (this is useful when FLAGS is 0). */
6dba1858 11853
dfcf069d 11854void
af31d76f 11855x_wm_set_size_hint (f, flags, user_position)
f676886a 11856 struct frame *f;
af31d76f
RS
11857 long flags;
11858 int user_position;
dc6f92b8
JB
11859{
11860 XSizeHints size_hints;
3afe33e7
RS
11861
11862#ifdef USE_X_TOOLKIT
7e4f2521
FP
11863 Arg al[2];
11864 int ac = 0;
11865 Dimension widget_width, widget_height;
7556890b 11866 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 11867#else /* not USE_X_TOOLKIT */
c118dd06 11868 Window window = FRAME_X_WINDOW (f);
3afe33e7 11869#endif /* not USE_X_TOOLKIT */
dc6f92b8 11870
b72a58fd
RS
11871 /* Setting PMaxSize caused various problems. */
11872 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 11873
7556890b
RS
11874 size_hints.x = f->output_data.x->left_pos;
11875 size_hints.y = f->output_data.x->top_pos;
7553a6b7 11876
7e4f2521
FP
11877#ifdef USE_X_TOOLKIT
11878 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11879 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 11880 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
11881 size_hints.height = widget_height;
11882 size_hints.width = widget_width;
11883#else /* not USE_X_TOOLKIT */
f676886a
JB
11884 size_hints.height = PIXEL_HEIGHT (f);
11885 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 11886#endif /* not USE_X_TOOLKIT */
7553a6b7 11887
7556890b
RS
11888 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11889 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
11890 size_hints.max_width
11891 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11892 size_hints.max_height
11893 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 11894
d067ea8b
KH
11895 /* Calculate the base and minimum sizes.
11896
11897 (When we use the X toolkit, we don't do it here.
11898 Instead we copy the values that the widgets are using, below.) */
11899#ifndef USE_X_TOOLKIT
b1c884c3 11900 {
b0342f17 11901 int base_width, base_height;
0134a210 11902 int min_rows = 0, min_cols = 0;
b0342f17 11903
f451eb13
JB
11904 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11905 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 11906
0134a210 11907 check_frame_size (f, &min_rows, &min_cols);
b0342f17 11908
0134a210
RS
11909 /* The window manager uses the base width hints to calculate the
11910 current number of rows and columns in the frame while
11911 resizing; min_width and min_height aren't useful for this
11912 purpose, since they might not give the dimensions for a
11913 zero-row, zero-column frame.
58769bee 11914
0134a210
RS
11915 We use the base_width and base_height members if we have
11916 them; otherwise, we set the min_width and min_height members
11917 to the size for a zero x zero frame. */
b0342f17
JB
11918
11919#ifdef HAVE_X11R4
0134a210
RS
11920 size_hints.flags |= PBaseSize;
11921 size_hints.base_width = base_width;
11922 size_hints.base_height = base_height;
11923 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
11924 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 11925#else
0134a210
RS
11926 size_hints.min_width = base_width;
11927 size_hints.min_height = base_height;
b0342f17 11928#endif
b1c884c3 11929 }
dc6f92b8 11930
d067ea8b 11931 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 11932 if (flags)
dc6f92b8 11933 {
d067ea8b
KH
11934 size_hints.flags |= flags;
11935 goto no_read;
11936 }
11937#endif /* not USE_X_TOOLKIT */
11938
11939 {
11940 XSizeHints hints; /* Sometimes I hate X Windows... */
11941 long supplied_return;
11942 int value;
af31d76f
RS
11943
11944#ifdef HAVE_X11R4
d067ea8b
KH
11945 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
11946 &supplied_return);
af31d76f 11947#else
d067ea8b 11948 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 11949#endif
58769bee 11950
d067ea8b
KH
11951#ifdef USE_X_TOOLKIT
11952 size_hints.base_height = hints.base_height;
11953 size_hints.base_width = hints.base_width;
11954 size_hints.min_height = hints.min_height;
11955 size_hints.min_width = hints.min_width;
11956#endif
11957
11958 if (flags)
11959 size_hints.flags |= flags;
11960 else
11961 {
11962 if (value == 0)
11963 hints.flags = 0;
11964 if (hints.flags & PSize)
11965 size_hints.flags |= PSize;
11966 if (hints.flags & PPosition)
11967 size_hints.flags |= PPosition;
11968 if (hints.flags & USPosition)
11969 size_hints.flags |= USPosition;
11970 if (hints.flags & USSize)
11971 size_hints.flags |= USSize;
11972 }
11973 }
11974
06a2c219 11975#ifndef USE_X_TOOLKIT
d067ea8b 11976 no_read:
06a2c219 11977#endif
0134a210 11978
af31d76f 11979#ifdef PWinGravity
7556890b 11980 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 11981 size_hints.flags |= PWinGravity;
dc05a16b 11982
af31d76f 11983 if (user_position)
6dba1858 11984 {
af31d76f
RS
11985 size_hints.flags &= ~ PPosition;
11986 size_hints.flags |= USPosition;
6dba1858 11987 }
2554751d 11988#endif /* PWinGravity */
6dba1858 11989
b0342f17 11990#ifdef HAVE_X11R4
334208b7 11991 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 11992#else
334208b7 11993 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 11994#endif
dc6f92b8
JB
11995}
11996
11997/* Used for IconicState or NormalState */
06a2c219 11998
dfcf069d 11999void
f676886a
JB
12000x_wm_set_window_state (f, state)
12001 struct frame *f;
dc6f92b8
JB
12002 int state;
12003{
3afe33e7 12004#ifdef USE_X_TOOLKIT
546e6d5b
RS
12005 Arg al[1];
12006
12007 XtSetArg (al[0], XtNinitialState, state);
7556890b 12008 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12009#else /* not USE_X_TOOLKIT */
c118dd06 12010 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12011
7556890b
RS
12012 f->output_data.x->wm_hints.flags |= StateHint;
12013 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12014
7556890b 12015 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12016#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12017}
12018
dfcf069d 12019void
7f2ae036 12020x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12021 struct frame *f;
7f2ae036 12022 int pixmap_id;
dc6f92b8 12023{
d2bd6bc4
RS
12024 Pixmap icon_pixmap;
12025
06a2c219 12026#ifndef USE_X_TOOLKIT
c118dd06 12027 Window window = FRAME_X_WINDOW (f);
75231bad 12028#endif
dc6f92b8 12029
7f2ae036 12030 if (pixmap_id > 0)
dbc4e1c1 12031 {
d2bd6bc4 12032 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12033 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12034 }
12035 else
68568555
RS
12036 {
12037 /* It seems there is no way to turn off use of an icon pixmap.
12038 The following line does it, only if no icon has yet been created,
12039 for some window managers. But with mwm it crashes.
12040 Some people say it should clear the IconPixmapHint bit in this case,
12041 but that doesn't work, and the X consortium said it isn't the
12042 right thing at all. Since there is no way to win,
12043 best to explicitly give up. */
12044#if 0
12045 f->output_data.x->wm_hints.icon_pixmap = None;
12046#else
12047 return;
12048#endif
12049 }
b1c884c3 12050
d2bd6bc4
RS
12051#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12052
12053 {
12054 Arg al[1];
12055 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12056 XtSetValues (f->output_data.x->widget, al, 1);
12057 }
12058
12059#else /* not USE_X_TOOLKIT */
12060
7556890b
RS
12061 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12062 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12063
12064#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12065}
12066
dfcf069d 12067void
f676886a
JB
12068x_wm_set_icon_position (f, icon_x, icon_y)
12069 struct frame *f;
dc6f92b8
JB
12070 int icon_x, icon_y;
12071{
75231bad 12072#ifdef USE_X_TOOLKIT
7556890b 12073 Window window = XtWindow (f->output_data.x->widget);
75231bad 12074#else
c118dd06 12075 Window window = FRAME_X_WINDOW (f);
75231bad 12076#endif
dc6f92b8 12077
7556890b
RS
12078 f->output_data.x->wm_hints.flags |= IconPositionHint;
12079 f->output_data.x->wm_hints.icon_x = icon_x;
12080 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12081
7556890b 12082 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12083}
12084
12085\f
06a2c219
GM
12086/***********************************************************************
12087 Fonts
12088 ***********************************************************************/
dc43ef94
KH
12089
12090/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12091
dc43ef94
KH
12092struct font_info *
12093x_get_font_info (f, font_idx)
12094 FRAME_PTR f;
12095 int font_idx;
12096{
12097 return (FRAME_X_FONT_TABLE (f) + font_idx);
12098}
12099
12100
12101/* Return a list of names of available fonts matching PATTERN on frame
12102 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12103 to be listed. Frame F NULL means we have not yet created any
12104 frame on X, and consult the first display in x_display_list.
12105 MAXNAMES sets a limit on how many fonts to match. */
12106
12107Lisp_Object
12108x_list_fonts (f, pattern, size, maxnames)
12109 FRAME_PTR f;
12110 Lisp_Object pattern;
12111 int size;
12112 int maxnames;
12113{
06a2c219
GM
12114 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12115 Lisp_Object tem, second_best;
dc43ef94 12116 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12117 int try_XLoadQueryFont = 0;
53ca4657 12118 int count;
dc43ef94 12119
6b0efe73 12120 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12121 if (NILP (patterns))
12122 patterns = Fcons (pattern, Qnil);
81ba44e5 12123
09c6077f
KH
12124 if (maxnames == 1 && !size)
12125 /* We can return any single font matching PATTERN. */
12126 try_XLoadQueryFont = 1;
9a32686f 12127
8e713be6 12128 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12129 {
dc43ef94
KH
12130 int num_fonts;
12131 char **names;
12132
8e713be6 12133 pattern = XCAR (patterns);
536f4067
RS
12134 /* See if we cached the result for this particular query.
12135 The cache is an alist of the form:
12136 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12137 */
8e713be6 12138 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12139 key = Fcons (pattern, make_number (maxnames)),
12140 !NILP (list = Fassoc (key, tem))))
12141 {
12142 list = Fcdr_safe (list);
12143 /* We have a cashed list. Don't have to get the list again. */
12144 goto label_cached;
12145 }
12146
12147 /* At first, put PATTERN in the cache. */
09c6077f 12148
dc43ef94 12149 BLOCK_INPUT;
17d85edc
KH
12150 count = x_catch_errors (dpy);
12151
09c6077f
KH
12152 if (try_XLoadQueryFont)
12153 {
12154 XFontStruct *font;
12155 unsigned long value;
12156
12157 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12158 if (x_had_errors_p (dpy))
12159 {
12160 /* This error is perhaps due to insufficient memory on X
12161 server. Let's just ignore it. */
12162 font = NULL;
12163 x_clear_errors (dpy);
12164 }
12165
09c6077f
KH
12166 if (font
12167 && XGetFontProperty (font, XA_FONT, &value))
12168 {
12169 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12170 int len = strlen (name);
01c752b5 12171 char *tmp;
09c6077f 12172
6f6512e8
KH
12173 /* If DXPC (a Differential X Protocol Compressor)
12174 Ver.3.7 is running, XGetAtomName will return null
12175 string. We must avoid such a name. */
12176 if (len == 0)
12177 try_XLoadQueryFont = 0;
12178 else
12179 {
12180 num_fonts = 1;
12181 names = (char **) alloca (sizeof (char *));
12182 /* Some systems only allow alloca assigned to a
12183 simple var. */
12184 tmp = (char *) alloca (len + 1); names[0] = tmp;
12185 bcopy (name, names[0], len + 1);
12186 XFree (name);
12187 }
09c6077f
KH
12188 }
12189 else
12190 try_XLoadQueryFont = 0;
a083fd23
RS
12191
12192 if (font)
12193 XFreeFont (dpy, font);
09c6077f
KH
12194 }
12195
12196 if (!try_XLoadQueryFont)
17d85edc
KH
12197 {
12198 /* We try at least 10 fonts because XListFonts will return
12199 auto-scaled fonts at the head. */
12200 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12201 &num_fonts);
12202 if (x_had_errors_p (dpy))
12203 {
12204 /* This error is perhaps due to insufficient memory on X
12205 server. Let's just ignore it. */
12206 names = NULL;
12207 x_clear_errors (dpy);
12208 }
12209 }
12210
12211 x_uncatch_errors (dpy, count);
dc43ef94
KH
12212 UNBLOCK_INPUT;
12213
12214 if (names)
12215 {
12216 int i;
dc43ef94
KH
12217
12218 /* Make a list of all the fonts we got back.
12219 Store that in the font cache for the display. */
12220 for (i = 0; i < num_fonts; i++)
12221 {
06a2c219 12222 int width = 0;
dc43ef94 12223 char *p = names[i];
06a2c219
GM
12224 int average_width = -1, dashes = 0;
12225
dc43ef94 12226 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12227 14 dashes, and the field value following 12th dash
12228 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12229 is usually too ugly to be used for editing. Let's
12230 ignore it. */
dc43ef94
KH
12231 while (*p)
12232 if (*p++ == '-')
12233 {
12234 dashes++;
12235 if (dashes == 7) /* PIXEL_SIZE field */
12236 width = atoi (p);
12237 else if (dashes == 12) /* AVERAGE_WIDTH field */
12238 average_width = atoi (p);
12239 }
12240 if (dashes < 14 || average_width != 0)
12241 {
12242 tem = build_string (names[i]);
12243 if (NILP (Fassoc (tem, list)))
12244 {
12245 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12246 && ((fast_c_string_match_ignore_case
12247 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12248 >= 0))
12249 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12250 width of this font. */
dc43ef94
KH
12251 list = Fcons (Fcons (tem, make_number (width)), list);
12252 else
12253 /* For the moment, width is not known. */
12254 list = Fcons (Fcons (tem, Qnil), list);
12255 }
12256 }
12257 }
09c6077f
KH
12258 if (!try_XLoadQueryFont)
12259 XFreeFontNames (names);
dc43ef94
KH
12260 }
12261
b5210ea7 12262 /* Now store the result in the cache. */
dc43ef94 12263 if (f != NULL)
8e713be6 12264 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12265 = Fcons (Fcons (key, list),
8e713be6 12266 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12267
b5210ea7
KH
12268 label_cached:
12269 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12270
b5210ea7
KH
12271 newlist = second_best = Qnil;
12272 /* Make a list of the fonts that have the right width. */
8e713be6 12273 for (; CONSP (list); list = XCDR (list))
b5210ea7 12274 {
536f4067
RS
12275 int found_size;
12276
8e713be6 12277 tem = XCAR (list);
dc43ef94 12278
8e713be6 12279 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12280 continue;
12281 if (!size)
12282 {
8e713be6 12283 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12284 continue;
12285 }
dc43ef94 12286
8e713be6 12287 if (!INTEGERP (XCDR (tem)))
dc43ef94 12288 {
b5210ea7
KH
12289 /* Since we have not yet known the size of this font, we
12290 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12291 XFontStruct *thisinfo;
12292
12293 BLOCK_INPUT;
17d85edc 12294 count = x_catch_errors (dpy);
dc43ef94 12295 thisinfo = XLoadQueryFont (dpy,
8e713be6 12296 XSTRING (XCAR (tem))->data);
17d85edc
KH
12297 if (x_had_errors_p (dpy))
12298 {
12299 /* This error is perhaps due to insufficient memory on X
12300 server. Let's just ignore it. */
12301 thisinfo = NULL;
12302 x_clear_errors (dpy);
12303 }
12304 x_uncatch_errors (dpy, count);
dc43ef94
KH
12305 UNBLOCK_INPUT;
12306
12307 if (thisinfo)
12308 {
8e713be6 12309 XCDR (tem)
536f4067
RS
12310 = (thisinfo->min_bounds.width == 0
12311 ? make_number (0)
12312 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12313 XFreeFont (dpy, thisinfo);
12314 }
12315 else
b5210ea7 12316 /* For unknown reason, the previous call of XListFont had
06a2c219 12317 returned a font which can't be opened. Record the size
b5210ea7 12318 as 0 not to try to open it again. */
8e713be6 12319 XCDR (tem) = make_number (0);
dc43ef94 12320 }
536f4067 12321
8e713be6 12322 found_size = XINT (XCDR (tem));
536f4067 12323 if (found_size == size)
8e713be6 12324 newlist = Fcons (XCAR (tem), newlist);
536f4067 12325 else if (found_size > 0)
b5210ea7 12326 {
536f4067 12327 if (NILP (second_best))
b5210ea7 12328 second_best = tem;
536f4067
RS
12329 else if (found_size < size)
12330 {
8e713be6
KR
12331 if (XINT (XCDR (second_best)) > size
12332 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12333 second_best = tem;
12334 }
12335 else
12336 {
8e713be6
KR
12337 if (XINT (XCDR (second_best)) > size
12338 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12339 second_best = tem;
12340 }
b5210ea7
KH
12341 }
12342 }
12343 if (!NILP (newlist))
12344 break;
12345 else if (!NILP (second_best))
12346 {
8e713be6 12347 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12348 break;
dc43ef94 12349 }
dc43ef94
KH
12350 }
12351
12352 return newlist;
12353}
12354
06a2c219
GM
12355
12356#if GLYPH_DEBUG
12357
12358/* Check that FONT is valid on frame F. It is if it can be found in F's
12359 font table. */
12360
12361static void
12362x_check_font (f, font)
12363 struct frame *f;
12364 XFontStruct *font;
12365{
12366 int i;
12367 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12368
12369 xassert (font != NULL);
12370
12371 for (i = 0; i < dpyinfo->n_fonts; i++)
12372 if (dpyinfo->font_table[i].name
12373 && font == dpyinfo->font_table[i].font)
12374 break;
12375
12376 xassert (i < dpyinfo->n_fonts);
12377}
12378
12379#endif /* GLYPH_DEBUG != 0 */
12380
12381/* Set *W to the minimum width, *H to the minimum font height of FONT.
12382 Note: There are (broken) X fonts out there with invalid XFontStruct
12383 min_bounds contents. For example, handa@etl.go.jp reports that
12384 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12385 have font->min_bounds.width == 0. */
12386
12387static INLINE void
12388x_font_min_bounds (font, w, h)
12389 XFontStruct *font;
12390 int *w, *h;
12391{
12392 *h = FONT_HEIGHT (font);
12393 *w = font->min_bounds.width;
12394
12395 /* Try to handle the case where FONT->min_bounds has invalid
12396 contents. Since the only font known to have invalid min_bounds
12397 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12398 if (*w <= 0)
12399 *w = font->max_bounds.width;
12400}
12401
12402
12403/* Compute the smallest character width and smallest font height over
12404 all fonts available on frame F. Set the members smallest_char_width
12405 and smallest_font_height in F's x_display_info structure to
12406 the values computed. Value is non-zero if smallest_font_height or
12407 smallest_char_width become smaller than they were before. */
12408
12409static int
12410x_compute_min_glyph_bounds (f)
12411 struct frame *f;
12412{
12413 int i;
12414 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12415 XFontStruct *font;
12416 int old_width = dpyinfo->smallest_char_width;
12417 int old_height = dpyinfo->smallest_font_height;
12418
12419 dpyinfo->smallest_font_height = 100000;
12420 dpyinfo->smallest_char_width = 100000;
12421
12422 for (i = 0; i < dpyinfo->n_fonts; ++i)
12423 if (dpyinfo->font_table[i].name)
12424 {
12425 struct font_info *fontp = dpyinfo->font_table + i;
12426 int w, h;
12427
12428 font = (XFontStruct *) fontp->font;
12429 xassert (font != (XFontStruct *) ~0);
12430 x_font_min_bounds (font, &w, &h);
12431
12432 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12433 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12434 }
12435
12436 xassert (dpyinfo->smallest_char_width > 0
12437 && dpyinfo->smallest_font_height > 0);
12438
12439 return (dpyinfo->n_fonts == 1
12440 || dpyinfo->smallest_char_width < old_width
12441 || dpyinfo->smallest_font_height < old_height);
12442}
12443
12444
dc43ef94
KH
12445/* Load font named FONTNAME of the size SIZE for frame F, and return a
12446 pointer to the structure font_info while allocating it dynamically.
12447 If SIZE is 0, load any size of font.
12448 If loading is failed, return NULL. */
12449
12450struct font_info *
12451x_load_font (f, fontname, size)
12452 struct frame *f;
12453 register char *fontname;
12454 int size;
12455{
12456 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12457 Lisp_Object font_names;
d645aaa4 12458 int count;
dc43ef94
KH
12459
12460 /* Get a list of all the fonts that match this name. Once we
12461 have a list of matching fonts, we compare them against the fonts
12462 we already have by comparing names. */
09c6077f 12463 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
12464
12465 if (!NILP (font_names))
12466 {
12467 Lisp_Object tail;
12468 int i;
12469
12470 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 12471 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
12472 if (dpyinfo->font_table[i].name
12473 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 12474 XSTRING (XCAR (tail))->data)
06a2c219 12475 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 12476 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
12477 return (dpyinfo->font_table + i);
12478 }
12479
12480 /* Load the font and add it to the table. */
12481 {
12482 char *full_name;
12483 XFontStruct *font;
12484 struct font_info *fontp;
12485 unsigned long value;
06a2c219 12486 int i;
dc43ef94 12487
2da424f1
KH
12488 /* If we have found fonts by x_list_font, load one of them. If
12489 not, we still try to load a font by the name given as FONTNAME
12490 because XListFonts (called in x_list_font) of some X server has
12491 a bug of not finding a font even if the font surely exists and
12492 is loadable by XLoadQueryFont. */
e1d6d5b9 12493 if (size > 0 && !NILP (font_names))
8e713be6 12494 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
12495
12496 BLOCK_INPUT;
d645aaa4 12497 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 12498 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
12499 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12500 {
12501 /* This error is perhaps due to insufficient memory on X
12502 server. Let's just ignore it. */
12503 font = NULL;
12504 x_clear_errors (FRAME_X_DISPLAY (f));
12505 }
12506 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 12507 UNBLOCK_INPUT;
b5210ea7 12508 if (!font)
dc43ef94
KH
12509 return NULL;
12510
06a2c219
GM
12511 /* Find a free slot in the font table. */
12512 for (i = 0; i < dpyinfo->n_fonts; ++i)
12513 if (dpyinfo->font_table[i].name == NULL)
12514 break;
12515
12516 /* If no free slot found, maybe enlarge the font table. */
12517 if (i == dpyinfo->n_fonts
12518 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 12519 {
06a2c219
GM
12520 int sz;
12521 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12522 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 12523 dpyinfo->font_table
06a2c219 12524 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
12525 }
12526
06a2c219
GM
12527 fontp = dpyinfo->font_table + i;
12528 if (i == dpyinfo->n_fonts)
12529 ++dpyinfo->n_fonts;
dc43ef94
KH
12530
12531 /* Now fill in the slots of *FONTP. */
12532 BLOCK_INPUT;
12533 fontp->font = font;
06a2c219 12534 fontp->font_idx = i;
dc43ef94
KH
12535 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12536 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12537
12538 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12539 full_name = 0;
12540 if (XGetFontProperty (font, XA_FONT, &value))
12541 {
12542 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12543 char *p = name;
12544 int dashes = 0;
12545
12546 /* Count the number of dashes in the "full name".
12547 If it is too few, this isn't really the font's full name,
12548 so don't use it.
12549 In X11R4, the fonts did not come with their canonical names
12550 stored in them. */
12551 while (*p)
12552 {
12553 if (*p == '-')
12554 dashes++;
12555 p++;
12556 }
12557
12558 if (dashes >= 13)
12559 {
12560 full_name = (char *) xmalloc (p - name + 1);
12561 bcopy (name, full_name, p - name + 1);
12562 }
12563
12564 XFree (name);
12565 }
12566
12567 if (full_name != 0)
12568 fontp->full_name = full_name;
12569 else
12570 fontp->full_name = fontp->name;
12571
12572 fontp->size = font->max_bounds.width;
d5749adb
KH
12573 fontp->height = FONT_HEIGHT (font);
12574 {
12575 /* For some font, ascent and descent in max_bounds field is
12576 larger than the above value. */
12577 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12578 if (max_height > fontp->height)
74848a96 12579 fontp->height = max_height;
d5749adb 12580 }
dc43ef94 12581
2da424f1
KH
12582 if (NILP (font_names))
12583 {
12584 /* We come here because of a bug of XListFonts mentioned at
12585 the head of this block. Let's store this information in
12586 the cache for x_list_fonts. */
12587 Lisp_Object lispy_name = build_string (fontname);
12588 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12589
8e713be6 12590 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12591 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12592 Fcons (Fcons (lispy_full_name,
12593 make_number (fontp->size)),
12594 Qnil)),
8e713be6 12595 XCDR (dpyinfo->name_list_element));
2da424f1 12596 if (full_name)
8e713be6 12597 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12598 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12599 Fcons (Fcons (lispy_full_name,
12600 make_number (fontp->size)),
12601 Qnil)),
8e713be6 12602 XCDR (dpyinfo->name_list_element));
2da424f1
KH
12603 }
12604
dc43ef94
KH
12605 /* The slot `encoding' specifies how to map a character
12606 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
12607 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12608 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 12609 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 12610 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
12611 which is never used by any charset. If mapping can't be
12612 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
12613 fontp->encoding[1]
12614 = (font->max_byte1 == 0
12615 /* 1-byte font */
12616 ? (font->min_char_or_byte2 < 0x80
12617 ? (font->max_char_or_byte2 < 0x80
12618 ? 0 /* 0x20..0x7F */
8ff102bd 12619 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
12620 : 1) /* 0xA0..0xFF */
12621 /* 2-byte font */
12622 : (font->min_byte1 < 0x80
12623 ? (font->max_byte1 < 0x80
12624 ? (font->min_char_or_byte2 < 0x80
12625 ? (font->max_char_or_byte2 < 0x80
12626 ? 0 /* 0x2020..0x7F7F */
8ff102bd 12627 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 12628 : 3) /* 0x20A0..0x7FFF */
8ff102bd 12629 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
12630 : (font->min_char_or_byte2 < 0x80
12631 ? (font->max_char_or_byte2 < 0x80
12632 ? 2 /* 0xA020..0xFF7F */
8ff102bd 12633 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
12634 : 1))); /* 0xA0A0..0xFFFF */
12635
12636 fontp->baseline_offset
12637 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12638 ? (long) value : 0);
12639 fontp->relative_compose
12640 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12641 ? (long) value : 0);
f78798df
KH
12642 fontp->default_ascent
12643 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12644 ? (long) value : 0);
dc43ef94 12645
06a2c219
GM
12646 /* Set global flag fonts_changed_p to non-zero if the font loaded
12647 has a character with a smaller width than any other character
12648 before, or if the font loaded has a smalle>r height than any
12649 other font loaded before. If this happens, it will make a
12650 glyph matrix reallocation necessary. */
12651 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 12652 UNBLOCK_INPUT;
dc43ef94
KH
12653 return fontp;
12654 }
12655}
12656
06a2c219
GM
12657
12658/* Return a pointer to struct font_info of a font named FONTNAME for
12659 frame F. If no such font is loaded, return NULL. */
12660
dc43ef94
KH
12661struct font_info *
12662x_query_font (f, fontname)
12663 struct frame *f;
12664 register char *fontname;
12665{
12666 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12667 int i;
12668
12669 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
12670 if (dpyinfo->font_table[i].name
12671 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12672 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
12673 return (dpyinfo->font_table + i);
12674 return NULL;
12675}
12676
06a2c219
GM
12677
12678/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
12679 `encoder' of the structure. */
12680
12681void
12682x_find_ccl_program (fontp)
12683 struct font_info *fontp;
12684{
a42f54e6 12685 Lisp_Object list, elt;
a6582676 12686
8e713be6 12687 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 12688 {
8e713be6 12689 elt = XCAR (list);
a6582676 12690 if (CONSP (elt)
8e713be6
KR
12691 && STRINGP (XCAR (elt))
12692 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
a6582676 12693 >= 0))
a42f54e6
KH
12694 break;
12695 }
12696 if (! NILP (list))
12697 {
d27f8ca7
KH
12698 struct ccl_program *ccl
12699 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 12700
8e713be6 12701 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
12702 xfree (ccl);
12703 else
12704 fontp->font_encoder = ccl;
a6582676
KH
12705 }
12706}
12707
06a2c219 12708
dc43ef94 12709\f
06a2c219
GM
12710/***********************************************************************
12711 Initialization
12712 ***********************************************************************/
f451eb13 12713
3afe33e7
RS
12714#ifdef USE_X_TOOLKIT
12715static XrmOptionDescRec emacs_options[] = {
12716 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12717 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12718
12719 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12720 XrmoptionSepArg, NULL},
12721 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12722
12723 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12724 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12725 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12726 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12727 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12728 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12729 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12730};
12731#endif /* USE_X_TOOLKIT */
12732
7a13e894
RS
12733static int x_initialized;
12734
29b38361
KH
12735#ifdef MULTI_KBOARD
12736/* Test whether two display-name strings agree up to the dot that separates
12737 the screen number from the server number. */
12738static int
12739same_x_server (name1, name2)
12740 char *name1, *name2;
12741{
12742 int seen_colon = 0;
cf591cc1
RS
12743 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12744 int system_name_length = strlen (system_name);
12745 int length_until_period = 0;
12746
12747 while (system_name[length_until_period] != 0
12748 && system_name[length_until_period] != '.')
12749 length_until_period++;
12750
12751 /* Treat `unix' like an empty host name. */
12752 if (! strncmp (name1, "unix:", 5))
12753 name1 += 4;
12754 if (! strncmp (name2, "unix:", 5))
12755 name2 += 4;
12756 /* Treat this host's name like an empty host name. */
12757 if (! strncmp (name1, system_name, system_name_length)
12758 && name1[system_name_length] == ':')
12759 name1 += system_name_length;
12760 if (! strncmp (name2, system_name, system_name_length)
12761 && name2[system_name_length] == ':')
12762 name2 += system_name_length;
12763 /* Treat this host's domainless name like an empty host name. */
12764 if (! strncmp (name1, system_name, length_until_period)
12765 && name1[length_until_period] == ':')
12766 name1 += length_until_period;
12767 if (! strncmp (name2, system_name, length_until_period)
12768 && name2[length_until_period] == ':')
12769 name2 += length_until_period;
12770
29b38361
KH
12771 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12772 {
12773 if (*name1 == ':')
12774 seen_colon++;
12775 if (seen_colon && *name1 == '.')
12776 return 1;
12777 }
12778 return (seen_colon
12779 && (*name1 == '.' || *name1 == '\0')
12780 && (*name2 == '.' || *name2 == '\0'));
12781}
12782#endif
12783
334208b7 12784struct x_display_info *
1f8255f2 12785x_term_init (display_name, xrm_option, resource_name)
334208b7 12786 Lisp_Object display_name;
1f8255f2
RS
12787 char *xrm_option;
12788 char *resource_name;
dc6f92b8 12789{
334208b7 12790 int connection;
7a13e894 12791 Display *dpy;
334208b7
RS
12792 struct x_display_info *dpyinfo;
12793 XrmDatabase xrdb;
12794
60439948
KH
12795 BLOCK_INPUT;
12796
7a13e894
RS
12797 if (!x_initialized)
12798 {
12799 x_initialize ();
12800 x_initialized = 1;
12801 }
dc6f92b8 12802
3afe33e7 12803#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
12804 /* weiner@footloose.sps.mot.com reports that this causes
12805 errors with X11R5:
12806 X protocol error: BadAtom (invalid Atom parameter)
12807 on protocol request 18skiloaf.
12808 So let's not use it until R6. */
12809#ifdef HAVE_X11XTR6
bdcd49ba
RS
12810 XtSetLanguageProc (NULL, NULL, NULL);
12811#endif
12812
7f9c7f94
RS
12813 {
12814 int argc = 0;
12815 char *argv[3];
12816
12817 argv[0] = "";
12818 argc = 1;
12819 if (xrm_option)
12820 {
12821 argv[argc++] = "-xrm";
12822 argv[argc++] = xrm_option;
12823 }
12824 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12825 resource_name, EMACS_CLASS,
12826 emacs_options, XtNumber (emacs_options),
12827 &argc, argv);
39d8bb4d
KH
12828
12829#ifdef HAVE_X11XTR6
10537cb1 12830 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 12831 fixup_locale ();
39d8bb4d 12832#endif
7f9c7f94 12833 }
3afe33e7
RS
12834
12835#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
12836#ifdef HAVE_X11R5
12837 XSetLocaleModifiers ("");
12838#endif
7a13e894 12839 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 12840#endif /* not USE_X_TOOLKIT */
334208b7 12841
7a13e894
RS
12842 /* Detect failure. */
12843 if (dpy == 0)
60439948
KH
12844 {
12845 UNBLOCK_INPUT;
12846 return 0;
12847 }
7a13e894
RS
12848
12849 /* We have definitely succeeded. Record the new connection. */
12850
12851 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12852
29b38361
KH
12853#ifdef MULTI_KBOARD
12854 {
12855 struct x_display_info *share;
12856 Lisp_Object tail;
12857
12858 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
12859 share = share->next, tail = XCDR (tail))
12860 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
12861 XSTRING (display_name)->data))
12862 break;
12863 if (share)
12864 dpyinfo->kboard = share->kboard;
12865 else
12866 {
12867 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12868 init_kboard (dpyinfo->kboard);
59e755be
KH
12869 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12870 {
12871 char *vendor = ServerVendor (dpy);
12872 dpyinfo->kboard->Vsystem_key_alist
12873 = call1 (Qvendor_specific_keysyms,
12874 build_string (vendor ? vendor : ""));
12875 }
12876
29b38361
KH
12877 dpyinfo->kboard->next_kboard = all_kboards;
12878 all_kboards = dpyinfo->kboard;
0ad5446c
KH
12879 /* Don't let the initial kboard remain current longer than necessary.
12880 That would cause problems if a file loaded on startup tries to
06a2c219 12881 prompt in the mini-buffer. */
0ad5446c
KH
12882 if (current_kboard == initial_kboard)
12883 current_kboard = dpyinfo->kboard;
29b38361
KH
12884 }
12885 dpyinfo->kboard->reference_count++;
12886 }
b9737ad3
KH
12887#endif
12888
7a13e894
RS
12889 /* Put this display on the chain. */
12890 dpyinfo->next = x_display_list;
12891 x_display_list = dpyinfo;
12892
12893 /* Put it on x_display_name_list as well, to keep them parallel. */
12894 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12895 x_display_name_list);
8e713be6 12896 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
12897
12898 dpyinfo->display = dpy;
dc6f92b8 12899
dc6f92b8 12900#if 0
7a13e894 12901 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 12902#endif /* ! 0 */
7a13e894
RS
12903
12904 dpyinfo->x_id_name
fc932ac6
RS
12905 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12906 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
12907 + 2);
12908 sprintf (dpyinfo->x_id_name, "%s@%s",
12909 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
12910
12911 /* Figure out which modifier bits mean what. */
334208b7 12912 x_find_modifier_meanings (dpyinfo);
f451eb13 12913
ab648270 12914 /* Get the scroll bar cursor. */
7a13e894 12915 dpyinfo->vertical_scroll_bar_cursor
334208b7 12916 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 12917
334208b7
RS
12918 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12919 resource_name, EMACS_CLASS);
12920#ifdef HAVE_XRMSETDATABASE
12921 XrmSetDatabase (dpyinfo->display, xrdb);
12922#else
12923 dpyinfo->display->db = xrdb;
12924#endif
547d9db8 12925 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
12926 all versions. */
12927 dpyinfo->xrdb = xrdb;
334208b7
RS
12928
12929 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12930 DefaultScreen (dpyinfo->display));
5ff67d81 12931 select_visual (dpyinfo);
43bd1b2b 12932 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
12933 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
12934 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
12935 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12936 dpyinfo->grabbed = 0;
12937 dpyinfo->reference_count = 0;
12938 dpyinfo->icon_bitmap_id = -1;
06a2c219 12939 dpyinfo->font_table = NULL;
7a13e894
RS
12940 dpyinfo->n_fonts = 0;
12941 dpyinfo->font_table_size = 0;
12942 dpyinfo->bitmaps = 0;
12943 dpyinfo->bitmaps_size = 0;
12944 dpyinfo->bitmaps_last = 0;
12945 dpyinfo->scratch_cursor_gc = 0;
12946 dpyinfo->mouse_face_mouse_frame = 0;
12947 dpyinfo->mouse_face_deferred_gc = 0;
12948 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12949 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 12950 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
12951 dpyinfo->mouse_face_window = Qnil;
12952 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
12953 dpyinfo->mouse_face_defer = 0;
0f941935
KH
12954 dpyinfo->x_focus_frame = 0;
12955 dpyinfo->x_focus_event_frame = 0;
12956 dpyinfo->x_highlight_frame = 0;
06a2c219 12957 dpyinfo->image_cache = make_image_cache ();
334208b7 12958
43bd1b2b 12959 /* See if a private colormap is requested. */
5ff67d81
GM
12960 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
12961 {
12962 if (dpyinfo->visual->class == PseudoColor)
12963 {
12964 Lisp_Object value;
12965 value = display_x_get_resource (dpyinfo,
12966 build_string ("privateColormap"),
12967 build_string ("PrivateColormap"),
12968 Qnil, Qnil);
12969 if (STRINGP (value)
12970 && (!strcmp (XSTRING (value)->data, "true")
12971 || !strcmp (XSTRING (value)->data, "on")))
12972 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
12973 }
43bd1b2b 12974 }
5ff67d81
GM
12975 else
12976 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
12977 dpyinfo->visual, AllocNone);
43bd1b2b 12978
06a2c219
GM
12979 {
12980 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
12981 double pixels = DisplayHeight (dpyinfo->display, screen_number);
12982 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
12983 dpyinfo->resy = pixels * 25.4 / mm;
12984 pixels = DisplayWidth (dpyinfo->display, screen_number);
12985 mm = DisplayWidthMM (dpyinfo->display, screen_number);
12986 dpyinfo->resx = pixels * 25.4 / mm;
12987 }
12988
334208b7
RS
12989 dpyinfo->Xatom_wm_protocols
12990 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
12991 dpyinfo->Xatom_wm_take_focus
12992 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
12993 dpyinfo->Xatom_wm_save_yourself
12994 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
12995 dpyinfo->Xatom_wm_delete_window
12996 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
12997 dpyinfo->Xatom_wm_change_state
12998 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
12999 dpyinfo->Xatom_wm_configure_denied
13000 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13001 dpyinfo->Xatom_wm_window_moved
13002 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13003 dpyinfo->Xatom_editres
13004 = XInternAtom (dpyinfo->display, "Editres", False);
13005 dpyinfo->Xatom_CLIPBOARD
13006 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13007 dpyinfo->Xatom_TIMESTAMP
13008 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13009 dpyinfo->Xatom_TEXT
13010 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13011 dpyinfo->Xatom_COMPOUND_TEXT
13012 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13013 dpyinfo->Xatom_DELETE
13014 = XInternAtom (dpyinfo->display, "DELETE", False);
13015 dpyinfo->Xatom_MULTIPLE
13016 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13017 dpyinfo->Xatom_INCR
13018 = XInternAtom (dpyinfo->display, "INCR", False);
13019 dpyinfo->Xatom_EMACS_TMP
13020 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13021 dpyinfo->Xatom_TARGETS
13022 = XInternAtom (dpyinfo->display, "TARGETS", False);
13023 dpyinfo->Xatom_NULL
13024 = XInternAtom (dpyinfo->display, "NULL", False);
13025 dpyinfo->Xatom_ATOM_PAIR
13026 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13027 /* For properties of font. */
13028 dpyinfo->Xatom_PIXEL_SIZE
13029 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13030 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13031 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13032 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13033 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13034 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13035 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13036
06a2c219
GM
13037 /* Ghostscript support. */
13038 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13039 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13040
13041 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13042 False);
13043
547d9db8
KH
13044 dpyinfo->cut_buffers_initialized = 0;
13045
334208b7
RS
13046 connection = ConnectionNumber (dpyinfo->display);
13047 dpyinfo->connection = connection;
13048
dc43ef94 13049 {
5d7cc324
RS
13050 char null_bits[1];
13051
13052 null_bits[0] = 0x00;
dc43ef94
KH
13053
13054 dpyinfo->null_pixel
13055 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13056 null_bits, 1, 1, (long) 0, (long) 0,
13057 1);
13058 }
13059
06a2c219
GM
13060 {
13061 extern int gray_bitmap_width, gray_bitmap_height;
13062 extern unsigned char *gray_bitmap_bits;
13063 dpyinfo->gray
13064 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13065 gray_bitmap_bits,
13066 gray_bitmap_width, gray_bitmap_height,
13067 (unsigned long) 1, (unsigned long) 0, 1);
13068 }
13069
f5d11644
GM
13070#ifdef HAVE_X_I18N
13071 xim_initialize (dpyinfo, resource_name);
13072#endif
13073
87485d6f
MW
13074#ifdef subprocesses
13075 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13076 if (connection != 0)
7a13e894 13077 add_keyboard_wait_descriptor (connection);
87485d6f 13078#endif
6d4238f3 13079
041b69ac 13080#ifndef F_SETOWN_BUG
dc6f92b8 13081#ifdef F_SETOWN
dc6f92b8 13082#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13083 /* stdin is a socket here */
334208b7 13084 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13085#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13086 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13087#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13088#endif /* ! defined (F_SETOWN) */
041b69ac 13089#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13090
13091#ifdef SIGIO
eee20f6a
KH
13092 if (interrupt_input)
13093 init_sigio (connection);
c118dd06 13094#endif /* ! defined (SIGIO) */
dc6f92b8 13095
51b592fb 13096#ifdef USE_LUCID
f8c39f51 13097#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13098 /* Make sure that we have a valid font for dialog boxes
13099 so that Xt does not crash. */
13100 {
13101 Display *dpy = dpyinfo->display;
13102 XrmValue d, fr, to;
13103 Font font;
e99db5a1 13104 int count;
51b592fb
RS
13105
13106 d.addr = (XPointer)&dpy;
13107 d.size = sizeof (Display *);
13108 fr.addr = XtDefaultFont;
13109 fr.size = sizeof (XtDefaultFont);
13110 to.size = sizeof (Font *);
13111 to.addr = (XPointer)&font;
e99db5a1 13112 count = x_catch_errors (dpy);
51b592fb
RS
13113 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13114 abort ();
13115 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13116 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13117 x_uncatch_errors (dpy, count);
51b592fb
RS
13118 }
13119#endif
f8c39f51 13120#endif
51b592fb 13121
34e23e5a
GM
13122 /* See if we should run in synchronous mode. This is useful
13123 for debugging X code. */
13124 {
13125 Lisp_Object value;
13126 value = display_x_get_resource (dpyinfo,
13127 build_string ("synchronous"),
13128 build_string ("Synchronous"),
13129 Qnil, Qnil);
13130 if (STRINGP (value)
13131 && (!strcmp (XSTRING (value)->data, "true")
13132 || !strcmp (XSTRING (value)->data, "on")))
13133 XSynchronize (dpyinfo->display, True);
13134 }
13135
60439948
KH
13136 UNBLOCK_INPUT;
13137
7a13e894
RS
13138 return dpyinfo;
13139}
13140\f
13141/* Get rid of display DPYINFO, assuming all frames are already gone,
13142 and without sending any more commands to the X server. */
dc6f92b8 13143
7a13e894
RS
13144void
13145x_delete_display (dpyinfo)
13146 struct x_display_info *dpyinfo;
13147{
13148 delete_keyboard_wait_descriptor (dpyinfo->connection);
13149
13150 /* Discard this display from x_display_name_list and x_display_list.
13151 We can't use Fdelq because that can quit. */
13152 if (! NILP (x_display_name_list)
8e713be6
KR
13153 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13154 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13155 else
13156 {
13157 Lisp_Object tail;
13158
13159 tail = x_display_name_list;
8e713be6 13160 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13161 {
bffcfca9 13162 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13163 {
8e713be6 13164 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13165 break;
13166 }
8e713be6 13167 tail = XCDR (tail);
7a13e894
RS
13168 }
13169 }
13170
9bda743f
GM
13171 if (next_noop_dpyinfo == dpyinfo)
13172 next_noop_dpyinfo = dpyinfo->next;
13173
7a13e894
RS
13174 if (x_display_list == dpyinfo)
13175 x_display_list = dpyinfo->next;
7f9c7f94
RS
13176 else
13177 {
13178 struct x_display_info *tail;
7a13e894 13179
7f9c7f94
RS
13180 for (tail = x_display_list; tail; tail = tail->next)
13181 if (tail->next == dpyinfo)
13182 tail->next = tail->next->next;
13183 }
7a13e894 13184
0d777288
RS
13185#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13186#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13187 XrmDestroyDatabase (dpyinfo->xrdb);
13188#endif
0d777288 13189#endif
29b38361
KH
13190#ifdef MULTI_KBOARD
13191 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13192 delete_kboard (dpyinfo->kboard);
b9737ad3 13193#endif
f5d11644
GM
13194#ifdef HAVE_X_I18N
13195 if (dpyinfo->xim)
13196 xim_close_dpy (dpyinfo);
13197#endif
13198
b9737ad3
KH
13199 xfree (dpyinfo->font_table);
13200 xfree (dpyinfo->x_id_name);
13201 xfree (dpyinfo);
7a13e894
RS
13202}
13203\f
13204/* Set up use of X before we make the first connection. */
13205
06a2c219
GM
13206static struct redisplay_interface x_redisplay_interface =
13207{
13208 x_produce_glyphs,
13209 x_write_glyphs,
13210 x_insert_glyphs,
13211 x_clear_end_of_line,
13212 x_scroll_run,
13213 x_after_update_window_line,
13214 x_update_window_begin,
13215 x_update_window_end,
13216 XTcursor_to,
13217 x_flush,
66ac4b0e
GM
13218 x_get_glyph_overhangs,
13219 x_fix_overlapping_area
06a2c219
GM
13220};
13221
dfcf069d 13222void
7a13e894
RS
13223x_initialize ()
13224{
06a2c219
GM
13225 rif = &x_redisplay_interface;
13226
13227 clear_frame_hook = x_clear_frame;
13228 ins_del_lines_hook = x_ins_del_lines;
13229 change_line_highlight_hook = x_change_line_highlight;
13230 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13231 ring_bell_hook = XTring_bell;
13232 reset_terminal_modes_hook = XTreset_terminal_modes;
13233 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13234 update_begin_hook = x_update_begin;
13235 update_end_hook = x_update_end;
dc6f92b8
JB
13236 set_terminal_window_hook = XTset_terminal_window;
13237 read_socket_hook = XTread_socket;
b8009dd1 13238 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13239 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13240 mouse_position_hook = XTmouse_position;
f451eb13 13241 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13242 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13243 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13244 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13245 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13246 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13247 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13248
f676886a 13249 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13250 char_ins_del_ok = 0; /* just as fast to write the line */
13251 line_ins_del_ok = 1; /* we'll just blt 'em */
13252 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13253 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13254 off the bottom */
13255 baud_rate = 19200;
13256
7a13e894 13257 x_noop_count = 0;
9ea173e8 13258 last_tool_bar_item = -1;
06a2c219
GM
13259 any_help_event_p = 0;
13260
b30b24cb
RS
13261 /* Try to use interrupt input; if we can't, then start polling. */
13262 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13263
7f9c7f94
RS
13264#ifdef USE_X_TOOLKIT
13265 XtToolkitInitialize ();
13266 Xt_app_con = XtCreateApplicationContext ();
665881ad 13267 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13268
13269 /* Install an asynchronous timer that processes Xt timeout events
13270 every 0.1s. This is necessary because some widget sets use
13271 timeouts internally, for example the LessTif menu bar, or the
13272 Xaw3d scroll bar. When Xt timouts aren't processed, these
13273 widgets don't behave normally. */
13274 {
13275 EMACS_TIME interval;
13276 EMACS_SET_SECS_USECS (interval, 0, 100000);
13277 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13278 }
db74249b 13279#endif
bffcfca9 13280
db74249b 13281#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13282 xaw3d_arrow_scroll = False;
13283 xaw3d_pick_top = True;
7f9c7f94
RS
13284#endif
13285
58769bee 13286 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13287 original error handler. */
e99db5a1 13288 XSetErrorHandler (x_error_handler);
334208b7 13289 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13290
06a2c219 13291 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13292#ifdef SIGWINCH
13293 signal (SIGWINCH, SIG_DFL);
c118dd06 13294#endif /* ! defined (SIGWINCH) */
dc6f92b8 13295
92e2441b 13296 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13297}
55123275 13298
06a2c219 13299
55123275
JB
13300void
13301syms_of_xterm ()
13302{
e99db5a1
RS
13303 staticpro (&x_error_message_string);
13304 x_error_message_string = Qnil;
13305
7a13e894
RS
13306 staticpro (&x_display_name_list);
13307 x_display_name_list = Qnil;
334208b7 13308
ab648270 13309 staticpro (&last_mouse_scroll_bar);
e53cb100 13310 last_mouse_scroll_bar = Qnil;
59e755be
KH
13311
13312 staticpro (&Qvendor_specific_keysyms);
13313 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13314
13315 staticpro (&last_mouse_press_frame);
13316 last_mouse_press_frame = Qnil;
06a2c219
GM
13317
13318 staticpro (&help_echo);
13319 help_echo = Qnil;
13320 staticpro (&previous_help_echo);
13321 previous_help_echo = Qnil;
13322
13323 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13324 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13325For example, if a block cursor is over a tab, it will be drawn as\n\
13326wide as that tab on the display.");
13327 x_stretch_cursor_p = 0;
13328
13329 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13330 "If not nil, Emacs uses toolkit scroll bars.");
13331#if USE_TOOLKIT_SCROLL_BARS
13332 x_toolkit_scroll_bars_p = 1;
13333#else
13334 x_toolkit_scroll_bars_p = 0;
13335#endif
13336
06a2c219
GM
13337 staticpro (&last_mouse_motion_frame);
13338 last_mouse_motion_frame = Qnil;
55123275 13339}
6cf0ae86
RS
13340
13341#endif /* not HAVE_X_WINDOWS */
06a2c219 13342