(menu_highlight_callback): Store help string in the
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
1c7e22fd 2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000
06a2c219 3 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
06a2c219 22/* New display code by Gerd Moellmann <gerd@gnu.org>. */
3afe33e7
RS
23/* Xt features made by Fred Pierresteguy. */
24
68c45bf0
PE
25#include <config.h>
26
039440c4 27/* On 4.3 these lose if they come after xterm.h. */
039440c4 28/* Putting these at the beginning seems to be standard for other .c files. */
039440c4
RS
29#include <signal.h>
30
4846819e
RS
31#include <stdio.h>
32
dc6f92b8
JB
33#ifdef HAVE_X_WINDOWS
34
35#include "lisp.h"
9ac0d9e0 36#include "blockinput.h"
dc6f92b8 37
ae79c227
AS
38/* Need syssignal.h for various externs and definitions that may be required
39 by some configurations for calls to signal later in this source file. */
40#include "syssignal.h"
41
dc6f92b8
JB
42/* This may include sys/types.h, and that somehow loses
43 if this is not done before the other system files. */
44#include "xterm.h"
f451eb13 45#include <X11/cursorfont.h>
dc6f92b8
JB
46
47/* Load sys/types.h if not already loaded.
48 In some systems loading it twice is suicidal. */
49#ifndef makedev
50#include <sys/types.h>
c118dd06 51#endif /* makedev */
dc6f92b8 52
6df54671 53#ifdef BSD_SYSTEM
dc6f92b8 54#include <sys/ioctl.h>
6df54671 55#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 56
2d368234 57#include "systty.h"
3a2712f9 58#include "systime.h"
dc6f92b8 59
b8009dd1 60#ifndef INCLUDED_FCNTL
dc6f92b8 61#include <fcntl.h>
b8009dd1 62#endif
dc6f92b8
JB
63#include <ctype.h>
64#include <errno.h>
65#include <setjmp.h>
66#include <sys/stat.h>
a0a7635f
RS
67/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
68/* #include <sys/param.h> */
dc6f92b8 69
dc43ef94
KH
70#include "charset.h"
71#include "ccl.h"
7a13e894 72#include "frame.h"
dc6f92b8 73#include "dispextern.h"
ee569018 74#include "fontset.h"
dc6f92b8
JB
75#include "termhooks.h"
76#include "termopts.h"
77#include "termchar.h"
78#if 0
79#include "sink.h"
80#include "sinkmask.h"
c118dd06 81#endif /* ! 0 */
dc6f92b8 82#include "gnu.h"
dc6f92b8 83#include "disptab.h"
dc6f92b8 84#include "buffer.h"
f451eb13 85#include "window.h"
3b2fa4e6 86#include "keyboard.h"
bde7c500 87#include "intervals.h"
dfcf069d 88#include "process.h"
bffcfca9 89#include "atimer.h"
dc6f92b8 90
d2bd6bc4
RS
91#ifdef USE_X_TOOLKIT
92#include <X11/Shell.h>
93#endif
94
06a2c219
GM
95#ifdef HAVE_SYS_TIME_H
96#include <sys/time.h>
97#endif
98#ifdef HAVE_UNISTD_H
99#include <unistd.h>
100#endif
101
3afe33e7 102#ifdef USE_X_TOOLKIT
06a2c219 103
9d7e2e3e 104extern void free_frame_menubar ();
2224b905 105extern FRAME_PTR x_menubar_window_to_frame ();
06a2c219 106
0fdff6bb
RS
107#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
108#define HACK_EDITRES
109extern void _XEditResCheckMessages ();
110#endif /* not NO_EDITRES */
06a2c219
GM
111
112/* Include toolkit specific headers for the scroll bar widget. */
113
114#ifdef USE_TOOLKIT_SCROLL_BARS
115#if defined USE_MOTIF
116#include <Xm/Xm.h> /* for LESSTIF_VERSION */
117#include <Xm/ScrollBar.h>
118#include <Xm/ScrollBarP.h>
ec18280f
SM
119#else /* !USE_MOTIF i.e. use Xaw */
120
121#ifdef HAVE_XAW3D
06a2c219 122#include <X11/Xaw3d/Simple.h>
06a2c219
GM
123#include <X11/Xaw3d/Scrollbar.h>
124#define ARROW_SCROLLBAR
125#include <X11/Xaw3d/ScrollbarP.h>
ec18280f
SM
126#else /* !HAVE_XAW3D */
127#include <X11/Xaw/Simple.h>
128#include <X11/Xaw/Scrollbar.h>
129#endif /* !HAVE_XAW3D */
130#ifndef XtNpickTop
131#define XtNpickTop "pickTop"
132#endif /* !XtNpickTop */
133#endif /* !USE_MOTIF */
06a2c219
GM
134#endif /* USE_TOOLKIT_SCROLL_BARS */
135
3afe33e7
RS
136#endif /* USE_X_TOOLKIT */
137
b849c413
RS
138#ifndef USE_X_TOOLKIT
139#define x_any_window_to_frame x_window_to_frame
5627c40e 140#define x_top_window_to_frame x_window_to_frame
b849c413
RS
141#endif
142
546e6d5b 143#ifdef USE_X_TOOLKIT
d067ea8b 144#include "widget.h"
546e6d5b
RS
145#ifndef XtNinitialState
146#define XtNinitialState "initialState"
147#endif
148#endif
149
80528801
KH
150#ifdef SOLARIS2
151/* memmove will be defined as a macro in Xfuncs.h unless
152 <string.h> is included beforehand. The declaration for memmove in
153 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
154#include <string.h>
155#endif
156
e4b68333 157#ifndef min
06a2c219 158#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
159#endif
160#ifndef max
06a2c219
GM
161#define max(a,b) ((a) > (b) ? (a) : (b))
162#endif
163
164#define abs(x) ((x) < 0 ? -(x) : (x))
165
166#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
167
168\f
169/* Bitmaps for truncated lines. */
170
171enum bitmap_type
172{
173 NO_BITMAP,
174 LEFT_TRUNCATION_BITMAP,
175 RIGHT_TRUNCATION_BITMAP,
176 OVERLAY_ARROW_BITMAP,
177 CONTINUED_LINE_BITMAP,
178 CONTINUATION_LINE_BITMAP,
179 ZV_LINE_BITMAP
180};
181
182/* Bitmap drawn to indicate lines not displaying text if
183 `indicate-empty-lines' is non-nil. */
184
185#define zv_width 8
186#define zv_height 8
187static unsigned char zv_bits[] = {
188 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
189
190/* An arrow like this: `<-'. */
191
192#define left_width 8
193#define left_height 8
194static unsigned char left_bits[] = {
195 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
196
110859fc
GM
197/* Right truncation arrow bitmap `->'. */
198
199#define right_width 8
200#define right_height 8
201static unsigned char right_bits[] = {
202 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
203
06a2c219
GM
204/* Marker for continued lines. */
205
206#define continued_width 8
207#define continued_height 8
208static unsigned char continued_bits[] = {
110859fc
GM
209 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
210
211/* Marker for continuation lines. */
06a2c219
GM
212
213#define continuation_width 8
214#define continuation_height 8
215static unsigned char continuation_bits[] = {
110859fc 216 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
06a2c219 217
110859fc 218/* Overlay arrow bitmap. */
06a2c219 219
110859fc
GM
220#if 0
221/* A bomb. */
06a2c219
GM
222#define ov_width 8
223#define ov_height 8
224static unsigned char ov_bits[] = {
225 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
06a2c219 226#else
110859fc 227/* A triangular arrow. */
06a2c219
GM
228#define ov_width 8
229#define ov_height 8
230static unsigned char ov_bits[] = {
110859fc
GM
231 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
232
e4b68333 233#endif
06a2c219
GM
234
235extern Lisp_Object Qhelp_echo;
236
69388238 237\f
06a2c219
GM
238/* Non-zero means Emacs uses toolkit scroll bars. */
239
240int x_toolkit_scroll_bars_p;
241
242/* If a string, XTread_socket generates an event to display that string.
243 (The display is done in read_char.) */
244
245static Lisp_Object help_echo;
246
247/* Temporary variable for XTread_socket. */
248
249static Lisp_Object previous_help_echo;
250
251/* Non-zero means that a HELP_EVENT has been generated since Emacs
252 start. */
253
254static int any_help_event_p;
255
256/* Non-zero means draw block and hollow cursor as wide as the glyph
257 under it. For example, if a block cursor is over a tab, it will be
258 drawn as wide as that tab on the display. */
259
260int x_stretch_cursor_p;
261
262/* This is a chain of structures for all the X displays currently in
263 use. */
264
334208b7 265struct x_display_info *x_display_list;
dc6f92b8 266
06a2c219
GM
267/* This is a list of cons cells, each of the form (NAME
268 . FONT-LIST-CACHE), one for each element of x_display_list and in
269 the same order. NAME is the name of the frame. FONT-LIST-CACHE
270 records previous values returned by x-list-fonts. */
271
7a13e894 272Lisp_Object x_display_name_list;
f451eb13 273
987d2ad1 274/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
275 This is set by update_begin and looked at by all the XT functions.
276 It is zero while not inside an update. In that case, the XT
277 functions assume that `selected_frame' is the frame to apply to. */
278
d0386f2a 279extern struct frame *updating_frame;
dc6f92b8 280
dfcf069d 281extern int waiting_for_input;
0e81d8cd 282
06a2c219
GM
283/* This is a frame waiting to be auto-raised, within XTread_socket. */
284
0134a210
RS
285struct frame *pending_autoraise_frame;
286
7f9c7f94
RS
287#ifdef USE_X_TOOLKIT
288/* The application context for Xt use. */
289XtAppContext Xt_app_con;
06a2c219
GM
290static String Xt_default_resources[] = {0};
291#endif /* USE_X_TOOLKIT */
665881ad 292
06a2c219
GM
293/* Nominal cursor position -- where to draw output.
294 HPOS and VPOS are window relative glyph matrix coordinates.
295 X and Y are window relative pixel coordinates. */
dc6f92b8 296
06a2c219 297struct cursor_pos output_cursor;
dc6f92b8 298
bffcfca9
GM
299/* Non-zero means user is interacting with a toolkit scroll bar. */
300
301static int toolkit_scroll_bar_interaction;
dc6f92b8 302
69388238
RS
303/* Mouse movement.
304
06a2c219 305 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
306 so that we would have to call XQueryPointer after each MotionNotify
307 event to ask for another such event. However, this made mouse tracking
308 slow, and there was a bug that made it eventually stop.
309
310 Simply asking for MotionNotify all the time seems to work better.
311
69388238
RS
312 In order to avoid asking for motion events and then throwing most
313 of them away or busy-polling the server for mouse positions, we ask
314 the server for pointer motion hints. This means that we get only
315 one event per group of mouse movements. "Groups" are delimited by
316 other kinds of events (focus changes and button clicks, for
317 example), or by XQueryPointer calls; when one of these happens, we
318 get another MotionNotify event the next time the mouse moves. This
319 is at least as efficient as getting motion events when mouse
320 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 321 is off. */
69388238
RS
322
323/* Where the mouse was last time we reported a mouse event. */
69388238 324
06a2c219
GM
325FRAME_PTR last_mouse_frame;
326static XRectangle last_mouse_glyph;
2237cac9
RS
327static Lisp_Object last_mouse_press_frame;
328
69388238
RS
329/* The scroll bar in which the last X motion event occurred.
330
06a2c219
GM
331 If the last X motion event occurred in a scroll bar, we set this so
332 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
333 an ordinary motion.
334
06a2c219
GM
335 If the last X motion event didn't occur in a scroll bar, we set
336 this to Qnil, to tell XTmouse_position to return an ordinary motion
337 event. */
338
69388238
RS
339static Lisp_Object last_mouse_scroll_bar;
340
69388238
RS
341/* This is a hack. We would really prefer that XTmouse_position would
342 return the time associated with the position it returns, but there
06a2c219 343 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
344 along with the position query. So, we just keep track of the time
345 of the last movement we received, and return that in hopes that
346 it's somewhat accurate. */
06a2c219 347
69388238
RS
348static Time last_mouse_movement_time;
349
06a2c219
GM
350/* Incremented by XTread_socket whenever it really tries to read
351 events. */
352
c0a04927
RS
353#ifdef __STDC__
354static int volatile input_signal_count;
355#else
356static int input_signal_count;
357#endif
358
7a13e894 359/* Used locally within XTread_socket. */
06a2c219 360
7a13e894 361static int x_noop_count;
dc6f92b8 362
7a13e894 363/* Initial values of argv and argc. */
06a2c219 364
7a13e894
RS
365extern char **initial_argv;
366extern int initial_argc;
dc6f92b8 367
7a13e894 368extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 369
06a2c219 370/* Tells if a window manager is present or not. */
7a13e894
RS
371
372extern Lisp_Object Vx_no_window_manager;
dc6f92b8 373
c2df547c 374extern Lisp_Object Qface, Qmouse_face;
b8009dd1 375
dc6f92b8
JB
376extern int errno;
377
dfeccd2d 378/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 379
64bb1782
RS
380extern int extra_keyboard_modifiers;
381
59e755be
KH
382static Lisp_Object Qvendor_specific_keysyms;
383
334208b7 384extern XrmDatabase x_load_resources ();
c32cdd9a
KH
385extern Lisp_Object x_icon_type ();
386
7a13e894 387
06a2c219
GM
388/* Enumeration for overriding/changing the face to use for drawing
389 glyphs in x_draw_glyphs. */
390
391enum draw_glyphs_face
392{
393 DRAW_NORMAL_TEXT,
394 DRAW_INVERSE_VIDEO,
395 DRAW_CURSOR,
396 DRAW_MOUSE_FACE,
397 DRAW_IMAGE_RAISED,
398 DRAW_IMAGE_SUNKEN
399};
400
71b8321e 401static void x_update_window_end P_ ((struct window *, int, int));
06a2c219
GM
402static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
403void x_delete_display P_ ((struct x_display_info *));
404static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
405 unsigned));
406static int fast_find_position P_ ((struct window *, int, int *, int *,
407 int *, int *));
408static void set_output_cursor P_ ((struct cursor_pos *));
409static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
410 int *, int *, int *));
411static void note_mode_line_highlight P_ ((struct window *, int, int));
06a2c219 412static void note_mouse_highlight P_ ((struct frame *, int, int));
9ea173e8
GM
413static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
414static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
06a2c219
GM
415static void show_mouse_face P_ ((struct x_display_info *,
416 enum draw_glyphs_face));
417static int x_io_error_quitter P_ ((Display *));
418int x_catch_errors P_ ((Display *));
419void x_uncatch_errors P_ ((Display *, int));
420void x_lower_frame P_ ((struct frame *));
421void x_scroll_bar_clear P_ ((struct frame *));
422int x_had_errors_p P_ ((Display *));
423void x_wm_set_size_hint P_ ((struct frame *, long, int));
424void x_raise_frame P_ ((struct frame *));
425void x_set_window_size P_ ((struct frame *, int, int, int));
426void x_wm_set_window_state P_ ((struct frame *, int));
427void x_wm_set_icon_pixmap P_ ((struct frame *, int));
428void x_initialize P_ ((void));
429static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
430static int x_compute_min_glyph_bounds P_ ((struct frame *));
431static void x_draw_phys_cursor_glyph P_ ((struct window *,
432 struct glyph_row *,
433 enum draw_glyphs_face));
434static void x_update_end P_ ((struct frame *));
435static void XTframe_up_to_date P_ ((struct frame *));
436static void XTreassert_line_highlight P_ ((int, int));
437static void x_change_line_highlight P_ ((int, int, int, int));
438static void XTset_terminal_modes P_ ((void));
439static void XTreset_terminal_modes P_ ((void));
440static void XTcursor_to P_ ((int, int, int, int));
441static void x_write_glyphs P_ ((struct glyph *, int));
442static void x_clear_end_of_line P_ ((int));
443static void x_clear_frame P_ ((void));
444static void x_clear_cursor P_ ((struct window *));
445static void frame_highlight P_ ((struct frame *));
446static void frame_unhighlight P_ ((struct frame *));
447static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
448static void XTframe_rehighlight P_ ((struct frame *));
449static void x_frame_rehighlight P_ ((struct x_display_info *));
450static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
f02d8aa0 451static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
06a2c219
GM
452static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
453 XRectangle *));
454static void expose_frame P_ ((struct frame *, int, int, int, int));
455static void expose_window_tree P_ ((struct window *, XRectangle *));
456static void expose_window P_ ((struct window *, XRectangle *));
457static void expose_area P_ ((struct window *, struct glyph_row *,
458 XRectangle *, enum glyph_row_area));
459static void expose_line P_ ((struct window *, struct glyph_row *,
460 XRectangle *));
461static void x_update_cursor_in_window_tree P_ ((struct window *, int));
462static void x_update_window_cursor P_ ((struct window *, int));
463static void x_erase_phys_cursor P_ ((struct window *));
464void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
465static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
466 enum bitmap_type));
467
468static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
469 GC, int));
470static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
471static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
472static void note_overwritten_text_cursor P_ ((struct window *, int, int));
473static void x_flush P_ ((struct frame *f));
474
475
476/* Flush display of frame F, or of all frames if F is null. */
477
478static void
479x_flush (f)
480 struct frame *f;
481{
482 BLOCK_INPUT;
483 if (f == NULL)
484 {
485 Lisp_Object rest, frame;
486 FOR_EACH_FRAME (rest, frame)
487 x_flush (XFRAME (frame));
488 }
489 else if (FRAME_X_P (f))
490 XFlush (FRAME_X_DISPLAY (f));
491 UNBLOCK_INPUT;
492}
493
dc6f92b8 494
06a2c219
GM
495/* Remove calls to XFlush by defining XFlush to an empty replacement.
496 Calls to XFlush should be unnecessary because the X output buffer
497 is flushed automatically as needed by calls to XPending,
498 XNextEvent, or XWindowEvent according to the XFlush man page.
499 XTread_socket calls XPending. Removing XFlush improves
500 performance. */
501
502#define XFlush(DISPLAY) (void) 0
b8009dd1 503
334208b7 504\f
06a2c219
GM
505/***********************************************************************
506 Debugging
507 ***********************************************************************/
508
9382638d 509#if 0
06a2c219
GM
510
511/* This is a function useful for recording debugging information about
512 the sequence of occurrences in this file. */
9382638d
KH
513
514struct record
515{
516 char *locus;
517 int type;
518};
519
520struct record event_record[100];
521
522int event_record_index;
523
524record_event (locus, type)
525 char *locus;
526 int type;
527{
528 if (event_record_index == sizeof (event_record) / sizeof (struct record))
529 event_record_index = 0;
530
531 event_record[event_record_index].locus = locus;
532 event_record[event_record_index].type = type;
533 event_record_index++;
534}
535
536#endif /* 0 */
06a2c219
GM
537
538
9382638d 539\f
334208b7
RS
540/* Return the struct x_display_info corresponding to DPY. */
541
542struct x_display_info *
543x_display_info_for_display (dpy)
544 Display *dpy;
545{
546 struct x_display_info *dpyinfo;
547
548 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
549 if (dpyinfo->display == dpy)
550 return dpyinfo;
16bd92ea 551
334208b7
RS
552 return 0;
553}
f451eb13 554
06a2c219
GM
555
556\f
557/***********************************************************************
558 Starting and ending an update
559 ***********************************************************************/
560
561/* Start an update of frame F. This function is installed as a hook
562 for update_begin, i.e. it is called when update_begin is called.
563 This function is called prior to calls to x_update_window_begin for
564 each window being updated. Currently, there is nothing to do here
565 because all interesting stuff is done on a window basis. */
dc6f92b8 566
dfcf069d 567static void
06a2c219 568x_update_begin (f)
f676886a 569 struct frame *f;
58769bee 570{
06a2c219
GM
571 /* Nothing to do. */
572}
dc6f92b8 573
dc6f92b8 574
06a2c219
GM
575/* Start update of window W. Set the global variable updated_window
576 to the window being updated and set output_cursor to the cursor
577 position of W. */
dc6f92b8 578
06a2c219
GM
579static void
580x_update_window_begin (w)
581 struct window *w;
582{
583 struct frame *f = XFRAME (WINDOW_FRAME (w));
584 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
585
586 updated_window = w;
587 set_output_cursor (&w->cursor);
b8009dd1 588
06a2c219 589 BLOCK_INPUT;
d1bc4182 590
06a2c219 591 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 592 {
514e4681 593 /* Don't do highlighting for mouse motion during the update. */
06a2c219 594 display_info->mouse_face_defer = 1;
37c2c98b 595
06a2c219
GM
596 /* If F needs to be redrawn, simply forget about any prior mouse
597 highlighting. */
9f67f20b 598 if (FRAME_GARBAGED_P (f))
06a2c219
GM
599 display_info->mouse_face_window = Qnil;
600
64f26cf5
GM
601#if 0 /* Rows in a current matrix containing glyphs in mouse-face have
602 their mouse_face_p flag set, which means that they are always
603 unequal to rows in a desired matrix which never have that
604 flag set. So, rows containing mouse-face glyphs are never
605 scrolled, and we don't have to switch the mouse highlight off
606 here to prevent it from being scrolled. */
607
06a2c219
GM
608 /* Can we tell that this update does not affect the window
609 where the mouse highlight is? If so, no need to turn off.
610 Likewise, don't do anything if the frame is garbaged;
611 in that case, the frame's current matrix that we would use
612 is all wrong, and we will redisplay that line anyway. */
613 if (!NILP (display_info->mouse_face_window)
614 && w == XWINDOW (display_info->mouse_face_window))
514e4681 615 {
06a2c219 616 int i;
514e4681 617
06a2c219
GM
618 for (i = 0; i < w->desired_matrix->nrows; ++i)
619 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
620 break;
621
06a2c219
GM
622 if (i < w->desired_matrix->nrows)
623 clear_mouse_face (display_info);
514e4681 624 }
64f26cf5 625#endif /* 0 */
b8009dd1 626 }
6ccf47d1 627
dc6f92b8
JB
628 UNBLOCK_INPUT;
629}
630
06a2c219
GM
631
632/* Draw a vertical window border to the right of window W if W doesn't
633 have vertical scroll bars. */
634
dfcf069d 635static void
06a2c219
GM
636x_draw_vertical_border (w)
637 struct window *w;
58769bee 638{
06a2c219
GM
639 struct frame *f = XFRAME (WINDOW_FRAME (w));
640
641 /* Redraw borders between horizontally adjacent windows. Don't
642 do it for frames with vertical scroll bars because either the
643 right scroll bar of a window, or the left scroll bar of its
644 neighbor will suffice as a border. */
645 if (!WINDOW_RIGHTMOST_P (w)
646 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
647 {
648 int x0, x1, y0, y1;
dc6f92b8 649
06a2c219 650 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 651 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
652 y1 -= 1;
653
654 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
655 f->output_data.x->normal_gc, x1, y0, x1, y1);
656 }
657}
658
659
71b8321e
GM
660/* End update of window W (which is equal to updated_window).
661
662 Draw vertical borders between horizontally adjacent windows, and
663 display W's cursor if CURSOR_ON_P is non-zero.
664
665 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
666 glyphs in mouse-face were overwritten. In that case we have to
667 make sure that the mouse-highlight is properly redrawn.
668
669 W may be a menu bar pseudo-window in case we don't have X toolkit
670 support. Such windows don't have a cursor, so don't display it
671 here. */
06a2c219
GM
672
673static void
71b8321e 674x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
06a2c219 675 struct window *w;
71b8321e 676 int cursor_on_p, mouse_face_overwritten_p;
06a2c219
GM
677{
678 if (!w->pseudo_window_p)
679 {
71b8321e
GM
680 struct x_display_info *dpyinfo
681 = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
682
06a2c219 683 BLOCK_INPUT;
71b8321e
GM
684
685 /* If a row with mouse-face was overwritten, arrange for
686 XTframe_up_to_date to redisplay the mouse highlight. */
687 if (mouse_face_overwritten_p)
688 {
689 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
690 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
691 dpyinfo->mouse_face_window = Qnil;
692 }
693
06a2c219
GM
694 if (cursor_on_p)
695 x_display_and_set_cursor (w, 1, output_cursor.hpos,
696 output_cursor.vpos,
697 output_cursor.x, output_cursor.y);
71b8321e 698
06a2c219
GM
699 x_draw_vertical_border (w);
700 UNBLOCK_INPUT;
701 }
702
703 updated_window = NULL;
704}
dc6f92b8 705
dc6f92b8 706
06a2c219
GM
707/* End update of frame F. This function is installed as a hook in
708 update_end. */
709
710static void
711x_update_end (f)
712 struct frame *f;
713{
714 /* Mouse highlight may be displayed again. */
aa8bff2e 715 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 716
06a2c219 717 BLOCK_INPUT;
334208b7 718 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
719 UNBLOCK_INPUT;
720}
b8009dd1 721
06a2c219
GM
722
723/* This function is called from various places in xdisp.c whenever a
724 complete update has been performed. The global variable
725 updated_window is not available here. */
b8009dd1 726
dfcf069d 727static void
b8009dd1 728XTframe_up_to_date (f)
06a2c219 729 struct frame *f;
b8009dd1 730{
06a2c219 731 if (FRAME_X_P (f))
514e4681 732 {
06a2c219 733 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
71b8321e 734
06a2c219
GM
735 if (dpyinfo->mouse_face_deferred_gc
736 || f == dpyinfo->mouse_face_mouse_frame)
737 {
738 BLOCK_INPUT;
739 if (dpyinfo->mouse_face_mouse_frame)
740 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
741 dpyinfo->mouse_face_mouse_x,
742 dpyinfo->mouse_face_mouse_y);
743 dpyinfo->mouse_face_deferred_gc = 0;
744 UNBLOCK_INPUT;
745 }
514e4681 746 }
b8009dd1 747}
06a2c219
GM
748
749
750/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
751 arrow bitmaps, or clear the areas where they would be displayed
752 before DESIRED_ROW is made current. The window being updated is
753 found in updated_window. This function It is called from
754 update_window_line only if it is known that there are differences
755 between bitmaps to be drawn between current row and DESIRED_ROW. */
756
757static void
758x_after_update_window_line (desired_row)
759 struct glyph_row *desired_row;
760{
761 struct window *w = updated_window;
762
763 xassert (w);
764
765 if (!desired_row->mode_line_p && !w->pseudo_window_p)
766 {
767 BLOCK_INPUT;
768 x_draw_row_bitmaps (w, desired_row);
769
770 /* When a window has disappeared, make sure that no rest of
771 full-width rows stays visible in the internal border. */
772 if (windows_or_buffers_changed)
773 {
774 struct frame *f = XFRAME (w->frame);
775 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
776 int height = desired_row->visible_height;
110859fc
GM
777 int x = (window_box_right (w, -1)
778 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
779 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
780
781 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
782 x, y, width, height, False);
783 }
784
785 UNBLOCK_INPUT;
786 }
787}
788
789
790/* Draw the bitmap WHICH in one of the areas to the left or right of
791 window W. ROW is the glyph row for which to display the bitmap; it
792 determines the vertical position at which the bitmap has to be
793 drawn. */
794
795static void
796x_draw_bitmap (w, row, which)
797 struct window *w;
798 struct glyph_row *row;
799 enum bitmap_type which;
800{
801 struct frame *f = XFRAME (WINDOW_FRAME (w));
802 Display *display = FRAME_X_DISPLAY (f);
803 Window window = FRAME_X_WINDOW (f);
804 int x, y, wd, h, dy;
805 unsigned char *bits;
806 Pixmap pixmap;
807 GC gc = f->output_data.x->normal_gc;
808 struct face *face;
809 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
810
811 /* Must clip because of partially visible lines. */
812 x_clip_to_row (w, row, gc, 1);
813
814 switch (which)
815 {
816 case LEFT_TRUNCATION_BITMAP:
817 wd = left_width;
818 h = left_height;
819 bits = left_bits;
820 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
821 - wd
110859fc 822 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
823 break;
824
825 case OVERLAY_ARROW_BITMAP:
826 wd = left_width;
827 h = left_height;
828 bits = ov_bits;
829 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
830 - wd
110859fc 831 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
832 break;
833
834 case RIGHT_TRUNCATION_BITMAP:
835 wd = right_width;
836 h = right_height;
837 bits = right_bits;
838 x = window_box_right (w, -1);
110859fc 839 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
840 break;
841
842 case CONTINUED_LINE_BITMAP:
843 wd = right_width;
844 h = right_height;
845 bits = continued_bits;
846 x = window_box_right (w, -1);
110859fc 847 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
848 break;
849
850 case CONTINUATION_LINE_BITMAP:
851 wd = continuation_width;
852 h = continuation_height;
853 bits = continuation_bits;
854 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
855 - wd
110859fc 856 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
857 break;
858
859 case ZV_LINE_BITMAP:
860 wd = zv_width;
861 h = zv_height;
862 bits = zv_bits;
863 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
864 - wd
110859fc 865 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
866 break;
867
868 default:
869 abort ();
870 }
871
872 /* Convert to frame coordinates. Set dy to the offset in the row to
873 start drawing the bitmap. */
874 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
875 dy = (row->height - h) / 2;
876
877 /* Draw the bitmap. I believe these small pixmaps can be cached
878 by the server. */
879 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
880 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
881 face->foreground,
882 face->background, depth);
883 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
884 XFreePixmap (display, pixmap);
885 XSetClipMask (display, gc, None);
886}
887
888
889/* Draw flags bitmaps for glyph row ROW on window W. Call this
890 function with input blocked. */
891
892static void
893x_draw_row_bitmaps (w, row)
894 struct window *w;
895 struct glyph_row *row;
896{
897 struct frame *f = XFRAME (w->frame);
898 enum bitmap_type bitmap;
899 struct face *face;
045dee35 900 int header_line_height = -1;
06a2c219
GM
901
902 xassert (interrupt_input_blocked);
903
904 /* If row is completely invisible, because of vscrolling, we
905 don't have to draw anything. */
906 if (row->visible_height <= 0)
907 return;
908
909 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
910 PREPARE_FACE_FOR_DISPLAY (f, face);
911
912 /* Decide which bitmap to draw at the left side. */
913 if (row->overlay_arrow_p)
914 bitmap = OVERLAY_ARROW_BITMAP;
915 else if (row->truncated_on_left_p)
916 bitmap = LEFT_TRUNCATION_BITMAP;
917 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
918 bitmap = CONTINUATION_LINE_BITMAP;
919 else if (row->indicate_empty_line_p)
920 bitmap = ZV_LINE_BITMAP;
921 else
922 bitmap = NO_BITMAP;
923
924 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
925 the flags area. */
926 if (bitmap == NO_BITMAP
110859fc 927 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
928 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
929 {
930 /* If W has a vertical border to its left, don't draw over it. */
931 int border = ((XFASTINT (w->left) > 0
932 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
933 ? 1 : 0);
934 int left = window_box_left (w, -1);
935
045dee35
GM
936 if (header_line_height < 0)
937 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
938
939 /* In case the same realized face is used for bitmap areas and
940 for something displayed in the text (e.g. face `region' on
941 mono-displays, the fill style may have been changed to
942 FillSolid in x_draw_glyph_string_background. */
943 if (face->stipple)
944 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
945 else
946 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
947
06a2c219
GM
948 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
949 face->gc,
950 (left
110859fc 951 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 952 + border),
045dee35 953 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 954 row->y)),
110859fc 955 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 956 row->visible_height);
dcd08bfb
GM
957 if (!face->stipple)
958 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
959 }
960
961 /* Draw the left bitmap. */
962 if (bitmap != NO_BITMAP)
963 x_draw_bitmap (w, row, bitmap);
964
965 /* Decide which bitmap to draw at the right side. */
966 if (row->truncated_on_right_p)
967 bitmap = RIGHT_TRUNCATION_BITMAP;
968 else if (row->continued_p)
969 bitmap = CONTINUED_LINE_BITMAP;
970 else
971 bitmap = NO_BITMAP;
972
973 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
974 the flags area. */
975 if (bitmap == NO_BITMAP
110859fc 976 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
977 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
978 {
979 int right = window_box_right (w, -1);
980
045dee35
GM
981 if (header_line_height < 0)
982 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
983
984 /* In case the same realized face is used for bitmap areas and
985 for something displayed in the text (e.g. face `region' on
986 mono-displays, the fill style may have been changed to
987 FillSolid in x_draw_glyph_string_background. */
988 if (face->stipple)
989 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
990 else
991 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
992 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
993 face->gc,
994 right,
045dee35 995 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 996 row->y)),
110859fc 997 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 998 row->visible_height);
dcd08bfb
GM
999 if (!face->stipple)
1000 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
1001 }
1002
1003 /* Draw the right bitmap. */
1004 if (bitmap != NO_BITMAP)
1005 x_draw_bitmap (w, row, bitmap);
1006}
1007
dc6f92b8 1008\f
06a2c219
GM
1009/***********************************************************************
1010 Line Highlighting
1011 ***********************************************************************/
dc6f92b8 1012
06a2c219
GM
1013/* External interface to control of standout mode. Not used for X
1014 frames. Aborts when called. */
1015
1016static void
dc6f92b8
JB
1017XTreassert_line_highlight (new, vpos)
1018 int new, vpos;
1019{
06a2c219 1020 abort ();
dc6f92b8
JB
1021}
1022
06a2c219
GM
1023
1024/* Call this when about to modify line at position VPOS and change
1025 whether it is highlighted. Not used for X frames. Aborts when
1026 called. */
dc6f92b8 1027
dfcf069d 1028static void
06a2c219
GM
1029x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1030 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1031{
06a2c219 1032 abort ();
dc6f92b8
JB
1033}
1034
06a2c219
GM
1035
1036/* This is called when starting Emacs and when restarting after
1037 suspend. When starting Emacs, no X window is mapped. And nothing
1038 must be done to Emacs's own window if it is suspended (though that
1039 rarely happens). */
dc6f92b8 1040
dfcf069d 1041static void
dc6f92b8
JB
1042XTset_terminal_modes ()
1043{
1044}
1045
06a2c219
GM
1046/* This is called when exiting or suspending Emacs. Exiting will make
1047 the X-windows go away, and suspending requires no action. */
dc6f92b8 1048
dfcf069d 1049static void
dc6f92b8
JB
1050XTreset_terminal_modes ()
1051{
dc6f92b8 1052}
06a2c219
GM
1053
1054
dc6f92b8 1055\f
06a2c219
GM
1056/***********************************************************************
1057 Output Cursor
1058 ***********************************************************************/
1059
1060/* Set the global variable output_cursor to CURSOR. All cursor
1061 positions are relative to updated_window. */
dc6f92b8 1062
dfcf069d 1063static void
06a2c219
GM
1064set_output_cursor (cursor)
1065 struct cursor_pos *cursor;
dc6f92b8 1066{
06a2c219
GM
1067 output_cursor.hpos = cursor->hpos;
1068 output_cursor.vpos = cursor->vpos;
1069 output_cursor.x = cursor->x;
1070 output_cursor.y = cursor->y;
1071}
1072
1073
1074/* Set a nominal cursor position.
dc6f92b8 1075
06a2c219
GM
1076 HPOS and VPOS are column/row positions in a window glyph matrix. X
1077 and Y are window text area relative pixel positions.
1078
1079 If this is done during an update, updated_window will contain the
1080 window that is being updated and the position is the future output
1081 cursor position for that window. If updated_window is null, use
1082 selected_window and display the cursor at the given position. */
1083
1084static void
1085XTcursor_to (vpos, hpos, y, x)
1086 int vpos, hpos, y, x;
1087{
1088 struct window *w;
1089
1090 /* If updated_window is not set, work on selected_window. */
1091 if (updated_window)
1092 w = updated_window;
1093 else
1094 w = XWINDOW (selected_window);
dbcb258a 1095
06a2c219
GM
1096 /* Set the output cursor. */
1097 output_cursor.hpos = hpos;
1098 output_cursor.vpos = vpos;
1099 output_cursor.x = x;
1100 output_cursor.y = y;
dc6f92b8 1101
06a2c219
GM
1102 /* If not called as part of an update, really display the cursor.
1103 This will also set the cursor position of W. */
1104 if (updated_window == NULL)
dc6f92b8
JB
1105 {
1106 BLOCK_INPUT;
06a2c219 1107 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1108 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1109 UNBLOCK_INPUT;
1110 }
1111}
dc43ef94 1112
06a2c219
GM
1113
1114\f
1115/***********************************************************************
1116 Display Iterator
1117 ***********************************************************************/
1118
1119/* Function prototypes of this page. */
1120
1121static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1122 struct glyph *,
ee569018
KH
1123 XChar2b *,
1124 int *));
06a2c219
GM
1125static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1126 int, XChar2b *, int));
1127static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1128static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1129static void x_append_glyph P_ ((struct it *));
b4192550 1130static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1131static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1132 int, int, double));
1133static void x_produce_glyphs P_ ((struct it *));
06a2c219 1134static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1135
1136
1137/* Return a pointer to per-char metric information in FONT of a
1138 character pointed by B which is a pointer to an XChar2b. */
1139
1140#define PER_CHAR_METRIC(font, b) \
1141 ((font)->per_char \
1142 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1143 + (((font)->min_byte1 || (font)->max_byte1) \
1144 ? (((b)->byte1 - (font)->min_byte1) \
1145 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1146 : 0)) \
1147 : &((font)->max_bounds))
dc43ef94 1148
dc6f92b8 1149
e2ef8ee6
GM
1150/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1151 is not contained in the font. */
dc43ef94 1152
06a2c219 1153static INLINE XCharStruct *
ee569018 1154x_per_char_metric (font, char2b)
06a2c219
GM
1155 XFontStruct *font;
1156 XChar2b *char2b;
1157{
1158 /* The result metric information. */
1159 XCharStruct *pcm = NULL;
dc6f92b8 1160
06a2c219 1161 xassert (font && char2b);
dc6f92b8 1162
06a2c219 1163 if (font->per_char != NULL)
dc6f92b8 1164 {
06a2c219 1165 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1166 {
06a2c219
GM
1167 /* min_char_or_byte2 specifies the linear character index
1168 corresponding to the first element of the per_char array,
1169 max_char_or_byte2 is the index of the last character. A
1170 character with non-zero CHAR2B->byte1 is not in the font.
1171 A character with byte2 less than min_char_or_byte2 or
1172 greater max_char_or_byte2 is not in the font. */
1173 if (char2b->byte1 == 0
1174 && char2b->byte2 >= font->min_char_or_byte2
1175 && char2b->byte2 <= font->max_char_or_byte2)
1176 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1177 }
06a2c219 1178 else
dc6f92b8 1179 {
06a2c219
GM
1180 /* If either min_byte1 or max_byte1 are nonzero, both
1181 min_char_or_byte2 and max_char_or_byte2 are less than
1182 256, and the 2-byte character index values corresponding
1183 to the per_char array element N (counting from 0) are:
1184
1185 byte1 = N/D + min_byte1
1186 byte2 = N\D + min_char_or_byte2
1187
1188 where:
1189
1190 D = max_char_or_byte2 - min_char_or_byte2 + 1
1191 / = integer division
1192 \ = integer modulus */
1193 if (char2b->byte1 >= font->min_byte1
1194 && char2b->byte1 <= font->max_byte1
1195 && char2b->byte2 >= font->min_char_or_byte2
1196 && char2b->byte2 <= font->max_char_or_byte2)
1197 {
1198 pcm = (font->per_char
1199 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1200 * (char2b->byte1 - font->min_byte1))
1201 + (char2b->byte2 - font->min_char_or_byte2));
1202 }
dc6f92b8 1203 }
06a2c219
GM
1204 }
1205 else
1206 {
1207 /* If the per_char pointer is null, all glyphs between the first
1208 and last character indexes inclusive have the same
1209 information, as given by both min_bounds and max_bounds. */
1210 if (char2b->byte2 >= font->min_char_or_byte2
1211 && char2b->byte2 <= font->max_char_or_byte2)
1212 pcm = &font->max_bounds;
1213 }
dc6f92b8 1214
ee569018 1215 return ((pcm == NULL
3e71d8f2 1216 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1217 ? NULL : pcm);
06a2c219 1218}
b73b6aaf 1219
57b03282 1220
06a2c219
GM
1221/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1222 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1223
06a2c219
GM
1224static INLINE void
1225x_encode_char (c, char2b, font_info)
1226 int c;
1227 XChar2b *char2b;
1228 struct font_info *font_info;
1229{
1230 int charset = CHAR_CHARSET (c);
1231 XFontStruct *font = font_info->font;
1232
1233 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1234 This may be either a program in a special encoder language or a
1235 fixed encoding. */
1236 if (font_info->font_encoder)
1237 {
1238 /* It's a program. */
1239 struct ccl_program *ccl = font_info->font_encoder;
1240
1241 if (CHARSET_DIMENSION (charset) == 1)
1242 {
1243 ccl->reg[0] = charset;
1244 ccl->reg[1] = char2b->byte2;
1245 }
1246 else
1247 {
1248 ccl->reg[0] = charset;
1249 ccl->reg[1] = char2b->byte1;
1250 ccl->reg[2] = char2b->byte2;
1251 }
1252
1253 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1254
1255 /* We assume that MSBs are appropriately set/reset by CCL
1256 program. */
1257 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1258 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1259 else
1260 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1261 }
1262 else if (font_info->encoding[charset])
1263 {
1264 /* Fixed encoding scheme. See fontset.h for the meaning of the
1265 encoding numbers. */
1266 int enc = font_info->encoding[charset];
1267
1268 if ((enc == 1 || enc == 2)
1269 && CHARSET_DIMENSION (charset) == 2)
1270 char2b->byte1 |= 0x80;
1271
1272 if (enc == 1 || enc == 3)
1273 char2b->byte2 |= 0x80;
1274 }
1275}
1276
1277
1278/* Get face and two-byte form of character C in face FACE_ID on frame
1279 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1280 means we want to display multibyte text. Value is a pointer to a
1281 realized face that is ready for display. */
1282
1283static INLINE struct face *
1284x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1285 struct frame *f;
1286 int c, face_id;
1287 XChar2b *char2b;
1288 int multibyte_p;
1289{
1290 struct face *face = FACE_FROM_ID (f, face_id);
1291
1292 if (!multibyte_p)
1293 {
1294 /* Unibyte case. We don't have to encode, but we have to make
1295 sure to use a face suitable for unibyte. */
1296 char2b->byte1 = 0;
1297 char2b->byte2 = c;
ee569018
KH
1298 face_id = FACE_FOR_CHAR (f, face, c);
1299 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1300 }
1301 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1302 {
1303 /* Case of ASCII in a face known to fit ASCII. */
1304 char2b->byte1 = 0;
1305 char2b->byte2 = c;
1306 }
1307 else
1308 {
1309 int c1, c2, charset;
1310
1311 /* Split characters into bytes. If c2 is -1 afterwards, C is
1312 really a one-byte character so that byte1 is zero. */
1313 SPLIT_CHAR (c, charset, c1, c2);
1314 if (c2 > 0)
1315 char2b->byte1 = c1, char2b->byte2 = c2;
1316 else
1317 char2b->byte1 = 0, char2b->byte2 = c1;
1318
06a2c219 1319 /* Maybe encode the character in *CHAR2B. */
ee569018 1320 if (face->font != NULL)
06a2c219
GM
1321 {
1322 struct font_info *font_info
1323 = FONT_INFO_FROM_ID (f, face->font_info_id);
1324 if (font_info)
ee569018 1325 x_encode_char (c, char2b, font_info);
06a2c219
GM
1326 }
1327 }
1328
1329 /* Make sure X resources of the face are allocated. */
1330 xassert (face != NULL);
1331 PREPARE_FACE_FOR_DISPLAY (f, face);
1332
1333 return face;
1334}
1335
1336
1337/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1338 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1339 a pointer to a realized face that is ready for display. */
1340
1341static INLINE struct face *
ee569018 1342x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1343 struct frame *f;
1344 struct glyph *glyph;
1345 XChar2b *char2b;
ee569018 1346 int *two_byte_p;
06a2c219
GM
1347{
1348 struct face *face;
1349
1350 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1351 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1352
ee569018
KH
1353 if (two_byte_p)
1354 *two_byte_p = 0;
1355
06a2c219
GM
1356 if (!glyph->multibyte_p)
1357 {
1358 /* Unibyte case. We don't have to encode, but we have to make
1359 sure to use a face suitable for unibyte. */
1360 char2b->byte1 = 0;
43d120d8 1361 char2b->byte2 = glyph->u.ch;
06a2c219 1362 }
43d120d8
KH
1363 else if (glyph->u.ch < 128
1364 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1365 {
1366 /* Case of ASCII in a face known to fit ASCII. */
1367 char2b->byte1 = 0;
43d120d8 1368 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1369 }
1370 else
1371 {
1372 int c1, c2, charset;
1373
1374 /* Split characters into bytes. If c2 is -1 afterwards, C is
1375 really a one-byte character so that byte1 is zero. */
43d120d8 1376 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1377 if (c2 > 0)
1378 char2b->byte1 = c1, char2b->byte2 = c2;
1379 else
1380 char2b->byte1 = 0, char2b->byte2 = c1;
1381
1382 /* Maybe encode the character in *CHAR2B. */
1383 if (charset != CHARSET_ASCII)
1384 {
1385 struct font_info *font_info
1386 = FONT_INFO_FROM_ID (f, face->font_info_id);
1387 if (font_info)
1388 {
43d120d8 1389 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1390 if (two_byte_p)
1391 *two_byte_p
1392 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1393 }
1394 }
1395 }
1396
1397 /* Make sure X resources of the face are allocated. */
1398 xassert (face != NULL);
1399 PREPARE_FACE_FOR_DISPLAY (f, face);
1400 return face;
1401}
1402
1403
1404/* Store one glyph for IT->char_to_display in IT->glyph_row.
1405 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1406
1407static INLINE void
1408x_append_glyph (it)
1409 struct it *it;
1410{
1411 struct glyph *glyph;
1412 enum glyph_row_area area = it->area;
1413
1414 xassert (it->glyph_row);
1415 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1416
1417 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1418 if (glyph < it->glyph_row->glyphs[area + 1])
1419 {
06a2c219
GM
1420 glyph->charpos = CHARPOS (it->position);
1421 glyph->object = it->object;
88d75730 1422 glyph->pixel_width = it->pixel_width;
06a2c219 1423 glyph->voffset = it->voffset;
88d75730 1424 glyph->type = CHAR_GLYPH;
06a2c219 1425 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1426 glyph->left_box_line_p = it->start_of_box_run_p;
1427 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1428 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1429 || it->phys_descent > it->descent);
88d75730 1430 glyph->padding_p = 0;
ee569018 1431 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1432 glyph->face_id = it->face_id;
1433 glyph->u.ch = it->char_to_display;
06a2c219
GM
1434 ++it->glyph_row->used[area];
1435 }
1436}
1437
b4192550
KH
1438/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1439 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1440
1441static INLINE void
1442x_append_composite_glyph (it)
1443 struct it *it;
1444{
1445 struct glyph *glyph;
1446 enum glyph_row_area area = it->area;
1447
1448 xassert (it->glyph_row);
1449
1450 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1451 if (glyph < it->glyph_row->glyphs[area + 1])
1452 {
b4192550
KH
1453 glyph->charpos = CHARPOS (it->position);
1454 glyph->object = it->object;
88d75730 1455 glyph->pixel_width = it->pixel_width;
b4192550 1456 glyph->voffset = it->voffset;
88d75730 1457 glyph->type = COMPOSITE_GLYPH;
b4192550 1458 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1459 glyph->left_box_line_p = it->start_of_box_run_p;
1460 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1461 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1462 || it->phys_descent > it->descent);
88d75730
GM
1463 glyph->padding_p = 0;
1464 glyph->glyph_not_available_p = 0;
1465 glyph->face_id = it->face_id;
1466 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1467 ++it->glyph_row->used[area];
1468 }
1469}
1470
06a2c219
GM
1471
1472/* Change IT->ascent and IT->height according to the setting of
1473 IT->voffset. */
1474
1475static INLINE void
1476take_vertical_position_into_account (it)
1477 struct it *it;
1478{
1479 if (it->voffset)
1480 {
1481 if (it->voffset < 0)
1482 /* Increase the ascent so that we can display the text higher
1483 in the line. */
1484 it->ascent += abs (it->voffset);
1485 else
1486 /* Increase the descent so that we can display the text lower
1487 in the line. */
1488 it->descent += it->voffset;
1489 }
1490}
1491
1492
1493/* Produce glyphs/get display metrics for the image IT is loaded with.
1494 See the description of struct display_iterator in dispextern.h for
1495 an overview of struct display_iterator. */
1496
1497static void
1498x_produce_image_glyph (it)
1499 struct it *it;
1500{
1501 struct image *img;
1502 struct face *face;
1503
1504 xassert (it->what == IT_IMAGE);
1505
1506 face = FACE_FROM_ID (it->f, it->face_id);
1507 img = IMAGE_FROM_ID (it->f, it->image_id);
1508 xassert (img);
1509
1510 /* Make sure X resources of the face and image are loaded. */
1511 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1512 prepare_image_for_display (it->f, img);
1513
95af8492 1514 it->ascent = it->phys_ascent = image_ascent (img, face);
66ac4b0e 1515 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1516 it->pixel_width = img->width + 2 * img->margin;
1517
1518 it->nglyphs = 1;
1519
1520 if (face->box != FACE_NO_BOX)
1521 {
1522 it->ascent += face->box_line_width;
1523 it->descent += face->box_line_width;
1524
1525 if (it->start_of_box_run_p)
1526 it->pixel_width += face->box_line_width;
1527 if (it->end_of_box_run_p)
1528 it->pixel_width += face->box_line_width;
1529 }
1530
1531 take_vertical_position_into_account (it);
1532
1533 if (it->glyph_row)
1534 {
1535 struct glyph *glyph;
1536 enum glyph_row_area area = it->area;
1537
1538 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1539 if (glyph < it->glyph_row->glyphs[area + 1])
1540 {
06a2c219
GM
1541 glyph->charpos = CHARPOS (it->position);
1542 glyph->object = it->object;
88d75730 1543 glyph->pixel_width = it->pixel_width;
06a2c219 1544 glyph->voffset = it->voffset;
88d75730 1545 glyph->type = IMAGE_GLYPH;
06a2c219 1546 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1547 glyph->left_box_line_p = it->start_of_box_run_p;
1548 glyph->right_box_line_p = it->end_of_box_run_p;
1549 glyph->overlaps_vertically_p = 0;
1550 glyph->padding_p = 0;
1551 glyph->glyph_not_available_p = 0;
1552 glyph->face_id = it->face_id;
1553 glyph->u.img_id = img->id;
06a2c219
GM
1554 ++it->glyph_row->used[area];
1555 }
1556 }
1557}
1558
1559
1560/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1561 of the glyph, WIDTH and HEIGHT are the width and height of the
1562 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1563 ascent of the glyph (0 <= ASCENT <= 1). */
1564
1565static void
1566x_append_stretch_glyph (it, object, width, height, ascent)
1567 struct it *it;
1568 Lisp_Object object;
1569 int width, height;
1570 double ascent;
1571{
1572 struct glyph *glyph;
1573 enum glyph_row_area area = it->area;
1574
1575 xassert (ascent >= 0 && ascent <= 1);
1576
1577 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1578 if (glyph < it->glyph_row->glyphs[area + 1])
1579 {
06a2c219
GM
1580 glyph->charpos = CHARPOS (it->position);
1581 glyph->object = object;
88d75730 1582 glyph->pixel_width = width;
06a2c219 1583 glyph->voffset = it->voffset;
88d75730 1584 glyph->type = STRETCH_GLYPH;
06a2c219 1585 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1586 glyph->left_box_line_p = it->start_of_box_run_p;
1587 glyph->right_box_line_p = it->end_of_box_run_p;
1588 glyph->overlaps_vertically_p = 0;
1589 glyph->padding_p = 0;
1590 glyph->glyph_not_available_p = 0;
1591 glyph->face_id = it->face_id;
1592 glyph->u.stretch.ascent = height * ascent;
1593 glyph->u.stretch.height = height;
06a2c219
GM
1594 ++it->glyph_row->used[area];
1595 }
1596}
1597
1598
1599/* Produce a stretch glyph for iterator IT. IT->object is the value
1600 of the glyph property displayed. The value must be a list
1601 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1602 being recognized:
1603
1604 1. `:width WIDTH' specifies that the space should be WIDTH *
1605 canonical char width wide. WIDTH may be an integer or floating
1606 point number.
1607
1608 2. `:relative-width FACTOR' specifies that the width of the stretch
1609 should be computed from the width of the first character having the
1610 `glyph' property, and should be FACTOR times that width.
1611
1612 3. `:align-to HPOS' specifies that the space should be wide enough
1613 to reach HPOS, a value in canonical character units.
1614
1615 Exactly one of the above pairs must be present.
1616
1617 4. `:height HEIGHT' specifies that the height of the stretch produced
1618 should be HEIGHT, measured in canonical character units.
1619
1620 5. `:relative-height FACTOR' specifies that the height of the the
1621 stretch should be FACTOR times the height of the characters having
1622 the glyph property.
1623
1624 Either none or exactly one of 4 or 5 must be present.
1625
1626 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1627 of the stretch should be used for the ascent of the stretch.
1628 ASCENT must be in the range 0 <= ASCENT <= 100. */
1629
1630#define NUMVAL(X) \
1631 ((INTEGERP (X) || FLOATP (X)) \
1632 ? XFLOATINT (X) \
1633 : - 1)
1634
1635
1636static void
1637x_produce_stretch_glyph (it)
1638 struct it *it;
1639{
1640 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1641#if GLYPH_DEBUG
1642 extern Lisp_Object Qspace;
1643#endif
1644 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1645 extern Lisp_Object QCrelative_width, QCrelative_height;
1646 extern Lisp_Object QCalign_to;
1647 Lisp_Object prop, plist;
1648 double width = 0, height = 0, ascent = 0;
1649 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1650 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1651
1652 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1653
1654 /* List should start with `space'. */
1655 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1656 plist = XCDR (it->object);
1657
1658 /* Compute the width of the stretch. */
1659 if (prop = Fplist_get (plist, QCwidth),
1660 NUMVAL (prop) > 0)
1661 /* Absolute width `:width WIDTH' specified and valid. */
1662 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1663 else if (prop = Fplist_get (plist, QCrelative_width),
1664 NUMVAL (prop) > 0)
1665 {
1666 /* Relative width `:relative-width FACTOR' specified and valid.
1667 Compute the width of the characters having the `glyph'
1668 property. */
1669 struct it it2;
1670 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1671
1672 it2 = *it;
1673 if (it->multibyte_p)
1674 {
1675 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1676 - IT_BYTEPOS (*it));
1677 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1678 }
1679 else
1680 it2.c = *p, it2.len = 1;
1681
1682 it2.glyph_row = NULL;
1683 it2.what = IT_CHARACTER;
1684 x_produce_glyphs (&it2);
1685 width = NUMVAL (prop) * it2.pixel_width;
1686 }
1687 else if (prop = Fplist_get (plist, QCalign_to),
1688 NUMVAL (prop) > 0)
1689 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1690 else
1691 /* Nothing specified -> width defaults to canonical char width. */
1692 width = CANON_X_UNIT (it->f);
1693
1694 /* Compute height. */
1695 if (prop = Fplist_get (plist, QCheight),
1696 NUMVAL (prop) > 0)
1697 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1698 else if (prop = Fplist_get (plist, QCrelative_height),
1699 NUMVAL (prop) > 0)
1700 height = FONT_HEIGHT (font) * NUMVAL (prop);
1701 else
1702 height = FONT_HEIGHT (font);
1703
1704 /* Compute percentage of height used for ascent. If
1705 `:ascent ASCENT' is present and valid, use that. Otherwise,
1706 derive the ascent from the font in use. */
1707 if (prop = Fplist_get (plist, QCascent),
1708 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1709 ascent = NUMVAL (prop) / 100.0;
1710 else
1711 ascent = (double) font->ascent / FONT_HEIGHT (font);
1712
1713 if (width <= 0)
1714 width = 1;
1715 if (height <= 0)
1716 height = 1;
1717
1718 if (it->glyph_row)
1719 {
1720 Lisp_Object object = it->stack[it->sp - 1].string;
1721 if (!STRINGP (object))
1722 object = it->w->buffer;
1723 x_append_stretch_glyph (it, object, width, height, ascent);
1724 }
1725
1726 it->pixel_width = width;
66ac4b0e
GM
1727 it->ascent = it->phys_ascent = height * ascent;
1728 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1729 it->nglyphs = 1;
1730
1731 if (face->box != FACE_NO_BOX)
1732 {
1733 it->ascent += face->box_line_width;
1734 it->descent += face->box_line_width;
1735
1736 if (it->start_of_box_run_p)
1737 it->pixel_width += face->box_line_width;
1738 if (it->end_of_box_run_p)
1739 it->pixel_width += face->box_line_width;
1740 }
1741
1742 take_vertical_position_into_account (it);
1743}
1744
b4192550
KH
1745/* Return proper value to be used as baseline offset of font that has
1746 ASCENT and DESCENT to draw characters by the font at the vertical
1747 center of the line of frame F.
1748
1749 Here, out task is to find the value of BOFF in the following figure;
1750
1751 -------------------------+-----------+-
1752 -+-+---------+-+ | |
1753 | | | | | |
1754 | | | | F_ASCENT F_HEIGHT
1755 | | | ASCENT | |
1756 HEIGHT | | | | |
1757 | | |-|-+------+-----------|------- baseline
1758 | | | | BOFF | |
1759 | |---------|-+-+ | |
1760 | | | DESCENT | |
1761 -+-+---------+-+ F_DESCENT |
1762 -------------------------+-----------+-
1763
1764 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1765 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1766 DESCENT = FONT->descent
1767 HEIGHT = FONT_HEIGHT (FONT)
1768 F_DESCENT = (F->output_data.x->font->descent
1769 - F->output_data.x->baseline_offset)
1770 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1771*/
1772
1773#define VCENTER_BASELINE_OFFSET(FONT, F) \
1774 ((FONT)->descent \
1775 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1776 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1777
1778/* Produce glyphs/get display metrics for the display element IT is
1779 loaded with. See the description of struct display_iterator in
1780 dispextern.h for an overview of struct display_iterator. */
1781
1782static void
1783x_produce_glyphs (it)
1784 struct it *it;
1785{
ee569018
KH
1786 it->glyph_not_available_p = 0;
1787
06a2c219
GM
1788 if (it->what == IT_CHARACTER)
1789 {
1790 XChar2b char2b;
1791 XFontStruct *font;
ee569018 1792 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1793 XCharStruct *pcm;
06a2c219 1794 int font_not_found_p;
b4192550
KH
1795 struct font_info *font_info;
1796 int boff; /* baseline offset */
06a2c219 1797
ee569018
KH
1798 /* Maybe translate single-byte characters to multibyte, or the
1799 other way. */
06a2c219 1800 it->char_to_display = it->c;
ee569018 1801 if (!ASCII_BYTE_P (it->c))
06a2c219 1802 {
ee569018
KH
1803 if (unibyte_display_via_language_environment
1804 && SINGLE_BYTE_CHAR_P (it->c)
1805 && (it->c >= 0240
1806 || !NILP (Vnonascii_translation_table)))
1807 {
1808 it->char_to_display = unibyte_char_to_multibyte (it->c);
1809 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1810 face = FACE_FROM_ID (it->f, it->face_id);
1811 }
1812 else if (!SINGLE_BYTE_CHAR_P (it->c)
1813 && !it->multibyte_p)
1814 {
1815 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1816 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1817 face = FACE_FROM_ID (it->f, it->face_id);
1818 }
06a2c219
GM
1819 }
1820
ee569018
KH
1821 /* Get font to use. Encode IT->char_to_display. */
1822 x_get_char_face_and_encoding (it->f, it->char_to_display,
1823 it->face_id, &char2b,
1824 it->multibyte_p);
06a2c219
GM
1825 font = face->font;
1826
1827 /* When no suitable font found, use the default font. */
1828 font_not_found_p = font == NULL;
1829 if (font_not_found_p)
b4192550
KH
1830 {
1831 font = FRAME_FONT (it->f);
1832 boff = it->f->output_data.x->baseline_offset;
1833 font_info = NULL;
1834 }
1835 else
1836 {
1837 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1838 boff = font_info->baseline_offset;
1839 if (font_info->vertical_centering)
1840 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1841 }
06a2c219
GM
1842
1843 if (it->char_to_display >= ' '
1844 && (!it->multibyte_p || it->char_to_display < 128))
1845 {
1846 /* Either unibyte or ASCII. */
1847 int stretched_p;
1848
1849 it->nglyphs = 1;
06a2c219
GM
1850
1851 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1852 it->ascent = font->ascent + boff;
1853 it->descent = font->descent - boff;
474848ac
GM
1854
1855 if (pcm)
1856 {
1857 it->phys_ascent = pcm->ascent + boff;
1858 it->phys_descent = pcm->descent - boff;
1859 it->pixel_width = pcm->width;
1860 }
1861 else
1862 {
1863 it->glyph_not_available_p = 1;
1864 it->phys_ascent = font->ascent + boff;
1865 it->phys_descent = font->descent - boff;
1866 it->pixel_width = FONT_WIDTH (font);
1867 }
06a2c219
GM
1868
1869 /* If this is a space inside a region of text with
1870 `space-width' property, change its width. */
1871 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1872 if (stretched_p)
1873 it->pixel_width *= XFLOATINT (it->space_width);
1874
1875 /* If face has a box, add the box thickness to the character
1876 height. If character has a box line to the left and/or
1877 right, add the box line width to the character's width. */
1878 if (face->box != FACE_NO_BOX)
1879 {
1880 int thick = face->box_line_width;
1881
1882 it->ascent += thick;
1883 it->descent += thick;
1884
1885 if (it->start_of_box_run_p)
1886 it->pixel_width += thick;
1887 if (it->end_of_box_run_p)
1888 it->pixel_width += thick;
1889 }
1890
1891 /* If face has an overline, add the height of the overline
1892 (1 pixel) and a 1 pixel margin to the character height. */
1893 if (face->overline_p)
1894 it->ascent += 2;
1895
1896 take_vertical_position_into_account (it);
1897
1898 /* If we have to actually produce glyphs, do it. */
1899 if (it->glyph_row)
1900 {
1901 if (stretched_p)
1902 {
1903 /* Translate a space with a `space-width' property
1904 into a stretch glyph. */
1905 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1906 x_append_stretch_glyph (it, it->object, it->pixel_width,
1907 it->ascent + it->descent, ascent);
1908 }
1909 else
1910 x_append_glyph (it);
1911
1912 /* If characters with lbearing or rbearing are displayed
1913 in this line, record that fact in a flag of the
1914 glyph row. This is used to optimize X output code. */
1c7e22fd 1915 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1916 it->glyph_row->contains_overlapping_glyphs_p = 1;
1917 }
1918 }
1919 else if (it->char_to_display == '\n')
1920 {
1921 /* A newline has no width but we need the height of the line. */
1922 it->pixel_width = 0;
1923 it->nglyphs = 0;
b4192550
KH
1924 it->ascent = it->phys_ascent = font->ascent + boff;
1925 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1926
1927 if (face->box != FACE_NO_BOX)
1928 {
1929 int thick = face->box_line_width;
1930 it->ascent += thick;
1931 it->descent += thick;
1932 }
1933 }
1934 else if (it->char_to_display == '\t')
1935 {
1936 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1937 int x = it->current_x + it->continuation_lines_width;
06a2c219
GM
1938 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1939
1940 it->pixel_width = next_tab_x - x;
1941 it->nglyphs = 1;
b4192550
KH
1942 it->ascent = it->phys_ascent = font->ascent + boff;
1943 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1944
1945 if (it->glyph_row)
1946 {
1947 double ascent = (double) it->ascent / (it->ascent + it->descent);
1948 x_append_stretch_glyph (it, it->object, it->pixel_width,
1949 it->ascent + it->descent, ascent);
1950 }
1951 }
1952 else
1953 {
1954 /* A multi-byte character. Assume that the display width of the
1955 character is the width of the character multiplied by the
b4192550 1956 width of the font. */
06a2c219 1957
b4192550
KH
1958 /* If we found a font, this font should give us the right
1959 metrics. If we didn't find a font, use the frame's
1960 default font and calculate the width of the character
1961 from the charset width; this is what old redisplay code
1962 did. */
1963 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1964 if (font_not_found_p || !pcm)
1965 {
1966 int charset = CHAR_CHARSET (it->char_to_display);
1967
1968 it->glyph_not_available_p = 1;
1969 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1970 * CHARSET_WIDTH (charset));
1971 it->phys_ascent = font->ascent + boff;
1972 it->phys_descent = font->descent - boff;
1973 }
1974 else
1975 {
1976 it->pixel_width = pcm->width;
1977 it->phys_ascent = pcm->ascent + boff;
1978 it->phys_descent = pcm->descent - boff;
1979 if (it->glyph_row
1980 && (pcm->lbearing < 0
1981 || pcm->rbearing > pcm->width))
1982 it->glyph_row->contains_overlapping_glyphs_p = 1;
1983 }
b4192550
KH
1984 it->nglyphs = 1;
1985 it->ascent = font->ascent + boff;
1986 it->descent = font->descent - boff;
06a2c219
GM
1987 if (face->box != FACE_NO_BOX)
1988 {
1989 int thick = face->box_line_width;
1990 it->ascent += thick;
1991 it->descent += thick;
1992
1993 if (it->start_of_box_run_p)
1994 it->pixel_width += thick;
1995 if (it->end_of_box_run_p)
1996 it->pixel_width += thick;
1997 }
1998
1999 /* If face has an overline, add the height of the overline
2000 (1 pixel) and a 1 pixel margin to the character height. */
2001 if (face->overline_p)
2002 it->ascent += 2;
2003
2004 take_vertical_position_into_account (it);
2005
2006 if (it->glyph_row)
2007 x_append_glyph (it);
2008 }
2009 }
b4192550
KH
2010 else if (it->what == IT_COMPOSITION)
2011 {
2012 /* Note: A composition is represented as one glyph in the
2013 glyph matrix. There are no padding glyphs. */
2014 XChar2b char2b;
2015 XFontStruct *font;
ee569018 2016 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
2017 XCharStruct *pcm;
2018 int font_not_found_p;
2019 struct font_info *font_info;
2020 int boff; /* baseline offset */
2021 struct composition *cmp = composition_table[it->cmp_id];
2022
2023 /* Maybe translate single-byte characters to multibyte. */
2024 it->char_to_display = it->c;
2025 if (unibyte_display_via_language_environment
2026 && SINGLE_BYTE_CHAR_P (it->c)
2027 && (it->c >= 0240
2028 || (it->c >= 0200
2029 && !NILP (Vnonascii_translation_table))))
2030 {
2031 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2032 }
2033
2034 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2035 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2036 face = FACE_FROM_ID (it->f, it->face_id);
2037 x_get_char_face_and_encoding (it->f, it->char_to_display,
2038 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2039 font = face->font;
2040
2041 /* When no suitable font found, use the default font. */
2042 font_not_found_p = font == NULL;
2043 if (font_not_found_p)
2044 {
2045 font = FRAME_FONT (it->f);
2046 boff = it->f->output_data.x->baseline_offset;
2047 font_info = NULL;
2048 }
2049 else
2050 {
2051 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2052 boff = font_info->baseline_offset;
2053 if (font_info->vertical_centering)
2054 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2055 }
2056
2057 /* There are no padding glyphs, so there is only one glyph to
2058 produce for the composition. Important is that pixel_width,
2059 ascent and descent are the values of what is drawn by
2060 draw_glyphs (i.e. the values of the overall glyphs composed). */
2061 it->nglyphs = 1;
2062
2063 /* If we have not yet calculated pixel size data of glyphs of
2064 the composition for the current face font, calculate them
2065 now. Theoretically, we have to check all fonts for the
2066 glyphs, but that requires much time and memory space. So,
2067 here we check only the font of the first glyph. This leads
2068 to incorrect display very rarely, and C-l (recenter) can
2069 correct the display anyway. */
2070 if (cmp->font != (void *) font)
2071 {
2072 /* Ascent and descent of the font of the first character of
2073 this composition (adjusted by baseline offset). Ascent
2074 and descent of overall glyphs should not be less than
2075 them respectively. */
2076 int font_ascent = font->ascent + boff;
2077 int font_descent = font->descent - boff;
2078 /* Bounding box of the overall glyphs. */
2079 int leftmost, rightmost, lowest, highest;
329bed06 2080 int i, width, ascent, descent;
b4192550
KH
2081
2082 cmp->font = (void *) font;
2083
2084 /* Initialize the bounding box. */
2085 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2086 if (pcm)
2087 {
2088 width = pcm->width;
2089 ascent = pcm->ascent;
2090 descent = pcm->descent;
2091 }
2092 else
2093 {
2094 width = FONT_WIDTH (font);
2095 ascent = font->ascent;
2096 descent = font->descent;
2097 }
2098
2099 rightmost = width;
2100 lowest = - descent + boff;
2101 highest = ascent + boff;
b4192550 2102 leftmost = 0;
329bed06 2103
b4192550
KH
2104 if (font_info
2105 && font_info->default_ascent
2106 && CHAR_TABLE_P (Vuse_default_ascent)
2107 && !NILP (Faref (Vuse_default_ascent,
2108 make_number (it->char_to_display))))
2109 highest = font_info->default_ascent + boff;
2110
2111 /* Draw the first glyph at the normal position. It may be
2112 shifted to right later if some other glyphs are drawn at
2113 the left. */
2114 cmp->offsets[0] = 0;
2115 cmp->offsets[1] = boff;
2116
2117 /* Set cmp->offsets for the remaining glyphs. */
2118 for (i = 1; i < cmp->glyph_len; i++)
2119 {
2120 int left, right, btm, top;
2121 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2122 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2123
2124 face = FACE_FROM_ID (it->f, face_id);
2125 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2126 it->multibyte_p);
b4192550
KH
2127 font = face->font;
2128 if (font == NULL)
2129 {
2130 font = FRAME_FONT (it->f);
2131 boff = it->f->output_data.x->baseline_offset;
2132 font_info = NULL;
2133 }
2134 else
2135 {
2136 font_info
2137 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2138 boff = font_info->baseline_offset;
2139 if (font_info->vertical_centering)
2140 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2141 }
2142
2143 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2144 if (pcm)
2145 {
2146 width = pcm->width;
2147 ascent = pcm->ascent;
2148 descent = pcm->descent;
2149 }
2150 else
2151 {
2152 width = FONT_WIDTH (font);
2153 ascent = font->ascent;
2154 descent = font->descent;
2155 }
b4192550
KH
2156
2157 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2158 {
2159 /* Relative composition with or without
2160 alternate chars. */
329bed06
GM
2161 left = (leftmost + rightmost - width) / 2;
2162 btm = - descent + boff;
b4192550
KH
2163 if (font_info && font_info->relative_compose
2164 && (! CHAR_TABLE_P (Vignore_relative_composition)
2165 || NILP (Faref (Vignore_relative_composition,
2166 make_number (ch)))))
2167 {
2168
329bed06 2169 if (- descent >= font_info->relative_compose)
b4192550
KH
2170 /* One extra pixel between two glyphs. */
2171 btm = highest + 1;
329bed06 2172 else if (ascent <= 0)
b4192550 2173 /* One extra pixel between two glyphs. */
329bed06 2174 btm = lowest - 1 - ascent - descent;
b4192550
KH
2175 }
2176 }
2177 else
2178 {
2179 /* A composition rule is specified by an integer
2180 value that encodes global and new reference
2181 points (GREF and NREF). GREF and NREF are
2182 specified by numbers as below:
2183
2184 0---1---2 -- ascent
2185 | |
2186 | |
2187 | |
2188 9--10--11 -- center
2189 | |
2190 ---3---4---5--- baseline
2191 | |
2192 6---7---8 -- descent
2193 */
2194 int rule = COMPOSITION_RULE (cmp, i);
2195 int gref, nref, grefx, grefy, nrefx, nrefy;
2196
2197 COMPOSITION_DECODE_RULE (rule, gref, nref);
2198 grefx = gref % 3, nrefx = nref % 3;
2199 grefy = gref / 3, nrefy = nref / 3;
2200
2201 left = (leftmost
2202 + grefx * (rightmost - leftmost) / 2
329bed06 2203 - nrefx * width / 2);
b4192550
KH
2204 btm = ((grefy == 0 ? highest
2205 : grefy == 1 ? 0
2206 : grefy == 2 ? lowest
2207 : (highest + lowest) / 2)
329bed06
GM
2208 - (nrefy == 0 ? ascent + descent
2209 : nrefy == 1 ? descent - boff
b4192550 2210 : nrefy == 2 ? 0
329bed06 2211 : (ascent + descent) / 2));
b4192550
KH
2212 }
2213
2214 cmp->offsets[i * 2] = left;
329bed06 2215 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2216
2217 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2218 right = left + width;
2219 top = btm + descent + ascent;
b4192550
KH
2220 if (left < leftmost)
2221 leftmost = left;
2222 if (right > rightmost)
2223 rightmost = right;
2224 if (top > highest)
2225 highest = top;
2226 if (btm < lowest)
2227 lowest = btm;
2228 }
2229
2230 /* If there are glyphs whose x-offsets are negative,
2231 shift all glyphs to the right and make all x-offsets
2232 non-negative. */
2233 if (leftmost < 0)
2234 {
2235 for (i = 0; i < cmp->glyph_len; i++)
2236 cmp->offsets[i * 2] -= leftmost;
2237 rightmost -= leftmost;
2238 }
2239
2240 cmp->pixel_width = rightmost;
2241 cmp->ascent = highest;
2242 cmp->descent = - lowest;
2243 if (cmp->ascent < font_ascent)
2244 cmp->ascent = font_ascent;
2245 if (cmp->descent < font_descent)
2246 cmp->descent = font_descent;
2247 }
2248
2249 it->pixel_width = cmp->pixel_width;
2250 it->ascent = it->phys_ascent = cmp->ascent;
2251 it->descent = it->phys_descent = cmp->descent;
2252
2253 if (face->box != FACE_NO_BOX)
2254 {
2255 int thick = face->box_line_width;
2256 it->ascent += thick;
2257 it->descent += thick;
2258
2259 if (it->start_of_box_run_p)
2260 it->pixel_width += thick;
2261 if (it->end_of_box_run_p)
2262 it->pixel_width += thick;
2263 }
2264
2265 /* If face has an overline, add the height of the overline
2266 (1 pixel) and a 1 pixel margin to the character height. */
2267 if (face->overline_p)
2268 it->ascent += 2;
2269
2270 take_vertical_position_into_account (it);
2271
2272 if (it->glyph_row)
2273 x_append_composite_glyph (it);
2274 }
06a2c219
GM
2275 else if (it->what == IT_IMAGE)
2276 x_produce_image_glyph (it);
2277 else if (it->what == IT_STRETCH)
2278 x_produce_stretch_glyph (it);
2279
3017fdd1
GM
2280 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2281 because this isn't true for images with `:ascent 100'. */
2282 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2283 if (it->area == TEXT_AREA)
2284 it->current_x += it->pixel_width;
66ac4b0e 2285
d365f5bb
GM
2286 it->descent += it->extra_line_spacing;
2287
06a2c219
GM
2288 it->max_ascent = max (it->max_ascent, it->ascent);
2289 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2290 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2291 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2292}
2293
2294
2295/* Estimate the pixel height of the mode or top line on frame F.
2296 FACE_ID specifies what line's height to estimate. */
2297
2298int
2299x_estimate_mode_line_height (f, face_id)
2300 struct frame *f;
2301 enum face_id face_id;
2302{
2303 int height = 1;
2304
2305 /* This function is called so early when Emacs starts that the face
2306 cache and mode line face are not yet initialized. */
2307 if (FRAME_FACE_CACHE (f))
2308 {
2309 struct face *face = FACE_FROM_ID (f, face_id);
2310 if (face)
2311 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2312 }
2313
2314 return height;
2315}
2316
2317\f
2318/***********************************************************************
2319 Glyph display
2320 ***********************************************************************/
2321
2322/* A sequence of glyphs to be drawn in the same face.
2323
2324 This data structure is not really completely X specific, so it
2325 could possibly, at least partially, be useful for other systems. It
2326 is currently not part of the external redisplay interface because
2327 it's not clear what other systems will need. */
2328
2329struct glyph_string
2330{
2331 /* X-origin of the string. */
2332 int x;
2333
2334 /* Y-origin and y-position of the base line of this string. */
2335 int y, ybase;
2336
2337 /* The width of the string, not including a face extension. */
2338 int width;
2339
2340 /* The width of the string, including a face extension. */
2341 int background_width;
2342
2343 /* The height of this string. This is the height of the line this
2344 string is drawn in, and can be different from the height of the
2345 font the string is drawn in. */
2346 int height;
2347
2348 /* Number of pixels this string overwrites in front of its x-origin.
2349 This number is zero if the string has an lbearing >= 0; it is
2350 -lbearing, if the string has an lbearing < 0. */
2351 int left_overhang;
2352
2353 /* Number of pixels this string overwrites past its right-most
2354 nominal x-position, i.e. x + width. Zero if the string's
2355 rbearing is <= its nominal width, rbearing - width otherwise. */
2356 int right_overhang;
2357
2358 /* The frame on which the glyph string is drawn. */
2359 struct frame *f;
2360
2361 /* The window on which the glyph string is drawn. */
2362 struct window *w;
2363
2364 /* X display and window for convenience. */
2365 Display *display;
2366 Window window;
2367
2368 /* The glyph row for which this string was built. It determines the
2369 y-origin and height of the string. */
2370 struct glyph_row *row;
2371
2372 /* The area within row. */
2373 enum glyph_row_area area;
2374
2375 /* Characters to be drawn, and number of characters. */
2376 XChar2b *char2b;
2377 int nchars;
2378
06a2c219
GM
2379 /* A face-override for drawing cursors, mouse face and similar. */
2380 enum draw_glyphs_face hl;
2381
2382 /* Face in which this string is to be drawn. */
2383 struct face *face;
2384
2385 /* Font in which this string is to be drawn. */
2386 XFontStruct *font;
2387
2388 /* Font info for this string. */
2389 struct font_info *font_info;
2390
b4192550
KH
2391 /* Non-null means this string describes (part of) a composition.
2392 All characters from char2b are drawn composed. */
2393 struct composition *cmp;
06a2c219
GM
2394
2395 /* Index of this glyph string's first character in the glyph
b4192550
KH
2396 definition of CMP. If this is zero, this glyph string describes
2397 the first character of a composition. */
06a2c219
GM
2398 int gidx;
2399
2400 /* 1 means this glyph strings face has to be drawn to the right end
2401 of the window's drawing area. */
2402 unsigned extends_to_end_of_line_p : 1;
2403
2404 /* 1 means the background of this string has been drawn. */
2405 unsigned background_filled_p : 1;
2406
2407 /* 1 means glyph string must be drawn with 16-bit functions. */
2408 unsigned two_byte_p : 1;
2409
2410 /* 1 means that the original font determined for drawing this glyph
2411 string could not be loaded. The member `font' has been set to
2412 the frame's default font in this case. */
2413 unsigned font_not_found_p : 1;
2414
2415 /* 1 means that the face in which this glyph string is drawn has a
2416 stipple pattern. */
2417 unsigned stippled_p : 1;
2418
66ac4b0e
GM
2419 /* 1 means only the foreground of this glyph string must be drawn,
2420 and we should use the physical height of the line this glyph
2421 string appears in as clip rect. */
2422 unsigned for_overlaps_p : 1;
2423
06a2c219
GM
2424 /* The GC to use for drawing this glyph string. */
2425 GC gc;
2426
2427 /* A pointer to the first glyph in the string. This glyph
2428 corresponds to char2b[0]. Needed to draw rectangles if
2429 font_not_found_p is 1. */
2430 struct glyph *first_glyph;
2431
2432 /* Image, if any. */
2433 struct image *img;
2434
2435 struct glyph_string *next, *prev;
2436};
2437
2438
5c187dee 2439#if 0
06a2c219
GM
2440
2441static void
2442x_dump_glyph_string (s)
2443 struct glyph_string *s;
2444{
2445 fprintf (stderr, "glyph string\n");
2446 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2447 s->x, s->y, s->width, s->height);
2448 fprintf (stderr, " ybase = %d\n", s->ybase);
2449 fprintf (stderr, " hl = %d\n", s->hl);
2450 fprintf (stderr, " left overhang = %d, right = %d\n",
2451 s->left_overhang, s->right_overhang);
2452 fprintf (stderr, " nchars = %d\n", s->nchars);
2453 fprintf (stderr, " extends to end of line = %d\n",
2454 s->extends_to_end_of_line_p);
2455 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2456 fprintf (stderr, " bg width = %d\n", s->background_width);
2457}
2458
2459#endif /* GLYPH_DEBUG */
2460
2461
2462
2463static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2464 struct glyph_string **,
2465 struct glyph_string *,
2466 struct glyph_string *));
2467static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2468 struct glyph_string **,
2469 struct glyph_string *,
2470 struct glyph_string *));
2471static void x_append_glyph_string P_ ((struct glyph_string **,
2472 struct glyph_string **,
2473 struct glyph_string *));
2474static int x_left_overwritten P_ ((struct glyph_string *));
2475static int x_left_overwriting P_ ((struct glyph_string *));
2476static int x_right_overwritten P_ ((struct glyph_string *));
2477static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2478static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2479 int));
06a2c219
GM
2480static void x_init_glyph_string P_ ((struct glyph_string *,
2481 XChar2b *, struct window *,
2482 struct glyph_row *,
2483 enum glyph_row_area, int,
2484 enum draw_glyphs_face));
2485static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2486 enum glyph_row_area, int, int,
66ac4b0e 2487 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2488static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2489static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2490static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2491 int));
2492static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2493static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2494static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2495static void x_draw_glyph_string P_ ((struct glyph_string *));
2496static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2497static void x_set_cursor_gc P_ ((struct glyph_string *));
2498static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2499static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2500static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2501 int *, int *));
2502static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2503static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2504 unsigned long *, double, int));
06a2c219 2505static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2506 double, int, unsigned long));
06a2c219
GM
2507static void x_setup_relief_colors P_ ((struct glyph_string *));
2508static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2509static void x_draw_image_relief P_ ((struct glyph_string *));
2510static void x_draw_image_foreground P_ ((struct glyph_string *));
2511static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2512static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2513static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2514 int, int, int));
2515static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2516 int, int, int, int, XRectangle *));
2517static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2518 int, int, int, XRectangle *));
66ac4b0e
GM
2519static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2520 enum glyph_row_area));
209f68d9
GM
2521static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2522 struct glyph_row *,
2523 enum glyph_row_area, int, int));
06a2c219 2524
163dcff3
GM
2525#if GLYPH_DEBUG
2526static void x_check_font P_ ((struct frame *, XFontStruct *));
2527#endif
2528
06a2c219 2529
06a2c219
GM
2530/* Append the list of glyph strings with head H and tail T to the list
2531 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2532
2533static INLINE void
2534x_append_glyph_string_lists (head, tail, h, t)
2535 struct glyph_string **head, **tail;
2536 struct glyph_string *h, *t;
2537{
2538 if (h)
2539 {
2540 if (*head)
2541 (*tail)->next = h;
2542 else
2543 *head = h;
2544 h->prev = *tail;
2545 *tail = t;
2546 }
2547}
2548
2549
2550/* Prepend the list of glyph strings with head H and tail T to the
2551 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2552 result. */
2553
2554static INLINE void
2555x_prepend_glyph_string_lists (head, tail, h, t)
2556 struct glyph_string **head, **tail;
2557 struct glyph_string *h, *t;
2558{
2559 if (h)
2560 {
2561 if (*head)
2562 (*head)->prev = t;
2563 else
2564 *tail = t;
2565 t->next = *head;
2566 *head = h;
2567 }
2568}
2569
2570
2571/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2572 Set *HEAD and *TAIL to the resulting list. */
2573
2574static INLINE void
2575x_append_glyph_string (head, tail, s)
2576 struct glyph_string **head, **tail;
2577 struct glyph_string *s;
2578{
2579 s->next = s->prev = NULL;
2580 x_append_glyph_string_lists (head, tail, s, s);
2581}
2582
2583
2584/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2585 face. */
2586
2587static void
2588x_set_cursor_gc (s)
2589 struct glyph_string *s;
2590{
2591 if (s->font == FRAME_FONT (s->f)
2592 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2593 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2594 && !s->cmp)
06a2c219
GM
2595 s->gc = s->f->output_data.x->cursor_gc;
2596 else
2597 {
2598 /* Cursor on non-default face: must merge. */
2599 XGCValues xgcv;
2600 unsigned long mask;
2601
2602 xgcv.background = s->f->output_data.x->cursor_pixel;
2603 xgcv.foreground = s->face->background;
2604
2605 /* If the glyph would be invisible, try a different foreground. */
2606 if (xgcv.foreground == xgcv.background)
2607 xgcv.foreground = s->face->foreground;
2608 if (xgcv.foreground == xgcv.background)
2609 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2610 if (xgcv.foreground == xgcv.background)
2611 xgcv.foreground = s->face->foreground;
2612
2613 /* Make sure the cursor is distinct from text in this face. */
2614 if (xgcv.background == s->face->background
2615 && xgcv.foreground == s->face->foreground)
2616 {
2617 xgcv.background = s->face->foreground;
2618 xgcv.foreground = s->face->background;
2619 }
2620
2621 IF_DEBUG (x_check_font (s->f, s->font));
2622 xgcv.font = s->font->fid;
2623 xgcv.graphics_exposures = False;
2624 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2625
2626 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2627 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2628 mask, &xgcv);
2629 else
2630 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2631 = XCreateGC (s->display, s->window, mask, &xgcv);
2632
2633 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2634 }
2635}
2636
2637
2638/* Set up S->gc of glyph string S for drawing text in mouse face. */
2639
2640static void
2641x_set_mouse_face_gc (s)
2642 struct glyph_string *s;
2643{
2644 int face_id;
ee569018 2645 struct face *face;
06a2c219
GM
2646
2647 /* What face has to be used for the mouse face? */
2648 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2649 face = FACE_FROM_ID (s->f, face_id);
033e3e18
GM
2650 if (s->first_glyph->type == CHAR_GLYPH)
2651 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2652 else
2653 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2654 s->face = FACE_FROM_ID (s->f, face_id);
2655 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2656
2657 /* If font in this face is same as S->font, use it. */
2658 if (s->font == s->face->font)
2659 s->gc = s->face->gc;
2660 else
2661 {
2662 /* Otherwise construct scratch_cursor_gc with values from FACE
2663 but font FONT. */
2664 XGCValues xgcv;
2665 unsigned long mask;
2666
2667 xgcv.background = s->face->background;
2668 xgcv.foreground = s->face->foreground;
2669 IF_DEBUG (x_check_font (s->f, s->font));
2670 xgcv.font = s->font->fid;
2671 xgcv.graphics_exposures = False;
2672 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2673
2674 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2675 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2676 mask, &xgcv);
2677 else
2678 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2679 = XCreateGC (s->display, s->window, mask, &xgcv);
2680
2681 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2682 }
2683
2684 xassert (s->gc != 0);
2685}
2686
2687
2688/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2689 Faces to use in the mode line have already been computed when the
2690 matrix was built, so there isn't much to do, here. */
2691
2692static INLINE void
2693x_set_mode_line_face_gc (s)
2694 struct glyph_string *s;
2695{
2696 s->gc = s->face->gc;
06a2c219
GM
2697}
2698
2699
2700/* Set S->gc of glyph string S for drawing that glyph string. Set
2701 S->stippled_p to a non-zero value if the face of S has a stipple
2702 pattern. */
2703
2704static INLINE void
2705x_set_glyph_string_gc (s)
2706 struct glyph_string *s;
2707{
209f68d9
GM
2708 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2709
06a2c219
GM
2710 if (s->hl == DRAW_NORMAL_TEXT)
2711 {
2712 s->gc = s->face->gc;
2713 s->stippled_p = s->face->stipple != 0;
2714 }
2715 else if (s->hl == DRAW_INVERSE_VIDEO)
2716 {
2717 x_set_mode_line_face_gc (s);
2718 s->stippled_p = s->face->stipple != 0;
2719 }
2720 else if (s->hl == DRAW_CURSOR)
2721 {
2722 x_set_cursor_gc (s);
2723 s->stippled_p = 0;
2724 }
2725 else if (s->hl == DRAW_MOUSE_FACE)
2726 {
2727 x_set_mouse_face_gc (s);
2728 s->stippled_p = s->face->stipple != 0;
2729 }
2730 else if (s->hl == DRAW_IMAGE_RAISED
2731 || s->hl == DRAW_IMAGE_SUNKEN)
2732 {
2733 s->gc = s->face->gc;
2734 s->stippled_p = s->face->stipple != 0;
2735 }
2736 else
2737 {
2738 s->gc = s->face->gc;
2739 s->stippled_p = s->face->stipple != 0;
2740 }
2741
2742 /* GC must have been set. */
2743 xassert (s->gc != 0);
2744}
2745
2746
2747/* Return in *R the clipping rectangle for glyph string S. */
2748
2749static void
2750x_get_glyph_string_clip_rect (s, r)
2751 struct glyph_string *s;
2752 XRectangle *r;
2753{
2754 if (s->row->full_width_p)
2755 {
2756 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2757 int canon_x = CANON_X_UNIT (s->f);
2758
2759 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2760 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2761
2762 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2763 {
1da3fd71 2764 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2765 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2766 r->x -= width;
2767 }
2768
b9432a85 2769 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2770
06a2c219
GM
2771 /* Unless displaying a mode or menu bar line, which are always
2772 fully visible, clip to the visible part of the row. */
2773 if (s->w->pseudo_window_p)
2774 r->height = s->row->visible_height;
2775 else
2776 r->height = s->height;
2777 }
2778 else
2779 {
2780 /* This is a text line that may be partially visible. */
2781 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2782 r->width = window_box_width (s->w, s->area);
2783 r->height = s->row->visible_height;
2784 }
2785
2786 /* Don't use S->y for clipping because it doesn't take partially
2787 visible lines into account. For example, it can be negative for
2788 partially visible lines at the top of a window. */
2789 if (!s->row->full_width_p
2790 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2791 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2792 else
2793 r->y = max (0, s->row->y);
06a2c219 2794
9ea173e8 2795 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2796 at the top of the window. */
9ea173e8 2797 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2798 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2799
2800 /* If S draws overlapping rows, it's sufficient to use the top and
2801 bottom of the window for clipping because this glyph string
2802 intentionally draws over other lines. */
2803 if (s->for_overlaps_p)
2804 {
045dee35 2805 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2806 r->height = window_text_bottom_y (s->w) - r->y;
2807 }
2808
2809 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2810}
2811
2812
2813/* Set clipping for output of glyph string S. S may be part of a mode
2814 line or menu if we don't have X toolkit support. */
2815
2816static INLINE void
2817x_set_glyph_string_clipping (s)
2818 struct glyph_string *s;
2819{
2820 XRectangle r;
2821 x_get_glyph_string_clip_rect (s, &r);
2822 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2823}
2824
2825
2826/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2827 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2828
2829static INLINE void
2830x_compute_glyph_string_overhangs (s)
2831 struct glyph_string *s;
2832{
b4192550 2833 if (s->cmp == NULL
06a2c219
GM
2834 && s->first_glyph->type == CHAR_GLYPH)
2835 {
2836 XCharStruct cs;
2837 int direction, font_ascent, font_descent;
2838 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2839 &font_ascent, &font_descent, &cs);
2840 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2841 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2842 }
2843}
2844
2845
2846/* Compute overhangs and x-positions for glyph string S and its
2847 predecessors, or successors. X is the starting x-position for S.
2848 BACKWARD_P non-zero means process predecessors. */
2849
2850static void
2851x_compute_overhangs_and_x (s, x, backward_p)
2852 struct glyph_string *s;
2853 int x;
2854 int backward_p;
2855{
2856 if (backward_p)
2857 {
2858 while (s)
2859 {
2860 x_compute_glyph_string_overhangs (s);
2861 x -= s->width;
2862 s->x = x;
2863 s = s->prev;
2864 }
2865 }
2866 else
2867 {
2868 while (s)
2869 {
2870 x_compute_glyph_string_overhangs (s);
2871 s->x = x;
2872 x += s->width;
2873 s = s->next;
2874 }
2875 }
2876}
2877
2878
2879/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2880 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2881 assumed to be zero. */
06a2c219
GM
2882
2883static void
2884x_get_glyph_overhangs (glyph, f, left, right)
2885 struct glyph *glyph;
2886 struct frame *f;
2887 int *left, *right;
2888{
06a2c219
GM
2889 *left = *right = 0;
2890
b4192550 2891 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2892 {
2893 XFontStruct *font;
2894 struct face *face;
2895 struct font_info *font_info;
2896 XChar2b char2b;
ee569018
KH
2897 XCharStruct *pcm;
2898
2899 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2900 font = face->font;
2901 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2902 if (font
2903 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2904 {
06a2c219
GM
2905 if (pcm->rbearing > pcm->width)
2906 *right = pcm->rbearing - pcm->width;
2907 if (pcm->lbearing < 0)
2908 *left = -pcm->lbearing;
2909 }
2910 }
2911}
2912
2913
2914/* Return the index of the first glyph preceding glyph string S that
2915 is overwritten by S because of S's left overhang. Value is -1
2916 if no glyphs are overwritten. */
2917
2918static int
2919x_left_overwritten (s)
2920 struct glyph_string *s;
2921{
2922 int k;
2923
2924 if (s->left_overhang)
2925 {
2926 int x = 0, i;
2927 struct glyph *glyphs = s->row->glyphs[s->area];
2928 int first = s->first_glyph - glyphs;
2929
2930 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2931 x -= glyphs[i].pixel_width;
2932
2933 k = i + 1;
2934 }
2935 else
2936 k = -1;
2937
2938 return k;
2939}
2940
2941
2942/* Return the index of the first glyph preceding glyph string S that
2943 is overwriting S because of its right overhang. Value is -1 if no
2944 glyph in front of S overwrites S. */
2945
2946static int
2947x_left_overwriting (s)
2948 struct glyph_string *s;
2949{
2950 int i, k, x;
2951 struct glyph *glyphs = s->row->glyphs[s->area];
2952 int first = s->first_glyph - glyphs;
2953
2954 k = -1;
2955 x = 0;
2956 for (i = first - 1; i >= 0; --i)
2957 {
2958 int left, right;
2959 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2960 if (x + right > 0)
2961 k = i;
2962 x -= glyphs[i].pixel_width;
2963 }
2964
2965 return k;
2966}
2967
2968
2969/* Return the index of the last glyph following glyph string S that is
2970 not overwritten by S because of S's right overhang. Value is -1 if
2971 no such glyph is found. */
2972
2973static int
2974x_right_overwritten (s)
2975 struct glyph_string *s;
2976{
2977 int k = -1;
2978
2979 if (s->right_overhang)
2980 {
2981 int x = 0, i;
2982 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2983 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2984 int end = s->row->used[s->area];
2985
2986 for (i = first; i < end && s->right_overhang > x; ++i)
2987 x += glyphs[i].pixel_width;
2988
2989 k = i;
2990 }
2991
2992 return k;
2993}
2994
2995
2996/* Return the index of the last glyph following glyph string S that
2997 overwrites S because of its left overhang. Value is negative
2998 if no such glyph is found. */
2999
3000static int
3001x_right_overwriting (s)
3002 struct glyph_string *s;
3003{
3004 int i, k, x;
3005 int end = s->row->used[s->area];
3006 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 3007 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
3008
3009 k = -1;
3010 x = 0;
3011 for (i = first; i < end; ++i)
3012 {
3013 int left, right;
3014 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
3015 if (x - left < 0)
3016 k = i;
3017 x += glyphs[i].pixel_width;
3018 }
3019
3020 return k;
3021}
3022
3023
3024/* Fill rectangle X, Y, W, H with background color of glyph string S. */
3025
3026static INLINE void
3027x_clear_glyph_string_rect (s, x, y, w, h)
3028 struct glyph_string *s;
3029 int x, y, w, h;
3030{
3031 XGCValues xgcv;
3032 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3033 XSetForeground (s->display, s->gc, xgcv.background);
3034 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3035 XSetForeground (s->display, s->gc, xgcv.foreground);
3036}
3037
3038
3039/* Draw the background of glyph_string S. If S->background_filled_p
3040 is non-zero don't draw it. FORCE_P non-zero means draw the
3041 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3042 when a string preceding S draws into the background of S, or S
3043 contains the first component of a composition. */
06a2c219
GM
3044
3045static void
3046x_draw_glyph_string_background (s, force_p)
3047 struct glyph_string *s;
3048 int force_p;
3049{
3050 /* Nothing to do if background has already been drawn or if it
3051 shouldn't be drawn in the first place. */
3052 if (!s->background_filled_p)
3053 {
b4192550 3054 if (s->stippled_p)
06a2c219
GM
3055 {
3056 /* Fill background with a stipple pattern. */
3057 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3058 XFillRectangle (s->display, s->window, s->gc, s->x,
3059 s->y + s->face->box_line_width,
3060 s->background_width,
3061 s->height - 2 * s->face->box_line_width);
3062 XSetFillStyle (s->display, s->gc, FillSolid);
3063 s->background_filled_p = 1;
3064 }
3065 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3066 || s->font_not_found_p
3067 || s->extends_to_end_of_line_p
06a2c219
GM
3068 || force_p)
3069 {
3070 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3071 s->background_width,
3072 s->height - 2 * s->face->box_line_width);
3073 s->background_filled_p = 1;
3074 }
3075 }
3076}
3077
3078
3079/* Draw the foreground of glyph string S. */
3080
3081static void
3082x_draw_glyph_string_foreground (s)
3083 struct glyph_string *s;
3084{
3085 int i, x;
3086
3087 /* If first glyph of S has a left box line, start drawing the text
3088 of S to the right of that box line. */
3089 if (s->face->box != FACE_NO_BOX
3090 && s->first_glyph->left_box_line_p)
3091 x = s->x + s->face->box_line_width;
3092 else
3093 x = s->x;
3094
b4192550
KH
3095 /* Draw characters of S as rectangles if S's font could not be
3096 loaded. */
3097 if (s->font_not_found_p)
06a2c219 3098 {
b4192550 3099 for (i = 0; i < s->nchars; ++i)
06a2c219 3100 {
b4192550
KH
3101 struct glyph *g = s->first_glyph + i;
3102 XDrawRectangle (s->display, s->window,
3103 s->gc, x, s->y, g->pixel_width - 1,
3104 s->height - 1);
3105 x += g->pixel_width;
06a2c219
GM
3106 }
3107 }
3108 else
3109 {
b4192550
KH
3110 char *char1b = (char *) s->char2b;
3111 int boff = s->font_info->baseline_offset;
06a2c219 3112
b4192550
KH
3113 if (s->font_info->vertical_centering)
3114 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3115
3116 /* If we can use 8-bit functions, condense S->char2b. */
3117 if (!s->two_byte_p)
3118 for (i = 0; i < s->nchars; ++i)
3119 char1b[i] = s->char2b[i].byte2;
3120
3121 /* Draw text with XDrawString if background has already been
3122 filled. Otherwise, use XDrawImageString. (Note that
3123 XDrawImageString is usually faster than XDrawString.) Always
3124 use XDrawImageString when drawing the cursor so that there is
3125 no chance that characters under a box cursor are invisible. */
3126 if (s->for_overlaps_p
3127 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3128 {
3129 /* Draw characters with 16-bit or 8-bit functions. */
3130 if (s->two_byte_p)
3131 XDrawString16 (s->display, s->window, s->gc, x,
3132 s->ybase - boff, s->char2b, s->nchars);
3133 else
3134 XDrawString (s->display, s->window, s->gc, x,
3135 s->ybase - boff, char1b, s->nchars);
3136 }
06a2c219
GM
3137 else
3138 {
b4192550
KH
3139 if (s->two_byte_p)
3140 XDrawImageString16 (s->display, s->window, s->gc, x,
3141 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3142 else
b4192550
KH
3143 XDrawImageString (s->display, s->window, s->gc, x,
3144 s->ybase - boff, char1b, s->nchars);
3145 }
3146 }
3147}
06a2c219 3148
b4192550 3149/* Draw the foreground of composite glyph string S. */
06a2c219 3150
b4192550
KH
3151static void
3152x_draw_composite_glyph_string_foreground (s)
3153 struct glyph_string *s;
3154{
3155 int i, x;
06a2c219 3156
b4192550
KH
3157 /* If first glyph of S has a left box line, start drawing the text
3158 of S to the right of that box line. */
3159 if (s->face->box != FACE_NO_BOX
3160 && s->first_glyph->left_box_line_p)
3161 x = s->x + s->face->box_line_width;
3162 else
3163 x = s->x;
06a2c219 3164
b4192550
KH
3165 /* S is a glyph string for a composition. S->gidx is the index of
3166 the first character drawn for glyphs of this composition.
3167 S->gidx == 0 means we are drawing the very first character of
3168 this composition. */
06a2c219 3169
b4192550
KH
3170 /* Draw a rectangle for the composition if the font for the very
3171 first character of the composition could not be loaded. */
3172 if (s->font_not_found_p)
3173 {
3174 if (s->gidx == 0)
3175 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3176 s->width - 1, s->height - 1);
3177 }
3178 else
3179 {
3180 for (i = 0; i < s->nchars; i++, ++s->gidx)
3181 XDrawString16 (s->display, s->window, s->gc,
3182 x + s->cmp->offsets[s->gidx * 2],
3183 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3184 s->char2b + i, 1);
06a2c219
GM
3185 }
3186}
3187
3188
80c32bcc
GM
3189#ifdef USE_X_TOOLKIT
3190
3e71d8f2 3191static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3192
3e71d8f2
GM
3193
3194/* Return the frame on which widget WIDGET is used.. Abort if frame
3195 cannot be determined. */
3196
e851c833 3197static struct frame *
3e71d8f2 3198x_frame_of_widget (widget)
80c32bcc 3199 Widget widget;
80c32bcc 3200{
80c32bcc 3201 struct x_display_info *dpyinfo;
5c187dee 3202 Lisp_Object tail;
3e71d8f2
GM
3203 struct frame *f;
3204
80c32bcc
GM
3205 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3206
3207 /* Find the top-level shell of the widget. Note that this function
3208 can be called when the widget is not yet realized, so XtWindow
3209 (widget) == 0. That's the reason we can't simply use
3210 x_any_window_to_frame. */
3211 while (!XtIsTopLevelShell (widget))
3212 widget = XtParent (widget);
3213
3214 /* Look for a frame with that top-level widget. Allocate the color
3215 on that frame to get the right gamma correction value. */
3216 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3217 if (GC_FRAMEP (XCAR (tail))
3218 && (f = XFRAME (XCAR (tail)),
3219 (f->output_data.nothing != 1
3220 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3221 && f->output_data.x->widget == widget)
3e71d8f2 3222 return f;
80c32bcc
GM
3223
3224 abort ();
3225}
3226
3e71d8f2
GM
3227
3228/* Allocate the color COLOR->pixel on the screen and display of
3229 widget WIDGET in colormap CMAP. If an exact match cannot be
3230 allocated, try the nearest color available. Value is non-zero
3231 if successful. This is called from lwlib. */
3232
3233int
3234x_alloc_nearest_color_for_widget (widget, cmap, color)
3235 Widget widget;
3236 Colormap cmap;
3237 XColor *color;
3238{
3239 struct frame *f = x_frame_of_widget (widget);
3240 return x_alloc_nearest_color (f, cmap, color);
3241}
3242
3243
80c32bcc
GM
3244#endif /* USE_X_TOOLKIT */
3245
3246
06a2c219
GM
3247/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3248 CMAP. If an exact match can't be allocated, try the nearest color
3249 available. Value is non-zero if successful. Set *COLOR to the
3250 color allocated. */
3251
3252int
80c32bcc
GM
3253x_alloc_nearest_color (f, cmap, color)
3254 struct frame *f;
06a2c219
GM
3255 Colormap cmap;
3256 XColor *color;
3257{
80c32bcc
GM
3258 Display *display = FRAME_X_DISPLAY (f);
3259 Screen *screen = FRAME_X_SCREEN (f);
3260 int rc;
3261
3262 gamma_correct (f, color);
3263 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3264 if (rc == 0)
3265 {
3266 /* If we got to this point, the colormap is full, so we're going
3267 to try to get the next closest color. The algorithm used is
3268 a least-squares matching, which is what X uses for closest
3269 color matching with StaticColor visuals. */
3270 int nearest, i;
3271 unsigned long nearest_delta = ~0;
3272 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3273 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3274
3275 for (i = 0; i < ncells; ++i)
3276 cells[i].pixel = i;
3277 XQueryColors (display, cmap, cells, ncells);
3278
3279 for (nearest = i = 0; i < ncells; ++i)
3280 {
3281 long dred = (color->red >> 8) - (cells[i].red >> 8);
3282 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3283 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3284 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3285
3286 if (delta < nearest_delta)
3287 {
3288 nearest = i;
3289 nearest_delta = delta;
3290 }
3291 }
3292
3293 color->red = cells[nearest].red;
3294 color->green = cells[nearest].green;
3295 color->blue = cells[nearest].blue;
3296 rc = XAllocColor (display, cmap, color);
3297 }
3298
d9c545da
GM
3299#ifdef DEBUG_X_COLORS
3300 if (rc)
3301 register_color (color->pixel);
3302#endif /* DEBUG_X_COLORS */
3303
06a2c219
GM
3304 return rc;
3305}
3306
3307
d9c545da
GM
3308/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3309 It's necessary to do this instead of just using PIXEL directly to
3310 get color reference counts right. */
3311
3312unsigned long
3313x_copy_color (f, pixel)
3314 struct frame *f;
3315 unsigned long pixel;
3316{
3317 XColor color;
3318
3319 color.pixel = pixel;
3320 BLOCK_INPUT;
3321 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3322 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3323 UNBLOCK_INPUT;
3324#ifdef DEBUG_X_COLORS
3325 register_color (pixel);
3326#endif
3327 return color.pixel;
3328}
3329
3330
3e71d8f2
GM
3331/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3332 It's necessary to do this instead of just using PIXEL directly to
3333 get color reference counts right. */
3334
3335unsigned long
3336x_copy_dpy_color (dpy, cmap, pixel)
3337 Display *dpy;
3338 Colormap cmap;
3339 unsigned long pixel;
3340{
3341 XColor color;
3342
3343 color.pixel = pixel;
3344 BLOCK_INPUT;
3345 XQueryColor (dpy, cmap, &color);
3346 XAllocColor (dpy, cmap, &color);
3347 UNBLOCK_INPUT;
3348#ifdef DEBUG_X_COLORS
3349 register_color (pixel);
3350#endif
3351 return color.pixel;
3352}
3353
3354
06a2c219
GM
3355/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3356 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3357 If this produces the same color as PIXEL, try a color where all RGB
3358 values have DELTA added. Return the allocated color in *PIXEL.
3359 DISPLAY is the X display, CMAP is the colormap to operate on.
3360 Value is non-zero if successful. */
3361
3362static int
3363x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3364 struct frame *f;
3365 Display *display;
3366 Colormap cmap;
3367 unsigned long *pixel;
68c45bf0 3368 double factor;
06a2c219
GM
3369 int delta;
3370{
3371 XColor color, new;
3372 int success_p;
3373
3374 /* Get RGB color values. */
3375 color.pixel = *pixel;
3376 XQueryColor (display, cmap, &color);
3377
3378 /* Change RGB values by specified FACTOR. Avoid overflow! */
3379 xassert (factor >= 0);
3380 new.red = min (0xffff, factor * color.red);
3381 new.green = min (0xffff, factor * color.green);
3382 new.blue = min (0xffff, factor * color.blue);
3383
3384 /* Try to allocate the color. */
80c32bcc 3385 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3386 if (success_p)
3387 {
3388 if (new.pixel == *pixel)
3389 {
3390 /* If we end up with the same color as before, try adding
3391 delta to the RGB values. */
0d605c67 3392 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3393
3394 new.red = min (0xffff, delta + color.red);
3395 new.green = min (0xffff, delta + color.green);
3396 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3397 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3398 }
3399 else
3400 success_p = 1;
3401 *pixel = new.pixel;
3402 }
3403
3404 return success_p;
3405}
3406
3407
3408/* Set up the foreground color for drawing relief lines of glyph
3409 string S. RELIEF is a pointer to a struct relief containing the GC
3410 with which lines will be drawn. Use a color that is FACTOR or
3411 DELTA lighter or darker than the relief's background which is found
3412 in S->f->output_data.x->relief_background. If such a color cannot
3413 be allocated, use DEFAULT_PIXEL, instead. */
3414
3415static void
3416x_setup_relief_color (f, relief, factor, delta, default_pixel)
3417 struct frame *f;
3418 struct relief *relief;
68c45bf0 3419 double factor;
06a2c219
GM
3420 int delta;
3421 unsigned long default_pixel;
3422{
3423 XGCValues xgcv;
3424 struct x_output *di = f->output_data.x;
3425 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3426 unsigned long pixel;
3427 unsigned long background = di->relief_background;
43bd1b2b 3428 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3429 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3430 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3431
3432 xgcv.graphics_exposures = False;
3433 xgcv.line_width = 1;
3434
3435 /* Free previously allocated color. The color cell will be reused
3436 when it has been freed as many times as it was allocated, so this
3437 doesn't affect faces using the same colors. */
3438 if (relief->gc
3439 && relief->allocated_p)
3440 {
0d605c67 3441 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3442 relief->allocated_p = 0;
3443 }
3444
3445 /* Allocate new color. */
3446 xgcv.foreground = default_pixel;
3447 pixel = background;
dcd08bfb
GM
3448 if (dpyinfo->n_planes != 1
3449 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3450 {
3451 relief->allocated_p = 1;
3452 xgcv.foreground = relief->pixel = pixel;
3453 }
3454
3455 if (relief->gc == 0)
3456 {
dcd08bfb 3457 xgcv.stipple = dpyinfo->gray;
06a2c219 3458 mask |= GCStipple;
dcd08bfb 3459 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3460 }
3461 else
dcd08bfb 3462 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3463}
3464
3465
3466/* Set up colors for the relief lines around glyph string S. */
3467
3468static void
3469x_setup_relief_colors (s)
3470 struct glyph_string *s;
3471{
3472 struct x_output *di = s->f->output_data.x;
3473 unsigned long color;
3474
3475 if (s->face->use_box_color_for_shadows_p)
3476 color = s->face->box_color;
3477 else
3478 {
3479 XGCValues xgcv;
3480
3481 /* Get the background color of the face. */
3482 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3483 color = xgcv.background;
3484 }
3485
3486 if (di->white_relief.gc == 0
3487 || color != di->relief_background)
3488 {
3489 di->relief_background = color;
3490 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3491 WHITE_PIX_DEFAULT (s->f));
3492 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3493 BLACK_PIX_DEFAULT (s->f));
3494 }
3495}
3496
3497
3498/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3499 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3500 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3501 relief. LEFT_P non-zero means draw a relief on the left side of
3502 the rectangle. RIGHT_P non-zero means draw a relief on the right
3503 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3504 when drawing. */
3505
3506static void
3507x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3508 raised_p, left_p, right_p, clip_rect)
3509 struct frame *f;
3510 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3511 XRectangle *clip_rect;
3512{
3513 int i;
3514 GC gc;
3515
3516 if (raised_p)
3517 gc = f->output_data.x->white_relief.gc;
3518 else
3519 gc = f->output_data.x->black_relief.gc;
3520 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3521
3522 /* Top. */
3523 for (i = 0; i < width; ++i)
3524 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3525 left_x + i * left_p, top_y + i,
3526 right_x + 1 - i * right_p, top_y + i);
3527
3528 /* Left. */
3529 if (left_p)
3530 for (i = 0; i < width; ++i)
3531 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3532 left_x + i, top_y + i, left_x + i, bottom_y - i);
3533
3534 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3535 if (raised_p)
3536 gc = f->output_data.x->black_relief.gc;
3537 else
3538 gc = f->output_data.x->white_relief.gc;
3539 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3540
3541 /* Bottom. */
3542 for (i = 0; i < width; ++i)
3543 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3544 left_x + i * left_p, bottom_y - i,
3545 right_x + 1 - i * right_p, bottom_y - i);
3546
3547 /* Right. */
3548 if (right_p)
3549 for (i = 0; i < width; ++i)
3550 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3551 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3552
3553 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3554}
3555
3556
3557/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3558 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3559 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3560 left side of the rectangle. RIGHT_P non-zero means draw a line
3561 on the right side of the rectangle. CLIP_RECT is the clipping
3562 rectangle to use when drawing. */
3563
3564static void
3565x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3566 left_p, right_p, clip_rect)
3567 struct glyph_string *s;
3568 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3569 XRectangle *clip_rect;
3570{
3571 XGCValues xgcv;
3572
3573 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3574 XSetForeground (s->display, s->gc, s->face->box_color);
3575 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3576
3577 /* Top. */
3578 XFillRectangle (s->display, s->window, s->gc,
3579 left_x, top_y, right_x - left_x, width);
3580
3581 /* Left. */
3582 if (left_p)
3583 XFillRectangle (s->display, s->window, s->gc,
3584 left_x, top_y, width, bottom_y - top_y);
3585
3586 /* Bottom. */
3587 XFillRectangle (s->display, s->window, s->gc,
3588 left_x, bottom_y - width, right_x - left_x, width);
3589
3590 /* Right. */
3591 if (right_p)
3592 XFillRectangle (s->display, s->window, s->gc,
3593 right_x - width, top_y, width, bottom_y - top_y);
3594
3595 XSetForeground (s->display, s->gc, xgcv.foreground);
3596 XSetClipMask (s->display, s->gc, None);
3597}
3598
3599
3600/* Draw a box around glyph string S. */
3601
3602static void
3603x_draw_glyph_string_box (s)
3604 struct glyph_string *s;
3605{
3606 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3607 int left_p, right_p;
3608 struct glyph *last_glyph;
3609 XRectangle clip_rect;
3610
3611 last_x = window_box_right (s->w, s->area);
3612 if (s->row->full_width_p
3613 && !s->w->pseudo_window_p)
3614 {
110859fc 3615 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3616 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3617 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3618 }
3619
3620 /* The glyph that may have a right box line. */
b4192550 3621 last_glyph = (s->cmp || s->img
06a2c219
GM
3622 ? s->first_glyph
3623 : s->first_glyph + s->nchars - 1);
3624
3625 width = s->face->box_line_width;
3626 raised_p = s->face->box == FACE_RAISED_BOX;
3627 left_x = s->x;
3628 right_x = ((s->row->full_width_p
1da3fd71 3629 ? last_x - 1
a7aeb2de 3630 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3631 top_y = s->y;
3632 bottom_y = top_y + s->height - 1;
3633
3634 left_p = (s->first_glyph->left_box_line_p
3635 || (s->hl == DRAW_MOUSE_FACE
3636 && (s->prev == NULL
3637 || s->prev->hl != s->hl)));
3638 right_p = (last_glyph->right_box_line_p
3639 || (s->hl == DRAW_MOUSE_FACE
3640 && (s->next == NULL
3641 || s->next->hl != s->hl)));
3642
3643 x_get_glyph_string_clip_rect (s, &clip_rect);
3644
3645 if (s->face->box == FACE_SIMPLE_BOX)
3646 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3647 left_p, right_p, &clip_rect);
3648 else
3649 {
3650 x_setup_relief_colors (s);
3651 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3652 width, raised_p, left_p, right_p, &clip_rect);
3653 }
3654}
3655
3656
3657/* Draw foreground of image glyph string S. */
3658
3659static void
3660x_draw_image_foreground (s)
3661 struct glyph_string *s;
3662{
3663 int x;
95af8492 3664 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3665
3666 /* If first glyph of S has a left box line, start drawing it to the
3667 right of that line. */
3668 if (s->face->box != FACE_NO_BOX
3669 && s->first_glyph->left_box_line_p)
3670 x = s->x + s->face->box_line_width;
3671 else
3672 x = s->x;
3673
3674 /* If there is a margin around the image, adjust x- and y-position
3675 by that margin. */
3676 if (s->img->margin)
3677 {
3678 x += s->img->margin;
3679 y += s->img->margin;
3680 }
3681
3682 if (s->img->pixmap)
3683 {
3684 if (s->img->mask)
3685 {
3686 /* We can't set both a clip mask and use XSetClipRectangles
3687 because the latter also sets a clip mask. We also can't
3688 trust on the shape extension to be available
3689 (XShapeCombineRegion). So, compute the rectangle to draw
3690 manually. */
3691 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3692 | GCFunction);
3693 XGCValues xgcv;
3694 XRectangle clip_rect, image_rect, r;
3695
3696 xgcv.clip_mask = s->img->mask;
3697 xgcv.clip_x_origin = x;
3698 xgcv.clip_y_origin = y;
3699 xgcv.function = GXcopy;
3700 XChangeGC (s->display, s->gc, mask, &xgcv);
3701
3702 x_get_glyph_string_clip_rect (s, &clip_rect);
3703 image_rect.x = x;
3704 image_rect.y = y;
3705 image_rect.width = s->img->width;
3706 image_rect.height = s->img->height;
3707 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3708 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3709 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3710 }
3711 else
3712 {
3713 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3714 0, 0, s->img->width, s->img->height, x, y);
3715
3716 /* When the image has a mask, we can expect that at
3717 least part of a mouse highlight or a block cursor will
3718 be visible. If the image doesn't have a mask, make
3719 a block cursor visible by drawing a rectangle around
3720 the image. I believe it's looking better if we do
3721 nothing here for mouse-face. */
3722 if (s->hl == DRAW_CURSOR)
3723 XDrawRectangle (s->display, s->window, s->gc, x, y,
3724 s->img->width - 1, s->img->height - 1);
3725 }
3726 }
3727 else
3728 /* Draw a rectangle if image could not be loaded. */
3729 XDrawRectangle (s->display, s->window, s->gc, x, y,
3730 s->img->width - 1, s->img->height - 1);
3731}
3732
3733
3734/* Draw a relief around the image glyph string S. */
3735
3736static void
3737x_draw_image_relief (s)
3738 struct glyph_string *s;
3739{
3740 int x0, y0, x1, y1, thick, raised_p;
3741 XRectangle r;
3742 int x;
95af8492 3743 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3744
3745 /* If first glyph of S has a left box line, start drawing it to the
3746 right of that line. */
3747 if (s->face->box != FACE_NO_BOX
3748 && s->first_glyph->left_box_line_p)
3749 x = s->x + s->face->box_line_width;
3750 else
3751 x = s->x;
3752
3753 /* If there is a margin around the image, adjust x- and y-position
3754 by that margin. */
3755 if (s->img->margin)
3756 {
3757 x += s->img->margin;
3758 y += s->img->margin;
3759 }
3760
3761 if (s->hl == DRAW_IMAGE_SUNKEN
3762 || s->hl == DRAW_IMAGE_RAISED)
3763 {
9ea173e8 3764 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3765 raised_p = s->hl == DRAW_IMAGE_RAISED;
3766 }
3767 else
3768 {
3769 thick = abs (s->img->relief);
3770 raised_p = s->img->relief > 0;
3771 }
3772
3773 x0 = x - thick;
3774 y0 = y - thick;
3775 x1 = x + s->img->width + thick - 1;
3776 y1 = y + s->img->height + thick - 1;
3777
3778 x_setup_relief_colors (s);
3779 x_get_glyph_string_clip_rect (s, &r);
3780 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3781}
3782
3783
3784/* Draw the foreground of image glyph string S to PIXMAP. */
3785
3786static void
3787x_draw_image_foreground_1 (s, pixmap)
3788 struct glyph_string *s;
3789 Pixmap pixmap;
3790{
3791 int x;
95af8492 3792 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3793
3794 /* If first glyph of S has a left box line, start drawing it to the
3795 right of that line. */
3796 if (s->face->box != FACE_NO_BOX
3797 && s->first_glyph->left_box_line_p)
3798 x = s->face->box_line_width;
3799 else
3800 x = 0;
3801
3802 /* If there is a margin around the image, adjust x- and y-position
3803 by that margin. */
3804 if (s->img->margin)
3805 {
3806 x += s->img->margin;
3807 y += s->img->margin;
3808 }
dc43ef94 3809
06a2c219
GM
3810 if (s->img->pixmap)
3811 {
3812 if (s->img->mask)
3813 {
3814 /* We can't set both a clip mask and use XSetClipRectangles
3815 because the latter also sets a clip mask. We also can't
3816 trust on the shape extension to be available
3817 (XShapeCombineRegion). So, compute the rectangle to draw
3818 manually. */
3819 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3820 | GCFunction);
3821 XGCValues xgcv;
3822
3823 xgcv.clip_mask = s->img->mask;
3824 xgcv.clip_x_origin = x;
3825 xgcv.clip_y_origin = y;
3826 xgcv.function = GXcopy;
3827 XChangeGC (s->display, s->gc, mask, &xgcv);
3828
3829 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3830 0, 0, s->img->width, s->img->height, x, y);
3831 XSetClipMask (s->display, s->gc, None);
3832 }
3833 else
3834 {
3835 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3836 0, 0, s->img->width, s->img->height, x, y);
3837
3838 /* When the image has a mask, we can expect that at
3839 least part of a mouse highlight or a block cursor will
3840 be visible. If the image doesn't have a mask, make
3841 a block cursor visible by drawing a rectangle around
3842 the image. I believe it's looking better if we do
3843 nothing here for mouse-face. */
3844 if (s->hl == DRAW_CURSOR)
3845 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3846 s->img->width - 1, s->img->height - 1);
3847 }
3848 }
3849 else
3850 /* Draw a rectangle if image could not be loaded. */
3851 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3852 s->img->width - 1, s->img->height - 1);
3853}
dc43ef94 3854
990ba854 3855
06a2c219
GM
3856/* Draw part of the background of glyph string S. X, Y, W, and H
3857 give the rectangle to draw. */
a9a5b0a5 3858
06a2c219
GM
3859static void
3860x_draw_glyph_string_bg_rect (s, x, y, w, h)
3861 struct glyph_string *s;
3862 int x, y, w, h;
3863{
3864 if (s->stippled_p)
3865 {
3866 /* Fill background with a stipple pattern. */
3867 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3868 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3869 XSetFillStyle (s->display, s->gc, FillSolid);
3870 }
3871 else
3872 x_clear_glyph_string_rect (s, x, y, w, h);
3873}
07e34cb0 3874
b5210ea7 3875
06a2c219 3876/* Draw image glyph string S.
dc43ef94 3877
06a2c219
GM
3878 s->y
3879 s->x +-------------------------
3880 | s->face->box
3881 |
3882 | +-------------------------
3883 | | s->img->margin
3884 | |
3885 | | +-------------------
3886 | | | the image
dc43ef94 3887
06a2c219 3888 */
dc43ef94 3889
06a2c219
GM
3890static void
3891x_draw_image_glyph_string (s)
3892 struct glyph_string *s;
3893{
3894 int x, y;
3895 int box_line_width = s->face->box_line_width;
3896 int margin = s->img->margin;
3897 int height;
3898 Pixmap pixmap = None;
3899
3900 height = s->height - 2 * box_line_width;
3901
3902 /* Fill background with face under the image. Do it only if row is
3903 taller than image or if image has a clip mask to reduce
3904 flickering. */
3905 s->stippled_p = s->face->stipple != 0;
3906 if (height > s->img->height
3907 || margin
3908 || s->img->mask
3909 || s->img->pixmap == 0
3910 || s->width != s->background_width)
3911 {
3912 if (box_line_width && s->first_glyph->left_box_line_p)
3913 x = s->x + box_line_width;
3914 else
3915 x = s->x;
3916
3917 y = s->y + box_line_width;
3918
3919 if (s->img->mask)
3920 {
3921 /* Create a pixmap as large as the glyph string Fill it with
3922 the background color. Copy the image to it, using its
3923 mask. Copy the temporary pixmap to the display. */
3924 Screen *screen = FRAME_X_SCREEN (s->f);
3925 int depth = DefaultDepthOfScreen (screen);
3926
3927 /* Create a pixmap as large as the glyph string. */
3928 pixmap = XCreatePixmap (s->display, s->window,
3929 s->background_width,
3930 s->height, depth);
3931
3932 /* Don't clip in the following because we're working on the
3933 pixmap. */
3934 XSetClipMask (s->display, s->gc, None);
3935
3936 /* Fill the pixmap with the background color/stipple. */
3937 if (s->stippled_p)
3938 {
3939 /* Fill background with a stipple pattern. */
3940 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3941 XFillRectangle (s->display, pixmap, s->gc,
3942 0, 0, s->background_width, s->height);
3943 XSetFillStyle (s->display, s->gc, FillSolid);
3944 }
3945 else
3946 {
3947 XGCValues xgcv;
3948 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3949 &xgcv);
3950 XSetForeground (s->display, s->gc, xgcv.background);
3951 XFillRectangle (s->display, pixmap, s->gc,
3952 0, 0, s->background_width, s->height);
3953 XSetForeground (s->display, s->gc, xgcv.foreground);
3954 }
3955 }
3956 else
3957 /* Implementation idea: Is it possible to construct a mask?
3958 We could look at the color at the margins of the image, and
3959 say that this color is probably the background color of the
3960 image. */
3961 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3962
3963 s->background_filled_p = 1;
3964 }
dc43ef94 3965
06a2c219
GM
3966 /* Draw the foreground. */
3967 if (pixmap != None)
3968 {
3969 x_draw_image_foreground_1 (s, pixmap);
3970 x_set_glyph_string_clipping (s);
3971 XCopyArea (s->display, pixmap, s->window, s->gc,
3972 0, 0, s->background_width, s->height, s->x, s->y);
3973 XFreePixmap (s->display, pixmap);
3974 }
3975 else
3976 x_draw_image_foreground (s);
b5210ea7 3977
06a2c219
GM
3978 /* If we must draw a relief around the image, do it. */
3979 if (s->img->relief
3980 || s->hl == DRAW_IMAGE_RAISED
3981 || s->hl == DRAW_IMAGE_SUNKEN)
3982 x_draw_image_relief (s);
3983}
8c1a6a84 3984
990ba854 3985
06a2c219 3986/* Draw stretch glyph string S. */
dc43ef94 3987
06a2c219
GM
3988static void
3989x_draw_stretch_glyph_string (s)
3990 struct glyph_string *s;
3991{
3992 xassert (s->first_glyph->type == STRETCH_GLYPH);
3993 s->stippled_p = s->face->stipple != 0;
990ba854 3994
06a2c219
GM
3995 if (s->hl == DRAW_CURSOR
3996 && !x_stretch_cursor_p)
3997 {
3998 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3999 as wide as the stretch glyph. */
4000 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 4001
06a2c219
GM
4002 /* Draw cursor. */
4003 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 4004
06a2c219
GM
4005 /* Clear rest using the GC of the original non-cursor face. */
4006 if (width < s->background_width)
4007 {
4008 GC gc = s->face->gc;
4009 int x = s->x + width, y = s->y;
4010 int w = s->background_width - width, h = s->height;
4011 XRectangle r;
dc43ef94 4012
06a2c219
GM
4013 x_get_glyph_string_clip_rect (s, &r);
4014 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 4015
06a2c219
GM
4016 if (s->face->stipple)
4017 {
4018 /* Fill background with a stipple pattern. */
4019 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4020 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4021 XSetFillStyle (s->display, gc, FillSolid);
4022 }
4023 else
4024 {
4025 XGCValues xgcv;
4026 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
4027 XSetForeground (s->display, gc, xgcv.background);
4028 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4029 XSetForeground (s->display, gc, xgcv.foreground);
4030 }
4031 }
4032 }
4033 else
4034 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4035 s->height);
4036
4037 s->background_filled_p = 1;
4038}
4039
4040
4041/* Draw glyph string S. */
4042
4043static void
4044x_draw_glyph_string (s)
4045 struct glyph_string *s;
4046{
4047 /* If S draws into the background of its successor, draw the
4048 background of the successor first so that S can draw into it.
4049 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4050 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4051 {
4052 xassert (s->next->img == NULL);
4053 x_set_glyph_string_gc (s->next);
4054 x_set_glyph_string_clipping (s->next);
4055 x_draw_glyph_string_background (s->next, 1);
4056 }
97210f4e 4057
06a2c219
GM
4058 /* Set up S->gc, set clipping and draw S. */
4059 x_set_glyph_string_gc (s);
4060 x_set_glyph_string_clipping (s);
4061
4062 switch (s->first_glyph->type)
4063 {
4064 case IMAGE_GLYPH:
4065 x_draw_image_glyph_string (s);
4066 break;
4067
4068 case STRETCH_GLYPH:
4069 x_draw_stretch_glyph_string (s);
4070 break;
4071
4072 case CHAR_GLYPH:
66ac4b0e
GM
4073 if (s->for_overlaps_p)
4074 s->background_filled_p = 1;
4075 else
4076 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4077 x_draw_glyph_string_foreground (s);
4078 break;
4079
b4192550
KH
4080 case COMPOSITE_GLYPH:
4081 if (s->for_overlaps_p || s->gidx > 0)
4082 s->background_filled_p = 1;
4083 else
4084 x_draw_glyph_string_background (s, 1);
4085 x_draw_composite_glyph_string_foreground (s);
4086 break;
4087
06a2c219
GM
4088 default:
4089 abort ();
4090 }
4091
66ac4b0e 4092 if (!s->for_overlaps_p)
06a2c219 4093 {
66ac4b0e
GM
4094 /* Draw underline. */
4095 if (s->face->underline_p)
4096 {
4097 unsigned long dy, h;
06a2c219 4098
66ac4b0e
GM
4099 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4100 h = 1;
4101 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4102 dy = s->height - h;
06a2c219 4103
66ac4b0e
GM
4104 if (s->face->underline_defaulted_p)
4105 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4106 s->width, h);
4107 else
4108 {
4109 XGCValues xgcv;
4110 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4111 XSetForeground (s->display, s->gc, s->face->underline_color);
4112 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4113 s->width, h);
4114 XSetForeground (s->display, s->gc, xgcv.foreground);
4115 }
dc6f92b8 4116 }
07e34cb0 4117
66ac4b0e
GM
4118 /* Draw overline. */
4119 if (s->face->overline_p)
06a2c219 4120 {
66ac4b0e
GM
4121 unsigned long dy = 0, h = 1;
4122
4123 if (s->face->overline_color_defaulted_p)
4124 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4125 s->width, h);
4126 else
4127 {
4128 XGCValues xgcv;
4129 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4130 XSetForeground (s->display, s->gc, s->face->overline_color);
4131 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4132 s->width, h);
4133 XSetForeground (s->display, s->gc, xgcv.foreground);
4134 }
06a2c219 4135 }
06a2c219 4136
66ac4b0e
GM
4137 /* Draw strike-through. */
4138 if (s->face->strike_through_p)
06a2c219 4139 {
66ac4b0e
GM
4140 unsigned long h = 1;
4141 unsigned long dy = (s->height - h) / 2;
4142
4143 if (s->face->strike_through_color_defaulted_p)
4144 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4145 s->width, h);
4146 else
4147 {
4148 XGCValues xgcv;
4149 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4150 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4151 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4152 s->width, h);
4153 XSetForeground (s->display, s->gc, xgcv.foreground);
4154 }
06a2c219 4155 }
06a2c219 4156
66ac4b0e
GM
4157 /* Draw relief. */
4158 if (s->face->box != FACE_NO_BOX)
4159 x_draw_glyph_string_box (s);
4160 }
06a2c219
GM
4161
4162 /* Reset clipping. */
4163 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4164}
07e34cb0 4165
06a2c219 4166
b4192550
KH
4167static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4168 struct face **, int));
06a2c219 4169
06a2c219 4170
209f68d9
GM
4171/* Fill glyph string S with composition components specified by S->cmp.
4172
b4192550
KH
4173 FACES is an array of faces for all components of this composition.
4174 S->gidx is the index of the first component for S.
4175 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4176 use its physical height for clipping.
06a2c219 4177
b4192550 4178 Value is the index of a component not in S. */
07e34cb0 4179
b4192550
KH
4180static int
4181x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4182 struct glyph_string *s;
b4192550 4183 struct face **faces;
66ac4b0e 4184 int overlaps_p;
07e34cb0 4185{
b4192550 4186 int i;
06a2c219 4187
b4192550 4188 xassert (s);
06a2c219 4189
b4192550 4190 s->for_overlaps_p = overlaps_p;
06a2c219 4191
b4192550
KH
4192 s->face = faces[s->gidx];
4193 s->font = s->face->font;
4194 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4195
b4192550
KH
4196 /* For all glyphs of this composition, starting at the offset
4197 S->gidx, until we reach the end of the definition or encounter a
4198 glyph that requires the different face, add it to S. */
4199 ++s->nchars;
4200 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4201 ++s->nchars;
06a2c219 4202
b4192550
KH
4203 /* All glyph strings for the same composition has the same width,
4204 i.e. the width set for the first component of the composition. */
06a2c219 4205
06a2c219
GM
4206 s->width = s->first_glyph->pixel_width;
4207
4208 /* If the specified font could not be loaded, use the frame's
4209 default font, but record the fact that we couldn't load it in
4210 the glyph string so that we can draw rectangles for the
4211 characters of the glyph string. */
4212 if (s->font == NULL)
4213 {
4214 s->font_not_found_p = 1;
4215 s->font = FRAME_FONT (s->f);
4216 }
4217
4218 /* Adjust base line for subscript/superscript text. */
4219 s->ybase += s->first_glyph->voffset;
4220
4221 xassert (s->face && s->face->gc);
4222
4223 /* This glyph string must always be drawn with 16-bit functions. */
4224 s->two_byte_p = 1;
b4192550
KH
4225
4226 return s->gidx + s->nchars;
06a2c219
GM
4227}
4228
4229
209f68d9
GM
4230/* Fill glyph string S from a sequence of character glyphs.
4231
06a2c219 4232 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4233 first glyph to consider, END is the index of the last + 1.
4234 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4235 use its physical height for clipping.
66ac4b0e
GM
4236
4237 Value is the index of the first glyph not in S. */
06a2c219
GM
4238
4239static int
66ac4b0e 4240x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4241 struct glyph_string *s;
4242 int face_id;
66ac4b0e 4243 int start, end, overlaps_p;
06a2c219
GM
4244{
4245 struct glyph *glyph, *last;
4246 int voffset;
ee569018 4247 int glyph_not_available_p;
06a2c219 4248
06a2c219
GM
4249 xassert (s->f == XFRAME (s->w->frame));
4250 xassert (s->nchars == 0);
4251 xassert (start >= 0 && end > start);
4252
66ac4b0e 4253 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4254 glyph = s->row->glyphs[s->area] + start;
4255 last = s->row->glyphs[s->area] + end;
4256 voffset = glyph->voffset;
4257
ee569018
KH
4258 glyph_not_available_p = glyph->glyph_not_available_p;
4259
06a2c219
GM
4260 while (glyph < last
4261 && glyph->type == CHAR_GLYPH
4262 && glyph->voffset == voffset
ee569018
KH
4263 /* Same face id implies same font, nowadays. */
4264 && glyph->face_id == face_id
4265 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4266 {
ee569018
KH
4267 int two_byte_p;
4268
06a2c219 4269 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4270 s->char2b + s->nchars,
4271 &two_byte_p);
4272 s->two_byte_p = two_byte_p;
06a2c219
GM
4273 ++s->nchars;
4274 xassert (s->nchars <= end - start);
4275 s->width += glyph->pixel_width;
4276 ++glyph;
4277 }
4278
4279 s->font = s->face->font;
4280 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4281
4282 /* If the specified font could not be loaded, use the frame's font,
4283 but record the fact that we couldn't load it in
4284 S->font_not_found_p so that we can draw rectangles for the
4285 characters of the glyph string. */
ee569018 4286 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4287 {
4288 s->font_not_found_p = 1;
4289 s->font = FRAME_FONT (s->f);
4290 }
4291
4292 /* Adjust base line for subscript/superscript text. */
4293 s->ybase += voffset;
66ac4b0e 4294
06a2c219
GM
4295 xassert (s->face && s->face->gc);
4296 return glyph - s->row->glyphs[s->area];
07e34cb0 4297}
dc6f92b8 4298
06a2c219
GM
4299
4300/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4301
dfcf069d 4302static void
06a2c219
GM
4303x_fill_image_glyph_string (s)
4304 struct glyph_string *s;
4305{
4306 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4307 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4308 xassert (s->img);
43d120d8 4309 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4310 s->font = s->face->font;
4311 s->width = s->first_glyph->pixel_width;
4312
4313 /* Adjust base line for subscript/superscript text. */
4314 s->ybase += s->first_glyph->voffset;
4315}
4316
4317
209f68d9 4318/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4319
209f68d9
GM
4320 ROW is the glyph row in which the glyphs are found, AREA is the
4321 area within the row. START is the index of the first glyph to
4322 consider, END is the index of the last + 1.
4323
4324 Value is the index of the first glyph not in S. */
4325
4326static int
4327x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4328 struct glyph_string *s;
209f68d9
GM
4329 struct glyph_row *row;
4330 enum glyph_row_area area;
4331 int start, end;
06a2c219 4332{
209f68d9
GM
4333 struct glyph *glyph, *last;
4334 int voffset, face_id;
4335
06a2c219 4336 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4337
4338 glyph = s->row->glyphs[s->area] + start;
4339 last = s->row->glyphs[s->area] + end;
4340 face_id = glyph->face_id;
4341 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4342 s->font = s->face->font;
209f68d9
GM
4343 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4344 s->width = glyph->pixel_width;
4345 voffset = glyph->voffset;
4346
4347 for (++glyph;
4348 (glyph < last
4349 && glyph->type == STRETCH_GLYPH
4350 && glyph->voffset == voffset
4351 && glyph->face_id == face_id);
4352 ++glyph)
4353 s->width += glyph->pixel_width;
06a2c219
GM
4354
4355 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4356 s->ybase += voffset;
4357
4358 xassert (s->face && s->face->gc);
4359 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4360}
4361
4362
4363/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4364 of XChar2b structures for S; it can't be allocated in
4365 x_init_glyph_string because it must be allocated via `alloca'. W
4366 is the window on which S is drawn. ROW and AREA are the glyph row
4367 and area within the row from which S is constructed. START is the
4368 index of the first glyph structure covered by S. HL is a
4369 face-override for drawing S. */
4370
4371static void
4372x_init_glyph_string (s, char2b, w, row, area, start, hl)
4373 struct glyph_string *s;
4374 XChar2b *char2b;
4375 struct window *w;
4376 struct glyph_row *row;
4377 enum glyph_row_area area;
4378 int start;
4379 enum draw_glyphs_face hl;
4380{
4381 bzero (s, sizeof *s);
4382 s->w = w;
4383 s->f = XFRAME (w->frame);
4384 s->display = FRAME_X_DISPLAY (s->f);
4385 s->window = FRAME_X_WINDOW (s->f);
4386 s->char2b = char2b;
4387 s->hl = hl;
4388 s->row = row;
4389 s->area = area;
4390 s->first_glyph = row->glyphs[area] + start;
4391 s->height = row->height;
4392 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4393
9ea173e8
GM
4394 /* Display the internal border below the tool-bar window. */
4395 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4396 s->y -= s->f->output_data.x->internal_border_width;
4397
4398 s->ybase = s->y + row->ascent;
4399}
4400
4401
4402/* Set background width of glyph string S. START is the index of the
4403 first glyph following S. LAST_X is the right-most x-position + 1
4404 in the drawing area. */
4405
4406static INLINE void
4407x_set_glyph_string_background_width (s, start, last_x)
4408 struct glyph_string *s;
4409 int start;
4410 int last_x;
4411{
4412 /* If the face of this glyph string has to be drawn to the end of
4413 the drawing area, set S->extends_to_end_of_line_p. */
4414 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4415
4416 if (start == s->row->used[s->area]
4417 && s->hl == DRAW_NORMAL_TEXT
4418 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4419 || s->face->background != default_face->background
4420 || s->face->stipple != default_face->stipple))
4421 s->extends_to_end_of_line_p = 1;
4422
4423 /* If S extends its face to the end of the line, set its
4424 background_width to the distance to the right edge of the drawing
4425 area. */
4426 if (s->extends_to_end_of_line_p)
1da3fd71 4427 s->background_width = last_x - s->x + 1;
06a2c219
GM
4428 else
4429 s->background_width = s->width;
4430}
4431
4432
4433/* Add a glyph string for a stretch glyph to the list of strings
4434 between HEAD and TAIL. START is the index of the stretch glyph in
4435 row area AREA of glyph row ROW. END is the index of the last glyph
4436 in that glyph row area. X is the current output position assigned
4437 to the new glyph string constructed. HL overrides that face of the
4438 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4439 is the right-most x-position of the drawing area. */
4440
8abee2e1
DL
4441/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4442 and below -- keep them on one line. */
4443#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4444 do \
4445 { \
4446 s = (struct glyph_string *) alloca (sizeof *s); \
4447 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4448 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4449 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4450 s->x = (X); \
4451 } \
4452 while (0)
4453
4454
4455/* Add a glyph string for an image glyph to the list of strings
4456 between HEAD and TAIL. START is the index of the image glyph in
4457 row area AREA of glyph row ROW. END is the index of the last glyph
4458 in that glyph row area. X is the current output position assigned
4459 to the new glyph string constructed. HL overrides that face of the
4460 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4461 is the right-most x-position of the drawing area. */
4462
8abee2e1 4463#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4464 do \
4465 { \
4466 s = (struct glyph_string *) alloca (sizeof *s); \
4467 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4468 x_fill_image_glyph_string (s); \
4469 x_append_glyph_string (&HEAD, &TAIL, s); \
4470 ++START; \
4471 s->x = (X); \
4472 } \
4473 while (0)
4474
4475
4476/* Add a glyph string for a sequence of character glyphs to the list
4477 of strings between HEAD and TAIL. START is the index of the first
4478 glyph in row area AREA of glyph row ROW that is part of the new
4479 glyph string. END is the index of the last glyph in that glyph row
4480 area. X is the current output position assigned to the new glyph
4481 string constructed. HL overrides that face of the glyph; e.g. it
4482 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4483 right-most x-position of the drawing area. */
4484
8abee2e1 4485#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4486 do \
4487 { \
3e71d8f2 4488 int c, face_id; \
06a2c219
GM
4489 XChar2b *char2b; \
4490 \
43d120d8 4491 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4492 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4493 \
b4192550
KH
4494 s = (struct glyph_string *) alloca (sizeof *s); \
4495 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4496 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4497 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4498 s->x = (X); \
4499 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4500 OVERLAPS_P); \
06a2c219
GM
4501 } \
4502 while (0)
4503
4504
b4192550
KH
4505/* Add a glyph string for a composite sequence to the list of strings
4506 between HEAD and TAIL. START is the index of the first glyph in
4507 row area AREA of glyph row ROW that is part of the new glyph
4508 string. END is the index of the last glyph in that glyph row area.
4509 X is the current output position assigned to the new glyph string
4510 constructed. HL overrides that face of the glyph; e.g. it is
4511 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4512 x-position of the drawing area. */
4513
6c27ec25 4514#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4515 do { \
43d120d8
KH
4516 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4517 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4518 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4519 struct composition *cmp = composition_table[cmp_id]; \
4520 int glyph_len = cmp->glyph_len; \
4521 XChar2b *char2b; \
4522 struct face **faces; \
4523 struct glyph_string *first_s = NULL; \
4524 int n; \
4525 \
ee569018 4526 base_face = base_face->ascii_face; \
b4192550
KH
4527 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4528 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4529 /* At first, fill in `char2b' and `faces'. */ \
4530 for (n = 0; n < glyph_len; n++) \
4531 { \
43d120d8 4532 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4533 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4534 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4535 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4536 this_face_id, char2b + n, 1); \
b4192550
KH
4537 } \
4538 \
4539 /* Make glyph_strings for each glyph sequence that is drawable by \
4540 the same face, and append them to HEAD/TAIL. */ \
4541 for (n = 0; n < cmp->glyph_len;) \
4542 { \
4543 s = (struct glyph_string *) alloca (sizeof *s); \
4544 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4545 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4546 s->cmp = cmp; \
4547 s->gidx = n; \
b4192550
KH
4548 s->x = (X); \
4549 \
4550 if (n == 0) \
4551 first_s = s; \
4552 \
4553 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4554 } \
4555 \
4556 ++START; \
4557 s = first_s; \
4558 } while (0)
4559
4560
06a2c219
GM
4561/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4562 of AREA of glyph row ROW on window W between indices START and END.
4563 HL overrides the face for drawing glyph strings, e.g. it is
4564 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4565 x-positions of the drawing area.
4566
4567 This is an ugly monster macro construct because we must use alloca
4568 to allocate glyph strings (because x_draw_glyphs can be called
4569 asynchronously). */
4570
8abee2e1 4571#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4572 do \
4573 { \
4574 HEAD = TAIL = NULL; \
4575 while (START < END) \
4576 { \
4577 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4578 switch (first_glyph->type) \
4579 { \
4580 case CHAR_GLYPH: \
4581 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4582 TAIL, HL, X, LAST_X, \
4583 OVERLAPS_P); \
06a2c219
GM
4584 break; \
4585 \
b4192550
KH
4586 case COMPOSITE_GLYPH: \
4587 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4588 HEAD, TAIL, HL, X, LAST_X,\
4589 OVERLAPS_P); \
4590 break; \
4591 \
06a2c219
GM
4592 case STRETCH_GLYPH: \
4593 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4594 HEAD, TAIL, HL, X, LAST_X); \
4595 break; \
4596 \
4597 case IMAGE_GLYPH: \
4598 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4599 TAIL, HL, X, LAST_X); \
4600 break; \
4601 \
4602 default: \
4603 abort (); \
4604 } \
4605 \
4606 x_set_glyph_string_background_width (s, START, LAST_X); \
4607 (X) += s->width; \
4608 } \
4609 } \
4610 while (0)
4611
4612
4613/* Draw glyphs between START and END in AREA of ROW on window W,
4614 starting at x-position X. X is relative to AREA in W. HL is a
4615 face-override with the following meaning:
4616
4617 DRAW_NORMAL_TEXT draw normally
4618 DRAW_CURSOR draw in cursor face
4619 DRAW_MOUSE_FACE draw in mouse face.
4620 DRAW_INVERSE_VIDEO draw in mode line face
4621 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4622 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4623
4624 If REAL_START is non-null, return in *REAL_START the real starting
4625 position for display. This can be different from START in case
4626 overlapping glyphs must be displayed. If REAL_END is non-null,
4627 return in *REAL_END the real end position for display. This can be
4628 different from END in case overlapping glyphs must be displayed.
4629
66ac4b0e
GM
4630 If OVERLAPS_P is non-zero, draw only the foreground of characters
4631 and clip to the physical height of ROW.
4632
06a2c219
GM
4633 Value is the x-position reached, relative to AREA of W. */
4634
4635static int
66ac4b0e
GM
4636x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4637 overlaps_p)
06a2c219
GM
4638 struct window *w;
4639 int x;
4640 struct glyph_row *row;
4641 enum glyph_row_area area;
4642 int start, end;
4643 enum draw_glyphs_face hl;
4644 int *real_start, *real_end;
66ac4b0e 4645 int overlaps_p;
dc6f92b8 4646{
06a2c219
GM
4647 struct glyph_string *head, *tail;
4648 struct glyph_string *s;
4649 int last_x, area_width;
4650 int x_reached;
4651 int i, j;
4652
4653 /* Let's rather be paranoid than getting a SEGV. */
4654 start = max (0, start);
4655 end = min (end, row->used[area]);
4656 if (real_start)
4657 *real_start = start;
4658 if (real_end)
4659 *real_end = end;
4660
4661 /* Translate X to frame coordinates. Set last_x to the right
4662 end of the drawing area. */
4663 if (row->full_width_p)
4664 {
4665 /* X is relative to the left edge of W, without scroll bars
4666 or flag areas. */
4667 struct frame *f = XFRAME (w->frame);
110859fc 4668 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4669 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4670
06a2c219
GM
4671 x += window_left_x;
4672 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4673 last_x = window_left_x + area_width;
4674
4675 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4676 {
110859fc 4677 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4678 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4679 last_x += width;
4680 else
4681 x -= width;
4682 }
dc6f92b8 4683
b9432a85
GM
4684 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4685 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4686 }
4687 else
dc6f92b8 4688 {
06a2c219
GM
4689 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4690 area_width = window_box_width (w, area);
4691 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4692 }
4693
06a2c219
GM
4694 /* Build a doubly-linked list of glyph_string structures between
4695 head and tail from what we have to draw. Note that the macro
4696 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4697 the reason we use a separate variable `i'. */
4698 i = start;
66ac4b0e
GM
4699 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4700 overlaps_p);
06a2c219
GM
4701 if (tail)
4702 x_reached = tail->x + tail->background_width;
4703 else
4704 x_reached = x;
90e65f07 4705
06a2c219
GM
4706 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4707 the row, redraw some glyphs in front or following the glyph
4708 strings built above. */
66ac4b0e 4709 if (!overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4710 {
4711 int dummy_x = 0;
4712 struct glyph_string *h, *t;
4713
4714 /* Compute overhangs for all glyph strings. */
4715 for (s = head; s; s = s->next)
4716 x_compute_glyph_string_overhangs (s);
4717
4718 /* Prepend glyph strings for glyphs in front of the first glyph
4719 string that are overwritten because of the first glyph
4720 string's left overhang. The background of all strings
4721 prepended must be drawn because the first glyph string
4722 draws over it. */
4723 i = x_left_overwritten (head);
4724 if (i >= 0)
4725 {
4726 j = i;
4727 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4728 DRAW_NORMAL_TEXT, dummy_x, last_x,
4729 overlaps_p);
06a2c219
GM
4730 start = i;
4731 if (real_start)
4732 *real_start = start;
4733 x_compute_overhangs_and_x (t, head->x, 1);
4734 x_prepend_glyph_string_lists (&head, &tail, h, t);
4735 }
58769bee 4736
06a2c219
GM
4737 /* Prepend glyph strings for glyphs in front of the first glyph
4738 string that overwrite that glyph string because of their
4739 right overhang. For these strings, only the foreground must
4740 be drawn, because it draws over the glyph string at `head'.
4741 The background must not be drawn because this would overwrite
4742 right overhangs of preceding glyphs for which no glyph
4743 strings exist. */
4744 i = x_left_overwriting (head);
4745 if (i >= 0)
4746 {
4747 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4748 DRAW_NORMAL_TEXT, dummy_x, last_x,
4749 overlaps_p);
06a2c219
GM
4750 for (s = h; s; s = s->next)
4751 s->background_filled_p = 1;
4752 if (real_start)
4753 *real_start = i;
4754 x_compute_overhangs_and_x (t, head->x, 1);
4755 x_prepend_glyph_string_lists (&head, &tail, h, t);
4756 }
dbcb258a 4757
06a2c219
GM
4758 /* Append glyphs strings for glyphs following the last glyph
4759 string tail that are overwritten by tail. The background of
4760 these strings has to be drawn because tail's foreground draws
4761 over it. */
4762 i = x_right_overwritten (tail);
4763 if (i >= 0)
4764 {
4765 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4766 DRAW_NORMAL_TEXT, x, last_x,
4767 overlaps_p);
06a2c219
GM
4768 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4769 x_append_glyph_string_lists (&head, &tail, h, t);
4770 if (real_end)
4771 *real_end = i;
4772 }
dc6f92b8 4773
06a2c219
GM
4774 /* Append glyph strings for glyphs following the last glyph
4775 string tail that overwrite tail. The foreground of such
4776 glyphs has to be drawn because it writes into the background
4777 of tail. The background must not be drawn because it could
4778 paint over the foreground of following glyphs. */
4779 i = x_right_overwriting (tail);
4780 if (i >= 0)
4781 {
4782 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4783 DRAW_NORMAL_TEXT, x, last_x,
4784 overlaps_p);
06a2c219
GM
4785 for (s = h; s; s = s->next)
4786 s->background_filled_p = 1;
4787 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4788 x_append_glyph_string_lists (&head, &tail, h, t);
4789 if (real_end)
4790 *real_end = i;
4791 }
4792 }
58769bee 4793
06a2c219
GM
4794 /* Draw all strings. */
4795 for (s = head; s; s = s->next)
4796 x_draw_glyph_string (s);
dc6f92b8 4797
06a2c219
GM
4798 /* Value is the x-position up to which drawn, relative to AREA of W.
4799 This doesn't include parts drawn because of overhangs. */
4800 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4801 if (!row->full_width_p)
4802 {
4803 if (area > LEFT_MARGIN_AREA)
4804 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4805 if (area > TEXT_AREA)
4806 x_reached -= window_box_width (w, TEXT_AREA);
4807 }
4808 return x_reached;
4809}
dc6f92b8 4810
dc6f92b8 4811
66ac4b0e
GM
4812/* Fix the display of area AREA of overlapping row ROW in window W. */
4813
4814static void
4815x_fix_overlapping_area (w, row, area)
4816 struct window *w;
4817 struct glyph_row *row;
4818 enum glyph_row_area area;
4819{
4820 int i, x;
4821
4822 BLOCK_INPUT;
4823
4824 if (area == LEFT_MARGIN_AREA)
4825 x = 0;
4826 else if (area == TEXT_AREA)
4827 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4828 else
4829 x = (window_box_width (w, LEFT_MARGIN_AREA)
4830 + window_box_width (w, TEXT_AREA));
4831
4832 for (i = 0; i < row->used[area];)
4833 {
4834 if (row->glyphs[area][i].overlaps_vertically_p)
4835 {
4836 int start = i, start_x = x;
4837
4838 do
4839 {
4840 x += row->glyphs[area][i].pixel_width;
4841 ++i;
4842 }
4843 while (i < row->used[area]
4844 && row->glyphs[area][i].overlaps_vertically_p);
4845
4846 x_draw_glyphs (w, start_x, row, area, start, i,
4847 (row->inverse_p
4848 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4849 NULL, NULL, 1);
4850 }
4851 else
4852 {
4853 x += row->glyphs[area][i].pixel_width;
4854 ++i;
4855 }
4856 }
4857
4858 UNBLOCK_INPUT;
4859}
4860
4861
06a2c219
GM
4862/* Output LEN glyphs starting at START at the nominal cursor position.
4863 Advance the nominal cursor over the text. The global variable
4864 updated_window contains the window being updated, updated_row is
4865 the glyph row being updated, and updated_area is the area of that
4866 row being updated. */
dc6f92b8 4867
06a2c219
GM
4868static void
4869x_write_glyphs (start, len)
4870 struct glyph *start;
4871 int len;
4872{
4873 int x, hpos, real_start, real_end;
d9cdbb3d 4874
06a2c219 4875 xassert (updated_window && updated_row);
dc6f92b8 4876 BLOCK_INPUT;
06a2c219
GM
4877
4878 /* Write glyphs. */
dc6f92b8 4879
06a2c219
GM
4880 hpos = start - updated_row->glyphs[updated_area];
4881 x = x_draw_glyphs (updated_window, output_cursor.x,
4882 updated_row, updated_area,
4883 hpos, hpos + len,
4884 (updated_row->inverse_p
4885 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 4886 &real_start, &real_end, 0);
b30ec466 4887
06a2c219
GM
4888 /* If we drew over the cursor, note that it is not visible any more. */
4889 note_overwritten_text_cursor (updated_window, real_start,
4890 real_end - real_start);
dc6f92b8
JB
4891
4892 UNBLOCK_INPUT;
06a2c219
GM
4893
4894 /* Advance the output cursor. */
4895 output_cursor.hpos += len;
4896 output_cursor.x = x;
dc6f92b8
JB
4897}
4898
0cdd0c9f 4899
06a2c219 4900/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4901
06a2c219
GM
4902static void
4903x_insert_glyphs (start, len)
4904 struct glyph *start;
4905 register int len;
4906{
4907 struct frame *f;
4908 struct window *w;
4909 int line_height, shift_by_width, shifted_region_width;
4910 struct glyph_row *row;
4911 struct glyph *glyph;
4912 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4913
06a2c219 4914 xassert (updated_window && updated_row);
0cdd0c9f 4915 BLOCK_INPUT;
06a2c219
GM
4916 w = updated_window;
4917 f = XFRAME (WINDOW_FRAME (w));
4918
4919 /* Get the height of the line we are in. */
4920 row = updated_row;
4921 line_height = row->height;
4922
4923 /* Get the width of the glyphs to insert. */
4924 shift_by_width = 0;
4925 for (glyph = start; glyph < start + len; ++glyph)
4926 shift_by_width += glyph->pixel_width;
4927
4928 /* Get the width of the region to shift right. */
4929 shifted_region_width = (window_box_width (w, updated_area)
4930 - output_cursor.x
4931 - shift_by_width);
4932
4933 /* Shift right. */
4934 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4935 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4936 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4937 f->output_data.x->normal_gc,
4938 frame_x, frame_y,
4939 shifted_region_width, line_height,
4940 frame_x + shift_by_width, frame_y);
4941
4942 /* Write the glyphs. */
4943 hpos = start - row->glyphs[updated_area];
4944 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 4945 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
4946 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4947
4948 /* Advance the output cursor. */
4949 output_cursor.hpos += len;
4950 output_cursor.x += shift_by_width;
0cdd0c9f
RS
4951 UNBLOCK_INPUT;
4952}
0cdd0c9f 4953
0cdd0c9f 4954
06a2c219
GM
4955/* Delete N glyphs at the nominal cursor position. Not implemented
4956 for X frames. */
c83febd7
RS
4957
4958static void
06a2c219
GM
4959x_delete_glyphs (n)
4960 register int n;
c83febd7 4961{
06a2c219 4962 abort ();
c83febd7
RS
4963}
4964
0cdd0c9f 4965
06a2c219
GM
4966/* Erase the current text line from the nominal cursor position
4967 (inclusive) to pixel column TO_X (exclusive). The idea is that
4968 everything from TO_X onward is already erased.
4969
4970 TO_X is a pixel position relative to updated_area of
4971 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 4972
06a2c219
GM
4973static void
4974x_clear_end_of_line (to_x)
4975 int to_x;
4976{
4977 struct frame *f;
4978 struct window *w = updated_window;
4979 int max_x, min_y, max_y;
4980 int from_x, from_y, to_y;
4981
4982 xassert (updated_window && updated_row);
4983 f = XFRAME (w->frame);
4984
4985 if (updated_row->full_width_p)
4986 {
4987 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4988 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4989 && !w->pseudo_window_p)
4990 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 4991 }
06a2c219
GM
4992 else
4993 max_x = window_box_width (w, updated_area);
4994 max_y = window_text_bottom_y (w);
dc6f92b8 4995
06a2c219
GM
4996 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4997 of window. For TO_X > 0, truncate to end of drawing area. */
4998 if (to_x == 0)
4999 return;
5000 else if (to_x < 0)
5001 to_x = max_x;
5002 else
5003 to_x = min (to_x, max_x);
dbc4e1c1 5004
06a2c219
GM
5005 to_y = min (max_y, output_cursor.y + updated_row->height);
5006
5007 /* Notice if the cursor will be cleared by this operation. */
5008 if (!updated_row->full_width_p)
5009 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 5010
06a2c219
GM
5011 from_x = output_cursor.x;
5012
5013 /* Translate to frame coordinates. */
5014 if (updated_row->full_width_p)
5015 {
5016 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5017 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5018 }
0cdd0c9f
RS
5019 else
5020 {
06a2c219
GM
5021 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5022 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5023 }
5024
045dee35 5025 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
5026 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5027 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5028
5029 /* Prevent inadvertently clearing to end of the X window. */
5030 if (to_x > from_x && to_y > from_y)
5031 {
5032 BLOCK_INPUT;
5033 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5034 from_x, from_y, to_x - from_x, to_y - from_y,
5035 False);
5036 UNBLOCK_INPUT;
0cdd0c9f 5037 }
0cdd0c9f 5038}
dbc4e1c1 5039
0cdd0c9f 5040
06a2c219 5041/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5042 frame. Otherwise clear the selected frame. */
06a2c219
GM
5043
5044static void
5045x_clear_frame ()
0cdd0c9f 5046{
06a2c219 5047 struct frame *f;
0cdd0c9f 5048
06a2c219
GM
5049 if (updating_frame)
5050 f = updating_frame;
0cdd0c9f 5051 else
b86bd3dd 5052 f = SELECTED_FRAME ();
58769bee 5053
06a2c219
GM
5054 /* Clearing the frame will erase any cursor, so mark them all as no
5055 longer visible. */
5056 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5057 output_cursor.hpos = output_cursor.vpos = 0;
5058 output_cursor.x = -1;
5059
5060 /* We don't set the output cursor here because there will always
5061 follow an explicit cursor_to. */
5062 BLOCK_INPUT;
5063 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5064
5065 /* We have to clear the scroll bars, too. If we have changed
5066 colors or something like that, then they should be notified. */
5067 x_scroll_bar_clear (f);
0cdd0c9f 5068
06a2c219
GM
5069 XFlush (FRAME_X_DISPLAY (f));
5070 UNBLOCK_INPUT;
dc6f92b8 5071}
06a2c219
GM
5072
5073
dc6f92b8 5074\f
dbc4e1c1
JB
5075/* Invert the middle quarter of the frame for .15 sec. */
5076
06a2c219
GM
5077/* We use the select system call to do the waiting, so we have to make
5078 sure it's available. If it isn't, we just won't do visual bells. */
5079
dbc4e1c1
JB
5080#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5081
06a2c219
GM
5082
5083/* Subtract the `struct timeval' values X and Y, storing the result in
5084 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5085
5086static int
5087timeval_subtract (result, x, y)
5088 struct timeval *result, x, y;
5089{
06a2c219
GM
5090 /* Perform the carry for the later subtraction by updating y. This
5091 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5092 if (x.tv_usec < y.tv_usec)
5093 {
5094 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5095 y.tv_usec -= 1000000 * nsec;
5096 y.tv_sec += nsec;
5097 }
06a2c219 5098
dbc4e1c1
JB
5099 if (x.tv_usec - y.tv_usec > 1000000)
5100 {
5101 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5102 y.tv_usec += 1000000 * nsec;
5103 y.tv_sec -= nsec;
5104 }
5105
06a2c219
GM
5106 /* Compute the time remaining to wait. tv_usec is certainly
5107 positive. */
dbc4e1c1
JB
5108 result->tv_sec = x.tv_sec - y.tv_sec;
5109 result->tv_usec = x.tv_usec - y.tv_usec;
5110
06a2c219
GM
5111 /* Return indication of whether the result should be considered
5112 negative. */
dbc4e1c1
JB
5113 return x.tv_sec < y.tv_sec;
5114}
dc6f92b8 5115
dfcf069d 5116void
f676886a
JB
5117XTflash (f)
5118 struct frame *f;
dc6f92b8 5119{
dbc4e1c1 5120 BLOCK_INPUT;
dc6f92b8 5121
dbc4e1c1
JB
5122 {
5123 GC gc;
dc6f92b8 5124
06a2c219
GM
5125 /* Create a GC that will use the GXxor function to flip foreground
5126 pixels into background pixels. */
dbc4e1c1
JB
5127 {
5128 XGCValues values;
dc6f92b8 5129
dbc4e1c1 5130 values.function = GXxor;
7556890b
RS
5131 values.foreground = (f->output_data.x->foreground_pixel
5132 ^ f->output_data.x->background_pixel);
58769bee 5133
334208b7 5134 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5135 GCFunction | GCForeground, &values);
5136 }
dc6f92b8 5137
dbc4e1c1 5138 {
e84e14c3
RS
5139 /* Get the height not including a menu bar widget. */
5140 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5141 /* Height of each line to flash. */
5142 int flash_height = FRAME_LINE_HEIGHT (f);
5143 /* These will be the left and right margins of the rectangles. */
5144 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5145 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5146
5147 int width;
5148
5149 /* Don't flash the area between a scroll bar and the frame
5150 edge it is next to. */
5151 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5152 {
5153 case vertical_scroll_bar_left:
5154 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5155 break;
5156
5157 case vertical_scroll_bar_right:
5158 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5159 break;
06a2c219
GM
5160
5161 default:
5162 break;
e84e14c3
RS
5163 }
5164
5165 width = flash_right - flash_left;
5166
5167 /* If window is tall, flash top and bottom line. */
5168 if (height > 3 * FRAME_LINE_HEIGHT (f))
5169 {
5170 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5171 flash_left,
5172 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5173 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5174 width, flash_height);
5175 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5176 flash_left,
5177 (height - flash_height
5178 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5179 width, flash_height);
5180 }
5181 else
5182 /* If it is short, flash it all. */
5183 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5184 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5185 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5186
06a2c219 5187 x_flush (f);
dc6f92b8 5188
dbc4e1c1 5189 {
06a2c219 5190 struct timeval wakeup;
dc6f92b8 5191
66c30ea1 5192 EMACS_GET_TIME (wakeup);
dc6f92b8 5193
dbc4e1c1
JB
5194 /* Compute time to wait until, propagating carry from usecs. */
5195 wakeup.tv_usec += 150000;
5196 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5197 wakeup.tv_usec %= 1000000;
5198
5199 /* Keep waiting until past the time wakeup. */
5200 while (1)
5201 {
5202 struct timeval timeout;
5203
66c30ea1 5204 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5205
5206 /* In effect, timeout = wakeup - timeout.
5207 Break if result would be negative. */
5208 if (timeval_subtract (&timeout, wakeup, timeout))
5209 break;
5210
5211 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5212 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5213 }
5214 }
58769bee 5215
e84e14c3
RS
5216 /* If window is tall, flash top and bottom line. */
5217 if (height > 3 * FRAME_LINE_HEIGHT (f))
5218 {
5219 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5220 flash_left,
5221 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5222 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5223 width, flash_height);
5224 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5225 flash_left,
5226 (height - flash_height
5227 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5228 width, flash_height);
5229 }
5230 else
5231 /* If it is short, flash it all. */
5232 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5233 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5234 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5235
334208b7 5236 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5237 x_flush (f);
dc6f92b8 5238 }
dbc4e1c1
JB
5239 }
5240
5241 UNBLOCK_INPUT;
dc6f92b8
JB
5242}
5243
06a2c219 5244#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5245
5246
dc6f92b8
JB
5247/* Make audible bell. */
5248
dfcf069d 5249void
dc6f92b8
JB
5250XTring_bell ()
5251{
b86bd3dd
GM
5252 struct frame *f = SELECTED_FRAME ();
5253
5254 if (FRAME_X_DISPLAY (f))
5255 {
dbc4e1c1 5256#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5257 if (visible_bell)
5258 XTflash (f);
5259 else
dbc4e1c1 5260#endif
b86bd3dd
GM
5261 {
5262 BLOCK_INPUT;
5263 XBell (FRAME_X_DISPLAY (f), 0);
5264 XFlush (FRAME_X_DISPLAY (f));
5265 UNBLOCK_INPUT;
5266 }
dc6f92b8
JB
5267 }
5268}
06a2c219 5269
dc6f92b8 5270\f
06a2c219
GM
5271/* Specify how many text lines, from the top of the window,
5272 should be affected by insert-lines and delete-lines operations.
5273 This, and those operations, are used only within an update
5274 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5275
dfcf069d 5276static void
06a2c219
GM
5277XTset_terminal_window (n)
5278 register int n;
dc6f92b8 5279{
06a2c219 5280 /* This function intentionally left blank. */
dc6f92b8
JB
5281}
5282
06a2c219
GM
5283
5284\f
5285/***********************************************************************
5286 Line Dance
5287 ***********************************************************************/
5288
5289/* Perform an insert-lines or delete-lines operation, inserting N
5290 lines or deleting -N lines at vertical position VPOS. */
5291
dfcf069d 5292static void
06a2c219
GM
5293x_ins_del_lines (vpos, n)
5294 int vpos, n;
dc6f92b8
JB
5295{
5296 abort ();
5297}
06a2c219
GM
5298
5299
5300/* Scroll part of the display as described by RUN. */
dc6f92b8 5301
dfcf069d 5302static void
06a2c219
GM
5303x_scroll_run (w, run)
5304 struct window *w;
5305 struct run *run;
dc6f92b8 5306{
06a2c219
GM
5307 struct frame *f = XFRAME (w->frame);
5308 int x, y, width, height, from_y, to_y, bottom_y;
5309
5310 /* Get frame-relative bounding box of the text display area of W,
5311 without mode lines. Include in this box the flags areas to the
5312 left and right of W. */
5313 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5314 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5315 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5316
5317 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5318 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5319 bottom_y = y + height;
dc6f92b8 5320
06a2c219
GM
5321 if (to_y < from_y)
5322 {
5323 /* Scrolling up. Make sure we don't copy part of the mode
5324 line at the bottom. */
5325 if (from_y + run->height > bottom_y)
5326 height = bottom_y - from_y;
5327 else
5328 height = run->height;
5329 }
dc6f92b8 5330 else
06a2c219
GM
5331 {
5332 /* Scolling down. Make sure we don't copy over the mode line.
5333 at the bottom. */
5334 if (to_y + run->height > bottom_y)
5335 height = bottom_y - to_y;
5336 else
5337 height = run->height;
5338 }
7a13e894 5339
06a2c219
GM
5340 BLOCK_INPUT;
5341
5342 /* Cursor off. Will be switched on again in x_update_window_end. */
5343 updated_window = w;
5344 x_clear_cursor (w);
5345
5346 XCopyArea (FRAME_X_DISPLAY (f),
5347 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5348 f->output_data.x->normal_gc,
5349 x, from_y,
5350 width, height,
5351 x, to_y);
5352
5353 UNBLOCK_INPUT;
5354}
dc6f92b8 5355
dc6f92b8 5356
06a2c219
GM
5357\f
5358/***********************************************************************
5359 Exposure Events
5360 ***********************************************************************/
5361
5362/* Redisplay an exposed area of frame F. X and Y are the upper-left
5363 corner of the exposed rectangle. W and H are width and height of
5364 the exposed area. All are pixel values. W or H zero means redraw
5365 the entire frame. */
dc6f92b8 5366
06a2c219
GM
5367static void
5368expose_frame (f, x, y, w, h)
5369 struct frame *f;
5370 int x, y, w, h;
dc6f92b8 5371{
06a2c219 5372 XRectangle r;
dc6f92b8 5373
06a2c219 5374 TRACE ((stderr, "expose_frame "));
dc6f92b8 5375
06a2c219
GM
5376 /* No need to redraw if frame will be redrawn soon. */
5377 if (FRAME_GARBAGED_P (f))
dc6f92b8 5378 {
06a2c219
GM
5379 TRACE ((stderr, " garbaged\n"));
5380 return;
5381 }
5382
5383 /* If basic faces haven't been realized yet, there is no point in
5384 trying to redraw anything. This can happen when we get an expose
5385 event while Emacs is starting, e.g. by moving another window. */
5386 if (FRAME_FACE_CACHE (f) == NULL
5387 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5388 {
5389 TRACE ((stderr, " no faces\n"));
5390 return;
58769bee 5391 }
06a2c219
GM
5392
5393 if (w == 0 || h == 0)
58769bee 5394 {
06a2c219
GM
5395 r.x = r.y = 0;
5396 r.width = CANON_X_UNIT (f) * f->width;
5397 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5398 }
5399 else
5400 {
06a2c219
GM
5401 r.x = x;
5402 r.y = y;
5403 r.width = w;
5404 r.height = h;
5405 }
5406
5407 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5408 expose_window_tree (XWINDOW (f->root_window), &r);
5409
9ea173e8 5410 if (WINDOWP (f->tool_bar_window))
06a2c219 5411 {
9ea173e8 5412 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5413 XRectangle window_rect;
5414 XRectangle intersection_rect;
5415 int window_x, window_y, window_width, window_height;
5416
5417
5418 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5419 window_rect.x = window_x;
5420 window_rect.y = window_y;
5421 window_rect.width = window_width;
5422 window_rect.height = window_height;
5423
5424 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5425 expose_window (w, &intersection_rect);
5426 }
5427
5428#ifndef USE_X_TOOLKIT
5429 if (WINDOWP (f->menu_bar_window))
5430 {
5431 struct window *w = XWINDOW (f->menu_bar_window);
5432 XRectangle window_rect;
5433 XRectangle intersection_rect;
5434 int window_x, window_y, window_width, window_height;
5435
5436
5437 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5438 window_rect.x = window_x;
5439 window_rect.y = window_y;
5440 window_rect.width = window_width;
5441 window_rect.height = window_height;
5442
5443 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5444 expose_window (w, &intersection_rect);
dc6f92b8 5445 }
06a2c219 5446#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5447}
5448
06a2c219
GM
5449
5450/* Redraw (parts) of all windows in the window tree rooted at W that
5451 intersect R. R contains frame pixel coordinates. */
5452
58769bee 5453static void
06a2c219
GM
5454expose_window_tree (w, r)
5455 struct window *w;
5456 XRectangle *r;
dc6f92b8 5457{
06a2c219
GM
5458 while (w)
5459 {
5460 if (!NILP (w->hchild))
5461 expose_window_tree (XWINDOW (w->hchild), r);
5462 else if (!NILP (w->vchild))
5463 expose_window_tree (XWINDOW (w->vchild), r);
5464 else
5465 {
5466 XRectangle window_rect;
5467 XRectangle intersection_rect;
5468 struct frame *f = XFRAME (w->frame);
5469 int window_x, window_y, window_width, window_height;
5470
5471 /* Frame-relative pixel rectangle of W. */
5472 window_box (w, -1, &window_x, &window_y, &window_width,
5473 &window_height);
5474 window_rect.x
5475 = (window_x
110859fc 5476 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5477 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5478 window_rect.y = window_y;
5479 window_rect.width
5480 = (window_width
110859fc 5481 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5482 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5483 window_rect.height
5484 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5485
5486 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5487 expose_window (w, &intersection_rect);
5488 }
58769bee 5489
06a2c219
GM
5490 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5491 }
5492}
58769bee 5493
dc6f92b8 5494
06a2c219
GM
5495/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5496 which intersects rectangle R. R is in window-relative coordinates. */
5497
5498static void
5499expose_area (w, row, r, area)
5500 struct window *w;
5501 struct glyph_row *row;
5502 XRectangle *r;
5503 enum glyph_row_area area;
5504{
5505 int x;
5506 struct glyph *first = row->glyphs[area];
5507 struct glyph *end = row->glyphs[area] + row->used[area];
5508 struct glyph *last;
5509 int first_x;
5510
5511 /* Set x to the window-relative start position for drawing glyphs of
5512 AREA. The first glyph of the text area can be partially visible.
5513 The first glyphs of other areas cannot. */
5514 if (area == LEFT_MARGIN_AREA)
5515 x = 0;
5516 else if (area == TEXT_AREA)
5517 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5518 else
5519 x = (window_box_width (w, LEFT_MARGIN_AREA)
5520 + window_box_width (w, TEXT_AREA));
5521
6fb13182
GM
5522 if (area == TEXT_AREA && row->fill_line_p)
5523 /* If row extends face to end of line write the whole line. */
5524 x_draw_glyphs (w, x, row, area,
5525 0, row->used[area],
06a2c219 5526 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5527 NULL, NULL, 0);
6fb13182
GM
5528 else
5529 {
5530 /* Find the first glyph that must be redrawn. */
5531 while (first < end
5532 && x + first->pixel_width < r->x)
5533 {
5534 x += first->pixel_width;
5535 ++first;
5536 }
5537
5538 /* Find the last one. */
5539 last = first;
5540 first_x = x;
5541 while (last < end
5542 && x < r->x + r->width)
5543 {
5544 x += last->pixel_width;
5545 ++last;
5546 }
5547
5548 /* Repaint. */
5549 if (last > first)
5550 x_draw_glyphs (w, first_x, row, area,
5551 first - row->glyphs[area],
5552 last - row->glyphs[area],
5553 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5554 NULL, NULL, 0);
5555 }
06a2c219
GM
5556}
5557
58769bee 5558
06a2c219
GM
5559/* Redraw the parts of the glyph row ROW on window W intersecting
5560 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5561
06a2c219
GM
5562static void
5563expose_line (w, row, r)
5564 struct window *w;
5565 struct glyph_row *row;
5566 XRectangle *r;
5567{
5568 xassert (row->enabled_p);
5569
5570 if (row->mode_line_p || w->pseudo_window_p)
5571 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5572 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5573 NULL, NULL, 0);
06a2c219
GM
5574 else
5575 {
5576 if (row->used[LEFT_MARGIN_AREA])
5577 expose_area (w, row, r, LEFT_MARGIN_AREA);
5578 if (row->used[TEXT_AREA])
5579 expose_area (w, row, r, TEXT_AREA);
5580 if (row->used[RIGHT_MARGIN_AREA])
5581 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5582 x_draw_row_bitmaps (w, row);
5583 }
5584}
dc6f92b8 5585
58769bee 5586
06a2c219
GM
5587/* Return non-zero if W's cursor intersects rectangle R. */
5588
5589static int
5590x_phys_cursor_in_rect_p (w, r)
5591 struct window *w;
5592 XRectangle *r;
5593{
5594 XRectangle cr, result;
5595 struct glyph *cursor_glyph;
5596
5597 cursor_glyph = get_phys_cursor_glyph (w);
5598 if (cursor_glyph)
5599 {
5600 cr.x = w->phys_cursor.x;
5601 cr.y = w->phys_cursor.y;
5602 cr.width = cursor_glyph->pixel_width;
5603 cr.height = w->phys_cursor_height;
5604 return x_intersect_rectangles (&cr, r, &result);
5605 }
5606 else
5607 return 0;
dc6f92b8 5608}
dc6f92b8 5609
06a2c219
GM
5610
5611/* Redraw a rectangle of window W. R is a rectangle in window
5612 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5613
5614static void
06a2c219
GM
5615expose_window (w, r)
5616 struct window *w;
5617 XRectangle *r;
dc6f92b8 5618{
06a2c219
GM
5619 struct glyph_row *row;
5620 int y;
5621 int yb = window_text_bottom_y (w);
5622 int cursor_cleared_p;
dc6f92b8 5623
80c32bcc
GM
5624 /* If window is not yet fully initialized, do nothing. This can
5625 happen when toolkit scroll bars are used and a window is split.
5626 Reconfiguring the scroll bar will generate an expose for a newly
5627 created window. */
5628 if (w->current_matrix == NULL)
5629 return;
5630
06a2c219
GM
5631 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5632 r->x, r->y, r->width, r->height));
dc6f92b8 5633
06a2c219
GM
5634 /* Convert to window coordinates. */
5635 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5636 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5637
06a2c219
GM
5638 /* Turn off the cursor. */
5639 if (!w->pseudo_window_p
5640 && x_phys_cursor_in_rect_p (w, r))
5641 {
5642 x_clear_cursor (w);
5643 cursor_cleared_p = 1;
5644 }
5645 else
5646 cursor_cleared_p = 0;
5647
5648 /* Find the first row intersecting the rectangle R. */
5649 row = w->current_matrix->rows;
5650 y = 0;
5651 while (row->enabled_p
5652 && y < yb
5653 && y + row->height < r->y)
5654 {
5655 y += row->height;
5656 ++row;
5657 }
5658
dc6f92b8 5659 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5660 while (row->enabled_p
5661 && y < yb
5662 && y < r->y + r->height)
5663 {
5664 expose_line (w, row, r);
5665 y += row->height;
5666 ++row;
5667 }
5668
5669 /* Display the mode line if there is one. */
5670 if (WINDOW_WANTS_MODELINE_P (w)
5671 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5672 row->enabled_p)
5673 && row->y < r->y + r->height)
5674 expose_line (w, row, r);
dc6f92b8 5675
06a2c219 5676 if (!w->pseudo_window_p)
dc6f92b8 5677 {
06a2c219
GM
5678 /* Draw border between windows. */
5679 x_draw_vertical_border (w);
5680
5681 /* Turn the cursor on again. */
5682 if (cursor_cleared_p)
5683 x_update_window_cursor (w, 1);
5684 }
5685}
dc6f92b8 5686
dc6f92b8 5687
06a2c219
GM
5688/* Determine the intersection of two rectangles R1 and R2. Return
5689 the intersection in *RESULT. Value is non-zero if RESULT is not
5690 empty. */
5691
5692static int
5693x_intersect_rectangles (r1, r2, result)
5694 XRectangle *r1, *r2, *result;
5695{
5696 XRectangle *left, *right;
5697 XRectangle *upper, *lower;
5698 int intersection_p = 0;
5699
5700 /* Rearrange so that R1 is the left-most rectangle. */
5701 if (r1->x < r2->x)
5702 left = r1, right = r2;
5703 else
5704 left = r2, right = r1;
5705
5706 /* X0 of the intersection is right.x0, if this is inside R1,
5707 otherwise there is no intersection. */
5708 if (right->x <= left->x + left->width)
5709 {
5710 result->x = right->x;
5711
5712 /* The right end of the intersection is the minimum of the
5713 the right ends of left and right. */
5714 result->width = (min (left->x + left->width, right->x + right->width)
5715 - result->x);
5716
5717 /* Same game for Y. */
5718 if (r1->y < r2->y)
5719 upper = r1, lower = r2;
5720 else
5721 upper = r2, lower = r1;
5722
5723 /* The upper end of the intersection is lower.y0, if this is inside
5724 of upper. Otherwise, there is no intersection. */
5725 if (lower->y <= upper->y + upper->height)
dc43ef94 5726 {
06a2c219
GM
5727 result->y = lower->y;
5728
5729 /* The lower end of the intersection is the minimum of the lower
5730 ends of upper and lower. */
5731 result->height = (min (lower->y + lower->height,
5732 upper->y + upper->height)
5733 - result->y);
5734 intersection_p = 1;
dc43ef94 5735 }
dc6f92b8
JB
5736 }
5737
06a2c219 5738 return intersection_p;
dc6f92b8 5739}
06a2c219
GM
5740
5741
5742
5743
dc6f92b8 5744\f
dc6f92b8 5745static void
334208b7
RS
5746frame_highlight (f)
5747 struct frame *f;
dc6f92b8 5748{
b3e1e05c
JB
5749 /* We used to only do this if Vx_no_window_manager was non-nil, but
5750 the ICCCM (section 4.1.6) says that the window's border pixmap
5751 and border pixel are window attributes which are "private to the
5752 client", so we can always change it to whatever we want. */
5753 BLOCK_INPUT;
334208b7 5754 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5755 f->output_data.x->border_pixel);
b3e1e05c 5756 UNBLOCK_INPUT;
5d46f928 5757 x_update_cursor (f, 1);
dc6f92b8
JB
5758}
5759
5760static void
334208b7
RS
5761frame_unhighlight (f)
5762 struct frame *f;
dc6f92b8 5763{
b3e1e05c
JB
5764 /* We used to only do this if Vx_no_window_manager was non-nil, but
5765 the ICCCM (section 4.1.6) says that the window's border pixmap
5766 and border pixel are window attributes which are "private to the
5767 client", so we can always change it to whatever we want. */
5768 BLOCK_INPUT;
334208b7 5769 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5770 f->output_data.x->border_tile);
b3e1e05c 5771 UNBLOCK_INPUT;
5d46f928 5772 x_update_cursor (f, 1);
dc6f92b8 5773}
dc6f92b8 5774
f676886a
JB
5775/* The focus has changed. Update the frames as necessary to reflect
5776 the new situation. Note that we can't change the selected frame
c5acd733 5777 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5778 Each event gets marked with the frame in which it occurred, so the
c5acd733 5779 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5780
6d4238f3 5781static void
0f941935
KH
5782x_new_focus_frame (dpyinfo, frame)
5783 struct x_display_info *dpyinfo;
f676886a 5784 struct frame *frame;
dc6f92b8 5785{
0f941935 5786 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5787
0f941935 5788 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5789 {
58769bee 5790 /* Set this before calling other routines, so that they see
f676886a 5791 the correct value of x_focus_frame. */
0f941935 5792 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5793
5794 if (old_focus && old_focus->auto_lower)
f676886a 5795 x_lower_frame (old_focus);
dc6f92b8
JB
5796
5797#if 0
f676886a 5798 selected_frame = frame;
e0c1aef2
KH
5799 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5800 selected_frame);
f676886a
JB
5801 Fselect_window (selected_frame->selected_window);
5802 choose_minibuf_frame ();
c118dd06 5803#endif /* ! 0 */
dc6f92b8 5804
0f941935
KH
5805 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5806 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5807 else
5808 pending_autoraise_frame = 0;
6d4238f3 5809 }
dc6f92b8 5810
0f941935 5811 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5812}
5813
37c2c98b
RS
5814/* Handle an event saying the mouse has moved out of an Emacs frame. */
5815
5816void
0f941935
KH
5817x_mouse_leave (dpyinfo)
5818 struct x_display_info *dpyinfo;
37c2c98b 5819{
0f941935 5820 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5821}
6d4238f3 5822
f451eb13
JB
5823/* The focus has changed, or we have redirected a frame's focus to
5824 another frame (this happens when a frame uses a surrogate
06a2c219 5825 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5826
5827 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5828 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5829 the appropriate X display info. */
06a2c219 5830
6d4238f3 5831static void
0f941935
KH
5832XTframe_rehighlight (frame)
5833 struct frame *frame;
6d4238f3 5834{
0f941935
KH
5835 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5836}
6d4238f3 5837
0f941935
KH
5838static void
5839x_frame_rehighlight (dpyinfo)
5840 struct x_display_info *dpyinfo;
5841{
5842 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5843
5844 if (dpyinfo->x_focus_frame)
6d4238f3 5845 {
0f941935
KH
5846 dpyinfo->x_highlight_frame
5847 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5848 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5849 : dpyinfo->x_focus_frame);
5850 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5851 {
0f941935
KH
5852 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5853 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5854 }
dc6f92b8 5855 }
6d4238f3 5856 else
0f941935 5857 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5858
0f941935 5859 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5860 {
5861 if (old_highlight)
f676886a 5862 frame_unhighlight (old_highlight);
0f941935
KH
5863 if (dpyinfo->x_highlight_frame)
5864 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5865 }
dc6f92b8 5866}
06a2c219
GM
5867
5868
dc6f92b8 5869\f
06a2c219 5870/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5871
28430d3c
JB
5872/* Initialize mode_switch_bit and modifier_meaning. */
5873static void
334208b7
RS
5874x_find_modifier_meanings (dpyinfo)
5875 struct x_display_info *dpyinfo;
28430d3c 5876{
f689eb05 5877 int min_code, max_code;
28430d3c
JB
5878 KeySym *syms;
5879 int syms_per_code;
5880 XModifierKeymap *mods;
5881
334208b7
RS
5882 dpyinfo->meta_mod_mask = 0;
5883 dpyinfo->shift_lock_mask = 0;
5884 dpyinfo->alt_mod_mask = 0;
5885 dpyinfo->super_mod_mask = 0;
5886 dpyinfo->hyper_mod_mask = 0;
58769bee 5887
9658a521 5888#ifdef HAVE_X11R4
334208b7 5889 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5890#else
4a60f8c5
RS
5891 min_code = dpyinfo->display->min_keycode;
5892 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5893#endif
5894
334208b7 5895 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5896 min_code, max_code - min_code + 1,
5897 &syms_per_code);
334208b7 5898 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5899
58769bee 5900 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5901 Alt keysyms are on. */
28430d3c 5902 {
06a2c219 5903 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5904
5905 for (row = 3; row < 8; row++)
5906 for (col = 0; col < mods->max_keypermod; col++)
5907 {
0299d313
RS
5908 KeyCode code
5909 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5910
af92970c
KH
5911 /* Zeroes are used for filler. Skip them. */
5912 if (code == 0)
5913 continue;
5914
28430d3c
JB
5915 /* Are any of this keycode's keysyms a meta key? */
5916 {
5917 int code_col;
5918
5919 for (code_col = 0; code_col < syms_per_code; code_col++)
5920 {
f689eb05 5921 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5922
f689eb05 5923 switch (sym)
28430d3c 5924 {
f689eb05
JB
5925 case XK_Meta_L:
5926 case XK_Meta_R:
334208b7 5927 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5928 break;
f689eb05
JB
5929
5930 case XK_Alt_L:
5931 case XK_Alt_R:
334208b7 5932 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5933 break;
5934
5935 case XK_Hyper_L:
5936 case XK_Hyper_R:
334208b7 5937 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5938 break;
5939
5940 case XK_Super_L:
5941 case XK_Super_R:
334208b7 5942 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5943 break;
11edeb03
JB
5944
5945 case XK_Shift_Lock:
5946 /* Ignore this if it's not on the lock modifier. */
5947 if ((1 << row) == LockMask)
334208b7 5948 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5949 break;
28430d3c
JB
5950 }
5951 }
5952 }
5953 }
5954 }
5955
f689eb05 5956 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 5957 if (! dpyinfo->meta_mod_mask)
a3c44b14 5958 {
334208b7
RS
5959 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5960 dpyinfo->alt_mod_mask = 0;
a3c44b14 5961 }
f689eb05 5962
148c4b70
RS
5963 /* If some keys are both alt and meta,
5964 make them just meta, not alt. */
334208b7 5965 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 5966 {
334208b7 5967 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 5968 }
58769bee 5969
28430d3c 5970 XFree ((char *) syms);
f689eb05 5971 XFreeModifiermap (mods);
28430d3c
JB
5972}
5973
dfeccd2d
JB
5974/* Convert between the modifier bits X uses and the modifier bits
5975 Emacs uses. */
06a2c219 5976
7c5283e4 5977static unsigned int
334208b7
RS
5978x_x_to_emacs_modifiers (dpyinfo, state)
5979 struct x_display_info *dpyinfo;
dc6f92b8
JB
5980 unsigned int state;
5981{
334208b7
RS
5982 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5983 | ((state & ControlMask) ? ctrl_modifier : 0)
5984 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5985 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5986 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5987 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
5988}
5989
dfeccd2d 5990static unsigned int
334208b7
RS
5991x_emacs_to_x_modifiers (dpyinfo, state)
5992 struct x_display_info *dpyinfo;
dfeccd2d
JB
5993 unsigned int state;
5994{
334208b7
RS
5995 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5996 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5997 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5998 | ((state & shift_modifier) ? ShiftMask : 0)
5999 | ((state & ctrl_modifier) ? ControlMask : 0)
6000 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 6001}
d047c4eb
KH
6002
6003/* Convert a keysym to its name. */
6004
6005char *
6006x_get_keysym_name (keysym)
6007 KeySym keysym;
6008{
6009 char *value;
6010
6011 BLOCK_INPUT;
6012 value = XKeysymToString (keysym);
6013 UNBLOCK_INPUT;
6014
6015 return value;
6016}
06a2c219
GM
6017
6018
e4571a43
JB
6019\f
6020/* Mouse clicks and mouse movement. Rah. */
e4571a43 6021
06a2c219
GM
6022/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
6023 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
6024 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
6025 not force the value into range. */
69388238 6026
c8dba240 6027void
69388238 6028pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 6029 FRAME_PTR f;
69388238 6030 register int pix_x, pix_y;
e4571a43
JB
6031 register int *x, *y;
6032 XRectangle *bounds;
69388238 6033 int noclip;
e4571a43 6034{
06a2c219 6035 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6036 even for negative values. */
6037 if (pix_x < 0)
7556890b 6038 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6039 if (pix_y < 0)
7556890b 6040 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6041
e4571a43
JB
6042 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6043 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6044
6045 if (bounds)
6046 {
7556890b
RS
6047 bounds->width = FONT_WIDTH (f->output_data.x->font);
6048 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6049 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6050 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6051 }
6052
69388238
RS
6053 if (!noclip)
6054 {
6055 if (pix_x < 0)
6056 pix_x = 0;
3cbd2e0b
RS
6057 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6058 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6059
6060 if (pix_y < 0)
6061 pix_y = 0;
6062 else if (pix_y > f->height)
6063 pix_y = f->height;
6064 }
e4571a43
JB
6065
6066 *x = pix_x;
6067 *y = pix_y;
6068}
6069
06a2c219
GM
6070
6071/* Given HPOS/VPOS in the current matrix of W, return corresponding
6072 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6073 can't tell the positions because W's display is not up to date,
6074 return 0. */
6075
6076int
6077glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6078 struct window *w;
6079 int hpos, vpos;
6080 int *frame_x, *frame_y;
2b5c9e71 6081{
06a2c219
GM
6082 int success_p;
6083
6084 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6085 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6086
6087 if (display_completed)
6088 {
6089 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6090 struct glyph *glyph = row->glyphs[TEXT_AREA];
6091 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6092
6093 *frame_y = row->y;
6094 *frame_x = row->x;
6095 while (glyph < end)
6096 {
6097 *frame_x += glyph->pixel_width;
6098 ++glyph;
6099 }
6100
6101 success_p = 1;
6102 }
6103 else
6104 {
6105 *frame_y = *frame_x = 0;
6106 success_p = 0;
6107 }
6108
6109 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6110 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6111 return success_p;
2b5c9e71
RS
6112}
6113
06a2c219 6114
dc6f92b8
JB
6115/* Prepare a mouse-event in *RESULT for placement in the input queue.
6116
6117 If the event is a button press, then note that we have grabbed
f451eb13 6118 the mouse. */
dc6f92b8
JB
6119
6120static Lisp_Object
f451eb13 6121construct_mouse_click (result, event, f)
dc6f92b8
JB
6122 struct input_event *result;
6123 XButtonEvent *event;
f676886a 6124 struct frame *f;
dc6f92b8 6125{
f451eb13 6126 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6127 otherwise. */
f451eb13 6128 result->kind = mouse_click;
69388238 6129 result->code = event->button - Button1;
1113d9db 6130 result->timestamp = event->time;
334208b7
RS
6131 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6132 event->state)
f689eb05 6133 | (event->type == ButtonRelease
58769bee 6134 ? up_modifier
f689eb05 6135 : down_modifier));
dc6f92b8 6136
06a2c219
GM
6137 XSETINT (result->x, event->x);
6138 XSETINT (result->y, event->y);
6139 XSETFRAME (result->frame_or_window, f);
6140 return Qnil;
dc6f92b8 6141}
b849c413 6142
06a2c219
GM
6143#if 0 /* This function isn't called. --gerd */
6144
b849c413
RS
6145/* Prepare a menu-event in *RESULT for placement in the input queue. */
6146
6147static Lisp_Object
6148construct_menu_click (result, event, f)
6149 struct input_event *result;
6150 XButtonEvent *event;
6151 struct frame *f;
6152{
6153 /* Make the event type no_event; we'll change that when we decide
6154 otherwise. */
6155 result->kind = mouse_click;
26459b28 6156 result->code = event->button - Button1;
b849c413 6157 result->timestamp = event->time;
334208b7
RS
6158 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6159 event->state)
b849c413 6160 | (event->type == ButtonRelease
58769bee 6161 ? up_modifier
b849c413
RS
6162 : down_modifier));
6163
e0c1aef2
KH
6164 XSETINT (result->x, event->x);
6165 XSETINT (result->y, -1);
6166 XSETFRAME (result->frame_or_window, f);
b849c413 6167}
06a2c219
GM
6168
6169#endif /* 0 */
6170
69388238 6171\f
90e65f07
JB
6172/* Function to report a mouse movement to the mainstream Emacs code.
6173 The input handler calls this.
6174
6175 We have received a mouse movement event, which is given in *event.
6176 If the mouse is over a different glyph than it was last time, tell
6177 the mainstream emacs code by setting mouse_moved. If not, ask for
6178 another motion event, so we can check again the next time it moves. */
b8009dd1 6179
06a2c219
GM
6180static XMotionEvent last_mouse_motion_event;
6181static Lisp_Object last_mouse_motion_frame;
6182
90e65f07 6183static void
12ba150f 6184note_mouse_movement (frame, event)
f676886a 6185 FRAME_PTR frame;
90e65f07 6186 XMotionEvent *event;
90e65f07 6187{
e5d77022 6188 last_mouse_movement_time = event->time;
06a2c219
GM
6189 last_mouse_motion_event = *event;
6190 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6191
27f338af
RS
6192 if (event->window != FRAME_X_WINDOW (frame))
6193 {
39d8bb4d 6194 frame->mouse_moved = 1;
27f338af 6195 last_mouse_scroll_bar = Qnil;
27f338af 6196 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6197 }
6198
90e65f07 6199 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6200 else if (event->x < last_mouse_glyph.x
6201 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6202 || event->y < last_mouse_glyph.y
6203 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6204 {
39d8bb4d 6205 frame->mouse_moved = 1;
ab648270 6206 last_mouse_scroll_bar = Qnil;
b8009dd1 6207 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6208 }
6209}
6210
bf1c0ba1 6211/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6212
06a2c219
GM
6213 int disable_mouse_highlight;
6214
6215
6216\f
6217/************************************************************************
6218 Mouse Face
6219 ************************************************************************/
6220
6221/* Find the glyph under window-relative coordinates X/Y in window W.
6222 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6223 strings. Return in *HPOS and *VPOS the row and column number of
6224 the glyph found. Return in *AREA the glyph area containing X.
6225 Value is a pointer to the glyph found or null if X/Y is not on
6226 text, or we can't tell because W's current matrix is not up to
6227 date. */
6228
6229static struct glyph *
6230x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6231 struct window *w;
6232 int x, y;
6233 int *hpos, *vpos, *area;
6234{
6235 struct glyph *glyph, *end;
3e71d8f2 6236 struct glyph_row *row = NULL;
06a2c219
GM
6237 int x0, i, left_area_width;
6238
6239 /* Find row containing Y. Give up if some row is not enabled. */
6240 for (i = 0; i < w->current_matrix->nrows; ++i)
6241 {
6242 row = MATRIX_ROW (w->current_matrix, i);
6243 if (!row->enabled_p)
6244 return NULL;
6245 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6246 break;
6247 }
6248
6249 *vpos = i;
6250 *hpos = 0;
6251
6252 /* Give up if Y is not in the window. */
6253 if (i == w->current_matrix->nrows)
6254 return NULL;
6255
6256 /* Get the glyph area containing X. */
6257 if (w->pseudo_window_p)
6258 {
6259 *area = TEXT_AREA;
6260 x0 = 0;
6261 }
6262 else
6263 {
6264 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6265 if (x < left_area_width)
6266 {
6267 *area = LEFT_MARGIN_AREA;
6268 x0 = 0;
6269 }
6270 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6271 {
6272 *area = TEXT_AREA;
6273 x0 = row->x + left_area_width;
6274 }
6275 else
6276 {
6277 *area = RIGHT_MARGIN_AREA;
6278 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6279 }
6280 }
6281
6282 /* Find glyph containing X. */
6283 glyph = row->glyphs[*area];
6284 end = glyph + row->used[*area];
6285 while (glyph < end)
6286 {
6287 if (x < x0 + glyph->pixel_width)
6288 {
6289 if (w->pseudo_window_p)
6290 break;
6291 else if (BUFFERP (glyph->object))
6292 break;
6293 }
6294
6295 x0 += glyph->pixel_width;
6296 ++glyph;
6297 }
6298
6299 if (glyph == end)
6300 return NULL;
6301
6302 *hpos = glyph - row->glyphs[*area];
6303 return glyph;
6304}
6305
6306
6307/* Convert frame-relative x/y to coordinates relative to window W.
6308 Takes pseudo-windows into account. */
6309
6310static void
6311frame_to_window_pixel_xy (w, x, y)
6312 struct window *w;
6313 int *x, *y;
6314{
6315 if (w->pseudo_window_p)
6316 {
6317 /* A pseudo-window is always full-width, and starts at the
6318 left edge of the frame, plus a frame border. */
6319 struct frame *f = XFRAME (w->frame);
6320 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6321 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6322 }
6323 else
6324 {
6325 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6326 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6327 }
6328}
6329
6330
6331/* Take proper action when mouse has moved to the mode or top line of
6332 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6333 mode line. X is relative to the start of the text display area of
6334 W, so the width of bitmap areas and scroll bars must be subtracted
6335 to get a position relative to the start of the mode line. */
6336
6337static void
6338note_mode_line_highlight (w, x, mode_line_p)
6339 struct window *w;
6340 int x, mode_line_p;
6341{
6342 struct frame *f = XFRAME (w->frame);
6343 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6344 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6345 struct glyph_row *row;
6346
6347 if (mode_line_p)
6348 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6349 else
045dee35 6350 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6351
6352 if (row->enabled_p)
6353 {
6354 struct glyph *glyph, *end;
6355 Lisp_Object help, map;
6356 int x0;
6357
6358 /* Find the glyph under X. */
6359 glyph = row->glyphs[TEXT_AREA];
6360 end = glyph + row->used[TEXT_AREA];
6361 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6362 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6363 while (glyph < end
6364 && x >= x0 + glyph->pixel_width)
6365 {
6366 x0 += glyph->pixel_width;
6367 ++glyph;
6368 }
6369
6370 if (glyph < end
6371 && STRINGP (glyph->object)
6372 && XSTRING (glyph->object)->intervals
6373 && glyph->charpos >= 0
6374 && glyph->charpos < XSTRING (glyph->object)->size)
6375 {
6376 /* If we're on a string with `help-echo' text property,
6377 arrange for the help to be displayed. This is done by
6378 setting the global variable help_echo to the help string. */
6379 help = Fget_text_property (make_number (glyph->charpos),
6380 Qhelp_echo, glyph->object);
b7e80413 6381 if (!NILP (help))
06a2c219
GM
6382 help_echo = help;
6383
6384 /* Change the mouse pointer according to what is under X/Y. */
6385 map = Fget_text_property (make_number (glyph->charpos),
6386 Qlocal_map, glyph->object);
6387 if (!NILP (Fkeymapp (map)))
6388 cursor = f->output_data.x->nontext_cursor;
6389 }
6390 }
6391
6392 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6393}
6394
6395
6396/* Take proper action when the mouse has moved to position X, Y on
6397 frame F as regards highlighting characters that have mouse-face
6398 properties. Also de-highlighting chars where the mouse was before.
27f338af 6399 X and Y can be negative or out of range. */
b8009dd1
RS
6400
6401static void
6402note_mouse_highlight (f, x, y)
06a2c219 6403 struct frame *f;
c32cdd9a 6404 int x, y;
b8009dd1 6405{
06a2c219
GM
6406 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6407 int portion;
b8009dd1
RS
6408 Lisp_Object window;
6409 struct window *w;
6410
06a2c219
GM
6411 /* When a menu is active, don't highlight because this looks odd. */
6412#ifdef USE_X_TOOLKIT
6413 if (popup_activated ())
6414 return;
6415#endif
6416
04fff9c0
GM
6417 if (disable_mouse_highlight
6418 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6419 return;
6420
06a2c219
GM
6421 dpyinfo->mouse_face_mouse_x = x;
6422 dpyinfo->mouse_face_mouse_y = y;
6423 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6424
06a2c219 6425 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6426 return;
6427
514e4681
RS
6428 if (gc_in_progress)
6429 {
06a2c219 6430 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6431 return;
6432 }
6433
b8009dd1 6434 /* Which window is that in? */
06a2c219 6435 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6436
6437 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6438 if (! EQ (window, dpyinfo->mouse_face_window))
6439 clear_mouse_face (dpyinfo);
6440
6441 /* Not on a window -> return. */
6442 if (!WINDOWP (window))
6443 return;
6444
6445 /* Convert to window-relative pixel coordinates. */
6446 w = XWINDOW (window);
6447 frame_to_window_pixel_xy (w, &x, &y);
6448
9ea173e8 6449 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6450 buffer. */
9ea173e8 6451 if (EQ (window, f->tool_bar_window))
06a2c219 6452 {
9ea173e8 6453 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6454 return;
6455 }
6456
6457 if (portion == 1 || portion == 3)
6458 {
6459 /* Mouse is on the mode or top line. */
6460 note_mode_line_highlight (w, x, portion == 1);
6461 return;
6462 }
6463 else
6464 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6465 f->output_data.x->text_cursor);
b8009dd1 6466
0cdd0c9f
RS
6467 /* Are we in a window whose display is up to date?
6468 And verify the buffer's text has not changed. */
06a2c219
GM
6469 if (/* Within text portion of the window. */
6470 portion == 0
0cdd0c9f 6471 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6472 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6473 && (XFASTINT (w->last_overlay_modified)
6474 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6475 {
06a2c219
GM
6476 int hpos, vpos, pos, i, area;
6477 struct glyph *glyph;
b8009dd1 6478
06a2c219
GM
6479 /* Find the glyph under X/Y. */
6480 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6481
6482 /* Clear mouse face if X/Y not over text. */
6483 if (glyph == NULL
6484 || area != TEXT_AREA
6485 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6486 {
06a2c219
GM
6487 clear_mouse_face (dpyinfo);
6488 return;
6489 }
6490
6491 pos = glyph->charpos;
6492 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6493
6494 /* Check for mouse-face and help-echo. */
6495 {
6496 Lisp_Object mouse_face, overlay, position;
6497 Lisp_Object *overlay_vec;
6498 int len, noverlays;
6499 struct buffer *obuf;
6500 int obegv, ozv;
6501
6502 /* If we get an out-of-range value, return now; avoid an error. */
6503 if (pos > BUF_Z (XBUFFER (w->buffer)))
6504 return;
6505
6506 /* Make the window's buffer temporarily current for
6507 overlays_at and compute_char_face. */
6508 obuf = current_buffer;
6509 current_buffer = XBUFFER (w->buffer);
6510 obegv = BEGV;
6511 ozv = ZV;
6512 BEGV = BEG;
6513 ZV = Z;
6514
6515 /* Is this char mouse-active or does it have help-echo? */
6516 XSETINT (position, pos);
6517
6518 /* Put all the overlays we want in a vector in overlay_vec.
6519 Store the length in len. If there are more than 10, make
6520 enough space for all, and try again. */
6521 len = 10;
6522 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6523 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6524 if (noverlays > len)
6525 {
6526 len = noverlays;
6527 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6528 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6529 }
6530
6531 noverlays = sort_overlays (overlay_vec, noverlays, w);
6532
6533 /* Check mouse-face highlighting. */
6534 if (! (EQ (window, dpyinfo->mouse_face_window)
6535 && vpos >= dpyinfo->mouse_face_beg_row
6536 && vpos <= dpyinfo->mouse_face_end_row
6537 && (vpos > dpyinfo->mouse_face_beg_row
6538 || hpos >= dpyinfo->mouse_face_beg_col)
6539 && (vpos < dpyinfo->mouse_face_end_row
6540 || hpos < dpyinfo->mouse_face_end_col
6541 || dpyinfo->mouse_face_past_end)))
6542 {
6543 /* Clear the display of the old active region, if any. */
6544 clear_mouse_face (dpyinfo);
6545
6546 /* Find the highest priority overlay that has a mouse-face prop. */
6547 overlay = Qnil;
6548 for (i = 0; i < noverlays; i++)
6549 {
6550 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6551 if (!NILP (mouse_face))
6552 {
6553 overlay = overlay_vec[i];
6554 break;
6555 }
6556 }
6557
6558 /* If no overlay applies, get a text property. */
6559 if (NILP (overlay))
6560 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6561
6562 /* Handle the overlay case. */
6563 if (! NILP (overlay))
6564 {
6565 /* Find the range of text around this char that
6566 should be active. */
6567 Lisp_Object before, after;
6568 int ignore;
6569
6570 before = Foverlay_start (overlay);
6571 after = Foverlay_end (overlay);
6572 /* Record this as the current active region. */
6573 fast_find_position (w, XFASTINT (before),
6574 &dpyinfo->mouse_face_beg_col,
6575 &dpyinfo->mouse_face_beg_row,
6576 &dpyinfo->mouse_face_beg_x,
6577 &dpyinfo->mouse_face_beg_y);
6578 dpyinfo->mouse_face_past_end
6579 = !fast_find_position (w, XFASTINT (after),
6580 &dpyinfo->mouse_face_end_col,
6581 &dpyinfo->mouse_face_end_row,
6582 &dpyinfo->mouse_face_end_x,
6583 &dpyinfo->mouse_face_end_y);
6584 dpyinfo->mouse_face_window = window;
6585 dpyinfo->mouse_face_face_id
6586 = face_at_buffer_position (w, pos, 0, 0,
6587 &ignore, pos + 1, 1);
6588
6589 /* Display it as active. */
6590 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6591 }
6592 /* Handle the text property case. */
6593 else if (! NILP (mouse_face))
6594 {
6595 /* Find the range of text around this char that
6596 should be active. */
6597 Lisp_Object before, after, beginning, end;
6598 int ignore;
6599
6600 beginning = Fmarker_position (w->start);
6601 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6602 - XFASTINT (w->window_end_pos)));
6603 before
6604 = Fprevious_single_property_change (make_number (pos + 1),
6605 Qmouse_face,
6606 w->buffer, beginning);
6607 after
6608 = Fnext_single_property_change (position, Qmouse_face,
6609 w->buffer, end);
6610 /* Record this as the current active region. */
6611 fast_find_position (w, XFASTINT (before),
6612 &dpyinfo->mouse_face_beg_col,
6613 &dpyinfo->mouse_face_beg_row,
6614 &dpyinfo->mouse_face_beg_x,
6615 &dpyinfo->mouse_face_beg_y);
6616 dpyinfo->mouse_face_past_end
6617 = !fast_find_position (w, XFASTINT (after),
6618 &dpyinfo->mouse_face_end_col,
6619 &dpyinfo->mouse_face_end_row,
6620 &dpyinfo->mouse_face_end_x,
6621 &dpyinfo->mouse_face_end_y);
6622 dpyinfo->mouse_face_window = window;
6623 dpyinfo->mouse_face_face_id
6624 = face_at_buffer_position (w, pos, 0, 0,
6625 &ignore, pos + 1, 1);
6626
6627 /* Display it as active. */
6628 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6629 }
6630 }
6631
6632 /* Look for a `help-echo' property. */
6633 {
6634 Lisp_Object help;
6635
6636 /* Check overlays first. */
6637 help = Qnil;
b7e80413 6638 for (i = 0; i < noverlays && NILP (help); ++i)
06a2c219
GM
6639 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6640
6641 /* Try text properties. */
b7e80413 6642 if (NILP (help)
06a2c219
GM
6643 && ((STRINGP (glyph->object)
6644 && glyph->charpos >= 0
6645 && glyph->charpos < XSTRING (glyph->object)->size)
6646 || (BUFFERP (glyph->object)
6647 && glyph->charpos >= BEGV
6648 && glyph->charpos < ZV)))
6649 help = Fget_text_property (make_number (glyph->charpos),
6650 Qhelp_echo, glyph->object);
6651
b7e80413 6652 if (!NILP (help))
06a2c219
GM
6653 help_echo = help;
6654 }
6655
6656 BEGV = obegv;
6657 ZV = ozv;
6658 current_buffer = obuf;
6659 }
6660 }
6661}
6662
6663static void
6664redo_mouse_highlight ()
6665{
6666 if (!NILP (last_mouse_motion_frame)
6667 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6668 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6669 last_mouse_motion_event.x,
6670 last_mouse_motion_event.y);
6671}
6672
6673
6674\f
6675/***********************************************************************
9ea173e8 6676 Tool-bars
06a2c219
GM
6677 ***********************************************************************/
6678
9ea173e8
GM
6679static int x_tool_bar_item P_ ((struct frame *, int, int,
6680 struct glyph **, int *, int *, int *));
06a2c219 6681
9ea173e8 6682/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6683 or -1. */
6684
9ea173e8 6685static int last_tool_bar_item;
06a2c219
GM
6686
6687
9ea173e8
GM
6688/* Get information about the tool-bar item at position X/Y on frame F.
6689 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6690 the current matrix of the tool-bar window of F, or NULL if not
6691 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6692 item in F->current_tool_bar_items. Value is
06a2c219 6693
9ea173e8 6694 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6695 0 if X/Y is on the same item that was highlighted before.
6696 1 otherwise. */
6697
6698static int
9ea173e8 6699x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6700 struct frame *f;
6701 int x, y;
6702 struct glyph **glyph;
6703 int *hpos, *vpos, *prop_idx;
6704{
6705 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6706 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6707 int area;
6708
6709 /* Find the glyph under X/Y. */
6710 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6711 if (*glyph == NULL)
6712 return -1;
6713
9ea173e8
GM
6714 /* Get the start of this tool-bar item's properties in
6715 f->current_tool_bar_items. */
6716 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6717 return -1;
6718
6719 /* Is mouse on the highlighted item? */
9ea173e8 6720 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6721 && *vpos >= dpyinfo->mouse_face_beg_row
6722 && *vpos <= dpyinfo->mouse_face_end_row
6723 && (*vpos > dpyinfo->mouse_face_beg_row
6724 || *hpos >= dpyinfo->mouse_face_beg_col)
6725 && (*vpos < dpyinfo->mouse_face_end_row
6726 || *hpos < dpyinfo->mouse_face_end_col
6727 || dpyinfo->mouse_face_past_end))
6728 return 0;
6729
6730 return 1;
6731}
6732
6733
9ea173e8 6734/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6735 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6736 or ButtonRelase. */
6737
6738static void
9ea173e8 6739x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6740 struct frame *f;
6741 XButtonEvent *button_event;
6742{
6743 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6744 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6745 int hpos, vpos, prop_idx;
6746 struct glyph *glyph;
6747 Lisp_Object enabled_p;
6748 int x = button_event->x;
6749 int y = button_event->y;
6750
9ea173e8 6751 /* If not on the highlighted tool-bar item, return. */
06a2c219 6752 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6753 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6754 return;
6755
6756 /* If item is disabled, do nothing. */
9ea173e8
GM
6757 enabled_p = (XVECTOR (f->current_tool_bar_items)
6758 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6759 if (NILP (enabled_p))
6760 return;
6761
6762 if (button_event->type == ButtonPress)
6763 {
6764 /* Show item in pressed state. */
6765 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6766 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6767 last_tool_bar_item = prop_idx;
06a2c219
GM
6768 }
6769 else
6770 {
6771 Lisp_Object key, frame;
6772 struct input_event event;
6773
6774 /* Show item in released state. */
6775 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6776 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6777
9ea173e8
GM
6778 key = (XVECTOR (f->current_tool_bar_items)
6779 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
6780
6781 XSETFRAME (frame, f);
9ea173e8
GM
6782 event.kind = TOOL_BAR_EVENT;
6783 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
06a2c219
GM
6784 kbd_buffer_store_event (&event);
6785
9ea173e8 6786 event.kind = TOOL_BAR_EVENT;
06a2c219
GM
6787 event.frame_or_window = Fcons (frame, key);
6788 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6789 button_event->state);
6790 kbd_buffer_store_event (&event);
9ea173e8 6791 last_tool_bar_item = -1;
06a2c219
GM
6792 }
6793}
6794
6795
9ea173e8
GM
6796/* Possibly highlight a tool-bar item on frame F when mouse moves to
6797 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6798 note_mouse_highlight. */
6799
6800static void
9ea173e8 6801note_tool_bar_highlight (f, x, y)
06a2c219
GM
6802 struct frame *f;
6803 int x, y;
6804{
9ea173e8 6805 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
6806 struct window *w = XWINDOW (window);
6807 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6808 int hpos, vpos;
6809 struct glyph *glyph;
6810 struct glyph_row *row;
5c187dee 6811 int i;
06a2c219
GM
6812 Lisp_Object enabled_p;
6813 int prop_idx;
6814 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 6815 int mouse_down_p, rc;
06a2c219
GM
6816
6817 /* Function note_mouse_highlight is called with negative x(y
6818 values when mouse moves outside of the frame. */
6819 if (x <= 0 || y <= 0)
6820 {
6821 clear_mouse_face (dpyinfo);
6822 return;
6823 }
6824
9ea173e8 6825 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
6826 if (rc < 0)
6827 {
9ea173e8 6828 /* Not on tool-bar item. */
06a2c219
GM
6829 clear_mouse_face (dpyinfo);
6830 return;
6831 }
6832 else if (rc == 0)
9ea173e8 6833 /* On same tool-bar item as before. */
06a2c219 6834 goto set_help_echo;
b8009dd1 6835
06a2c219
GM
6836 clear_mouse_face (dpyinfo);
6837
9ea173e8 6838 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
6839 mouse_down_p = (dpyinfo->grabbed
6840 && f == last_mouse_frame
6841 && FRAME_LIVE_P (f));
6842 if (mouse_down_p
9ea173e8 6843 && last_tool_bar_item != prop_idx)
06a2c219
GM
6844 return;
6845
6846 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6847 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6848
9ea173e8
GM
6849 /* If tool-bar item is not enabled, don't highlight it. */
6850 enabled_p = (XVECTOR (f->current_tool_bar_items)
6851 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6852 if (!NILP (enabled_p))
6853 {
6854 /* Compute the x-position of the glyph. In front and past the
6855 image is a space. We include this is the highlighted area. */
6856 row = MATRIX_ROW (w->current_matrix, vpos);
6857 for (i = x = 0; i < hpos; ++i)
6858 x += row->glyphs[TEXT_AREA][i].pixel_width;
6859
6860 /* Record this as the current active region. */
6861 dpyinfo->mouse_face_beg_col = hpos;
6862 dpyinfo->mouse_face_beg_row = vpos;
6863 dpyinfo->mouse_face_beg_x = x;
6864 dpyinfo->mouse_face_beg_y = row->y;
6865 dpyinfo->mouse_face_past_end = 0;
6866
6867 dpyinfo->mouse_face_end_col = hpos + 1;
6868 dpyinfo->mouse_face_end_row = vpos;
6869 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6870 dpyinfo->mouse_face_end_y = row->y;
6871 dpyinfo->mouse_face_window = window;
9ea173e8 6872 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
6873
6874 /* Display it as active. */
6875 show_mouse_face (dpyinfo, draw);
6876 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6877 }
06a2c219
GM
6878
6879 set_help_echo:
6880
9ea173e8 6881 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 6882 XTread_socket does the rest. */
9ea173e8
GM
6883 help_echo = (XVECTOR (f->current_tool_bar_items)
6884 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
b7e80413 6885 if (NILP (help_echo))
9ea173e8
GM
6886 help_echo = (XVECTOR (f->current_tool_bar_items)
6887 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 6888}
4d73d038 6889
06a2c219
GM
6890
6891\f
6892/* Find the glyph matrix position of buffer position POS in window W.
6893 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6894 current glyphs must be up to date. If POS is above window start
6895 return (0, 0, 0, 0). If POS is after end of W, return end of
6896 last line in W. */
b8009dd1
RS
6897
6898static int
06a2c219
GM
6899fast_find_position (w, pos, hpos, vpos, x, y)
6900 struct window *w;
b8009dd1 6901 int pos;
06a2c219 6902 int *hpos, *vpos, *x, *y;
b8009dd1 6903{
b8009dd1 6904 int i;
bf1c0ba1 6905 int lastcol;
06a2c219
GM
6906 int maybe_next_line_p = 0;
6907 int line_start_position;
6908 int yb = window_text_bottom_y (w);
6909 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6910 struct glyph_row *best_row = row;
6911 int row_vpos = 0, best_row_vpos = 0;
6912 int current_x;
6913
6914 while (row->y < yb)
b8009dd1 6915 {
06a2c219
GM
6916 if (row->used[TEXT_AREA])
6917 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6918 else
6919 line_start_position = 0;
6920
6921 if (line_start_position > pos)
b8009dd1 6922 break;
77b68646
RS
6923 /* If the position sought is the end of the buffer,
6924 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6925 else if (line_start_position == pos
6926 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6927 {
06a2c219 6928 maybe_next_line_p = 1;
77b68646
RS
6929 break;
6930 }
06a2c219
GM
6931 else if (line_start_position > 0)
6932 {
6933 best_row = row;
6934 best_row_vpos = row_vpos;
6935 }
4b0bb6f3
GM
6936
6937 if (row->y + row->height >= yb)
6938 break;
06a2c219
GM
6939
6940 ++row;
6941 ++row_vpos;
b8009dd1 6942 }
06a2c219
GM
6943
6944 /* Find the right column within BEST_ROW. */
6945 lastcol = 0;
6946 current_x = best_row->x;
6947 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 6948 {
06a2c219
GM
6949 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6950 int charpos;
6951
6952 charpos = glyph->charpos;
6953 if (charpos == pos)
bf1c0ba1 6954 {
06a2c219
GM
6955 *hpos = i;
6956 *vpos = best_row_vpos;
6957 *x = current_x;
6958 *y = best_row->y;
bf1c0ba1
RS
6959 return 1;
6960 }
06a2c219 6961 else if (charpos > pos)
4d73d038 6962 break;
06a2c219
GM
6963 else if (charpos > 0)
6964 lastcol = i;
6965
6966 current_x += glyph->pixel_width;
bf1c0ba1 6967 }
b8009dd1 6968
77b68646
RS
6969 /* If we're looking for the end of the buffer,
6970 and we didn't find it in the line we scanned,
6971 use the start of the following line. */
06a2c219 6972 if (maybe_next_line_p)
77b68646 6973 {
06a2c219
GM
6974 ++best_row;
6975 ++best_row_vpos;
6976 lastcol = 0;
6977 current_x = best_row->x;
77b68646
RS
6978 }
6979
06a2c219
GM
6980 *vpos = best_row_vpos;
6981 *hpos = lastcol + 1;
6982 *x = current_x;
6983 *y = best_row->y;
b8009dd1
RS
6984 return 0;
6985}
6986
06a2c219 6987
b8009dd1
RS
6988/* Display the active region described by mouse_face_*
6989 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6990
6991static void
06a2c219 6992show_mouse_face (dpyinfo, draw)
7a13e894 6993 struct x_display_info *dpyinfo;
06a2c219 6994 enum draw_glyphs_face draw;
b8009dd1 6995{
7a13e894 6996 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 6997 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 6998 int i;
06a2c219
GM
6999 int cursor_off_p = 0;
7000 struct cursor_pos saved_cursor;
7001
7002 saved_cursor = output_cursor;
7003
7004 /* If window is in the process of being destroyed, don't bother
7005 to do anything. */
7006 if (w->current_matrix == NULL)
7007 goto set_x_cursor;
7008
7009 /* Recognize when we are called to operate on rows that don't exist
7010 anymore. This can happen when a window is split. */
7011 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
7012 goto set_x_cursor;
7013
7014 set_output_cursor (&w->phys_cursor);
7015
7016 /* Note that mouse_face_beg_row etc. are window relative. */
7017 for (i = dpyinfo->mouse_face_beg_row;
7018 i <= dpyinfo->mouse_face_end_row;
7019 i++)
7020 {
7021 int start_hpos, end_hpos, start_x;
7022 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
7023
7024 /* Don't do anything if row doesn't have valid contents. */
7025 if (!row->enabled_p)
7026 continue;
7027
7028 /* For all but the first row, the highlight starts at column 0. */
7029 if (i == dpyinfo->mouse_face_beg_row)
7030 {
7031 start_hpos = dpyinfo->mouse_face_beg_col;
7032 start_x = dpyinfo->mouse_face_beg_x;
7033 }
7034 else
7035 {
7036 start_hpos = 0;
7037 start_x = 0;
7038 }
7039
7040 if (i == dpyinfo->mouse_face_end_row)
7041 end_hpos = dpyinfo->mouse_face_end_col;
7042 else
7043 end_hpos = row->used[TEXT_AREA];
7044
7045 /* If the cursor's in the text we are about to rewrite, turn the
7046 cursor off. */
7047 if (!w->pseudo_window_p
7048 && i == output_cursor.vpos
7049 && output_cursor.hpos >= start_hpos - 1
7050 && output_cursor.hpos <= end_hpos)
514e4681 7051 {
06a2c219
GM
7052 x_update_window_cursor (w, 0);
7053 cursor_off_p = 1;
514e4681 7054 }
b8009dd1 7055
06a2c219 7056 if (end_hpos > start_hpos)
64f26cf5
GM
7057 {
7058 row->mouse_face_p = draw == DRAW_MOUSE_FACE;
7059 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7060 start_hpos, end_hpos, draw, NULL, NULL, 0);
7061 }
b8009dd1
RS
7062 }
7063
514e4681 7064 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7065 if (cursor_off_p)
7066 x_display_cursor (w, 1,
7067 output_cursor.hpos, output_cursor.vpos,
7068 output_cursor.x, output_cursor.y);
2729a2b5 7069
06a2c219 7070 output_cursor = saved_cursor;
fb3b7de5 7071
06a2c219
GM
7072 set_x_cursor:
7073
7074 /* Change the mouse cursor. */
7075 if (draw == DRAW_NORMAL_TEXT)
7076 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7077 f->output_data.x->text_cursor);
7078 else if (draw == DRAW_MOUSE_FACE)
334208b7 7079 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7080 f->output_data.x->cross_cursor);
27ead1d5 7081 else
334208b7 7082 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7083 f->output_data.x->nontext_cursor);
b8009dd1
RS
7084}
7085
7086/* Clear out the mouse-highlighted active region.
06a2c219 7087 Redraw it un-highlighted first. */
b8009dd1 7088
06a2c219 7089void
7a13e894
RS
7090clear_mouse_face (dpyinfo)
7091 struct x_display_info *dpyinfo;
b8009dd1 7092{
06a2c219
GM
7093 if (tip_frame)
7094 return;
7095
7a13e894 7096 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7097 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7098
7a13e894
RS
7099 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7100 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7101 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7102}
e687d06e 7103
71b8321e
GM
7104
7105/* Clear any mouse-face on window W. This function is part of the
7106 redisplay interface, and is called from try_window_id and similar
7107 functions to ensure the mouse-highlight is off. */
7108
7109static void
7110x_clear_mouse_face (w)
7111 struct window *w;
7112{
7113 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
7114 Lisp_Object window;
7115
7116 XSETWINDOW (window, w);
7117 if (EQ (window, dpyinfo->mouse_face_window))
7118 clear_mouse_face (dpyinfo);
7119}
7120
7121
e687d06e
RS
7122/* Just discard the mouse face information for frame F, if any.
7123 This is used when the size of F is changed. */
7124
dfcf069d 7125void
e687d06e
RS
7126cancel_mouse_face (f)
7127 FRAME_PTR f;
7128{
7129 Lisp_Object window;
7130 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7131
7132 window = dpyinfo->mouse_face_window;
7133 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7134 {
7135 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7136 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7137 dpyinfo->mouse_face_window = Qnil;
7138 }
7139}
b8009dd1 7140\f
ab648270
JB
7141static struct scroll_bar *x_window_to_scroll_bar ();
7142static void x_scroll_bar_report_motion ();
12ba150f 7143
90e65f07 7144/* Return the current position of the mouse.
2d7fc7e8 7145 *fp should be a frame which indicates which display to ask about.
90e65f07 7146
2d7fc7e8 7147 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7148 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7149 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7150 position on the scroll bar.
12ba150f 7151
2d7fc7e8 7152 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7153 mouse is on, *bar_window to nil, and *x and *y to the character cell
7154 the mouse is over.
7155
06a2c219 7156 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7157 was at this position.
7158
a135645a
RS
7159 Don't store anything if we don't have a valid set of values to report.
7160
90e65f07 7161 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7162 movement. */
90e65f07
JB
7163
7164static void
1cf412ec 7165XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7166 FRAME_PTR *fp;
1cf412ec 7167 int insist;
12ba150f 7168 Lisp_Object *bar_window;
ab648270 7169 enum scroll_bar_part *part;
90e65f07 7170 Lisp_Object *x, *y;
e5d77022 7171 unsigned long *time;
90e65f07 7172{
a135645a
RS
7173 FRAME_PTR f1;
7174
90e65f07
JB
7175 BLOCK_INPUT;
7176
8bcee03e 7177 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7178 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7179 else
7180 {
12ba150f
JB
7181 Window root;
7182 int root_x, root_y;
90e65f07 7183
12ba150f
JB
7184 Window dummy_window;
7185 int dummy;
7186
39d8bb4d
KH
7187 Lisp_Object frame, tail;
7188
7189 /* Clear the mouse-moved flag for every frame on this display. */
7190 FOR_EACH_FRAME (tail, frame)
7191 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7192 XFRAME (frame)->mouse_moved = 0;
7193
ab648270 7194 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7195
7196 /* Figure out which root window we're on. */
334208b7
RS
7197 XQueryPointer (FRAME_X_DISPLAY (*fp),
7198 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7199
7200 /* The root window which contains the pointer. */
7201 &root,
7202
7203 /* Trash which we can't trust if the pointer is on
7204 a different screen. */
7205 &dummy_window,
7206
7207 /* The position on that root window. */
58769bee 7208 &root_x, &root_y,
12ba150f
JB
7209
7210 /* More trash we can't trust. */
7211 &dummy, &dummy,
7212
7213 /* Modifier keys and pointer buttons, about which
7214 we don't care. */
7215 (unsigned int *) &dummy);
7216
7217 /* Now we have a position on the root; find the innermost window
7218 containing the pointer. */
7219 {
7220 Window win, child;
7221 int win_x, win_y;
06a2c219 7222 int parent_x = 0, parent_y = 0;
e99db5a1 7223 int count;
12ba150f
JB
7224
7225 win = root;
69388238 7226
2d7fc7e8
RS
7227 /* XTranslateCoordinates can get errors if the window
7228 structure is changing at the same time this function
7229 is running. So at least we must not crash from them. */
7230
e99db5a1 7231 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7232
334208b7 7233 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7234 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7235 {
69388238
RS
7236 /* If mouse was grabbed on a frame, give coords for that frame
7237 even if the mouse is now outside it. */
334208b7 7238 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7239
12ba150f 7240 /* From-window, to-window. */
69388238 7241 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7242
7243 /* From-position, to-position. */
7244 root_x, root_y, &win_x, &win_y,
7245
7246 /* Child of win. */
7247 &child);
69388238
RS
7248 f1 = last_mouse_frame;
7249 }
7250 else
7251 {
7252 while (1)
7253 {
334208b7 7254 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7255
69388238
RS
7256 /* From-window, to-window. */
7257 root, win,
12ba150f 7258
69388238
RS
7259 /* From-position, to-position. */
7260 root_x, root_y, &win_x, &win_y,
7261
7262 /* Child of win. */
7263 &child);
7264
9af3143a 7265 if (child == None || child == win)
69388238
RS
7266 break;
7267
7268 win = child;
7269 parent_x = win_x;
7270 parent_y = win_y;
7271 }
12ba150f 7272
69388238
RS
7273 /* Now we know that:
7274 win is the innermost window containing the pointer
7275 (XTC says it has no child containing the pointer),
7276 win_x and win_y are the pointer's position in it
7277 (XTC did this the last time through), and
7278 parent_x and parent_y are the pointer's position in win's parent.
7279 (They are what win_x and win_y were when win was child.
7280 If win is the root window, it has no parent, and
7281 parent_{x,y} are invalid, but that's okay, because we'll
7282 never use them in that case.) */
7283
7284 /* Is win one of our frames? */
19126e11 7285 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7286 }
58769bee 7287
2d7fc7e8
RS
7288 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7289 f1 = 0;
7290
e99db5a1 7291 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7292
ab648270 7293 /* If not, is it one of our scroll bars? */
a135645a 7294 if (! f1)
12ba150f 7295 {
ab648270 7296 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7297
7298 if (bar)
7299 {
a135645a 7300 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7301 win_x = parent_x;
7302 win_y = parent_y;
7303 }
7304 }
90e65f07 7305
8bcee03e 7306 if (f1 == 0 && insist > 0)
b86bd3dd 7307 f1 = SELECTED_FRAME ();
1cf412ec 7308
a135645a 7309 if (f1)
12ba150f 7310 {
06a2c219
GM
7311 /* Ok, we found a frame. Store all the values.
7312 last_mouse_glyph is a rectangle used to reduce the
7313 generation of mouse events. To not miss any motion
7314 events, we must divide the frame into rectangles of the
7315 size of the smallest character that could be displayed
7316 on it, i.e. into the same rectangles that matrices on
7317 the frame are divided into. */
7318
7319#if OLD_REDISPLAY_CODE
2b5c9e71 7320 int ignore1, ignore2;
2b5c9e71 7321 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7322 &last_mouse_glyph,
1cf412ec
RS
7323 FRAME_X_DISPLAY_INFO (f1)->grabbed
7324 || insist);
06a2c219
GM
7325#else
7326 {
7327 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7328 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7329 int x = win_x;
7330 int y = win_y;
7331
7332 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7333 round down even for negative values. */
7334 if (x < 0)
7335 x -= width - 1;
7336 if (y < 0)
7337 y -= height - 1;
7338
7339 last_mouse_glyph.width = width;
7340 last_mouse_glyph.height = height;
7341 last_mouse_glyph.x = (x + width - 1) / width * width;
7342 last_mouse_glyph.y = (y + height - 1) / height * height;
7343 }
7344#endif
12ba150f
JB
7345
7346 *bar_window = Qnil;
7347 *part = 0;
334208b7 7348 *fp = f1;
e0c1aef2
KH
7349 XSETINT (*x, win_x);
7350 XSETINT (*y, win_y);
12ba150f
JB
7351 *time = last_mouse_movement_time;
7352 }
7353 }
7354 }
90e65f07
JB
7355
7356 UNBLOCK_INPUT;
7357}
f451eb13 7358
06a2c219 7359
06a2c219 7360#ifdef USE_X_TOOLKIT
bffcfca9
GM
7361
7362/* Atimer callback function for TIMER. Called every 0.1s to process
7363 Xt timeouts, if needed. We must avoid calling XtAppPending as
7364 much as possible because that function does an implicit XFlush
7365 that slows us down. */
7366
7367static void
7368x_process_timeouts (timer)
7369 struct atimer *timer;
7370{
7371 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7372 {
7373 BLOCK_INPUT;
7374 while (XtAppPending (Xt_app_con) & XtIMTimer)
7375 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7376 UNBLOCK_INPUT;
7377 }
06a2c219
GM
7378}
7379
bffcfca9 7380#endif /* USE_X_TOOLKIT */
06a2c219
GM
7381
7382\f
7383/* Scroll bar support. */
7384
7385/* Given an X window ID, find the struct scroll_bar which manages it.
7386 This can be called in GC, so we have to make sure to strip off mark
7387 bits. */
bffcfca9 7388
06a2c219
GM
7389static struct scroll_bar *
7390x_window_to_scroll_bar (window_id)
7391 Window window_id;
7392{
7393 Lisp_Object tail;
7394
7395 for (tail = Vframe_list;
7396 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7397 tail = XCDR (tail))
06a2c219
GM
7398 {
7399 Lisp_Object frame, bar, condemned;
7400
8e713be6 7401 frame = XCAR (tail);
06a2c219
GM
7402 /* All elements of Vframe_list should be frames. */
7403 if (! GC_FRAMEP (frame))
7404 abort ();
7405
7406 /* Scan this frame's scroll bar list for a scroll bar with the
7407 right window ID. */
7408 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7409 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7410 /* This trick allows us to search both the ordinary and
7411 condemned scroll bar lists with one loop. */
7412 ! GC_NILP (bar) || (bar = condemned,
7413 condemned = Qnil,
7414 ! GC_NILP (bar));
7415 bar = XSCROLL_BAR (bar)->next)
7416 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7417 return XSCROLL_BAR (bar);
7418 }
7419
7420 return 0;
7421}
7422
7423
7424\f
7425/************************************************************************
7426 Toolkit scroll bars
7427 ************************************************************************/
7428
7429#if USE_TOOLKIT_SCROLL_BARS
7430
7431static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7432static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7433static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7434 struct scroll_bar *));
7435static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7436 int, int, int));
7437
7438
7439/* Id of action hook installed for scroll bars. */
7440
7441static XtActionHookId action_hook_id;
7442
7443/* Lisp window being scrolled. Set when starting to interact with
7444 a toolkit scroll bar, reset to nil when ending the interaction. */
7445
7446static Lisp_Object window_being_scrolled;
7447
7448/* Last scroll bar part sent in xm_scroll_callback. */
7449
7450static int last_scroll_bar_part;
7451
ec18280f
SM
7452/* Whether this is an Xaw with arrow-scrollbars. This should imply
7453 that movements of 1/20 of the screen size are mapped to up/down. */
7454
7455static Boolean xaw3d_arrow_scroll;
7456
7457/* Whether the drag scrolling maintains the mouse at the top of the
7458 thumb. If not, resizing the thumb needs to be done more carefully
7459 to avoid jerkyness. */
7460
7461static Boolean xaw3d_pick_top;
7462
06a2c219
GM
7463
7464/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7465 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7466 the user ends an interaction with the scroll bar, and generates
7467 a `end-scroll' scroll_bar_click' event if so. */
7468
7469static void
7470xt_action_hook (widget, client_data, action_name, event, params,
7471 num_params)
7472 Widget widget;
7473 XtPointer client_data;
7474 String action_name;
7475 XEvent *event;
7476 String *params;
7477 Cardinal *num_params;
7478{
7479 int scroll_bar_p;
7480 char *end_action;
7481
7482#ifdef USE_MOTIF
7483 scroll_bar_p = XmIsScrollBar (widget);
7484 end_action = "Release";
ec18280f 7485#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7486 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7487 end_action = "EndScroll";
ec18280f 7488#endif /* USE_MOTIF */
06a2c219 7489
06a2c219
GM
7490 if (scroll_bar_p
7491 && strcmp (action_name, end_action) == 0
7492 && WINDOWP (window_being_scrolled))
7493 {
7494 struct window *w;
7495
7496 x_send_scroll_bar_event (window_being_scrolled,
7497 scroll_bar_end_scroll, 0, 0);
7498 w = XWINDOW (window_being_scrolled);
7499 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7500 window_being_scrolled = Qnil;
7501 last_scroll_bar_part = -1;
bffcfca9
GM
7502
7503 /* Xt timeouts no longer needed. */
7504 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7505 }
7506}
7507
7508
7509/* Send a client message with message type Xatom_Scrollbar for a
7510 scroll action to the frame of WINDOW. PART is a value identifying
7511 the part of the scroll bar that was clicked on. PORTION is the
7512 amount to scroll of a whole of WHOLE. */
7513
7514static void
7515x_send_scroll_bar_event (window, part, portion, whole)
7516 Lisp_Object window;
7517 int part, portion, whole;
7518{
7519 XEvent event;
7520 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7521 struct frame *f = XFRAME (XWINDOW (window)->frame);
7522
7523 /* Construct a ClientMessage event to send to the frame. */
7524 ev->type = ClientMessage;
7525 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7526 ev->display = FRAME_X_DISPLAY (f);
7527 ev->window = FRAME_X_WINDOW (f);
7528 ev->format = 32;
52e386c2 7529 ev->data.l[0] = (long) XFASTINT (window);
06a2c219
GM
7530 ev->data.l[1] = (long) part;
7531 ev->data.l[2] = (long) 0;
7532 ev->data.l[3] = (long) portion;
7533 ev->data.l[4] = (long) whole;
7534
bffcfca9
GM
7535 /* Make Xt timeouts work while the scroll bar is active. */
7536 toolkit_scroll_bar_interaction = 1;
7537
06a2c219
GM
7538 /* Setting the event mask to zero means that the message will
7539 be sent to the client that created the window, and if that
7540 window no longer exists, no event will be sent. */
7541 BLOCK_INPUT;
7542 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7543 UNBLOCK_INPUT;
7544}
7545
7546
7547/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7548 in *IEVENT. */
7549
7550static void
7551x_scroll_bar_to_input_event (event, ievent)
7552 XEvent *event;
7553 struct input_event *ievent;
7554{
7555 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7556 Lisp_Object window;
7557 struct frame *f;
7558
7559 XSETFASTINT (window, ev->data.l[0]);
7560 f = XFRAME (XWINDOW (window)->frame);
06a2c219
GM
7561
7562 ievent->kind = scroll_bar_click;
7563 ievent->frame_or_window = window;
7564 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7565 ievent->part = ev->data.l[1];
7566 ievent->code = ev->data.l[2];
7567 ievent->x = make_number ((int) ev->data.l[3]);
7568 ievent->y = make_number ((int) ev->data.l[4]);
7569 ievent->modifiers = 0;
7570}
7571
7572
7573#ifdef USE_MOTIF
7574
7575/* Minimum and maximum values used for Motif scroll bars. */
7576
7577#define XM_SB_MIN 1
7578#define XM_SB_MAX 10000000
7579#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7580
7581
7582/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7583 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7584 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7585
7586static void
7587xm_scroll_callback (widget, client_data, call_data)
7588 Widget widget;
7589 XtPointer client_data, call_data;
7590{
7591 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7592 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7593 double percent;
7594 int part = -1, whole = 0, portion = 0;
7595
7596 switch (cs->reason)
7597 {
7598 case XmCR_DECREMENT:
7599 bar->dragging = Qnil;
7600 part = scroll_bar_up_arrow;
7601 break;
7602
7603 case XmCR_INCREMENT:
7604 bar->dragging = Qnil;
7605 part = scroll_bar_down_arrow;
7606 break;
7607
7608 case XmCR_PAGE_DECREMENT:
7609 bar->dragging = Qnil;
7610 part = scroll_bar_above_handle;
7611 break;
7612
7613 case XmCR_PAGE_INCREMENT:
7614 bar->dragging = Qnil;
7615 part = scroll_bar_below_handle;
7616 break;
7617
7618 case XmCR_TO_TOP:
7619 bar->dragging = Qnil;
7620 part = scroll_bar_to_top;
7621 break;
7622
7623 case XmCR_TO_BOTTOM:
7624 bar->dragging = Qnil;
7625 part = scroll_bar_to_bottom;
7626 break;
7627
7628 case XmCR_DRAG:
7629 {
7630 int slider_size;
7631 int dragging_down_p = (INTEGERP (bar->dragging)
7632 && XINT (bar->dragging) <= cs->value);
7633
7634 /* Get the slider size. */
7635 BLOCK_INPUT;
7636 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7637 UNBLOCK_INPUT;
7638
7639 /* At the max position of the scroll bar, do a line-wise
7640 movement. Without doing anything, the LessTif scroll bar
7641 calls us with the same cs->value again and again. If we
7642 want to make sure that we can reach the end of the buffer,
7643 we have to do something.
7644
7645 Implementation note: setting bar->dragging always to
7646 cs->value gives a smoother movement at the max position.
7647 Setting it to nil when doing line-wise movement gives
7648 a better slider behavior. */
7649
7650 if (cs->value + slider_size == XM_SB_MAX
7651 || (dragging_down_p
7652 && last_scroll_bar_part == scroll_bar_down_arrow))
7653 {
7654 part = scroll_bar_down_arrow;
7655 bar->dragging = Qnil;
7656 }
7657 else
7658 {
7659 whole = XM_SB_RANGE;
7660 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7661 part = scroll_bar_handle;
7662 bar->dragging = make_number (cs->value);
7663 }
7664 }
7665 break;
7666
7667 case XmCR_VALUE_CHANGED:
7668 break;
7669 };
7670
7671 if (part >= 0)
7672 {
7673 window_being_scrolled = bar->window;
7674 last_scroll_bar_part = part;
7675 x_send_scroll_bar_event (bar->window, part, portion, whole);
7676 }
7677}
7678
7679
ec18280f 7680#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7681
7682
ec18280f 7683/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7684 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7685 scroll bar struct. CALL_DATA is a pointer to a float saying where
7686 the thumb is. */
7687
7688static void
ec18280f 7689xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7690 Widget widget;
7691 XtPointer client_data, call_data;
7692{
7693 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7694 float top = *(float *) call_data;
7695 float shown;
ec18280f
SM
7696 int whole, portion, height;
7697 int part;
06a2c219
GM
7698
7699 /* Get the size of the thumb, a value between 0 and 1. */
7700 BLOCK_INPUT;
ec18280f 7701 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7702 UNBLOCK_INPUT;
7703
7704 whole = 10000000;
7705 portion = shown < 1 ? top * whole : 0;
06a2c219 7706
ec18280f
SM
7707 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7708 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7709 the bottom, so we force the scrolling whenever we see that we're
7710 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7711 we try to ensure that we always stay two pixels away from the
7712 bottom). */
06a2c219
GM
7713 part = scroll_bar_down_arrow;
7714 else
7715 part = scroll_bar_handle;
7716
7717 window_being_scrolled = bar->window;
7718 bar->dragging = make_number (portion);
7719 last_scroll_bar_part = part;
7720 x_send_scroll_bar_event (bar->window, part, portion, whole);
7721}
7722
7723
ec18280f
SM
7724/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7725 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7726 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7727 the scroll bar. CALL_DATA is an integer specifying the action that
7728 has taken place. It's magnitude is in the range 0..height of the
7729 scroll bar. Negative values mean scroll towards buffer start.
7730 Values < height of scroll bar mean line-wise movement. */
7731
7732static void
ec18280f 7733xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7734 Widget widget;
7735 XtPointer client_data, call_data;
7736{
7737 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7738 int position = (int) call_data;
7739 Dimension height;
7740 int part;
7741
7742 /* Get the height of the scroll bar. */
7743 BLOCK_INPUT;
7744 XtVaGetValues (widget, XtNheight, &height, NULL);
7745 UNBLOCK_INPUT;
7746
ec18280f
SM
7747 if (abs (position) >= height)
7748 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7749
7750 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7751 it maps line-movement to call_data = max(5, height/20). */
7752 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7753 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7754 else
ec18280f 7755 part = scroll_bar_move_ratio;
06a2c219
GM
7756
7757 window_being_scrolled = bar->window;
7758 bar->dragging = Qnil;
7759 last_scroll_bar_part = part;
ec18280f 7760 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7761}
7762
7763
7764#endif /* not USE_MOTIF */
7765
7766
7767/* Create the widget for scroll bar BAR on frame F. Record the widget
7768 and X window of the scroll bar in BAR. */
7769
7770static void
7771x_create_toolkit_scroll_bar (f, bar)
7772 struct frame *f;
7773 struct scroll_bar *bar;
7774{
7775 Window xwindow;
7776 Widget widget;
7777 Arg av[20];
7778 int ac = 0;
7779 char *scroll_bar_name = "verticalScrollBar";
7780 unsigned long pixel;
7781
7782 BLOCK_INPUT;
7783
7784#ifdef USE_MOTIF
7785 /* LessTif 0.85, problems:
7786
7787 1. When the mouse if over the scroll bar, the scroll bar will
7788 get keyboard events. I didn't find a way to turn this off.
7789
7790 2. Do we have to explicitly set the cursor to get an arrow
7791 cursor (see below)? */
7792
7793 /* Set resources. Create the widget. */
7794 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7795 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7796 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7797 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7798 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7799 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7800 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7801
7802 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7803 if (pixel != -1)
7804 {
7805 XtSetArg (av[ac], XmNforeground, pixel);
7806 ++ac;
7807 }
7808
7809 pixel = f->output_data.x->scroll_bar_background_pixel;
7810 if (pixel != -1)
7811 {
7812 XtSetArg (av[ac], XmNbackground, pixel);
7813 ++ac;
7814 }
7815
7816 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7817 scroll_bar_name, av, ac);
7818
7819 /* Add one callback for everything that can happen. */
7820 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7821 (XtPointer) bar);
7822 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7823 (XtPointer) bar);
7824 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7825 (XtPointer) bar);
7826 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7827 (XtPointer) bar);
7828 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7829 (XtPointer) bar);
7830 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7831 (XtPointer) bar);
7832 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7833 (XtPointer) bar);
7834
7835 /* Realize the widget. Only after that is the X window created. */
7836 XtRealizeWidget (widget);
7837
7838 /* Set the cursor to an arrow. I didn't find a resource to do that.
7839 And I'm wondering why it hasn't an arrow cursor by default. */
7840 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7841 f->output_data.x->nontext_cursor);
7842
ec18280f 7843#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7844
7845 /* Set resources. Create the widget. The background of the
7846 Xaw3d scroll bar widget is a little bit light for my taste.
7847 We don't alter it here to let users change it according
7848 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7849 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7850 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
7851 /* For smoother scrolling with Xaw3d -sm */
7852 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7853 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
7854
7855 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7856 if (pixel != -1)
7857 {
7858 XtSetArg (av[ac], XtNforeground, pixel);
7859 ++ac;
7860 }
7861
7862 pixel = f->output_data.x->scroll_bar_background_pixel;
7863 if (pixel != -1)
7864 {
7865 XtSetArg (av[ac], XtNbackground, pixel);
7866 ++ac;
7867 }
7868
7869 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7870 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
7871
7872 {
7873 char *initial = "";
7874 char *val = initial;
7875 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7876 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7877 if (val == initial)
7878 { /* ARROW_SCROLL */
7879 xaw3d_arrow_scroll = True;
7880 /* Isn't that just a personal preference ? -sm */
7881 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7882 }
7883 }
06a2c219
GM
7884
7885 /* Define callbacks. */
ec18280f
SM
7886 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7887 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
7888 (XtPointer) bar);
7889
7890 /* Realize the widget. Only after that is the X window created. */
7891 XtRealizeWidget (widget);
7892
ec18280f 7893#endif /* !USE_MOTIF */
06a2c219
GM
7894
7895 /* Install an action hook that let's us detect when the user
7896 finishes interacting with a scroll bar. */
7897 if (action_hook_id == 0)
7898 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7899
7900 /* Remember X window and widget in the scroll bar vector. */
7901 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7902 xwindow = XtWindow (widget);
7903 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7904
7905 UNBLOCK_INPUT;
7906}
7907
7908
7909/* Set the thumb size and position of scroll bar BAR. We are currently
7910 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7911
7912static void
7913x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7914 struct scroll_bar *bar;
7915 int portion, position, whole;
f451eb13 7916{
06a2c219 7917 float top, shown;
06a2c219 7918 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7919
06a2c219
GM
7920 if (whole == 0)
7921 top = 0, shown = 1;
7922 else
f451eb13 7923 {
06a2c219
GM
7924 top = (float) position / whole;
7925 shown = (float) portion / whole;
7926 }
f451eb13 7927
06a2c219 7928 BLOCK_INPUT;
f451eb13 7929
06a2c219
GM
7930#ifdef USE_MOTIF
7931 {
7932 int size, value;
7933 Boolean arrow1_selected, arrow2_selected;
7934 unsigned char flags;
7935 XmScrollBarWidget sb;
7936
ec18280f 7937 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
7938 is the scroll bar's maximum and MIN is the scroll bar's minimum
7939 value. */
7940 size = shown * XM_SB_RANGE;
7941 size = min (size, XM_SB_RANGE);
7942 size = max (size, 1);
7943
7944 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7945 value = top * XM_SB_RANGE;
7946 value = min (value, XM_SB_MAX - size);
7947 value = max (value, XM_SB_MIN);
7948
7949 /* LessTif: Calling XmScrollBarSetValues after an increment or
7950 decrement turns off auto-repeat LessTif-internally. This can
7951 be seen in ScrollBar.c which resets Arrow1Selected and
7952 Arrow2Selected. It also sets internal flags so that LessTif
7953 believes the mouse is in the slider. We either have to change
7954 our code, or work around that by accessing private data. */
7955
7956 sb = (XmScrollBarWidget) widget;
7957 arrow1_selected = sb->scrollBar.arrow1_selected;
7958 arrow2_selected = sb->scrollBar.arrow2_selected;
7959 flags = sb->scrollBar.flags;
7960
7961 if (NILP (bar->dragging))
7962 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7963 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7964 /* This has the negative side effect that the slider value is
ec18280f 7965 not what it would be if we scrolled here using line-wise or
06a2c219
GM
7966 page-wise movement. */
7967 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7968 else
7969 {
7970 /* If currently dragging, only update the slider size.
7971 This reduces flicker effects. */
7972 int old_value, old_size, increment, page_increment;
7973
7974 XmScrollBarGetValues (widget, &old_value, &old_size,
7975 &increment, &page_increment);
7976 XmScrollBarSetValues (widget, old_value,
7977 min (size, XM_SB_RANGE - old_value),
7978 0, 0, False);
7979 }
7980
7981 sb->scrollBar.arrow1_selected = arrow1_selected;
7982 sb->scrollBar.arrow2_selected = arrow2_selected;
7983 sb->scrollBar.flags = flags;
7984 }
ec18280f 7985#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 7986 {
ec18280f
SM
7987 float old_top, old_shown;
7988 Dimension height;
7989 XtVaGetValues (widget,
7990 XtNtopOfThumb, &old_top,
7991 XtNshown, &old_shown,
7992 XtNheight, &height,
7993 NULL);
7994
7995 /* Massage the top+shown values. */
7996 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7997 top = max (0, min (1, top));
7998 else
7999 top = old_top;
8000 /* Keep two pixels available for moving the thumb down. */
8001 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
8002
8003 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
8004 check that your system's configuration file contains a define
8005 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 8006 if (top != old_top || shown != old_shown)
eb393530 8007 {
ec18280f 8008 if (NILP (bar->dragging))
eb393530 8009 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
8010 else
8011 {
ec18280f
SM
8012#ifdef HAVE_XAW3D
8013 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 8014 int scroll_mode = 0;
ec18280f
SM
8015
8016 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
8017 if (xaw3d_arrow_scroll)
8018 {
8019 /* Xaw3d stupidly ignores resize requests while dragging
8020 so we have to make it believe it's not in dragging mode. */
8021 scroll_mode = sb->scrollbar.scroll_mode;
8022 if (scroll_mode == 2)
8023 sb->scrollbar.scroll_mode = 0;
8024 }
8025#endif
8026 /* Try to make the scrolling a tad smoother. */
8027 if (!xaw3d_pick_top)
8028 shown = min (shown, old_shown);
8029
8030 XawScrollbarSetThumb (widget, top, shown);
8031
8032#ifdef HAVE_XAW3D
8033 if (xaw3d_arrow_scroll && scroll_mode == 2)
8034 sb->scrollbar.scroll_mode = scroll_mode;
8035#endif
06a2c219 8036 }
06a2c219
GM
8037 }
8038 }
ec18280f 8039#endif /* !USE_MOTIF */
06a2c219
GM
8040
8041 UNBLOCK_INPUT;
f451eb13
JB
8042}
8043
06a2c219
GM
8044#endif /* USE_TOOLKIT_SCROLL_BARS */
8045
8046
8047\f
8048/************************************************************************
8049 Scroll bars, general
8050 ************************************************************************/
8051
8052/* Create a scroll bar and return the scroll bar vector for it. W is
8053 the Emacs window on which to create the scroll bar. TOP, LEFT,
8054 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8055 scroll bar. */
8056
ab648270 8057static struct scroll_bar *
06a2c219
GM
8058x_scroll_bar_create (w, top, left, width, height)
8059 struct window *w;
f451eb13
JB
8060 int top, left, width, height;
8061{
06a2c219 8062 struct frame *f = XFRAME (w->frame);
334208b7
RS
8063 struct scroll_bar *bar
8064 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8065
8066 BLOCK_INPUT;
8067
06a2c219
GM
8068#if USE_TOOLKIT_SCROLL_BARS
8069 x_create_toolkit_scroll_bar (f, bar);
8070#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8071 {
8072 XSetWindowAttributes a;
8073 unsigned long mask;
5c187dee 8074 Window window;
06a2c219
GM
8075
8076 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8077 if (a.background_pixel == -1)
8078 a.background_pixel = f->output_data.x->background_pixel;
8079
12ba150f 8080 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8081 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8082 | ExposureMask);
7a13e894 8083 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8084
dbc4e1c1 8085 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8086
06a2c219
GM
8087 /* Clear the area of W that will serve as a scroll bar. This is
8088 for the case that a window has been split horizontally. In
8089 this case, no clear_frame is generated to reduce flickering. */
8090 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8091 left, top, width,
8092 window_box_height (w), False);
8093
8094 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8095 /* Position and size of scroll bar. */
8096 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8097 top,
8098 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8099 height,
8100 /* Border width, depth, class, and visual. */
8101 0,
8102 CopyFromParent,
8103 CopyFromParent,
8104 CopyFromParent,
8105 /* Attributes. */
8106 mask, &a);
8107 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8108 }
06a2c219 8109#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8110
06a2c219 8111 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8112 XSETINT (bar->top, top);
8113 XSETINT (bar->left, left);
8114 XSETINT (bar->width, width);
8115 XSETINT (bar->height, height);
8116 XSETINT (bar->start, 0);
8117 XSETINT (bar->end, 0);
12ba150f 8118 bar->dragging = Qnil;
f451eb13
JB
8119
8120 /* Add bar to its frame's list of scroll bars. */
334208b7 8121 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8122 bar->prev = Qnil;
334208b7 8123 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8124 if (!NILP (bar->next))
e0c1aef2 8125 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8126
06a2c219
GM
8127 /* Map the window/widget. */
8128#if USE_TOOLKIT_SCROLL_BARS
8129 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8130 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8131 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8132 top,
8133 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8134 height, 0);
8135#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8136 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8137#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8138
8139 UNBLOCK_INPUT;
12ba150f 8140 return bar;
f451eb13
JB
8141}
8142
06a2c219 8143
12ba150f 8144/* Draw BAR's handle in the proper position.
06a2c219 8145
12ba150f
JB
8146 If the handle is already drawn from START to END, don't bother
8147 redrawing it, unless REBUILD is non-zero; in that case, always
8148 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8149 events.)
12ba150f
JB
8150
8151 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8152 fit inside its rectangle, but if the user is dragging the scroll
8153 bar handle, we want to let them drag it down all the way, so that
8154 the bar's top is as far down as it goes; otherwise, there's no way
8155 to move to the very end of the buffer. */
8156
5c187dee
GM
8157#ifndef USE_TOOLKIT_SCROLL_BARS
8158
f451eb13 8159static void
ab648270
JB
8160x_scroll_bar_set_handle (bar, start, end, rebuild)
8161 struct scroll_bar *bar;
f451eb13 8162 int start, end;
12ba150f 8163 int rebuild;
f451eb13 8164{
12ba150f 8165 int dragging = ! NILP (bar->dragging);
ab648270 8166 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8167 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8168 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8169
8170 /* If the display is already accurate, do nothing. */
8171 if (! rebuild
8172 && start == XINT (bar->start)
8173 && end == XINT (bar->end))
8174 return;
8175
f451eb13
JB
8176 BLOCK_INPUT;
8177
8178 {
d9cdbb3d
RS
8179 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8180 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8181 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8182
8183 /* Make sure the values are reasonable, and try to preserve
8184 the distance between start and end. */
12ba150f
JB
8185 {
8186 int length = end - start;
8187
8188 if (start < 0)
8189 start = 0;
8190 else if (start > top_range)
8191 start = top_range;
8192 end = start + length;
8193
8194 if (end < start)
8195 end = start;
8196 else if (end > top_range && ! dragging)
8197 end = top_range;
8198 }
f451eb13 8199
ab648270 8200 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8201 XSETINT (bar->start, start);
8202 XSETINT (bar->end, end);
f451eb13 8203
12ba150f
JB
8204 /* Clip the end position, just for display. */
8205 if (end > top_range)
8206 end = top_range;
f451eb13 8207
ab648270 8208 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8209 below top positions, to make sure the handle is always at least
8210 that many pixels tall. */
ab648270 8211 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8212
12ba150f
JB
8213 /* Draw the empty space above the handle. Note that we can't clear
8214 zero-height areas; that means "clear to end of window." */
8215 if (0 < start)
334208b7 8216 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8217
12ba150f 8218 /* x, y, width, height, and exposures. */
ab648270
JB
8219 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8220 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8221 inside_width, start,
8222 False);
f451eb13 8223
06a2c219
GM
8224 /* Change to proper foreground color if one is specified. */
8225 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8226 XSetForeground (FRAME_X_DISPLAY (f), gc,
8227 f->output_data.x->scroll_bar_foreground_pixel);
8228
12ba150f 8229 /* Draw the handle itself. */
334208b7 8230 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8231
12ba150f 8232 /* x, y, width, height */
ab648270
JB
8233 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8234 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8235 inside_width, end - start);
f451eb13 8236
06a2c219
GM
8237 /* Restore the foreground color of the GC if we changed it above. */
8238 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8239 XSetForeground (FRAME_X_DISPLAY (f), gc,
8240 f->output_data.x->foreground_pixel);
f451eb13 8241
12ba150f
JB
8242 /* Draw the empty space below the handle. Note that we can't
8243 clear zero-height areas; that means "clear to end of window." */
8244 if (end < inside_height)
334208b7 8245 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8246
12ba150f 8247 /* x, y, width, height, and exposures. */
ab648270
JB
8248 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8249 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8250 inside_width, inside_height - end,
8251 False);
f451eb13 8252
f451eb13
JB
8253 }
8254
f451eb13
JB
8255 UNBLOCK_INPUT;
8256}
8257
5c187dee 8258#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8259
06a2c219
GM
8260/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8261 nil. */
58769bee 8262
12ba150f 8263static void
ab648270
JB
8264x_scroll_bar_remove (bar)
8265 struct scroll_bar *bar;
12ba150f 8266{
12ba150f
JB
8267 BLOCK_INPUT;
8268
06a2c219
GM
8269#if USE_TOOLKIT_SCROLL_BARS
8270 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8271#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8272 {
8273 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8274 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8275 }
06a2c219
GM
8276#endif /* not USE_TOOLKIT_SCROLL_BARS */
8277
ab648270
JB
8278 /* Disassociate this scroll bar from its window. */
8279 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8280
8281 UNBLOCK_INPUT;
8282}
8283
06a2c219 8284
12ba150f
JB
8285/* Set the handle of the vertical scroll bar for WINDOW to indicate
8286 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8287 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8288 create one. */
06a2c219 8289
12ba150f 8290static void
06a2c219
GM
8291XTset_vertical_scroll_bar (w, portion, whole, position)
8292 struct window *w;
f451eb13
JB
8293 int portion, whole, position;
8294{
06a2c219 8295 struct frame *f = XFRAME (w->frame);
ab648270 8296 struct scroll_bar *bar;
3c6ede7b 8297 int top, height, left, sb_left, width, sb_width;
06a2c219 8298 int window_x, window_y, window_width, window_height;
06a2c219 8299
3c6ede7b 8300 /* Get window dimensions. */
06a2c219 8301 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8302 top = window_y;
8303 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8304 height = window_height;
06a2c219 8305
3c6ede7b 8306 /* Compute the left edge of the scroll bar area. */
06a2c219 8307 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8308 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8309 else
8310 left = XFASTINT (w->left);
8311 left *= CANON_X_UNIT (f);
8312 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8313
8314 /* Compute the width of the scroll bar which might be less than
8315 the width of the area reserved for the scroll bar. */
8316 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8317 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8318 else
3c6ede7b 8319 sb_width = width;
12ba150f 8320
3c6ede7b
GM
8321 /* Compute the left edge of the scroll bar. */
8322#ifdef USE_TOOLKIT_SCROLL_BARS
8323 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8324 sb_left = left + width - sb_width - (width - sb_width) / 2;
8325 else
8326 sb_left = left + (width - sb_width) / 2;
8327#else
8328 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8329 sb_left = left + width - sb_width;
8330 else
8331 sb_left = left;
8332#endif
8333
ab648270 8334 /* Does the scroll bar exist yet? */
06a2c219 8335 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8336 {
80c32bcc 8337 BLOCK_INPUT;
3c6ede7b
GM
8338 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8339 left, top, width, height, False);
80c32bcc 8340 UNBLOCK_INPUT;
3c6ede7b
GM
8341 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8342 }
f451eb13 8343 else
12ba150f
JB
8344 {
8345 /* It may just need to be moved and resized. */
06a2c219
GM
8346 unsigned int mask = 0;
8347
8348 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8349
8350 BLOCK_INPUT;
8351
3c6ede7b 8352 if (sb_left != XINT (bar->left))
06a2c219 8353 mask |= CWX;
3c6ede7b 8354 if (top != XINT (bar->top))
06a2c219 8355 mask |= CWY;
3c6ede7b 8356 if (sb_width != XINT (bar->width))
06a2c219 8357 mask |= CWWidth;
3c6ede7b 8358 if (height != XINT (bar->height))
06a2c219
GM
8359 mask |= CWHeight;
8360
8361#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8362
8363 /* Since toolkit scroll bars are smaller than the space reserved
8364 for them on the frame, we have to clear "under" them. */
8365 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8366 left, top, width, height, False);
06a2c219
GM
8367
8368 /* Move/size the scroll bar widget. */
8369 if (mask)
8370 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8371 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8372 top,
8373 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8374 height, 0);
06a2c219
GM
8375
8376#else /* not USE_TOOLKIT_SCROLL_BARS */
8377
e1f6572f
RS
8378 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8379 {
8380 /* Clear areas not covered by the scroll bar. This makes sure a
8381 previous mode line display is cleared after C-x 2 C-x 1, for
8382 example. Non-toolkit scroll bars are as wide as the area
8383 reserved for scroll bars - trim at both sides. */
8384 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8385 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8386 height, False);
8387 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8388 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8389 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8390 height, False);
8391 }
06a2c219
GM
8392
8393 /* Move/size the scroll bar window. */
8394 if (mask)
8395 {
8396 XWindowChanges wc;
8397
3c6ede7b
GM
8398 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8399 wc.y = top;
8400 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8401 wc.height = height;
06a2c219
GM
8402 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8403 mask, &wc);
8404 }
8405
8406#endif /* not USE_TOOLKIT_SCROLL_BARS */
8407
8408 /* Remember new settings. */
3c6ede7b
GM
8409 XSETINT (bar->left, sb_left);
8410 XSETINT (bar->top, top);
8411 XSETINT (bar->width, sb_width);
8412 XSETINT (bar->height, height);
06a2c219
GM
8413
8414 UNBLOCK_INPUT;
12ba150f 8415 }
f451eb13 8416
06a2c219
GM
8417#if USE_TOOLKIT_SCROLL_BARS
8418 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8419#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8420 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8421 dragged. */
12ba150f 8422 if (NILP (bar->dragging))
f451eb13 8423 {
92857db0 8424 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8425
12ba150f 8426 if (whole == 0)
ab648270 8427 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8428 else
8429 {
43f868f5
JB
8430 int start = ((double) position * top_range) / whole;
8431 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8432 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8433 }
f451eb13 8434 }
06a2c219 8435#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8436
06a2c219 8437 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8438}
8439
12ba150f 8440
f451eb13 8441/* The following three hooks are used when we're doing a thorough
ab648270 8442 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8443 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8444 away is a real pain - "Can you say set-window-configuration, boys
8445 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8446 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8447 from the fiery pit when we actually redisplay its window. */
f451eb13 8448
ab648270
JB
8449/* Arrange for all scroll bars on FRAME to be removed at the next call
8450 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8451 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8452
58769bee 8453static void
ab648270 8454XTcondemn_scroll_bars (frame)
f451eb13
JB
8455 FRAME_PTR frame;
8456{
f9e24cb9
RS
8457 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8458 while (! NILP (FRAME_SCROLL_BARS (frame)))
8459 {
8460 Lisp_Object bar;
8461 bar = FRAME_SCROLL_BARS (frame);
8462 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8463 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8464 XSCROLL_BAR (bar)->prev = Qnil;
8465 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8466 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8467 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8468 }
f451eb13
JB
8469}
8470
06a2c219 8471/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8472 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 8473static void
ab648270 8474XTredeem_scroll_bar (window)
12ba150f 8475 struct window *window;
f451eb13 8476{
ab648270 8477 struct scroll_bar *bar;
12ba150f 8478
ab648270
JB
8479 /* We can't redeem this window's scroll bar if it doesn't have one. */
8480 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8481 abort ();
8482
ab648270 8483 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8484
8485 /* Unlink it from the condemned list. */
8486 {
8487 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8488
8489 if (NILP (bar->prev))
8490 {
8491 /* If the prev pointer is nil, it must be the first in one of
8492 the lists. */
ab648270 8493 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
8494 /* It's not condemned. Everything's fine. */
8495 return;
ab648270
JB
8496 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8497 window->vertical_scroll_bar))
8498 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
8499 else
8500 /* If its prev pointer is nil, it must be at the front of
8501 one or the other! */
8502 abort ();
8503 }
8504 else
ab648270 8505 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
8506
8507 if (! NILP (bar->next))
ab648270 8508 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8509
ab648270 8510 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8511 bar->prev = Qnil;
e0c1aef2 8512 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 8513 if (! NILP (bar->next))
e0c1aef2 8514 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 8515 }
f451eb13
JB
8516}
8517
ab648270
JB
8518/* Remove all scroll bars on FRAME that haven't been saved since the
8519 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8520
f451eb13 8521static void
ab648270 8522XTjudge_scroll_bars (f)
12ba150f 8523 FRAME_PTR f;
f451eb13 8524{
12ba150f 8525 Lisp_Object bar, next;
f451eb13 8526
ab648270 8527 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8528
8529 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8530 more events on the hapless scroll bars. */
8531 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8532
8533 for (; ! NILP (bar); bar = next)
f451eb13 8534 {
ab648270 8535 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8536
ab648270 8537 x_scroll_bar_remove (b);
12ba150f
JB
8538
8539 next = b->next;
8540 b->next = b->prev = Qnil;
f451eb13 8541 }
12ba150f 8542
ab648270 8543 /* Now there should be no references to the condemned scroll bars,
12ba150f 8544 and they should get garbage-collected. */
f451eb13
JB
8545}
8546
8547
06a2c219
GM
8548/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8549 is a no-op when using toolkit scroll bars.
ab648270
JB
8550
8551 This may be called from a signal handler, so we have to ignore GC
8552 mark bits. */
06a2c219 8553
f451eb13 8554static void
ab648270
JB
8555x_scroll_bar_expose (bar, event)
8556 struct scroll_bar *bar;
f451eb13
JB
8557 XEvent *event;
8558{
06a2c219
GM
8559#ifndef USE_TOOLKIT_SCROLL_BARS
8560
ab648270 8561 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8562 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8563 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8564 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8565
f451eb13
JB
8566 BLOCK_INPUT;
8567
ab648270 8568 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8569
06a2c219 8570 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8571 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8572
8573 /* x, y, width, height */
d9cdbb3d 8574 0, 0,
3cbd2e0b 8575 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8576 XINT (bar->height) - 1);
8577
f451eb13 8578 UNBLOCK_INPUT;
06a2c219
GM
8579
8580#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8581}
8582
ab648270
JB
8583/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8584 is set to something other than no_event, it is enqueued.
8585
8586 This may be called from a signal handler, so we have to ignore GC
8587 mark bits. */
06a2c219 8588
5c187dee
GM
8589#ifndef USE_TOOLKIT_SCROLL_BARS
8590
f451eb13 8591static void
ab648270
JB
8592x_scroll_bar_handle_click (bar, event, emacs_event)
8593 struct scroll_bar *bar;
f451eb13
JB
8594 XEvent *event;
8595 struct input_event *emacs_event;
8596{
0299d313 8597 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8598 abort ();
8599
ab648270 8600 emacs_event->kind = scroll_bar_click;
69388238 8601 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8602 emacs_event->modifiers
8603 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8604 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8605 event->xbutton.state)
8606 | (event->type == ButtonRelease
8607 ? up_modifier
8608 : down_modifier));
12ba150f 8609 emacs_event->frame_or_window = bar->window;
f451eb13 8610 emacs_event->timestamp = event->xbutton.time;
12ba150f 8611 {
06a2c219 8612#if 0
d9cdbb3d 8613 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8614 int internal_height
d9cdbb3d 8615 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8616#endif
0299d313 8617 int top_range
d9cdbb3d 8618 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8619 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8620
8621 if (y < 0) y = 0;
8622 if (y > top_range) y = top_range;
8623
8624 if (y < XINT (bar->start))
ab648270
JB
8625 emacs_event->part = scroll_bar_above_handle;
8626 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8627 emacs_event->part = scroll_bar_handle;
12ba150f 8628 else
ab648270 8629 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8630
8631 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8632 they want to drag it. Lisp code needs to be able to decide
8633 whether or not we're dragging. */
929787e1 8634#if 0
12ba150f
JB
8635 /* If the user has just clicked on the handle, record where they're
8636 holding it. */
8637 if (event->type == ButtonPress
ab648270 8638 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8639 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8640#endif
12ba150f
JB
8641
8642 /* If the user has released the handle, set it to its final position. */
8643 if (event->type == ButtonRelease
8644 && ! NILP (bar->dragging))
8645 {
8646 int new_start = y - XINT (bar->dragging);
8647 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8648
ab648270 8649 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8650 bar->dragging = Qnil;
8651 }
f451eb13 8652
5116f055
JB
8653 /* Same deal here as the other #if 0. */
8654#if 0
58769bee 8655 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8656 the handle. */
ab648270 8657 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8658 emacs_event->x = bar->start;
8659 else
e0c1aef2 8660 XSETINT (emacs_event->x, y);
5116f055 8661#else
e0c1aef2 8662 XSETINT (emacs_event->x, y);
5116f055 8663#endif
f451eb13 8664
e0c1aef2 8665 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8666 }
8667}
f451eb13 8668
ab648270
JB
8669/* Handle some mouse motion while someone is dragging the scroll bar.
8670
8671 This may be called from a signal handler, so we have to ignore GC
8672 mark bits. */
06a2c219 8673
f451eb13 8674static void
ab648270
JB
8675x_scroll_bar_note_movement (bar, event)
8676 struct scroll_bar *bar;
f451eb13
JB
8677 XEvent *event;
8678{
39d8bb4d
KH
8679 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8680
f451eb13
JB
8681 last_mouse_movement_time = event->xmotion.time;
8682
39d8bb4d 8683 f->mouse_moved = 1;
e0c1aef2 8684 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8685
8686 /* If we're dragging the bar, display it. */
ab648270 8687 if (! GC_NILP (bar->dragging))
f451eb13
JB
8688 {
8689 /* Where should the handle be now? */
12ba150f 8690 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8691
12ba150f 8692 if (new_start != XINT (bar->start))
f451eb13 8693 {
12ba150f 8694 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8695
ab648270 8696 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8697 }
8698 }
f451eb13
JB
8699}
8700
5c187dee
GM
8701#endif /* !USE_TOOLKIT_SCROLL_BARS */
8702
12ba150f 8703/* Return information to the user about the current position of the mouse
ab648270 8704 on the scroll bar. */
06a2c219 8705
12ba150f 8706static void
334208b7
RS
8707x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8708 FRAME_PTR *fp;
12ba150f 8709 Lisp_Object *bar_window;
ab648270 8710 enum scroll_bar_part *part;
12ba150f
JB
8711 Lisp_Object *x, *y;
8712 unsigned long *time;
8713{
ab648270 8714 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8715 Window w = SCROLL_BAR_X_WINDOW (bar);
8716 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8717 int win_x, win_y;
559cb2fb
JB
8718 Window dummy_window;
8719 int dummy_coord;
8720 unsigned int dummy_mask;
12ba150f 8721
cf7cb199
JB
8722 BLOCK_INPUT;
8723
ab648270 8724 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8725 report that. */
334208b7 8726 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8727
559cb2fb
JB
8728 /* Root, child, root x and root y. */
8729 &dummy_window, &dummy_window,
8730 &dummy_coord, &dummy_coord,
12ba150f 8731
559cb2fb
JB
8732 /* Position relative to scroll bar. */
8733 &win_x, &win_y,
12ba150f 8734
559cb2fb
JB
8735 /* Mouse buttons and modifier keys. */
8736 &dummy_mask))
7a13e894 8737 ;
559cb2fb
JB
8738 else
8739 {
06a2c219 8740#if 0
559cb2fb 8741 int inside_height
d9cdbb3d 8742 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8743#endif
559cb2fb 8744 int top_range
d9cdbb3d 8745 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8746
8747 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8748
8749 if (! NILP (bar->dragging))
8750 win_y -= XINT (bar->dragging);
8751
8752 if (win_y < 0)
8753 win_y = 0;
8754 if (win_y > top_range)
8755 win_y = top_range;
8756
334208b7 8757 *fp = f;
7a13e894 8758 *bar_window = bar->window;
559cb2fb
JB
8759
8760 if (! NILP (bar->dragging))
8761 *part = scroll_bar_handle;
8762 else if (win_y < XINT (bar->start))
8763 *part = scroll_bar_above_handle;
8764 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8765 *part = scroll_bar_handle;
8766 else
8767 *part = scroll_bar_below_handle;
12ba150f 8768
e0c1aef2
KH
8769 XSETINT (*x, win_y);
8770 XSETINT (*y, top_range);
12ba150f 8771
39d8bb4d 8772 f->mouse_moved = 0;
559cb2fb
JB
8773 last_mouse_scroll_bar = Qnil;
8774 }
12ba150f 8775
559cb2fb 8776 *time = last_mouse_movement_time;
cf7cb199 8777
cf7cb199 8778 UNBLOCK_INPUT;
12ba150f
JB
8779}
8780
f451eb13 8781
dbc4e1c1 8782/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8783 background colors, and the scroll bars may need to be redrawn.
8784 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8785 redraw them. */
8786
dfcf069d 8787void
ab648270 8788x_scroll_bar_clear (f)
dbc4e1c1
JB
8789 FRAME_PTR f;
8790{
06a2c219 8791#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8792 Lisp_Object bar;
8793
b80c363e
RS
8794 /* We can have scroll bars even if this is 0,
8795 if we just turned off scroll bar mode.
8796 But in that case we should not clear them. */
8797 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8798 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8799 bar = XSCROLL_BAR (bar)->next)
8800 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8801 0, 0, 0, 0, True);
06a2c219 8802#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8803}
8804
06a2c219 8805/* This processes Expose events from the menu-bar specific X event
19126e11 8806 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8807 when handling menu-bar or pop-up items. */
3afe33e7 8808
06a2c219 8809int
3afe33e7
RS
8810process_expose_from_menu (event)
8811 XEvent event;
8812{
8813 FRAME_PTR f;
19126e11 8814 struct x_display_info *dpyinfo;
06a2c219 8815 int frame_exposed_p = 0;
3afe33e7 8816
f94397b5
KH
8817 BLOCK_INPUT;
8818
19126e11
KH
8819 dpyinfo = x_display_info_for_display (event.xexpose.display);
8820 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8821 if (f)
8822 {
8823 if (f->async_visible == 0)
8824 {
8825 f->async_visible = 1;
8826 f->async_iconified = 0;
06c488fd 8827 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8828 SET_FRAME_GARBAGED (f);
8829 }
8830 else
8831 {
06a2c219
GM
8832 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8833 event.xexpose.x, event.xexpose.y,
8834 event.xexpose.width, event.xexpose.height);
8835 frame_exposed_p = 1;
3afe33e7
RS
8836 }
8837 }
8838 else
8839 {
8840 struct scroll_bar *bar
8841 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8842
3afe33e7
RS
8843 if (bar)
8844 x_scroll_bar_expose (bar, &event);
8845 }
f94397b5
KH
8846
8847 UNBLOCK_INPUT;
06a2c219 8848 return frame_exposed_p;
3afe33e7 8849}
09756a85
RS
8850\f
8851/* Define a queue to save up SelectionRequest events for later handling. */
8852
8853struct selection_event_queue
8854 {
8855 XEvent event;
8856 struct selection_event_queue *next;
8857 };
8858
8859static struct selection_event_queue *queue;
8860
8861/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8862
09756a85
RS
8863static int x_queue_selection_requests;
8864
8865/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8866
09756a85 8867static void
334208b7
RS
8868x_queue_event (f, event)
8869 FRAME_PTR f;
09756a85
RS
8870 XEvent *event;
8871{
8872 struct selection_event_queue *queue_tmp
06a2c219 8873 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8874
58769bee 8875 if (queue_tmp != NULL)
09756a85
RS
8876 {
8877 queue_tmp->event = *event;
8878 queue_tmp->next = queue;
8879 queue = queue_tmp;
8880 }
8881}
8882
8883/* Take all the queued events and put them back
8884 so that they get processed afresh. */
8885
8886static void
db3906fd
RS
8887x_unqueue_events (display)
8888 Display *display;
09756a85 8889{
58769bee 8890 while (queue != NULL)
09756a85
RS
8891 {
8892 struct selection_event_queue *queue_tmp = queue;
db3906fd 8893 XPutBackEvent (display, &queue_tmp->event);
09756a85 8894 queue = queue_tmp->next;
06a2c219 8895 xfree ((char *)queue_tmp);
09756a85
RS
8896 }
8897}
8898
8899/* Start queuing SelectionRequest events. */
8900
8901void
db3906fd
RS
8902x_start_queuing_selection_requests (display)
8903 Display *display;
09756a85
RS
8904{
8905 x_queue_selection_requests++;
8906}
8907
8908/* Stop queuing SelectionRequest events. */
8909
8910void
db3906fd
RS
8911x_stop_queuing_selection_requests (display)
8912 Display *display;
09756a85
RS
8913{
8914 x_queue_selection_requests--;
db3906fd 8915 x_unqueue_events (display);
09756a85 8916}
f451eb13
JB
8917\f
8918/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8919
06a2c219 8920/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8921 but we have to put it out here, since static variables within functions
8922 sometimes don't work. */
06a2c219 8923
dc6f92b8
JB
8924static Time enter_timestamp;
8925
11edeb03 8926/* This holds the state XLookupString needs to implement dead keys
58769bee 8927 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8928 says that a portable program can't use this, but Stephen Gildea assures
8929 me that letting the compiler initialize it to zeros will work okay.
8930
8931 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8932 given for enter_time stamp, above. */
8933
11edeb03
JB
8934static XComposeStatus compose_status;
8935
10e6549c
RS
8936/* Record the last 100 characters stored
8937 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8938
2224b905
RS
8939static int temp_index;
8940static short temp_buffer[100];
10e6549c 8941
7a13e894
RS
8942/* Set this to nonzero to fake an "X I/O error"
8943 on a particular display. */
06a2c219 8944
7a13e894
RS
8945struct x_display_info *XTread_socket_fake_io_error;
8946
2224b905
RS
8947/* When we find no input here, we occasionally do a no-op command
8948 to verify that the X server is still running and we can still talk with it.
8949 We try all the open displays, one by one.
8950 This variable is used for cycling thru the displays. */
06a2c219 8951
2224b905
RS
8952static struct x_display_info *next_noop_dpyinfo;
8953
06a2c219
GM
8954#define SET_SAVED_MENU_EVENT(size) \
8955 do \
8956 { \
8957 if (f->output_data.x->saved_menu_event == 0) \
8958 f->output_data.x->saved_menu_event \
8959 = (XEvent *) xmalloc (sizeof (XEvent)); \
8960 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8961 if (numchars >= 1) \
8962 { \
8963 bufp->kind = menu_bar_activate_event; \
8964 XSETFRAME (bufp->frame_or_window, f); \
8965 bufp++; \
8966 count++; \
8967 numchars--; \
8968 } \
8969 } \
8970 while (0)
8971
8805890a 8972#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 8973#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 8974
dc6f92b8
JB
8975/* Read events coming from the X server.
8976 This routine is called by the SIGIO handler.
8977 We return as soon as there are no more events to be read.
8978
8979 Events representing keys are stored in buffer BUFP,
8980 which can hold up to NUMCHARS characters.
8981 We return the number of characters stored into the buffer,
8982 thus pretending to be `read'.
8983
dc6f92b8
JB
8984 EXPECTED is nonzero if the caller knows input is available. */
8985
7c5283e4 8986int
f66868ba 8987XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 8988 register int sd;
8805890a
KH
8989 /* register */ struct input_event *bufp;
8990 /* register */ int numchars;
dc6f92b8
JB
8991 int expected;
8992{
8993 int count = 0;
8994 int nbytes = 0;
dc6f92b8 8995 XEvent event;
f676886a 8996 struct frame *f;
66f55a9d 8997 int event_found = 0;
334208b7 8998 struct x_display_info *dpyinfo;
dc6f92b8 8999
9ac0d9e0 9000 if (interrupt_input_blocked)
dc6f92b8 9001 {
9ac0d9e0 9002 interrupt_input_pending = 1;
dc6f92b8
JB
9003 return -1;
9004 }
9005
9ac0d9e0 9006 interrupt_input_pending = 0;
dc6f92b8 9007 BLOCK_INPUT;
c0a04927
RS
9008
9009 /* So people can tell when we have read the available input. */
9010 input_signal_count++;
9011
dc6f92b8 9012 if (numchars <= 0)
06a2c219 9013 abort (); /* Don't think this happens. */
dc6f92b8 9014
bde5503b
GM
9015 ++handling_signal;
9016
7a13e894
RS
9017 /* Find the display we are supposed to read input for.
9018 It's the one communicating on descriptor SD. */
9019 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
9020 {
9021#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 9022#ifdef FIOSNBIO
7a13e894
RS
9023 /* If available, Xlib uses FIOSNBIO to make the socket
9024 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 9025 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 9026 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 9027 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 9028#endif /* ! defined (FIOSNBIO) */
7a13e894 9029#endif
dc6f92b8 9030
7a13e894
RS
9031#if 0 /* This code can't be made to work, with multiple displays,
9032 and appears not to be used on any system any more.
9033 Also keyboard.c doesn't turn O_NDELAY on and off
9034 for X connections. */
dc6f92b8
JB
9035#ifndef SIGIO
9036#ifndef HAVE_SELECT
7a13e894
RS
9037 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
9038 {
9039 extern int read_alarm_should_throw;
9040 read_alarm_should_throw = 1;
9041 XPeekEvent (dpyinfo->display, &event);
9042 read_alarm_should_throw = 0;
9043 }
c118dd06
JB
9044#endif /* HAVE_SELECT */
9045#endif /* SIGIO */
7a13e894 9046#endif
dc6f92b8 9047
7a13e894
RS
9048 /* For debugging, this gives a way to fake an I/O error. */
9049 if (dpyinfo == XTread_socket_fake_io_error)
9050 {
9051 XTread_socket_fake_io_error = 0;
9052 x_io_error_quitter (dpyinfo->display);
9053 }
dc6f92b8 9054
06a2c219 9055 while (XPending (dpyinfo->display))
dc6f92b8 9056 {
7a13e894 9057 XNextEvent (dpyinfo->display, &event);
06a2c219 9058
531483fb 9059#ifdef HAVE_X_I18N
d1bc4182 9060 {
f2be1146
GM
9061 /* Filter events for the current X input method.
9062 XFilterEvent returns non-zero if the input method has
9063 consumed the event. We pass the frame's X window to
9064 XFilterEvent because that's the one for which the IC
9065 was created. */
f5d11644
GM
9066 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9067 event.xclient.window);
9068 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9069 break;
9070 }
0cd6403b 9071#endif
7a13e894
RS
9072 event_found = 1;
9073
9074 switch (event.type)
9075 {
9076 case ClientMessage:
c047688c 9077 {
7a13e894
RS
9078 if (event.xclient.message_type
9079 == dpyinfo->Xatom_wm_protocols
9080 && event.xclient.format == 32)
c047688c 9081 {
7a13e894
RS
9082 if (event.xclient.data.l[0]
9083 == dpyinfo->Xatom_wm_take_focus)
c047688c 9084 {
8c1a6a84
RS
9085 /* Use x_any_window_to_frame because this
9086 could be the shell widget window
9087 if the frame has no title bar. */
9088 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9089#ifdef HAVE_X_I18N
9090 /* Not quite sure this is needed -pd */
8c1a6a84 9091 if (f && FRAME_XIC (f))
6c183ba5
RS
9092 XSetICFocus (FRAME_XIC (f));
9093#endif
f1da8f06
GM
9094#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9095 instructs the WM to set the input focus automatically for
9096 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9097 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9098 it has set the focus. So, XSetInputFocus below is not
9099 needed.
9100
9101 The call to XSetInputFocus below has also caused trouble. In
9102 cases where the XSetInputFocus done by the WM and the one
9103 below are temporally close (on a fast machine), the call
9104 below can generate additional FocusIn events which confuse
9105 Emacs. */
9106
bf7253f4
RS
9107 /* Since we set WM_TAKE_FOCUS, we must call
9108 XSetInputFocus explicitly. But not if f is null,
9109 since that might be an event for a deleted frame. */
7a13e894 9110 if (f)
bf7253f4
RS
9111 {
9112 Display *d = event.xclient.display;
9113 /* Catch and ignore errors, in case window has been
9114 iconified by a window manager such as GWM. */
9115 int count = x_catch_errors (d);
9116 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9117 /* The ICCCM says this is
9118 the only valid choice. */
9119 RevertToParent,
bf7253f4
RS
9120 event.xclient.data.l[1]);
9121 /* This is needed to detect the error
9122 if there is an error. */
9123 XSync (d, False);
9124 x_uncatch_errors (d, count);
9125 }
7a13e894 9126 /* Not certain about handling scroll bars here */
f1da8f06 9127#endif /* 0 */
c047688c 9128 }
7a13e894
RS
9129 else if (event.xclient.data.l[0]
9130 == dpyinfo->Xatom_wm_save_yourself)
9131 {
9132 /* Save state modify the WM_COMMAND property to
06a2c219 9133 something which can reinstate us. This notifies
7a13e894
RS
9134 the session manager, who's looking for such a
9135 PropertyNotify. Can restart processing when
06a2c219 9136 a keyboard or mouse event arrives. */
7a13e894
RS
9137 if (numchars > 0)
9138 {
19126e11
KH
9139 f = x_top_window_to_frame (dpyinfo,
9140 event.xclient.window);
7a13e894
RS
9141
9142 /* This is just so we only give real data once
9143 for a single Emacs process. */
b86bd3dd 9144 if (f == SELECTED_FRAME ())
7a13e894
RS
9145 XSetCommand (FRAME_X_DISPLAY (f),
9146 event.xclient.window,
9147 initial_argv, initial_argc);
f000f5c5 9148 else if (f)
7a13e894
RS
9149 XSetCommand (FRAME_X_DISPLAY (f),
9150 event.xclient.window,
9151 0, 0);
9152 }
9153 }
9154 else if (event.xclient.data.l[0]
9155 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9156 {
19126e11
KH
9157 struct frame *f
9158 = x_any_window_to_frame (dpyinfo,
9159 event.xclient.window);
1fb20991 9160
7a13e894
RS
9161 if (f)
9162 {
9163 if (numchars == 0)
9164 abort ();
1fb20991 9165
7a13e894
RS
9166 bufp->kind = delete_window_event;
9167 XSETFRAME (bufp->frame_or_window, f);
9168 bufp++;
9169
9170 count += 1;
9171 numchars -= 1;
9172 }
1fb20991 9173 }
c047688c 9174 }
7a13e894
RS
9175 else if (event.xclient.message_type
9176 == dpyinfo->Xatom_wm_configure_denied)
9177 {
9178 }
9179 else if (event.xclient.message_type
9180 == dpyinfo->Xatom_wm_window_moved)
9181 {
9182 int new_x, new_y;
19126e11
KH
9183 struct frame *f
9184 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9185
7a13e894
RS
9186 new_x = event.xclient.data.s[0];
9187 new_y = event.xclient.data.s[1];
1fb20991 9188
7a13e894
RS
9189 if (f)
9190 {
7556890b
RS
9191 f->output_data.x->left_pos = new_x;
9192 f->output_data.x->top_pos = new_y;
7a13e894 9193 }
1fb20991 9194 }
0fdff6bb 9195#ifdef HACK_EDITRES
7a13e894
RS
9196 else if (event.xclient.message_type
9197 == dpyinfo->Xatom_editres)
9198 {
19126e11
KH
9199 struct frame *f
9200 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9201 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9202 &event, NULL);
7a13e894 9203 }
0fdff6bb 9204#endif /* HACK_EDITRES */
06a2c219
GM
9205 else if ((event.xclient.message_type
9206 == dpyinfo->Xatom_DONE)
9207 || (event.xclient.message_type
9208 == dpyinfo->Xatom_PAGE))
9209 {
9210 /* Ghostview job completed. Kill it. We could
9211 reply with "Next" if we received "Page", but we
9212 currently never do because we are interested in
9213 images, only, which should have 1 page. */
06a2c219
GM
9214 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9215 struct frame *f
9216 = x_window_to_frame (dpyinfo, event.xclient.window);
9217 x_kill_gs_process (pixmap, f);
9218 expose_frame (f, 0, 0, 0, 0);
9219 }
9220#ifdef USE_TOOLKIT_SCROLL_BARS
9221 /* Scroll bar callbacks send a ClientMessage from which
9222 we construct an input_event. */
9223 else if (event.xclient.message_type
9224 == dpyinfo->Xatom_Scrollbar)
9225 {
9226 x_scroll_bar_to_input_event (&event, bufp);
9227 ++bufp, ++count, --numchars;
9228 goto out;
9229 }
9230#endif /* USE_TOOLKIT_SCROLL_BARS */
9231 else
9232 goto OTHER;
7a13e894
RS
9233 }
9234 break;
dc6f92b8 9235
7a13e894 9236 case SelectionNotify:
3afe33e7 9237#ifdef USE_X_TOOLKIT
19126e11 9238 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9239 goto OTHER;
3afe33e7 9240#endif /* not USE_X_TOOLKIT */
dfcf069d 9241 x_handle_selection_notify (&event.xselection);
7a13e894 9242 break;
d56a553a 9243
06a2c219 9244 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9245#ifdef USE_X_TOOLKIT
19126e11 9246 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9247 goto OTHER;
3afe33e7 9248#endif /* USE_X_TOOLKIT */
7a13e894
RS
9249 {
9250 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9251
7a13e894
RS
9252 if (numchars == 0)
9253 abort ();
d56a553a 9254
7a13e894
RS
9255 bufp->kind = selection_clear_event;
9256 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9257 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9258 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9259 bufp->frame_or_window = Qnil;
7a13e894 9260 bufp++;
d56a553a 9261
7a13e894
RS
9262 count += 1;
9263 numchars -= 1;
9264 }
9265 break;
dc6f92b8 9266
06a2c219 9267 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9268#ifdef USE_X_TOOLKIT
19126e11 9269 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9270 goto OTHER;
3afe33e7 9271#endif /* USE_X_TOOLKIT */
7a13e894 9272 if (x_queue_selection_requests)
19126e11 9273 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9274 &event);
9275 else
9276 {
9277 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9278
7a13e894
RS
9279 if (numchars == 0)
9280 abort ();
9281
9282 bufp->kind = selection_request_event;
9283 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9284 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9285 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9286 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9287 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9288 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9289 bufp->frame_or_window = Qnil;
7a13e894
RS
9290 bufp++;
9291
9292 count += 1;
9293 numchars -= 1;
9294 }
9295 break;
9296
9297 case PropertyNotify:
3afe33e7 9298#ifdef USE_X_TOOLKIT
19126e11 9299 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9300 goto OTHER;
3afe33e7 9301#endif /* not USE_X_TOOLKIT */
dfcf069d 9302 x_handle_property_notify (&event.xproperty);
7a13e894 9303 break;
dc6f92b8 9304
7a13e894 9305 case ReparentNotify:
19126e11 9306 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9307 if (f)
9308 {
9309 int x, y;
7556890b 9310 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9311 x_real_positions (f, &x, &y);
7556890b
RS
9312 f->output_data.x->left_pos = x;
9313 f->output_data.x->top_pos = y;
7a13e894
RS
9314 }
9315 break;
3bd330d4 9316
7a13e894 9317 case Expose:
19126e11 9318 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9319 if (f)
dc6f92b8 9320 {
7a13e894
RS
9321 if (f->async_visible == 0)
9322 {
9323 f->async_visible = 1;
9324 f->async_iconified = 0;
06c488fd 9325 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9326 SET_FRAME_GARBAGED (f);
9327 }
9328 else
06a2c219
GM
9329 expose_frame (x_window_to_frame (dpyinfo,
9330 event.xexpose.window),
9331 event.xexpose.x, event.xexpose.y,
9332 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9333 }
9334 else
7a13e894 9335 {
06a2c219
GM
9336#ifdef USE_TOOLKIT_SCROLL_BARS
9337 /* Dispatch event to the widget. */
9338 goto OTHER;
9339#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9340 struct scroll_bar *bar
9341 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9342
7a13e894
RS
9343 if (bar)
9344 x_scroll_bar_expose (bar, &event);
3afe33e7 9345#ifdef USE_X_TOOLKIT
7a13e894
RS
9346 else
9347 goto OTHER;
3afe33e7 9348#endif /* USE_X_TOOLKIT */
06a2c219 9349#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9350 }
9351 break;
dc6f92b8 9352
7a13e894
RS
9353 case GraphicsExpose: /* This occurs when an XCopyArea's
9354 source area was obscured or not
9355 available.*/
19126e11 9356 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9357 if (f)
9358 {
06a2c219
GM
9359 expose_frame (f,
9360 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9361 event.xgraphicsexpose.width,
9362 event.xgraphicsexpose.height);
7a13e894 9363 }
3afe33e7 9364#ifdef USE_X_TOOLKIT
7a13e894
RS
9365 else
9366 goto OTHER;
3afe33e7 9367#endif /* USE_X_TOOLKIT */
7a13e894 9368 break;
dc6f92b8 9369
7a13e894 9370 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9371 source area was completely
9372 available */
7a13e894 9373 break;
dc6f92b8 9374
7a13e894 9375 case UnmapNotify:
06a2c219
GM
9376 /* Redo the mouse-highlight after the tooltip has gone. */
9377 if (event.xmap.window == tip_window)
9378 {
9379 tip_window = 0;
9380 redo_mouse_highlight ();
9381 }
9382
91ea2a7a 9383 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9384 if (f) /* F may no longer exist if
9385 the frame was deleted. */
9386 {
9387 /* While a frame is unmapped, display generation is
9388 disabled; you don't want to spend time updating a
9389 display that won't ever be seen. */
9390 f->async_visible = 0;
9391 /* We can't distinguish, from the event, whether the window
9392 has become iconified or invisible. So assume, if it
9393 was previously visible, than now it is iconified.
1aa6072f
RS
9394 But x_make_frame_invisible clears both
9395 the visible flag and the iconified flag;
9396 and that way, we know the window is not iconified now. */
7a13e894 9397 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9398 {
9399 f->async_iconified = 1;
bddd097c 9400
1aa6072f
RS
9401 bufp->kind = iconify_event;
9402 XSETFRAME (bufp->frame_or_window, f);
9403 bufp++;
9404 count++;
9405 numchars--;
9406 }
7a13e894 9407 }
7a13e894 9408 goto OTHER;
dc6f92b8 9409
7a13e894 9410 case MapNotify:
06a2c219
GM
9411 if (event.xmap.window == tip_window)
9412 /* The tooltip has been drawn already. Avoid
9413 the SET_FRAME_GARBAGED below. */
9414 goto OTHER;
9415
9416 /* We use x_top_window_to_frame because map events can
9417 come for sub-windows and they don't mean that the
9418 frame is visible. */
19126e11 9419 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9420 if (f)
9421 {
9422 f->async_visible = 1;
9423 f->async_iconified = 0;
06c488fd 9424 f->output_data.x->has_been_visible = 1;
dc6f92b8 9425
7a13e894
RS
9426 /* wait_reading_process_input will notice this and update
9427 the frame's display structures. */
9428 SET_FRAME_GARBAGED (f);
bddd097c 9429
d806e720
RS
9430 if (f->iconified)
9431 {
9432 bufp->kind = deiconify_event;
9433 XSETFRAME (bufp->frame_or_window, f);
9434 bufp++;
9435 count++;
9436 numchars--;
9437 }
e73ec6fa 9438 else if (! NILP (Vframe_list)
8e713be6 9439 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9440 /* Force a redisplay sooner or later
9441 to update the frame titles
9442 in case this is the second frame. */
9443 record_asynch_buffer_change ();
7a13e894 9444 }
7a13e894 9445 goto OTHER;
dc6f92b8 9446
7a13e894 9447 case KeyPress:
19126e11 9448 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9449
06a2c219
GM
9450#ifdef USE_MOTIF
9451 /* I couldn't find a way to prevent LessTif scroll bars
9452 from consuming key events. */
9453 if (f == 0)
9454 {
9455 Widget widget = XtWindowToWidget (dpyinfo->display,
9456 event.xkey.window);
9457 if (widget && XmIsScrollBar (widget))
9458 {
9459 widget = XtParent (widget);
9460 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9461 }
9462 }
9463#endif /* USE_MOTIF */
9464
7a13e894
RS
9465 if (f != 0)
9466 {
9467 KeySym keysym, orig_keysym;
9468 /* al%imercury@uunet.uu.net says that making this 81 instead of
9469 80 fixed a bug whereby meta chars made his Emacs hang. */
9470 unsigned char copy_buffer[81];
9471 int modifiers;
64bb1782 9472
7a13e894
RS
9473 event.xkey.state
9474 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9475 extra_keyboard_modifiers);
9476 modifiers = event.xkey.state;
3a2712f9 9477
7a13e894 9478 /* This will have to go some day... */
752a043f 9479
7a13e894
RS
9480 /* make_lispy_event turns chars into control chars.
9481 Don't do it here because XLookupString is too eager. */
9482 event.xkey.state &= ~ControlMask;
5d46f928
RS
9483 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9484 | dpyinfo->super_mod_mask
9485 | dpyinfo->hyper_mod_mask
9486 | dpyinfo->alt_mod_mask);
9487
1cf4a0d1
RS
9488 /* In case Meta is ComposeCharacter,
9489 clear its status. According to Markus Ehrnsperger
9490 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9491 this enables ComposeCharacter to work whether or
9492 not it is combined with Meta. */
9493 if (modifiers & dpyinfo->meta_mod_mask)
9494 bzero (&compose_status, sizeof (compose_status));
9495
6c183ba5
RS
9496#ifdef HAVE_X_I18N
9497 if (FRAME_XIC (f))
9498 {
f5d11644
GM
9499 unsigned char *copy_bufptr = copy_buffer;
9500 int copy_bufsiz = sizeof (copy_buffer);
9501 Status status_return;
9502
6c183ba5 9503 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9504 &event.xkey, copy_bufptr,
9505 copy_bufsiz, &keysym,
6c183ba5 9506 &status_return);
f5d11644
GM
9507 if (status_return == XBufferOverflow)
9508 {
9509 copy_bufsiz = nbytes + 1;
9510 copy_bufptr = (char *) alloca (copy_bufsiz);
9511 nbytes = XmbLookupString (FRAME_XIC (f),
9512 &event.xkey, copy_bufptr,
9513 copy_bufsiz, &keysym,
9514 &status_return);
9515 }
9516
1decb680
PE
9517 if (status_return == XLookupNone)
9518 break;
9519 else if (status_return == XLookupChars)
fdd9d55e
GM
9520 {
9521 keysym = NoSymbol;
9522 modifiers = 0;
9523 }
1decb680
PE
9524 else if (status_return != XLookupKeySym
9525 && status_return != XLookupBoth)
9526 abort ();
6c183ba5
RS
9527 }
9528 else
9529 nbytes = XLookupString (&event.xkey, copy_buffer,
9530 80, &keysym, &compose_status);
9531#else
0299d313
RS
9532 nbytes = XLookupString (&event.xkey, copy_buffer,
9533 80, &keysym, &compose_status);
6c183ba5 9534#endif
dc6f92b8 9535
7a13e894 9536 orig_keysym = keysym;
55123275 9537
7a13e894
RS
9538 if (numchars > 1)
9539 {
9540 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9541 || keysym == XK_Delete
1097aea0 9542#ifdef XK_ISO_Left_Tab
441affdb 9543 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9544#endif
852bff8f 9545 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9546 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9547 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9548#ifdef HPUX
7a13e894
RS
9549 /* This recognizes the "extended function keys".
9550 It seems there's no cleaner way.
9551 Test IsModifierKey to avoid handling mode_switch
9552 incorrectly. */
9553 || ((unsigned) (keysym) >= XK_Select
9554 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9555#endif
9556#ifdef XK_dead_circumflex
7a13e894 9557 || orig_keysym == XK_dead_circumflex
69388238
RS
9558#endif
9559#ifdef XK_dead_grave
7a13e894 9560 || orig_keysym == XK_dead_grave
69388238
RS
9561#endif
9562#ifdef XK_dead_tilde
7a13e894 9563 || orig_keysym == XK_dead_tilde
69388238
RS
9564#endif
9565#ifdef XK_dead_diaeresis
7a13e894 9566 || orig_keysym == XK_dead_diaeresis
69388238
RS
9567#endif
9568#ifdef XK_dead_macron
7a13e894 9569 || orig_keysym == XK_dead_macron
69388238
RS
9570#endif
9571#ifdef XK_dead_degree
7a13e894 9572 || orig_keysym == XK_dead_degree
69388238
RS
9573#endif
9574#ifdef XK_dead_acute
7a13e894 9575 || orig_keysym == XK_dead_acute
69388238
RS
9576#endif
9577#ifdef XK_dead_cedilla
7a13e894 9578 || orig_keysym == XK_dead_cedilla
69388238
RS
9579#endif
9580#ifdef XK_dead_breve
7a13e894 9581 || orig_keysym == XK_dead_breve
69388238
RS
9582#endif
9583#ifdef XK_dead_ogonek
7a13e894 9584 || orig_keysym == XK_dead_ogonek
69388238
RS
9585#endif
9586#ifdef XK_dead_caron
7a13e894 9587 || orig_keysym == XK_dead_caron
69388238
RS
9588#endif
9589#ifdef XK_dead_doubleacute
7a13e894 9590 || orig_keysym == XK_dead_doubleacute
69388238
RS
9591#endif
9592#ifdef XK_dead_abovedot
7a13e894 9593 || orig_keysym == XK_dead_abovedot
c34790e0 9594#endif
7a13e894
RS
9595 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9596 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9597 /* Any "vendor-specific" key is ok. */
9598 || (orig_keysym & (1 << 28)))
9599 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9600#ifndef HAVE_X11R5
9601#ifdef XK_Mode_switch
7a13e894 9602 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9603#endif
9604#ifdef XK_Num_Lock
7a13e894 9605 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9606#endif
9607#endif /* not HAVE_X11R5 */
7a13e894 9608 ))
dc6f92b8 9609 {
10e6549c
RS
9610 if (temp_index == sizeof temp_buffer / sizeof (short))
9611 temp_index = 0;
7a13e894
RS
9612 temp_buffer[temp_index++] = keysym;
9613 bufp->kind = non_ascii_keystroke;
9614 bufp->code = keysym;
e0c1aef2 9615 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
9616 bufp->modifiers
9617 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9618 modifiers);
1113d9db 9619 bufp->timestamp = event.xkey.time;
dc6f92b8 9620 bufp++;
7a13e894
RS
9621 count++;
9622 numchars--;
dc6f92b8 9623 }
7a13e894
RS
9624 else if (numchars > nbytes)
9625 {
9626 register int i;
9627
9628 for (i = 0; i < nbytes; i++)
9629 {
9630 if (temp_index == sizeof temp_buffer / sizeof (short))
9631 temp_index = 0;
9632 temp_buffer[temp_index++] = copy_buffer[i];
9633 bufp->kind = ascii_keystroke;
9634 bufp->code = copy_buffer[i];
9635 XSETFRAME (bufp->frame_or_window, f);
9636 bufp->modifiers
9637 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9638 modifiers);
9639 bufp->timestamp = event.xkey.time;
9640 bufp++;
9641 }
9642
9643 count += nbytes;
9644 numchars -= nbytes;
1decb680
PE
9645
9646 if (keysym == NoSymbol)
9647 break;
7a13e894
RS
9648 }
9649 else
9650 abort ();
dc6f92b8 9651 }
10e6549c
RS
9652 else
9653 abort ();
dc6f92b8 9654 }
59ddecde
GM
9655#ifdef HAVE_X_I18N
9656 /* Don't dispatch this event since XtDispatchEvent calls
9657 XFilterEvent, and two calls in a row may freeze the
9658 client. */
9659 break;
9660#else
717ca130 9661 goto OTHER;
59ddecde 9662#endif
f451eb13 9663
f5d11644 9664 case KeyRelease:
59ddecde
GM
9665#ifdef HAVE_X_I18N
9666 /* Don't dispatch this event since XtDispatchEvent calls
9667 XFilterEvent, and two calls in a row may freeze the
9668 client. */
9669 break;
9670#else
f5d11644 9671 goto OTHER;
59ddecde 9672#endif
f5d11644 9673
7a13e894 9674 /* Here's a possible interpretation of the whole
06a2c219
GM
9675 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9676 you get a FocusIn event, you have to get a FocusOut
9677 event before you relinquish the focus. If you
9678 haven't received a FocusIn event, then a mere
9679 LeaveNotify is enough to free you. */
f451eb13 9680
7a13e894 9681 case EnterNotify:
06a2c219
GM
9682 {
9683 int from_menu_bar_p = 0;
9684
9685 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9686
9687#ifdef LESSTIF_VERSION
9688 /* When clicking outside of a menu bar popup to close
9689 it, we get a FocusIn/ EnterNotify sequence of
9690 events. The flag event.xcrossing.focus is not set
9691 in the EnterNotify event of that sequence because
9692 the focus is in the menu bar,
9693 event.xcrossing.window is the frame's X window.
9694 Unconditionally setting the focus frame to null in
9695 this case is not the right thing, because no event
9696 follows that could set the focus frame to the right
9697 value.
9698
9699 This could be a LessTif bug, but I wasn't able to
9700 reproduce the behavior in a simple test program.
9701
9702 (gerd, LessTif 0.88.1). */
9703
9704 if (!event.xcrossing.focus
9705 && f
9706 && f->output_data.x->menubar_widget)
9707 {
9708 Window focus;
9709 int revert;
9710
9711 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9712 if (focus == XtWindow (f->output_data.x->menubar_widget))
9713 from_menu_bar_p = 1;
9714 }
9715#endif /* LESSTIF_VERSION */
6d4238f3 9716
06a2c219
GM
9717 if (event.xcrossing.focus || from_menu_bar_p)
9718 {
9719 /* Avoid nasty pop/raise loops. */
9720 if (f && (!(f->auto_raise)
9721 || !(f->auto_lower)
9722 || (event.xcrossing.time - enter_timestamp) > 500))
9723 {
9724 x_new_focus_frame (dpyinfo, f);
9725 enter_timestamp = event.xcrossing.time;
9726 }
9727 }
9728 else if (f == dpyinfo->x_focus_frame)
9729 x_new_focus_frame (dpyinfo, 0);
9730
9731 /* EnterNotify counts as mouse movement,
9732 so update things that depend on mouse position. */
9733 if (f && !f->output_data.x->busy_p)
9734 note_mouse_movement (f, &event.xmotion);
9735 goto OTHER;
9736 }
dc6f92b8 9737
7a13e894 9738 case FocusIn:
19126e11 9739 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9740 if (event.xfocus.detail != NotifyPointer)
0f941935 9741 dpyinfo->x_focus_event_frame = f;
7a13e894 9742 if (f)
eb72635f
GM
9743 {
9744 x_new_focus_frame (dpyinfo, f);
9745
9746 /* Don't stop displaying the initial startup message
9747 for a switch-frame event we don't need. */
9748 if (GC_NILP (Vterminal_frame)
9749 && GC_CONSP (Vframe_list)
9750 && !GC_NILP (XCDR (Vframe_list)))
9751 {
9752 bufp->kind = FOCUS_IN_EVENT;
9753 XSETFRAME (bufp->frame_or_window, f);
9754 ++bufp, ++count, --numchars;
9755 }
9756 }
f9e24cb9 9757
6c183ba5
RS
9758#ifdef HAVE_X_I18N
9759 if (f && FRAME_XIC (f))
9760 XSetICFocus (FRAME_XIC (f));
9761#endif
9762
7a13e894 9763 goto OTHER;
10c5e63d 9764
7a13e894 9765 case LeaveNotify:
19126e11 9766 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9767 if (f)
10c5e63d 9768 {
06a2c219
GM
9769 Lisp_Object frame;
9770 int from_menu_bar_p = 0;
9771
7a13e894 9772 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9773 {
9774 /* If we move outside the frame, then we're
9775 certainly no longer on any text in the frame. */
9776 clear_mouse_face (dpyinfo);
9777 dpyinfo->mouse_face_mouse_frame = 0;
9778 }
9779
9780 /* Generate a nil HELP_EVENT to cancel a help-echo.
9781 Do it only if there's something to cancel.
9782 Otherwise, the startup message is cleared when
9783 the mouse leaves the frame. */
9784 if (any_help_event_p)
9785 {
9786 XSETFRAME (frame, f);
9787 bufp->kind = HELP_EVENT;
9788 bufp->frame_or_window = Fcons (frame, Qnil);
9789 ++bufp, ++count, --numchars;
9790 }
7a13e894 9791
06a2c219
GM
9792#ifdef LESSTIF_VERSION
9793 /* Please see the comment at the start of the
9794 EnterNotify case. */
9795 if (!event.xcrossing.focus
9796 && f->output_data.x->menubar_widget)
9797 {
9798 Window focus;
9799 int revert;
9800 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9801 if (focus == XtWindow (f->output_data.x->menubar_widget))
9802 from_menu_bar_p = 1;
9803 }
9804#endif /* LESSTIF_VERSION */
9805
9806 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9807 x_mouse_leave (dpyinfo);
10c5e63d 9808 else
7a13e894 9809 {
0f941935
KH
9810 if (f == dpyinfo->x_focus_event_frame)
9811 dpyinfo->x_focus_event_frame = 0;
9812 if (f == dpyinfo->x_focus_frame)
9813 x_new_focus_frame (dpyinfo, 0);
7a13e894 9814 }
10c5e63d 9815 }
7a13e894 9816 goto OTHER;
dc6f92b8 9817
7a13e894 9818 case FocusOut:
19126e11 9819 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9820 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9821 && f == dpyinfo->x_focus_event_frame)
9822 dpyinfo->x_focus_event_frame = 0;
9823 if (f && f == dpyinfo->x_focus_frame)
9824 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9825
6c183ba5
RS
9826#ifdef HAVE_X_I18N
9827 if (f && FRAME_XIC (f))
9828 XUnsetICFocus (FRAME_XIC (f));
9829#endif
9830
7a13e894 9831 goto OTHER;
dc6f92b8 9832
7a13e894 9833 case MotionNotify:
dc6f92b8 9834 {
06a2c219
GM
9835 previous_help_echo = help_echo;
9836 help_echo = Qnil;
9837
7a13e894
RS
9838 if (dpyinfo->grabbed && last_mouse_frame
9839 && FRAME_LIVE_P (last_mouse_frame))
9840 f = last_mouse_frame;
9841 else
19126e11 9842 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9843
7a13e894
RS
9844 if (f)
9845 note_mouse_movement (f, &event.xmotion);
9846 else
9847 {
e88b3c50 9848#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9849 struct scroll_bar *bar
9850 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9851
7a13e894
RS
9852 if (bar)
9853 x_scroll_bar_note_movement (bar, &event);
e88b3c50 9854#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 9855
06a2c219
GM
9856 /* If we move outside the frame, then we're
9857 certainly no longer on any text in the frame. */
7a13e894
RS
9858 clear_mouse_face (dpyinfo);
9859 }
06a2c219
GM
9860
9861 /* If the contents of the global variable help_echo
9862 has changed, generate a HELP_EVENT. */
b7e80413
SM
9863 if (!NILP (help_echo)
9864 || !NILP (previous_help_echo))
06a2c219
GM
9865 {
9866 Lisp_Object frame;
9867
9868 if (f)
9869 XSETFRAME (frame, f);
9870 else
9871 frame = Qnil;
9872
9873 any_help_event_p = 1;
9874 bufp->kind = HELP_EVENT;
9875 bufp->frame_or_window = Fcons (frame, help_echo);
9876 ++bufp, ++count, --numchars;
9877 }
9878
9879 goto OTHER;
dc6f92b8 9880 }
dc6f92b8 9881
7a13e894 9882 case ConfigureNotify:
9829ddba
RS
9883 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9884 if (f)
af395ec1 9885 {
5c187dee 9886#ifndef USE_X_TOOLKIT
bf1b7b30
KH
9887 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9888 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 9889
2d7fc7e8
RS
9890 /* In the toolkit version, change_frame_size
9891 is called by the code that handles resizing
9892 of the EmacsFrame widget. */
7a13e894 9893
7a13e894
RS
9894 /* Even if the number of character rows and columns has
9895 not changed, the font size may have changed, so we need
9896 to check the pixel dimensions as well. */
9897 if (columns != f->width
9898 || rows != f->height
7556890b
RS
9899 || event.xconfigure.width != f->output_data.x->pixel_width
9900 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 9901 {
7d1e984f 9902 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 9903 SET_FRAME_GARBAGED (f);
e687d06e 9904 cancel_mouse_face (f);
7a13e894 9905 }
2d7fc7e8 9906#endif
af395ec1 9907
7556890b
RS
9908 f->output_data.x->pixel_width = event.xconfigure.width;
9909 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
9910
9911 /* What we have now is the position of Emacs's own window.
9912 Convert that to the position of the window manager window. */
dcb07ae9
RS
9913 x_real_positions (f, &f->output_data.x->left_pos,
9914 &f->output_data.x->top_pos);
9915
f5d11644
GM
9916#ifdef HAVE_X_I18N
9917 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9918 xic_set_statusarea (f);
9919#endif
9920
dcb07ae9
RS
9921 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9922 {
9923 /* Since the WM decorations come below top_pos now,
9924 we must put them below top_pos in the future. */
9925 f->output_data.x->win_gravity = NorthWestGravity;
9926 x_wm_set_size_hint (f, (long) 0, 0);
9927 }
8f08dc93
KH
9928#ifdef USE_MOTIF
9929 /* Some window managers pass (0,0) as the location of
9930 the window, and the Motif event handler stores it
9931 in the emacs widget, which messes up Motif menus. */
9932 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9933 {
9934 event.xconfigure.x = f->output_data.x->widget->core.x;
9935 event.xconfigure.y = f->output_data.x->widget->core.y;
9936 }
06a2c219 9937#endif /* USE_MOTIF */
7a13e894 9938 }
2d7fc7e8 9939 goto OTHER;
dc6f92b8 9940
7a13e894
RS
9941 case ButtonPress:
9942 case ButtonRelease:
9943 {
9944 /* If we decide we want to generate an event to be seen
9945 by the rest of Emacs, we put it here. */
9946 struct input_event emacs_event;
9ea173e8 9947 int tool_bar_p = 0;
06a2c219 9948
7a13e894 9949 emacs_event.kind = no_event;
7a13e894 9950 bzero (&compose_status, sizeof (compose_status));
9b07615b 9951
06a2c219
GM
9952 if (dpyinfo->grabbed
9953 && last_mouse_frame
9f67f20b
RS
9954 && FRAME_LIVE_P (last_mouse_frame))
9955 f = last_mouse_frame;
9956 else
2224b905 9957 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 9958
06a2c219
GM
9959 if (f)
9960 {
9ea173e8
GM
9961 /* Is this in the tool-bar? */
9962 if (WINDOWP (f->tool_bar_window)
9963 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
9964 {
9965 Lisp_Object window;
9966 int p, x, y;
9967
9968 x = event.xbutton.x;
9969 y = event.xbutton.y;
9970
9971 /* Set x and y. */
9972 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 9973 if (EQ (window, f->tool_bar_window))
06a2c219 9974 {
9ea173e8
GM
9975 x_handle_tool_bar_click (f, &event.xbutton);
9976 tool_bar_p = 1;
06a2c219
GM
9977 }
9978 }
9979
9ea173e8 9980 if (!tool_bar_p)
06a2c219
GM
9981 if (!dpyinfo->x_focus_frame
9982 || f == dpyinfo->x_focus_frame)
9983 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
9984 }
9985 else
9986 {
06a2c219 9987#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9988 struct scroll_bar *bar
9989 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 9990
7a13e894
RS
9991 if (bar)
9992 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 9993#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9994 }
9995
9996 if (event.type == ButtonPress)
9997 {
9998 dpyinfo->grabbed |= (1 << event.xbutton.button);
9999 last_mouse_frame = f;
edad46f6
KH
10000 /* Ignore any mouse motion that happened
10001 before this event; any subsequent mouse-movement
10002 Emacs events should reflect only motion after
10003 the ButtonPress. */
a00e91cd
KH
10004 if (f != 0)
10005 f->mouse_moved = 0;
06a2c219 10006
9ea173e8
GM
10007 if (!tool_bar_p)
10008 last_tool_bar_item = -1;
7a13e894 10009 }
3afe33e7
RS
10010 else
10011 {
7a13e894 10012 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 10013 }
23faf38f 10014
7a13e894
RS
10015 if (numchars >= 1 && emacs_event.kind != no_event)
10016 {
10017 bcopy (&emacs_event, bufp, sizeof (struct input_event));
10018 bufp++;
10019 count++;
10020 numchars--;
10021 }
3afe33e7
RS
10022
10023#ifdef USE_X_TOOLKIT
2224b905
RS
10024 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
10025 /* For a down-event in the menu bar,
10026 don't pass it to Xt right now.
10027 Instead, save it away
10028 and we will pass it to Xt from kbd_buffer_get_event.
10029 That way, we can run some Lisp code first. */
91375f8f
RS
10030 if (f && event.type == ButtonPress
10031 /* Verify the event is really within the menu bar
10032 and not just sent to it due to grabbing. */
10033 && event.xbutton.x >= 0
10034 && event.xbutton.x < f->output_data.x->pixel_width
10035 && event.xbutton.y >= 0
10036 && event.xbutton.y < f->output_data.x->menubar_height
10037 && event.xbutton.same_screen)
2224b905 10038 {
8805890a 10039 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
10040 XSETFRAME (last_mouse_press_frame, f);
10041 }
10042 else if (event.type == ButtonPress)
10043 {
10044 last_mouse_press_frame = Qnil;
30e671c3 10045 goto OTHER;
ce89ef46 10046 }
06a2c219 10047
2237cac9
RS
10048#ifdef USE_MOTIF /* This should do not harm for Lucid,
10049 but I am trying to be cautious. */
ce89ef46
RS
10050 else if (event.type == ButtonRelease)
10051 {
2237cac9 10052 if (!NILP (last_mouse_press_frame))
f10ded1c 10053 {
2237cac9
RS
10054 f = XFRAME (last_mouse_press_frame);
10055 if (f->output_data.x)
06a2c219 10056 SET_SAVED_BUTTON_EVENT;
f10ded1c 10057 }
06a2c219 10058 else
30e671c3 10059 goto OTHER;
2224b905 10060 }
2237cac9 10061#endif /* USE_MOTIF */
2224b905
RS
10062 else
10063 goto OTHER;
3afe33e7 10064#endif /* USE_X_TOOLKIT */
7a13e894
RS
10065 }
10066 break;
dc6f92b8 10067
7a13e894 10068 case CirculateNotify:
06a2c219
GM
10069 goto OTHER;
10070
7a13e894 10071 case CirculateRequest:
06a2c219
GM
10072 goto OTHER;
10073
10074 case VisibilityNotify:
10075 goto OTHER;
dc6f92b8 10076
7a13e894
RS
10077 case MappingNotify:
10078 /* Someone has changed the keyboard mapping - update the
10079 local cache. */
10080 switch (event.xmapping.request)
10081 {
10082 case MappingModifier:
10083 x_find_modifier_meanings (dpyinfo);
10084 /* This is meant to fall through. */
10085 case MappingKeyboard:
10086 XRefreshKeyboardMapping (&event.xmapping);
10087 }
7a13e894 10088 goto OTHER;
dc6f92b8 10089
7a13e894 10090 default:
7a13e894 10091 OTHER:
717ca130 10092#ifdef USE_X_TOOLKIT
7a13e894
RS
10093 BLOCK_INPUT;
10094 XtDispatchEvent (&event);
10095 UNBLOCK_INPUT;
3afe33e7 10096#endif /* USE_X_TOOLKIT */
7a13e894
RS
10097 break;
10098 }
dc6f92b8
JB
10099 }
10100 }
10101
06a2c219
GM
10102 out:;
10103
9a5196d0
RS
10104 /* On some systems, an X bug causes Emacs to get no more events
10105 when the window is destroyed. Detect that. (1994.) */
58769bee 10106 if (! event_found)
ef2a22d0 10107 {
ef2a22d0
RS
10108 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10109 One XNOOP in 100 loops will make Emacs terminate.
10110 B. Bretthauer, 1994 */
10111 x_noop_count++;
58769bee 10112 if (x_noop_count >= 100)
ef2a22d0
RS
10113 {
10114 x_noop_count=0;
2224b905
RS
10115
10116 if (next_noop_dpyinfo == 0)
10117 next_noop_dpyinfo = x_display_list;
10118
10119 XNoOp (next_noop_dpyinfo->display);
10120
10121 /* Each time we get here, cycle through the displays now open. */
10122 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10123 }
10124 }
502add23 10125
06a2c219 10126 /* If the focus was just given to an auto-raising frame,
0134a210 10127 raise it now. */
7a13e894 10128 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10129 if (pending_autoraise_frame)
10130 {
10131 x_raise_frame (pending_autoraise_frame);
10132 pending_autoraise_frame = 0;
10133 }
0134a210 10134
dc6f92b8 10135 UNBLOCK_INPUT;
bde5503b 10136 --handling_signal;
dc6f92b8
JB
10137 return count;
10138}
06a2c219
GM
10139
10140
10141
dc6f92b8 10142\f
06a2c219
GM
10143/***********************************************************************
10144 Text Cursor
10145 ***********************************************************************/
10146
10147/* Note if the text cursor of window W has been overwritten by a
10148 drawing operation that outputs N glyphs starting at HPOS in the
10149 line given by output_cursor.vpos. N < 0 means all the rest of the
10150 line after HPOS has been written. */
10151
10152static void
10153note_overwritten_text_cursor (w, hpos, n)
10154 struct window *w;
10155 int hpos, n;
10156{
10157 if (updated_area == TEXT_AREA
10158 && output_cursor.vpos == w->phys_cursor.vpos
10159 && hpos <= w->phys_cursor.hpos
10160 && (n < 0
10161 || hpos + n > w->phys_cursor.hpos))
10162 w->phys_cursor_on_p = 0;
10163}
f451eb13
JB
10164
10165
06a2c219
GM
10166/* Set clipping for output in glyph row ROW. W is the window in which
10167 we operate. GC is the graphics context to set clipping in.
10168 WHOLE_LINE_P non-zero means include the areas used for truncation
10169 mark display and alike in the clipping rectangle.
10170
10171 ROW may be a text row or, e.g., a mode line. Text rows must be
10172 clipped to the interior of the window dedicated to text display,
10173 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10174
10175static void
06a2c219
GM
10176x_clip_to_row (w, row, gc, whole_line_p)
10177 struct window *w;
10178 struct glyph_row *row;
10179 GC gc;
10180 int whole_line_p;
dc6f92b8 10181{
06a2c219
GM
10182 struct frame *f = XFRAME (WINDOW_FRAME (w));
10183 XRectangle clip_rect;
10184 int window_x, window_y, window_width, window_height;
dc6f92b8 10185
06a2c219 10186 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10187
06a2c219
GM
10188 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10189 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10190 clip_rect.y = max (clip_rect.y, window_y);
10191 clip_rect.width = window_width;
10192 clip_rect.height = row->visible_height;
5c1aae96 10193
06a2c219
GM
10194 /* If clipping to the whole line, including trunc marks, extend
10195 the rectangle to the left and increase its width. */
10196 if (whole_line_p)
10197 {
110859fc
GM
10198 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10199 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10200 }
5c1aae96 10201
06a2c219 10202 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10203}
10204
06a2c219
GM
10205
10206/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10207
10208static void
06a2c219
GM
10209x_draw_hollow_cursor (w, row)
10210 struct window *w;
10211 struct glyph_row *row;
dc6f92b8 10212{
06a2c219
GM
10213 struct frame *f = XFRAME (WINDOW_FRAME (w));
10214 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10215 Display *dpy = FRAME_X_DISPLAY (f);
10216 int x, y, wd, h;
10217 XGCValues xgcv;
10218 struct glyph *cursor_glyph;
10219 GC gc;
10220
10221 /* Compute frame-relative coordinates from window-relative
10222 coordinates. */
10223 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10224 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10225 + row->ascent - w->phys_cursor_ascent);
10226 h = row->height - 1;
10227
10228 /* Get the glyph the cursor is on. If we can't tell because
10229 the current matrix is invalid or such, give up. */
10230 cursor_glyph = get_phys_cursor_glyph (w);
10231 if (cursor_glyph == NULL)
dc6f92b8
JB
10232 return;
10233
06a2c219
GM
10234 /* Compute the width of the rectangle to draw. If on a stretch
10235 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10236 rectangle as wide as the glyph, but use a canonical character
10237 width instead. */
10238 wd = cursor_glyph->pixel_width - 1;
10239 if (cursor_glyph->type == STRETCH_GLYPH
10240 && !x_stretch_cursor_p)
10241 wd = min (CANON_X_UNIT (f), wd);
10242
10243 /* The foreground of cursor_gc is typically the same as the normal
10244 background color, which can cause the cursor box to be invisible. */
10245 xgcv.foreground = f->output_data.x->cursor_pixel;
10246 if (dpyinfo->scratch_cursor_gc)
10247 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10248 else
10249 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10250 GCForeground, &xgcv);
10251 gc = dpyinfo->scratch_cursor_gc;
10252
10253 /* Set clipping, draw the rectangle, and reset clipping again. */
10254 x_clip_to_row (w, row, gc, 0);
10255 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10256 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10257}
10258
06a2c219
GM
10259
10260/* Draw a bar cursor on window W in glyph row ROW.
10261
10262 Implementation note: One would like to draw a bar cursor with an
10263 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10264 Unfortunately, I didn't find a font yet that has this property set.
10265 --gerd. */
dc6f92b8
JB
10266
10267static void
f02d8aa0 10268x_draw_bar_cursor (w, row, width)
06a2c219
GM
10269 struct window *w;
10270 struct glyph_row *row;
f02d8aa0 10271 int width;
dc6f92b8 10272{
06a2c219
GM
10273 /* If cursor hpos is out of bounds, don't draw garbage. This can
10274 happen in mini-buffer windows when switching between echo area
10275 glyphs and mini-buffer. */
10276 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10277 {
10278 struct frame *f = XFRAME (w->frame);
10279 struct glyph *cursor_glyph;
10280 GC gc;
10281 int x;
10282 unsigned long mask;
10283 XGCValues xgcv;
10284 Display *dpy;
10285 Window window;
10286
10287 cursor_glyph = get_phys_cursor_glyph (w);
10288 if (cursor_glyph == NULL)
10289 return;
10290
10291 xgcv.background = f->output_data.x->cursor_pixel;
10292 xgcv.foreground = f->output_data.x->cursor_pixel;
10293 xgcv.graphics_exposures = 0;
10294 mask = GCForeground | GCBackground | GCGraphicsExposures;
10295 dpy = FRAME_X_DISPLAY (f);
10296 window = FRAME_X_WINDOW (f);
10297 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10298
10299 if (gc)
10300 XChangeGC (dpy, gc, mask, &xgcv);
10301 else
10302 {
10303 gc = XCreateGC (dpy, window, mask, &xgcv);
10304 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10305 }
10306
f02d8aa0
GM
10307 if (width < 0)
10308 width = f->output_data.x->cursor_width;
10309
06a2c219
GM
10310 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10311 x_clip_to_row (w, row, gc, 0);
10312 XFillRectangle (dpy, window, gc,
10313 x,
10314 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10315 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10316 row->height);
10317 XSetClipMask (dpy, gc, None);
10318 }
dc6f92b8
JB
10319}
10320
06a2c219
GM
10321
10322/* Clear the cursor of window W to background color, and mark the
10323 cursor as not shown. This is used when the text where the cursor
10324 is is about to be rewritten. */
10325
dc6f92b8 10326static void
06a2c219
GM
10327x_clear_cursor (w)
10328 struct window *w;
dc6f92b8 10329{
06a2c219
GM
10330 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10331 x_update_window_cursor (w, 0);
10332}
90e65f07 10333
dbc4e1c1 10334
06a2c219
GM
10335/* Draw the cursor glyph of window W in glyph row ROW. See the
10336 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10337
06a2c219
GM
10338static void
10339x_draw_phys_cursor_glyph (w, row, hl)
10340 struct window *w;
10341 struct glyph_row *row;
10342 enum draw_glyphs_face hl;
10343{
10344 /* If cursor hpos is out of bounds, don't draw garbage. This can
10345 happen in mini-buffer windows when switching between echo area
10346 glyphs and mini-buffer. */
10347 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10348 {
10349 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10350 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10351 hl, 0, 0, 0);
10352
10353 /* When we erase the cursor, and ROW is overlapped by other
10354 rows, make sure that these overlapping parts of other rows
10355 are redrawn. */
10356 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10357 {
10358 if (row > w->current_matrix->rows
10359 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10360 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10361
10362 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10363 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10364 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10365 }
10366 }
06a2c219 10367}
dbc4e1c1 10368
eea6af04 10369
06a2c219 10370/* Erase the image of a cursor of window W from the screen. */
eea6af04 10371
06a2c219
GM
10372static void
10373x_erase_phys_cursor (w)
10374 struct window *w;
10375{
10376 struct frame *f = XFRAME (w->frame);
10377 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10378 int hpos = w->phys_cursor.hpos;
10379 int vpos = w->phys_cursor.vpos;
10380 int mouse_face_here_p = 0;
10381 struct glyph_matrix *active_glyphs = w->current_matrix;
10382 struct glyph_row *cursor_row;
10383 struct glyph *cursor_glyph;
10384 enum draw_glyphs_face hl;
10385
10386 /* No cursor displayed or row invalidated => nothing to do on the
10387 screen. */
10388 if (w->phys_cursor_type == NO_CURSOR)
10389 goto mark_cursor_off;
10390
10391 /* VPOS >= active_glyphs->nrows means that window has been resized.
10392 Don't bother to erase the cursor. */
10393 if (vpos >= active_glyphs->nrows)
10394 goto mark_cursor_off;
10395
10396 /* If row containing cursor is marked invalid, there is nothing we
10397 can do. */
10398 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10399 if (!cursor_row->enabled_p)
10400 goto mark_cursor_off;
10401
10402 /* This can happen when the new row is shorter than the old one.
10403 In this case, either x_draw_glyphs or clear_end_of_line
10404 should have cleared the cursor. Note that we wouldn't be
10405 able to erase the cursor in this case because we don't have a
10406 cursor glyph at hand. */
10407 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10408 goto mark_cursor_off;
10409
10410 /* If the cursor is in the mouse face area, redisplay that when
10411 we clear the cursor. */
8801a864
KR
10412 if (! NILP (dpyinfo->mouse_face_window)
10413 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10414 && (vpos > dpyinfo->mouse_face_beg_row
10415 || (vpos == dpyinfo->mouse_face_beg_row
10416 && hpos >= dpyinfo->mouse_face_beg_col))
10417 && (vpos < dpyinfo->mouse_face_end_row
10418 || (vpos == dpyinfo->mouse_face_end_row
10419 && hpos < dpyinfo->mouse_face_end_col))
10420 /* Don't redraw the cursor's spot in mouse face if it is at the
10421 end of a line (on a newline). The cursor appears there, but
10422 mouse highlighting does not. */
10423 && cursor_row->used[TEXT_AREA] > hpos)
10424 mouse_face_here_p = 1;
10425
10426 /* Maybe clear the display under the cursor. */
10427 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10428 {
10429 int x;
045dee35 10430 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10431
06a2c219
GM
10432 cursor_glyph = get_phys_cursor_glyph (w);
10433 if (cursor_glyph == NULL)
10434 goto mark_cursor_off;
dbc4e1c1 10435
06a2c219
GM
10436 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10437
10438 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10439 x,
045dee35 10440 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10441 cursor_row->y)),
10442 cursor_glyph->pixel_width,
10443 cursor_row->visible_height,
10444 False);
dbc4e1c1 10445 }
06a2c219
GM
10446
10447 /* Erase the cursor by redrawing the character underneath it. */
10448 if (mouse_face_here_p)
10449 hl = DRAW_MOUSE_FACE;
10450 else if (cursor_row->inverse_p)
10451 hl = DRAW_INVERSE_VIDEO;
10452 else
10453 hl = DRAW_NORMAL_TEXT;
10454 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10455
06a2c219
GM
10456 mark_cursor_off:
10457 w->phys_cursor_on_p = 0;
10458 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10459}
10460
10461
06a2c219
GM
10462/* Display or clear cursor of window W. If ON is zero, clear the
10463 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10464 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10465
06a2c219
GM
10466void
10467x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10468 struct window *w;
10469 int on, hpos, vpos, x, y;
dbc4e1c1 10470{
06a2c219
GM
10471 struct frame *f = XFRAME (w->frame);
10472 int new_cursor_type;
f02d8aa0 10473 int new_cursor_width;
06a2c219
GM
10474 struct glyph_matrix *current_glyphs;
10475 struct glyph_row *glyph_row;
10476 struct glyph *glyph;
dbc4e1c1 10477
49d838ea 10478 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10479 windows and frames; in the latter case, the frame or window may
10480 be in the midst of changing its size, and x and y may be off the
10481 window. */
10482 if (! FRAME_VISIBLE_P (f)
10483 || FRAME_GARBAGED_P (f)
10484 || vpos >= w->current_matrix->nrows
10485 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10486 return;
10487
10488 /* If cursor is off and we want it off, return quickly. */
06a2c219 10489 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10490 return;
10491
06a2c219
GM
10492 current_glyphs = w->current_matrix;
10493 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10494 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10495
10496 /* If cursor row is not enabled, we don't really know where to
10497 display the cursor. */
10498 if (!glyph_row->enabled_p)
10499 {
10500 w->phys_cursor_on_p = 0;
10501 return;
10502 }
10503
10504 xassert (interrupt_input_blocked);
10505
10506 /* Set new_cursor_type to the cursor we want to be displayed. In a
10507 mini-buffer window, we want the cursor only to appear if we are
10508 reading input from this window. For the selected window, we want
10509 the cursor type given by the frame parameter. If explicitly
10510 marked off, draw no cursor. In all other cases, we want a hollow
10511 box cursor. */
f02d8aa0 10512 new_cursor_width = -1;
9b4a7047
GM
10513 if (cursor_in_echo_area
10514 && FRAME_HAS_MINIBUF_P (f)
10515 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10516 {
9b4a7047
GM
10517 if (w == XWINDOW (echo_area_window))
10518 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10519 else
10520 new_cursor_type = HOLLOW_BOX_CURSOR;
10521 }
06a2c219 10522 else
9b4a7047
GM
10523 {
10524 if (w != XWINDOW (selected_window)
10525 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10526 {
e55a0b79
GM
10527 extern int cursor_in_non_selected_windows;
10528
10529 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
9b4a7047
GM
10530 new_cursor_type = NO_CURSOR;
10531 else
10532 new_cursor_type = HOLLOW_BOX_CURSOR;
10533 }
10534 else if (w->cursor_off_p)
10535 new_cursor_type = NO_CURSOR;
10536 else
f02d8aa0
GM
10537 {
10538 struct buffer *b = XBUFFER (w->buffer);
10539
10540 if (EQ (b->cursor_type, Qt))
10541 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10542 else
10543 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10544 &new_cursor_width);
10545 }
9b4a7047 10546 }
06a2c219
GM
10547
10548 /* If cursor is currently being shown and we don't want it to be or
10549 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10550 erase it. */
06a2c219 10551 if (w->phys_cursor_on_p
dc6f92b8 10552 && (!on
06a2c219
GM
10553 || w->phys_cursor.x != x
10554 || w->phys_cursor.y != y
10555 || new_cursor_type != w->phys_cursor_type))
10556 x_erase_phys_cursor (w);
10557
10558 /* If the cursor is now invisible and we want it to be visible,
10559 display it. */
10560 if (on && !w->phys_cursor_on_p)
10561 {
10562 w->phys_cursor_ascent = glyph_row->ascent;
10563 w->phys_cursor_height = glyph_row->height;
10564
10565 /* Set phys_cursor_.* before x_draw_.* is called because some
10566 of them may need the information. */
10567 w->phys_cursor.x = x;
10568 w->phys_cursor.y = glyph_row->y;
10569 w->phys_cursor.hpos = hpos;
10570 w->phys_cursor.vpos = vpos;
10571 w->phys_cursor_type = new_cursor_type;
10572 w->phys_cursor_on_p = 1;
10573
10574 switch (new_cursor_type)
dc6f92b8 10575 {
06a2c219
GM
10576 case HOLLOW_BOX_CURSOR:
10577 x_draw_hollow_cursor (w, glyph_row);
10578 break;
10579
10580 case FILLED_BOX_CURSOR:
10581 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10582 break;
10583
10584 case BAR_CURSOR:
f02d8aa0 10585 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10586 break;
10587
10588 case NO_CURSOR:
10589 break;
dc6f92b8 10590
06a2c219
GM
10591 default:
10592 abort ();
10593 }
59ddecde
GM
10594
10595#ifdef HAVE_X_I18N
10596 if (w == XWINDOW (f->selected_window))
10597 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10598 xic_set_preeditarea (w, x, y);
10599#endif
dc6f92b8
JB
10600 }
10601
06a2c219 10602#ifndef XFlush
f676886a 10603 if (updating_frame != f)
334208b7 10604 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10605#endif
dc6f92b8
JB
10606}
10607
06a2c219
GM
10608
10609/* Display the cursor on window W, or clear it. X and Y are window
10610 relative pixel coordinates. HPOS and VPOS are glyph matrix
10611 positions. If W is not the selected window, display a hollow
10612 cursor. ON non-zero means display the cursor at X, Y which
10613 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10614
dfcf069d 10615void
06a2c219
GM
10616x_display_cursor (w, on, hpos, vpos, x, y)
10617 struct window *w;
10618 int on, hpos, vpos, x, y;
dc6f92b8 10619{
f94397b5 10620 BLOCK_INPUT;
06a2c219 10621 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10622 UNBLOCK_INPUT;
10623}
10624
06a2c219
GM
10625
10626/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10627 Don't change the cursor's position. */
10628
dfcf069d 10629void
06a2c219 10630x_update_cursor (f, on_p)
5d46f928 10631 struct frame *f;
5d46f928 10632{
06a2c219
GM
10633 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10634}
10635
10636
10637/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10638 in the window tree rooted at W. */
10639
10640static void
10641x_update_cursor_in_window_tree (w, on_p)
10642 struct window *w;
10643 int on_p;
10644{
10645 while (w)
10646 {
10647 if (!NILP (w->hchild))
10648 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10649 else if (!NILP (w->vchild))
10650 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10651 else
10652 x_update_window_cursor (w, on_p);
10653
10654 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10655 }
10656}
5d46f928 10657
f94397b5 10658
06a2c219
GM
10659/* Switch the display of W's cursor on or off, according to the value
10660 of ON. */
10661
10662static void
10663x_update_window_cursor (w, on)
10664 struct window *w;
10665 int on;
10666{
16b5d424
GM
10667 /* Don't update cursor in windows whose frame is in the process
10668 of being deleted. */
10669 if (w->current_matrix)
10670 {
10671 BLOCK_INPUT;
10672 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10673 w->phys_cursor.x, w->phys_cursor.y);
10674 UNBLOCK_INPUT;
10675 }
dc6f92b8 10676}
06a2c219
GM
10677
10678
10679
dc6f92b8
JB
10680\f
10681/* Icons. */
10682
f676886a 10683/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10684 when we get an expose event for it. */
dc6f92b8 10685
dfcf069d 10686void
f676886a
JB
10687refreshicon (f)
10688 struct frame *f;
dc6f92b8 10689{
06a2c219 10690 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10691}
10692
dbc4e1c1 10693/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10694
10695int
990ba854 10696x_bitmap_icon (f, file)
f676886a 10697 struct frame *f;
990ba854 10698 Lisp_Object file;
dc6f92b8 10699{
06a2c219 10700 int bitmap_id;
dc6f92b8 10701
c118dd06 10702 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10703 return 1;
10704
990ba854 10705 /* Free up our existing icon bitmap if any. */
7556890b
RS
10706 if (f->output_data.x->icon_bitmap > 0)
10707 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10708 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10709
10710 if (STRINGP (file))
7f2ae036
RS
10711 bitmap_id = x_create_bitmap_from_file (f, file);
10712 else
10713 {
990ba854 10714 /* Create the GNU bitmap if necessary. */
5bf01b68 10715 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10716 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10717 = x_create_bitmap_from_data (f, gnu_bits,
10718 gnu_width, gnu_height);
990ba854
RS
10719
10720 /* The first time we create the GNU bitmap,
06a2c219 10721 this increments the ref-count one extra time.
990ba854
RS
10722 As a result, the GNU bitmap is never freed.
10723 That way, we don't have to worry about allocating it again. */
334208b7 10724 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10725
334208b7 10726 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10727 }
10728
10729 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10730 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10731
10732 return 0;
10733}
10734
10735
1be2d067
KH
10736/* Make the x-window of frame F use a rectangle with text.
10737 Use ICON_NAME as the text. */
dc6f92b8
JB
10738
10739int
f676886a
JB
10740x_text_icon (f, icon_name)
10741 struct frame *f;
dc6f92b8
JB
10742 char *icon_name;
10743{
c118dd06 10744 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10745 return 1;
10746
1be2d067
KH
10747#ifdef HAVE_X11R4
10748 {
10749 XTextProperty text;
10750 text.value = (unsigned char *) icon_name;
10751 text.encoding = XA_STRING;
10752 text.format = 8;
10753 text.nitems = strlen (icon_name);
10754#ifdef USE_X_TOOLKIT
7556890b 10755 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10756 &text);
10757#else /* not USE_X_TOOLKIT */
10758 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10759#endif /* not USE_X_TOOLKIT */
10760 }
10761#else /* not HAVE_X11R4 */
10762 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10763#endif /* not HAVE_X11R4 */
58769bee 10764
7556890b
RS
10765 if (f->output_data.x->icon_bitmap > 0)
10766 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10767 f->output_data.x->icon_bitmap = 0;
b1c884c3 10768 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10769
10770 return 0;
10771}
10772\f
e99db5a1
RS
10773#define X_ERROR_MESSAGE_SIZE 200
10774
10775/* If non-nil, this should be a string.
10776 It means catch X errors and store the error message in this string. */
10777
10778static Lisp_Object x_error_message_string;
10779
10780/* An X error handler which stores the error message in
10781 x_error_message_string. This is called from x_error_handler if
10782 x_catch_errors is in effect. */
10783
06a2c219 10784static void
e99db5a1
RS
10785x_error_catcher (display, error)
10786 Display *display;
10787 XErrorEvent *error;
10788{
10789 XGetErrorText (display, error->error_code,
10790 XSTRING (x_error_message_string)->data,
10791 X_ERROR_MESSAGE_SIZE);
10792}
10793
10794/* Begin trapping X errors for display DPY. Actually we trap X errors
10795 for all displays, but DPY should be the display you are actually
10796 operating on.
10797
10798 After calling this function, X protocol errors no longer cause
10799 Emacs to exit; instead, they are recorded in the string
10800 stored in x_error_message_string.
10801
10802 Calling x_check_errors signals an Emacs error if an X error has
10803 occurred since the last call to x_catch_errors or x_check_errors.
10804
10805 Calling x_uncatch_errors resumes the normal error handling. */
10806
10807void x_check_errors ();
10808static Lisp_Object x_catch_errors_unwind ();
10809
10810int
10811x_catch_errors (dpy)
10812 Display *dpy;
10813{
10814 int count = specpdl_ptr - specpdl;
10815
10816 /* Make sure any errors from previous requests have been dealt with. */
10817 XSync (dpy, False);
10818
10819 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10820
10821 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10822 XSTRING (x_error_message_string)->data[0] = 0;
10823
10824 return count;
10825}
10826
10827/* Unbind the binding that we made to check for X errors. */
10828
10829static Lisp_Object
10830x_catch_errors_unwind (old_val)
10831 Lisp_Object old_val;
10832{
10833 x_error_message_string = old_val;
10834 return Qnil;
10835}
10836
10837/* If any X protocol errors have arrived since the last call to
10838 x_catch_errors or x_check_errors, signal an Emacs error using
10839 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10840
10841void
10842x_check_errors (dpy, format)
10843 Display *dpy;
10844 char *format;
10845{
10846 /* Make sure to catch any errors incurred so far. */
10847 XSync (dpy, False);
10848
10849 if (XSTRING (x_error_message_string)->data[0])
10850 error (format, XSTRING (x_error_message_string)->data);
10851}
10852
9829ddba
RS
10853/* Nonzero if we had any X protocol errors
10854 since we did x_catch_errors on DPY. */
e99db5a1
RS
10855
10856int
10857x_had_errors_p (dpy)
10858 Display *dpy;
10859{
10860 /* Make sure to catch any errors incurred so far. */
10861 XSync (dpy, False);
10862
10863 return XSTRING (x_error_message_string)->data[0] != 0;
10864}
10865
9829ddba
RS
10866/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10867
06a2c219 10868void
9829ddba
RS
10869x_clear_errors (dpy)
10870 Display *dpy;
10871{
10872 XSTRING (x_error_message_string)->data[0] = 0;
10873}
10874
e99db5a1
RS
10875/* Stop catching X protocol errors and let them make Emacs die.
10876 DPY should be the display that was passed to x_catch_errors.
10877 COUNT should be the value that was returned by
10878 the corresponding call to x_catch_errors. */
10879
10880void
10881x_uncatch_errors (dpy, count)
10882 Display *dpy;
10883 int count;
10884{
10885 unbind_to (count, Qnil);
10886}
10887
10888#if 0
10889static unsigned int x_wire_count;
10890x_trace_wire ()
10891{
10892 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10893}
10894#endif /* ! 0 */
10895
10896\f
10897/* Handle SIGPIPE, which can happen when the connection to a server
10898 simply goes away. SIGPIPE is handled by x_connection_signal.
10899 Don't need to do anything, because the write which caused the
10900 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 10901 which will do the appropriate cleanup for us. */
e99db5a1
RS
10902
10903static SIGTYPE
10904x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 10905 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
10906{
10907#ifdef USG
10908 /* USG systems forget handlers when they are used;
10909 must reestablish each time */
10910 signal (signalnum, x_connection_signal);
10911#endif /* USG */
10912}
10913\f
4746118a
JB
10914/* Handling X errors. */
10915
7a13e894 10916/* Handle the loss of connection to display DISPLAY. */
16bd92ea 10917
4746118a 10918static SIGTYPE
7a13e894
RS
10919x_connection_closed (display, error_message)
10920 Display *display;
10921 char *error_message;
4746118a 10922{
7a13e894
RS
10923 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10924 Lisp_Object frame, tail;
10925
6186a4a0
RS
10926 /* Indicate that this display is dead. */
10927
2e465cdd 10928#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 10929#ifdef USE_X_TOOLKIT
adabc3a9 10930 XtCloseDisplay (display);
2e465cdd 10931#endif
f613a4c8 10932#endif
adabc3a9 10933
9e80b57d
KR
10934 if (dpyinfo)
10935 dpyinfo->display = 0;
6186a4a0 10936
06a2c219 10937 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
10938 that are on the dead display. */
10939 FOR_EACH_FRAME (tail, frame)
10940 {
10941 Lisp_Object minibuf_frame;
10942 minibuf_frame
10943 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
10944 if (FRAME_X_P (XFRAME (frame))
10945 && FRAME_X_P (XFRAME (minibuf_frame))
10946 && ! EQ (frame, minibuf_frame)
10947 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
10948 Fdelete_frame (frame, Qt);
10949 }
10950
10951 /* Now delete all remaining frames on the dead display.
06a2c219 10952 We are now sure none of these is used as the mini-buffer
7a13e894
RS
10953 for another frame that we need to delete. */
10954 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
10955 if (FRAME_X_P (XFRAME (frame))
10956 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
10957 {
10958 /* Set this to t so that Fdelete_frame won't get confused
10959 trying to find a replacement. */
10960 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10961 Fdelete_frame (frame, Qt);
10962 }
7a13e894 10963
482a1bd2
KH
10964 if (dpyinfo)
10965 x_delete_display (dpyinfo);
7a13e894
RS
10966
10967 if (x_display_list == 0)
10968 {
f8d07b62 10969 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
10970 shut_down_emacs (0, 0, Qnil);
10971 exit (70);
10972 }
12ba150f 10973
7a13e894
RS
10974 /* Ordinary stack unwind doesn't deal with these. */
10975#ifdef SIGIO
10976 sigunblock (sigmask (SIGIO));
10977#endif
10978 sigunblock (sigmask (SIGALRM));
10979 TOTALLY_UNBLOCK_INPUT;
10980
aa4d9a9e 10981 clear_waiting_for_input ();
7a13e894 10982 error ("%s", error_message);
4746118a
JB
10983}
10984
7a13e894
RS
10985/* This is the usual handler for X protocol errors.
10986 It kills all frames on the display that we got the error for.
10987 If that was the only one, it prints an error message and kills Emacs. */
10988
06a2c219 10989static void
c118dd06
JB
10990x_error_quitter (display, error)
10991 Display *display;
10992 XErrorEvent *error;
10993{
7a13e894 10994 char buf[256], buf1[356];
dc6f92b8 10995
58769bee 10996 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 10997 original error handler. */
dc6f92b8 10998
c118dd06 10999 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 11000 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 11001 buf, error->request_code);
7a13e894 11002 x_connection_closed (display, buf1);
dc6f92b8
JB
11003}
11004
e99db5a1
RS
11005/* This is the first-level handler for X protocol errors.
11006 It calls x_error_quitter or x_error_catcher. */
7a13e894 11007
8922af5f 11008static int
e99db5a1 11009x_error_handler (display, error)
8922af5f 11010 Display *display;
e99db5a1 11011 XErrorEvent *error;
8922af5f 11012{
e99db5a1
RS
11013 if (! NILP (x_error_message_string))
11014 x_error_catcher (display, error);
11015 else
11016 x_error_quitter (display, error);
06a2c219 11017 return 0;
f9e24cb9 11018}
c118dd06 11019
e99db5a1
RS
11020/* This is the handler for X IO errors, always.
11021 It kills all frames on the display that we lost touch with.
11022 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 11023
c118dd06 11024static int
e99db5a1 11025x_io_error_quitter (display)
c118dd06 11026 Display *display;
c118dd06 11027{
e99db5a1 11028 char buf[256];
dc6f92b8 11029
e99db5a1
RS
11030 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
11031 x_connection_closed (display, buf);
06a2c219 11032 return 0;
dc6f92b8 11033}
dc6f92b8 11034\f
f451eb13
JB
11035/* Changing the font of the frame. */
11036
76bcdf39
RS
11037/* Give frame F the font named FONTNAME as its default font, and
11038 return the full name of that font. FONTNAME may be a wildcard
11039 pattern; in that case, we choose some font that fits the pattern.
11040 The return value shows which font we chose. */
11041
b5cf7a0e 11042Lisp_Object
f676886a
JB
11043x_new_font (f, fontname)
11044 struct frame *f;
dc6f92b8
JB
11045 register char *fontname;
11046{
dc43ef94 11047 struct font_info *fontp
ee569018 11048 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 11049
dc43ef94
KH
11050 if (!fontp)
11051 return Qnil;
2224a5fc 11052
dc43ef94 11053 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11054 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11055 f->output_data.x->fontset = -1;
11056
b2cad826
KH
11057 /* Compute the scroll bar width in character columns. */
11058 if (f->scroll_bar_pixel_width > 0)
11059 {
7556890b 11060 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11061 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11062 }
11063 else
4e61bddf
RS
11064 {
11065 int wid = FONT_WIDTH (f->output_data.x->font);
11066 f->scroll_bar_cols = (14 + wid - 1) / wid;
11067 }
b2cad826 11068
f676886a 11069 /* Now make the frame display the given font. */
c118dd06 11070 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11071 {
7556890b
RS
11072 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11073 f->output_data.x->font->fid);
11074 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11075 f->output_data.x->font->fid);
11076 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11077 f->output_data.x->font->fid);
f676886a 11078
a27f9f86 11079 frame_update_line_height (f);
0134a210 11080 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11081 }
a27f9f86
RS
11082 else
11083 /* If we are setting a new frame's font for the first time,
11084 there are no faces yet, so this font's height is the line height. */
7556890b 11085 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11086
dc43ef94
KH
11087 return build_string (fontp->full_name);
11088}
11089
11090/* Give frame F the fontset named FONTSETNAME as its default font, and
11091 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11092 pattern; in that case, we choose some fontset that fits the pattern.
11093 The return value shows which fontset we chose. */
b5cf7a0e 11094
dc43ef94
KH
11095Lisp_Object
11096x_new_fontset (f, fontsetname)
11097 struct frame *f;
11098 char *fontsetname;
11099{
ee569018 11100 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11101 Lisp_Object result;
b5cf7a0e 11102
dc43ef94
KH
11103 if (fontset < 0)
11104 return Qnil;
b5cf7a0e 11105
2da424f1
KH
11106 if (f->output_data.x->fontset == fontset)
11107 /* This fontset is already set in frame F. There's nothing more
11108 to do. */
ee569018 11109 return fontset_name (fontset);
dc43ef94 11110
ee569018 11111 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11112
11113 if (!STRINGP (result))
11114 /* Can't load ASCII font. */
11115 return Qnil;
11116
11117 /* Since x_new_font doesn't update any fontset information, do it now. */
11118 f->output_data.x->fontset = fontset;
dc43ef94 11119
f5d11644
GM
11120#ifdef HAVE_X_I18N
11121 if (FRAME_XIC (f)
11122 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11123 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11124#endif
11125
dc43ef94 11126 return build_string (fontsetname);
dc6f92b8 11127}
f5d11644
GM
11128
11129\f
11130/***********************************************************************
11131 X Input Methods
11132 ***********************************************************************/
11133
11134#ifdef HAVE_X_I18N
11135
11136#ifdef HAVE_X11R6
11137
11138/* XIM destroy callback function, which is called whenever the
11139 connection to input method XIM dies. CLIENT_DATA contains a
11140 pointer to the x_display_info structure corresponding to XIM. */
11141
11142static void
11143xim_destroy_callback (xim, client_data, call_data)
11144 XIM xim;
11145 XPointer client_data;
11146 XPointer call_data;
11147{
11148 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11149 Lisp_Object frame, tail;
11150
11151 BLOCK_INPUT;
11152
11153 /* No need to call XDestroyIC.. */
11154 FOR_EACH_FRAME (tail, frame)
11155 {
11156 struct frame *f = XFRAME (frame);
11157 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11158 {
11159 FRAME_XIC (f) = NULL;
11160 if (FRAME_XIC_FONTSET (f))
11161 {
11162 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11163 FRAME_XIC_FONTSET (f) = NULL;
11164 }
11165 }
11166 }
11167
11168 /* No need to call XCloseIM. */
11169 dpyinfo->xim = NULL;
11170 XFree (dpyinfo->xim_styles);
11171 UNBLOCK_INPUT;
11172}
11173
11174#endif /* HAVE_X11R6 */
11175
11176/* Open the connection to the XIM server on display DPYINFO.
11177 RESOURCE_NAME is the resource name Emacs uses. */
11178
11179static void
11180xim_open_dpy (dpyinfo, resource_name)
11181 struct x_display_info *dpyinfo;
11182 char *resource_name;
11183{
287f7dd6 11184#ifdef USE_XIM
f5d11644
GM
11185 XIM xim;
11186
11187 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11188 dpyinfo->xim = xim;
11189
11190 if (xim)
11191 {
f5d11644
GM
11192#ifdef HAVE_X11R6
11193 XIMCallback destroy;
11194#endif
11195
11196 /* Get supported styles and XIM values. */
11197 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11198
11199#ifdef HAVE_X11R6
11200 destroy.callback = xim_destroy_callback;
11201 destroy.client_data = (XPointer)dpyinfo;
68642df6 11202 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11203 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11204#endif
11205 }
287f7dd6
GM
11206
11207#else /* not USE_XIM */
11208 dpyinfo->xim = NULL;
11209#endif /* not USE_XIM */
f5d11644
GM
11210}
11211
11212
b9de836c 11213#ifdef HAVE_X11R6_XIM
f5d11644
GM
11214
11215struct xim_inst_t
11216{
11217 struct x_display_info *dpyinfo;
11218 char *resource_name;
11219};
11220
11221/* XIM instantiate callback function, which is called whenever an XIM
11222 server is available. DISPLAY is teh display of the XIM.
11223 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11224 when the callback was registered. */
11225
11226static void
11227xim_instantiate_callback (display, client_data, call_data)
11228 Display *display;
11229 XPointer client_data;
11230 XPointer call_data;
11231{
11232 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11233 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11234
11235 /* We don't support multiple XIM connections. */
11236 if (dpyinfo->xim)
11237 return;
11238
11239 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11240
11241 /* Create XIC for the existing frames on the same display, as long
11242 as they have no XIC. */
11243 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11244 {
11245 Lisp_Object tail, frame;
11246
11247 BLOCK_INPUT;
11248 FOR_EACH_FRAME (tail, frame)
11249 {
11250 struct frame *f = XFRAME (frame);
11251
11252 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11253 if (FRAME_XIC (f) == NULL)
11254 {
11255 create_frame_xic (f);
11256 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11257 xic_set_statusarea (f);
11258 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11259 {
11260 struct window *w = XWINDOW (f->selected_window);
11261 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11262 }
11263 }
11264 }
11265
11266 UNBLOCK_INPUT;
11267 }
11268}
11269
b9de836c 11270#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11271
11272
11273/* Open a connection to the XIM server on display DPYINFO.
11274 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11275 connection only at the first time. On X11R6, open the connection
11276 in the XIM instantiate callback function. */
11277
11278static void
11279xim_initialize (dpyinfo, resource_name)
11280 struct x_display_info *dpyinfo;
11281 char *resource_name;
11282{
287f7dd6 11283#ifdef USE_XIM
b9de836c 11284#ifdef HAVE_X11R6_XIM
f5d11644
GM
11285 struct xim_inst_t *xim_inst;
11286 int len;
11287
11288 dpyinfo->xim = NULL;
11289 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11290 xim_inst->dpyinfo = dpyinfo;
11291 len = strlen (resource_name);
11292 xim_inst->resource_name = (char *) xmalloc (len + 1);
11293 bcopy (resource_name, xim_inst->resource_name, len + 1);
11294 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11295 resource_name, EMACS_CLASS,
11296 xim_instantiate_callback,
2ebb2f8b
DL
11297 /* Fixme: This is XPointer in
11298 XFree86 but (XPointer *) on
11299 Tru64, at least. */
11300 (XPointer) xim_inst);
b9de836c 11301#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11302 dpyinfo->xim = NULL;
11303 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11304#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11305
11306#else /* not USE_XIM */
11307 dpyinfo->xim = NULL;
11308#endif /* not USE_XIM */
f5d11644
GM
11309}
11310
11311
11312/* Close the connection to the XIM server on display DPYINFO. */
11313
11314static void
11315xim_close_dpy (dpyinfo)
11316 struct x_display_info *dpyinfo;
11317{
287f7dd6 11318#ifdef USE_XIM
b9de836c 11319#ifdef HAVE_X11R6_XIM
f5d11644
GM
11320 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11321 NULL, EMACS_CLASS,
11322 xim_instantiate_callback, NULL);
b9de836c 11323#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11324 XCloseIM (dpyinfo->xim);
11325 dpyinfo->xim = NULL;
11326 XFree (dpyinfo->xim_styles);
287f7dd6 11327#endif /* USE_XIM */
f5d11644
GM
11328}
11329
b9de836c 11330#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11331
11332
dc6f92b8 11333\f
2e365682
RS
11334/* Calculate the absolute position in frame F
11335 from its current recorded position values and gravity. */
11336
dfcf069d 11337void
43bca5d5 11338x_calc_absolute_position (f)
f676886a 11339 struct frame *f;
dc6f92b8 11340{
06a2c219 11341 Window child;
6dba1858 11342 int win_x = 0, win_y = 0;
7556890b 11343 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11344 int this_window;
11345
9829ddba
RS
11346 /* We have nothing to do if the current position
11347 is already for the top-left corner. */
11348 if (! ((flags & XNegative) || (flags & YNegative)))
11349 return;
11350
c81412a0 11351#ifdef USE_X_TOOLKIT
7556890b 11352 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11353#else
11354 this_window = FRAME_X_WINDOW (f);
11355#endif
6dba1858
RS
11356
11357 /* Find the position of the outside upper-left corner of
9829ddba
RS
11358 the inner window, with respect to the outer window.
11359 But do this only if we will need the results. */
7556890b 11360 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11361 {
9829ddba
RS
11362 int count;
11363
6dba1858 11364 BLOCK_INPUT;
9829ddba
RS
11365 count = x_catch_errors (FRAME_X_DISPLAY (f));
11366 while (1)
11367 {
11368 x_clear_errors (FRAME_X_DISPLAY (f));
11369 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11370
11371 /* From-window, to-window. */
11372 this_window,
11373 f->output_data.x->parent_desc,
11374
11375 /* From-position, to-position. */
11376 0, 0, &win_x, &win_y,
11377
11378 /* Child of win. */
11379 &child);
11380 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11381 {
11382 Window newroot, newparent = 0xdeadbeef;
11383 Window *newchildren;
2ebb2f8b 11384 unsigned int nchildren;
9829ddba
RS
11385
11386 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11387 &newparent, &newchildren, &nchildren))
11388 break;
58769bee 11389
7c3c78a3 11390 XFree ((char *) newchildren);
6dba1858 11391
9829ddba
RS
11392 f->output_data.x->parent_desc = newparent;
11393 }
11394 else
11395 break;
11396 }
6dba1858 11397
9829ddba 11398 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11399 UNBLOCK_INPUT;
11400 }
11401
11402 /* Treat negative positions as relative to the leftmost bottommost
11403 position that fits on the screen. */
20f55f9a 11404 if (flags & XNegative)
7556890b 11405 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11406 - 2 * f->output_data.x->border_width - win_x
11407 - PIXEL_WIDTH (f)
11408 + f->output_data.x->left_pos);
dc6f92b8 11409
20f55f9a 11410 if (flags & YNegative)
06a2c219
GM
11411 {
11412 int menubar_height = 0;
11413
11414#ifdef USE_X_TOOLKIT
11415 if (f->output_data.x->menubar_widget)
11416 menubar_height
11417 = (f->output_data.x->menubar_widget->core.height
11418 + f->output_data.x->menubar_widget->core.border_width);
11419#endif
11420
11421 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11422 - 2 * f->output_data.x->border_width
11423 - win_y
11424 - PIXEL_HEIGHT (f)
11425 - menubar_height
11426 + f->output_data.x->top_pos);
11427 }
2e365682 11428
3a35ab44
RS
11429 /* The left_pos and top_pos
11430 are now relative to the top and left screen edges,
11431 so the flags should correspond. */
7556890b 11432 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11433}
11434
3a35ab44
RS
11435/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11436 to really change the position, and 0 when calling from
11437 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11438 position values). It is -1 when calling from x_set_frame_parameters,
11439 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11440
dfcf069d 11441void
dc05a16b 11442x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11443 struct frame *f;
dc6f92b8 11444 register int xoff, yoff;
dc05a16b 11445 int change_gravity;
dc6f92b8 11446{
4a4cbdd5
KH
11447 int modified_top, modified_left;
11448
aa3ff7c9 11449 if (change_gravity > 0)
3a35ab44 11450 {
7556890b
RS
11451 f->output_data.x->top_pos = yoff;
11452 f->output_data.x->left_pos = xoff;
11453 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11454 if (xoff < 0)
7556890b 11455 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11456 if (yoff < 0)
7556890b
RS
11457 f->output_data.x->size_hint_flags |= YNegative;
11458 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11459 }
43bca5d5 11460 x_calc_absolute_position (f);
dc6f92b8
JB
11461
11462 BLOCK_INPUT;
c32cdd9a 11463 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11464
7556890b
RS
11465 modified_left = f->output_data.x->left_pos;
11466 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11467#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11468 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11469 /* It is a mystery why we need to add the border_width here
11470 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11471 if (change_gravity != 0)
4a4cbdd5 11472 {
7556890b
RS
11473 modified_left += f->output_data.x->border_width;
11474 modified_top += f->output_data.x->border_width;
4a4cbdd5 11475 }
e73ec6fa 11476#endif
4a4cbdd5 11477
3afe33e7 11478#ifdef USE_X_TOOLKIT
7556890b 11479 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11480 modified_left, modified_top);
3afe33e7 11481#else /* not USE_X_TOOLKIT */
334208b7 11482 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11483 modified_left, modified_top);
3afe33e7 11484#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11485 UNBLOCK_INPUT;
11486}
11487
bc20ebbf
FP
11488/* Call this to change the size of frame F's x-window.
11489 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11490 for this size change and subsequent size changes.
11491 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11492
dfcf069d 11493void
bc20ebbf 11494x_set_window_size (f, change_gravity, cols, rows)
f676886a 11495 struct frame *f;
bc20ebbf 11496 int change_gravity;
b1c884c3 11497 int cols, rows;
dc6f92b8 11498{
06a2c219 11499#ifndef USE_X_TOOLKIT
dc6f92b8 11500 int pixelwidth, pixelheight;
06a2c219 11501#endif
dc6f92b8 11502
80fd1fe2 11503 BLOCK_INPUT;
aee9a898
RS
11504
11505#ifdef USE_X_TOOLKIT
3a20653d
RS
11506 {
11507 /* The x and y position of the widget is clobbered by the
11508 call to XtSetValues within EmacsFrameSetCharSize.
11509 This is a real kludge, but I don't understand Xt so I can't
11510 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11511 int xpos = f->output_data.x->widget->core.x;
11512 int ypos = f->output_data.x->widget->core.y;
11513 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11514 f->output_data.x->widget->core.x = xpos;
11515 f->output_data.x->widget->core.y = ypos;
3a20653d 11516 }
80fd1fe2
FP
11517
11518#else /* not USE_X_TOOLKIT */
11519
b1c884c3 11520 check_frame_size (f, &rows, &cols);
7556890b 11521 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11522 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11523 ? 0
11524 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11525 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11526 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11527 f->output_data.x->flags_areas_extra
110859fc 11528 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11529 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11530 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11531
7556890b 11532 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11533 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11534
334208b7
RS
11535 XSync (FRAME_X_DISPLAY (f), False);
11536 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11537 pixelwidth, pixelheight);
b1c884c3
JB
11538
11539 /* Now, strictly speaking, we can't be sure that this is accurate,
11540 but the window manager will get around to dealing with the size
11541 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11542 ConfigureNotify event gets here.
11543
11544 We could just not bother storing any of this information here,
11545 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11546 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11547 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11548 point in the future when the ConfigureNotify event arrives.
11549
11550 We pass 1 for DELAY since we can't run Lisp code inside of
11551 a BLOCK_INPUT. */
7d1e984f 11552 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11553 PIXEL_WIDTH (f) = pixelwidth;
11554 PIXEL_HEIGHT (f) = pixelheight;
11555
aee9a898
RS
11556 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11557 receive in the ConfigureNotify event; if we get what we asked
11558 for, then the event won't cause the screen to become garbaged, so
11559 we have to make sure to do it here. */
11560 SET_FRAME_GARBAGED (f);
11561
11562 XFlush (FRAME_X_DISPLAY (f));
11563
11564#endif /* not USE_X_TOOLKIT */
11565
4d73d038 11566 /* If cursor was outside the new size, mark it as off. */
06a2c219 11567 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11568
aee9a898
RS
11569 /* Clear out any recollection of where the mouse highlighting was,
11570 since it might be in a place that's outside the new frame size.
11571 Actually checking whether it is outside is a pain in the neck,
11572 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11573 cancel_mouse_face (f);
dbc4e1c1 11574
dc6f92b8
JB
11575 UNBLOCK_INPUT;
11576}
dc6f92b8 11577\f
d047c4eb 11578/* Mouse warping. */
dc6f92b8 11579
9b378208 11580void
f676886a
JB
11581x_set_mouse_position (f, x, y)
11582 struct frame *f;
dc6f92b8
JB
11583 int x, y;
11584{
11585 int pix_x, pix_y;
11586
7556890b
RS
11587 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11588 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11589
11590 if (pix_x < 0) pix_x = 0;
11591 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11592
11593 if (pix_y < 0) pix_y = 0;
11594 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11595
11596 BLOCK_INPUT;
dc6f92b8 11597
334208b7
RS
11598 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11599 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11600 UNBLOCK_INPUT;
11601}
11602
9b378208
RS
11603/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11604
11605void
11606x_set_mouse_pixel_position (f, pix_x, pix_y)
11607 struct frame *f;
11608 int pix_x, pix_y;
11609{
11610 BLOCK_INPUT;
11611
334208b7
RS
11612 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11613 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11614 UNBLOCK_INPUT;
11615}
d047c4eb
KH
11616\f
11617/* focus shifting, raising and lowering. */
9b378208 11618
dfcf069d 11619void
f676886a
JB
11620x_focus_on_frame (f)
11621 struct frame *f;
dc6f92b8 11622{
1fb20991 11623#if 0 /* This proves to be unpleasant. */
f676886a 11624 x_raise_frame (f);
1fb20991 11625#endif
6d4238f3
JB
11626#if 0
11627 /* I don't think that the ICCCM allows programs to do things like this
11628 without the interaction of the window manager. Whatever you end up
f676886a 11629 doing with this code, do it to x_unfocus_frame too. */
334208b7 11630 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11631 RevertToPointerRoot, CurrentTime);
c118dd06 11632#endif /* ! 0 */
dc6f92b8
JB
11633}
11634
dfcf069d 11635void
f676886a
JB
11636x_unfocus_frame (f)
11637 struct frame *f;
dc6f92b8 11638{
6d4238f3 11639#if 0
f676886a 11640 /* Look at the remarks in x_focus_on_frame. */
0f941935 11641 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11642 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11643 RevertToPointerRoot, CurrentTime);
c118dd06 11644#endif /* ! 0 */
dc6f92b8
JB
11645}
11646
f676886a 11647/* Raise frame F. */
dc6f92b8 11648
dfcf069d 11649void
f676886a
JB
11650x_raise_frame (f)
11651 struct frame *f;
dc6f92b8 11652{
3a88c238 11653 if (f->async_visible)
dc6f92b8
JB
11654 {
11655 BLOCK_INPUT;
3afe33e7 11656#ifdef USE_X_TOOLKIT
7556890b 11657 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11658#else /* not USE_X_TOOLKIT */
334208b7 11659 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11660#endif /* not USE_X_TOOLKIT */
334208b7 11661 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11662 UNBLOCK_INPUT;
11663 }
11664}
11665
f676886a 11666/* Lower frame F. */
dc6f92b8 11667
dfcf069d 11668void
f676886a
JB
11669x_lower_frame (f)
11670 struct frame *f;
dc6f92b8 11671{
3a88c238 11672 if (f->async_visible)
dc6f92b8
JB
11673 {
11674 BLOCK_INPUT;
3afe33e7 11675#ifdef USE_X_TOOLKIT
7556890b 11676 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11677#else /* not USE_X_TOOLKIT */
334208b7 11678 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11679#endif /* not USE_X_TOOLKIT */
334208b7 11680 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11681 UNBLOCK_INPUT;
11682 }
11683}
11684
dbc4e1c1 11685static void
6b0442dc 11686XTframe_raise_lower (f, raise_flag)
dbc4e1c1 11687 FRAME_PTR f;
6b0442dc 11688 int raise_flag;
dbc4e1c1 11689{
6b0442dc 11690 if (raise_flag)
dbc4e1c1
JB
11691 x_raise_frame (f);
11692 else
11693 x_lower_frame (f);
11694}
d047c4eb
KH
11695\f
11696/* Change of visibility. */
dc6f92b8 11697
9382638d
KH
11698/* This tries to wait until the frame is really visible.
11699 However, if the window manager asks the user where to position
11700 the frame, this will return before the user finishes doing that.
11701 The frame will not actually be visible at that time,
11702 but it will become visible later when the window manager
11703 finishes with it. */
11704
dfcf069d 11705void
f676886a
JB
11706x_make_frame_visible (f)
11707 struct frame *f;
dc6f92b8 11708{
990ba854 11709 Lisp_Object type;
1aa6072f 11710 int original_top, original_left;
dc6f92b8 11711
dc6f92b8 11712 BLOCK_INPUT;
dc6f92b8 11713
990ba854
RS
11714 type = x_icon_type (f);
11715 if (!NILP (type))
11716 x_bitmap_icon (f, type);
bdcd49ba 11717
f676886a 11718 if (! FRAME_VISIBLE_P (f))
90e65f07 11719 {
1aa6072f
RS
11720 /* We test FRAME_GARBAGED_P here to make sure we don't
11721 call x_set_offset a second time
11722 if we get to x_make_frame_visible a second time
11723 before the window gets really visible. */
11724 if (! FRAME_ICONIFIED_P (f)
11725 && ! f->output_data.x->asked_for_visible)
11726 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11727
11728 f->output_data.x->asked_for_visible = 1;
11729
90e65f07 11730 if (! EQ (Vx_no_window_manager, Qt))
f676886a 11731 x_wm_set_window_state (f, NormalState);
3afe33e7 11732#ifdef USE_X_TOOLKIT
d7a38a2e 11733 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11734 XtMapWidget (f->output_data.x->widget);
3afe33e7 11735#else /* not USE_X_TOOLKIT */
7f9c7f94 11736 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11737#endif /* not USE_X_TOOLKIT */
0134a210
RS
11738#if 0 /* This seems to bring back scroll bars in the wrong places
11739 if the window configuration has changed. They seem
11740 to come back ok without this. */
ab648270 11741 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 11742 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 11743#endif
90e65f07 11744 }
dc6f92b8 11745
334208b7 11746 XFlush (FRAME_X_DISPLAY (f));
90e65f07 11747
0dacf791
RS
11748 /* Synchronize to ensure Emacs knows the frame is visible
11749 before we do anything else. We do this loop with input not blocked
11750 so that incoming events are handled. */
11751 {
11752 Lisp_Object frame;
12ce2351 11753 int count;
28c01ffe
RS
11754 /* This must be before UNBLOCK_INPUT
11755 since events that arrive in response to the actions above
11756 will set it when they are handled. */
11757 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
11758
11759 original_left = f->output_data.x->left_pos;
11760 original_top = f->output_data.x->top_pos;
c0a04927
RS
11761
11762 /* This must come after we set COUNT. */
11763 UNBLOCK_INPUT;
11764
2745e6c4 11765 /* We unblock here so that arriving X events are processed. */
1aa6072f 11766
dcb07ae9
RS
11767 /* Now move the window back to where it was "supposed to be".
11768 But don't do it if the gravity is negative.
11769 When the gravity is negative, this uses a position
28c01ffe
RS
11770 that is 3 pixels too low. Perhaps that's really the border width.
11771
11772 Don't do this if the window has never been visible before,
11773 because the window manager may choose the position
11774 and we don't want to override it. */
1aa6072f 11775
4d3f5d9a 11776 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 11777 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 11778 && previously_visible)
1aa6072f 11779 {
2745e6c4
RS
11780 Drawable rootw;
11781 int x, y;
11782 unsigned int width, height, border, depth;
06a2c219 11783
1aa6072f 11784 BLOCK_INPUT;
9829ddba 11785
06a2c219
GM
11786 /* On some window managers (such as FVWM) moving an existing
11787 window, even to the same place, causes the window manager
11788 to introduce an offset. This can cause the window to move
11789 to an unexpected location. Check the geometry (a little
11790 slow here) and then verify that the window is in the right
11791 place. If the window is not in the right place, move it
11792 there, and take the potential window manager hit. */
2745e6c4
RS
11793 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11794 &rootw, &x, &y, &width, &height, &border, &depth);
11795
11796 if (original_left != x || original_top != y)
11797 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11798 original_left, original_top);
11799
1aa6072f
RS
11800 UNBLOCK_INPUT;
11801 }
9829ddba 11802
e0c1aef2 11803 XSETFRAME (frame, f);
c0a04927 11804
12ce2351
GM
11805 /* Wait until the frame is visible. Process X events until a
11806 MapNotify event has been seen, or until we think we won't get a
11807 MapNotify at all.. */
11808 for (count = input_signal_count + 10;
11809 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 11810 {
12ce2351 11811 /* Force processing of queued events. */
334208b7 11812 x_sync (f);
12ce2351
GM
11813
11814 /* Machines that do polling rather than SIGIO have been
11815 observed to go into a busy-wait here. So we'll fake an
11816 alarm signal to let the handler know that there's something
11817 to be read. We used to raise a real alarm, but it seems
11818 that the handler isn't always enabled here. This is
11819 probably a bug. */
8b2f8d4e 11820 if (input_polling_used ())
3b2fa4e6 11821 {
12ce2351
GM
11822 /* It could be confusing if a real alarm arrives while
11823 processing the fake one. Turn it off and let the
11824 handler reset it. */
3e71d8f2 11825 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
11826 int old_poll_suppress_count = poll_suppress_count;
11827 poll_suppress_count = 1;
11828 poll_for_input_1 ();
11829 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 11830 }
12ce2351
GM
11831
11832 /* See if a MapNotify event has been processed. */
11833 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 11834 }
0dacf791 11835 }
dc6f92b8
JB
11836}
11837
06a2c219 11838/* Change from mapped state to withdrawn state. */
dc6f92b8 11839
d047c4eb
KH
11840/* Make the frame visible (mapped and not iconified). */
11841
dfcf069d 11842void
f676886a
JB
11843x_make_frame_invisible (f)
11844 struct frame *f;
dc6f92b8 11845{
546e6d5b
RS
11846 Window window;
11847
11848#ifdef USE_X_TOOLKIT
11849 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11850 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11851#else /* not USE_X_TOOLKIT */
11852 window = FRAME_X_WINDOW (f);
11853#endif /* not USE_X_TOOLKIT */
dc6f92b8 11854
9319ae23 11855 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11856 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11857 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11858
5627c40e 11859#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 11860 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 11861 return;
5627c40e 11862#endif
dc6f92b8
JB
11863
11864 BLOCK_INPUT;
c118dd06 11865
af31d76f
RS
11866 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11867 that the current position of the window is user-specified, rather than
11868 program-specified, so that when the window is mapped again, it will be
11869 placed at the same location, without forcing the user to position it
11870 by hand again (they have already done that once for this window.) */
c32cdd9a 11871 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 11872
c118dd06
JB
11873#ifdef HAVE_X11R4
11874
334208b7
RS
11875 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11876 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
11877 {
11878 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11879 error ("Can't notify window manager of window withdrawal");
c118dd06 11880 }
c118dd06 11881#else /* ! defined (HAVE_X11R4) */
16bd92ea 11882
c118dd06 11883 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
11884 if (! EQ (Vx_no_window_manager, Qt))
11885 {
16bd92ea 11886 XEvent unmap;
dc6f92b8 11887
16bd92ea 11888 unmap.xunmap.type = UnmapNotify;
546e6d5b 11889 unmap.xunmap.window = window;
334208b7 11890 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 11891 unmap.xunmap.from_configure = False;
334208b7
RS
11892 if (! XSendEvent (FRAME_X_DISPLAY (f),
11893 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 11894 False,
06a2c219 11895 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
11896 &unmap))
11897 {
11898 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11899 error ("Can't notify window manager of withdrawal");
16bd92ea 11900 }
dc6f92b8
JB
11901 }
11902
16bd92ea 11903 /* Unmap the window ourselves. Cheeky! */
334208b7 11904 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 11905#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 11906
5627c40e
RS
11907 /* We can't distinguish this from iconification
11908 just by the event that we get from the server.
11909 So we can't win using the usual strategy of letting
11910 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11911 and synchronize with the server to make sure we agree. */
11912 f->visible = 0;
11913 FRAME_ICONIFIED_P (f) = 0;
11914 f->async_visible = 0;
11915 f->async_iconified = 0;
11916
334208b7 11917 x_sync (f);
5627c40e 11918
dc6f92b8
JB
11919 UNBLOCK_INPUT;
11920}
11921
06a2c219 11922/* Change window state from mapped to iconified. */
dc6f92b8 11923
dfcf069d 11924void
f676886a
JB
11925x_iconify_frame (f)
11926 struct frame *f;
dc6f92b8 11927{
3afe33e7 11928 int result;
990ba854 11929 Lisp_Object type;
dc6f92b8 11930
9319ae23 11931 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11932 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11933 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11934
3a88c238 11935 if (f->async_iconified)
dc6f92b8
JB
11936 return;
11937
3afe33e7 11938 BLOCK_INPUT;
546e6d5b 11939
9af3143a
RS
11940 FRAME_SAMPLE_VISIBILITY (f);
11941
990ba854
RS
11942 type = x_icon_type (f);
11943 if (!NILP (type))
11944 x_bitmap_icon (f, type);
bdcd49ba
RS
11945
11946#ifdef USE_X_TOOLKIT
11947
546e6d5b
RS
11948 if (! FRAME_VISIBLE_P (f))
11949 {
11950 if (! EQ (Vx_no_window_manager, Qt))
11951 x_wm_set_window_state (f, IconicState);
11952 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11953 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
11954 /* The server won't give us any event to indicate
11955 that an invisible frame was changed to an icon,
11956 so we have to record it here. */
11957 f->iconified = 1;
1e6bc770 11958 f->visible = 1;
9cf30a30 11959 f->async_iconified = 1;
1e6bc770 11960 f->async_visible = 0;
546e6d5b
RS
11961 UNBLOCK_INPUT;
11962 return;
11963 }
11964
334208b7 11965 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 11966 XtWindow (f->output_data.x->widget),
334208b7 11967 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
11968 UNBLOCK_INPUT;
11969
11970 if (!result)
546e6d5b 11971 error ("Can't notify window manager of iconification");
3afe33e7
RS
11972
11973 f->async_iconified = 1;
1e6bc770
RS
11974 f->async_visible = 0;
11975
8c002a25
KH
11976
11977 BLOCK_INPUT;
334208b7 11978 XFlush (FRAME_X_DISPLAY (f));
8c002a25 11979 UNBLOCK_INPUT;
3afe33e7
RS
11980#else /* not USE_X_TOOLKIT */
11981
fd13dbb2
RS
11982 /* Make sure the X server knows where the window should be positioned,
11983 in case the user deiconifies with the window manager. */
11984 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 11985 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 11986
16bd92ea
JB
11987 /* Since we don't know which revision of X we're running, we'll use both
11988 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11989
11990 /* X11R4: send a ClientMessage to the window manager using the
11991 WM_CHANGE_STATE type. */
11992 {
11993 XEvent message;
58769bee 11994
c118dd06 11995 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 11996 message.xclient.type = ClientMessage;
334208b7 11997 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
11998 message.xclient.format = 32;
11999 message.xclient.data.l[0] = IconicState;
12000
334208b7
RS
12001 if (! XSendEvent (FRAME_X_DISPLAY (f),
12002 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
12003 False,
12004 SubstructureRedirectMask | SubstructureNotifyMask,
12005 &message))
dc6f92b8
JB
12006 {
12007 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 12008 error ("Can't notify window manager of iconification");
dc6f92b8 12009 }
16bd92ea 12010 }
dc6f92b8 12011
58769bee 12012 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
12013 IconicState. */
12014 x_wm_set_window_state (f, IconicState);
dc6f92b8 12015
a9c00105
RS
12016 if (!FRAME_VISIBLE_P (f))
12017 {
12018 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 12019 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
12020 }
12021
3a88c238 12022 f->async_iconified = 1;
1e6bc770 12023 f->async_visible = 0;
dc6f92b8 12024
334208b7 12025 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 12026 UNBLOCK_INPUT;
8c002a25 12027#endif /* not USE_X_TOOLKIT */
dc6f92b8 12028}
d047c4eb 12029\f
c0ff3fab 12030/* Destroy the X window of frame F. */
dc6f92b8 12031
dfcf069d 12032void
c0ff3fab 12033x_destroy_window (f)
f676886a 12034 struct frame *f;
dc6f92b8 12035{
7f9c7f94
RS
12036 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12037
dc6f92b8 12038 BLOCK_INPUT;
c0ff3fab 12039
6186a4a0
RS
12040 /* If a display connection is dead, don't try sending more
12041 commands to the X server. */
12042 if (dpyinfo->display != 0)
12043 {
12044 if (f->output_data.x->icon_desc != 0)
12045 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 12046#ifdef HAVE_X_I18N
f5d11644
GM
12047 if (FRAME_XIC (f))
12048 free_frame_xic (f);
31f41daf 12049#endif
6186a4a0 12050 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 12051#ifdef USE_X_TOOLKIT
06a2c219
GM
12052 if (f->output_data.x->widget)
12053 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12054 free_frame_menubar (f);
3afe33e7
RS
12055#endif /* USE_X_TOOLKIT */
12056
3e71d8f2
GM
12057 unload_color (f, f->output_data.x->foreground_pixel);
12058 unload_color (f, f->output_data.x->background_pixel);
12059 unload_color (f, f->output_data.x->cursor_pixel);
12060 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12061 unload_color (f, f->output_data.x->border_pixel);
12062 unload_color (f, f->output_data.x->mouse_pixel);
12063 if (f->output_data.x->scroll_bar_background_pixel != -1)
12064 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12065 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12066 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12067 if (f->output_data.x->white_relief.allocated_p)
12068 unload_color (f, f->output_data.x->white_relief.pixel);
12069 if (f->output_data.x->black_relief.allocated_p)
12070 unload_color (f, f->output_data.x->black_relief.pixel);
12071
6186a4a0
RS
12072 free_frame_faces (f);
12073 XFlush (FRAME_X_DISPLAY (f));
12074 }
dc6f92b8 12075
df89d8a4 12076 if (f->output_data.x->saved_menu_event)
06a2c219 12077 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12078
7556890b
RS
12079 xfree (f->output_data.x);
12080 f->output_data.x = 0;
0f941935
KH
12081 if (f == dpyinfo->x_focus_frame)
12082 dpyinfo->x_focus_frame = 0;
12083 if (f == dpyinfo->x_focus_event_frame)
12084 dpyinfo->x_focus_event_frame = 0;
12085 if (f == dpyinfo->x_highlight_frame)
12086 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12087
7f9c7f94
RS
12088 dpyinfo->reference_count--;
12089
12090 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12091 {
7f9c7f94
RS
12092 dpyinfo->mouse_face_beg_row
12093 = dpyinfo->mouse_face_beg_col = -1;
12094 dpyinfo->mouse_face_end_row
12095 = dpyinfo->mouse_face_end_col = -1;
12096 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12097 dpyinfo->mouse_face_deferred_gc = 0;
12098 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12099 }
0134a210 12100
c0ff3fab 12101 UNBLOCK_INPUT;
dc6f92b8
JB
12102}
12103\f
f451eb13
JB
12104/* Setting window manager hints. */
12105
af31d76f
RS
12106/* Set the normal size hints for the window manager, for frame F.
12107 FLAGS is the flags word to use--or 0 meaning preserve the flags
12108 that the window now has.
12109 If USER_POSITION is nonzero, we set the USPosition
12110 flag (this is useful when FLAGS is 0). */
6dba1858 12111
dfcf069d 12112void
af31d76f 12113x_wm_set_size_hint (f, flags, user_position)
f676886a 12114 struct frame *f;
af31d76f
RS
12115 long flags;
12116 int user_position;
dc6f92b8
JB
12117{
12118 XSizeHints size_hints;
3afe33e7
RS
12119
12120#ifdef USE_X_TOOLKIT
7e4f2521
FP
12121 Arg al[2];
12122 int ac = 0;
12123 Dimension widget_width, widget_height;
7556890b 12124 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12125#else /* not USE_X_TOOLKIT */
c118dd06 12126 Window window = FRAME_X_WINDOW (f);
3afe33e7 12127#endif /* not USE_X_TOOLKIT */
dc6f92b8 12128
b72a58fd
RS
12129 /* Setting PMaxSize caused various problems. */
12130 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12131
7556890b
RS
12132 size_hints.x = f->output_data.x->left_pos;
12133 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12134
7e4f2521
FP
12135#ifdef USE_X_TOOLKIT
12136 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12137 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12138 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12139 size_hints.height = widget_height;
12140 size_hints.width = widget_width;
12141#else /* not USE_X_TOOLKIT */
f676886a
JB
12142 size_hints.height = PIXEL_HEIGHT (f);
12143 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12144#endif /* not USE_X_TOOLKIT */
7553a6b7 12145
7556890b
RS
12146 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12147 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12148 size_hints.max_width
12149 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12150 size_hints.max_height
12151 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12152
d067ea8b
KH
12153 /* Calculate the base and minimum sizes.
12154
12155 (When we use the X toolkit, we don't do it here.
12156 Instead we copy the values that the widgets are using, below.) */
12157#ifndef USE_X_TOOLKIT
b1c884c3 12158 {
b0342f17 12159 int base_width, base_height;
0134a210 12160 int min_rows = 0, min_cols = 0;
b0342f17 12161
f451eb13
JB
12162 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12163 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12164
0134a210 12165 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12166
0134a210
RS
12167 /* The window manager uses the base width hints to calculate the
12168 current number of rows and columns in the frame while
12169 resizing; min_width and min_height aren't useful for this
12170 purpose, since they might not give the dimensions for a
12171 zero-row, zero-column frame.
58769bee 12172
0134a210
RS
12173 We use the base_width and base_height members if we have
12174 them; otherwise, we set the min_width and min_height members
12175 to the size for a zero x zero frame. */
b0342f17
JB
12176
12177#ifdef HAVE_X11R4
0134a210
RS
12178 size_hints.flags |= PBaseSize;
12179 size_hints.base_width = base_width;
12180 size_hints.base_height = base_height;
12181 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12182 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12183#else
0134a210
RS
12184 size_hints.min_width = base_width;
12185 size_hints.min_height = base_height;
b0342f17 12186#endif
b1c884c3 12187 }
dc6f92b8 12188
d067ea8b 12189 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12190 if (flags)
dc6f92b8 12191 {
d067ea8b
KH
12192 size_hints.flags |= flags;
12193 goto no_read;
12194 }
12195#endif /* not USE_X_TOOLKIT */
12196
12197 {
12198 XSizeHints hints; /* Sometimes I hate X Windows... */
12199 long supplied_return;
12200 int value;
af31d76f
RS
12201
12202#ifdef HAVE_X11R4
d067ea8b
KH
12203 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12204 &supplied_return);
af31d76f 12205#else
d067ea8b 12206 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12207#endif
58769bee 12208
d067ea8b
KH
12209#ifdef USE_X_TOOLKIT
12210 size_hints.base_height = hints.base_height;
12211 size_hints.base_width = hints.base_width;
12212 size_hints.min_height = hints.min_height;
12213 size_hints.min_width = hints.min_width;
12214#endif
12215
12216 if (flags)
12217 size_hints.flags |= flags;
12218 else
12219 {
12220 if (value == 0)
12221 hints.flags = 0;
12222 if (hints.flags & PSize)
12223 size_hints.flags |= PSize;
12224 if (hints.flags & PPosition)
12225 size_hints.flags |= PPosition;
12226 if (hints.flags & USPosition)
12227 size_hints.flags |= USPosition;
12228 if (hints.flags & USSize)
12229 size_hints.flags |= USSize;
12230 }
12231 }
12232
06a2c219 12233#ifndef USE_X_TOOLKIT
d067ea8b 12234 no_read:
06a2c219 12235#endif
0134a210 12236
af31d76f 12237#ifdef PWinGravity
7556890b 12238 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12239 size_hints.flags |= PWinGravity;
dc05a16b 12240
af31d76f 12241 if (user_position)
6dba1858 12242 {
af31d76f
RS
12243 size_hints.flags &= ~ PPosition;
12244 size_hints.flags |= USPosition;
6dba1858 12245 }
2554751d 12246#endif /* PWinGravity */
6dba1858 12247
b0342f17 12248#ifdef HAVE_X11R4
334208b7 12249 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12250#else
334208b7 12251 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12252#endif
dc6f92b8
JB
12253}
12254
12255/* Used for IconicState or NormalState */
06a2c219 12256
dfcf069d 12257void
f676886a
JB
12258x_wm_set_window_state (f, state)
12259 struct frame *f;
dc6f92b8
JB
12260 int state;
12261{
3afe33e7 12262#ifdef USE_X_TOOLKIT
546e6d5b
RS
12263 Arg al[1];
12264
12265 XtSetArg (al[0], XtNinitialState, state);
7556890b 12266 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12267#else /* not USE_X_TOOLKIT */
c118dd06 12268 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12269
7556890b
RS
12270 f->output_data.x->wm_hints.flags |= StateHint;
12271 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12272
7556890b 12273 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12274#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12275}
12276
dfcf069d 12277void
7f2ae036 12278x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12279 struct frame *f;
7f2ae036 12280 int pixmap_id;
dc6f92b8 12281{
d2bd6bc4
RS
12282 Pixmap icon_pixmap;
12283
06a2c219 12284#ifndef USE_X_TOOLKIT
c118dd06 12285 Window window = FRAME_X_WINDOW (f);
75231bad 12286#endif
dc6f92b8 12287
7f2ae036 12288 if (pixmap_id > 0)
dbc4e1c1 12289 {
d2bd6bc4 12290 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12291 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12292 }
12293 else
68568555
RS
12294 {
12295 /* It seems there is no way to turn off use of an icon pixmap.
12296 The following line does it, only if no icon has yet been created,
12297 for some window managers. But with mwm it crashes.
12298 Some people say it should clear the IconPixmapHint bit in this case,
12299 but that doesn't work, and the X consortium said it isn't the
12300 right thing at all. Since there is no way to win,
12301 best to explicitly give up. */
12302#if 0
12303 f->output_data.x->wm_hints.icon_pixmap = None;
12304#else
12305 return;
12306#endif
12307 }
b1c884c3 12308
d2bd6bc4
RS
12309#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12310
12311 {
12312 Arg al[1];
12313 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12314 XtSetValues (f->output_data.x->widget, al, 1);
12315 }
12316
12317#else /* not USE_X_TOOLKIT */
12318
7556890b
RS
12319 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12320 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12321
12322#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12323}
12324
dfcf069d 12325void
f676886a
JB
12326x_wm_set_icon_position (f, icon_x, icon_y)
12327 struct frame *f;
dc6f92b8
JB
12328 int icon_x, icon_y;
12329{
75231bad 12330#ifdef USE_X_TOOLKIT
7556890b 12331 Window window = XtWindow (f->output_data.x->widget);
75231bad 12332#else
c118dd06 12333 Window window = FRAME_X_WINDOW (f);
75231bad 12334#endif
dc6f92b8 12335
7556890b
RS
12336 f->output_data.x->wm_hints.flags |= IconPositionHint;
12337 f->output_data.x->wm_hints.icon_x = icon_x;
12338 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12339
7556890b 12340 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12341}
12342
12343\f
06a2c219
GM
12344/***********************************************************************
12345 Fonts
12346 ***********************************************************************/
dc43ef94
KH
12347
12348/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12349
dc43ef94
KH
12350struct font_info *
12351x_get_font_info (f, font_idx)
12352 FRAME_PTR f;
12353 int font_idx;
12354{
12355 return (FRAME_X_FONT_TABLE (f) + font_idx);
12356}
12357
12358
12359/* Return a list of names of available fonts matching PATTERN on frame
12360 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12361 to be listed. Frame F NULL means we have not yet created any
12362 frame on X, and consult the first display in x_display_list.
12363 MAXNAMES sets a limit on how many fonts to match. */
12364
12365Lisp_Object
12366x_list_fonts (f, pattern, size, maxnames)
12367 FRAME_PTR f;
12368 Lisp_Object pattern;
12369 int size;
12370 int maxnames;
12371{
06a2c219
GM
12372 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12373 Lisp_Object tem, second_best;
dc43ef94 12374 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12375 int try_XLoadQueryFont = 0;
53ca4657 12376 int count;
dc43ef94 12377
6b0efe73 12378 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12379 if (NILP (patterns))
12380 patterns = Fcons (pattern, Qnil);
81ba44e5 12381
09c6077f
KH
12382 if (maxnames == 1 && !size)
12383 /* We can return any single font matching PATTERN. */
12384 try_XLoadQueryFont = 1;
9a32686f 12385
8e713be6 12386 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12387 {
dc43ef94 12388 int num_fonts;
3e71d8f2 12389 char **names = NULL;
dc43ef94 12390
8e713be6 12391 pattern = XCAR (patterns);
536f4067
RS
12392 /* See if we cached the result for this particular query.
12393 The cache is an alist of the form:
12394 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12395 */
8e713be6 12396 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12397 key = Fcons (pattern, make_number (maxnames)),
12398 !NILP (list = Fassoc (key, tem))))
12399 {
12400 list = Fcdr_safe (list);
12401 /* We have a cashed list. Don't have to get the list again. */
12402 goto label_cached;
12403 }
12404
12405 /* At first, put PATTERN in the cache. */
09c6077f 12406
dc43ef94 12407 BLOCK_INPUT;
17d85edc
KH
12408 count = x_catch_errors (dpy);
12409
09c6077f
KH
12410 if (try_XLoadQueryFont)
12411 {
12412 XFontStruct *font;
12413 unsigned long value;
12414
12415 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12416 if (x_had_errors_p (dpy))
12417 {
12418 /* This error is perhaps due to insufficient memory on X
12419 server. Let's just ignore it. */
12420 font = NULL;
12421 x_clear_errors (dpy);
12422 }
12423
09c6077f
KH
12424 if (font
12425 && XGetFontProperty (font, XA_FONT, &value))
12426 {
12427 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12428 int len = strlen (name);
01c752b5 12429 char *tmp;
09c6077f 12430
6f6512e8
KH
12431 /* If DXPC (a Differential X Protocol Compressor)
12432 Ver.3.7 is running, XGetAtomName will return null
12433 string. We must avoid such a name. */
12434 if (len == 0)
12435 try_XLoadQueryFont = 0;
12436 else
12437 {
12438 num_fonts = 1;
12439 names = (char **) alloca (sizeof (char *));
12440 /* Some systems only allow alloca assigned to a
12441 simple var. */
12442 tmp = (char *) alloca (len + 1); names[0] = tmp;
12443 bcopy (name, names[0], len + 1);
12444 XFree (name);
12445 }
09c6077f
KH
12446 }
12447 else
12448 try_XLoadQueryFont = 0;
a083fd23
RS
12449
12450 if (font)
12451 XFreeFont (dpy, font);
09c6077f
KH
12452 }
12453
12454 if (!try_XLoadQueryFont)
17d85edc
KH
12455 {
12456 /* We try at least 10 fonts because XListFonts will return
12457 auto-scaled fonts at the head. */
12458 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12459 &num_fonts);
12460 if (x_had_errors_p (dpy))
12461 {
12462 /* This error is perhaps due to insufficient memory on X
12463 server. Let's just ignore it. */
12464 names = NULL;
12465 x_clear_errors (dpy);
12466 }
12467 }
12468
12469 x_uncatch_errors (dpy, count);
dc43ef94
KH
12470 UNBLOCK_INPUT;
12471
12472 if (names)
12473 {
12474 int i;
dc43ef94
KH
12475
12476 /* Make a list of all the fonts we got back.
12477 Store that in the font cache for the display. */
12478 for (i = 0; i < num_fonts; i++)
12479 {
06a2c219 12480 int width = 0;
dc43ef94 12481 char *p = names[i];
06a2c219
GM
12482 int average_width = -1, dashes = 0;
12483
dc43ef94 12484 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12485 14 dashes, and the field value following 12th dash
12486 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12487 is usually too ugly to be used for editing. Let's
12488 ignore it. */
dc43ef94
KH
12489 while (*p)
12490 if (*p++ == '-')
12491 {
12492 dashes++;
12493 if (dashes == 7) /* PIXEL_SIZE field */
12494 width = atoi (p);
12495 else if (dashes == 12) /* AVERAGE_WIDTH field */
12496 average_width = atoi (p);
12497 }
12498 if (dashes < 14 || average_width != 0)
12499 {
12500 tem = build_string (names[i]);
12501 if (NILP (Fassoc (tem, list)))
12502 {
12503 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12504 && ((fast_c_string_match_ignore_case
12505 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12506 >= 0))
12507 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12508 width of this font. */
dc43ef94
KH
12509 list = Fcons (Fcons (tem, make_number (width)), list);
12510 else
12511 /* For the moment, width is not known. */
12512 list = Fcons (Fcons (tem, Qnil), list);
12513 }
12514 }
12515 }
09c6077f
KH
12516 if (!try_XLoadQueryFont)
12517 XFreeFontNames (names);
dc43ef94
KH
12518 }
12519
b5210ea7 12520 /* Now store the result in the cache. */
dc43ef94 12521 if (f != NULL)
8e713be6 12522 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12523 = Fcons (Fcons (key, list),
8e713be6 12524 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12525
b5210ea7
KH
12526 label_cached:
12527 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12528
b5210ea7
KH
12529 newlist = second_best = Qnil;
12530 /* Make a list of the fonts that have the right width. */
8e713be6 12531 for (; CONSP (list); list = XCDR (list))
b5210ea7 12532 {
536f4067
RS
12533 int found_size;
12534
8e713be6 12535 tem = XCAR (list);
dc43ef94 12536
8e713be6 12537 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12538 continue;
12539 if (!size)
12540 {
8e713be6 12541 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12542 continue;
12543 }
dc43ef94 12544
8e713be6 12545 if (!INTEGERP (XCDR (tem)))
dc43ef94 12546 {
b5210ea7
KH
12547 /* Since we have not yet known the size of this font, we
12548 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12549 XFontStruct *thisinfo;
12550
12551 BLOCK_INPUT;
17d85edc 12552 count = x_catch_errors (dpy);
dc43ef94 12553 thisinfo = XLoadQueryFont (dpy,
8e713be6 12554 XSTRING (XCAR (tem))->data);
17d85edc
KH
12555 if (x_had_errors_p (dpy))
12556 {
12557 /* This error is perhaps due to insufficient memory on X
12558 server. Let's just ignore it. */
12559 thisinfo = NULL;
12560 x_clear_errors (dpy);
12561 }
12562 x_uncatch_errors (dpy, count);
dc43ef94
KH
12563 UNBLOCK_INPUT;
12564
12565 if (thisinfo)
12566 {
8e713be6 12567 XCDR (tem)
536f4067
RS
12568 = (thisinfo->min_bounds.width == 0
12569 ? make_number (0)
12570 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12571 XFreeFont (dpy, thisinfo);
12572 }
12573 else
b5210ea7 12574 /* For unknown reason, the previous call of XListFont had
06a2c219 12575 returned a font which can't be opened. Record the size
b5210ea7 12576 as 0 not to try to open it again. */
8e713be6 12577 XCDR (tem) = make_number (0);
dc43ef94 12578 }
536f4067 12579
8e713be6 12580 found_size = XINT (XCDR (tem));
536f4067 12581 if (found_size == size)
8e713be6 12582 newlist = Fcons (XCAR (tem), newlist);
536f4067 12583 else if (found_size > 0)
b5210ea7 12584 {
536f4067 12585 if (NILP (second_best))
b5210ea7 12586 second_best = tem;
536f4067
RS
12587 else if (found_size < size)
12588 {
8e713be6
KR
12589 if (XINT (XCDR (second_best)) > size
12590 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12591 second_best = tem;
12592 }
12593 else
12594 {
8e713be6
KR
12595 if (XINT (XCDR (second_best)) > size
12596 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12597 second_best = tem;
12598 }
b5210ea7
KH
12599 }
12600 }
12601 if (!NILP (newlist))
12602 break;
12603 else if (!NILP (second_best))
12604 {
8e713be6 12605 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12606 break;
dc43ef94 12607 }
dc43ef94
KH
12608 }
12609
12610 return newlist;
12611}
12612
06a2c219
GM
12613
12614#if GLYPH_DEBUG
12615
12616/* Check that FONT is valid on frame F. It is if it can be found in F's
12617 font table. */
12618
12619static void
12620x_check_font (f, font)
12621 struct frame *f;
12622 XFontStruct *font;
12623{
12624 int i;
12625 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12626
12627 xassert (font != NULL);
12628
12629 for (i = 0; i < dpyinfo->n_fonts; i++)
12630 if (dpyinfo->font_table[i].name
12631 && font == dpyinfo->font_table[i].font)
12632 break;
12633
12634 xassert (i < dpyinfo->n_fonts);
12635}
12636
12637#endif /* GLYPH_DEBUG != 0 */
12638
12639/* Set *W to the minimum width, *H to the minimum font height of FONT.
12640 Note: There are (broken) X fonts out there with invalid XFontStruct
12641 min_bounds contents. For example, handa@etl.go.jp reports that
12642 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12643 have font->min_bounds.width == 0. */
12644
12645static INLINE void
12646x_font_min_bounds (font, w, h)
12647 XFontStruct *font;
12648 int *w, *h;
12649{
12650 *h = FONT_HEIGHT (font);
12651 *w = font->min_bounds.width;
12652
12653 /* Try to handle the case where FONT->min_bounds has invalid
12654 contents. Since the only font known to have invalid min_bounds
12655 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12656 if (*w <= 0)
12657 *w = font->max_bounds.width;
12658}
12659
12660
12661/* Compute the smallest character width and smallest font height over
12662 all fonts available on frame F. Set the members smallest_char_width
12663 and smallest_font_height in F's x_display_info structure to
12664 the values computed. Value is non-zero if smallest_font_height or
12665 smallest_char_width become smaller than they were before. */
12666
12667static int
12668x_compute_min_glyph_bounds (f)
12669 struct frame *f;
12670{
12671 int i;
12672 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12673 XFontStruct *font;
12674 int old_width = dpyinfo->smallest_char_width;
12675 int old_height = dpyinfo->smallest_font_height;
12676
12677 dpyinfo->smallest_font_height = 100000;
12678 dpyinfo->smallest_char_width = 100000;
12679
12680 for (i = 0; i < dpyinfo->n_fonts; ++i)
12681 if (dpyinfo->font_table[i].name)
12682 {
12683 struct font_info *fontp = dpyinfo->font_table + i;
12684 int w, h;
12685
12686 font = (XFontStruct *) fontp->font;
12687 xassert (font != (XFontStruct *) ~0);
12688 x_font_min_bounds (font, &w, &h);
12689
12690 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12691 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12692 }
12693
12694 xassert (dpyinfo->smallest_char_width > 0
12695 && dpyinfo->smallest_font_height > 0);
12696
12697 return (dpyinfo->n_fonts == 1
12698 || dpyinfo->smallest_char_width < old_width
12699 || dpyinfo->smallest_font_height < old_height);
12700}
12701
12702
dc43ef94
KH
12703/* Load font named FONTNAME of the size SIZE for frame F, and return a
12704 pointer to the structure font_info while allocating it dynamically.
12705 If SIZE is 0, load any size of font.
12706 If loading is failed, return NULL. */
12707
12708struct font_info *
12709x_load_font (f, fontname, size)
12710 struct frame *f;
12711 register char *fontname;
12712 int size;
12713{
12714 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12715 Lisp_Object font_names;
d645aaa4 12716 int count;
dc43ef94
KH
12717
12718 /* Get a list of all the fonts that match this name. Once we
12719 have a list of matching fonts, we compare them against the fonts
12720 we already have by comparing names. */
09c6077f 12721 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
12722
12723 if (!NILP (font_names))
12724 {
12725 Lisp_Object tail;
12726 int i;
12727
12728 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 12729 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
12730 if (dpyinfo->font_table[i].name
12731 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 12732 XSTRING (XCAR (tail))->data)
06a2c219 12733 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 12734 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
12735 return (dpyinfo->font_table + i);
12736 }
12737
12738 /* Load the font and add it to the table. */
12739 {
12740 char *full_name;
12741 XFontStruct *font;
12742 struct font_info *fontp;
12743 unsigned long value;
06a2c219 12744 int i;
dc43ef94 12745
2da424f1
KH
12746 /* If we have found fonts by x_list_font, load one of them. If
12747 not, we still try to load a font by the name given as FONTNAME
12748 because XListFonts (called in x_list_font) of some X server has
12749 a bug of not finding a font even if the font surely exists and
12750 is loadable by XLoadQueryFont. */
e1d6d5b9 12751 if (size > 0 && !NILP (font_names))
8e713be6 12752 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
12753
12754 BLOCK_INPUT;
d645aaa4 12755 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 12756 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
12757 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12758 {
12759 /* This error is perhaps due to insufficient memory on X
12760 server. Let's just ignore it. */
12761 font = NULL;
12762 x_clear_errors (FRAME_X_DISPLAY (f));
12763 }
12764 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 12765 UNBLOCK_INPUT;
b5210ea7 12766 if (!font)
dc43ef94
KH
12767 return NULL;
12768
06a2c219
GM
12769 /* Find a free slot in the font table. */
12770 for (i = 0; i < dpyinfo->n_fonts; ++i)
12771 if (dpyinfo->font_table[i].name == NULL)
12772 break;
12773
12774 /* If no free slot found, maybe enlarge the font table. */
12775 if (i == dpyinfo->n_fonts
12776 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 12777 {
06a2c219
GM
12778 int sz;
12779 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12780 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 12781 dpyinfo->font_table
06a2c219 12782 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
12783 }
12784
06a2c219
GM
12785 fontp = dpyinfo->font_table + i;
12786 if (i == dpyinfo->n_fonts)
12787 ++dpyinfo->n_fonts;
dc43ef94
KH
12788
12789 /* Now fill in the slots of *FONTP. */
12790 BLOCK_INPUT;
12791 fontp->font = font;
06a2c219 12792 fontp->font_idx = i;
dc43ef94
KH
12793 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12794 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12795
12796 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12797 full_name = 0;
12798 if (XGetFontProperty (font, XA_FONT, &value))
12799 {
12800 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12801 char *p = name;
12802 int dashes = 0;
12803
12804 /* Count the number of dashes in the "full name".
12805 If it is too few, this isn't really the font's full name,
12806 so don't use it.
12807 In X11R4, the fonts did not come with their canonical names
12808 stored in them. */
12809 while (*p)
12810 {
12811 if (*p == '-')
12812 dashes++;
12813 p++;
12814 }
12815
12816 if (dashes >= 13)
12817 {
12818 full_name = (char *) xmalloc (p - name + 1);
12819 bcopy (name, full_name, p - name + 1);
12820 }
12821
12822 XFree (name);
12823 }
12824
12825 if (full_name != 0)
12826 fontp->full_name = full_name;
12827 else
12828 fontp->full_name = fontp->name;
12829
12830 fontp->size = font->max_bounds.width;
d5749adb
KH
12831 fontp->height = FONT_HEIGHT (font);
12832 {
12833 /* For some font, ascent and descent in max_bounds field is
12834 larger than the above value. */
12835 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12836 if (max_height > fontp->height)
74848a96 12837 fontp->height = max_height;
d5749adb 12838 }
dc43ef94 12839
2da424f1
KH
12840 if (NILP (font_names))
12841 {
12842 /* We come here because of a bug of XListFonts mentioned at
12843 the head of this block. Let's store this information in
12844 the cache for x_list_fonts. */
12845 Lisp_Object lispy_name = build_string (fontname);
12846 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12847
8e713be6 12848 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12849 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12850 Fcons (Fcons (lispy_full_name,
12851 make_number (fontp->size)),
12852 Qnil)),
8e713be6 12853 XCDR (dpyinfo->name_list_element));
2da424f1 12854 if (full_name)
8e713be6 12855 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12856 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12857 Fcons (Fcons (lispy_full_name,
12858 make_number (fontp->size)),
12859 Qnil)),
8e713be6 12860 XCDR (dpyinfo->name_list_element));
2da424f1
KH
12861 }
12862
dc43ef94
KH
12863 /* The slot `encoding' specifies how to map a character
12864 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
12865 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12866 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 12867 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 12868 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
12869 which is never used by any charset. If mapping can't be
12870 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
12871 fontp->encoding[1]
12872 = (font->max_byte1 == 0
12873 /* 1-byte font */
12874 ? (font->min_char_or_byte2 < 0x80
12875 ? (font->max_char_or_byte2 < 0x80
12876 ? 0 /* 0x20..0x7F */
8ff102bd 12877 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
12878 : 1) /* 0xA0..0xFF */
12879 /* 2-byte font */
12880 : (font->min_byte1 < 0x80
12881 ? (font->max_byte1 < 0x80
12882 ? (font->min_char_or_byte2 < 0x80
12883 ? (font->max_char_or_byte2 < 0x80
12884 ? 0 /* 0x2020..0x7F7F */
8ff102bd 12885 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 12886 : 3) /* 0x20A0..0x7FFF */
8ff102bd 12887 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
12888 : (font->min_char_or_byte2 < 0x80
12889 ? (font->max_char_or_byte2 < 0x80
12890 ? 2 /* 0xA020..0xFF7F */
8ff102bd 12891 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
12892 : 1))); /* 0xA0A0..0xFFFF */
12893
12894 fontp->baseline_offset
12895 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12896 ? (long) value : 0);
12897 fontp->relative_compose
12898 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12899 ? (long) value : 0);
f78798df
KH
12900 fontp->default_ascent
12901 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12902 ? (long) value : 0);
dc43ef94 12903
06a2c219
GM
12904 /* Set global flag fonts_changed_p to non-zero if the font loaded
12905 has a character with a smaller width than any other character
12906 before, or if the font loaded has a smalle>r height than any
12907 other font loaded before. If this happens, it will make a
12908 glyph matrix reallocation necessary. */
12909 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 12910 UNBLOCK_INPUT;
dc43ef94
KH
12911 return fontp;
12912 }
12913}
12914
06a2c219
GM
12915
12916/* Return a pointer to struct font_info of a font named FONTNAME for
12917 frame F. If no such font is loaded, return NULL. */
12918
dc43ef94
KH
12919struct font_info *
12920x_query_font (f, fontname)
12921 struct frame *f;
12922 register char *fontname;
12923{
12924 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12925 int i;
12926
12927 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
12928 if (dpyinfo->font_table[i].name
12929 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12930 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
12931 return (dpyinfo->font_table + i);
12932 return NULL;
12933}
12934
06a2c219
GM
12935
12936/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
12937 `encoder' of the structure. */
12938
12939void
12940x_find_ccl_program (fontp)
12941 struct font_info *fontp;
12942{
a42f54e6 12943 Lisp_Object list, elt;
a6582676 12944
8e713be6 12945 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 12946 {
8e713be6 12947 elt = XCAR (list);
a6582676 12948 if (CONSP (elt)
8e713be6
KR
12949 && STRINGP (XCAR (elt))
12950 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
a6582676 12951 >= 0))
a42f54e6
KH
12952 break;
12953 }
12954 if (! NILP (list))
12955 {
d27f8ca7
KH
12956 struct ccl_program *ccl
12957 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 12958
8e713be6 12959 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
12960 xfree (ccl);
12961 else
12962 fontp->font_encoder = ccl;
a6582676
KH
12963 }
12964}
12965
06a2c219 12966
dc43ef94 12967\f
06a2c219
GM
12968/***********************************************************************
12969 Initialization
12970 ***********************************************************************/
f451eb13 12971
3afe33e7
RS
12972#ifdef USE_X_TOOLKIT
12973static XrmOptionDescRec emacs_options[] = {
12974 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12975 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12976
12977 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12978 XrmoptionSepArg, NULL},
12979 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12980
12981 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12982 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12983 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12984 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12985 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12986 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12987 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12988};
12989#endif /* USE_X_TOOLKIT */
12990
7a13e894
RS
12991static int x_initialized;
12992
29b38361
KH
12993#ifdef MULTI_KBOARD
12994/* Test whether two display-name strings agree up to the dot that separates
12995 the screen number from the server number. */
12996static int
12997same_x_server (name1, name2)
12998 char *name1, *name2;
12999{
13000 int seen_colon = 0;
cf591cc1
RS
13001 unsigned char *system_name = XSTRING (Vsystem_name)->data;
13002 int system_name_length = strlen (system_name);
13003 int length_until_period = 0;
13004
13005 while (system_name[length_until_period] != 0
13006 && system_name[length_until_period] != '.')
13007 length_until_period++;
13008
13009 /* Treat `unix' like an empty host name. */
13010 if (! strncmp (name1, "unix:", 5))
13011 name1 += 4;
13012 if (! strncmp (name2, "unix:", 5))
13013 name2 += 4;
13014 /* Treat this host's name like an empty host name. */
13015 if (! strncmp (name1, system_name, system_name_length)
13016 && name1[system_name_length] == ':')
13017 name1 += system_name_length;
13018 if (! strncmp (name2, system_name, system_name_length)
13019 && name2[system_name_length] == ':')
13020 name2 += system_name_length;
13021 /* Treat this host's domainless name like an empty host name. */
13022 if (! strncmp (name1, system_name, length_until_period)
13023 && name1[length_until_period] == ':')
13024 name1 += length_until_period;
13025 if (! strncmp (name2, system_name, length_until_period)
13026 && name2[length_until_period] == ':')
13027 name2 += length_until_period;
13028
29b38361
KH
13029 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
13030 {
13031 if (*name1 == ':')
13032 seen_colon++;
13033 if (seen_colon && *name1 == '.')
13034 return 1;
13035 }
13036 return (seen_colon
13037 && (*name1 == '.' || *name1 == '\0')
13038 && (*name2 == '.' || *name2 == '\0'));
13039}
13040#endif
13041
334208b7 13042struct x_display_info *
1f8255f2 13043x_term_init (display_name, xrm_option, resource_name)
334208b7 13044 Lisp_Object display_name;
1f8255f2
RS
13045 char *xrm_option;
13046 char *resource_name;
dc6f92b8 13047{
334208b7 13048 int connection;
7a13e894 13049 Display *dpy;
334208b7
RS
13050 struct x_display_info *dpyinfo;
13051 XrmDatabase xrdb;
13052
60439948
KH
13053 BLOCK_INPUT;
13054
7a13e894
RS
13055 if (!x_initialized)
13056 {
13057 x_initialize ();
13058 x_initialized = 1;
13059 }
dc6f92b8 13060
3afe33e7 13061#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13062 /* weiner@footloose.sps.mot.com reports that this causes
13063 errors with X11R5:
13064 X protocol error: BadAtom (invalid Atom parameter)
13065 on protocol request 18skiloaf.
13066 So let's not use it until R6. */
13067#ifdef HAVE_X11XTR6
bdcd49ba
RS
13068 XtSetLanguageProc (NULL, NULL, NULL);
13069#endif
13070
7f9c7f94
RS
13071 {
13072 int argc = 0;
13073 char *argv[3];
13074
13075 argv[0] = "";
13076 argc = 1;
13077 if (xrm_option)
13078 {
13079 argv[argc++] = "-xrm";
13080 argv[argc++] = xrm_option;
13081 }
13082 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13083 resource_name, EMACS_CLASS,
13084 emacs_options, XtNumber (emacs_options),
13085 &argc, argv);
39d8bb4d
KH
13086
13087#ifdef HAVE_X11XTR6
10537cb1 13088 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13089 fixup_locale ();
39d8bb4d 13090#endif
7f9c7f94 13091 }
3afe33e7
RS
13092
13093#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13094#ifdef HAVE_X11R5
13095 XSetLocaleModifiers ("");
13096#endif
7a13e894 13097 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13098#endif /* not USE_X_TOOLKIT */
334208b7 13099
7a13e894
RS
13100 /* Detect failure. */
13101 if (dpy == 0)
60439948
KH
13102 {
13103 UNBLOCK_INPUT;
13104 return 0;
13105 }
7a13e894
RS
13106
13107 /* We have definitely succeeded. Record the new connection. */
13108
13109 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13110
29b38361
KH
13111#ifdef MULTI_KBOARD
13112 {
13113 struct x_display_info *share;
13114 Lisp_Object tail;
13115
13116 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13117 share = share->next, tail = XCDR (tail))
13118 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13119 XSTRING (display_name)->data))
13120 break;
13121 if (share)
13122 dpyinfo->kboard = share->kboard;
13123 else
13124 {
13125 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13126 init_kboard (dpyinfo->kboard);
59e755be
KH
13127 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13128 {
13129 char *vendor = ServerVendor (dpy);
9b6ed9f3 13130 UNBLOCK_INPUT;
59e755be
KH
13131 dpyinfo->kboard->Vsystem_key_alist
13132 = call1 (Qvendor_specific_keysyms,
13133 build_string (vendor ? vendor : ""));
9b6ed9f3 13134 BLOCK_INPUT;
59e755be
KH
13135 }
13136
29b38361
KH
13137 dpyinfo->kboard->next_kboard = all_kboards;
13138 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13139 /* Don't let the initial kboard remain current longer than necessary.
13140 That would cause problems if a file loaded on startup tries to
06a2c219 13141 prompt in the mini-buffer. */
0ad5446c
KH
13142 if (current_kboard == initial_kboard)
13143 current_kboard = dpyinfo->kboard;
29b38361
KH
13144 }
13145 dpyinfo->kboard->reference_count++;
13146 }
b9737ad3
KH
13147#endif
13148
7a13e894
RS
13149 /* Put this display on the chain. */
13150 dpyinfo->next = x_display_list;
13151 x_display_list = dpyinfo;
13152
13153 /* Put it on x_display_name_list as well, to keep them parallel. */
13154 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13155 x_display_name_list);
8e713be6 13156 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13157
13158 dpyinfo->display = dpy;
dc6f92b8 13159
dc6f92b8 13160#if 0
7a13e894 13161 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13162#endif /* ! 0 */
7a13e894
RS
13163
13164 dpyinfo->x_id_name
fc932ac6
RS
13165 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13166 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13167 + 2);
13168 sprintf (dpyinfo->x_id_name, "%s@%s",
13169 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13170
13171 /* Figure out which modifier bits mean what. */
334208b7 13172 x_find_modifier_meanings (dpyinfo);
f451eb13 13173
ab648270 13174 /* Get the scroll bar cursor. */
7a13e894 13175 dpyinfo->vertical_scroll_bar_cursor
334208b7 13176 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13177
334208b7
RS
13178 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13179 resource_name, EMACS_CLASS);
13180#ifdef HAVE_XRMSETDATABASE
13181 XrmSetDatabase (dpyinfo->display, xrdb);
13182#else
13183 dpyinfo->display->db = xrdb;
13184#endif
547d9db8 13185 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13186 all versions. */
13187 dpyinfo->xrdb = xrdb;
334208b7
RS
13188
13189 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13190 DefaultScreen (dpyinfo->display));
5ff67d81 13191 select_visual (dpyinfo);
43bd1b2b 13192 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13193 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13194 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13195 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13196 dpyinfo->grabbed = 0;
13197 dpyinfo->reference_count = 0;
13198 dpyinfo->icon_bitmap_id = -1;
06a2c219 13199 dpyinfo->font_table = NULL;
7a13e894
RS
13200 dpyinfo->n_fonts = 0;
13201 dpyinfo->font_table_size = 0;
13202 dpyinfo->bitmaps = 0;
13203 dpyinfo->bitmaps_size = 0;
13204 dpyinfo->bitmaps_last = 0;
13205 dpyinfo->scratch_cursor_gc = 0;
13206 dpyinfo->mouse_face_mouse_frame = 0;
13207 dpyinfo->mouse_face_deferred_gc = 0;
13208 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13209 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13210 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13211 dpyinfo->mouse_face_window = Qnil;
13212 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13213 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13214 dpyinfo->x_focus_frame = 0;
13215 dpyinfo->x_focus_event_frame = 0;
13216 dpyinfo->x_highlight_frame = 0;
06a2c219 13217 dpyinfo->image_cache = make_image_cache ();
334208b7 13218
43bd1b2b 13219 /* See if a private colormap is requested. */
5ff67d81
GM
13220 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13221 {
13222 if (dpyinfo->visual->class == PseudoColor)
13223 {
13224 Lisp_Object value;
13225 value = display_x_get_resource (dpyinfo,
13226 build_string ("privateColormap"),
13227 build_string ("PrivateColormap"),
13228 Qnil, Qnil);
13229 if (STRINGP (value)
13230 && (!strcmp (XSTRING (value)->data, "true")
13231 || !strcmp (XSTRING (value)->data, "on")))
13232 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13233 }
43bd1b2b 13234 }
5ff67d81
GM
13235 else
13236 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13237 dpyinfo->visual, AllocNone);
43bd1b2b 13238
06a2c219
GM
13239 {
13240 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13241 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13242 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13243 dpyinfo->resy = pixels * 25.4 / mm;
13244 pixels = DisplayWidth (dpyinfo->display, screen_number);
13245 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13246 dpyinfo->resx = pixels * 25.4 / mm;
13247 }
13248
334208b7
RS
13249 dpyinfo->Xatom_wm_protocols
13250 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13251 dpyinfo->Xatom_wm_take_focus
13252 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13253 dpyinfo->Xatom_wm_save_yourself
13254 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13255 dpyinfo->Xatom_wm_delete_window
13256 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13257 dpyinfo->Xatom_wm_change_state
13258 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13259 dpyinfo->Xatom_wm_configure_denied
13260 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13261 dpyinfo->Xatom_wm_window_moved
13262 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13263 dpyinfo->Xatom_editres
13264 = XInternAtom (dpyinfo->display, "Editres", False);
13265 dpyinfo->Xatom_CLIPBOARD
13266 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13267 dpyinfo->Xatom_TIMESTAMP
13268 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13269 dpyinfo->Xatom_TEXT
13270 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13271 dpyinfo->Xatom_COMPOUND_TEXT
13272 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13273 dpyinfo->Xatom_DELETE
13274 = XInternAtom (dpyinfo->display, "DELETE", False);
13275 dpyinfo->Xatom_MULTIPLE
13276 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13277 dpyinfo->Xatom_INCR
13278 = XInternAtom (dpyinfo->display, "INCR", False);
13279 dpyinfo->Xatom_EMACS_TMP
13280 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13281 dpyinfo->Xatom_TARGETS
13282 = XInternAtom (dpyinfo->display, "TARGETS", False);
13283 dpyinfo->Xatom_NULL
13284 = XInternAtom (dpyinfo->display, "NULL", False);
13285 dpyinfo->Xatom_ATOM_PAIR
13286 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13287 /* For properties of font. */
13288 dpyinfo->Xatom_PIXEL_SIZE
13289 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13290 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13291 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13292 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13293 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13294 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13295 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13296
06a2c219
GM
13297 /* Ghostscript support. */
13298 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13299 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13300
13301 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13302 False);
13303
547d9db8
KH
13304 dpyinfo->cut_buffers_initialized = 0;
13305
334208b7
RS
13306 connection = ConnectionNumber (dpyinfo->display);
13307 dpyinfo->connection = connection;
13308
dc43ef94 13309 {
5d7cc324
RS
13310 char null_bits[1];
13311
13312 null_bits[0] = 0x00;
dc43ef94
KH
13313
13314 dpyinfo->null_pixel
13315 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13316 null_bits, 1, 1, (long) 0, (long) 0,
13317 1);
13318 }
13319
06a2c219
GM
13320 {
13321 extern int gray_bitmap_width, gray_bitmap_height;
13322 extern unsigned char *gray_bitmap_bits;
13323 dpyinfo->gray
13324 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13325 gray_bitmap_bits,
13326 gray_bitmap_width, gray_bitmap_height,
13327 (unsigned long) 1, (unsigned long) 0, 1);
13328 }
13329
f5d11644
GM
13330#ifdef HAVE_X_I18N
13331 xim_initialize (dpyinfo, resource_name);
13332#endif
13333
87485d6f
MW
13334#ifdef subprocesses
13335 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13336 if (connection != 0)
7a13e894 13337 add_keyboard_wait_descriptor (connection);
87485d6f 13338#endif
6d4238f3 13339
041b69ac 13340#ifndef F_SETOWN_BUG
dc6f92b8 13341#ifdef F_SETOWN
dc6f92b8 13342#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13343 /* stdin is a socket here */
334208b7 13344 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13345#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13346 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13347#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13348#endif /* ! defined (F_SETOWN) */
041b69ac 13349#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13350
13351#ifdef SIGIO
eee20f6a
KH
13352 if (interrupt_input)
13353 init_sigio (connection);
c118dd06 13354#endif /* ! defined (SIGIO) */
dc6f92b8 13355
51b592fb 13356#ifdef USE_LUCID
f8c39f51 13357#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13358 /* Make sure that we have a valid font for dialog boxes
13359 so that Xt does not crash. */
13360 {
13361 Display *dpy = dpyinfo->display;
13362 XrmValue d, fr, to;
13363 Font font;
e99db5a1 13364 int count;
51b592fb
RS
13365
13366 d.addr = (XPointer)&dpy;
13367 d.size = sizeof (Display *);
13368 fr.addr = XtDefaultFont;
13369 fr.size = sizeof (XtDefaultFont);
13370 to.size = sizeof (Font *);
13371 to.addr = (XPointer)&font;
e99db5a1 13372 count = x_catch_errors (dpy);
51b592fb
RS
13373 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13374 abort ();
13375 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13376 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13377 x_uncatch_errors (dpy, count);
51b592fb
RS
13378 }
13379#endif
f8c39f51 13380#endif
51b592fb 13381
34e23e5a
GM
13382 /* See if we should run in synchronous mode. This is useful
13383 for debugging X code. */
13384 {
13385 Lisp_Object value;
13386 value = display_x_get_resource (dpyinfo,
13387 build_string ("synchronous"),
13388 build_string ("Synchronous"),
13389 Qnil, Qnil);
13390 if (STRINGP (value)
13391 && (!strcmp (XSTRING (value)->data, "true")
13392 || !strcmp (XSTRING (value)->data, "on")))
13393 XSynchronize (dpyinfo->display, True);
13394 }
13395
60439948
KH
13396 UNBLOCK_INPUT;
13397
7a13e894
RS
13398 return dpyinfo;
13399}
13400\f
13401/* Get rid of display DPYINFO, assuming all frames are already gone,
13402 and without sending any more commands to the X server. */
dc6f92b8 13403
7a13e894
RS
13404void
13405x_delete_display (dpyinfo)
13406 struct x_display_info *dpyinfo;
13407{
13408 delete_keyboard_wait_descriptor (dpyinfo->connection);
13409
13410 /* Discard this display from x_display_name_list and x_display_list.
13411 We can't use Fdelq because that can quit. */
13412 if (! NILP (x_display_name_list)
8e713be6
KR
13413 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13414 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13415 else
13416 {
13417 Lisp_Object tail;
13418
13419 tail = x_display_name_list;
8e713be6 13420 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13421 {
bffcfca9 13422 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13423 {
8e713be6 13424 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13425 break;
13426 }
8e713be6 13427 tail = XCDR (tail);
7a13e894
RS
13428 }
13429 }
13430
9bda743f
GM
13431 if (next_noop_dpyinfo == dpyinfo)
13432 next_noop_dpyinfo = dpyinfo->next;
13433
7a13e894
RS
13434 if (x_display_list == dpyinfo)
13435 x_display_list = dpyinfo->next;
7f9c7f94
RS
13436 else
13437 {
13438 struct x_display_info *tail;
7a13e894 13439
7f9c7f94
RS
13440 for (tail = x_display_list; tail; tail = tail->next)
13441 if (tail->next == dpyinfo)
13442 tail->next = tail->next->next;
13443 }
7a13e894 13444
0d777288
RS
13445#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13446#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13447 XrmDestroyDatabase (dpyinfo->xrdb);
13448#endif
0d777288 13449#endif
29b38361
KH
13450#ifdef MULTI_KBOARD
13451 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13452 delete_kboard (dpyinfo->kboard);
b9737ad3 13453#endif
f5d11644
GM
13454#ifdef HAVE_X_I18N
13455 if (dpyinfo->xim)
13456 xim_close_dpy (dpyinfo);
13457#endif
13458
b9737ad3
KH
13459 xfree (dpyinfo->font_table);
13460 xfree (dpyinfo->x_id_name);
13461 xfree (dpyinfo);
7a13e894
RS
13462}
13463\f
13464/* Set up use of X before we make the first connection. */
13465
06a2c219
GM
13466static struct redisplay_interface x_redisplay_interface =
13467{
13468 x_produce_glyphs,
13469 x_write_glyphs,
13470 x_insert_glyphs,
13471 x_clear_end_of_line,
13472 x_scroll_run,
13473 x_after_update_window_line,
13474 x_update_window_begin,
13475 x_update_window_end,
13476 XTcursor_to,
13477 x_flush,
71b8321e 13478 x_clear_mouse_face,
66ac4b0e
GM
13479 x_get_glyph_overhangs,
13480 x_fix_overlapping_area
06a2c219
GM
13481};
13482
dfcf069d 13483void
7a13e894
RS
13484x_initialize ()
13485{
06a2c219
GM
13486 rif = &x_redisplay_interface;
13487
13488 clear_frame_hook = x_clear_frame;
13489 ins_del_lines_hook = x_ins_del_lines;
13490 change_line_highlight_hook = x_change_line_highlight;
13491 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13492 ring_bell_hook = XTring_bell;
13493 reset_terminal_modes_hook = XTreset_terminal_modes;
13494 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13495 update_begin_hook = x_update_begin;
13496 update_end_hook = x_update_end;
dc6f92b8
JB
13497 set_terminal_window_hook = XTset_terminal_window;
13498 read_socket_hook = XTread_socket;
b8009dd1 13499 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13500 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13501 mouse_position_hook = XTmouse_position;
f451eb13 13502 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13503 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13504 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13505 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13506 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13507 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13508 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13509
f676886a 13510 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13511 char_ins_del_ok = 0; /* just as fast to write the line */
13512 line_ins_del_ok = 1; /* we'll just blt 'em */
13513 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13514 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13515 off the bottom */
13516 baud_rate = 19200;
13517
7a13e894 13518 x_noop_count = 0;
9ea173e8 13519 last_tool_bar_item = -1;
06a2c219
GM
13520 any_help_event_p = 0;
13521
b30b24cb
RS
13522 /* Try to use interrupt input; if we can't, then start polling. */
13523 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13524
7f9c7f94
RS
13525#ifdef USE_X_TOOLKIT
13526 XtToolkitInitialize ();
13527 Xt_app_con = XtCreateApplicationContext ();
665881ad 13528 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13529
13530 /* Install an asynchronous timer that processes Xt timeout events
13531 every 0.1s. This is necessary because some widget sets use
13532 timeouts internally, for example the LessTif menu bar, or the
13533 Xaw3d scroll bar. When Xt timouts aren't processed, these
13534 widgets don't behave normally. */
13535 {
13536 EMACS_TIME interval;
13537 EMACS_SET_SECS_USECS (interval, 0, 100000);
13538 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13539 }
db74249b 13540#endif
bffcfca9 13541
db74249b 13542#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13543 xaw3d_arrow_scroll = False;
13544 xaw3d_pick_top = True;
7f9c7f94
RS
13545#endif
13546
58769bee 13547 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13548 original error handler. */
e99db5a1 13549 XSetErrorHandler (x_error_handler);
334208b7 13550 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13551
06a2c219 13552 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13553#ifdef SIGWINCH
13554 signal (SIGWINCH, SIG_DFL);
c118dd06 13555#endif /* ! defined (SIGWINCH) */
dc6f92b8 13556
92e2441b 13557 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13558}
55123275 13559
06a2c219 13560
55123275
JB
13561void
13562syms_of_xterm ()
13563{
e99db5a1
RS
13564 staticpro (&x_error_message_string);
13565 x_error_message_string = Qnil;
13566
7a13e894
RS
13567 staticpro (&x_display_name_list);
13568 x_display_name_list = Qnil;
334208b7 13569
ab648270 13570 staticpro (&last_mouse_scroll_bar);
e53cb100 13571 last_mouse_scroll_bar = Qnil;
59e755be
KH
13572
13573 staticpro (&Qvendor_specific_keysyms);
13574 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13575
13576 staticpro (&last_mouse_press_frame);
13577 last_mouse_press_frame = Qnil;
06a2c219
GM
13578
13579 staticpro (&help_echo);
13580 help_echo = Qnil;
13581 staticpro (&previous_help_echo);
13582 previous_help_echo = Qnil;
13583
13584 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13585 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13586For example, if a block cursor is over a tab, it will be drawn as\n\
13587wide as that tab on the display.");
13588 x_stretch_cursor_p = 0;
13589
13590 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13591 "If not nil, Emacs uses toolkit scroll bars.");
13592#if USE_TOOLKIT_SCROLL_BARS
13593 x_toolkit_scroll_bars_p = 1;
13594#else
13595 x_toolkit_scroll_bars_p = 0;
13596#endif
13597
06a2c219
GM
13598 staticpro (&last_mouse_motion_frame);
13599 last_mouse_motion_frame = Qnil;
55123275 13600}
6cf0ae86
RS
13601
13602#endif /* not HAVE_X_WINDOWS */
06a2c219 13603