(x_window) [!USE_XIM]: Don't call create_frame_ic.
[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
401static void x_update_window_end P_ ((struct window *, int));
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
601 /* Can we tell that this update does not affect the window
602 where the mouse highlight is? If so, no need to turn off.
603 Likewise, don't do anything if the frame is garbaged;
604 in that case, the frame's current matrix that we would use
605 is all wrong, and we will redisplay that line anyway. */
606 if (!NILP (display_info->mouse_face_window)
607 && w == XWINDOW (display_info->mouse_face_window))
514e4681 608 {
06a2c219 609 int i;
514e4681 610
06a2c219
GM
611 for (i = 0; i < w->desired_matrix->nrows; ++i)
612 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
613 break;
614
06a2c219
GM
615 if (i < w->desired_matrix->nrows)
616 clear_mouse_face (display_info);
514e4681 617 }
b8009dd1 618 }
6ccf47d1 619
dc6f92b8
JB
620 UNBLOCK_INPUT;
621}
622
06a2c219
GM
623
624/* Draw a vertical window border to the right of window W if W doesn't
625 have vertical scroll bars. */
626
dfcf069d 627static void
06a2c219
GM
628x_draw_vertical_border (w)
629 struct window *w;
58769bee 630{
06a2c219
GM
631 struct frame *f = XFRAME (WINDOW_FRAME (w));
632
633 /* Redraw borders between horizontally adjacent windows. Don't
634 do it for frames with vertical scroll bars because either the
635 right scroll bar of a window, or the left scroll bar of its
636 neighbor will suffice as a border. */
637 if (!WINDOW_RIGHTMOST_P (w)
638 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
639 {
640 int x0, x1, y0, y1;
dc6f92b8 641
06a2c219 642 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
110859fc 643 x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
644 y1 -= 1;
645
646 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
647 f->output_data.x->normal_gc, x1, y0, x1, y1);
648 }
649}
650
651
652/* End update of window W (which is equal to updated_window). Draw
653 vertical borders between horizontally adjacent windows, and display
654 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
655 pseudo-window in case we don't have X toolkit support. Such
656 windows don't have a cursor, so don't display it here. */
657
658static void
659x_update_window_end (w, cursor_on_p)
660 struct window *w;
661 int cursor_on_p;
662{
663 if (!w->pseudo_window_p)
664 {
665 BLOCK_INPUT;
666 if (cursor_on_p)
667 x_display_and_set_cursor (w, 1, output_cursor.hpos,
668 output_cursor.vpos,
669 output_cursor.x, output_cursor.y);
670 x_draw_vertical_border (w);
671 UNBLOCK_INPUT;
672 }
673
674 updated_window = NULL;
675}
dc6f92b8 676
dc6f92b8 677
06a2c219
GM
678/* End update of frame F. This function is installed as a hook in
679 update_end. */
680
681static void
682x_update_end (f)
683 struct frame *f;
684{
685 /* Mouse highlight may be displayed again. */
aa8bff2e 686 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 687
06a2c219 688 BLOCK_INPUT;
334208b7 689 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
690 UNBLOCK_INPUT;
691}
b8009dd1 692
06a2c219
GM
693
694/* This function is called from various places in xdisp.c whenever a
695 complete update has been performed. The global variable
696 updated_window is not available here. */
b8009dd1 697
dfcf069d 698static void
b8009dd1 699XTframe_up_to_date (f)
06a2c219 700 struct frame *f;
b8009dd1 701{
06a2c219 702 if (FRAME_X_P (f))
514e4681 703 {
06a2c219
GM
704 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
705 if (dpyinfo->mouse_face_deferred_gc
706 || f == dpyinfo->mouse_face_mouse_frame)
707 {
708 BLOCK_INPUT;
709 if (dpyinfo->mouse_face_mouse_frame)
710 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
711 dpyinfo->mouse_face_mouse_x,
712 dpyinfo->mouse_face_mouse_y);
713 dpyinfo->mouse_face_deferred_gc = 0;
714 UNBLOCK_INPUT;
715 }
514e4681 716 }
b8009dd1 717}
06a2c219
GM
718
719
720/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
721 arrow bitmaps, or clear the areas where they would be displayed
722 before DESIRED_ROW is made current. The window being updated is
723 found in updated_window. This function It is called from
724 update_window_line only if it is known that there are differences
725 between bitmaps to be drawn between current row and DESIRED_ROW. */
726
727static void
728x_after_update_window_line (desired_row)
729 struct glyph_row *desired_row;
730{
731 struct window *w = updated_window;
732
733 xassert (w);
734
735 if (!desired_row->mode_line_p && !w->pseudo_window_p)
736 {
737 BLOCK_INPUT;
738 x_draw_row_bitmaps (w, desired_row);
739
740 /* When a window has disappeared, make sure that no rest of
741 full-width rows stays visible in the internal border. */
742 if (windows_or_buffers_changed)
743 {
744 struct frame *f = XFRAME (w->frame);
745 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
746 int height = desired_row->visible_height;
110859fc
GM
747 int x = (window_box_right (w, -1)
748 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
749 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
750
751 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
752 x, y, width, height, False);
753 }
754
755 UNBLOCK_INPUT;
756 }
757}
758
759
760/* Draw the bitmap WHICH in one of the areas to the left or right of
761 window W. ROW is the glyph row for which to display the bitmap; it
762 determines the vertical position at which the bitmap has to be
763 drawn. */
764
765static void
766x_draw_bitmap (w, row, which)
767 struct window *w;
768 struct glyph_row *row;
769 enum bitmap_type which;
770{
771 struct frame *f = XFRAME (WINDOW_FRAME (w));
772 Display *display = FRAME_X_DISPLAY (f);
773 Window window = FRAME_X_WINDOW (f);
774 int x, y, wd, h, dy;
775 unsigned char *bits;
776 Pixmap pixmap;
777 GC gc = f->output_data.x->normal_gc;
778 struct face *face;
779 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
780
781 /* Must clip because of partially visible lines. */
782 x_clip_to_row (w, row, gc, 1);
783
784 switch (which)
785 {
786 case LEFT_TRUNCATION_BITMAP:
787 wd = left_width;
788 h = left_height;
789 bits = left_bits;
790 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
791 - wd
110859fc 792 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
793 break;
794
795 case OVERLAY_ARROW_BITMAP:
796 wd = left_width;
797 h = left_height;
798 bits = ov_bits;
799 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
800 - wd
110859fc 801 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
802 break;
803
804 case RIGHT_TRUNCATION_BITMAP:
805 wd = right_width;
806 h = right_height;
807 bits = right_bits;
808 x = window_box_right (w, -1);
110859fc 809 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
810 break;
811
812 case CONTINUED_LINE_BITMAP:
813 wd = right_width;
814 h = right_height;
815 bits = continued_bits;
816 x = window_box_right (w, -1);
110859fc 817 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
06a2c219
GM
818 break;
819
820 case CONTINUATION_LINE_BITMAP:
821 wd = continuation_width;
822 h = continuation_height;
823 bits = continuation_bits;
824 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
825 - wd
110859fc 826 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
827 break;
828
829 case ZV_LINE_BITMAP:
830 wd = zv_width;
831 h = zv_height;
832 bits = zv_bits;
833 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
834 - wd
110859fc 835 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
06a2c219
GM
836 break;
837
838 default:
839 abort ();
840 }
841
842 /* Convert to frame coordinates. Set dy to the offset in the row to
843 start drawing the bitmap. */
844 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
845 dy = (row->height - h) / 2;
846
847 /* Draw the bitmap. I believe these small pixmaps can be cached
848 by the server. */
849 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
850 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
851 face->foreground,
852 face->background, depth);
853 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
854 XFreePixmap (display, pixmap);
855 XSetClipMask (display, gc, None);
856}
857
858
859/* Draw flags bitmaps for glyph row ROW on window W. Call this
860 function with input blocked. */
861
862static void
863x_draw_row_bitmaps (w, row)
864 struct window *w;
865 struct glyph_row *row;
866{
867 struct frame *f = XFRAME (w->frame);
868 enum bitmap_type bitmap;
869 struct face *face;
045dee35 870 int header_line_height = -1;
06a2c219
GM
871
872 xassert (interrupt_input_blocked);
873
874 /* If row is completely invisible, because of vscrolling, we
875 don't have to draw anything. */
876 if (row->visible_height <= 0)
877 return;
878
879 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
880 PREPARE_FACE_FOR_DISPLAY (f, face);
881
882 /* Decide which bitmap to draw at the left side. */
883 if (row->overlay_arrow_p)
884 bitmap = OVERLAY_ARROW_BITMAP;
885 else if (row->truncated_on_left_p)
886 bitmap = LEFT_TRUNCATION_BITMAP;
887 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
888 bitmap = CONTINUATION_LINE_BITMAP;
889 else if (row->indicate_empty_line_p)
890 bitmap = ZV_LINE_BITMAP;
891 else
892 bitmap = NO_BITMAP;
893
894 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
895 the flags area. */
896 if (bitmap == NO_BITMAP
110859fc 897 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
898 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
899 {
900 /* If W has a vertical border to its left, don't draw over it. */
901 int border = ((XFASTINT (w->left) > 0
902 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
903 ? 1 : 0);
904 int left = window_box_left (w, -1);
905
045dee35
GM
906 if (header_line_height < 0)
907 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
908
909 /* In case the same realized face is used for bitmap areas and
910 for something displayed in the text (e.g. face `region' on
911 mono-displays, the fill style may have been changed to
912 FillSolid in x_draw_glyph_string_background. */
913 if (face->stipple)
914 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
915 else
916 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
917
06a2c219
GM
918 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
919 face->gc,
920 (left
110859fc 921 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
06a2c219 922 + border),
045dee35 923 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 924 row->y)),
110859fc 925 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
06a2c219 926 row->visible_height);
dcd08bfb
GM
927 if (!face->stipple)
928 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
929 }
930
931 /* Draw the left bitmap. */
932 if (bitmap != NO_BITMAP)
933 x_draw_bitmap (w, row, bitmap);
934
935 /* Decide which bitmap to draw at the right side. */
936 if (row->truncated_on_right_p)
937 bitmap = RIGHT_TRUNCATION_BITMAP;
938 else if (row->continued_p)
939 bitmap = CONTINUED_LINE_BITMAP;
940 else
941 bitmap = NO_BITMAP;
942
943 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
944 the flags area. */
945 if (bitmap == NO_BITMAP
110859fc 946 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
06a2c219
GM
947 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
948 {
949 int right = window_box_right (w, -1);
950
045dee35
GM
951 if (header_line_height < 0)
952 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dcd08bfb
GM
953
954 /* In case the same realized face is used for bitmap areas and
955 for something displayed in the text (e.g. face `region' on
956 mono-displays, the fill style may have been changed to
957 FillSolid in x_draw_glyph_string_background. */
958 if (face->stipple)
959 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
960 else
961 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
962 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
963 face->gc,
964 right,
045dee35 965 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219 966 row->y)),
110859fc 967 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
06a2c219 968 row->visible_height);
dcd08bfb
GM
969 if (!face->stipple)
970 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
971 }
972
973 /* Draw the right bitmap. */
974 if (bitmap != NO_BITMAP)
975 x_draw_bitmap (w, row, bitmap);
976}
977
dc6f92b8 978\f
06a2c219
GM
979/***********************************************************************
980 Line Highlighting
981 ***********************************************************************/
dc6f92b8 982
06a2c219
GM
983/* External interface to control of standout mode. Not used for X
984 frames. Aborts when called. */
985
986static void
dc6f92b8
JB
987XTreassert_line_highlight (new, vpos)
988 int new, vpos;
989{
06a2c219 990 abort ();
dc6f92b8
JB
991}
992
06a2c219
GM
993
994/* Call this when about to modify line at position VPOS and change
995 whether it is highlighted. Not used for X frames. Aborts when
996 called. */
dc6f92b8 997
dfcf069d 998static void
06a2c219
GM
999x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1000 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1001{
06a2c219 1002 abort ();
dc6f92b8
JB
1003}
1004
06a2c219
GM
1005
1006/* This is called when starting Emacs and when restarting after
1007 suspend. When starting Emacs, no X window is mapped. And nothing
1008 must be done to Emacs's own window if it is suspended (though that
1009 rarely happens). */
dc6f92b8 1010
dfcf069d 1011static void
dc6f92b8
JB
1012XTset_terminal_modes ()
1013{
1014}
1015
06a2c219
GM
1016/* This is called when exiting or suspending Emacs. Exiting will make
1017 the X-windows go away, and suspending requires no action. */
dc6f92b8 1018
dfcf069d 1019static void
dc6f92b8
JB
1020XTreset_terminal_modes ()
1021{
dc6f92b8 1022}
06a2c219
GM
1023
1024
dc6f92b8 1025\f
06a2c219
GM
1026/***********************************************************************
1027 Output Cursor
1028 ***********************************************************************/
1029
1030/* Set the global variable output_cursor to CURSOR. All cursor
1031 positions are relative to updated_window. */
dc6f92b8 1032
dfcf069d 1033static void
06a2c219
GM
1034set_output_cursor (cursor)
1035 struct cursor_pos *cursor;
dc6f92b8 1036{
06a2c219
GM
1037 output_cursor.hpos = cursor->hpos;
1038 output_cursor.vpos = cursor->vpos;
1039 output_cursor.x = cursor->x;
1040 output_cursor.y = cursor->y;
1041}
1042
1043
1044/* Set a nominal cursor position.
dc6f92b8 1045
06a2c219
GM
1046 HPOS and VPOS are column/row positions in a window glyph matrix. X
1047 and Y are window text area relative pixel positions.
1048
1049 If this is done during an update, updated_window will contain the
1050 window that is being updated and the position is the future output
1051 cursor position for that window. If updated_window is null, use
1052 selected_window and display the cursor at the given position. */
1053
1054static void
1055XTcursor_to (vpos, hpos, y, x)
1056 int vpos, hpos, y, x;
1057{
1058 struct window *w;
1059
1060 /* If updated_window is not set, work on selected_window. */
1061 if (updated_window)
1062 w = updated_window;
1063 else
1064 w = XWINDOW (selected_window);
dbcb258a 1065
06a2c219
GM
1066 /* Set the output cursor. */
1067 output_cursor.hpos = hpos;
1068 output_cursor.vpos = vpos;
1069 output_cursor.x = x;
1070 output_cursor.y = y;
dc6f92b8 1071
06a2c219
GM
1072 /* If not called as part of an update, really display the cursor.
1073 This will also set the cursor position of W. */
1074 if (updated_window == NULL)
dc6f92b8
JB
1075 {
1076 BLOCK_INPUT;
06a2c219 1077 x_display_cursor (w, 1, hpos, vpos, x, y);
b86bd3dd 1078 XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
dc6f92b8
JB
1079 UNBLOCK_INPUT;
1080 }
1081}
dc43ef94 1082
06a2c219
GM
1083
1084\f
1085/***********************************************************************
1086 Display Iterator
1087 ***********************************************************************/
1088
1089/* Function prototypes of this page. */
1090
1091static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1092 struct glyph *,
ee569018
KH
1093 XChar2b *,
1094 int *));
06a2c219
GM
1095static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1096 int, XChar2b *, int));
1097static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1098static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
1099static void x_append_glyph P_ ((struct it *));
b4192550 1100static void x_append_composite_glyph P_ ((struct it *));
06a2c219
GM
1101static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1102 int, int, double));
1103static void x_produce_glyphs P_ ((struct it *));
06a2c219 1104static void x_produce_image_glyph P_ ((struct it *it));
ee569018
KH
1105
1106
1107/* Return a pointer to per-char metric information in FONT of a
1108 character pointed by B which is a pointer to an XChar2b. */
1109
1110#define PER_CHAR_METRIC(font, b) \
1111 ((font)->per_char \
1112 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1113 + (((font)->min_byte1 || (font)->max_byte1) \
1114 ? (((b)->byte1 - (font)->min_byte1) \
1115 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1116 : 0)) \
1117 : &((font)->max_bounds))
dc43ef94 1118
dc6f92b8 1119
e2ef8ee6
GM
1120/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1121 is not contained in the font. */
dc43ef94 1122
06a2c219 1123static INLINE XCharStruct *
ee569018 1124x_per_char_metric (font, char2b)
06a2c219
GM
1125 XFontStruct *font;
1126 XChar2b *char2b;
1127{
1128 /* The result metric information. */
1129 XCharStruct *pcm = NULL;
dc6f92b8 1130
06a2c219 1131 xassert (font && char2b);
dc6f92b8 1132
06a2c219 1133 if (font->per_char != NULL)
dc6f92b8 1134 {
06a2c219 1135 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1136 {
06a2c219
GM
1137 /* min_char_or_byte2 specifies the linear character index
1138 corresponding to the first element of the per_char array,
1139 max_char_or_byte2 is the index of the last character. A
1140 character with non-zero CHAR2B->byte1 is not in the font.
1141 A character with byte2 less than min_char_or_byte2 or
1142 greater max_char_or_byte2 is not in the font. */
1143 if (char2b->byte1 == 0
1144 && char2b->byte2 >= font->min_char_or_byte2
1145 && char2b->byte2 <= font->max_char_or_byte2)
1146 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1147 }
06a2c219 1148 else
dc6f92b8 1149 {
06a2c219
GM
1150 /* If either min_byte1 or max_byte1 are nonzero, both
1151 min_char_or_byte2 and max_char_or_byte2 are less than
1152 256, and the 2-byte character index values corresponding
1153 to the per_char array element N (counting from 0) are:
1154
1155 byte1 = N/D + min_byte1
1156 byte2 = N\D + min_char_or_byte2
1157
1158 where:
1159
1160 D = max_char_or_byte2 - min_char_or_byte2 + 1
1161 / = integer division
1162 \ = integer modulus */
1163 if (char2b->byte1 >= font->min_byte1
1164 && char2b->byte1 <= font->max_byte1
1165 && char2b->byte2 >= font->min_char_or_byte2
1166 && char2b->byte2 <= font->max_char_or_byte2)
1167 {
1168 pcm = (font->per_char
1169 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1170 * (char2b->byte1 - font->min_byte1))
1171 + (char2b->byte2 - font->min_char_or_byte2));
1172 }
dc6f92b8 1173 }
06a2c219
GM
1174 }
1175 else
1176 {
1177 /* If the per_char pointer is null, all glyphs between the first
1178 and last character indexes inclusive have the same
1179 information, as given by both min_bounds and max_bounds. */
1180 if (char2b->byte2 >= font->min_char_or_byte2
1181 && char2b->byte2 <= font->max_char_or_byte2)
1182 pcm = &font->max_bounds;
1183 }
dc6f92b8 1184
ee569018 1185 return ((pcm == NULL
3e71d8f2 1186 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
ee569018 1187 ? NULL : pcm);
06a2c219 1188}
b73b6aaf 1189
57b03282 1190
06a2c219
GM
1191/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1192 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1193
06a2c219
GM
1194static INLINE void
1195x_encode_char (c, char2b, font_info)
1196 int c;
1197 XChar2b *char2b;
1198 struct font_info *font_info;
1199{
1200 int charset = CHAR_CHARSET (c);
1201 XFontStruct *font = font_info->font;
1202
1203 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1204 This may be either a program in a special encoder language or a
1205 fixed encoding. */
1206 if (font_info->font_encoder)
1207 {
1208 /* It's a program. */
1209 struct ccl_program *ccl = font_info->font_encoder;
1210
1211 if (CHARSET_DIMENSION (charset) == 1)
1212 {
1213 ccl->reg[0] = charset;
1214 ccl->reg[1] = char2b->byte2;
1215 }
1216 else
1217 {
1218 ccl->reg[0] = charset;
1219 ccl->reg[1] = char2b->byte1;
1220 ccl->reg[2] = char2b->byte2;
1221 }
1222
1223 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1224
1225 /* We assume that MSBs are appropriately set/reset by CCL
1226 program. */
1227 if (font->max_byte1 == 0) /* 1-byte font */
ee569018 1228 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
06a2c219
GM
1229 else
1230 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1231 }
1232 else if (font_info->encoding[charset])
1233 {
1234 /* Fixed encoding scheme. See fontset.h for the meaning of the
1235 encoding numbers. */
1236 int enc = font_info->encoding[charset];
1237
1238 if ((enc == 1 || enc == 2)
1239 && CHARSET_DIMENSION (charset) == 2)
1240 char2b->byte1 |= 0x80;
1241
1242 if (enc == 1 || enc == 3)
1243 char2b->byte2 |= 0x80;
1244 }
1245}
1246
1247
1248/* Get face and two-byte form of character C in face FACE_ID on frame
1249 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1250 means we want to display multibyte text. Value is a pointer to a
1251 realized face that is ready for display. */
1252
1253static INLINE struct face *
1254x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1255 struct frame *f;
1256 int c, face_id;
1257 XChar2b *char2b;
1258 int multibyte_p;
1259{
1260 struct face *face = FACE_FROM_ID (f, face_id);
1261
1262 if (!multibyte_p)
1263 {
1264 /* Unibyte case. We don't have to encode, but we have to make
1265 sure to use a face suitable for unibyte. */
1266 char2b->byte1 = 0;
1267 char2b->byte2 = c;
ee569018
KH
1268 face_id = FACE_FOR_CHAR (f, face, c);
1269 face = FACE_FROM_ID (f, face_id);
06a2c219
GM
1270 }
1271 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1272 {
1273 /* Case of ASCII in a face known to fit ASCII. */
1274 char2b->byte1 = 0;
1275 char2b->byte2 = c;
1276 }
1277 else
1278 {
1279 int c1, c2, charset;
1280
1281 /* Split characters into bytes. If c2 is -1 afterwards, C is
1282 really a one-byte character so that byte1 is zero. */
1283 SPLIT_CHAR (c, charset, c1, c2);
1284 if (c2 > 0)
1285 char2b->byte1 = c1, char2b->byte2 = c2;
1286 else
1287 char2b->byte1 = 0, char2b->byte2 = c1;
1288
06a2c219 1289 /* Maybe encode the character in *CHAR2B. */
ee569018 1290 if (face->font != NULL)
06a2c219
GM
1291 {
1292 struct font_info *font_info
1293 = FONT_INFO_FROM_ID (f, face->font_info_id);
1294 if (font_info)
ee569018 1295 x_encode_char (c, char2b, font_info);
06a2c219
GM
1296 }
1297 }
1298
1299 /* Make sure X resources of the face are allocated. */
1300 xassert (face != NULL);
1301 PREPARE_FACE_FOR_DISPLAY (f, face);
1302
1303 return face;
1304}
1305
1306
1307/* Get face and two-byte form of character glyph GLYPH on frame F.
43d120d8 1308 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
06a2c219
GM
1309 a pointer to a realized face that is ready for display. */
1310
1311static INLINE struct face *
ee569018 1312x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
06a2c219
GM
1313 struct frame *f;
1314 struct glyph *glyph;
1315 XChar2b *char2b;
ee569018 1316 int *two_byte_p;
06a2c219
GM
1317{
1318 struct face *face;
1319
1320 xassert (glyph->type == CHAR_GLYPH);
43d120d8 1321 face = FACE_FROM_ID (f, glyph->face_id);
06a2c219 1322
ee569018
KH
1323 if (two_byte_p)
1324 *two_byte_p = 0;
1325
06a2c219
GM
1326 if (!glyph->multibyte_p)
1327 {
1328 /* Unibyte case. We don't have to encode, but we have to make
1329 sure to use a face suitable for unibyte. */
1330 char2b->byte1 = 0;
43d120d8 1331 char2b->byte2 = glyph->u.ch;
06a2c219 1332 }
43d120d8
KH
1333 else if (glyph->u.ch < 128
1334 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
06a2c219
GM
1335 {
1336 /* Case of ASCII in a face known to fit ASCII. */
1337 char2b->byte1 = 0;
43d120d8 1338 char2b->byte2 = glyph->u.ch;
06a2c219
GM
1339 }
1340 else
1341 {
1342 int c1, c2, charset;
1343
1344 /* Split characters into bytes. If c2 is -1 afterwards, C is
1345 really a one-byte character so that byte1 is zero. */
43d120d8 1346 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
06a2c219
GM
1347 if (c2 > 0)
1348 char2b->byte1 = c1, char2b->byte2 = c2;
1349 else
1350 char2b->byte1 = 0, char2b->byte2 = c1;
1351
1352 /* Maybe encode the character in *CHAR2B. */
1353 if (charset != CHARSET_ASCII)
1354 {
1355 struct font_info *font_info
1356 = FONT_INFO_FROM_ID (f, face->font_info_id);
1357 if (font_info)
1358 {
43d120d8 1359 x_encode_char (glyph->u.ch, char2b, font_info);
ee569018
KH
1360 if (two_byte_p)
1361 *two_byte_p
1362 = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
06a2c219
GM
1363 }
1364 }
1365 }
1366
1367 /* Make sure X resources of the face are allocated. */
1368 xassert (face != NULL);
1369 PREPARE_FACE_FOR_DISPLAY (f, face);
1370 return face;
1371}
1372
1373
1374/* Store one glyph for IT->char_to_display in IT->glyph_row.
1375 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1376
1377static INLINE void
1378x_append_glyph (it)
1379 struct it *it;
1380{
1381 struct glyph *glyph;
1382 enum glyph_row_area area = it->area;
1383
1384 xassert (it->glyph_row);
1385 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1386
1387 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1388 if (glyph < it->glyph_row->glyphs[area + 1])
1389 {
1390 /* Play it safe. If sub-structures of the glyph are not all the
1391 same size, it otherwise be that some bits stay set. This
1392 would prevent a comparison with GLYPH_EQUAL_P. */
1393 glyph->u.val = 0;
1394
1395 glyph->type = CHAR_GLYPH;
1396 glyph->pixel_width = it->pixel_width;
43d120d8
KH
1397 glyph->u.ch = it->char_to_display;
1398 glyph->face_id = it->face_id;
06a2c219
GM
1399 glyph->charpos = CHARPOS (it->position);
1400 glyph->object = it->object;
1401 glyph->left_box_line_p = it->start_of_box_run_p;
1402 glyph->right_box_line_p = it->end_of_box_run_p;
1403 glyph->voffset = it->voffset;
1404 glyph->multibyte_p = it->multibyte_p;
66ac4b0e
GM
1405 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1406 || it->phys_descent > it->descent);
ee569018 1407 glyph->glyph_not_available_p = it->glyph_not_available_p;
06a2c219
GM
1408 ++it->glyph_row->used[area];
1409 }
1410}
1411
b4192550
KH
1412/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1413 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1414
1415static INLINE void
1416x_append_composite_glyph (it)
1417 struct it *it;
1418{
1419 struct glyph *glyph;
1420 enum glyph_row_area area = it->area;
1421
1422 xassert (it->glyph_row);
1423
1424 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1425 if (glyph < it->glyph_row->glyphs[area + 1])
1426 {
1427 /* Play it safe. If sub-structures of the glyph are not all the
1428 same size, it otherwise be that some bits stay set. This
1429 would prevent a comparison with GLYPH_EQUAL_P. */
1430 glyph->u.val = 0;
1431
1432 glyph->type = COMPOSITE_GLYPH;
1433 glyph->pixel_width = it->pixel_width;
43d120d8
KH
1434 glyph->u.cmp_id = it->cmp_id;
1435 glyph->face_id = it->face_id;
b4192550
KH
1436 glyph->charpos = CHARPOS (it->position);
1437 glyph->object = it->object;
1438 glyph->left_box_line_p = it->start_of_box_run_p;
1439 glyph->right_box_line_p = it->end_of_box_run_p;
1440 glyph->voffset = it->voffset;
1441 glyph->multibyte_p = it->multibyte_p;
1442 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1443 || it->phys_descent > it->descent);
1444 ++it->glyph_row->used[area];
1445 }
1446}
1447
06a2c219
GM
1448
1449/* Change IT->ascent and IT->height according to the setting of
1450 IT->voffset. */
1451
1452static INLINE void
1453take_vertical_position_into_account (it)
1454 struct it *it;
1455{
1456 if (it->voffset)
1457 {
1458 if (it->voffset < 0)
1459 /* Increase the ascent so that we can display the text higher
1460 in the line. */
1461 it->ascent += abs (it->voffset);
1462 else
1463 /* Increase the descent so that we can display the text lower
1464 in the line. */
1465 it->descent += it->voffset;
1466 }
1467}
1468
1469
1470/* Produce glyphs/get display metrics for the image IT is loaded with.
1471 See the description of struct display_iterator in dispextern.h for
1472 an overview of struct display_iterator. */
1473
1474static void
1475x_produce_image_glyph (it)
1476 struct it *it;
1477{
1478 struct image *img;
1479 struct face *face;
1480
1481 xassert (it->what == IT_IMAGE);
1482
1483 face = FACE_FROM_ID (it->f, it->face_id);
1484 img = IMAGE_FROM_ID (it->f, it->image_id);
1485 xassert (img);
1486
1487 /* Make sure X resources of the face and image are loaded. */
1488 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1489 prepare_image_for_display (it->f, img);
1490
95af8492 1491 it->ascent = it->phys_ascent = image_ascent (img, face);
66ac4b0e 1492 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1493 it->pixel_width = img->width + 2 * img->margin;
1494
1495 it->nglyphs = 1;
1496
1497 if (face->box != FACE_NO_BOX)
1498 {
1499 it->ascent += face->box_line_width;
1500 it->descent += face->box_line_width;
1501
1502 if (it->start_of_box_run_p)
1503 it->pixel_width += face->box_line_width;
1504 if (it->end_of_box_run_p)
1505 it->pixel_width += face->box_line_width;
1506 }
1507
1508 take_vertical_position_into_account (it);
1509
1510 if (it->glyph_row)
1511 {
1512 struct glyph *glyph;
1513 enum glyph_row_area area = it->area;
1514
1515 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1516 if (glyph < it->glyph_row->glyphs[area + 1])
1517 {
1518 glyph->type = IMAGE_GLYPH;
43d120d8
KH
1519 glyph->u.img_id = img->id;
1520 glyph->face_id = it->face_id;
06a2c219
GM
1521 glyph->pixel_width = it->pixel_width;
1522 glyph->charpos = CHARPOS (it->position);
1523 glyph->object = it->object;
1524 glyph->left_box_line_p = it->start_of_box_run_p;
1525 glyph->right_box_line_p = it->end_of_box_run_p;
1526 glyph->voffset = it->voffset;
1527 glyph->multibyte_p = it->multibyte_p;
1528 ++it->glyph_row->used[area];
1529 }
1530 }
1531}
1532
1533
1534/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1535 of the glyph, WIDTH and HEIGHT are the width and height of the
1536 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1537 ascent of the glyph (0 <= ASCENT <= 1). */
1538
1539static void
1540x_append_stretch_glyph (it, object, width, height, ascent)
1541 struct it *it;
1542 Lisp_Object object;
1543 int width, height;
1544 double ascent;
1545{
1546 struct glyph *glyph;
1547 enum glyph_row_area area = it->area;
1548
1549 xassert (ascent >= 0 && ascent <= 1);
1550
1551 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1552 if (glyph < it->glyph_row->glyphs[area + 1])
1553 {
1554 glyph->type = STRETCH_GLYPH;
1555 glyph->u.stretch.ascent = height * ascent;
1556 glyph->u.stretch.height = height;
43d120d8 1557 glyph->face_id = it->face_id;
06a2c219
GM
1558 glyph->pixel_width = width;
1559 glyph->charpos = CHARPOS (it->position);
1560 glyph->object = object;
1561 glyph->left_box_line_p = it->start_of_box_run_p;
1562 glyph->right_box_line_p = it->end_of_box_run_p;
1563 glyph->voffset = it->voffset;
1564 glyph->multibyte_p = it->multibyte_p;
1565 ++it->glyph_row->used[area];
1566 }
1567}
1568
1569
1570/* Produce a stretch glyph for iterator IT. IT->object is the value
1571 of the glyph property displayed. The value must be a list
1572 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1573 being recognized:
1574
1575 1. `:width WIDTH' specifies that the space should be WIDTH *
1576 canonical char width wide. WIDTH may be an integer or floating
1577 point number.
1578
1579 2. `:relative-width FACTOR' specifies that the width of the stretch
1580 should be computed from the width of the first character having the
1581 `glyph' property, and should be FACTOR times that width.
1582
1583 3. `:align-to HPOS' specifies that the space should be wide enough
1584 to reach HPOS, a value in canonical character units.
1585
1586 Exactly one of the above pairs must be present.
1587
1588 4. `:height HEIGHT' specifies that the height of the stretch produced
1589 should be HEIGHT, measured in canonical character units.
1590
1591 5. `:relative-height FACTOR' specifies that the height of the the
1592 stretch should be FACTOR times the height of the characters having
1593 the glyph property.
1594
1595 Either none or exactly one of 4 or 5 must be present.
1596
1597 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1598 of the stretch should be used for the ascent of the stretch.
1599 ASCENT must be in the range 0 <= ASCENT <= 100. */
1600
1601#define NUMVAL(X) \
1602 ((INTEGERP (X) || FLOATP (X)) \
1603 ? XFLOATINT (X) \
1604 : - 1)
1605
1606
1607static void
1608x_produce_stretch_glyph (it)
1609 struct it *it;
1610{
1611 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1612#if GLYPH_DEBUG
1613 extern Lisp_Object Qspace;
1614#endif
1615 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1616 extern Lisp_Object QCrelative_width, QCrelative_height;
1617 extern Lisp_Object QCalign_to;
1618 Lisp_Object prop, plist;
1619 double width = 0, height = 0, ascent = 0;
1620 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1621 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1622
1623 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1624
1625 /* List should start with `space'. */
1626 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1627 plist = XCDR (it->object);
1628
1629 /* Compute the width of the stretch. */
1630 if (prop = Fplist_get (plist, QCwidth),
1631 NUMVAL (prop) > 0)
1632 /* Absolute width `:width WIDTH' specified and valid. */
1633 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1634 else if (prop = Fplist_get (plist, QCrelative_width),
1635 NUMVAL (prop) > 0)
1636 {
1637 /* Relative width `:relative-width FACTOR' specified and valid.
1638 Compute the width of the characters having the `glyph'
1639 property. */
1640 struct it it2;
1641 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1642
1643 it2 = *it;
1644 if (it->multibyte_p)
1645 {
1646 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1647 - IT_BYTEPOS (*it));
1648 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1649 }
1650 else
1651 it2.c = *p, it2.len = 1;
1652
1653 it2.glyph_row = NULL;
1654 it2.what = IT_CHARACTER;
1655 x_produce_glyphs (&it2);
1656 width = NUMVAL (prop) * it2.pixel_width;
1657 }
1658 else if (prop = Fplist_get (plist, QCalign_to),
1659 NUMVAL (prop) > 0)
1660 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1661 else
1662 /* Nothing specified -> width defaults to canonical char width. */
1663 width = CANON_X_UNIT (it->f);
1664
1665 /* Compute height. */
1666 if (prop = Fplist_get (plist, QCheight),
1667 NUMVAL (prop) > 0)
1668 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1669 else if (prop = Fplist_get (plist, QCrelative_height),
1670 NUMVAL (prop) > 0)
1671 height = FONT_HEIGHT (font) * NUMVAL (prop);
1672 else
1673 height = FONT_HEIGHT (font);
1674
1675 /* Compute percentage of height used for ascent. If
1676 `:ascent ASCENT' is present and valid, use that. Otherwise,
1677 derive the ascent from the font in use. */
1678 if (prop = Fplist_get (plist, QCascent),
1679 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1680 ascent = NUMVAL (prop) / 100.0;
1681 else
1682 ascent = (double) font->ascent / FONT_HEIGHT (font);
1683
1684 if (width <= 0)
1685 width = 1;
1686 if (height <= 0)
1687 height = 1;
1688
1689 if (it->glyph_row)
1690 {
1691 Lisp_Object object = it->stack[it->sp - 1].string;
1692 if (!STRINGP (object))
1693 object = it->w->buffer;
1694 x_append_stretch_glyph (it, object, width, height, ascent);
1695 }
1696
1697 it->pixel_width = width;
66ac4b0e
GM
1698 it->ascent = it->phys_ascent = height * ascent;
1699 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1700 it->nglyphs = 1;
1701
1702 if (face->box != FACE_NO_BOX)
1703 {
1704 it->ascent += face->box_line_width;
1705 it->descent += face->box_line_width;
1706
1707 if (it->start_of_box_run_p)
1708 it->pixel_width += face->box_line_width;
1709 if (it->end_of_box_run_p)
1710 it->pixel_width += face->box_line_width;
1711 }
1712
1713 take_vertical_position_into_account (it);
1714}
1715
b4192550
KH
1716/* Return proper value to be used as baseline offset of font that has
1717 ASCENT and DESCENT to draw characters by the font at the vertical
1718 center of the line of frame F.
1719
1720 Here, out task is to find the value of BOFF in the following figure;
1721
1722 -------------------------+-----------+-
1723 -+-+---------+-+ | |
1724 | | | | | |
1725 | | | | F_ASCENT F_HEIGHT
1726 | | | ASCENT | |
1727 HEIGHT | | | | |
1728 | | |-|-+------+-----------|------- baseline
1729 | | | | BOFF | |
1730 | |---------|-+-+ | |
1731 | | | DESCENT | |
1732 -+-+---------+-+ F_DESCENT |
1733 -------------------------+-----------+-
1734
1735 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1736 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1737 DESCENT = FONT->descent
1738 HEIGHT = FONT_HEIGHT (FONT)
1739 F_DESCENT = (F->output_data.x->font->descent
1740 - F->output_data.x->baseline_offset)
1741 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1742*/
1743
1744#define VCENTER_BASELINE_OFFSET(FONT, F) \
1745 ((FONT)->descent \
1746 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1747 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1748
1749/* Produce glyphs/get display metrics for the display element IT is
1750 loaded with. See the description of struct display_iterator in
1751 dispextern.h for an overview of struct display_iterator. */
1752
1753static void
1754x_produce_glyphs (it)
1755 struct it *it;
1756{
ee569018
KH
1757 it->glyph_not_available_p = 0;
1758
06a2c219
GM
1759 if (it->what == IT_CHARACTER)
1760 {
1761 XChar2b char2b;
1762 XFontStruct *font;
ee569018 1763 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1764 XCharStruct *pcm;
06a2c219 1765 int font_not_found_p;
b4192550
KH
1766 struct font_info *font_info;
1767 int boff; /* baseline offset */
06a2c219 1768
ee569018
KH
1769 /* Maybe translate single-byte characters to multibyte, or the
1770 other way. */
06a2c219 1771 it->char_to_display = it->c;
ee569018 1772 if (!ASCII_BYTE_P (it->c))
06a2c219 1773 {
ee569018
KH
1774 if (unibyte_display_via_language_environment
1775 && SINGLE_BYTE_CHAR_P (it->c)
1776 && (it->c >= 0240
1777 || !NILP (Vnonascii_translation_table)))
1778 {
1779 it->char_to_display = unibyte_char_to_multibyte (it->c);
1780 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1781 face = FACE_FROM_ID (it->f, it->face_id);
1782 }
1783 else if (!SINGLE_BYTE_CHAR_P (it->c)
1784 && !it->multibyte_p)
1785 {
1786 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1787 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1788 face = FACE_FROM_ID (it->f, it->face_id);
1789 }
06a2c219
GM
1790 }
1791
ee569018
KH
1792 /* Get font to use. Encode IT->char_to_display. */
1793 x_get_char_face_and_encoding (it->f, it->char_to_display,
1794 it->face_id, &char2b,
1795 it->multibyte_p);
06a2c219
GM
1796 font = face->font;
1797
1798 /* When no suitable font found, use the default font. */
1799 font_not_found_p = font == NULL;
1800 if (font_not_found_p)
b4192550
KH
1801 {
1802 font = FRAME_FONT (it->f);
1803 boff = it->f->output_data.x->baseline_offset;
1804 font_info = NULL;
1805 }
1806 else
1807 {
1808 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1809 boff = font_info->baseline_offset;
1810 if (font_info->vertical_centering)
1811 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1812 }
06a2c219
GM
1813
1814 if (it->char_to_display >= ' '
1815 && (!it->multibyte_p || it->char_to_display < 128))
1816 {
1817 /* Either unibyte or ASCII. */
1818 int stretched_p;
1819
1820 it->nglyphs = 1;
06a2c219
GM
1821
1822 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1823 it->ascent = font->ascent + boff;
1824 it->descent = font->descent - boff;
474848ac
GM
1825
1826 if (pcm)
1827 {
1828 it->phys_ascent = pcm->ascent + boff;
1829 it->phys_descent = pcm->descent - boff;
1830 it->pixel_width = pcm->width;
1831 }
1832 else
1833 {
1834 it->glyph_not_available_p = 1;
1835 it->phys_ascent = font->ascent + boff;
1836 it->phys_descent = font->descent - boff;
1837 it->pixel_width = FONT_WIDTH (font);
1838 }
06a2c219
GM
1839
1840 /* If this is a space inside a region of text with
1841 `space-width' property, change its width. */
1842 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1843 if (stretched_p)
1844 it->pixel_width *= XFLOATINT (it->space_width);
1845
1846 /* If face has a box, add the box thickness to the character
1847 height. If character has a box line to the left and/or
1848 right, add the box line width to the character's width. */
1849 if (face->box != FACE_NO_BOX)
1850 {
1851 int thick = face->box_line_width;
1852
1853 it->ascent += thick;
1854 it->descent += thick;
1855
1856 if (it->start_of_box_run_p)
1857 it->pixel_width += thick;
1858 if (it->end_of_box_run_p)
1859 it->pixel_width += thick;
1860 }
1861
1862 /* If face has an overline, add the height of the overline
1863 (1 pixel) and a 1 pixel margin to the character height. */
1864 if (face->overline_p)
1865 it->ascent += 2;
1866
1867 take_vertical_position_into_account (it);
1868
1869 /* If we have to actually produce glyphs, do it. */
1870 if (it->glyph_row)
1871 {
1872 if (stretched_p)
1873 {
1874 /* Translate a space with a `space-width' property
1875 into a stretch glyph. */
1876 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1877 x_append_stretch_glyph (it, it->object, it->pixel_width,
1878 it->ascent + it->descent, ascent);
1879 }
1880 else
1881 x_append_glyph (it);
1882
1883 /* If characters with lbearing or rbearing are displayed
1884 in this line, record that fact in a flag of the
1885 glyph row. This is used to optimize X output code. */
1c7e22fd 1886 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1887 it->glyph_row->contains_overlapping_glyphs_p = 1;
1888 }
1889 }
1890 else if (it->char_to_display == '\n')
1891 {
1892 /* A newline has no width but we need the height of the line. */
1893 it->pixel_width = 0;
1894 it->nglyphs = 0;
b4192550
KH
1895 it->ascent = it->phys_ascent = font->ascent + boff;
1896 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1897
1898 if (face->box != FACE_NO_BOX)
1899 {
1900 int thick = face->box_line_width;
1901 it->ascent += thick;
1902 it->descent += thick;
1903 }
1904 }
1905 else if (it->char_to_display == '\t')
1906 {
1907 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1908 int x = it->current_x + it->continuation_lines_width;
06a2c219
GM
1909 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1910
1911 it->pixel_width = next_tab_x - x;
1912 it->nglyphs = 1;
b4192550
KH
1913 it->ascent = it->phys_ascent = font->ascent + boff;
1914 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1915
1916 if (it->glyph_row)
1917 {
1918 double ascent = (double) it->ascent / (it->ascent + it->descent);
1919 x_append_stretch_glyph (it, it->object, it->pixel_width,
1920 it->ascent + it->descent, ascent);
1921 }
1922 }
1923 else
1924 {
1925 /* A multi-byte character. Assume that the display width of the
1926 character is the width of the character multiplied by the
b4192550 1927 width of the font. */
06a2c219 1928
b4192550
KH
1929 /* If we found a font, this font should give us the right
1930 metrics. If we didn't find a font, use the frame's
1931 default font and calculate the width of the character
1932 from the charset width; this is what old redisplay code
1933 did. */
1934 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1935 if (font_not_found_p || !pcm)
1936 {
1937 int charset = CHAR_CHARSET (it->char_to_display);
1938
1939 it->glyph_not_available_p = 1;
1940 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1941 * CHARSET_WIDTH (charset));
1942 it->phys_ascent = font->ascent + boff;
1943 it->phys_descent = font->descent - boff;
1944 }
1945 else
1946 {
1947 it->pixel_width = pcm->width;
1948 it->phys_ascent = pcm->ascent + boff;
1949 it->phys_descent = pcm->descent - boff;
1950 if (it->glyph_row
1951 && (pcm->lbearing < 0
1952 || pcm->rbearing > pcm->width))
1953 it->glyph_row->contains_overlapping_glyphs_p = 1;
1954 }
b4192550
KH
1955 it->nglyphs = 1;
1956 it->ascent = font->ascent + boff;
1957 it->descent = font->descent - boff;
06a2c219
GM
1958 if (face->box != FACE_NO_BOX)
1959 {
1960 int thick = face->box_line_width;
1961 it->ascent += thick;
1962 it->descent += thick;
1963
1964 if (it->start_of_box_run_p)
1965 it->pixel_width += thick;
1966 if (it->end_of_box_run_p)
1967 it->pixel_width += thick;
1968 }
1969
1970 /* If face has an overline, add the height of the overline
1971 (1 pixel) and a 1 pixel margin to the character height. */
1972 if (face->overline_p)
1973 it->ascent += 2;
1974
1975 take_vertical_position_into_account (it);
1976
1977 if (it->glyph_row)
1978 x_append_glyph (it);
1979 }
1980 }
b4192550
KH
1981 else if (it->what == IT_COMPOSITION)
1982 {
1983 /* Note: A composition is represented as one glyph in the
1984 glyph matrix. There are no padding glyphs. */
1985 XChar2b char2b;
1986 XFontStruct *font;
ee569018 1987 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
1988 XCharStruct *pcm;
1989 int font_not_found_p;
1990 struct font_info *font_info;
1991 int boff; /* baseline offset */
1992 struct composition *cmp = composition_table[it->cmp_id];
1993
1994 /* Maybe translate single-byte characters to multibyte. */
1995 it->char_to_display = it->c;
1996 if (unibyte_display_via_language_environment
1997 && SINGLE_BYTE_CHAR_P (it->c)
1998 && (it->c >= 0240
1999 || (it->c >= 0200
2000 && !NILP (Vnonascii_translation_table))))
2001 {
2002 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2003 }
2004
2005 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2006 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2007 face = FACE_FROM_ID (it->f, it->face_id);
2008 x_get_char_face_and_encoding (it->f, it->char_to_display,
2009 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2010 font = face->font;
2011
2012 /* When no suitable font found, use the default font. */
2013 font_not_found_p = font == NULL;
2014 if (font_not_found_p)
2015 {
2016 font = FRAME_FONT (it->f);
2017 boff = it->f->output_data.x->baseline_offset;
2018 font_info = NULL;
2019 }
2020 else
2021 {
2022 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2023 boff = font_info->baseline_offset;
2024 if (font_info->vertical_centering)
2025 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2026 }
2027
2028 /* There are no padding glyphs, so there is only one glyph to
2029 produce for the composition. Important is that pixel_width,
2030 ascent and descent are the values of what is drawn by
2031 draw_glyphs (i.e. the values of the overall glyphs composed). */
2032 it->nglyphs = 1;
2033
2034 /* If we have not yet calculated pixel size data of glyphs of
2035 the composition for the current face font, calculate them
2036 now. Theoretically, we have to check all fonts for the
2037 glyphs, but that requires much time and memory space. So,
2038 here we check only the font of the first glyph. This leads
2039 to incorrect display very rarely, and C-l (recenter) can
2040 correct the display anyway. */
2041 if (cmp->font != (void *) font)
2042 {
2043 /* Ascent and descent of the font of the first character of
2044 this composition (adjusted by baseline offset). Ascent
2045 and descent of overall glyphs should not be less than
2046 them respectively. */
2047 int font_ascent = font->ascent + boff;
2048 int font_descent = font->descent - boff;
2049 /* Bounding box of the overall glyphs. */
2050 int leftmost, rightmost, lowest, highest;
329bed06 2051 int i, width, ascent, descent;
b4192550
KH
2052
2053 cmp->font = (void *) font;
2054
2055 /* Initialize the bounding box. */
2056 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2057 if (pcm)
2058 {
2059 width = pcm->width;
2060 ascent = pcm->ascent;
2061 descent = pcm->descent;
2062 }
2063 else
2064 {
2065 width = FONT_WIDTH (font);
2066 ascent = font->ascent;
2067 descent = font->descent;
2068 }
2069
2070 rightmost = width;
2071 lowest = - descent + boff;
2072 highest = ascent + boff;
b4192550 2073 leftmost = 0;
329bed06 2074
b4192550
KH
2075 if (font_info
2076 && font_info->default_ascent
2077 && CHAR_TABLE_P (Vuse_default_ascent)
2078 && !NILP (Faref (Vuse_default_ascent,
2079 make_number (it->char_to_display))))
2080 highest = font_info->default_ascent + boff;
2081
2082 /* Draw the first glyph at the normal position. It may be
2083 shifted to right later if some other glyphs are drawn at
2084 the left. */
2085 cmp->offsets[0] = 0;
2086 cmp->offsets[1] = boff;
2087
2088 /* Set cmp->offsets for the remaining glyphs. */
2089 for (i = 1; i < cmp->glyph_len; i++)
2090 {
2091 int left, right, btm, top;
2092 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2093 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2094
2095 face = FACE_FROM_ID (it->f, face_id);
2096 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2097 it->multibyte_p);
b4192550
KH
2098 font = face->font;
2099 if (font == NULL)
2100 {
2101 font = FRAME_FONT (it->f);
2102 boff = it->f->output_data.x->baseline_offset;
2103 font_info = NULL;
2104 }
2105 else
2106 {
2107 font_info
2108 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2109 boff = font_info->baseline_offset;
2110 if (font_info->vertical_centering)
2111 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2112 }
2113
2114 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2115 if (pcm)
2116 {
2117 width = pcm->width;
2118 ascent = pcm->ascent;
2119 descent = pcm->descent;
2120 }
2121 else
2122 {
2123 width = FONT_WIDTH (font);
2124 ascent = font->ascent;
2125 descent = font->descent;
2126 }
b4192550
KH
2127
2128 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2129 {
2130 /* Relative composition with or without
2131 alternate chars. */
329bed06
GM
2132 left = (leftmost + rightmost - width) / 2;
2133 btm = - descent + boff;
b4192550
KH
2134 if (font_info && font_info->relative_compose
2135 && (! CHAR_TABLE_P (Vignore_relative_composition)
2136 || NILP (Faref (Vignore_relative_composition,
2137 make_number (ch)))))
2138 {
2139
329bed06 2140 if (- descent >= font_info->relative_compose)
b4192550
KH
2141 /* One extra pixel between two glyphs. */
2142 btm = highest + 1;
329bed06 2143 else if (ascent <= 0)
b4192550 2144 /* One extra pixel between two glyphs. */
329bed06 2145 btm = lowest - 1 - ascent - descent;
b4192550
KH
2146 }
2147 }
2148 else
2149 {
2150 /* A composition rule is specified by an integer
2151 value that encodes global and new reference
2152 points (GREF and NREF). GREF and NREF are
2153 specified by numbers as below:
2154
2155 0---1---2 -- ascent
2156 | |
2157 | |
2158 | |
2159 9--10--11 -- center
2160 | |
2161 ---3---4---5--- baseline
2162 | |
2163 6---7---8 -- descent
2164 */
2165 int rule = COMPOSITION_RULE (cmp, i);
2166 int gref, nref, grefx, grefy, nrefx, nrefy;
2167
2168 COMPOSITION_DECODE_RULE (rule, gref, nref);
2169 grefx = gref % 3, nrefx = nref % 3;
2170 grefy = gref / 3, nrefy = nref / 3;
2171
2172 left = (leftmost
2173 + grefx * (rightmost - leftmost) / 2
329bed06 2174 - nrefx * width / 2);
b4192550
KH
2175 btm = ((grefy == 0 ? highest
2176 : grefy == 1 ? 0
2177 : grefy == 2 ? lowest
2178 : (highest + lowest) / 2)
329bed06
GM
2179 - (nrefy == 0 ? ascent + descent
2180 : nrefy == 1 ? descent - boff
b4192550 2181 : nrefy == 2 ? 0
329bed06 2182 : (ascent + descent) / 2));
b4192550
KH
2183 }
2184
2185 cmp->offsets[i * 2] = left;
329bed06 2186 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2187
2188 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2189 right = left + width;
2190 top = btm + descent + ascent;
b4192550
KH
2191 if (left < leftmost)
2192 leftmost = left;
2193 if (right > rightmost)
2194 rightmost = right;
2195 if (top > highest)
2196 highest = top;
2197 if (btm < lowest)
2198 lowest = btm;
2199 }
2200
2201 /* If there are glyphs whose x-offsets are negative,
2202 shift all glyphs to the right and make all x-offsets
2203 non-negative. */
2204 if (leftmost < 0)
2205 {
2206 for (i = 0; i < cmp->glyph_len; i++)
2207 cmp->offsets[i * 2] -= leftmost;
2208 rightmost -= leftmost;
2209 }
2210
2211 cmp->pixel_width = rightmost;
2212 cmp->ascent = highest;
2213 cmp->descent = - lowest;
2214 if (cmp->ascent < font_ascent)
2215 cmp->ascent = font_ascent;
2216 if (cmp->descent < font_descent)
2217 cmp->descent = font_descent;
2218 }
2219
2220 it->pixel_width = cmp->pixel_width;
2221 it->ascent = it->phys_ascent = cmp->ascent;
2222 it->descent = it->phys_descent = cmp->descent;
2223
2224 if (face->box != FACE_NO_BOX)
2225 {
2226 int thick = face->box_line_width;
2227 it->ascent += thick;
2228 it->descent += thick;
2229
2230 if (it->start_of_box_run_p)
2231 it->pixel_width += thick;
2232 if (it->end_of_box_run_p)
2233 it->pixel_width += thick;
2234 }
2235
2236 /* If face has an overline, add the height of the overline
2237 (1 pixel) and a 1 pixel margin to the character height. */
2238 if (face->overline_p)
2239 it->ascent += 2;
2240
2241 take_vertical_position_into_account (it);
2242
2243 if (it->glyph_row)
2244 x_append_composite_glyph (it);
2245 }
06a2c219
GM
2246 else if (it->what == IT_IMAGE)
2247 x_produce_image_glyph (it);
2248 else if (it->what == IT_STRETCH)
2249 x_produce_stretch_glyph (it);
2250
3017fdd1
GM
2251 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2252 because this isn't true for images with `:ascent 100'. */
2253 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2254 if (it->area == TEXT_AREA)
2255 it->current_x += it->pixel_width;
66ac4b0e 2256
d365f5bb
GM
2257 it->descent += it->extra_line_spacing;
2258
06a2c219
GM
2259 it->max_ascent = max (it->max_ascent, it->ascent);
2260 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2261 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2262 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2263}
2264
2265
2266/* Estimate the pixel height of the mode or top line on frame F.
2267 FACE_ID specifies what line's height to estimate. */
2268
2269int
2270x_estimate_mode_line_height (f, face_id)
2271 struct frame *f;
2272 enum face_id face_id;
2273{
2274 int height = 1;
2275
2276 /* This function is called so early when Emacs starts that the face
2277 cache and mode line face are not yet initialized. */
2278 if (FRAME_FACE_CACHE (f))
2279 {
2280 struct face *face = FACE_FROM_ID (f, face_id);
2281 if (face)
2282 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2283 }
2284
2285 return height;
2286}
2287
2288\f
2289/***********************************************************************
2290 Glyph display
2291 ***********************************************************************/
2292
2293/* A sequence of glyphs to be drawn in the same face.
2294
2295 This data structure is not really completely X specific, so it
2296 could possibly, at least partially, be useful for other systems. It
2297 is currently not part of the external redisplay interface because
2298 it's not clear what other systems will need. */
2299
2300struct glyph_string
2301{
2302 /* X-origin of the string. */
2303 int x;
2304
2305 /* Y-origin and y-position of the base line of this string. */
2306 int y, ybase;
2307
2308 /* The width of the string, not including a face extension. */
2309 int width;
2310
2311 /* The width of the string, including a face extension. */
2312 int background_width;
2313
2314 /* The height of this string. This is the height of the line this
2315 string is drawn in, and can be different from the height of the
2316 font the string is drawn in. */
2317 int height;
2318
2319 /* Number of pixels this string overwrites in front of its x-origin.
2320 This number is zero if the string has an lbearing >= 0; it is
2321 -lbearing, if the string has an lbearing < 0. */
2322 int left_overhang;
2323
2324 /* Number of pixels this string overwrites past its right-most
2325 nominal x-position, i.e. x + width. Zero if the string's
2326 rbearing is <= its nominal width, rbearing - width otherwise. */
2327 int right_overhang;
2328
2329 /* The frame on which the glyph string is drawn. */
2330 struct frame *f;
2331
2332 /* The window on which the glyph string is drawn. */
2333 struct window *w;
2334
2335 /* X display and window for convenience. */
2336 Display *display;
2337 Window window;
2338
2339 /* The glyph row for which this string was built. It determines the
2340 y-origin and height of the string. */
2341 struct glyph_row *row;
2342
2343 /* The area within row. */
2344 enum glyph_row_area area;
2345
2346 /* Characters to be drawn, and number of characters. */
2347 XChar2b *char2b;
2348 int nchars;
2349
06a2c219
GM
2350 /* A face-override for drawing cursors, mouse face and similar. */
2351 enum draw_glyphs_face hl;
2352
2353 /* Face in which this string is to be drawn. */
2354 struct face *face;
2355
2356 /* Font in which this string is to be drawn. */
2357 XFontStruct *font;
2358
2359 /* Font info for this string. */
2360 struct font_info *font_info;
2361
b4192550
KH
2362 /* Non-null means this string describes (part of) a composition.
2363 All characters from char2b are drawn composed. */
2364 struct composition *cmp;
06a2c219
GM
2365
2366 /* Index of this glyph string's first character in the glyph
b4192550
KH
2367 definition of CMP. If this is zero, this glyph string describes
2368 the first character of a composition. */
06a2c219
GM
2369 int gidx;
2370
2371 /* 1 means this glyph strings face has to be drawn to the right end
2372 of the window's drawing area. */
2373 unsigned extends_to_end_of_line_p : 1;
2374
2375 /* 1 means the background of this string has been drawn. */
2376 unsigned background_filled_p : 1;
2377
2378 /* 1 means glyph string must be drawn with 16-bit functions. */
2379 unsigned two_byte_p : 1;
2380
2381 /* 1 means that the original font determined for drawing this glyph
2382 string could not be loaded. The member `font' has been set to
2383 the frame's default font in this case. */
2384 unsigned font_not_found_p : 1;
2385
2386 /* 1 means that the face in which this glyph string is drawn has a
2387 stipple pattern. */
2388 unsigned stippled_p : 1;
2389
66ac4b0e
GM
2390 /* 1 means only the foreground of this glyph string must be drawn,
2391 and we should use the physical height of the line this glyph
2392 string appears in as clip rect. */
2393 unsigned for_overlaps_p : 1;
2394
06a2c219
GM
2395 /* The GC to use for drawing this glyph string. */
2396 GC gc;
2397
2398 /* A pointer to the first glyph in the string. This glyph
2399 corresponds to char2b[0]. Needed to draw rectangles if
2400 font_not_found_p is 1. */
2401 struct glyph *first_glyph;
2402
2403 /* Image, if any. */
2404 struct image *img;
2405
2406 struct glyph_string *next, *prev;
2407};
2408
2409
5c187dee 2410#if 0
06a2c219
GM
2411
2412static void
2413x_dump_glyph_string (s)
2414 struct glyph_string *s;
2415{
2416 fprintf (stderr, "glyph string\n");
2417 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2418 s->x, s->y, s->width, s->height);
2419 fprintf (stderr, " ybase = %d\n", s->ybase);
2420 fprintf (stderr, " hl = %d\n", s->hl);
2421 fprintf (stderr, " left overhang = %d, right = %d\n",
2422 s->left_overhang, s->right_overhang);
2423 fprintf (stderr, " nchars = %d\n", s->nchars);
2424 fprintf (stderr, " extends to end of line = %d\n",
2425 s->extends_to_end_of_line_p);
2426 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2427 fprintf (stderr, " bg width = %d\n", s->background_width);
2428}
2429
2430#endif /* GLYPH_DEBUG */
2431
2432
2433
2434static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2435 struct glyph_string **,
2436 struct glyph_string *,
2437 struct glyph_string *));
2438static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2439 struct glyph_string **,
2440 struct glyph_string *,
2441 struct glyph_string *));
2442static void x_append_glyph_string P_ ((struct glyph_string **,
2443 struct glyph_string **,
2444 struct glyph_string *));
2445static int x_left_overwritten P_ ((struct glyph_string *));
2446static int x_left_overwriting P_ ((struct glyph_string *));
2447static int x_right_overwritten P_ ((struct glyph_string *));
2448static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2449static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2450 int));
06a2c219
GM
2451static void x_init_glyph_string P_ ((struct glyph_string *,
2452 XChar2b *, struct window *,
2453 struct glyph_row *,
2454 enum glyph_row_area, int,
2455 enum draw_glyphs_face));
2456static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2457 enum glyph_row_area, int, int,
66ac4b0e 2458 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2459static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2460static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2461static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2462 int));
2463static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2464static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2465static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2466static void x_draw_glyph_string P_ ((struct glyph_string *));
2467static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2468static void x_set_cursor_gc P_ ((struct glyph_string *));
2469static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2470static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2471static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2472 int *, int *));
2473static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2474static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2475 unsigned long *, double, int));
06a2c219 2476static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2477 double, int, unsigned long));
06a2c219
GM
2478static void x_setup_relief_colors P_ ((struct glyph_string *));
2479static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2480static void x_draw_image_relief P_ ((struct glyph_string *));
2481static void x_draw_image_foreground P_ ((struct glyph_string *));
2482static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2483static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2484static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2485 int, int, int));
2486static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2487 int, int, int, int, XRectangle *));
2488static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2489 int, int, int, XRectangle *));
66ac4b0e
GM
2490static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2491 enum glyph_row_area));
06a2c219 2492
163dcff3
GM
2493#if GLYPH_DEBUG
2494static void x_check_font P_ ((struct frame *, XFontStruct *));
2495#endif
2496
06a2c219 2497
06a2c219
GM
2498/* Append the list of glyph strings with head H and tail T to the list
2499 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2500
2501static INLINE void
2502x_append_glyph_string_lists (head, tail, h, t)
2503 struct glyph_string **head, **tail;
2504 struct glyph_string *h, *t;
2505{
2506 if (h)
2507 {
2508 if (*head)
2509 (*tail)->next = h;
2510 else
2511 *head = h;
2512 h->prev = *tail;
2513 *tail = t;
2514 }
2515}
2516
2517
2518/* Prepend the list of glyph strings with head H and tail T to the
2519 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2520 result. */
2521
2522static INLINE void
2523x_prepend_glyph_string_lists (head, tail, h, t)
2524 struct glyph_string **head, **tail;
2525 struct glyph_string *h, *t;
2526{
2527 if (h)
2528 {
2529 if (*head)
2530 (*head)->prev = t;
2531 else
2532 *tail = t;
2533 t->next = *head;
2534 *head = h;
2535 }
2536}
2537
2538
2539/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2540 Set *HEAD and *TAIL to the resulting list. */
2541
2542static INLINE void
2543x_append_glyph_string (head, tail, s)
2544 struct glyph_string **head, **tail;
2545 struct glyph_string *s;
2546{
2547 s->next = s->prev = NULL;
2548 x_append_glyph_string_lists (head, tail, s, s);
2549}
2550
2551
2552/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2553 face. */
2554
2555static void
2556x_set_cursor_gc (s)
2557 struct glyph_string *s;
2558{
2559 if (s->font == FRAME_FONT (s->f)
2560 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2561 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2562 && !s->cmp)
06a2c219
GM
2563 s->gc = s->f->output_data.x->cursor_gc;
2564 else
2565 {
2566 /* Cursor on non-default face: must merge. */
2567 XGCValues xgcv;
2568 unsigned long mask;
2569
2570 xgcv.background = s->f->output_data.x->cursor_pixel;
2571 xgcv.foreground = s->face->background;
2572
2573 /* If the glyph would be invisible, try a different foreground. */
2574 if (xgcv.foreground == xgcv.background)
2575 xgcv.foreground = s->face->foreground;
2576 if (xgcv.foreground == xgcv.background)
2577 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2578 if (xgcv.foreground == xgcv.background)
2579 xgcv.foreground = s->face->foreground;
2580
2581 /* Make sure the cursor is distinct from text in this face. */
2582 if (xgcv.background == s->face->background
2583 && xgcv.foreground == s->face->foreground)
2584 {
2585 xgcv.background = s->face->foreground;
2586 xgcv.foreground = s->face->background;
2587 }
2588
2589 IF_DEBUG (x_check_font (s->f, s->font));
2590 xgcv.font = s->font->fid;
2591 xgcv.graphics_exposures = False;
2592 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2593
2594 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2595 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2596 mask, &xgcv);
2597 else
2598 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2599 = XCreateGC (s->display, s->window, mask, &xgcv);
2600
2601 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2602 }
2603}
2604
2605
2606/* Set up S->gc of glyph string S for drawing text in mouse face. */
2607
2608static void
2609x_set_mouse_face_gc (s)
2610 struct glyph_string *s;
2611{
2612 int face_id;
ee569018 2613 struct face *face;
06a2c219
GM
2614
2615 /* What face has to be used for the mouse face? */
2616 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2617 face = FACE_FROM_ID (s->f, face_id);
033e3e18
GM
2618 if (s->first_glyph->type == CHAR_GLYPH)
2619 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2620 else
2621 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2622 s->face = FACE_FROM_ID (s->f, face_id);
2623 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2624
2625 /* If font in this face is same as S->font, use it. */
2626 if (s->font == s->face->font)
2627 s->gc = s->face->gc;
2628 else
2629 {
2630 /* Otherwise construct scratch_cursor_gc with values from FACE
2631 but font FONT. */
2632 XGCValues xgcv;
2633 unsigned long mask;
2634
2635 xgcv.background = s->face->background;
2636 xgcv.foreground = s->face->foreground;
2637 IF_DEBUG (x_check_font (s->f, s->font));
2638 xgcv.font = s->font->fid;
2639 xgcv.graphics_exposures = False;
2640 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2641
2642 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2643 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2644 mask, &xgcv);
2645 else
2646 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2647 = XCreateGC (s->display, s->window, mask, &xgcv);
2648
2649 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2650 }
2651
2652 xassert (s->gc != 0);
2653}
2654
2655
2656/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2657 Faces to use in the mode line have already been computed when the
2658 matrix was built, so there isn't much to do, here. */
2659
2660static INLINE void
2661x_set_mode_line_face_gc (s)
2662 struct glyph_string *s;
2663{
2664 s->gc = s->face->gc;
2665 xassert (s->gc != 0);
2666}
2667
2668
2669/* Set S->gc of glyph string S for drawing that glyph string. Set
2670 S->stippled_p to a non-zero value if the face of S has a stipple
2671 pattern. */
2672
2673static INLINE void
2674x_set_glyph_string_gc (s)
2675 struct glyph_string *s;
2676{
2677 if (s->hl == DRAW_NORMAL_TEXT)
2678 {
2679 s->gc = s->face->gc;
2680 s->stippled_p = s->face->stipple != 0;
2681 }
2682 else if (s->hl == DRAW_INVERSE_VIDEO)
2683 {
2684 x_set_mode_line_face_gc (s);
2685 s->stippled_p = s->face->stipple != 0;
2686 }
2687 else if (s->hl == DRAW_CURSOR)
2688 {
2689 x_set_cursor_gc (s);
2690 s->stippled_p = 0;
2691 }
2692 else if (s->hl == DRAW_MOUSE_FACE)
2693 {
2694 x_set_mouse_face_gc (s);
2695 s->stippled_p = s->face->stipple != 0;
2696 }
2697 else if (s->hl == DRAW_IMAGE_RAISED
2698 || s->hl == DRAW_IMAGE_SUNKEN)
2699 {
2700 s->gc = s->face->gc;
2701 s->stippled_p = s->face->stipple != 0;
2702 }
2703 else
2704 {
2705 s->gc = s->face->gc;
2706 s->stippled_p = s->face->stipple != 0;
2707 }
2708
2709 /* GC must have been set. */
2710 xassert (s->gc != 0);
2711}
2712
2713
2714/* Return in *R the clipping rectangle for glyph string S. */
2715
2716static void
2717x_get_glyph_string_clip_rect (s, r)
2718 struct glyph_string *s;
2719 XRectangle *r;
2720{
2721 if (s->row->full_width_p)
2722 {
2723 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2724 int canon_x = CANON_X_UNIT (s->f);
2725
2726 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2727 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2728
2729 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2730 {
1da3fd71 2731 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2732 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2733 r->x -= width;
2734 }
2735
b9432a85 2736 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2737
06a2c219
GM
2738 /* Unless displaying a mode or menu bar line, which are always
2739 fully visible, clip to the visible part of the row. */
2740 if (s->w->pseudo_window_p)
2741 r->height = s->row->visible_height;
2742 else
2743 r->height = s->height;
2744 }
2745 else
2746 {
2747 /* This is a text line that may be partially visible. */
2748 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2749 r->width = window_box_width (s->w, s->area);
2750 r->height = s->row->visible_height;
2751 }
2752
2753 /* Don't use S->y for clipping because it doesn't take partially
2754 visible lines into account. For example, it can be negative for
2755 partially visible lines at the top of a window. */
2756 if (!s->row->full_width_p
2757 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2758 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2759 else
2760 r->y = max (0, s->row->y);
06a2c219 2761
9ea173e8 2762 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2763 at the top of the window. */
9ea173e8 2764 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2765 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2766
2767 /* If S draws overlapping rows, it's sufficient to use the top and
2768 bottom of the window for clipping because this glyph string
2769 intentionally draws over other lines. */
2770 if (s->for_overlaps_p)
2771 {
045dee35 2772 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2773 r->height = window_text_bottom_y (s->w) - r->y;
2774 }
2775
2776 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2777}
2778
2779
2780/* Set clipping for output of glyph string S. S may be part of a mode
2781 line or menu if we don't have X toolkit support. */
2782
2783static INLINE void
2784x_set_glyph_string_clipping (s)
2785 struct glyph_string *s;
2786{
2787 XRectangle r;
2788 x_get_glyph_string_clip_rect (s, &r);
2789 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2790}
2791
2792
2793/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2794 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2795
2796static INLINE void
2797x_compute_glyph_string_overhangs (s)
2798 struct glyph_string *s;
2799{
b4192550 2800 if (s->cmp == NULL
06a2c219
GM
2801 && s->first_glyph->type == CHAR_GLYPH)
2802 {
2803 XCharStruct cs;
2804 int direction, font_ascent, font_descent;
2805 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2806 &font_ascent, &font_descent, &cs);
2807 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2808 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2809 }
2810}
2811
2812
2813/* Compute overhangs and x-positions for glyph string S and its
2814 predecessors, or successors. X is the starting x-position for S.
2815 BACKWARD_P non-zero means process predecessors. */
2816
2817static void
2818x_compute_overhangs_and_x (s, x, backward_p)
2819 struct glyph_string *s;
2820 int x;
2821 int backward_p;
2822{
2823 if (backward_p)
2824 {
2825 while (s)
2826 {
2827 x_compute_glyph_string_overhangs (s);
2828 x -= s->width;
2829 s->x = x;
2830 s = s->prev;
2831 }
2832 }
2833 else
2834 {
2835 while (s)
2836 {
2837 x_compute_glyph_string_overhangs (s);
2838 s->x = x;
2839 x += s->width;
2840 s = s->next;
2841 }
2842 }
2843}
2844
2845
2846/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2847 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2848 assumed to be zero. */
06a2c219
GM
2849
2850static void
2851x_get_glyph_overhangs (glyph, f, left, right)
2852 struct glyph *glyph;
2853 struct frame *f;
2854 int *left, *right;
2855{
06a2c219
GM
2856 *left = *right = 0;
2857
b4192550 2858 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2859 {
2860 XFontStruct *font;
2861 struct face *face;
2862 struct font_info *font_info;
2863 XChar2b char2b;
ee569018
KH
2864 XCharStruct *pcm;
2865
2866 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2867 font = face->font;
2868 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2869 if (font
2870 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2871 {
06a2c219
GM
2872 if (pcm->rbearing > pcm->width)
2873 *right = pcm->rbearing - pcm->width;
2874 if (pcm->lbearing < 0)
2875 *left = -pcm->lbearing;
2876 }
2877 }
2878}
2879
2880
2881/* Return the index of the first glyph preceding glyph string S that
2882 is overwritten by S because of S's left overhang. Value is -1
2883 if no glyphs are overwritten. */
2884
2885static int
2886x_left_overwritten (s)
2887 struct glyph_string *s;
2888{
2889 int k;
2890
2891 if (s->left_overhang)
2892 {
2893 int x = 0, i;
2894 struct glyph *glyphs = s->row->glyphs[s->area];
2895 int first = s->first_glyph - glyphs;
2896
2897 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2898 x -= glyphs[i].pixel_width;
2899
2900 k = i + 1;
2901 }
2902 else
2903 k = -1;
2904
2905 return k;
2906}
2907
2908
2909/* Return the index of the first glyph preceding glyph string S that
2910 is overwriting S because of its right overhang. Value is -1 if no
2911 glyph in front of S overwrites S. */
2912
2913static int
2914x_left_overwriting (s)
2915 struct glyph_string *s;
2916{
2917 int i, k, x;
2918 struct glyph *glyphs = s->row->glyphs[s->area];
2919 int first = s->first_glyph - glyphs;
2920
2921 k = -1;
2922 x = 0;
2923 for (i = first - 1; i >= 0; --i)
2924 {
2925 int left, right;
2926 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2927 if (x + right > 0)
2928 k = i;
2929 x -= glyphs[i].pixel_width;
2930 }
2931
2932 return k;
2933}
2934
2935
2936/* Return the index of the last glyph following glyph string S that is
2937 not overwritten by S because of S's right overhang. Value is -1 if
2938 no such glyph is found. */
2939
2940static int
2941x_right_overwritten (s)
2942 struct glyph_string *s;
2943{
2944 int k = -1;
2945
2946 if (s->right_overhang)
2947 {
2948 int x = 0, i;
2949 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2950 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2951 int end = s->row->used[s->area];
2952
2953 for (i = first; i < end && s->right_overhang > x; ++i)
2954 x += glyphs[i].pixel_width;
2955
2956 k = i;
2957 }
2958
2959 return k;
2960}
2961
2962
2963/* Return the index of the last glyph following glyph string S that
2964 overwrites S because of its left overhang. Value is negative
2965 if no such glyph is found. */
2966
2967static int
2968x_right_overwriting (s)
2969 struct glyph_string *s;
2970{
2971 int i, k, x;
2972 int end = s->row->used[s->area];
2973 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2974 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2975
2976 k = -1;
2977 x = 0;
2978 for (i = first; i < end; ++i)
2979 {
2980 int left, right;
2981 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2982 if (x - left < 0)
2983 k = i;
2984 x += glyphs[i].pixel_width;
2985 }
2986
2987 return k;
2988}
2989
2990
2991/* Fill rectangle X, Y, W, H with background color of glyph string S. */
2992
2993static INLINE void
2994x_clear_glyph_string_rect (s, x, y, w, h)
2995 struct glyph_string *s;
2996 int x, y, w, h;
2997{
2998 XGCValues xgcv;
2999 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3000 XSetForeground (s->display, s->gc, xgcv.background);
3001 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3002 XSetForeground (s->display, s->gc, xgcv.foreground);
3003}
3004
3005
3006/* Draw the background of glyph_string S. If S->background_filled_p
3007 is non-zero don't draw it. FORCE_P non-zero means draw the
3008 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3009 when a string preceding S draws into the background of S, or S
3010 contains the first component of a composition. */
06a2c219
GM
3011
3012static void
3013x_draw_glyph_string_background (s, force_p)
3014 struct glyph_string *s;
3015 int force_p;
3016{
3017 /* Nothing to do if background has already been drawn or if it
3018 shouldn't be drawn in the first place. */
3019 if (!s->background_filled_p)
3020 {
b4192550 3021 if (s->stippled_p)
06a2c219
GM
3022 {
3023 /* Fill background with a stipple pattern. */
3024 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3025 XFillRectangle (s->display, s->window, s->gc, s->x,
3026 s->y + s->face->box_line_width,
3027 s->background_width,
3028 s->height - 2 * s->face->box_line_width);
3029 XSetFillStyle (s->display, s->gc, FillSolid);
3030 s->background_filled_p = 1;
3031 }
3032 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3033 || s->font_not_found_p
3034 || s->extends_to_end_of_line_p
06a2c219
GM
3035 || force_p)
3036 {
3037 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3038 s->background_width,
3039 s->height - 2 * s->face->box_line_width);
3040 s->background_filled_p = 1;
3041 }
3042 }
3043}
3044
3045
3046/* Draw the foreground of glyph string S. */
3047
3048static void
3049x_draw_glyph_string_foreground (s)
3050 struct glyph_string *s;
3051{
3052 int i, x;
3053
3054 /* If first glyph of S has a left box line, start drawing the text
3055 of S to the right of that box line. */
3056 if (s->face->box != FACE_NO_BOX
3057 && s->first_glyph->left_box_line_p)
3058 x = s->x + s->face->box_line_width;
3059 else
3060 x = s->x;
3061
b4192550
KH
3062 /* Draw characters of S as rectangles if S's font could not be
3063 loaded. */
3064 if (s->font_not_found_p)
06a2c219 3065 {
b4192550 3066 for (i = 0; i < s->nchars; ++i)
06a2c219 3067 {
b4192550
KH
3068 struct glyph *g = s->first_glyph + i;
3069 XDrawRectangle (s->display, s->window,
3070 s->gc, x, s->y, g->pixel_width - 1,
3071 s->height - 1);
3072 x += g->pixel_width;
06a2c219
GM
3073 }
3074 }
3075 else
3076 {
b4192550
KH
3077 char *char1b = (char *) s->char2b;
3078 int boff = s->font_info->baseline_offset;
06a2c219 3079
b4192550
KH
3080 if (s->font_info->vertical_centering)
3081 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3082
3083 /* If we can use 8-bit functions, condense S->char2b. */
3084 if (!s->two_byte_p)
3085 for (i = 0; i < s->nchars; ++i)
3086 char1b[i] = s->char2b[i].byte2;
3087
3088 /* Draw text with XDrawString if background has already been
3089 filled. Otherwise, use XDrawImageString. (Note that
3090 XDrawImageString is usually faster than XDrawString.) Always
3091 use XDrawImageString when drawing the cursor so that there is
3092 no chance that characters under a box cursor are invisible. */
3093 if (s->for_overlaps_p
3094 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3095 {
3096 /* Draw characters with 16-bit or 8-bit functions. */
3097 if (s->two_byte_p)
3098 XDrawString16 (s->display, s->window, s->gc, x,
3099 s->ybase - boff, s->char2b, s->nchars);
3100 else
3101 XDrawString (s->display, s->window, s->gc, x,
3102 s->ybase - boff, char1b, s->nchars);
3103 }
06a2c219
GM
3104 else
3105 {
b4192550
KH
3106 if (s->two_byte_p)
3107 XDrawImageString16 (s->display, s->window, s->gc, x,
3108 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3109 else
b4192550
KH
3110 XDrawImageString (s->display, s->window, s->gc, x,
3111 s->ybase - boff, char1b, s->nchars);
3112 }
3113 }
3114}
06a2c219 3115
b4192550 3116/* Draw the foreground of composite glyph string S. */
06a2c219 3117
b4192550
KH
3118static void
3119x_draw_composite_glyph_string_foreground (s)
3120 struct glyph_string *s;
3121{
3122 int i, x;
06a2c219 3123
b4192550
KH
3124 /* If first glyph of S has a left box line, start drawing the text
3125 of S to the right of that box line. */
3126 if (s->face->box != FACE_NO_BOX
3127 && s->first_glyph->left_box_line_p)
3128 x = s->x + s->face->box_line_width;
3129 else
3130 x = s->x;
06a2c219 3131
b4192550
KH
3132 /* S is a glyph string for a composition. S->gidx is the index of
3133 the first character drawn for glyphs of this composition.
3134 S->gidx == 0 means we are drawing the very first character of
3135 this composition. */
06a2c219 3136
b4192550
KH
3137 /* Draw a rectangle for the composition if the font for the very
3138 first character of the composition could not be loaded. */
3139 if (s->font_not_found_p)
3140 {
3141 if (s->gidx == 0)
3142 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3143 s->width - 1, s->height - 1);
3144 }
3145 else
3146 {
3147 for (i = 0; i < s->nchars; i++, ++s->gidx)
3148 XDrawString16 (s->display, s->window, s->gc,
3149 x + s->cmp->offsets[s->gidx * 2],
3150 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3151 s->char2b + i, 1);
06a2c219
GM
3152 }
3153}
3154
3155
80c32bcc
GM
3156#ifdef USE_X_TOOLKIT
3157
3e71d8f2 3158static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3159
3e71d8f2
GM
3160
3161/* Return the frame on which widget WIDGET is used.. Abort if frame
3162 cannot be determined. */
3163
e851c833 3164static struct frame *
3e71d8f2 3165x_frame_of_widget (widget)
80c32bcc 3166 Widget widget;
80c32bcc 3167{
80c32bcc 3168 struct x_display_info *dpyinfo;
5c187dee 3169 Lisp_Object tail;
3e71d8f2
GM
3170 struct frame *f;
3171
80c32bcc
GM
3172 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3173
3174 /* Find the top-level shell of the widget. Note that this function
3175 can be called when the widget is not yet realized, so XtWindow
3176 (widget) == 0. That's the reason we can't simply use
3177 x_any_window_to_frame. */
3178 while (!XtIsTopLevelShell (widget))
3179 widget = XtParent (widget);
3180
3181 /* Look for a frame with that top-level widget. Allocate the color
3182 on that frame to get the right gamma correction value. */
3183 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3184 if (GC_FRAMEP (XCAR (tail))
3185 && (f = XFRAME (XCAR (tail)),
3186 (f->output_data.nothing != 1
3187 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3188 && f->output_data.x->widget == widget)
3e71d8f2 3189 return f;
80c32bcc
GM
3190
3191 abort ();
3192}
3193
3e71d8f2
GM
3194
3195/* Allocate the color COLOR->pixel on the screen and display of
3196 widget WIDGET in colormap CMAP. If an exact match cannot be
3197 allocated, try the nearest color available. Value is non-zero
3198 if successful. This is called from lwlib. */
3199
3200int
3201x_alloc_nearest_color_for_widget (widget, cmap, color)
3202 Widget widget;
3203 Colormap cmap;
3204 XColor *color;
3205{
3206 struct frame *f = x_frame_of_widget (widget);
3207 return x_alloc_nearest_color (f, cmap, color);
3208}
3209
3210
80c32bcc
GM
3211#endif /* USE_X_TOOLKIT */
3212
3213
06a2c219
GM
3214/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3215 CMAP. If an exact match can't be allocated, try the nearest color
3216 available. Value is non-zero if successful. Set *COLOR to the
3217 color allocated. */
3218
3219int
80c32bcc
GM
3220x_alloc_nearest_color (f, cmap, color)
3221 struct frame *f;
06a2c219
GM
3222 Colormap cmap;
3223 XColor *color;
3224{
80c32bcc
GM
3225 Display *display = FRAME_X_DISPLAY (f);
3226 Screen *screen = FRAME_X_SCREEN (f);
3227 int rc;
3228
3229 gamma_correct (f, color);
3230 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3231 if (rc == 0)
3232 {
3233 /* If we got to this point, the colormap is full, so we're going
3234 to try to get the next closest color. The algorithm used is
3235 a least-squares matching, which is what X uses for closest
3236 color matching with StaticColor visuals. */
3237 int nearest, i;
3238 unsigned long nearest_delta = ~0;
3239 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3240 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3241
3242 for (i = 0; i < ncells; ++i)
3243 cells[i].pixel = i;
3244 XQueryColors (display, cmap, cells, ncells);
3245
3246 for (nearest = i = 0; i < ncells; ++i)
3247 {
3248 long dred = (color->red >> 8) - (cells[i].red >> 8);
3249 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3250 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3251 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3252
3253 if (delta < nearest_delta)
3254 {
3255 nearest = i;
3256 nearest_delta = delta;
3257 }
3258 }
3259
3260 color->red = cells[nearest].red;
3261 color->green = cells[nearest].green;
3262 color->blue = cells[nearest].blue;
3263 rc = XAllocColor (display, cmap, color);
3264 }
3265
d9c545da
GM
3266#ifdef DEBUG_X_COLORS
3267 if (rc)
3268 register_color (color->pixel);
3269#endif /* DEBUG_X_COLORS */
3270
06a2c219
GM
3271 return rc;
3272}
3273
3274
d9c545da
GM
3275/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3276 It's necessary to do this instead of just using PIXEL directly to
3277 get color reference counts right. */
3278
3279unsigned long
3280x_copy_color (f, pixel)
3281 struct frame *f;
3282 unsigned long pixel;
3283{
3284 XColor color;
3285
3286 color.pixel = pixel;
3287 BLOCK_INPUT;
3288 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3289 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3290 UNBLOCK_INPUT;
3291#ifdef DEBUG_X_COLORS
3292 register_color (pixel);
3293#endif
3294 return color.pixel;
3295}
3296
3297
3e71d8f2
GM
3298/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3299 It's necessary to do this instead of just using PIXEL directly to
3300 get color reference counts right. */
3301
3302unsigned long
3303x_copy_dpy_color (dpy, cmap, pixel)
3304 Display *dpy;
3305 Colormap cmap;
3306 unsigned long pixel;
3307{
3308 XColor color;
3309
3310 color.pixel = pixel;
3311 BLOCK_INPUT;
3312 XQueryColor (dpy, cmap, &color);
3313 XAllocColor (dpy, cmap, &color);
3314 UNBLOCK_INPUT;
3315#ifdef DEBUG_X_COLORS
3316 register_color (pixel);
3317#endif
3318 return color.pixel;
3319}
3320
3321
06a2c219
GM
3322/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3323 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3324 If this produces the same color as PIXEL, try a color where all RGB
3325 values have DELTA added. Return the allocated color in *PIXEL.
3326 DISPLAY is the X display, CMAP is the colormap to operate on.
3327 Value is non-zero if successful. */
3328
3329static int
3330x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3331 struct frame *f;
3332 Display *display;
3333 Colormap cmap;
3334 unsigned long *pixel;
68c45bf0 3335 double factor;
06a2c219
GM
3336 int delta;
3337{
3338 XColor color, new;
3339 int success_p;
3340
3341 /* Get RGB color values. */
3342 color.pixel = *pixel;
3343 XQueryColor (display, cmap, &color);
3344
3345 /* Change RGB values by specified FACTOR. Avoid overflow! */
3346 xassert (factor >= 0);
3347 new.red = min (0xffff, factor * color.red);
3348 new.green = min (0xffff, factor * color.green);
3349 new.blue = min (0xffff, factor * color.blue);
3350
3351 /* Try to allocate the color. */
80c32bcc 3352 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3353 if (success_p)
3354 {
3355 if (new.pixel == *pixel)
3356 {
3357 /* If we end up with the same color as before, try adding
3358 delta to the RGB values. */
0d605c67 3359 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3360
3361 new.red = min (0xffff, delta + color.red);
3362 new.green = min (0xffff, delta + color.green);
3363 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3364 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3365 }
3366 else
3367 success_p = 1;
3368 *pixel = new.pixel;
3369 }
3370
3371 return success_p;
3372}
3373
3374
3375/* Set up the foreground color for drawing relief lines of glyph
3376 string S. RELIEF is a pointer to a struct relief containing the GC
3377 with which lines will be drawn. Use a color that is FACTOR or
3378 DELTA lighter or darker than the relief's background which is found
3379 in S->f->output_data.x->relief_background. If such a color cannot
3380 be allocated, use DEFAULT_PIXEL, instead. */
3381
3382static void
3383x_setup_relief_color (f, relief, factor, delta, default_pixel)
3384 struct frame *f;
3385 struct relief *relief;
68c45bf0 3386 double factor;
06a2c219
GM
3387 int delta;
3388 unsigned long default_pixel;
3389{
3390 XGCValues xgcv;
3391 struct x_output *di = f->output_data.x;
3392 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3393 unsigned long pixel;
3394 unsigned long background = di->relief_background;
43bd1b2b 3395 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3396 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3397 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3398
3399 xgcv.graphics_exposures = False;
3400 xgcv.line_width = 1;
3401
3402 /* Free previously allocated color. The color cell will be reused
3403 when it has been freed as many times as it was allocated, so this
3404 doesn't affect faces using the same colors. */
3405 if (relief->gc
3406 && relief->allocated_p)
3407 {
0d605c67 3408 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3409 relief->allocated_p = 0;
3410 }
3411
3412 /* Allocate new color. */
3413 xgcv.foreground = default_pixel;
3414 pixel = background;
dcd08bfb
GM
3415 if (dpyinfo->n_planes != 1
3416 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3417 {
3418 relief->allocated_p = 1;
3419 xgcv.foreground = relief->pixel = pixel;
3420 }
3421
3422 if (relief->gc == 0)
3423 {
dcd08bfb 3424 xgcv.stipple = dpyinfo->gray;
06a2c219 3425 mask |= GCStipple;
dcd08bfb 3426 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3427 }
3428 else
dcd08bfb 3429 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3430}
3431
3432
3433/* Set up colors for the relief lines around glyph string S. */
3434
3435static void
3436x_setup_relief_colors (s)
3437 struct glyph_string *s;
3438{
3439 struct x_output *di = s->f->output_data.x;
3440 unsigned long color;
3441
3442 if (s->face->use_box_color_for_shadows_p)
3443 color = s->face->box_color;
3444 else
3445 {
3446 XGCValues xgcv;
3447
3448 /* Get the background color of the face. */
3449 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3450 color = xgcv.background;
3451 }
3452
3453 if (di->white_relief.gc == 0
3454 || color != di->relief_background)
3455 {
3456 di->relief_background = color;
3457 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3458 WHITE_PIX_DEFAULT (s->f));
3459 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3460 BLACK_PIX_DEFAULT (s->f));
3461 }
3462}
3463
3464
3465/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3466 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3467 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3468 relief. LEFT_P non-zero means draw a relief on the left side of
3469 the rectangle. RIGHT_P non-zero means draw a relief on the right
3470 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3471 when drawing. */
3472
3473static void
3474x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3475 raised_p, left_p, right_p, clip_rect)
3476 struct frame *f;
3477 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3478 XRectangle *clip_rect;
3479{
3480 int i;
3481 GC gc;
3482
3483 if (raised_p)
3484 gc = f->output_data.x->white_relief.gc;
3485 else
3486 gc = f->output_data.x->black_relief.gc;
3487 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3488
3489 /* Top. */
3490 for (i = 0; i < width; ++i)
3491 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3492 left_x + i * left_p, top_y + i,
3493 right_x + 1 - i * right_p, top_y + i);
3494
3495 /* Left. */
3496 if (left_p)
3497 for (i = 0; i < width; ++i)
3498 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3499 left_x + i, top_y + i, left_x + i, bottom_y - i);
3500
3501 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3502 if (raised_p)
3503 gc = f->output_data.x->black_relief.gc;
3504 else
3505 gc = f->output_data.x->white_relief.gc;
3506 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3507
3508 /* Bottom. */
3509 for (i = 0; i < width; ++i)
3510 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3511 left_x + i * left_p, bottom_y - i,
3512 right_x + 1 - i * right_p, bottom_y - i);
3513
3514 /* Right. */
3515 if (right_p)
3516 for (i = 0; i < width; ++i)
3517 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3518 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3519
3520 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3521}
3522
3523
3524/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3525 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3526 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3527 left side of the rectangle. RIGHT_P non-zero means draw a line
3528 on the right side of the rectangle. CLIP_RECT is the clipping
3529 rectangle to use when drawing. */
3530
3531static void
3532x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3533 left_p, right_p, clip_rect)
3534 struct glyph_string *s;
3535 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3536 XRectangle *clip_rect;
3537{
3538 XGCValues xgcv;
3539
3540 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3541 XSetForeground (s->display, s->gc, s->face->box_color);
3542 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3543
3544 /* Top. */
3545 XFillRectangle (s->display, s->window, s->gc,
3546 left_x, top_y, right_x - left_x, width);
3547
3548 /* Left. */
3549 if (left_p)
3550 XFillRectangle (s->display, s->window, s->gc,
3551 left_x, top_y, width, bottom_y - top_y);
3552
3553 /* Bottom. */
3554 XFillRectangle (s->display, s->window, s->gc,
3555 left_x, bottom_y - width, right_x - left_x, width);
3556
3557 /* Right. */
3558 if (right_p)
3559 XFillRectangle (s->display, s->window, s->gc,
3560 right_x - width, top_y, width, bottom_y - top_y);
3561
3562 XSetForeground (s->display, s->gc, xgcv.foreground);
3563 XSetClipMask (s->display, s->gc, None);
3564}
3565
3566
3567/* Draw a box around glyph string S. */
3568
3569static void
3570x_draw_glyph_string_box (s)
3571 struct glyph_string *s;
3572{
3573 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3574 int left_p, right_p;
3575 struct glyph *last_glyph;
3576 XRectangle clip_rect;
3577
3578 last_x = window_box_right (s->w, s->area);
3579 if (s->row->full_width_p
3580 && !s->w->pseudo_window_p)
3581 {
110859fc 3582 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3583 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3584 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3585 }
3586
3587 /* The glyph that may have a right box line. */
b4192550 3588 last_glyph = (s->cmp || s->img
06a2c219
GM
3589 ? s->first_glyph
3590 : s->first_glyph + s->nchars - 1);
3591
3592 width = s->face->box_line_width;
3593 raised_p = s->face->box == FACE_RAISED_BOX;
3594 left_x = s->x;
3595 right_x = ((s->row->full_width_p
1da3fd71 3596 ? last_x - 1
a7aeb2de 3597 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3598 top_y = s->y;
3599 bottom_y = top_y + s->height - 1;
3600
3601 left_p = (s->first_glyph->left_box_line_p
3602 || (s->hl == DRAW_MOUSE_FACE
3603 && (s->prev == NULL
3604 || s->prev->hl != s->hl)));
3605 right_p = (last_glyph->right_box_line_p
3606 || (s->hl == DRAW_MOUSE_FACE
3607 && (s->next == NULL
3608 || s->next->hl != s->hl)));
3609
3610 x_get_glyph_string_clip_rect (s, &clip_rect);
3611
3612 if (s->face->box == FACE_SIMPLE_BOX)
3613 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3614 left_p, right_p, &clip_rect);
3615 else
3616 {
3617 x_setup_relief_colors (s);
3618 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3619 width, raised_p, left_p, right_p, &clip_rect);
3620 }
3621}
3622
3623
3624/* Draw foreground of image glyph string S. */
3625
3626static void
3627x_draw_image_foreground (s)
3628 struct glyph_string *s;
3629{
3630 int x;
95af8492 3631 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3632
3633 /* If first glyph of S has a left box line, start drawing it to the
3634 right of that line. */
3635 if (s->face->box != FACE_NO_BOX
3636 && s->first_glyph->left_box_line_p)
3637 x = s->x + s->face->box_line_width;
3638 else
3639 x = s->x;
3640
3641 /* If there is a margin around the image, adjust x- and y-position
3642 by that margin. */
3643 if (s->img->margin)
3644 {
3645 x += s->img->margin;
3646 y += s->img->margin;
3647 }
3648
3649 if (s->img->pixmap)
3650 {
3651 if (s->img->mask)
3652 {
3653 /* We can't set both a clip mask and use XSetClipRectangles
3654 because the latter also sets a clip mask. We also can't
3655 trust on the shape extension to be available
3656 (XShapeCombineRegion). So, compute the rectangle to draw
3657 manually. */
3658 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3659 | GCFunction);
3660 XGCValues xgcv;
3661 XRectangle clip_rect, image_rect, r;
3662
3663 xgcv.clip_mask = s->img->mask;
3664 xgcv.clip_x_origin = x;
3665 xgcv.clip_y_origin = y;
3666 xgcv.function = GXcopy;
3667 XChangeGC (s->display, s->gc, mask, &xgcv);
3668
3669 x_get_glyph_string_clip_rect (s, &clip_rect);
3670 image_rect.x = x;
3671 image_rect.y = y;
3672 image_rect.width = s->img->width;
3673 image_rect.height = s->img->height;
3674 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3675 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3676 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3677 }
3678 else
3679 {
3680 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3681 0, 0, s->img->width, s->img->height, x, y);
3682
3683 /* When the image has a mask, we can expect that at
3684 least part of a mouse highlight or a block cursor will
3685 be visible. If the image doesn't have a mask, make
3686 a block cursor visible by drawing a rectangle around
3687 the image. I believe it's looking better if we do
3688 nothing here for mouse-face. */
3689 if (s->hl == DRAW_CURSOR)
3690 XDrawRectangle (s->display, s->window, s->gc, x, y,
3691 s->img->width - 1, s->img->height - 1);
3692 }
3693 }
3694 else
3695 /* Draw a rectangle if image could not be loaded. */
3696 XDrawRectangle (s->display, s->window, s->gc, x, y,
3697 s->img->width - 1, s->img->height - 1);
3698}
3699
3700
3701/* Draw a relief around the image glyph string S. */
3702
3703static void
3704x_draw_image_relief (s)
3705 struct glyph_string *s;
3706{
3707 int x0, y0, x1, y1, thick, raised_p;
3708 XRectangle r;
3709 int x;
95af8492 3710 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3711
3712 /* If first glyph of S has a left box line, start drawing it to the
3713 right of that line. */
3714 if (s->face->box != FACE_NO_BOX
3715 && s->first_glyph->left_box_line_p)
3716 x = s->x + s->face->box_line_width;
3717 else
3718 x = s->x;
3719
3720 /* If there is a margin around the image, adjust x- and y-position
3721 by that margin. */
3722 if (s->img->margin)
3723 {
3724 x += s->img->margin;
3725 y += s->img->margin;
3726 }
3727
3728 if (s->hl == DRAW_IMAGE_SUNKEN
3729 || s->hl == DRAW_IMAGE_RAISED)
3730 {
9ea173e8 3731 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3732 raised_p = s->hl == DRAW_IMAGE_RAISED;
3733 }
3734 else
3735 {
3736 thick = abs (s->img->relief);
3737 raised_p = s->img->relief > 0;
3738 }
3739
3740 x0 = x - thick;
3741 y0 = y - thick;
3742 x1 = x + s->img->width + thick - 1;
3743 y1 = y + s->img->height + thick - 1;
3744
3745 x_setup_relief_colors (s);
3746 x_get_glyph_string_clip_rect (s, &r);
3747 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3748}
3749
3750
3751/* Draw the foreground of image glyph string S to PIXMAP. */
3752
3753static void
3754x_draw_image_foreground_1 (s, pixmap)
3755 struct glyph_string *s;
3756 Pixmap pixmap;
3757{
3758 int x;
95af8492 3759 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3760
3761 /* If first glyph of S has a left box line, start drawing it to the
3762 right of that line. */
3763 if (s->face->box != FACE_NO_BOX
3764 && s->first_glyph->left_box_line_p)
3765 x = s->face->box_line_width;
3766 else
3767 x = 0;
3768
3769 /* If there is a margin around the image, adjust x- and y-position
3770 by that margin. */
3771 if (s->img->margin)
3772 {
3773 x += s->img->margin;
3774 y += s->img->margin;
3775 }
dc43ef94 3776
06a2c219
GM
3777 if (s->img->pixmap)
3778 {
3779 if (s->img->mask)
3780 {
3781 /* We can't set both a clip mask and use XSetClipRectangles
3782 because the latter also sets a clip mask. We also can't
3783 trust on the shape extension to be available
3784 (XShapeCombineRegion). So, compute the rectangle to draw
3785 manually. */
3786 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3787 | GCFunction);
3788 XGCValues xgcv;
3789
3790 xgcv.clip_mask = s->img->mask;
3791 xgcv.clip_x_origin = x;
3792 xgcv.clip_y_origin = y;
3793 xgcv.function = GXcopy;
3794 XChangeGC (s->display, s->gc, mask, &xgcv);
3795
3796 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3797 0, 0, s->img->width, s->img->height, x, y);
3798 XSetClipMask (s->display, s->gc, None);
3799 }
3800 else
3801 {
3802 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3803 0, 0, s->img->width, s->img->height, x, y);
3804
3805 /* When the image has a mask, we can expect that at
3806 least part of a mouse highlight or a block cursor will
3807 be visible. If the image doesn't have a mask, make
3808 a block cursor visible by drawing a rectangle around
3809 the image. I believe it's looking better if we do
3810 nothing here for mouse-face. */
3811 if (s->hl == DRAW_CURSOR)
3812 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3813 s->img->width - 1, s->img->height - 1);
3814 }
3815 }
3816 else
3817 /* Draw a rectangle if image could not be loaded. */
3818 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3819 s->img->width - 1, s->img->height - 1);
3820}
dc43ef94 3821
990ba854 3822
06a2c219
GM
3823/* Draw part of the background of glyph string S. X, Y, W, and H
3824 give the rectangle to draw. */
a9a5b0a5 3825
06a2c219
GM
3826static void
3827x_draw_glyph_string_bg_rect (s, x, y, w, h)
3828 struct glyph_string *s;
3829 int x, y, w, h;
3830{
3831 if (s->stippled_p)
3832 {
3833 /* Fill background with a stipple pattern. */
3834 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3835 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3836 XSetFillStyle (s->display, s->gc, FillSolid);
3837 }
3838 else
3839 x_clear_glyph_string_rect (s, x, y, w, h);
3840}
07e34cb0 3841
b5210ea7 3842
06a2c219 3843/* Draw image glyph string S.
dc43ef94 3844
06a2c219
GM
3845 s->y
3846 s->x +-------------------------
3847 | s->face->box
3848 |
3849 | +-------------------------
3850 | | s->img->margin
3851 | |
3852 | | +-------------------
3853 | | | the image
dc43ef94 3854
06a2c219 3855 */
dc43ef94 3856
06a2c219
GM
3857static void
3858x_draw_image_glyph_string (s)
3859 struct glyph_string *s;
3860{
3861 int x, y;
3862 int box_line_width = s->face->box_line_width;
3863 int margin = s->img->margin;
3864 int height;
3865 Pixmap pixmap = None;
3866
3867 height = s->height - 2 * box_line_width;
3868
3869 /* Fill background with face under the image. Do it only if row is
3870 taller than image or if image has a clip mask to reduce
3871 flickering. */
3872 s->stippled_p = s->face->stipple != 0;
3873 if (height > s->img->height
3874 || margin
3875 || s->img->mask
3876 || s->img->pixmap == 0
3877 || s->width != s->background_width)
3878 {
3879 if (box_line_width && s->first_glyph->left_box_line_p)
3880 x = s->x + box_line_width;
3881 else
3882 x = s->x;
3883
3884 y = s->y + box_line_width;
3885
3886 if (s->img->mask)
3887 {
3888 /* Create a pixmap as large as the glyph string Fill it with
3889 the background color. Copy the image to it, using its
3890 mask. Copy the temporary pixmap to the display. */
3891 Screen *screen = FRAME_X_SCREEN (s->f);
3892 int depth = DefaultDepthOfScreen (screen);
3893
3894 /* Create a pixmap as large as the glyph string. */
3895 pixmap = XCreatePixmap (s->display, s->window,
3896 s->background_width,
3897 s->height, depth);
3898
3899 /* Don't clip in the following because we're working on the
3900 pixmap. */
3901 XSetClipMask (s->display, s->gc, None);
3902
3903 /* Fill the pixmap with the background color/stipple. */
3904 if (s->stippled_p)
3905 {
3906 /* Fill background with a stipple pattern. */
3907 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3908 XFillRectangle (s->display, pixmap, s->gc,
3909 0, 0, s->background_width, s->height);
3910 XSetFillStyle (s->display, s->gc, FillSolid);
3911 }
3912 else
3913 {
3914 XGCValues xgcv;
3915 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3916 &xgcv);
3917 XSetForeground (s->display, s->gc, xgcv.background);
3918 XFillRectangle (s->display, pixmap, s->gc,
3919 0, 0, s->background_width, s->height);
3920 XSetForeground (s->display, s->gc, xgcv.foreground);
3921 }
3922 }
3923 else
3924 /* Implementation idea: Is it possible to construct a mask?
3925 We could look at the color at the margins of the image, and
3926 say that this color is probably the background color of the
3927 image. */
3928 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3929
3930 s->background_filled_p = 1;
3931 }
dc43ef94 3932
06a2c219
GM
3933 /* Draw the foreground. */
3934 if (pixmap != None)
3935 {
3936 x_draw_image_foreground_1 (s, pixmap);
3937 x_set_glyph_string_clipping (s);
3938 XCopyArea (s->display, pixmap, s->window, s->gc,
3939 0, 0, s->background_width, s->height, s->x, s->y);
3940 XFreePixmap (s->display, pixmap);
3941 }
3942 else
3943 x_draw_image_foreground (s);
b5210ea7 3944
06a2c219
GM
3945 /* If we must draw a relief around the image, do it. */
3946 if (s->img->relief
3947 || s->hl == DRAW_IMAGE_RAISED
3948 || s->hl == DRAW_IMAGE_SUNKEN)
3949 x_draw_image_relief (s);
3950}
8c1a6a84 3951
990ba854 3952
06a2c219 3953/* Draw stretch glyph string S. */
dc43ef94 3954
06a2c219
GM
3955static void
3956x_draw_stretch_glyph_string (s)
3957 struct glyph_string *s;
3958{
3959 xassert (s->first_glyph->type == STRETCH_GLYPH);
3960 s->stippled_p = s->face->stipple != 0;
990ba854 3961
06a2c219
GM
3962 if (s->hl == DRAW_CURSOR
3963 && !x_stretch_cursor_p)
3964 {
3965 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3966 as wide as the stretch glyph. */
3967 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 3968
06a2c219
GM
3969 /* Draw cursor. */
3970 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 3971
06a2c219
GM
3972 /* Clear rest using the GC of the original non-cursor face. */
3973 if (width < s->background_width)
3974 {
3975 GC gc = s->face->gc;
3976 int x = s->x + width, y = s->y;
3977 int w = s->background_width - width, h = s->height;
3978 XRectangle r;
dc43ef94 3979
06a2c219
GM
3980 x_get_glyph_string_clip_rect (s, &r);
3981 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 3982
06a2c219
GM
3983 if (s->face->stipple)
3984 {
3985 /* Fill background with a stipple pattern. */
3986 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3987 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3988 XSetFillStyle (s->display, gc, FillSolid);
3989 }
3990 else
3991 {
3992 XGCValues xgcv;
3993 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3994 XSetForeground (s->display, gc, xgcv.background);
3995 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3996 XSetForeground (s->display, gc, xgcv.foreground);
3997 }
3998 }
3999 }
4000 else
4001 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4002 s->height);
4003
4004 s->background_filled_p = 1;
4005}
4006
4007
4008/* Draw glyph string S. */
4009
4010static void
4011x_draw_glyph_string (s)
4012 struct glyph_string *s;
4013{
4014 /* If S draws into the background of its successor, draw the
4015 background of the successor first so that S can draw into it.
4016 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4017 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4018 {
4019 xassert (s->next->img == NULL);
4020 x_set_glyph_string_gc (s->next);
4021 x_set_glyph_string_clipping (s->next);
4022 x_draw_glyph_string_background (s->next, 1);
4023 }
97210f4e 4024
06a2c219
GM
4025 /* Set up S->gc, set clipping and draw S. */
4026 x_set_glyph_string_gc (s);
4027 x_set_glyph_string_clipping (s);
4028
4029 switch (s->first_glyph->type)
4030 {
4031 case IMAGE_GLYPH:
4032 x_draw_image_glyph_string (s);
4033 break;
4034
4035 case STRETCH_GLYPH:
4036 x_draw_stretch_glyph_string (s);
4037 break;
4038
4039 case CHAR_GLYPH:
66ac4b0e
GM
4040 if (s->for_overlaps_p)
4041 s->background_filled_p = 1;
4042 else
4043 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4044 x_draw_glyph_string_foreground (s);
4045 break;
4046
b4192550
KH
4047 case COMPOSITE_GLYPH:
4048 if (s->for_overlaps_p || s->gidx > 0)
4049 s->background_filled_p = 1;
4050 else
4051 x_draw_glyph_string_background (s, 1);
4052 x_draw_composite_glyph_string_foreground (s);
4053 break;
4054
06a2c219
GM
4055 default:
4056 abort ();
4057 }
4058
66ac4b0e 4059 if (!s->for_overlaps_p)
06a2c219 4060 {
66ac4b0e
GM
4061 /* Draw underline. */
4062 if (s->face->underline_p)
4063 {
4064 unsigned long dy, h;
06a2c219 4065
66ac4b0e
GM
4066 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4067 h = 1;
4068 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4069 dy = s->height - h;
06a2c219 4070
66ac4b0e
GM
4071 if (s->face->underline_defaulted_p)
4072 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4073 s->width, h);
4074 else
4075 {
4076 XGCValues xgcv;
4077 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4078 XSetForeground (s->display, s->gc, s->face->underline_color);
4079 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4080 s->width, h);
4081 XSetForeground (s->display, s->gc, xgcv.foreground);
4082 }
dc6f92b8 4083 }
07e34cb0 4084
66ac4b0e
GM
4085 /* Draw overline. */
4086 if (s->face->overline_p)
06a2c219 4087 {
66ac4b0e
GM
4088 unsigned long dy = 0, h = 1;
4089
4090 if (s->face->overline_color_defaulted_p)
4091 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4092 s->width, h);
4093 else
4094 {
4095 XGCValues xgcv;
4096 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4097 XSetForeground (s->display, s->gc, s->face->overline_color);
4098 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4099 s->width, h);
4100 XSetForeground (s->display, s->gc, xgcv.foreground);
4101 }
06a2c219 4102 }
06a2c219 4103
66ac4b0e
GM
4104 /* Draw strike-through. */
4105 if (s->face->strike_through_p)
06a2c219 4106 {
66ac4b0e
GM
4107 unsigned long h = 1;
4108 unsigned long dy = (s->height - h) / 2;
4109
4110 if (s->face->strike_through_color_defaulted_p)
4111 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4112 s->width, h);
4113 else
4114 {
4115 XGCValues xgcv;
4116 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4117 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4118 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4119 s->width, h);
4120 XSetForeground (s->display, s->gc, xgcv.foreground);
4121 }
06a2c219 4122 }
06a2c219 4123
66ac4b0e
GM
4124 /* Draw relief. */
4125 if (s->face->box != FACE_NO_BOX)
4126 x_draw_glyph_string_box (s);
4127 }
06a2c219
GM
4128
4129 /* Reset clipping. */
4130 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4131}
07e34cb0 4132
06a2c219 4133
b4192550
KH
4134static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4135 struct face **, int));
06a2c219 4136
06a2c219 4137
b4192550
KH
4138/* Load glyph string S with a composition components specified by S->cmp.
4139 FACES is an array of faces for all components of this composition.
4140 S->gidx is the index of the first component for S.
4141 OVERLAPS_P non-zero means S should draw the foreground only, and
4142 use its lines physical height for clipping.
06a2c219 4143
b4192550 4144 Value is the index of a component not in S. */
07e34cb0 4145
b4192550
KH
4146static int
4147x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4148 struct glyph_string *s;
b4192550 4149 struct face **faces;
66ac4b0e 4150 int overlaps_p;
07e34cb0 4151{
b4192550 4152 int i;
06a2c219 4153
b4192550 4154 xassert (s);
06a2c219 4155
b4192550 4156 s->for_overlaps_p = overlaps_p;
06a2c219 4157
b4192550
KH
4158 s->face = faces[s->gidx];
4159 s->font = s->face->font;
4160 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4161
b4192550
KH
4162 /* For all glyphs of this composition, starting at the offset
4163 S->gidx, until we reach the end of the definition or encounter a
4164 glyph that requires the different face, add it to S. */
4165 ++s->nchars;
4166 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4167 ++s->nchars;
06a2c219 4168
b4192550
KH
4169 /* All glyph strings for the same composition has the same width,
4170 i.e. the width set for the first component of the composition. */
06a2c219 4171
06a2c219
GM
4172 s->width = s->first_glyph->pixel_width;
4173
4174 /* If the specified font could not be loaded, use the frame's
4175 default font, but record the fact that we couldn't load it in
4176 the glyph string so that we can draw rectangles for the
4177 characters of the glyph string. */
4178 if (s->font == NULL)
4179 {
4180 s->font_not_found_p = 1;
4181 s->font = FRAME_FONT (s->f);
4182 }
4183
4184 /* Adjust base line for subscript/superscript text. */
4185 s->ybase += s->first_glyph->voffset;
4186
4187 xassert (s->face && s->face->gc);
4188
4189 /* This glyph string must always be drawn with 16-bit functions. */
4190 s->two_byte_p = 1;
b4192550
KH
4191
4192 return s->gidx + s->nchars;
06a2c219
GM
4193}
4194
4195
b4192550 4196/* Load glyph string S with a sequence characters.
06a2c219 4197 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4198 first glyph to consider, END is the index of the last + 1.
4199 OVERLAPS_P non-zero means S should draw the foreground only, and
4200 use its lines physical height for clipping.
4201
4202 Value is the index of the first glyph not in S. */
06a2c219
GM
4203
4204static int
66ac4b0e 4205x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4206 struct glyph_string *s;
4207 int face_id;
66ac4b0e 4208 int start, end, overlaps_p;
06a2c219
GM
4209{
4210 struct glyph *glyph, *last;
4211 int voffset;
ee569018 4212 int glyph_not_available_p;
06a2c219 4213
06a2c219
GM
4214 xassert (s->f == XFRAME (s->w->frame));
4215 xassert (s->nchars == 0);
4216 xassert (start >= 0 && end > start);
4217
66ac4b0e 4218 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4219 glyph = s->row->glyphs[s->area] + start;
4220 last = s->row->glyphs[s->area] + end;
4221 voffset = glyph->voffset;
4222
ee569018
KH
4223 glyph_not_available_p = glyph->glyph_not_available_p;
4224
06a2c219
GM
4225 while (glyph < last
4226 && glyph->type == CHAR_GLYPH
4227 && glyph->voffset == voffset
ee569018
KH
4228 /* Same face id implies same font, nowadays. */
4229 && glyph->face_id == face_id
4230 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4231 {
ee569018
KH
4232 int two_byte_p;
4233
06a2c219 4234 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4235 s->char2b + s->nchars,
4236 &two_byte_p);
4237 s->two_byte_p = two_byte_p;
06a2c219
GM
4238 ++s->nchars;
4239 xassert (s->nchars <= end - start);
4240 s->width += glyph->pixel_width;
4241 ++glyph;
4242 }
4243
4244 s->font = s->face->font;
4245 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4246
4247 /* If the specified font could not be loaded, use the frame's font,
4248 but record the fact that we couldn't load it in
4249 S->font_not_found_p so that we can draw rectangles for the
4250 characters of the glyph string. */
ee569018 4251 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4252 {
4253 s->font_not_found_p = 1;
4254 s->font = FRAME_FONT (s->f);
4255 }
4256
4257 /* Adjust base line for subscript/superscript text. */
4258 s->ybase += voffset;
66ac4b0e 4259
06a2c219
GM
4260 xassert (s->face && s->face->gc);
4261 return glyph - s->row->glyphs[s->area];
07e34cb0 4262}
dc6f92b8 4263
06a2c219
GM
4264
4265/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4266
dfcf069d 4267static void
06a2c219
GM
4268x_fill_image_glyph_string (s)
4269 struct glyph_string *s;
4270{
4271 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4272 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4273 xassert (s->img);
43d120d8 4274 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4275 s->font = s->face->font;
4276 s->width = s->first_glyph->pixel_width;
4277
4278 /* Adjust base line for subscript/superscript text. */
4279 s->ybase += s->first_glyph->voffset;
4280}
4281
4282
4283/* Fill glyph string S from stretch glyph S->first_glyph. */
4284
4285static void
4286x_fill_stretch_glyph_string (s)
4287 struct glyph_string *s;
4288{
4289 xassert (s->first_glyph->type == STRETCH_GLYPH);
43d120d8 4290 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4291 s->font = s->face->font;
4292 s->width = s->first_glyph->pixel_width;
4293
4294 /* Adjust base line for subscript/superscript text. */
4295 s->ybase += s->first_glyph->voffset;
4296}
4297
4298
4299/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4300 of XChar2b structures for S; it can't be allocated in
4301 x_init_glyph_string because it must be allocated via `alloca'. W
4302 is the window on which S is drawn. ROW and AREA are the glyph row
4303 and area within the row from which S is constructed. START is the
4304 index of the first glyph structure covered by S. HL is a
4305 face-override for drawing S. */
4306
4307static void
4308x_init_glyph_string (s, char2b, w, row, area, start, hl)
4309 struct glyph_string *s;
4310 XChar2b *char2b;
4311 struct window *w;
4312 struct glyph_row *row;
4313 enum glyph_row_area area;
4314 int start;
4315 enum draw_glyphs_face hl;
4316{
4317 bzero (s, sizeof *s);
4318 s->w = w;
4319 s->f = XFRAME (w->frame);
4320 s->display = FRAME_X_DISPLAY (s->f);
4321 s->window = FRAME_X_WINDOW (s->f);
4322 s->char2b = char2b;
4323 s->hl = hl;
4324 s->row = row;
4325 s->area = area;
4326 s->first_glyph = row->glyphs[area] + start;
4327 s->height = row->height;
4328 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4329
9ea173e8
GM
4330 /* Display the internal border below the tool-bar window. */
4331 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4332 s->y -= s->f->output_data.x->internal_border_width;
4333
4334 s->ybase = s->y + row->ascent;
4335}
4336
4337
4338/* Set background width of glyph string S. START is the index of the
4339 first glyph following S. LAST_X is the right-most x-position + 1
4340 in the drawing area. */
4341
4342static INLINE void
4343x_set_glyph_string_background_width (s, start, last_x)
4344 struct glyph_string *s;
4345 int start;
4346 int last_x;
4347{
4348 /* If the face of this glyph string has to be drawn to the end of
4349 the drawing area, set S->extends_to_end_of_line_p. */
4350 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4351
4352 if (start == s->row->used[s->area]
4353 && s->hl == DRAW_NORMAL_TEXT
4354 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4355 || s->face->background != default_face->background
4356 || s->face->stipple != default_face->stipple))
4357 s->extends_to_end_of_line_p = 1;
4358
4359 /* If S extends its face to the end of the line, set its
4360 background_width to the distance to the right edge of the drawing
4361 area. */
4362 if (s->extends_to_end_of_line_p)
1da3fd71 4363 s->background_width = last_x - s->x + 1;
06a2c219
GM
4364 else
4365 s->background_width = s->width;
4366}
4367
4368
4369/* Add a glyph string for a stretch glyph to the list of strings
4370 between HEAD and TAIL. START is the index of the stretch glyph in
4371 row area AREA of glyph row ROW. END is the index of the last glyph
4372 in that glyph row area. X is the current output position assigned
4373 to the new glyph string constructed. HL overrides that face of the
4374 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4375 is the right-most x-position of the drawing area. */
4376
8abee2e1
DL
4377/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4378 and below -- keep them on one line. */
4379#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4380 do \
4381 { \
4382 s = (struct glyph_string *) alloca (sizeof *s); \
4383 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4384 x_fill_stretch_glyph_string (s); \
4385 x_append_glyph_string (&HEAD, &TAIL, s); \
4386 ++START; \
4387 s->x = (X); \
4388 } \
4389 while (0)
4390
4391
4392/* Add a glyph string for an image glyph to the list of strings
4393 between HEAD and TAIL. START is the index of the image glyph in
4394 row area AREA of glyph row ROW. END is the index of the last glyph
4395 in that glyph row area. X is the current output position assigned
4396 to the new glyph string constructed. HL overrides that face of the
4397 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4398 is the right-most x-position of the drawing area. */
4399
8abee2e1 4400#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4401 do \
4402 { \
4403 s = (struct glyph_string *) alloca (sizeof *s); \
4404 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4405 x_fill_image_glyph_string (s); \
4406 x_append_glyph_string (&HEAD, &TAIL, s); \
4407 ++START; \
4408 s->x = (X); \
4409 } \
4410 while (0)
4411
4412
4413/* Add a glyph string for a sequence of character glyphs to the list
4414 of strings between HEAD and TAIL. START is the index of the first
4415 glyph in row area AREA of glyph row ROW that is part of the new
4416 glyph string. END is the index of the last glyph in that glyph row
4417 area. X is the current output position assigned to the new glyph
4418 string constructed. HL overrides that face of the glyph; e.g. it
4419 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4420 right-most x-position of the drawing area. */
4421
8abee2e1 4422#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4423 do \
4424 { \
3e71d8f2 4425 int c, face_id; \
06a2c219
GM
4426 XChar2b *char2b; \
4427 \
43d120d8 4428 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4429 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4430 \
b4192550
KH
4431 s = (struct glyph_string *) alloca (sizeof *s); \
4432 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4433 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4434 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4435 s->x = (X); \
4436 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4437 OVERLAPS_P); \
06a2c219
GM
4438 } \
4439 while (0)
4440
4441
b4192550
KH
4442/* Add a glyph string for a composite sequence to the list of strings
4443 between HEAD and TAIL. START is the index of the first glyph in
4444 row area AREA of glyph row ROW that is part of the new glyph
4445 string. END is the index of the last glyph in that glyph row area.
4446 X is the current output position assigned to the new glyph string
4447 constructed. HL overrides that face of the glyph; e.g. it is
4448 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4449 x-position of the drawing area. */
4450
6c27ec25 4451#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4452 do { \
43d120d8
KH
4453 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4454 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4455 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4456 struct composition *cmp = composition_table[cmp_id]; \
4457 int glyph_len = cmp->glyph_len; \
4458 XChar2b *char2b; \
4459 struct face **faces; \
4460 struct glyph_string *first_s = NULL; \
4461 int n; \
4462 \
ee569018 4463 base_face = base_face->ascii_face; \
b4192550
KH
4464 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4465 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4466 /* At first, fill in `char2b' and `faces'. */ \
4467 for (n = 0; n < glyph_len; n++) \
4468 { \
43d120d8 4469 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4470 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4471 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4472 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4473 this_face_id, char2b + n, 1); \
b4192550
KH
4474 } \
4475 \
4476 /* Make glyph_strings for each glyph sequence that is drawable by \
4477 the same face, and append them to HEAD/TAIL. */ \
4478 for (n = 0; n < cmp->glyph_len;) \
4479 { \
4480 s = (struct glyph_string *) alloca (sizeof *s); \
4481 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4482 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4483 s->cmp = cmp; \
4484 s->gidx = n; \
b4192550
KH
4485 s->x = (X); \
4486 \
4487 if (n == 0) \
4488 first_s = s; \
4489 \
4490 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4491 } \
4492 \
4493 ++START; \
4494 s = first_s; \
4495 } while (0)
4496
4497
06a2c219
GM
4498/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4499 of AREA of glyph row ROW on window W between indices START and END.
4500 HL overrides the face for drawing glyph strings, e.g. it is
4501 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4502 x-positions of the drawing area.
4503
4504 This is an ugly monster macro construct because we must use alloca
4505 to allocate glyph strings (because x_draw_glyphs can be called
4506 asynchronously). */
4507
8abee2e1 4508#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4509 do \
4510 { \
4511 HEAD = TAIL = NULL; \
4512 while (START < END) \
4513 { \
4514 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4515 switch (first_glyph->type) \
4516 { \
4517 case CHAR_GLYPH: \
4518 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4519 TAIL, HL, X, LAST_X, \
4520 OVERLAPS_P); \
06a2c219
GM
4521 break; \
4522 \
b4192550
KH
4523 case COMPOSITE_GLYPH: \
4524 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4525 HEAD, TAIL, HL, X, LAST_X,\
4526 OVERLAPS_P); \
4527 break; \
4528 \
06a2c219
GM
4529 case STRETCH_GLYPH: \
4530 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4531 HEAD, TAIL, HL, X, LAST_X); \
4532 break; \
4533 \
4534 case IMAGE_GLYPH: \
4535 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4536 TAIL, HL, X, LAST_X); \
4537 break; \
4538 \
4539 default: \
4540 abort (); \
4541 } \
4542 \
4543 x_set_glyph_string_background_width (s, START, LAST_X); \
4544 (X) += s->width; \
4545 } \
4546 } \
4547 while (0)
4548
4549
4550/* Draw glyphs between START and END in AREA of ROW on window W,
4551 starting at x-position X. X is relative to AREA in W. HL is a
4552 face-override with the following meaning:
4553
4554 DRAW_NORMAL_TEXT draw normally
4555 DRAW_CURSOR draw in cursor face
4556 DRAW_MOUSE_FACE draw in mouse face.
4557 DRAW_INVERSE_VIDEO draw in mode line face
4558 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4559 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4560
4561 If REAL_START is non-null, return in *REAL_START the real starting
4562 position for display. This can be different from START in case
4563 overlapping glyphs must be displayed. If REAL_END is non-null,
4564 return in *REAL_END the real end position for display. This can be
4565 different from END in case overlapping glyphs must be displayed.
4566
66ac4b0e
GM
4567 If OVERLAPS_P is non-zero, draw only the foreground of characters
4568 and clip to the physical height of ROW.
4569
06a2c219
GM
4570 Value is the x-position reached, relative to AREA of W. */
4571
4572static int
66ac4b0e
GM
4573x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4574 overlaps_p)
06a2c219
GM
4575 struct window *w;
4576 int x;
4577 struct glyph_row *row;
4578 enum glyph_row_area area;
4579 int start, end;
4580 enum draw_glyphs_face hl;
4581 int *real_start, *real_end;
66ac4b0e 4582 int overlaps_p;
dc6f92b8 4583{
06a2c219
GM
4584 struct glyph_string *head, *tail;
4585 struct glyph_string *s;
4586 int last_x, area_width;
4587 int x_reached;
4588 int i, j;
4589
4590 /* Let's rather be paranoid than getting a SEGV. */
4591 start = max (0, start);
4592 end = min (end, row->used[area]);
4593 if (real_start)
4594 *real_start = start;
4595 if (real_end)
4596 *real_end = end;
4597
4598 /* Translate X to frame coordinates. Set last_x to the right
4599 end of the drawing area. */
4600 if (row->full_width_p)
4601 {
4602 /* X is relative to the left edge of W, without scroll bars
4603 or flag areas. */
4604 struct frame *f = XFRAME (w->frame);
110859fc 4605 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4606 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4607
06a2c219
GM
4608 x += window_left_x;
4609 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4610 last_x = window_left_x + area_width;
4611
4612 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4613 {
110859fc 4614 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4615 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4616 last_x += width;
4617 else
4618 x -= width;
4619 }
dc6f92b8 4620
b9432a85
GM
4621 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4622 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4623 }
4624 else
dc6f92b8 4625 {
06a2c219
GM
4626 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4627 area_width = window_box_width (w, area);
4628 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4629 }
4630
06a2c219
GM
4631 /* Build a doubly-linked list of glyph_string structures between
4632 head and tail from what we have to draw. Note that the macro
4633 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4634 the reason we use a separate variable `i'. */
4635 i = start;
66ac4b0e
GM
4636 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4637 overlaps_p);
06a2c219
GM
4638 if (tail)
4639 x_reached = tail->x + tail->background_width;
4640 else
4641 x_reached = x;
90e65f07 4642
06a2c219
GM
4643 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4644 the row, redraw some glyphs in front or following the glyph
4645 strings built above. */
66ac4b0e 4646 if (!overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4647 {
4648 int dummy_x = 0;
4649 struct glyph_string *h, *t;
4650
4651 /* Compute overhangs for all glyph strings. */
4652 for (s = head; s; s = s->next)
4653 x_compute_glyph_string_overhangs (s);
4654
4655 /* Prepend glyph strings for glyphs in front of the first glyph
4656 string that are overwritten because of the first glyph
4657 string's left overhang. The background of all strings
4658 prepended must be drawn because the first glyph string
4659 draws over it. */
4660 i = x_left_overwritten (head);
4661 if (i >= 0)
4662 {
4663 j = i;
4664 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4665 DRAW_NORMAL_TEXT, dummy_x, last_x,
4666 overlaps_p);
06a2c219
GM
4667 start = i;
4668 if (real_start)
4669 *real_start = start;
4670 x_compute_overhangs_and_x (t, head->x, 1);
4671 x_prepend_glyph_string_lists (&head, &tail, h, t);
4672 }
58769bee 4673
06a2c219
GM
4674 /* Prepend glyph strings for glyphs in front of the first glyph
4675 string that overwrite that glyph string because of their
4676 right overhang. For these strings, only the foreground must
4677 be drawn, because it draws over the glyph string at `head'.
4678 The background must not be drawn because this would overwrite
4679 right overhangs of preceding glyphs for which no glyph
4680 strings exist. */
4681 i = x_left_overwriting (head);
4682 if (i >= 0)
4683 {
4684 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4685 DRAW_NORMAL_TEXT, dummy_x, last_x,
4686 overlaps_p);
06a2c219
GM
4687 for (s = h; s; s = s->next)
4688 s->background_filled_p = 1;
4689 if (real_start)
4690 *real_start = i;
4691 x_compute_overhangs_and_x (t, head->x, 1);
4692 x_prepend_glyph_string_lists (&head, &tail, h, t);
4693 }
dbcb258a 4694
06a2c219
GM
4695 /* Append glyphs strings for glyphs following the last glyph
4696 string tail that are overwritten by tail. The background of
4697 these strings has to be drawn because tail's foreground draws
4698 over it. */
4699 i = x_right_overwritten (tail);
4700 if (i >= 0)
4701 {
4702 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4703 DRAW_NORMAL_TEXT, x, last_x,
4704 overlaps_p);
06a2c219
GM
4705 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4706 x_append_glyph_string_lists (&head, &tail, h, t);
4707 if (real_end)
4708 *real_end = i;
4709 }
dc6f92b8 4710
06a2c219
GM
4711 /* Append glyph strings for glyphs following the last glyph
4712 string tail that overwrite tail. The foreground of such
4713 glyphs has to be drawn because it writes into the background
4714 of tail. The background must not be drawn because it could
4715 paint over the foreground of following glyphs. */
4716 i = x_right_overwriting (tail);
4717 if (i >= 0)
4718 {
4719 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4720 DRAW_NORMAL_TEXT, x, last_x,
4721 overlaps_p);
06a2c219
GM
4722 for (s = h; s; s = s->next)
4723 s->background_filled_p = 1;
4724 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4725 x_append_glyph_string_lists (&head, &tail, h, t);
4726 if (real_end)
4727 *real_end = i;
4728 }
4729 }
58769bee 4730
06a2c219
GM
4731 /* Draw all strings. */
4732 for (s = head; s; s = s->next)
4733 x_draw_glyph_string (s);
dc6f92b8 4734
06a2c219
GM
4735 /* Value is the x-position up to which drawn, relative to AREA of W.
4736 This doesn't include parts drawn because of overhangs. */
4737 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4738 if (!row->full_width_p)
4739 {
4740 if (area > LEFT_MARGIN_AREA)
4741 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4742 if (area > TEXT_AREA)
4743 x_reached -= window_box_width (w, TEXT_AREA);
4744 }
4745 return x_reached;
4746}
dc6f92b8 4747
dc6f92b8 4748
66ac4b0e
GM
4749/* Fix the display of area AREA of overlapping row ROW in window W. */
4750
4751static void
4752x_fix_overlapping_area (w, row, area)
4753 struct window *w;
4754 struct glyph_row *row;
4755 enum glyph_row_area area;
4756{
4757 int i, x;
4758
4759 BLOCK_INPUT;
4760
4761 if (area == LEFT_MARGIN_AREA)
4762 x = 0;
4763 else if (area == TEXT_AREA)
4764 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4765 else
4766 x = (window_box_width (w, LEFT_MARGIN_AREA)
4767 + window_box_width (w, TEXT_AREA));
4768
4769 for (i = 0; i < row->used[area];)
4770 {
4771 if (row->glyphs[area][i].overlaps_vertically_p)
4772 {
4773 int start = i, start_x = x;
4774
4775 do
4776 {
4777 x += row->glyphs[area][i].pixel_width;
4778 ++i;
4779 }
4780 while (i < row->used[area]
4781 && row->glyphs[area][i].overlaps_vertically_p);
4782
4783 x_draw_glyphs (w, start_x, row, area, start, i,
4784 (row->inverse_p
4785 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4786 NULL, NULL, 1);
4787 }
4788 else
4789 {
4790 x += row->glyphs[area][i].pixel_width;
4791 ++i;
4792 }
4793 }
4794
4795 UNBLOCK_INPUT;
4796}
4797
4798
06a2c219
GM
4799/* Output LEN glyphs starting at START at the nominal cursor position.
4800 Advance the nominal cursor over the text. The global variable
4801 updated_window contains the window being updated, updated_row is
4802 the glyph row being updated, and updated_area is the area of that
4803 row being updated. */
dc6f92b8 4804
06a2c219
GM
4805static void
4806x_write_glyphs (start, len)
4807 struct glyph *start;
4808 int len;
4809{
4810 int x, hpos, real_start, real_end;
d9cdbb3d 4811
06a2c219 4812 xassert (updated_window && updated_row);
dc6f92b8 4813 BLOCK_INPUT;
06a2c219
GM
4814
4815 /* Write glyphs. */
dc6f92b8 4816
06a2c219
GM
4817 hpos = start - updated_row->glyphs[updated_area];
4818 x = x_draw_glyphs (updated_window, output_cursor.x,
4819 updated_row, updated_area,
4820 hpos, hpos + len,
4821 (updated_row->inverse_p
4822 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 4823 &real_start, &real_end, 0);
b30ec466 4824
06a2c219
GM
4825 /* If we drew over the cursor, note that it is not visible any more. */
4826 note_overwritten_text_cursor (updated_window, real_start,
4827 real_end - real_start);
dc6f92b8
JB
4828
4829 UNBLOCK_INPUT;
06a2c219
GM
4830
4831 /* Advance the output cursor. */
4832 output_cursor.hpos += len;
4833 output_cursor.x = x;
dc6f92b8
JB
4834}
4835
0cdd0c9f 4836
06a2c219 4837/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4838
06a2c219
GM
4839static void
4840x_insert_glyphs (start, len)
4841 struct glyph *start;
4842 register int len;
4843{
4844 struct frame *f;
4845 struct window *w;
4846 int line_height, shift_by_width, shifted_region_width;
4847 struct glyph_row *row;
4848 struct glyph *glyph;
4849 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4850
06a2c219 4851 xassert (updated_window && updated_row);
0cdd0c9f 4852 BLOCK_INPUT;
06a2c219
GM
4853 w = updated_window;
4854 f = XFRAME (WINDOW_FRAME (w));
4855
4856 /* Get the height of the line we are in. */
4857 row = updated_row;
4858 line_height = row->height;
4859
4860 /* Get the width of the glyphs to insert. */
4861 shift_by_width = 0;
4862 for (glyph = start; glyph < start + len; ++glyph)
4863 shift_by_width += glyph->pixel_width;
4864
4865 /* Get the width of the region to shift right. */
4866 shifted_region_width = (window_box_width (w, updated_area)
4867 - output_cursor.x
4868 - shift_by_width);
4869
4870 /* Shift right. */
4871 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4872 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4873 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4874 f->output_data.x->normal_gc,
4875 frame_x, frame_y,
4876 shifted_region_width, line_height,
4877 frame_x + shift_by_width, frame_y);
4878
4879 /* Write the glyphs. */
4880 hpos = start - row->glyphs[updated_area];
4881 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 4882 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
4883 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4884
4885 /* Advance the output cursor. */
4886 output_cursor.hpos += len;
4887 output_cursor.x += shift_by_width;
0cdd0c9f
RS
4888 UNBLOCK_INPUT;
4889}
0cdd0c9f 4890
0cdd0c9f 4891
06a2c219
GM
4892/* Delete N glyphs at the nominal cursor position. Not implemented
4893 for X frames. */
c83febd7
RS
4894
4895static void
06a2c219
GM
4896x_delete_glyphs (n)
4897 register int n;
c83febd7 4898{
06a2c219 4899 abort ();
c83febd7
RS
4900}
4901
0cdd0c9f 4902
06a2c219
GM
4903/* Erase the current text line from the nominal cursor position
4904 (inclusive) to pixel column TO_X (exclusive). The idea is that
4905 everything from TO_X onward is already erased.
4906
4907 TO_X is a pixel position relative to updated_area of
4908 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 4909
06a2c219
GM
4910static void
4911x_clear_end_of_line (to_x)
4912 int to_x;
4913{
4914 struct frame *f;
4915 struct window *w = updated_window;
4916 int max_x, min_y, max_y;
4917 int from_x, from_y, to_y;
4918
4919 xassert (updated_window && updated_row);
4920 f = XFRAME (w->frame);
4921
4922 if (updated_row->full_width_p)
4923 {
4924 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4925 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4926 && !w->pseudo_window_p)
4927 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 4928 }
06a2c219
GM
4929 else
4930 max_x = window_box_width (w, updated_area);
4931 max_y = window_text_bottom_y (w);
dc6f92b8 4932
06a2c219
GM
4933 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4934 of window. For TO_X > 0, truncate to end of drawing area. */
4935 if (to_x == 0)
4936 return;
4937 else if (to_x < 0)
4938 to_x = max_x;
4939 else
4940 to_x = min (to_x, max_x);
dbc4e1c1 4941
06a2c219
GM
4942 to_y = min (max_y, output_cursor.y + updated_row->height);
4943
4944 /* Notice if the cursor will be cleared by this operation. */
4945 if (!updated_row->full_width_p)
4946 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 4947
06a2c219
GM
4948 from_x = output_cursor.x;
4949
4950 /* Translate to frame coordinates. */
4951 if (updated_row->full_width_p)
4952 {
4953 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4954 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4955 }
0cdd0c9f
RS
4956 else
4957 {
06a2c219
GM
4958 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4959 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4960 }
4961
045dee35 4962 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
4963 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4964 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4965
4966 /* Prevent inadvertently clearing to end of the X window. */
4967 if (to_x > from_x && to_y > from_y)
4968 {
4969 BLOCK_INPUT;
4970 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4971 from_x, from_y, to_x - from_x, to_y - from_y,
4972 False);
4973 UNBLOCK_INPUT;
0cdd0c9f 4974 }
0cdd0c9f 4975}
dbc4e1c1 4976
0cdd0c9f 4977
06a2c219 4978/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 4979 frame. Otherwise clear the selected frame. */
06a2c219
GM
4980
4981static void
4982x_clear_frame ()
0cdd0c9f 4983{
06a2c219 4984 struct frame *f;
0cdd0c9f 4985
06a2c219
GM
4986 if (updating_frame)
4987 f = updating_frame;
0cdd0c9f 4988 else
b86bd3dd 4989 f = SELECTED_FRAME ();
58769bee 4990
06a2c219
GM
4991 /* Clearing the frame will erase any cursor, so mark them all as no
4992 longer visible. */
4993 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4994 output_cursor.hpos = output_cursor.vpos = 0;
4995 output_cursor.x = -1;
4996
4997 /* We don't set the output cursor here because there will always
4998 follow an explicit cursor_to. */
4999 BLOCK_INPUT;
5000 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5001
5002 /* We have to clear the scroll bars, too. If we have changed
5003 colors or something like that, then they should be notified. */
5004 x_scroll_bar_clear (f);
0cdd0c9f 5005
06a2c219
GM
5006 XFlush (FRAME_X_DISPLAY (f));
5007 UNBLOCK_INPUT;
dc6f92b8 5008}
06a2c219
GM
5009
5010
dc6f92b8 5011\f
dbc4e1c1
JB
5012/* Invert the middle quarter of the frame for .15 sec. */
5013
06a2c219
GM
5014/* We use the select system call to do the waiting, so we have to make
5015 sure it's available. If it isn't, we just won't do visual bells. */
5016
dbc4e1c1
JB
5017#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5018
06a2c219
GM
5019
5020/* Subtract the `struct timeval' values X and Y, storing the result in
5021 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5022
5023static int
5024timeval_subtract (result, x, y)
5025 struct timeval *result, x, y;
5026{
06a2c219
GM
5027 /* Perform the carry for the later subtraction by updating y. This
5028 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5029 if (x.tv_usec < y.tv_usec)
5030 {
5031 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5032 y.tv_usec -= 1000000 * nsec;
5033 y.tv_sec += nsec;
5034 }
06a2c219 5035
dbc4e1c1
JB
5036 if (x.tv_usec - y.tv_usec > 1000000)
5037 {
5038 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5039 y.tv_usec += 1000000 * nsec;
5040 y.tv_sec -= nsec;
5041 }
5042
06a2c219
GM
5043 /* Compute the time remaining to wait. tv_usec is certainly
5044 positive. */
dbc4e1c1
JB
5045 result->tv_sec = x.tv_sec - y.tv_sec;
5046 result->tv_usec = x.tv_usec - y.tv_usec;
5047
06a2c219
GM
5048 /* Return indication of whether the result should be considered
5049 negative. */
dbc4e1c1
JB
5050 return x.tv_sec < y.tv_sec;
5051}
dc6f92b8 5052
dfcf069d 5053void
f676886a
JB
5054XTflash (f)
5055 struct frame *f;
dc6f92b8 5056{
dbc4e1c1 5057 BLOCK_INPUT;
dc6f92b8 5058
dbc4e1c1
JB
5059 {
5060 GC gc;
dc6f92b8 5061
06a2c219
GM
5062 /* Create a GC that will use the GXxor function to flip foreground
5063 pixels into background pixels. */
dbc4e1c1
JB
5064 {
5065 XGCValues values;
dc6f92b8 5066
dbc4e1c1 5067 values.function = GXxor;
7556890b
RS
5068 values.foreground = (f->output_data.x->foreground_pixel
5069 ^ f->output_data.x->background_pixel);
58769bee 5070
334208b7 5071 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5072 GCFunction | GCForeground, &values);
5073 }
dc6f92b8 5074
dbc4e1c1 5075 {
e84e14c3
RS
5076 /* Get the height not including a menu bar widget. */
5077 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5078 /* Height of each line to flash. */
5079 int flash_height = FRAME_LINE_HEIGHT (f);
5080 /* These will be the left and right margins of the rectangles. */
5081 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5082 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5083
5084 int width;
5085
5086 /* Don't flash the area between a scroll bar and the frame
5087 edge it is next to. */
5088 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5089 {
5090 case vertical_scroll_bar_left:
5091 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5092 break;
5093
5094 case vertical_scroll_bar_right:
5095 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5096 break;
06a2c219
GM
5097
5098 default:
5099 break;
e84e14c3
RS
5100 }
5101
5102 width = flash_right - flash_left;
5103
5104 /* If window is tall, flash top and bottom line. */
5105 if (height > 3 * FRAME_LINE_HEIGHT (f))
5106 {
5107 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5108 flash_left,
5109 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5110 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5111 width, flash_height);
5112 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5113 flash_left,
5114 (height - flash_height
5115 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5116 width, flash_height);
5117 }
5118 else
5119 /* If it is short, flash it all. */
5120 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5121 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5122 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5123
06a2c219 5124 x_flush (f);
dc6f92b8 5125
dbc4e1c1 5126 {
06a2c219 5127 struct timeval wakeup;
dc6f92b8 5128
66c30ea1 5129 EMACS_GET_TIME (wakeup);
dc6f92b8 5130
dbc4e1c1
JB
5131 /* Compute time to wait until, propagating carry from usecs. */
5132 wakeup.tv_usec += 150000;
5133 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5134 wakeup.tv_usec %= 1000000;
5135
5136 /* Keep waiting until past the time wakeup. */
5137 while (1)
5138 {
5139 struct timeval timeout;
5140
66c30ea1 5141 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5142
5143 /* In effect, timeout = wakeup - timeout.
5144 Break if result would be negative. */
5145 if (timeval_subtract (&timeout, wakeup, timeout))
5146 break;
5147
5148 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5149 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5150 }
5151 }
58769bee 5152
e84e14c3
RS
5153 /* If window is tall, flash top and bottom line. */
5154 if (height > 3 * FRAME_LINE_HEIGHT (f))
5155 {
5156 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5157 flash_left,
5158 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5159 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5160 width, flash_height);
5161 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5162 flash_left,
5163 (height - flash_height
5164 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5165 width, flash_height);
5166 }
5167 else
5168 /* If it is short, flash it all. */
5169 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5170 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5171 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5172
334208b7 5173 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5174 x_flush (f);
dc6f92b8 5175 }
dbc4e1c1
JB
5176 }
5177
5178 UNBLOCK_INPUT;
dc6f92b8
JB
5179}
5180
06a2c219 5181#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5182
5183
dc6f92b8
JB
5184/* Make audible bell. */
5185
dfcf069d 5186void
dc6f92b8
JB
5187XTring_bell ()
5188{
b86bd3dd
GM
5189 struct frame *f = SELECTED_FRAME ();
5190
5191 if (FRAME_X_DISPLAY (f))
5192 {
dbc4e1c1 5193#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5194 if (visible_bell)
5195 XTflash (f);
5196 else
dbc4e1c1 5197#endif
b86bd3dd
GM
5198 {
5199 BLOCK_INPUT;
5200 XBell (FRAME_X_DISPLAY (f), 0);
5201 XFlush (FRAME_X_DISPLAY (f));
5202 UNBLOCK_INPUT;
5203 }
dc6f92b8
JB
5204 }
5205}
06a2c219 5206
dc6f92b8 5207\f
06a2c219
GM
5208/* Specify how many text lines, from the top of the window,
5209 should be affected by insert-lines and delete-lines operations.
5210 This, and those operations, are used only within an update
5211 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5212
dfcf069d 5213static void
06a2c219
GM
5214XTset_terminal_window (n)
5215 register int n;
dc6f92b8 5216{
06a2c219 5217 /* This function intentionally left blank. */
dc6f92b8
JB
5218}
5219
06a2c219
GM
5220
5221\f
5222/***********************************************************************
5223 Line Dance
5224 ***********************************************************************/
5225
5226/* Perform an insert-lines or delete-lines operation, inserting N
5227 lines or deleting -N lines at vertical position VPOS. */
5228
dfcf069d 5229static void
06a2c219
GM
5230x_ins_del_lines (vpos, n)
5231 int vpos, n;
dc6f92b8
JB
5232{
5233 abort ();
5234}
06a2c219
GM
5235
5236
5237/* Scroll part of the display as described by RUN. */
dc6f92b8 5238
dfcf069d 5239static void
06a2c219
GM
5240x_scroll_run (w, run)
5241 struct window *w;
5242 struct run *run;
dc6f92b8 5243{
06a2c219
GM
5244 struct frame *f = XFRAME (w->frame);
5245 int x, y, width, height, from_y, to_y, bottom_y;
5246
5247 /* Get frame-relative bounding box of the text display area of W,
5248 without mode lines. Include in this box the flags areas to the
5249 left and right of W. */
5250 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5251 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5252 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5253
5254 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5255 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5256 bottom_y = y + height;
dc6f92b8 5257
06a2c219
GM
5258 if (to_y < from_y)
5259 {
5260 /* Scrolling up. Make sure we don't copy part of the mode
5261 line at the bottom. */
5262 if (from_y + run->height > bottom_y)
5263 height = bottom_y - from_y;
5264 else
5265 height = run->height;
5266 }
dc6f92b8 5267 else
06a2c219
GM
5268 {
5269 /* Scolling down. Make sure we don't copy over the mode line.
5270 at the bottom. */
5271 if (to_y + run->height > bottom_y)
5272 height = bottom_y - to_y;
5273 else
5274 height = run->height;
5275 }
7a13e894 5276
06a2c219
GM
5277 BLOCK_INPUT;
5278
5279 /* Cursor off. Will be switched on again in x_update_window_end. */
5280 updated_window = w;
5281 x_clear_cursor (w);
5282
5283 XCopyArea (FRAME_X_DISPLAY (f),
5284 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5285 f->output_data.x->normal_gc,
5286 x, from_y,
5287 width, height,
5288 x, to_y);
5289
5290 UNBLOCK_INPUT;
5291}
dc6f92b8 5292
dc6f92b8 5293
06a2c219
GM
5294\f
5295/***********************************************************************
5296 Exposure Events
5297 ***********************************************************************/
5298
5299/* Redisplay an exposed area of frame F. X and Y are the upper-left
5300 corner of the exposed rectangle. W and H are width and height of
5301 the exposed area. All are pixel values. W or H zero means redraw
5302 the entire frame. */
dc6f92b8 5303
06a2c219
GM
5304static void
5305expose_frame (f, x, y, w, h)
5306 struct frame *f;
5307 int x, y, w, h;
dc6f92b8 5308{
06a2c219 5309 XRectangle r;
dc6f92b8 5310
06a2c219 5311 TRACE ((stderr, "expose_frame "));
dc6f92b8 5312
06a2c219
GM
5313 /* No need to redraw if frame will be redrawn soon. */
5314 if (FRAME_GARBAGED_P (f))
dc6f92b8 5315 {
06a2c219
GM
5316 TRACE ((stderr, " garbaged\n"));
5317 return;
5318 }
5319
5320 /* If basic faces haven't been realized yet, there is no point in
5321 trying to redraw anything. This can happen when we get an expose
5322 event while Emacs is starting, e.g. by moving another window. */
5323 if (FRAME_FACE_CACHE (f) == NULL
5324 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5325 {
5326 TRACE ((stderr, " no faces\n"));
5327 return;
58769bee 5328 }
06a2c219
GM
5329
5330 if (w == 0 || h == 0)
58769bee 5331 {
06a2c219
GM
5332 r.x = r.y = 0;
5333 r.width = CANON_X_UNIT (f) * f->width;
5334 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5335 }
5336 else
5337 {
06a2c219
GM
5338 r.x = x;
5339 r.y = y;
5340 r.width = w;
5341 r.height = h;
5342 }
5343
5344 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5345 expose_window_tree (XWINDOW (f->root_window), &r);
5346
9ea173e8 5347 if (WINDOWP (f->tool_bar_window))
06a2c219 5348 {
9ea173e8 5349 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5350 XRectangle window_rect;
5351 XRectangle intersection_rect;
5352 int window_x, window_y, window_width, window_height;
5353
5354
5355 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5356 window_rect.x = window_x;
5357 window_rect.y = window_y;
5358 window_rect.width = window_width;
5359 window_rect.height = window_height;
5360
5361 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5362 expose_window (w, &intersection_rect);
5363 }
5364
5365#ifndef USE_X_TOOLKIT
5366 if (WINDOWP (f->menu_bar_window))
5367 {
5368 struct window *w = XWINDOW (f->menu_bar_window);
5369 XRectangle window_rect;
5370 XRectangle intersection_rect;
5371 int window_x, window_y, window_width, window_height;
5372
5373
5374 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5375 window_rect.x = window_x;
5376 window_rect.y = window_y;
5377 window_rect.width = window_width;
5378 window_rect.height = window_height;
5379
5380 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5381 expose_window (w, &intersection_rect);
dc6f92b8 5382 }
06a2c219 5383#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5384}
5385
06a2c219
GM
5386
5387/* Redraw (parts) of all windows in the window tree rooted at W that
5388 intersect R. R contains frame pixel coordinates. */
5389
58769bee 5390static void
06a2c219
GM
5391expose_window_tree (w, r)
5392 struct window *w;
5393 XRectangle *r;
dc6f92b8 5394{
06a2c219
GM
5395 while (w)
5396 {
5397 if (!NILP (w->hchild))
5398 expose_window_tree (XWINDOW (w->hchild), r);
5399 else if (!NILP (w->vchild))
5400 expose_window_tree (XWINDOW (w->vchild), r);
5401 else
5402 {
5403 XRectangle window_rect;
5404 XRectangle intersection_rect;
5405 struct frame *f = XFRAME (w->frame);
5406 int window_x, window_y, window_width, window_height;
5407
5408 /* Frame-relative pixel rectangle of W. */
5409 window_box (w, -1, &window_x, &window_y, &window_width,
5410 &window_height);
5411 window_rect.x
5412 = (window_x
110859fc 5413 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5414 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5415 window_rect.y = window_y;
5416 window_rect.width
5417 = (window_width
110859fc 5418 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5419 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5420 window_rect.height
5421 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5422
5423 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5424 expose_window (w, &intersection_rect);
5425 }
58769bee 5426
06a2c219
GM
5427 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5428 }
5429}
58769bee 5430
dc6f92b8 5431
06a2c219
GM
5432/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5433 which intersects rectangle R. R is in window-relative coordinates. */
5434
5435static void
5436expose_area (w, row, r, area)
5437 struct window *w;
5438 struct glyph_row *row;
5439 XRectangle *r;
5440 enum glyph_row_area area;
5441{
5442 int x;
5443 struct glyph *first = row->glyphs[area];
5444 struct glyph *end = row->glyphs[area] + row->used[area];
5445 struct glyph *last;
5446 int first_x;
5447
5448 /* Set x to the window-relative start position for drawing glyphs of
5449 AREA. The first glyph of the text area can be partially visible.
5450 The first glyphs of other areas cannot. */
5451 if (area == LEFT_MARGIN_AREA)
5452 x = 0;
5453 else if (area == TEXT_AREA)
5454 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5455 else
5456 x = (window_box_width (w, LEFT_MARGIN_AREA)
5457 + window_box_width (w, TEXT_AREA));
5458
6fb13182
GM
5459 if (area == TEXT_AREA && row->fill_line_p)
5460 /* If row extends face to end of line write the whole line. */
5461 x_draw_glyphs (w, x, row, area,
5462 0, row->used[area],
06a2c219 5463 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5464 NULL, NULL, 0);
6fb13182
GM
5465 else
5466 {
5467 /* Find the first glyph that must be redrawn. */
5468 while (first < end
5469 && x + first->pixel_width < r->x)
5470 {
5471 x += first->pixel_width;
5472 ++first;
5473 }
5474
5475 /* Find the last one. */
5476 last = first;
5477 first_x = x;
5478 while (last < end
5479 && x < r->x + r->width)
5480 {
5481 x += last->pixel_width;
5482 ++last;
5483 }
5484
5485 /* Repaint. */
5486 if (last > first)
5487 x_draw_glyphs (w, first_x, row, area,
5488 first - row->glyphs[area],
5489 last - row->glyphs[area],
5490 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5491 NULL, NULL, 0);
5492 }
06a2c219
GM
5493}
5494
58769bee 5495
06a2c219
GM
5496/* Redraw the parts of the glyph row ROW on window W intersecting
5497 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5498
06a2c219
GM
5499static void
5500expose_line (w, row, r)
5501 struct window *w;
5502 struct glyph_row *row;
5503 XRectangle *r;
5504{
5505 xassert (row->enabled_p);
5506
5507 if (row->mode_line_p || w->pseudo_window_p)
5508 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5509 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5510 NULL, NULL, 0);
06a2c219
GM
5511 else
5512 {
5513 if (row->used[LEFT_MARGIN_AREA])
5514 expose_area (w, row, r, LEFT_MARGIN_AREA);
5515 if (row->used[TEXT_AREA])
5516 expose_area (w, row, r, TEXT_AREA);
5517 if (row->used[RIGHT_MARGIN_AREA])
5518 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5519 x_draw_row_bitmaps (w, row);
5520 }
5521}
dc6f92b8 5522
58769bee 5523
06a2c219
GM
5524/* Return non-zero if W's cursor intersects rectangle R. */
5525
5526static int
5527x_phys_cursor_in_rect_p (w, r)
5528 struct window *w;
5529 XRectangle *r;
5530{
5531 XRectangle cr, result;
5532 struct glyph *cursor_glyph;
5533
5534 cursor_glyph = get_phys_cursor_glyph (w);
5535 if (cursor_glyph)
5536 {
5537 cr.x = w->phys_cursor.x;
5538 cr.y = w->phys_cursor.y;
5539 cr.width = cursor_glyph->pixel_width;
5540 cr.height = w->phys_cursor_height;
5541 return x_intersect_rectangles (&cr, r, &result);
5542 }
5543 else
5544 return 0;
dc6f92b8 5545}
dc6f92b8 5546
06a2c219
GM
5547
5548/* Redraw a rectangle of window W. R is a rectangle in window
5549 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5550
5551static void
06a2c219
GM
5552expose_window (w, r)
5553 struct window *w;
5554 XRectangle *r;
dc6f92b8 5555{
06a2c219
GM
5556 struct glyph_row *row;
5557 int y;
5558 int yb = window_text_bottom_y (w);
5559 int cursor_cleared_p;
dc6f92b8 5560
80c32bcc
GM
5561 /* If window is not yet fully initialized, do nothing. This can
5562 happen when toolkit scroll bars are used and a window is split.
5563 Reconfiguring the scroll bar will generate an expose for a newly
5564 created window. */
5565 if (w->current_matrix == NULL)
5566 return;
5567
06a2c219
GM
5568 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5569 r->x, r->y, r->width, r->height));
dc6f92b8 5570
06a2c219
GM
5571 /* Convert to window coordinates. */
5572 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5573 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5574
06a2c219
GM
5575 /* Turn off the cursor. */
5576 if (!w->pseudo_window_p
5577 && x_phys_cursor_in_rect_p (w, r))
5578 {
5579 x_clear_cursor (w);
5580 cursor_cleared_p = 1;
5581 }
5582 else
5583 cursor_cleared_p = 0;
5584
5585 /* Find the first row intersecting the rectangle R. */
5586 row = w->current_matrix->rows;
5587 y = 0;
5588 while (row->enabled_p
5589 && y < yb
5590 && y + row->height < r->y)
5591 {
5592 y += row->height;
5593 ++row;
5594 }
5595
dc6f92b8 5596 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5597 while (row->enabled_p
5598 && y < yb
5599 && y < r->y + r->height)
5600 {
5601 expose_line (w, row, r);
5602 y += row->height;
5603 ++row;
5604 }
5605
5606 /* Display the mode line if there is one. */
5607 if (WINDOW_WANTS_MODELINE_P (w)
5608 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5609 row->enabled_p)
5610 && row->y < r->y + r->height)
5611 expose_line (w, row, r);
dc6f92b8 5612
06a2c219 5613 if (!w->pseudo_window_p)
dc6f92b8 5614 {
06a2c219
GM
5615 /* Draw border between windows. */
5616 x_draw_vertical_border (w);
5617
5618 /* Turn the cursor on again. */
5619 if (cursor_cleared_p)
5620 x_update_window_cursor (w, 1);
5621 }
5622}
dc6f92b8 5623
dc6f92b8 5624
06a2c219
GM
5625/* Determine the intersection of two rectangles R1 and R2. Return
5626 the intersection in *RESULT. Value is non-zero if RESULT is not
5627 empty. */
5628
5629static int
5630x_intersect_rectangles (r1, r2, result)
5631 XRectangle *r1, *r2, *result;
5632{
5633 XRectangle *left, *right;
5634 XRectangle *upper, *lower;
5635 int intersection_p = 0;
5636
5637 /* Rearrange so that R1 is the left-most rectangle. */
5638 if (r1->x < r2->x)
5639 left = r1, right = r2;
5640 else
5641 left = r2, right = r1;
5642
5643 /* X0 of the intersection is right.x0, if this is inside R1,
5644 otherwise there is no intersection. */
5645 if (right->x <= left->x + left->width)
5646 {
5647 result->x = right->x;
5648
5649 /* The right end of the intersection is the minimum of the
5650 the right ends of left and right. */
5651 result->width = (min (left->x + left->width, right->x + right->width)
5652 - result->x);
5653
5654 /* Same game for Y. */
5655 if (r1->y < r2->y)
5656 upper = r1, lower = r2;
5657 else
5658 upper = r2, lower = r1;
5659
5660 /* The upper end of the intersection is lower.y0, if this is inside
5661 of upper. Otherwise, there is no intersection. */
5662 if (lower->y <= upper->y + upper->height)
dc43ef94 5663 {
06a2c219
GM
5664 result->y = lower->y;
5665
5666 /* The lower end of the intersection is the minimum of the lower
5667 ends of upper and lower. */
5668 result->height = (min (lower->y + lower->height,
5669 upper->y + upper->height)
5670 - result->y);
5671 intersection_p = 1;
dc43ef94 5672 }
dc6f92b8
JB
5673 }
5674
06a2c219 5675 return intersection_p;
dc6f92b8 5676}
06a2c219
GM
5677
5678
5679
5680
dc6f92b8 5681\f
dc6f92b8 5682static void
334208b7
RS
5683frame_highlight (f)
5684 struct frame *f;
dc6f92b8 5685{
b3e1e05c
JB
5686 /* We used to only do this if Vx_no_window_manager was non-nil, but
5687 the ICCCM (section 4.1.6) says that the window's border pixmap
5688 and border pixel are window attributes which are "private to the
5689 client", so we can always change it to whatever we want. */
5690 BLOCK_INPUT;
334208b7 5691 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5692 f->output_data.x->border_pixel);
b3e1e05c 5693 UNBLOCK_INPUT;
5d46f928 5694 x_update_cursor (f, 1);
dc6f92b8
JB
5695}
5696
5697static void
334208b7
RS
5698frame_unhighlight (f)
5699 struct frame *f;
dc6f92b8 5700{
b3e1e05c
JB
5701 /* We used to only do this if Vx_no_window_manager was non-nil, but
5702 the ICCCM (section 4.1.6) says that the window's border pixmap
5703 and border pixel are window attributes which are "private to the
5704 client", so we can always change it to whatever we want. */
5705 BLOCK_INPUT;
334208b7 5706 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5707 f->output_data.x->border_tile);
b3e1e05c 5708 UNBLOCK_INPUT;
5d46f928 5709 x_update_cursor (f, 1);
dc6f92b8 5710}
dc6f92b8 5711
f676886a
JB
5712/* The focus has changed. Update the frames as necessary to reflect
5713 the new situation. Note that we can't change the selected frame
c5acd733 5714 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5715 Each event gets marked with the frame in which it occurred, so the
c5acd733 5716 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5717
6d4238f3 5718static void
0f941935
KH
5719x_new_focus_frame (dpyinfo, frame)
5720 struct x_display_info *dpyinfo;
f676886a 5721 struct frame *frame;
dc6f92b8 5722{
0f941935 5723 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5724
0f941935 5725 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5726 {
58769bee 5727 /* Set this before calling other routines, so that they see
f676886a 5728 the correct value of x_focus_frame. */
0f941935 5729 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5730
5731 if (old_focus && old_focus->auto_lower)
f676886a 5732 x_lower_frame (old_focus);
dc6f92b8
JB
5733
5734#if 0
f676886a 5735 selected_frame = frame;
e0c1aef2
KH
5736 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5737 selected_frame);
f676886a
JB
5738 Fselect_window (selected_frame->selected_window);
5739 choose_minibuf_frame ();
c118dd06 5740#endif /* ! 0 */
dc6f92b8 5741
0f941935
KH
5742 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5743 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5744 else
5745 pending_autoraise_frame = 0;
6d4238f3 5746 }
dc6f92b8 5747
0f941935 5748 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5749}
5750
37c2c98b
RS
5751/* Handle an event saying the mouse has moved out of an Emacs frame. */
5752
5753void
0f941935
KH
5754x_mouse_leave (dpyinfo)
5755 struct x_display_info *dpyinfo;
37c2c98b 5756{
0f941935 5757 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5758}
6d4238f3 5759
f451eb13
JB
5760/* The focus has changed, or we have redirected a frame's focus to
5761 another frame (this happens when a frame uses a surrogate
06a2c219 5762 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5763
5764 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5765 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5766 the appropriate X display info. */
06a2c219 5767
6d4238f3 5768static void
0f941935
KH
5769XTframe_rehighlight (frame)
5770 struct frame *frame;
6d4238f3 5771{
0f941935
KH
5772 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5773}
6d4238f3 5774
0f941935
KH
5775static void
5776x_frame_rehighlight (dpyinfo)
5777 struct x_display_info *dpyinfo;
5778{
5779 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5780
5781 if (dpyinfo->x_focus_frame)
6d4238f3 5782 {
0f941935
KH
5783 dpyinfo->x_highlight_frame
5784 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5785 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5786 : dpyinfo->x_focus_frame);
5787 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5788 {
0f941935
KH
5789 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5790 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5791 }
dc6f92b8 5792 }
6d4238f3 5793 else
0f941935 5794 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5795
0f941935 5796 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5797 {
5798 if (old_highlight)
f676886a 5799 frame_unhighlight (old_highlight);
0f941935
KH
5800 if (dpyinfo->x_highlight_frame)
5801 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5802 }
dc6f92b8 5803}
06a2c219
GM
5804
5805
dc6f92b8 5806\f
06a2c219 5807/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5808
28430d3c
JB
5809/* Initialize mode_switch_bit and modifier_meaning. */
5810static void
334208b7
RS
5811x_find_modifier_meanings (dpyinfo)
5812 struct x_display_info *dpyinfo;
28430d3c 5813{
f689eb05 5814 int min_code, max_code;
28430d3c
JB
5815 KeySym *syms;
5816 int syms_per_code;
5817 XModifierKeymap *mods;
5818
334208b7
RS
5819 dpyinfo->meta_mod_mask = 0;
5820 dpyinfo->shift_lock_mask = 0;
5821 dpyinfo->alt_mod_mask = 0;
5822 dpyinfo->super_mod_mask = 0;
5823 dpyinfo->hyper_mod_mask = 0;
58769bee 5824
9658a521 5825#ifdef HAVE_X11R4
334208b7 5826 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5827#else
4a60f8c5
RS
5828 min_code = dpyinfo->display->min_keycode;
5829 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5830#endif
5831
334208b7 5832 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5833 min_code, max_code - min_code + 1,
5834 &syms_per_code);
334208b7 5835 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5836
58769bee 5837 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5838 Alt keysyms are on. */
28430d3c 5839 {
06a2c219 5840 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5841
5842 for (row = 3; row < 8; row++)
5843 for (col = 0; col < mods->max_keypermod; col++)
5844 {
0299d313
RS
5845 KeyCode code
5846 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5847
af92970c
KH
5848 /* Zeroes are used for filler. Skip them. */
5849 if (code == 0)
5850 continue;
5851
28430d3c
JB
5852 /* Are any of this keycode's keysyms a meta key? */
5853 {
5854 int code_col;
5855
5856 for (code_col = 0; code_col < syms_per_code; code_col++)
5857 {
f689eb05 5858 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5859
f689eb05 5860 switch (sym)
28430d3c 5861 {
f689eb05
JB
5862 case XK_Meta_L:
5863 case XK_Meta_R:
334208b7 5864 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5865 break;
f689eb05
JB
5866
5867 case XK_Alt_L:
5868 case XK_Alt_R:
334208b7 5869 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5870 break;
5871
5872 case XK_Hyper_L:
5873 case XK_Hyper_R:
334208b7 5874 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5875 break;
5876
5877 case XK_Super_L:
5878 case XK_Super_R:
334208b7 5879 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5880 break;
11edeb03
JB
5881
5882 case XK_Shift_Lock:
5883 /* Ignore this if it's not on the lock modifier. */
5884 if ((1 << row) == LockMask)
334208b7 5885 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5886 break;
28430d3c
JB
5887 }
5888 }
5889 }
5890 }
5891 }
5892
f689eb05 5893 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 5894 if (! dpyinfo->meta_mod_mask)
a3c44b14 5895 {
334208b7
RS
5896 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5897 dpyinfo->alt_mod_mask = 0;
a3c44b14 5898 }
f689eb05 5899
148c4b70
RS
5900 /* If some keys are both alt and meta,
5901 make them just meta, not alt. */
334208b7 5902 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 5903 {
334208b7 5904 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 5905 }
58769bee 5906
28430d3c 5907 XFree ((char *) syms);
f689eb05 5908 XFreeModifiermap (mods);
28430d3c
JB
5909}
5910
dfeccd2d
JB
5911/* Convert between the modifier bits X uses and the modifier bits
5912 Emacs uses. */
06a2c219 5913
7c5283e4 5914static unsigned int
334208b7
RS
5915x_x_to_emacs_modifiers (dpyinfo, state)
5916 struct x_display_info *dpyinfo;
dc6f92b8
JB
5917 unsigned int state;
5918{
334208b7
RS
5919 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5920 | ((state & ControlMask) ? ctrl_modifier : 0)
5921 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5922 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5923 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5924 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
5925}
5926
dfeccd2d 5927static unsigned int
334208b7
RS
5928x_emacs_to_x_modifiers (dpyinfo, state)
5929 struct x_display_info *dpyinfo;
dfeccd2d
JB
5930 unsigned int state;
5931{
334208b7
RS
5932 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5933 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5934 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5935 | ((state & shift_modifier) ? ShiftMask : 0)
5936 | ((state & ctrl_modifier) ? ControlMask : 0)
5937 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 5938}
d047c4eb
KH
5939
5940/* Convert a keysym to its name. */
5941
5942char *
5943x_get_keysym_name (keysym)
5944 KeySym keysym;
5945{
5946 char *value;
5947
5948 BLOCK_INPUT;
5949 value = XKeysymToString (keysym);
5950 UNBLOCK_INPUT;
5951
5952 return value;
5953}
06a2c219
GM
5954
5955
e4571a43
JB
5956\f
5957/* Mouse clicks and mouse movement. Rah. */
e4571a43 5958
06a2c219
GM
5959/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5960 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5961 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5962 not force the value into range. */
69388238 5963
c8dba240 5964void
69388238 5965pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 5966 FRAME_PTR f;
69388238 5967 register int pix_x, pix_y;
e4571a43
JB
5968 register int *x, *y;
5969 XRectangle *bounds;
69388238 5970 int noclip;
e4571a43 5971{
06a2c219 5972 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
5973 even for negative values. */
5974 if (pix_x < 0)
7556890b 5975 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 5976 if (pix_y < 0)
7556890b 5977 pix_y -= (f)->output_data.x->line_height - 1;
69388238 5978
e4571a43
JB
5979 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5980 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5981
5982 if (bounds)
5983 {
7556890b
RS
5984 bounds->width = FONT_WIDTH (f->output_data.x->font);
5985 bounds->height = f->output_data.x->line_height;
e4571a43
JB
5986 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5987 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5988 }
5989
69388238
RS
5990 if (!noclip)
5991 {
5992 if (pix_x < 0)
5993 pix_x = 0;
3cbd2e0b
RS
5994 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5995 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
5996
5997 if (pix_y < 0)
5998 pix_y = 0;
5999 else if (pix_y > f->height)
6000 pix_y = f->height;
6001 }
e4571a43
JB
6002
6003 *x = pix_x;
6004 *y = pix_y;
6005}
6006
06a2c219
GM
6007
6008/* Given HPOS/VPOS in the current matrix of W, return corresponding
6009 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6010 can't tell the positions because W's display is not up to date,
6011 return 0. */
6012
6013int
6014glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6015 struct window *w;
6016 int hpos, vpos;
6017 int *frame_x, *frame_y;
2b5c9e71 6018{
06a2c219
GM
6019 int success_p;
6020
6021 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6022 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6023
6024 if (display_completed)
6025 {
6026 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6027 struct glyph *glyph = row->glyphs[TEXT_AREA];
6028 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6029
6030 *frame_y = row->y;
6031 *frame_x = row->x;
6032 while (glyph < end)
6033 {
6034 *frame_x += glyph->pixel_width;
6035 ++glyph;
6036 }
6037
6038 success_p = 1;
6039 }
6040 else
6041 {
6042 *frame_y = *frame_x = 0;
6043 success_p = 0;
6044 }
6045
6046 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6047 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6048 return success_p;
2b5c9e71
RS
6049}
6050
06a2c219 6051
dc6f92b8
JB
6052/* Prepare a mouse-event in *RESULT for placement in the input queue.
6053
6054 If the event is a button press, then note that we have grabbed
f451eb13 6055 the mouse. */
dc6f92b8
JB
6056
6057static Lisp_Object
f451eb13 6058construct_mouse_click (result, event, f)
dc6f92b8
JB
6059 struct input_event *result;
6060 XButtonEvent *event;
f676886a 6061 struct frame *f;
dc6f92b8 6062{
f451eb13 6063 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6064 otherwise. */
f451eb13 6065 result->kind = mouse_click;
69388238 6066 result->code = event->button - Button1;
1113d9db 6067 result->timestamp = event->time;
334208b7
RS
6068 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6069 event->state)
f689eb05 6070 | (event->type == ButtonRelease
58769bee 6071 ? up_modifier
f689eb05 6072 : down_modifier));
dc6f92b8 6073
06a2c219
GM
6074 XSETINT (result->x, event->x);
6075 XSETINT (result->y, event->y);
6076 XSETFRAME (result->frame_or_window, f);
6077 return Qnil;
dc6f92b8 6078}
b849c413 6079
06a2c219
GM
6080#if 0 /* This function isn't called. --gerd */
6081
b849c413
RS
6082/* Prepare a menu-event in *RESULT for placement in the input queue. */
6083
6084static Lisp_Object
6085construct_menu_click (result, event, f)
6086 struct input_event *result;
6087 XButtonEvent *event;
6088 struct frame *f;
6089{
6090 /* Make the event type no_event; we'll change that when we decide
6091 otherwise. */
6092 result->kind = mouse_click;
26459b28 6093 result->code = event->button - Button1;
b849c413 6094 result->timestamp = event->time;
334208b7
RS
6095 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6096 event->state)
b849c413 6097 | (event->type == ButtonRelease
58769bee 6098 ? up_modifier
b849c413
RS
6099 : down_modifier));
6100
e0c1aef2
KH
6101 XSETINT (result->x, event->x);
6102 XSETINT (result->y, -1);
6103 XSETFRAME (result->frame_or_window, f);
b849c413 6104}
06a2c219
GM
6105
6106#endif /* 0 */
6107
69388238 6108\f
90e65f07
JB
6109/* Function to report a mouse movement to the mainstream Emacs code.
6110 The input handler calls this.
6111
6112 We have received a mouse movement event, which is given in *event.
6113 If the mouse is over a different glyph than it was last time, tell
6114 the mainstream emacs code by setting mouse_moved. If not, ask for
6115 another motion event, so we can check again the next time it moves. */
b8009dd1 6116
06a2c219
GM
6117static XMotionEvent last_mouse_motion_event;
6118static Lisp_Object last_mouse_motion_frame;
6119
90e65f07 6120static void
12ba150f 6121note_mouse_movement (frame, event)
f676886a 6122 FRAME_PTR frame;
90e65f07 6123 XMotionEvent *event;
90e65f07 6124{
e5d77022 6125 last_mouse_movement_time = event->time;
06a2c219
GM
6126 last_mouse_motion_event = *event;
6127 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6128
27f338af
RS
6129 if (event->window != FRAME_X_WINDOW (frame))
6130 {
39d8bb4d 6131 frame->mouse_moved = 1;
27f338af 6132 last_mouse_scroll_bar = Qnil;
27f338af 6133 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6134 }
6135
90e65f07 6136 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6137 else if (event->x < last_mouse_glyph.x
6138 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6139 || event->y < last_mouse_glyph.y
6140 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6141 {
39d8bb4d 6142 frame->mouse_moved = 1;
ab648270 6143 last_mouse_scroll_bar = Qnil;
b8009dd1 6144 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6145 }
6146}
6147
bf1c0ba1 6148/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6149
06a2c219
GM
6150 int disable_mouse_highlight;
6151
6152
6153\f
6154/************************************************************************
6155 Mouse Face
6156 ************************************************************************/
6157
6158/* Find the glyph under window-relative coordinates X/Y in window W.
6159 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6160 strings. Return in *HPOS and *VPOS the row and column number of
6161 the glyph found. Return in *AREA the glyph area containing X.
6162 Value is a pointer to the glyph found or null if X/Y is not on
6163 text, or we can't tell because W's current matrix is not up to
6164 date. */
6165
6166static struct glyph *
6167x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6168 struct window *w;
6169 int x, y;
6170 int *hpos, *vpos, *area;
6171{
6172 struct glyph *glyph, *end;
3e71d8f2 6173 struct glyph_row *row = NULL;
06a2c219
GM
6174 int x0, i, left_area_width;
6175
6176 /* Find row containing Y. Give up if some row is not enabled. */
6177 for (i = 0; i < w->current_matrix->nrows; ++i)
6178 {
6179 row = MATRIX_ROW (w->current_matrix, i);
6180 if (!row->enabled_p)
6181 return NULL;
6182 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6183 break;
6184 }
6185
6186 *vpos = i;
6187 *hpos = 0;
6188
6189 /* Give up if Y is not in the window. */
6190 if (i == w->current_matrix->nrows)
6191 return NULL;
6192
6193 /* Get the glyph area containing X. */
6194 if (w->pseudo_window_p)
6195 {
6196 *area = TEXT_AREA;
6197 x0 = 0;
6198 }
6199 else
6200 {
6201 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6202 if (x < left_area_width)
6203 {
6204 *area = LEFT_MARGIN_AREA;
6205 x0 = 0;
6206 }
6207 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6208 {
6209 *area = TEXT_AREA;
6210 x0 = row->x + left_area_width;
6211 }
6212 else
6213 {
6214 *area = RIGHT_MARGIN_AREA;
6215 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6216 }
6217 }
6218
6219 /* Find glyph containing X. */
6220 glyph = row->glyphs[*area];
6221 end = glyph + row->used[*area];
6222 while (glyph < end)
6223 {
6224 if (x < x0 + glyph->pixel_width)
6225 {
6226 if (w->pseudo_window_p)
6227 break;
6228 else if (BUFFERP (glyph->object))
6229 break;
6230 }
6231
6232 x0 += glyph->pixel_width;
6233 ++glyph;
6234 }
6235
6236 if (glyph == end)
6237 return NULL;
6238
6239 *hpos = glyph - row->glyphs[*area];
6240 return glyph;
6241}
6242
6243
6244/* Convert frame-relative x/y to coordinates relative to window W.
6245 Takes pseudo-windows into account. */
6246
6247static void
6248frame_to_window_pixel_xy (w, x, y)
6249 struct window *w;
6250 int *x, *y;
6251{
6252 if (w->pseudo_window_p)
6253 {
6254 /* A pseudo-window is always full-width, and starts at the
6255 left edge of the frame, plus a frame border. */
6256 struct frame *f = XFRAME (w->frame);
6257 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6258 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6259 }
6260 else
6261 {
6262 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6263 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6264 }
6265}
6266
6267
6268/* Take proper action when mouse has moved to the mode or top line of
6269 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6270 mode line. X is relative to the start of the text display area of
6271 W, so the width of bitmap areas and scroll bars must be subtracted
6272 to get a position relative to the start of the mode line. */
6273
6274static void
6275note_mode_line_highlight (w, x, mode_line_p)
6276 struct window *w;
6277 int x, mode_line_p;
6278{
6279 struct frame *f = XFRAME (w->frame);
6280 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6281 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6282 struct glyph_row *row;
6283
6284 if (mode_line_p)
6285 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6286 else
045dee35 6287 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6288
6289 if (row->enabled_p)
6290 {
6291 struct glyph *glyph, *end;
6292 Lisp_Object help, map;
6293 int x0;
6294
6295 /* Find the glyph under X. */
6296 glyph = row->glyphs[TEXT_AREA];
6297 end = glyph + row->used[TEXT_AREA];
6298 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6299 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6300 while (glyph < end
6301 && x >= x0 + glyph->pixel_width)
6302 {
6303 x0 += glyph->pixel_width;
6304 ++glyph;
6305 }
6306
6307 if (glyph < end
6308 && STRINGP (glyph->object)
6309 && XSTRING (glyph->object)->intervals
6310 && glyph->charpos >= 0
6311 && glyph->charpos < XSTRING (glyph->object)->size)
6312 {
6313 /* If we're on a string with `help-echo' text property,
6314 arrange for the help to be displayed. This is done by
6315 setting the global variable help_echo to the help string. */
6316 help = Fget_text_property (make_number (glyph->charpos),
6317 Qhelp_echo, glyph->object);
6318 if (STRINGP (help))
6319 help_echo = help;
6320
6321 /* Change the mouse pointer according to what is under X/Y. */
6322 map = Fget_text_property (make_number (glyph->charpos),
6323 Qlocal_map, glyph->object);
6324 if (!NILP (Fkeymapp (map)))
6325 cursor = f->output_data.x->nontext_cursor;
6326 }
6327 }
6328
6329 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6330}
6331
6332
6333/* Take proper action when the mouse has moved to position X, Y on
6334 frame F as regards highlighting characters that have mouse-face
6335 properties. Also de-highlighting chars where the mouse was before.
27f338af 6336 X and Y can be negative or out of range. */
b8009dd1
RS
6337
6338static void
6339note_mouse_highlight (f, x, y)
06a2c219 6340 struct frame *f;
c32cdd9a 6341 int x, y;
b8009dd1 6342{
06a2c219
GM
6343 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6344 int portion;
b8009dd1
RS
6345 Lisp_Object window;
6346 struct window *w;
6347
06a2c219
GM
6348 /* When a menu is active, don't highlight because this looks odd. */
6349#ifdef USE_X_TOOLKIT
6350 if (popup_activated ())
6351 return;
6352#endif
6353
04fff9c0
GM
6354 if (disable_mouse_highlight
6355 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6356 return;
6357
06a2c219
GM
6358 dpyinfo->mouse_face_mouse_x = x;
6359 dpyinfo->mouse_face_mouse_y = y;
6360 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6361
06a2c219 6362 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6363 return;
6364
514e4681
RS
6365 if (gc_in_progress)
6366 {
06a2c219 6367 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6368 return;
6369 }
6370
b8009dd1 6371 /* Which window is that in? */
06a2c219 6372 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6373
6374 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6375 if (! EQ (window, dpyinfo->mouse_face_window))
6376 clear_mouse_face (dpyinfo);
6377
6378 /* Not on a window -> return. */
6379 if (!WINDOWP (window))
6380 return;
6381
6382 /* Convert to window-relative pixel coordinates. */
6383 w = XWINDOW (window);
6384 frame_to_window_pixel_xy (w, &x, &y);
6385
9ea173e8 6386 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6387 buffer. */
9ea173e8 6388 if (EQ (window, f->tool_bar_window))
06a2c219 6389 {
9ea173e8 6390 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6391 return;
6392 }
6393
6394 if (portion == 1 || portion == 3)
6395 {
6396 /* Mouse is on the mode or top line. */
6397 note_mode_line_highlight (w, x, portion == 1);
6398 return;
6399 }
6400 else
6401 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6402 f->output_data.x->text_cursor);
b8009dd1 6403
0cdd0c9f
RS
6404 /* Are we in a window whose display is up to date?
6405 And verify the buffer's text has not changed. */
06a2c219
GM
6406 if (/* Within text portion of the window. */
6407 portion == 0
0cdd0c9f 6408 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6409 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6410 && (XFASTINT (w->last_overlay_modified)
6411 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6412 {
06a2c219
GM
6413 int hpos, vpos, pos, i, area;
6414 struct glyph *glyph;
b8009dd1 6415
06a2c219
GM
6416 /* Find the glyph under X/Y. */
6417 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6418
6419 /* Clear mouse face if X/Y not over text. */
6420 if (glyph == NULL
6421 || area != TEXT_AREA
6422 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6423 {
06a2c219
GM
6424 clear_mouse_face (dpyinfo);
6425 return;
6426 }
6427
6428 pos = glyph->charpos;
6429 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6430
6431 /* Check for mouse-face and help-echo. */
6432 {
6433 Lisp_Object mouse_face, overlay, position;
6434 Lisp_Object *overlay_vec;
6435 int len, noverlays;
6436 struct buffer *obuf;
6437 int obegv, ozv;
6438
6439 /* If we get an out-of-range value, return now; avoid an error. */
6440 if (pos > BUF_Z (XBUFFER (w->buffer)))
6441 return;
6442
6443 /* Make the window's buffer temporarily current for
6444 overlays_at and compute_char_face. */
6445 obuf = current_buffer;
6446 current_buffer = XBUFFER (w->buffer);
6447 obegv = BEGV;
6448 ozv = ZV;
6449 BEGV = BEG;
6450 ZV = Z;
6451
6452 /* Is this char mouse-active or does it have help-echo? */
6453 XSETINT (position, pos);
6454
6455 /* Put all the overlays we want in a vector in overlay_vec.
6456 Store the length in len. If there are more than 10, make
6457 enough space for all, and try again. */
6458 len = 10;
6459 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6460 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6461 if (noverlays > len)
6462 {
6463 len = noverlays;
6464 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6465 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6466 }
6467
6468 noverlays = sort_overlays (overlay_vec, noverlays, w);
6469
6470 /* Check mouse-face highlighting. */
6471 if (! (EQ (window, dpyinfo->mouse_face_window)
6472 && vpos >= dpyinfo->mouse_face_beg_row
6473 && vpos <= dpyinfo->mouse_face_end_row
6474 && (vpos > dpyinfo->mouse_face_beg_row
6475 || hpos >= dpyinfo->mouse_face_beg_col)
6476 && (vpos < dpyinfo->mouse_face_end_row
6477 || hpos < dpyinfo->mouse_face_end_col
6478 || dpyinfo->mouse_face_past_end)))
6479 {
6480 /* Clear the display of the old active region, if any. */
6481 clear_mouse_face (dpyinfo);
6482
6483 /* Find the highest priority overlay that has a mouse-face prop. */
6484 overlay = Qnil;
6485 for (i = 0; i < noverlays; i++)
6486 {
6487 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6488 if (!NILP (mouse_face))
6489 {
6490 overlay = overlay_vec[i];
6491 break;
6492 }
6493 }
6494
6495 /* If no overlay applies, get a text property. */
6496 if (NILP (overlay))
6497 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6498
6499 /* Handle the overlay case. */
6500 if (! NILP (overlay))
6501 {
6502 /* Find the range of text around this char that
6503 should be active. */
6504 Lisp_Object before, after;
6505 int ignore;
6506
6507 before = Foverlay_start (overlay);
6508 after = Foverlay_end (overlay);
6509 /* Record this as the current active region. */
6510 fast_find_position (w, XFASTINT (before),
6511 &dpyinfo->mouse_face_beg_col,
6512 &dpyinfo->mouse_face_beg_row,
6513 &dpyinfo->mouse_face_beg_x,
6514 &dpyinfo->mouse_face_beg_y);
6515 dpyinfo->mouse_face_past_end
6516 = !fast_find_position (w, XFASTINT (after),
6517 &dpyinfo->mouse_face_end_col,
6518 &dpyinfo->mouse_face_end_row,
6519 &dpyinfo->mouse_face_end_x,
6520 &dpyinfo->mouse_face_end_y);
6521 dpyinfo->mouse_face_window = window;
6522 dpyinfo->mouse_face_face_id
6523 = face_at_buffer_position (w, pos, 0, 0,
6524 &ignore, pos + 1, 1);
6525
6526 /* Display it as active. */
6527 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6528 }
6529 /* Handle the text property case. */
6530 else if (! NILP (mouse_face))
6531 {
6532 /* Find the range of text around this char that
6533 should be active. */
6534 Lisp_Object before, after, beginning, end;
6535 int ignore;
6536
6537 beginning = Fmarker_position (w->start);
6538 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6539 - XFASTINT (w->window_end_pos)));
6540 before
6541 = Fprevious_single_property_change (make_number (pos + 1),
6542 Qmouse_face,
6543 w->buffer, beginning);
6544 after
6545 = Fnext_single_property_change (position, Qmouse_face,
6546 w->buffer, end);
6547 /* Record this as the current active region. */
6548 fast_find_position (w, XFASTINT (before),
6549 &dpyinfo->mouse_face_beg_col,
6550 &dpyinfo->mouse_face_beg_row,
6551 &dpyinfo->mouse_face_beg_x,
6552 &dpyinfo->mouse_face_beg_y);
6553 dpyinfo->mouse_face_past_end
6554 = !fast_find_position (w, XFASTINT (after),
6555 &dpyinfo->mouse_face_end_col,
6556 &dpyinfo->mouse_face_end_row,
6557 &dpyinfo->mouse_face_end_x,
6558 &dpyinfo->mouse_face_end_y);
6559 dpyinfo->mouse_face_window = window;
6560 dpyinfo->mouse_face_face_id
6561 = face_at_buffer_position (w, pos, 0, 0,
6562 &ignore, pos + 1, 1);
6563
6564 /* Display it as active. */
6565 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6566 }
6567 }
6568
6569 /* Look for a `help-echo' property. */
6570 {
6571 Lisp_Object help;
6572
6573 /* Check overlays first. */
6574 help = Qnil;
6575 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6576 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6577
6578 /* Try text properties. */
6579 if (!STRINGP (help)
6580 && ((STRINGP (glyph->object)
6581 && glyph->charpos >= 0
6582 && glyph->charpos < XSTRING (glyph->object)->size)
6583 || (BUFFERP (glyph->object)
6584 && glyph->charpos >= BEGV
6585 && glyph->charpos < ZV)))
6586 help = Fget_text_property (make_number (glyph->charpos),
6587 Qhelp_echo, glyph->object);
6588
6589 if (STRINGP (help))
6590 help_echo = help;
6591 }
6592
6593 BEGV = obegv;
6594 ZV = ozv;
6595 current_buffer = obuf;
6596 }
6597 }
6598}
6599
6600static void
6601redo_mouse_highlight ()
6602{
6603 if (!NILP (last_mouse_motion_frame)
6604 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6605 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6606 last_mouse_motion_event.x,
6607 last_mouse_motion_event.y);
6608}
6609
6610
6611\f
6612/***********************************************************************
9ea173e8 6613 Tool-bars
06a2c219
GM
6614 ***********************************************************************/
6615
9ea173e8
GM
6616static int x_tool_bar_item P_ ((struct frame *, int, int,
6617 struct glyph **, int *, int *, int *));
06a2c219 6618
9ea173e8 6619/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6620 or -1. */
6621
9ea173e8 6622static int last_tool_bar_item;
06a2c219
GM
6623
6624
9ea173e8
GM
6625/* Get information about the tool-bar item at position X/Y on frame F.
6626 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6627 the current matrix of the tool-bar window of F, or NULL if not
6628 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6629 item in F->current_tool_bar_items. Value is
06a2c219 6630
9ea173e8 6631 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6632 0 if X/Y is on the same item that was highlighted before.
6633 1 otherwise. */
6634
6635static int
9ea173e8 6636x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6637 struct frame *f;
6638 int x, y;
6639 struct glyph **glyph;
6640 int *hpos, *vpos, *prop_idx;
6641{
6642 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6643 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6644 int area;
6645
6646 /* Find the glyph under X/Y. */
6647 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6648 if (*glyph == NULL)
6649 return -1;
6650
9ea173e8
GM
6651 /* Get the start of this tool-bar item's properties in
6652 f->current_tool_bar_items. */
6653 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6654 return -1;
6655
6656 /* Is mouse on the highlighted item? */
9ea173e8 6657 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6658 && *vpos >= dpyinfo->mouse_face_beg_row
6659 && *vpos <= dpyinfo->mouse_face_end_row
6660 && (*vpos > dpyinfo->mouse_face_beg_row
6661 || *hpos >= dpyinfo->mouse_face_beg_col)
6662 && (*vpos < dpyinfo->mouse_face_end_row
6663 || *hpos < dpyinfo->mouse_face_end_col
6664 || dpyinfo->mouse_face_past_end))
6665 return 0;
6666
6667 return 1;
6668}
6669
6670
9ea173e8 6671/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6672 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6673 or ButtonRelase. */
6674
6675static void
9ea173e8 6676x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6677 struct frame *f;
6678 XButtonEvent *button_event;
6679{
6680 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6681 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6682 int hpos, vpos, prop_idx;
6683 struct glyph *glyph;
6684 Lisp_Object enabled_p;
6685 int x = button_event->x;
6686 int y = button_event->y;
6687
9ea173e8 6688 /* If not on the highlighted tool-bar item, return. */
06a2c219 6689 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6690 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6691 return;
6692
6693 /* If item is disabled, do nothing. */
9ea173e8
GM
6694 enabled_p = (XVECTOR (f->current_tool_bar_items)
6695 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6696 if (NILP (enabled_p))
6697 return;
6698
6699 if (button_event->type == ButtonPress)
6700 {
6701 /* Show item in pressed state. */
6702 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6703 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6704 last_tool_bar_item = prop_idx;
06a2c219
GM
6705 }
6706 else
6707 {
6708 Lisp_Object key, frame;
6709 struct input_event event;
6710
6711 /* Show item in released state. */
6712 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6713 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6714
9ea173e8
GM
6715 key = (XVECTOR (f->current_tool_bar_items)
6716 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
6717
6718 XSETFRAME (frame, f);
9ea173e8
GM
6719 event.kind = TOOL_BAR_EVENT;
6720 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
06a2c219
GM
6721 kbd_buffer_store_event (&event);
6722
9ea173e8 6723 event.kind = TOOL_BAR_EVENT;
06a2c219
GM
6724 event.frame_or_window = Fcons (frame, key);
6725 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6726 button_event->state);
6727 kbd_buffer_store_event (&event);
9ea173e8 6728 last_tool_bar_item = -1;
06a2c219
GM
6729 }
6730}
6731
6732
9ea173e8
GM
6733/* Possibly highlight a tool-bar item on frame F when mouse moves to
6734 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6735 note_mouse_highlight. */
6736
6737static void
9ea173e8 6738note_tool_bar_highlight (f, x, y)
06a2c219
GM
6739 struct frame *f;
6740 int x, y;
6741{
9ea173e8 6742 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
6743 struct window *w = XWINDOW (window);
6744 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6745 int hpos, vpos;
6746 struct glyph *glyph;
6747 struct glyph_row *row;
5c187dee 6748 int i;
06a2c219
GM
6749 Lisp_Object enabled_p;
6750 int prop_idx;
6751 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 6752 int mouse_down_p, rc;
06a2c219
GM
6753
6754 /* Function note_mouse_highlight is called with negative x(y
6755 values when mouse moves outside of the frame. */
6756 if (x <= 0 || y <= 0)
6757 {
6758 clear_mouse_face (dpyinfo);
6759 return;
6760 }
6761
9ea173e8 6762 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
6763 if (rc < 0)
6764 {
9ea173e8 6765 /* Not on tool-bar item. */
06a2c219
GM
6766 clear_mouse_face (dpyinfo);
6767 return;
6768 }
6769 else if (rc == 0)
9ea173e8 6770 /* On same tool-bar item as before. */
06a2c219 6771 goto set_help_echo;
b8009dd1 6772
06a2c219
GM
6773 clear_mouse_face (dpyinfo);
6774
9ea173e8 6775 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
6776 mouse_down_p = (dpyinfo->grabbed
6777 && f == last_mouse_frame
6778 && FRAME_LIVE_P (f));
6779 if (mouse_down_p
9ea173e8 6780 && last_tool_bar_item != prop_idx)
06a2c219
GM
6781 return;
6782
6783 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6784 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6785
9ea173e8
GM
6786 /* If tool-bar item is not enabled, don't highlight it. */
6787 enabled_p = (XVECTOR (f->current_tool_bar_items)
6788 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6789 if (!NILP (enabled_p))
6790 {
6791 /* Compute the x-position of the glyph. In front and past the
6792 image is a space. We include this is the highlighted area. */
6793 row = MATRIX_ROW (w->current_matrix, vpos);
6794 for (i = x = 0; i < hpos; ++i)
6795 x += row->glyphs[TEXT_AREA][i].pixel_width;
6796
6797 /* Record this as the current active region. */
6798 dpyinfo->mouse_face_beg_col = hpos;
6799 dpyinfo->mouse_face_beg_row = vpos;
6800 dpyinfo->mouse_face_beg_x = x;
6801 dpyinfo->mouse_face_beg_y = row->y;
6802 dpyinfo->mouse_face_past_end = 0;
6803
6804 dpyinfo->mouse_face_end_col = hpos + 1;
6805 dpyinfo->mouse_face_end_row = vpos;
6806 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6807 dpyinfo->mouse_face_end_y = row->y;
6808 dpyinfo->mouse_face_window = window;
9ea173e8 6809 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
6810
6811 /* Display it as active. */
6812 show_mouse_face (dpyinfo, draw);
6813 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6814 }
06a2c219
GM
6815
6816 set_help_echo:
6817
9ea173e8 6818 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 6819 XTread_socket does the rest. */
9ea173e8
GM
6820 help_echo = (XVECTOR (f->current_tool_bar_items)
6821 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
06a2c219 6822 if (!STRINGP (help_echo))
9ea173e8
GM
6823 help_echo = (XVECTOR (f->current_tool_bar_items)
6824 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 6825}
4d73d038 6826
06a2c219
GM
6827
6828\f
6829/* Find the glyph matrix position of buffer position POS in window W.
6830 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6831 current glyphs must be up to date. If POS is above window start
6832 return (0, 0, 0, 0). If POS is after end of W, return end of
6833 last line in W. */
b8009dd1
RS
6834
6835static int
06a2c219
GM
6836fast_find_position (w, pos, hpos, vpos, x, y)
6837 struct window *w;
b8009dd1 6838 int pos;
06a2c219 6839 int *hpos, *vpos, *x, *y;
b8009dd1 6840{
b8009dd1 6841 int i;
bf1c0ba1 6842 int lastcol;
06a2c219
GM
6843 int maybe_next_line_p = 0;
6844 int line_start_position;
6845 int yb = window_text_bottom_y (w);
6846 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6847 struct glyph_row *best_row = row;
6848 int row_vpos = 0, best_row_vpos = 0;
6849 int current_x;
6850
6851 while (row->y < yb)
b8009dd1 6852 {
06a2c219
GM
6853 if (row->used[TEXT_AREA])
6854 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6855 else
6856 line_start_position = 0;
6857
6858 if (line_start_position > pos)
b8009dd1 6859 break;
77b68646
RS
6860 /* If the position sought is the end of the buffer,
6861 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6862 else if (line_start_position == pos
6863 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6864 {
06a2c219 6865 maybe_next_line_p = 1;
77b68646
RS
6866 break;
6867 }
06a2c219
GM
6868 else if (line_start_position > 0)
6869 {
6870 best_row = row;
6871 best_row_vpos = row_vpos;
6872 }
4b0bb6f3
GM
6873
6874 if (row->y + row->height >= yb)
6875 break;
06a2c219
GM
6876
6877 ++row;
6878 ++row_vpos;
b8009dd1 6879 }
06a2c219
GM
6880
6881 /* Find the right column within BEST_ROW. */
6882 lastcol = 0;
6883 current_x = best_row->x;
6884 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 6885 {
06a2c219
GM
6886 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6887 int charpos;
6888
6889 charpos = glyph->charpos;
6890 if (charpos == pos)
bf1c0ba1 6891 {
06a2c219
GM
6892 *hpos = i;
6893 *vpos = best_row_vpos;
6894 *x = current_x;
6895 *y = best_row->y;
bf1c0ba1
RS
6896 return 1;
6897 }
06a2c219 6898 else if (charpos > pos)
4d73d038 6899 break;
06a2c219
GM
6900 else if (charpos > 0)
6901 lastcol = i;
6902
6903 current_x += glyph->pixel_width;
bf1c0ba1 6904 }
b8009dd1 6905
77b68646
RS
6906 /* If we're looking for the end of the buffer,
6907 and we didn't find it in the line we scanned,
6908 use the start of the following line. */
06a2c219 6909 if (maybe_next_line_p)
77b68646 6910 {
06a2c219
GM
6911 ++best_row;
6912 ++best_row_vpos;
6913 lastcol = 0;
6914 current_x = best_row->x;
77b68646
RS
6915 }
6916
06a2c219
GM
6917 *vpos = best_row_vpos;
6918 *hpos = lastcol + 1;
6919 *x = current_x;
6920 *y = best_row->y;
b8009dd1
RS
6921 return 0;
6922}
6923
06a2c219 6924
b8009dd1
RS
6925/* Display the active region described by mouse_face_*
6926 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6927
6928static void
06a2c219 6929show_mouse_face (dpyinfo, draw)
7a13e894 6930 struct x_display_info *dpyinfo;
06a2c219 6931 enum draw_glyphs_face draw;
b8009dd1 6932{
7a13e894 6933 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 6934 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 6935 int i;
06a2c219
GM
6936 int cursor_off_p = 0;
6937 struct cursor_pos saved_cursor;
6938
6939 saved_cursor = output_cursor;
6940
6941 /* If window is in the process of being destroyed, don't bother
6942 to do anything. */
6943 if (w->current_matrix == NULL)
6944 goto set_x_cursor;
6945
6946 /* Recognize when we are called to operate on rows that don't exist
6947 anymore. This can happen when a window is split. */
6948 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6949 goto set_x_cursor;
6950
6951 set_output_cursor (&w->phys_cursor);
6952
6953 /* Note that mouse_face_beg_row etc. are window relative. */
6954 for (i = dpyinfo->mouse_face_beg_row;
6955 i <= dpyinfo->mouse_face_end_row;
6956 i++)
6957 {
6958 int start_hpos, end_hpos, start_x;
6959 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6960
6961 /* Don't do anything if row doesn't have valid contents. */
6962 if (!row->enabled_p)
6963 continue;
6964
6965 /* For all but the first row, the highlight starts at column 0. */
6966 if (i == dpyinfo->mouse_face_beg_row)
6967 {
6968 start_hpos = dpyinfo->mouse_face_beg_col;
6969 start_x = dpyinfo->mouse_face_beg_x;
6970 }
6971 else
6972 {
6973 start_hpos = 0;
6974 start_x = 0;
6975 }
6976
6977 if (i == dpyinfo->mouse_face_end_row)
6978 end_hpos = dpyinfo->mouse_face_end_col;
6979 else
6980 end_hpos = row->used[TEXT_AREA];
6981
6982 /* If the cursor's in the text we are about to rewrite, turn the
6983 cursor off. */
6984 if (!w->pseudo_window_p
6985 && i == output_cursor.vpos
6986 && output_cursor.hpos >= start_hpos - 1
6987 && output_cursor.hpos <= end_hpos)
514e4681 6988 {
06a2c219
GM
6989 x_update_window_cursor (w, 0);
6990 cursor_off_p = 1;
514e4681 6991 }
b8009dd1 6992
06a2c219 6993 if (end_hpos > start_hpos)
54a91a0f 6994 x_draw_glyphs (w, start_x, row, TEXT_AREA,
66ac4b0e 6995 start_hpos, end_hpos, draw, NULL, NULL, 0);
b8009dd1
RS
6996 }
6997
514e4681 6998 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
6999 if (cursor_off_p)
7000 x_display_cursor (w, 1,
7001 output_cursor.hpos, output_cursor.vpos,
7002 output_cursor.x, output_cursor.y);
2729a2b5 7003
06a2c219 7004 output_cursor = saved_cursor;
fb3b7de5 7005
06a2c219
GM
7006 set_x_cursor:
7007
7008 /* Change the mouse cursor. */
7009 if (draw == DRAW_NORMAL_TEXT)
7010 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7011 f->output_data.x->text_cursor);
7012 else if (draw == DRAW_MOUSE_FACE)
334208b7 7013 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7014 f->output_data.x->cross_cursor);
27ead1d5 7015 else
334208b7 7016 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7017 f->output_data.x->nontext_cursor);
b8009dd1
RS
7018}
7019
7020/* Clear out the mouse-highlighted active region.
06a2c219 7021 Redraw it un-highlighted first. */
b8009dd1 7022
06a2c219 7023void
7a13e894
RS
7024clear_mouse_face (dpyinfo)
7025 struct x_display_info *dpyinfo;
b8009dd1 7026{
06a2c219
GM
7027 if (tip_frame)
7028 return;
7029
7a13e894 7030 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7031 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7032
7a13e894
RS
7033 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7034 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7035 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7036}
e687d06e
RS
7037
7038/* Just discard the mouse face information for frame F, if any.
7039 This is used when the size of F is changed. */
7040
dfcf069d 7041void
e687d06e
RS
7042cancel_mouse_face (f)
7043 FRAME_PTR f;
7044{
7045 Lisp_Object window;
7046 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7047
7048 window = dpyinfo->mouse_face_window;
7049 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7050 {
7051 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7052 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7053 dpyinfo->mouse_face_window = Qnil;
7054 }
7055}
b8009dd1 7056\f
ab648270
JB
7057static struct scroll_bar *x_window_to_scroll_bar ();
7058static void x_scroll_bar_report_motion ();
12ba150f 7059
90e65f07 7060/* Return the current position of the mouse.
2d7fc7e8 7061 *fp should be a frame which indicates which display to ask about.
90e65f07 7062
2d7fc7e8 7063 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7064 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7065 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7066 position on the scroll bar.
12ba150f 7067
2d7fc7e8 7068 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7069 mouse is on, *bar_window to nil, and *x and *y to the character cell
7070 the mouse is over.
7071
06a2c219 7072 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7073 was at this position.
7074
a135645a
RS
7075 Don't store anything if we don't have a valid set of values to report.
7076
90e65f07 7077 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7078 movement. */
90e65f07
JB
7079
7080static void
1cf412ec 7081XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7082 FRAME_PTR *fp;
1cf412ec 7083 int insist;
12ba150f 7084 Lisp_Object *bar_window;
ab648270 7085 enum scroll_bar_part *part;
90e65f07 7086 Lisp_Object *x, *y;
e5d77022 7087 unsigned long *time;
90e65f07 7088{
a135645a
RS
7089 FRAME_PTR f1;
7090
90e65f07
JB
7091 BLOCK_INPUT;
7092
8bcee03e 7093 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7094 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7095 else
7096 {
12ba150f
JB
7097 Window root;
7098 int root_x, root_y;
90e65f07 7099
12ba150f
JB
7100 Window dummy_window;
7101 int dummy;
7102
39d8bb4d
KH
7103 Lisp_Object frame, tail;
7104
7105 /* Clear the mouse-moved flag for every frame on this display. */
7106 FOR_EACH_FRAME (tail, frame)
7107 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7108 XFRAME (frame)->mouse_moved = 0;
7109
ab648270 7110 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7111
7112 /* Figure out which root window we're on. */
334208b7
RS
7113 XQueryPointer (FRAME_X_DISPLAY (*fp),
7114 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7115
7116 /* The root window which contains the pointer. */
7117 &root,
7118
7119 /* Trash which we can't trust if the pointer is on
7120 a different screen. */
7121 &dummy_window,
7122
7123 /* The position on that root window. */
58769bee 7124 &root_x, &root_y,
12ba150f
JB
7125
7126 /* More trash we can't trust. */
7127 &dummy, &dummy,
7128
7129 /* Modifier keys and pointer buttons, about which
7130 we don't care. */
7131 (unsigned int *) &dummy);
7132
7133 /* Now we have a position on the root; find the innermost window
7134 containing the pointer. */
7135 {
7136 Window win, child;
7137 int win_x, win_y;
06a2c219 7138 int parent_x = 0, parent_y = 0;
e99db5a1 7139 int count;
12ba150f
JB
7140
7141 win = root;
69388238 7142
2d7fc7e8
RS
7143 /* XTranslateCoordinates can get errors if the window
7144 structure is changing at the same time this function
7145 is running. So at least we must not crash from them. */
7146
e99db5a1 7147 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7148
334208b7 7149 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7150 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7151 {
69388238
RS
7152 /* If mouse was grabbed on a frame, give coords for that frame
7153 even if the mouse is now outside it. */
334208b7 7154 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7155
12ba150f 7156 /* From-window, to-window. */
69388238 7157 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7158
7159 /* From-position, to-position. */
7160 root_x, root_y, &win_x, &win_y,
7161
7162 /* Child of win. */
7163 &child);
69388238
RS
7164 f1 = last_mouse_frame;
7165 }
7166 else
7167 {
7168 while (1)
7169 {
334208b7 7170 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7171
69388238
RS
7172 /* From-window, to-window. */
7173 root, win,
12ba150f 7174
69388238
RS
7175 /* From-position, to-position. */
7176 root_x, root_y, &win_x, &win_y,
7177
7178 /* Child of win. */
7179 &child);
7180
9af3143a 7181 if (child == None || child == win)
69388238
RS
7182 break;
7183
7184 win = child;
7185 parent_x = win_x;
7186 parent_y = win_y;
7187 }
12ba150f 7188
69388238
RS
7189 /* Now we know that:
7190 win is the innermost window containing the pointer
7191 (XTC says it has no child containing the pointer),
7192 win_x and win_y are the pointer's position in it
7193 (XTC did this the last time through), and
7194 parent_x and parent_y are the pointer's position in win's parent.
7195 (They are what win_x and win_y were when win was child.
7196 If win is the root window, it has no parent, and
7197 parent_{x,y} are invalid, but that's okay, because we'll
7198 never use them in that case.) */
7199
7200 /* Is win one of our frames? */
19126e11 7201 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7202 }
58769bee 7203
2d7fc7e8
RS
7204 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7205 f1 = 0;
7206
e99db5a1 7207 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7208
ab648270 7209 /* If not, is it one of our scroll bars? */
a135645a 7210 if (! f1)
12ba150f 7211 {
ab648270 7212 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7213
7214 if (bar)
7215 {
a135645a 7216 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7217 win_x = parent_x;
7218 win_y = parent_y;
7219 }
7220 }
90e65f07 7221
8bcee03e 7222 if (f1 == 0 && insist > 0)
b86bd3dd 7223 f1 = SELECTED_FRAME ();
1cf412ec 7224
a135645a 7225 if (f1)
12ba150f 7226 {
06a2c219
GM
7227 /* Ok, we found a frame. Store all the values.
7228 last_mouse_glyph is a rectangle used to reduce the
7229 generation of mouse events. To not miss any motion
7230 events, we must divide the frame into rectangles of the
7231 size of the smallest character that could be displayed
7232 on it, i.e. into the same rectangles that matrices on
7233 the frame are divided into. */
7234
7235#if OLD_REDISPLAY_CODE
2b5c9e71 7236 int ignore1, ignore2;
2b5c9e71 7237 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7238 &last_mouse_glyph,
1cf412ec
RS
7239 FRAME_X_DISPLAY_INFO (f1)->grabbed
7240 || insist);
06a2c219
GM
7241#else
7242 {
7243 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7244 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7245 int x = win_x;
7246 int y = win_y;
7247
7248 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7249 round down even for negative values. */
7250 if (x < 0)
7251 x -= width - 1;
7252 if (y < 0)
7253 y -= height - 1;
7254
7255 last_mouse_glyph.width = width;
7256 last_mouse_glyph.height = height;
7257 last_mouse_glyph.x = (x + width - 1) / width * width;
7258 last_mouse_glyph.y = (y + height - 1) / height * height;
7259 }
7260#endif
12ba150f
JB
7261
7262 *bar_window = Qnil;
7263 *part = 0;
334208b7 7264 *fp = f1;
e0c1aef2
KH
7265 XSETINT (*x, win_x);
7266 XSETINT (*y, win_y);
12ba150f
JB
7267 *time = last_mouse_movement_time;
7268 }
7269 }
7270 }
90e65f07
JB
7271
7272 UNBLOCK_INPUT;
7273}
f451eb13 7274
06a2c219 7275
06a2c219 7276#ifdef USE_X_TOOLKIT
bffcfca9
GM
7277
7278/* Atimer callback function for TIMER. Called every 0.1s to process
7279 Xt timeouts, if needed. We must avoid calling XtAppPending as
7280 much as possible because that function does an implicit XFlush
7281 that slows us down. */
7282
7283static void
7284x_process_timeouts (timer)
7285 struct atimer *timer;
7286{
7287 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7288 {
7289 BLOCK_INPUT;
7290 while (XtAppPending (Xt_app_con) & XtIMTimer)
7291 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7292 UNBLOCK_INPUT;
7293 }
06a2c219
GM
7294}
7295
bffcfca9 7296#endif /* USE_X_TOOLKIT */
06a2c219
GM
7297
7298\f
7299/* Scroll bar support. */
7300
7301/* Given an X window ID, find the struct scroll_bar which manages it.
7302 This can be called in GC, so we have to make sure to strip off mark
7303 bits. */
bffcfca9 7304
06a2c219
GM
7305static struct scroll_bar *
7306x_window_to_scroll_bar (window_id)
7307 Window window_id;
7308{
7309 Lisp_Object tail;
7310
7311 for (tail = Vframe_list;
7312 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7313 tail = XCDR (tail))
06a2c219
GM
7314 {
7315 Lisp_Object frame, bar, condemned;
7316
8e713be6 7317 frame = XCAR (tail);
06a2c219
GM
7318 /* All elements of Vframe_list should be frames. */
7319 if (! GC_FRAMEP (frame))
7320 abort ();
7321
7322 /* Scan this frame's scroll bar list for a scroll bar with the
7323 right window ID. */
7324 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7325 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7326 /* This trick allows us to search both the ordinary and
7327 condemned scroll bar lists with one loop. */
7328 ! GC_NILP (bar) || (bar = condemned,
7329 condemned = Qnil,
7330 ! GC_NILP (bar));
7331 bar = XSCROLL_BAR (bar)->next)
7332 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7333 return XSCROLL_BAR (bar);
7334 }
7335
7336 return 0;
7337}
7338
7339
7340\f
7341/************************************************************************
7342 Toolkit scroll bars
7343 ************************************************************************/
7344
7345#if USE_TOOLKIT_SCROLL_BARS
7346
7347static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7348static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7349static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7350 struct scroll_bar *));
7351static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7352 int, int, int));
7353
7354
7355/* Id of action hook installed for scroll bars. */
7356
7357static XtActionHookId action_hook_id;
7358
7359/* Lisp window being scrolled. Set when starting to interact with
7360 a toolkit scroll bar, reset to nil when ending the interaction. */
7361
7362static Lisp_Object window_being_scrolled;
7363
7364/* Last scroll bar part sent in xm_scroll_callback. */
7365
7366static int last_scroll_bar_part;
7367
ec18280f
SM
7368/* Whether this is an Xaw with arrow-scrollbars. This should imply
7369 that movements of 1/20 of the screen size are mapped to up/down. */
7370
7371static Boolean xaw3d_arrow_scroll;
7372
7373/* Whether the drag scrolling maintains the mouse at the top of the
7374 thumb. If not, resizing the thumb needs to be done more carefully
7375 to avoid jerkyness. */
7376
7377static Boolean xaw3d_pick_top;
7378
06a2c219
GM
7379
7380/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7381 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7382 the user ends an interaction with the scroll bar, and generates
7383 a `end-scroll' scroll_bar_click' event if so. */
7384
7385static void
7386xt_action_hook (widget, client_data, action_name, event, params,
7387 num_params)
7388 Widget widget;
7389 XtPointer client_data;
7390 String action_name;
7391 XEvent *event;
7392 String *params;
7393 Cardinal *num_params;
7394{
7395 int scroll_bar_p;
7396 char *end_action;
7397
7398#ifdef USE_MOTIF
7399 scroll_bar_p = XmIsScrollBar (widget);
7400 end_action = "Release";
ec18280f 7401#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7402 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7403 end_action = "EndScroll";
ec18280f 7404#endif /* USE_MOTIF */
06a2c219 7405
06a2c219
GM
7406 if (scroll_bar_p
7407 && strcmp (action_name, end_action) == 0
7408 && WINDOWP (window_being_scrolled))
7409 {
7410 struct window *w;
7411
7412 x_send_scroll_bar_event (window_being_scrolled,
7413 scroll_bar_end_scroll, 0, 0);
7414 w = XWINDOW (window_being_scrolled);
7415 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7416 window_being_scrolled = Qnil;
7417 last_scroll_bar_part = -1;
bffcfca9
GM
7418
7419 /* Xt timeouts no longer needed. */
7420 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7421 }
7422}
7423
7424
7425/* Send a client message with message type Xatom_Scrollbar for a
7426 scroll action to the frame of WINDOW. PART is a value identifying
7427 the part of the scroll bar that was clicked on. PORTION is the
7428 amount to scroll of a whole of WHOLE. */
7429
7430static void
7431x_send_scroll_bar_event (window, part, portion, whole)
7432 Lisp_Object window;
7433 int part, portion, whole;
7434{
7435 XEvent event;
7436 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7437 struct frame *f = XFRAME (XWINDOW (window)->frame);
7438
7439 /* Construct a ClientMessage event to send to the frame. */
7440 ev->type = ClientMessage;
7441 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7442 ev->display = FRAME_X_DISPLAY (f);
7443 ev->window = FRAME_X_WINDOW (f);
7444 ev->format = 32;
52e386c2 7445 ev->data.l[0] = (long) XFASTINT (window);
06a2c219
GM
7446 ev->data.l[1] = (long) part;
7447 ev->data.l[2] = (long) 0;
7448 ev->data.l[3] = (long) portion;
7449 ev->data.l[4] = (long) whole;
7450
bffcfca9
GM
7451 /* Make Xt timeouts work while the scroll bar is active. */
7452 toolkit_scroll_bar_interaction = 1;
7453
06a2c219
GM
7454 /* Setting the event mask to zero means that the message will
7455 be sent to the client that created the window, and if that
7456 window no longer exists, no event will be sent. */
7457 BLOCK_INPUT;
7458 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7459 UNBLOCK_INPUT;
7460}
7461
7462
7463/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7464 in *IEVENT. */
7465
7466static void
7467x_scroll_bar_to_input_event (event, ievent)
7468 XEvent *event;
7469 struct input_event *ievent;
7470{
7471 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7472 Lisp_Object window;
7473 struct frame *f;
7474
7475 XSETFASTINT (window, ev->data.l[0]);
7476 f = XFRAME (XWINDOW (window)->frame);
06a2c219
GM
7477
7478 ievent->kind = scroll_bar_click;
7479 ievent->frame_or_window = window;
7480 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7481 ievent->part = ev->data.l[1];
7482 ievent->code = ev->data.l[2];
7483 ievent->x = make_number ((int) ev->data.l[3]);
7484 ievent->y = make_number ((int) ev->data.l[4]);
7485 ievent->modifiers = 0;
7486}
7487
7488
7489#ifdef USE_MOTIF
7490
7491/* Minimum and maximum values used for Motif scroll bars. */
7492
7493#define XM_SB_MIN 1
7494#define XM_SB_MAX 10000000
7495#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7496
7497
7498/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7499 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7500 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7501
7502static void
7503xm_scroll_callback (widget, client_data, call_data)
7504 Widget widget;
7505 XtPointer client_data, call_data;
7506{
7507 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7508 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7509 double percent;
7510 int part = -1, whole = 0, portion = 0;
7511
7512 switch (cs->reason)
7513 {
7514 case XmCR_DECREMENT:
7515 bar->dragging = Qnil;
7516 part = scroll_bar_up_arrow;
7517 break;
7518
7519 case XmCR_INCREMENT:
7520 bar->dragging = Qnil;
7521 part = scroll_bar_down_arrow;
7522 break;
7523
7524 case XmCR_PAGE_DECREMENT:
7525 bar->dragging = Qnil;
7526 part = scroll_bar_above_handle;
7527 break;
7528
7529 case XmCR_PAGE_INCREMENT:
7530 bar->dragging = Qnil;
7531 part = scroll_bar_below_handle;
7532 break;
7533
7534 case XmCR_TO_TOP:
7535 bar->dragging = Qnil;
7536 part = scroll_bar_to_top;
7537 break;
7538
7539 case XmCR_TO_BOTTOM:
7540 bar->dragging = Qnil;
7541 part = scroll_bar_to_bottom;
7542 break;
7543
7544 case XmCR_DRAG:
7545 {
7546 int slider_size;
7547 int dragging_down_p = (INTEGERP (bar->dragging)
7548 && XINT (bar->dragging) <= cs->value);
7549
7550 /* Get the slider size. */
7551 BLOCK_INPUT;
7552 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7553 UNBLOCK_INPUT;
7554
7555 /* At the max position of the scroll bar, do a line-wise
7556 movement. Without doing anything, the LessTif scroll bar
7557 calls us with the same cs->value again and again. If we
7558 want to make sure that we can reach the end of the buffer,
7559 we have to do something.
7560
7561 Implementation note: setting bar->dragging always to
7562 cs->value gives a smoother movement at the max position.
7563 Setting it to nil when doing line-wise movement gives
7564 a better slider behavior. */
7565
7566 if (cs->value + slider_size == XM_SB_MAX
7567 || (dragging_down_p
7568 && last_scroll_bar_part == scroll_bar_down_arrow))
7569 {
7570 part = scroll_bar_down_arrow;
7571 bar->dragging = Qnil;
7572 }
7573 else
7574 {
7575 whole = XM_SB_RANGE;
7576 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7577 part = scroll_bar_handle;
7578 bar->dragging = make_number (cs->value);
7579 }
7580 }
7581 break;
7582
7583 case XmCR_VALUE_CHANGED:
7584 break;
7585 };
7586
7587 if (part >= 0)
7588 {
7589 window_being_scrolled = bar->window;
7590 last_scroll_bar_part = part;
7591 x_send_scroll_bar_event (bar->window, part, portion, whole);
7592 }
7593}
7594
7595
ec18280f 7596#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7597
7598
ec18280f 7599/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7600 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7601 scroll bar struct. CALL_DATA is a pointer to a float saying where
7602 the thumb is. */
7603
7604static void
ec18280f 7605xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7606 Widget widget;
7607 XtPointer client_data, call_data;
7608{
7609 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7610 float top = *(float *) call_data;
7611 float shown;
ec18280f
SM
7612 int whole, portion, height;
7613 int part;
06a2c219
GM
7614
7615 /* Get the size of the thumb, a value between 0 and 1. */
7616 BLOCK_INPUT;
ec18280f 7617 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7618 UNBLOCK_INPUT;
7619
7620 whole = 10000000;
7621 portion = shown < 1 ? top * whole : 0;
06a2c219 7622
ec18280f
SM
7623 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7624 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7625 the bottom, so we force the scrolling whenever we see that we're
7626 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7627 we try to ensure that we always stay two pixels away from the
7628 bottom). */
06a2c219
GM
7629 part = scroll_bar_down_arrow;
7630 else
7631 part = scroll_bar_handle;
7632
7633 window_being_scrolled = bar->window;
7634 bar->dragging = make_number (portion);
7635 last_scroll_bar_part = part;
7636 x_send_scroll_bar_event (bar->window, part, portion, whole);
7637}
7638
7639
ec18280f
SM
7640/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7641 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7642 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7643 the scroll bar. CALL_DATA is an integer specifying the action that
7644 has taken place. It's magnitude is in the range 0..height of the
7645 scroll bar. Negative values mean scroll towards buffer start.
7646 Values < height of scroll bar mean line-wise movement. */
7647
7648static void
ec18280f 7649xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7650 Widget widget;
7651 XtPointer client_data, call_data;
7652{
7653 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7654 int position = (int) call_data;
7655 Dimension height;
7656 int part;
7657
7658 /* Get the height of the scroll bar. */
7659 BLOCK_INPUT;
7660 XtVaGetValues (widget, XtNheight, &height, NULL);
7661 UNBLOCK_INPUT;
7662
ec18280f
SM
7663 if (abs (position) >= height)
7664 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7665
7666 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7667 it maps line-movement to call_data = max(5, height/20). */
7668 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7669 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7670 else
ec18280f 7671 part = scroll_bar_move_ratio;
06a2c219
GM
7672
7673 window_being_scrolled = bar->window;
7674 bar->dragging = Qnil;
7675 last_scroll_bar_part = part;
ec18280f 7676 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7677}
7678
7679
7680#endif /* not USE_MOTIF */
7681
7682
7683/* Create the widget for scroll bar BAR on frame F. Record the widget
7684 and X window of the scroll bar in BAR. */
7685
7686static void
7687x_create_toolkit_scroll_bar (f, bar)
7688 struct frame *f;
7689 struct scroll_bar *bar;
7690{
7691 Window xwindow;
7692 Widget widget;
7693 Arg av[20];
7694 int ac = 0;
7695 char *scroll_bar_name = "verticalScrollBar";
7696 unsigned long pixel;
7697
7698 BLOCK_INPUT;
7699
7700#ifdef USE_MOTIF
7701 /* LessTif 0.85, problems:
7702
7703 1. When the mouse if over the scroll bar, the scroll bar will
7704 get keyboard events. I didn't find a way to turn this off.
7705
7706 2. Do we have to explicitly set the cursor to get an arrow
7707 cursor (see below)? */
7708
7709 /* Set resources. Create the widget. */
7710 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7711 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7712 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7713 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7714 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7715 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7716 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7717
7718 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7719 if (pixel != -1)
7720 {
7721 XtSetArg (av[ac], XmNforeground, pixel);
7722 ++ac;
7723 }
7724
7725 pixel = f->output_data.x->scroll_bar_background_pixel;
7726 if (pixel != -1)
7727 {
7728 XtSetArg (av[ac], XmNbackground, pixel);
7729 ++ac;
7730 }
7731
7732 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7733 scroll_bar_name, av, ac);
7734
7735 /* Add one callback for everything that can happen. */
7736 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7737 (XtPointer) bar);
7738 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7739 (XtPointer) bar);
7740 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7741 (XtPointer) bar);
7742 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7743 (XtPointer) bar);
7744 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7745 (XtPointer) bar);
7746 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7747 (XtPointer) bar);
7748 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7749 (XtPointer) bar);
7750
7751 /* Realize the widget. Only after that is the X window created. */
7752 XtRealizeWidget (widget);
7753
7754 /* Set the cursor to an arrow. I didn't find a resource to do that.
7755 And I'm wondering why it hasn't an arrow cursor by default. */
7756 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7757 f->output_data.x->nontext_cursor);
7758
ec18280f 7759#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7760
7761 /* Set resources. Create the widget. The background of the
7762 Xaw3d scroll bar widget is a little bit light for my taste.
7763 We don't alter it here to let users change it according
7764 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7765 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7766 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
7767 /* For smoother scrolling with Xaw3d -sm */
7768 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7769 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
7770
7771 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7772 if (pixel != -1)
7773 {
7774 XtSetArg (av[ac], XtNforeground, pixel);
7775 ++ac;
7776 }
7777
7778 pixel = f->output_data.x->scroll_bar_background_pixel;
7779 if (pixel != -1)
7780 {
7781 XtSetArg (av[ac], XtNbackground, pixel);
7782 ++ac;
7783 }
7784
7785 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7786 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
7787
7788 {
7789 char *initial = "";
7790 char *val = initial;
7791 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7792 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7793 if (val == initial)
7794 { /* ARROW_SCROLL */
7795 xaw3d_arrow_scroll = True;
7796 /* Isn't that just a personal preference ? -sm */
7797 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7798 }
7799 }
06a2c219
GM
7800
7801 /* Define callbacks. */
ec18280f
SM
7802 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7803 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
7804 (XtPointer) bar);
7805
7806 /* Realize the widget. Only after that is the X window created. */
7807 XtRealizeWidget (widget);
7808
ec18280f 7809#endif /* !USE_MOTIF */
06a2c219
GM
7810
7811 /* Install an action hook that let's us detect when the user
7812 finishes interacting with a scroll bar. */
7813 if (action_hook_id == 0)
7814 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7815
7816 /* Remember X window and widget in the scroll bar vector. */
7817 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7818 xwindow = XtWindow (widget);
7819 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7820
7821 UNBLOCK_INPUT;
7822}
7823
7824
7825/* Set the thumb size and position of scroll bar BAR. We are currently
7826 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7827
7828static void
7829x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7830 struct scroll_bar *bar;
7831 int portion, position, whole;
f451eb13 7832{
06a2c219 7833 float top, shown;
06a2c219 7834 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7835
06a2c219
GM
7836 if (whole == 0)
7837 top = 0, shown = 1;
7838 else
f451eb13 7839 {
06a2c219
GM
7840 top = (float) position / whole;
7841 shown = (float) portion / whole;
7842 }
f451eb13 7843
06a2c219 7844 BLOCK_INPUT;
f451eb13 7845
06a2c219
GM
7846#ifdef USE_MOTIF
7847 {
7848 int size, value;
7849 Boolean arrow1_selected, arrow2_selected;
7850 unsigned char flags;
7851 XmScrollBarWidget sb;
7852
ec18280f 7853 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
7854 is the scroll bar's maximum and MIN is the scroll bar's minimum
7855 value. */
7856 size = shown * XM_SB_RANGE;
7857 size = min (size, XM_SB_RANGE);
7858 size = max (size, 1);
7859
7860 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7861 value = top * XM_SB_RANGE;
7862 value = min (value, XM_SB_MAX - size);
7863 value = max (value, XM_SB_MIN);
7864
7865 /* LessTif: Calling XmScrollBarSetValues after an increment or
7866 decrement turns off auto-repeat LessTif-internally. This can
7867 be seen in ScrollBar.c which resets Arrow1Selected and
7868 Arrow2Selected. It also sets internal flags so that LessTif
7869 believes the mouse is in the slider. We either have to change
7870 our code, or work around that by accessing private data. */
7871
7872 sb = (XmScrollBarWidget) widget;
7873 arrow1_selected = sb->scrollBar.arrow1_selected;
7874 arrow2_selected = sb->scrollBar.arrow2_selected;
7875 flags = sb->scrollBar.flags;
7876
7877 if (NILP (bar->dragging))
7878 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7879 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7880 /* This has the negative side effect that the slider value is
ec18280f 7881 not what it would be if we scrolled here using line-wise or
06a2c219
GM
7882 page-wise movement. */
7883 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7884 else
7885 {
7886 /* If currently dragging, only update the slider size.
7887 This reduces flicker effects. */
7888 int old_value, old_size, increment, page_increment;
7889
7890 XmScrollBarGetValues (widget, &old_value, &old_size,
7891 &increment, &page_increment);
7892 XmScrollBarSetValues (widget, old_value,
7893 min (size, XM_SB_RANGE - old_value),
7894 0, 0, False);
7895 }
7896
7897 sb->scrollBar.arrow1_selected = arrow1_selected;
7898 sb->scrollBar.arrow2_selected = arrow2_selected;
7899 sb->scrollBar.flags = flags;
7900 }
ec18280f 7901#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 7902 {
ec18280f
SM
7903 float old_top, old_shown;
7904 Dimension height;
7905 XtVaGetValues (widget,
7906 XtNtopOfThumb, &old_top,
7907 XtNshown, &old_shown,
7908 XtNheight, &height,
7909 NULL);
7910
7911 /* Massage the top+shown values. */
7912 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7913 top = max (0, min (1, top));
7914 else
7915 top = old_top;
7916 /* Keep two pixels available for moving the thumb down. */
7917 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
7918
7919 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7920 check that your system's configuration file contains a define
7921 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 7922 if (top != old_top || shown != old_shown)
eb393530 7923 {
ec18280f 7924 if (NILP (bar->dragging))
eb393530 7925 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
7926 else
7927 {
ec18280f
SM
7928#ifdef HAVE_XAW3D
7929 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 7930 int scroll_mode = 0;
ec18280f
SM
7931
7932 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7933 if (xaw3d_arrow_scroll)
7934 {
7935 /* Xaw3d stupidly ignores resize requests while dragging
7936 so we have to make it believe it's not in dragging mode. */
7937 scroll_mode = sb->scrollbar.scroll_mode;
7938 if (scroll_mode == 2)
7939 sb->scrollbar.scroll_mode = 0;
7940 }
7941#endif
7942 /* Try to make the scrolling a tad smoother. */
7943 if (!xaw3d_pick_top)
7944 shown = min (shown, old_shown);
7945
7946 XawScrollbarSetThumb (widget, top, shown);
7947
7948#ifdef HAVE_XAW3D
7949 if (xaw3d_arrow_scroll && scroll_mode == 2)
7950 sb->scrollbar.scroll_mode = scroll_mode;
7951#endif
06a2c219 7952 }
06a2c219
GM
7953 }
7954 }
ec18280f 7955#endif /* !USE_MOTIF */
06a2c219
GM
7956
7957 UNBLOCK_INPUT;
f451eb13
JB
7958}
7959
06a2c219
GM
7960#endif /* USE_TOOLKIT_SCROLL_BARS */
7961
7962
7963\f
7964/************************************************************************
7965 Scroll bars, general
7966 ************************************************************************/
7967
7968/* Create a scroll bar and return the scroll bar vector for it. W is
7969 the Emacs window on which to create the scroll bar. TOP, LEFT,
7970 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7971 scroll bar. */
7972
ab648270 7973static struct scroll_bar *
06a2c219
GM
7974x_scroll_bar_create (w, top, left, width, height)
7975 struct window *w;
f451eb13
JB
7976 int top, left, width, height;
7977{
06a2c219 7978 struct frame *f = XFRAME (w->frame);
334208b7
RS
7979 struct scroll_bar *bar
7980 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
7981
7982 BLOCK_INPUT;
7983
06a2c219
GM
7984#if USE_TOOLKIT_SCROLL_BARS
7985 x_create_toolkit_scroll_bar (f, bar);
7986#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7987 {
7988 XSetWindowAttributes a;
7989 unsigned long mask;
5c187dee 7990 Window window;
06a2c219
GM
7991
7992 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7993 if (a.background_pixel == -1)
7994 a.background_pixel = f->output_data.x->background_pixel;
7995
12ba150f 7996 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 7997 | ButtonMotionMask | PointerMotionHintMask
12ba150f 7998 | ExposureMask);
7a13e894 7999 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8000
dbc4e1c1 8001 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8002
06a2c219
GM
8003 /* Clear the area of W that will serve as a scroll bar. This is
8004 for the case that a window has been split horizontally. In
8005 this case, no clear_frame is generated to reduce flickering. */
8006 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8007 left, top, width,
8008 window_box_height (w), False);
8009
8010 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8011 /* Position and size of scroll bar. */
8012 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8013 top,
8014 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8015 height,
8016 /* Border width, depth, class, and visual. */
8017 0,
8018 CopyFromParent,
8019 CopyFromParent,
8020 CopyFromParent,
8021 /* Attributes. */
8022 mask, &a);
8023 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8024 }
06a2c219 8025#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8026
06a2c219 8027 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8028 XSETINT (bar->top, top);
8029 XSETINT (bar->left, left);
8030 XSETINT (bar->width, width);
8031 XSETINT (bar->height, height);
8032 XSETINT (bar->start, 0);
8033 XSETINT (bar->end, 0);
12ba150f 8034 bar->dragging = Qnil;
f451eb13
JB
8035
8036 /* Add bar to its frame's list of scroll bars. */
334208b7 8037 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8038 bar->prev = Qnil;
334208b7 8039 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8040 if (!NILP (bar->next))
e0c1aef2 8041 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8042
06a2c219
GM
8043 /* Map the window/widget. */
8044#if USE_TOOLKIT_SCROLL_BARS
8045 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8046 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8047 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8048 top,
8049 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8050 height, 0);
8051#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8052 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8053#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8054
8055 UNBLOCK_INPUT;
12ba150f 8056 return bar;
f451eb13
JB
8057}
8058
06a2c219 8059
12ba150f 8060/* Draw BAR's handle in the proper position.
06a2c219 8061
12ba150f
JB
8062 If the handle is already drawn from START to END, don't bother
8063 redrawing it, unless REBUILD is non-zero; in that case, always
8064 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8065 events.)
12ba150f
JB
8066
8067 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8068 fit inside its rectangle, but if the user is dragging the scroll
8069 bar handle, we want to let them drag it down all the way, so that
8070 the bar's top is as far down as it goes; otherwise, there's no way
8071 to move to the very end of the buffer. */
8072
5c187dee
GM
8073#ifndef USE_TOOLKIT_SCROLL_BARS
8074
f451eb13 8075static void
ab648270
JB
8076x_scroll_bar_set_handle (bar, start, end, rebuild)
8077 struct scroll_bar *bar;
f451eb13 8078 int start, end;
12ba150f 8079 int rebuild;
f451eb13 8080{
12ba150f 8081 int dragging = ! NILP (bar->dragging);
ab648270 8082 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8083 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8084 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8085
8086 /* If the display is already accurate, do nothing. */
8087 if (! rebuild
8088 && start == XINT (bar->start)
8089 && end == XINT (bar->end))
8090 return;
8091
f451eb13
JB
8092 BLOCK_INPUT;
8093
8094 {
d9cdbb3d
RS
8095 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8096 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8097 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8098
8099 /* Make sure the values are reasonable, and try to preserve
8100 the distance between start and end. */
12ba150f
JB
8101 {
8102 int length = end - start;
8103
8104 if (start < 0)
8105 start = 0;
8106 else if (start > top_range)
8107 start = top_range;
8108 end = start + length;
8109
8110 if (end < start)
8111 end = start;
8112 else if (end > top_range && ! dragging)
8113 end = top_range;
8114 }
f451eb13 8115
ab648270 8116 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8117 XSETINT (bar->start, start);
8118 XSETINT (bar->end, end);
f451eb13 8119
12ba150f
JB
8120 /* Clip the end position, just for display. */
8121 if (end > top_range)
8122 end = top_range;
f451eb13 8123
ab648270 8124 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8125 below top positions, to make sure the handle is always at least
8126 that many pixels tall. */
ab648270 8127 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8128
12ba150f
JB
8129 /* Draw the empty space above the handle. Note that we can't clear
8130 zero-height areas; that means "clear to end of window." */
8131 if (0 < start)
334208b7 8132 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8133
12ba150f 8134 /* x, y, width, height, and exposures. */
ab648270
JB
8135 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8136 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8137 inside_width, start,
8138 False);
f451eb13 8139
06a2c219
GM
8140 /* Change to proper foreground color if one is specified. */
8141 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8142 XSetForeground (FRAME_X_DISPLAY (f), gc,
8143 f->output_data.x->scroll_bar_foreground_pixel);
8144
12ba150f 8145 /* Draw the handle itself. */
334208b7 8146 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8147
12ba150f 8148 /* x, y, width, height */
ab648270
JB
8149 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8150 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8151 inside_width, end - start);
f451eb13 8152
06a2c219
GM
8153 /* Restore the foreground color of the GC if we changed it above. */
8154 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8155 XSetForeground (FRAME_X_DISPLAY (f), gc,
8156 f->output_data.x->foreground_pixel);
f451eb13 8157
12ba150f
JB
8158 /* Draw the empty space below the handle. Note that we can't
8159 clear zero-height areas; that means "clear to end of window." */
8160 if (end < inside_height)
334208b7 8161 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8162
12ba150f 8163 /* x, y, width, height, and exposures. */
ab648270
JB
8164 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8165 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8166 inside_width, inside_height - end,
8167 False);
f451eb13 8168
f451eb13
JB
8169 }
8170
f451eb13
JB
8171 UNBLOCK_INPUT;
8172}
8173
5c187dee 8174#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8175
06a2c219
GM
8176/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8177 nil. */
58769bee 8178
12ba150f 8179static void
ab648270
JB
8180x_scroll_bar_remove (bar)
8181 struct scroll_bar *bar;
12ba150f 8182{
12ba150f
JB
8183 BLOCK_INPUT;
8184
06a2c219
GM
8185#if USE_TOOLKIT_SCROLL_BARS
8186 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8187#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8188 {
8189 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8190 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8191 }
06a2c219
GM
8192#endif /* not USE_TOOLKIT_SCROLL_BARS */
8193
ab648270
JB
8194 /* Disassociate this scroll bar from its window. */
8195 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8196
8197 UNBLOCK_INPUT;
8198}
8199
06a2c219 8200
12ba150f
JB
8201/* Set the handle of the vertical scroll bar for WINDOW to indicate
8202 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8203 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8204 create one. */
06a2c219 8205
12ba150f 8206static void
06a2c219
GM
8207XTset_vertical_scroll_bar (w, portion, whole, position)
8208 struct window *w;
f451eb13
JB
8209 int portion, whole, position;
8210{
06a2c219 8211 struct frame *f = XFRAME (w->frame);
ab648270 8212 struct scroll_bar *bar;
3c6ede7b 8213 int top, height, left, sb_left, width, sb_width;
06a2c219 8214 int window_x, window_y, window_width, window_height;
06a2c219 8215
3c6ede7b 8216 /* Get window dimensions. */
06a2c219 8217 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8218 top = window_y;
8219 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8220 height = window_height;
06a2c219 8221
3c6ede7b 8222 /* Compute the left edge of the scroll bar area. */
06a2c219 8223 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8224 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8225 else
8226 left = XFASTINT (w->left);
8227 left *= CANON_X_UNIT (f);
8228 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8229
8230 /* Compute the width of the scroll bar which might be less than
8231 the width of the area reserved for the scroll bar. */
8232 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8233 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8234 else
3c6ede7b 8235 sb_width = width;
12ba150f 8236
3c6ede7b
GM
8237 /* Compute the left edge of the scroll bar. */
8238#ifdef USE_TOOLKIT_SCROLL_BARS
8239 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8240 sb_left = left + width - sb_width - (width - sb_width) / 2;
8241 else
8242 sb_left = left + (width - sb_width) / 2;
8243#else
8244 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8245 sb_left = left + width - sb_width;
8246 else
8247 sb_left = left;
8248#endif
8249
ab648270 8250 /* Does the scroll bar exist yet? */
06a2c219 8251 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8252 {
80c32bcc 8253 BLOCK_INPUT;
3c6ede7b
GM
8254 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8255 left, top, width, height, False);
80c32bcc 8256 UNBLOCK_INPUT;
3c6ede7b
GM
8257 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8258 }
f451eb13 8259 else
12ba150f
JB
8260 {
8261 /* It may just need to be moved and resized. */
06a2c219
GM
8262 unsigned int mask = 0;
8263
8264 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8265
8266 BLOCK_INPUT;
8267
3c6ede7b 8268 if (sb_left != XINT (bar->left))
06a2c219 8269 mask |= CWX;
3c6ede7b 8270 if (top != XINT (bar->top))
06a2c219 8271 mask |= CWY;
3c6ede7b 8272 if (sb_width != XINT (bar->width))
06a2c219 8273 mask |= CWWidth;
3c6ede7b 8274 if (height != XINT (bar->height))
06a2c219
GM
8275 mask |= CWHeight;
8276
8277#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8278
8279 /* Since toolkit scroll bars are smaller than the space reserved
8280 for them on the frame, we have to clear "under" them. */
8281 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8282 left, top, width, height, False);
06a2c219
GM
8283
8284 /* Move/size the scroll bar widget. */
8285 if (mask)
8286 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8287 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8288 top,
8289 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8290 height, 0);
06a2c219
GM
8291
8292#else /* not USE_TOOLKIT_SCROLL_BARS */
8293
e1f6572f
RS
8294 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8295 {
8296 /* Clear areas not covered by the scroll bar. This makes sure a
8297 previous mode line display is cleared after C-x 2 C-x 1, for
8298 example. Non-toolkit scroll bars are as wide as the area
8299 reserved for scroll bars - trim at both sides. */
8300 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8301 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8302 height, False);
8303 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8304 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8305 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8306 height, False);
8307 }
06a2c219
GM
8308
8309 /* Move/size the scroll bar window. */
8310 if (mask)
8311 {
8312 XWindowChanges wc;
8313
3c6ede7b
GM
8314 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8315 wc.y = top;
8316 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8317 wc.height = height;
06a2c219
GM
8318 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8319 mask, &wc);
8320 }
8321
8322#endif /* not USE_TOOLKIT_SCROLL_BARS */
8323
8324 /* Remember new settings. */
3c6ede7b
GM
8325 XSETINT (bar->left, sb_left);
8326 XSETINT (bar->top, top);
8327 XSETINT (bar->width, sb_width);
8328 XSETINT (bar->height, height);
06a2c219
GM
8329
8330 UNBLOCK_INPUT;
12ba150f 8331 }
f451eb13 8332
06a2c219
GM
8333#if USE_TOOLKIT_SCROLL_BARS
8334 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8335#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8336 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8337 dragged. */
12ba150f 8338 if (NILP (bar->dragging))
f451eb13 8339 {
92857db0 8340 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8341
12ba150f 8342 if (whole == 0)
ab648270 8343 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8344 else
8345 {
43f868f5
JB
8346 int start = ((double) position * top_range) / whole;
8347 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8348 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8349 }
f451eb13 8350 }
06a2c219 8351#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8352
06a2c219 8353 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8354}
8355
12ba150f 8356
f451eb13 8357/* The following three hooks are used when we're doing a thorough
ab648270 8358 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8359 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8360 away is a real pain - "Can you say set-window-configuration, boys
8361 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8362 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8363 from the fiery pit when we actually redisplay its window. */
f451eb13 8364
ab648270
JB
8365/* Arrange for all scroll bars on FRAME to be removed at the next call
8366 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8367 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8368
58769bee 8369static void
ab648270 8370XTcondemn_scroll_bars (frame)
f451eb13
JB
8371 FRAME_PTR frame;
8372{
f9e24cb9
RS
8373 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8374 while (! NILP (FRAME_SCROLL_BARS (frame)))
8375 {
8376 Lisp_Object bar;
8377 bar = FRAME_SCROLL_BARS (frame);
8378 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8379 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8380 XSCROLL_BAR (bar)->prev = Qnil;
8381 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8382 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8383 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8384 }
f451eb13
JB
8385}
8386
06a2c219 8387/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8388 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 8389static void
ab648270 8390XTredeem_scroll_bar (window)
12ba150f 8391 struct window *window;
f451eb13 8392{
ab648270 8393 struct scroll_bar *bar;
12ba150f 8394
ab648270
JB
8395 /* We can't redeem this window's scroll bar if it doesn't have one. */
8396 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8397 abort ();
8398
ab648270 8399 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8400
8401 /* Unlink it from the condemned list. */
8402 {
8403 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8404
8405 if (NILP (bar->prev))
8406 {
8407 /* If the prev pointer is nil, it must be the first in one of
8408 the lists. */
ab648270 8409 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
8410 /* It's not condemned. Everything's fine. */
8411 return;
ab648270
JB
8412 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8413 window->vertical_scroll_bar))
8414 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
8415 else
8416 /* If its prev pointer is nil, it must be at the front of
8417 one or the other! */
8418 abort ();
8419 }
8420 else
ab648270 8421 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
8422
8423 if (! NILP (bar->next))
ab648270 8424 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8425
ab648270 8426 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8427 bar->prev = Qnil;
e0c1aef2 8428 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 8429 if (! NILP (bar->next))
e0c1aef2 8430 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 8431 }
f451eb13
JB
8432}
8433
ab648270
JB
8434/* Remove all scroll bars on FRAME that haven't been saved since the
8435 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8436
f451eb13 8437static void
ab648270 8438XTjudge_scroll_bars (f)
12ba150f 8439 FRAME_PTR f;
f451eb13 8440{
12ba150f 8441 Lisp_Object bar, next;
f451eb13 8442
ab648270 8443 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8444
8445 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8446 more events on the hapless scroll bars. */
8447 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8448
8449 for (; ! NILP (bar); bar = next)
f451eb13 8450 {
ab648270 8451 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8452
ab648270 8453 x_scroll_bar_remove (b);
12ba150f
JB
8454
8455 next = b->next;
8456 b->next = b->prev = Qnil;
f451eb13 8457 }
12ba150f 8458
ab648270 8459 /* Now there should be no references to the condemned scroll bars,
12ba150f 8460 and they should get garbage-collected. */
f451eb13
JB
8461}
8462
8463
06a2c219
GM
8464/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8465 is a no-op when using toolkit scroll bars.
ab648270
JB
8466
8467 This may be called from a signal handler, so we have to ignore GC
8468 mark bits. */
06a2c219 8469
f451eb13 8470static void
ab648270
JB
8471x_scroll_bar_expose (bar, event)
8472 struct scroll_bar *bar;
f451eb13
JB
8473 XEvent *event;
8474{
06a2c219
GM
8475#ifndef USE_TOOLKIT_SCROLL_BARS
8476
ab648270 8477 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8478 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8479 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8480 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8481
f451eb13
JB
8482 BLOCK_INPUT;
8483
ab648270 8484 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8485
06a2c219 8486 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8487 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8488
8489 /* x, y, width, height */
d9cdbb3d 8490 0, 0,
3cbd2e0b 8491 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8492 XINT (bar->height) - 1);
8493
f451eb13 8494 UNBLOCK_INPUT;
06a2c219
GM
8495
8496#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8497}
8498
ab648270
JB
8499/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8500 is set to something other than no_event, it is enqueued.
8501
8502 This may be called from a signal handler, so we have to ignore GC
8503 mark bits. */
06a2c219 8504
5c187dee
GM
8505#ifndef USE_TOOLKIT_SCROLL_BARS
8506
f451eb13 8507static void
ab648270
JB
8508x_scroll_bar_handle_click (bar, event, emacs_event)
8509 struct scroll_bar *bar;
f451eb13
JB
8510 XEvent *event;
8511 struct input_event *emacs_event;
8512{
0299d313 8513 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8514 abort ();
8515
ab648270 8516 emacs_event->kind = scroll_bar_click;
69388238 8517 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8518 emacs_event->modifiers
8519 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8520 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8521 event->xbutton.state)
8522 | (event->type == ButtonRelease
8523 ? up_modifier
8524 : down_modifier));
12ba150f 8525 emacs_event->frame_or_window = bar->window;
f451eb13 8526 emacs_event->timestamp = event->xbutton.time;
12ba150f 8527 {
06a2c219 8528#if 0
d9cdbb3d 8529 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8530 int internal_height
d9cdbb3d 8531 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8532#endif
0299d313 8533 int top_range
d9cdbb3d 8534 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8535 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8536
8537 if (y < 0) y = 0;
8538 if (y > top_range) y = top_range;
8539
8540 if (y < XINT (bar->start))
ab648270
JB
8541 emacs_event->part = scroll_bar_above_handle;
8542 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8543 emacs_event->part = scroll_bar_handle;
12ba150f 8544 else
ab648270 8545 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8546
8547 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8548 they want to drag it. Lisp code needs to be able to decide
8549 whether or not we're dragging. */
929787e1 8550#if 0
12ba150f
JB
8551 /* If the user has just clicked on the handle, record where they're
8552 holding it. */
8553 if (event->type == ButtonPress
ab648270 8554 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8555 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8556#endif
12ba150f
JB
8557
8558 /* If the user has released the handle, set it to its final position. */
8559 if (event->type == ButtonRelease
8560 && ! NILP (bar->dragging))
8561 {
8562 int new_start = y - XINT (bar->dragging);
8563 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8564
ab648270 8565 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8566 bar->dragging = Qnil;
8567 }
f451eb13 8568
5116f055
JB
8569 /* Same deal here as the other #if 0. */
8570#if 0
58769bee 8571 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8572 the handle. */
ab648270 8573 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8574 emacs_event->x = bar->start;
8575 else
e0c1aef2 8576 XSETINT (emacs_event->x, y);
5116f055 8577#else
e0c1aef2 8578 XSETINT (emacs_event->x, y);
5116f055 8579#endif
f451eb13 8580
e0c1aef2 8581 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8582 }
8583}
f451eb13 8584
ab648270
JB
8585/* Handle some mouse motion while someone is dragging the scroll bar.
8586
8587 This may be called from a signal handler, so we have to ignore GC
8588 mark bits. */
06a2c219 8589
f451eb13 8590static void
ab648270
JB
8591x_scroll_bar_note_movement (bar, event)
8592 struct scroll_bar *bar;
f451eb13
JB
8593 XEvent *event;
8594{
39d8bb4d
KH
8595 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8596
f451eb13
JB
8597 last_mouse_movement_time = event->xmotion.time;
8598
39d8bb4d 8599 f->mouse_moved = 1;
e0c1aef2 8600 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8601
8602 /* If we're dragging the bar, display it. */
ab648270 8603 if (! GC_NILP (bar->dragging))
f451eb13
JB
8604 {
8605 /* Where should the handle be now? */
12ba150f 8606 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8607
12ba150f 8608 if (new_start != XINT (bar->start))
f451eb13 8609 {
12ba150f 8610 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8611
ab648270 8612 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8613 }
8614 }
f451eb13
JB
8615}
8616
5c187dee
GM
8617#endif /* !USE_TOOLKIT_SCROLL_BARS */
8618
12ba150f 8619/* Return information to the user about the current position of the mouse
ab648270 8620 on the scroll bar. */
06a2c219 8621
12ba150f 8622static void
334208b7
RS
8623x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8624 FRAME_PTR *fp;
12ba150f 8625 Lisp_Object *bar_window;
ab648270 8626 enum scroll_bar_part *part;
12ba150f
JB
8627 Lisp_Object *x, *y;
8628 unsigned long *time;
8629{
ab648270 8630 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8631 Window w = SCROLL_BAR_X_WINDOW (bar);
8632 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8633 int win_x, win_y;
559cb2fb
JB
8634 Window dummy_window;
8635 int dummy_coord;
8636 unsigned int dummy_mask;
12ba150f 8637
cf7cb199
JB
8638 BLOCK_INPUT;
8639
ab648270 8640 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8641 report that. */
334208b7 8642 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8643
559cb2fb
JB
8644 /* Root, child, root x and root y. */
8645 &dummy_window, &dummy_window,
8646 &dummy_coord, &dummy_coord,
12ba150f 8647
559cb2fb
JB
8648 /* Position relative to scroll bar. */
8649 &win_x, &win_y,
12ba150f 8650
559cb2fb
JB
8651 /* Mouse buttons and modifier keys. */
8652 &dummy_mask))
7a13e894 8653 ;
559cb2fb
JB
8654 else
8655 {
06a2c219 8656#if 0
559cb2fb 8657 int inside_height
d9cdbb3d 8658 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8659#endif
559cb2fb 8660 int top_range
d9cdbb3d 8661 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8662
8663 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8664
8665 if (! NILP (bar->dragging))
8666 win_y -= XINT (bar->dragging);
8667
8668 if (win_y < 0)
8669 win_y = 0;
8670 if (win_y > top_range)
8671 win_y = top_range;
8672
334208b7 8673 *fp = f;
7a13e894 8674 *bar_window = bar->window;
559cb2fb
JB
8675
8676 if (! NILP (bar->dragging))
8677 *part = scroll_bar_handle;
8678 else if (win_y < XINT (bar->start))
8679 *part = scroll_bar_above_handle;
8680 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8681 *part = scroll_bar_handle;
8682 else
8683 *part = scroll_bar_below_handle;
12ba150f 8684
e0c1aef2
KH
8685 XSETINT (*x, win_y);
8686 XSETINT (*y, top_range);
12ba150f 8687
39d8bb4d 8688 f->mouse_moved = 0;
559cb2fb
JB
8689 last_mouse_scroll_bar = Qnil;
8690 }
12ba150f 8691
559cb2fb 8692 *time = last_mouse_movement_time;
cf7cb199 8693
cf7cb199 8694 UNBLOCK_INPUT;
12ba150f
JB
8695}
8696
f451eb13 8697
dbc4e1c1 8698/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8699 background colors, and the scroll bars may need to be redrawn.
8700 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8701 redraw them. */
8702
dfcf069d 8703void
ab648270 8704x_scroll_bar_clear (f)
dbc4e1c1
JB
8705 FRAME_PTR f;
8706{
06a2c219 8707#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8708 Lisp_Object bar;
8709
b80c363e
RS
8710 /* We can have scroll bars even if this is 0,
8711 if we just turned off scroll bar mode.
8712 But in that case we should not clear them. */
8713 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8714 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8715 bar = XSCROLL_BAR (bar)->next)
8716 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8717 0, 0, 0, 0, True);
06a2c219 8718#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8719}
8720
06a2c219 8721/* This processes Expose events from the menu-bar specific X event
19126e11 8722 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8723 when handling menu-bar or pop-up items. */
3afe33e7 8724
06a2c219 8725int
3afe33e7
RS
8726process_expose_from_menu (event)
8727 XEvent event;
8728{
8729 FRAME_PTR f;
19126e11 8730 struct x_display_info *dpyinfo;
06a2c219 8731 int frame_exposed_p = 0;
3afe33e7 8732
f94397b5
KH
8733 BLOCK_INPUT;
8734
19126e11
KH
8735 dpyinfo = x_display_info_for_display (event.xexpose.display);
8736 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8737 if (f)
8738 {
8739 if (f->async_visible == 0)
8740 {
8741 f->async_visible = 1;
8742 f->async_iconified = 0;
06c488fd 8743 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8744 SET_FRAME_GARBAGED (f);
8745 }
8746 else
8747 {
06a2c219
GM
8748 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8749 event.xexpose.x, event.xexpose.y,
8750 event.xexpose.width, event.xexpose.height);
8751 frame_exposed_p = 1;
3afe33e7
RS
8752 }
8753 }
8754 else
8755 {
8756 struct scroll_bar *bar
8757 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8758
3afe33e7
RS
8759 if (bar)
8760 x_scroll_bar_expose (bar, &event);
8761 }
f94397b5
KH
8762
8763 UNBLOCK_INPUT;
06a2c219 8764 return frame_exposed_p;
3afe33e7 8765}
09756a85
RS
8766\f
8767/* Define a queue to save up SelectionRequest events for later handling. */
8768
8769struct selection_event_queue
8770 {
8771 XEvent event;
8772 struct selection_event_queue *next;
8773 };
8774
8775static struct selection_event_queue *queue;
8776
8777/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8778
09756a85
RS
8779static int x_queue_selection_requests;
8780
8781/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8782
09756a85 8783static void
334208b7
RS
8784x_queue_event (f, event)
8785 FRAME_PTR f;
09756a85
RS
8786 XEvent *event;
8787{
8788 struct selection_event_queue *queue_tmp
06a2c219 8789 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8790
58769bee 8791 if (queue_tmp != NULL)
09756a85
RS
8792 {
8793 queue_tmp->event = *event;
8794 queue_tmp->next = queue;
8795 queue = queue_tmp;
8796 }
8797}
8798
8799/* Take all the queued events and put them back
8800 so that they get processed afresh. */
8801
8802static void
db3906fd
RS
8803x_unqueue_events (display)
8804 Display *display;
09756a85 8805{
58769bee 8806 while (queue != NULL)
09756a85
RS
8807 {
8808 struct selection_event_queue *queue_tmp = queue;
db3906fd 8809 XPutBackEvent (display, &queue_tmp->event);
09756a85 8810 queue = queue_tmp->next;
06a2c219 8811 xfree ((char *)queue_tmp);
09756a85
RS
8812 }
8813}
8814
8815/* Start queuing SelectionRequest events. */
8816
8817void
db3906fd
RS
8818x_start_queuing_selection_requests (display)
8819 Display *display;
09756a85
RS
8820{
8821 x_queue_selection_requests++;
8822}
8823
8824/* Stop queuing SelectionRequest events. */
8825
8826void
db3906fd
RS
8827x_stop_queuing_selection_requests (display)
8828 Display *display;
09756a85
RS
8829{
8830 x_queue_selection_requests--;
db3906fd 8831 x_unqueue_events (display);
09756a85 8832}
f451eb13
JB
8833\f
8834/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8835
06a2c219 8836/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8837 but we have to put it out here, since static variables within functions
8838 sometimes don't work. */
06a2c219 8839
dc6f92b8
JB
8840static Time enter_timestamp;
8841
11edeb03 8842/* This holds the state XLookupString needs to implement dead keys
58769bee 8843 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8844 says that a portable program can't use this, but Stephen Gildea assures
8845 me that letting the compiler initialize it to zeros will work okay.
8846
8847 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8848 given for enter_time stamp, above. */
8849
11edeb03
JB
8850static XComposeStatus compose_status;
8851
10e6549c
RS
8852/* Record the last 100 characters stored
8853 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8854
2224b905
RS
8855static int temp_index;
8856static short temp_buffer[100];
10e6549c 8857
7a13e894
RS
8858/* Set this to nonzero to fake an "X I/O error"
8859 on a particular display. */
06a2c219 8860
7a13e894
RS
8861struct x_display_info *XTread_socket_fake_io_error;
8862
2224b905
RS
8863/* When we find no input here, we occasionally do a no-op command
8864 to verify that the X server is still running and we can still talk with it.
8865 We try all the open displays, one by one.
8866 This variable is used for cycling thru the displays. */
06a2c219 8867
2224b905
RS
8868static struct x_display_info *next_noop_dpyinfo;
8869
06a2c219
GM
8870#define SET_SAVED_MENU_EVENT(size) \
8871 do \
8872 { \
8873 if (f->output_data.x->saved_menu_event == 0) \
8874 f->output_data.x->saved_menu_event \
8875 = (XEvent *) xmalloc (sizeof (XEvent)); \
8876 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8877 if (numchars >= 1) \
8878 { \
8879 bufp->kind = menu_bar_activate_event; \
8880 XSETFRAME (bufp->frame_or_window, f); \
8881 bufp++; \
8882 count++; \
8883 numchars--; \
8884 } \
8885 } \
8886 while (0)
8887
8805890a 8888#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 8889#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 8890
dc6f92b8
JB
8891/* Read events coming from the X server.
8892 This routine is called by the SIGIO handler.
8893 We return as soon as there are no more events to be read.
8894
8895 Events representing keys are stored in buffer BUFP,
8896 which can hold up to NUMCHARS characters.
8897 We return the number of characters stored into the buffer,
8898 thus pretending to be `read'.
8899
dc6f92b8
JB
8900 EXPECTED is nonzero if the caller knows input is available. */
8901
7c5283e4 8902int
f66868ba 8903XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 8904 register int sd;
8805890a
KH
8905 /* register */ struct input_event *bufp;
8906 /* register */ int numchars;
dc6f92b8
JB
8907 int expected;
8908{
8909 int count = 0;
8910 int nbytes = 0;
dc6f92b8 8911 XEvent event;
f676886a 8912 struct frame *f;
66f55a9d 8913 int event_found = 0;
334208b7 8914 struct x_display_info *dpyinfo;
dc6f92b8 8915
9ac0d9e0 8916 if (interrupt_input_blocked)
dc6f92b8 8917 {
9ac0d9e0 8918 interrupt_input_pending = 1;
dc6f92b8
JB
8919 return -1;
8920 }
8921
9ac0d9e0 8922 interrupt_input_pending = 0;
dc6f92b8 8923 BLOCK_INPUT;
c0a04927
RS
8924
8925 /* So people can tell when we have read the available input. */
8926 input_signal_count++;
8927
dc6f92b8 8928 if (numchars <= 0)
06a2c219 8929 abort (); /* Don't think this happens. */
dc6f92b8 8930
7a13e894
RS
8931 /* Find the display we are supposed to read input for.
8932 It's the one communicating on descriptor SD. */
8933 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8934 {
8935#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 8936#ifdef FIOSNBIO
7a13e894
RS
8937 /* If available, Xlib uses FIOSNBIO to make the socket
8938 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 8939 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 8940 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 8941 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 8942#endif /* ! defined (FIOSNBIO) */
7a13e894 8943#endif
dc6f92b8 8944
7a13e894
RS
8945#if 0 /* This code can't be made to work, with multiple displays,
8946 and appears not to be used on any system any more.
8947 Also keyboard.c doesn't turn O_NDELAY on and off
8948 for X connections. */
dc6f92b8
JB
8949#ifndef SIGIO
8950#ifndef HAVE_SELECT
7a13e894
RS
8951 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8952 {
8953 extern int read_alarm_should_throw;
8954 read_alarm_should_throw = 1;
8955 XPeekEvent (dpyinfo->display, &event);
8956 read_alarm_should_throw = 0;
8957 }
c118dd06
JB
8958#endif /* HAVE_SELECT */
8959#endif /* SIGIO */
7a13e894 8960#endif
dc6f92b8 8961
7a13e894
RS
8962 /* For debugging, this gives a way to fake an I/O error. */
8963 if (dpyinfo == XTread_socket_fake_io_error)
8964 {
8965 XTread_socket_fake_io_error = 0;
8966 x_io_error_quitter (dpyinfo->display);
8967 }
dc6f92b8 8968
06a2c219 8969 while (XPending (dpyinfo->display))
dc6f92b8 8970 {
7a13e894 8971 XNextEvent (dpyinfo->display, &event);
06a2c219 8972
531483fb 8973#ifdef HAVE_X_I18N
d1bc4182 8974 {
f2be1146
GM
8975 /* Filter events for the current X input method.
8976 XFilterEvent returns non-zero if the input method has
8977 consumed the event. We pass the frame's X window to
8978 XFilterEvent because that's the one for which the IC
8979 was created. */
f5d11644
GM
8980 struct frame *f1 = x_any_window_to_frame (dpyinfo,
8981 event.xclient.window);
8982 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
8983 break;
8984 }
0cd6403b 8985#endif
7a13e894
RS
8986 event_found = 1;
8987
8988 switch (event.type)
8989 {
8990 case ClientMessage:
c047688c 8991 {
7a13e894
RS
8992 if (event.xclient.message_type
8993 == dpyinfo->Xatom_wm_protocols
8994 && event.xclient.format == 32)
c047688c 8995 {
7a13e894
RS
8996 if (event.xclient.data.l[0]
8997 == dpyinfo->Xatom_wm_take_focus)
c047688c 8998 {
8c1a6a84
RS
8999 /* Use x_any_window_to_frame because this
9000 could be the shell widget window
9001 if the frame has no title bar. */
9002 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9003#ifdef HAVE_X_I18N
9004 /* Not quite sure this is needed -pd */
8c1a6a84 9005 if (f && FRAME_XIC (f))
6c183ba5
RS
9006 XSetICFocus (FRAME_XIC (f));
9007#endif
f1da8f06
GM
9008#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9009 instructs the WM to set the input focus automatically for
9010 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9011 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9012 it has set the focus. So, XSetInputFocus below is not
9013 needed.
9014
9015 The call to XSetInputFocus below has also caused trouble. In
9016 cases where the XSetInputFocus done by the WM and the one
9017 below are temporally close (on a fast machine), the call
9018 below can generate additional FocusIn events which confuse
9019 Emacs. */
9020
bf7253f4
RS
9021 /* Since we set WM_TAKE_FOCUS, we must call
9022 XSetInputFocus explicitly. But not if f is null,
9023 since that might be an event for a deleted frame. */
7a13e894 9024 if (f)
bf7253f4
RS
9025 {
9026 Display *d = event.xclient.display;
9027 /* Catch and ignore errors, in case window has been
9028 iconified by a window manager such as GWM. */
9029 int count = x_catch_errors (d);
9030 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9031 /* The ICCCM says this is
9032 the only valid choice. */
9033 RevertToParent,
bf7253f4
RS
9034 event.xclient.data.l[1]);
9035 /* This is needed to detect the error
9036 if there is an error. */
9037 XSync (d, False);
9038 x_uncatch_errors (d, count);
9039 }
7a13e894 9040 /* Not certain about handling scroll bars here */
f1da8f06 9041#endif /* 0 */
c047688c 9042 }
7a13e894
RS
9043 else if (event.xclient.data.l[0]
9044 == dpyinfo->Xatom_wm_save_yourself)
9045 {
9046 /* Save state modify the WM_COMMAND property to
06a2c219 9047 something which can reinstate us. This notifies
7a13e894
RS
9048 the session manager, who's looking for such a
9049 PropertyNotify. Can restart processing when
06a2c219 9050 a keyboard or mouse event arrives. */
7a13e894
RS
9051 if (numchars > 0)
9052 {
19126e11
KH
9053 f = x_top_window_to_frame (dpyinfo,
9054 event.xclient.window);
7a13e894
RS
9055
9056 /* This is just so we only give real data once
9057 for a single Emacs process. */
b86bd3dd 9058 if (f == SELECTED_FRAME ())
7a13e894
RS
9059 XSetCommand (FRAME_X_DISPLAY (f),
9060 event.xclient.window,
9061 initial_argv, initial_argc);
f000f5c5 9062 else if (f)
7a13e894
RS
9063 XSetCommand (FRAME_X_DISPLAY (f),
9064 event.xclient.window,
9065 0, 0);
9066 }
9067 }
9068 else if (event.xclient.data.l[0]
9069 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9070 {
19126e11
KH
9071 struct frame *f
9072 = x_any_window_to_frame (dpyinfo,
9073 event.xclient.window);
1fb20991 9074
7a13e894
RS
9075 if (f)
9076 {
9077 if (numchars == 0)
9078 abort ();
1fb20991 9079
7a13e894
RS
9080 bufp->kind = delete_window_event;
9081 XSETFRAME (bufp->frame_or_window, f);
9082 bufp++;
9083
9084 count += 1;
9085 numchars -= 1;
9086 }
1fb20991 9087 }
c047688c 9088 }
7a13e894
RS
9089 else if (event.xclient.message_type
9090 == dpyinfo->Xatom_wm_configure_denied)
9091 {
9092 }
9093 else if (event.xclient.message_type
9094 == dpyinfo->Xatom_wm_window_moved)
9095 {
9096 int new_x, new_y;
19126e11
KH
9097 struct frame *f
9098 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9099
7a13e894
RS
9100 new_x = event.xclient.data.s[0];
9101 new_y = event.xclient.data.s[1];
1fb20991 9102
7a13e894
RS
9103 if (f)
9104 {
7556890b
RS
9105 f->output_data.x->left_pos = new_x;
9106 f->output_data.x->top_pos = new_y;
7a13e894 9107 }
1fb20991 9108 }
0fdff6bb 9109#ifdef HACK_EDITRES
7a13e894
RS
9110 else if (event.xclient.message_type
9111 == dpyinfo->Xatom_editres)
9112 {
19126e11
KH
9113 struct frame *f
9114 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9115 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9116 &event, NULL);
7a13e894 9117 }
0fdff6bb 9118#endif /* HACK_EDITRES */
06a2c219
GM
9119 else if ((event.xclient.message_type
9120 == dpyinfo->Xatom_DONE)
9121 || (event.xclient.message_type
9122 == dpyinfo->Xatom_PAGE))
9123 {
9124 /* Ghostview job completed. Kill it. We could
9125 reply with "Next" if we received "Page", but we
9126 currently never do because we are interested in
9127 images, only, which should have 1 page. */
06a2c219
GM
9128 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9129 struct frame *f
9130 = x_window_to_frame (dpyinfo, event.xclient.window);
9131 x_kill_gs_process (pixmap, f);
9132 expose_frame (f, 0, 0, 0, 0);
9133 }
9134#ifdef USE_TOOLKIT_SCROLL_BARS
9135 /* Scroll bar callbacks send a ClientMessage from which
9136 we construct an input_event. */
9137 else if (event.xclient.message_type
9138 == dpyinfo->Xatom_Scrollbar)
9139 {
9140 x_scroll_bar_to_input_event (&event, bufp);
9141 ++bufp, ++count, --numchars;
9142 goto out;
9143 }
9144#endif /* USE_TOOLKIT_SCROLL_BARS */
9145 else
9146 goto OTHER;
7a13e894
RS
9147 }
9148 break;
dc6f92b8 9149
7a13e894 9150 case SelectionNotify:
3afe33e7 9151#ifdef USE_X_TOOLKIT
19126e11 9152 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9153 goto OTHER;
3afe33e7 9154#endif /* not USE_X_TOOLKIT */
dfcf069d 9155 x_handle_selection_notify (&event.xselection);
7a13e894 9156 break;
d56a553a 9157
06a2c219 9158 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9159#ifdef USE_X_TOOLKIT
19126e11 9160 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9161 goto OTHER;
3afe33e7 9162#endif /* USE_X_TOOLKIT */
7a13e894
RS
9163 {
9164 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9165
7a13e894
RS
9166 if (numchars == 0)
9167 abort ();
d56a553a 9168
7a13e894
RS
9169 bufp->kind = selection_clear_event;
9170 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9171 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9172 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9173 bufp->frame_or_window = Qnil;
7a13e894 9174 bufp++;
d56a553a 9175
7a13e894
RS
9176 count += 1;
9177 numchars -= 1;
9178 }
9179 break;
dc6f92b8 9180
06a2c219 9181 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9182#ifdef USE_X_TOOLKIT
19126e11 9183 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9184 goto OTHER;
3afe33e7 9185#endif /* USE_X_TOOLKIT */
7a13e894 9186 if (x_queue_selection_requests)
19126e11 9187 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9188 &event);
9189 else
9190 {
9191 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9192
7a13e894
RS
9193 if (numchars == 0)
9194 abort ();
9195
9196 bufp->kind = selection_request_event;
9197 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9198 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9199 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9200 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9201 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9202 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9203 bufp->frame_or_window = Qnil;
7a13e894
RS
9204 bufp++;
9205
9206 count += 1;
9207 numchars -= 1;
9208 }
9209 break;
9210
9211 case PropertyNotify:
3afe33e7 9212#ifdef USE_X_TOOLKIT
19126e11 9213 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9214 goto OTHER;
3afe33e7 9215#endif /* not USE_X_TOOLKIT */
dfcf069d 9216 x_handle_property_notify (&event.xproperty);
7a13e894 9217 break;
dc6f92b8 9218
7a13e894 9219 case ReparentNotify:
19126e11 9220 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9221 if (f)
9222 {
9223 int x, y;
7556890b 9224 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9225 x_real_positions (f, &x, &y);
7556890b
RS
9226 f->output_data.x->left_pos = x;
9227 f->output_data.x->top_pos = y;
7a13e894
RS
9228 }
9229 break;
3bd330d4 9230
7a13e894 9231 case Expose:
19126e11 9232 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9233 if (f)
dc6f92b8 9234 {
7a13e894
RS
9235 if (f->async_visible == 0)
9236 {
9237 f->async_visible = 1;
9238 f->async_iconified = 0;
06c488fd 9239 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9240 SET_FRAME_GARBAGED (f);
9241 }
9242 else
06a2c219
GM
9243 expose_frame (x_window_to_frame (dpyinfo,
9244 event.xexpose.window),
9245 event.xexpose.x, event.xexpose.y,
9246 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9247 }
9248 else
7a13e894 9249 {
06a2c219
GM
9250#ifdef USE_TOOLKIT_SCROLL_BARS
9251 /* Dispatch event to the widget. */
9252 goto OTHER;
9253#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9254 struct scroll_bar *bar
9255 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9256
7a13e894
RS
9257 if (bar)
9258 x_scroll_bar_expose (bar, &event);
3afe33e7 9259#ifdef USE_X_TOOLKIT
7a13e894
RS
9260 else
9261 goto OTHER;
3afe33e7 9262#endif /* USE_X_TOOLKIT */
06a2c219 9263#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9264 }
9265 break;
dc6f92b8 9266
7a13e894
RS
9267 case GraphicsExpose: /* This occurs when an XCopyArea's
9268 source area was obscured or not
9269 available.*/
19126e11 9270 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9271 if (f)
9272 {
06a2c219
GM
9273 expose_frame (f,
9274 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9275 event.xgraphicsexpose.width,
9276 event.xgraphicsexpose.height);
7a13e894 9277 }
3afe33e7 9278#ifdef USE_X_TOOLKIT
7a13e894
RS
9279 else
9280 goto OTHER;
3afe33e7 9281#endif /* USE_X_TOOLKIT */
7a13e894 9282 break;
dc6f92b8 9283
7a13e894 9284 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9285 source area was completely
9286 available */
7a13e894 9287 break;
dc6f92b8 9288
7a13e894 9289 case UnmapNotify:
06a2c219
GM
9290 /* Redo the mouse-highlight after the tooltip has gone. */
9291 if (event.xmap.window == tip_window)
9292 {
9293 tip_window = 0;
9294 redo_mouse_highlight ();
9295 }
9296
91ea2a7a 9297 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9298 if (f) /* F may no longer exist if
9299 the frame was deleted. */
9300 {
9301 /* While a frame is unmapped, display generation is
9302 disabled; you don't want to spend time updating a
9303 display that won't ever be seen. */
9304 f->async_visible = 0;
9305 /* We can't distinguish, from the event, whether the window
9306 has become iconified or invisible. So assume, if it
9307 was previously visible, than now it is iconified.
1aa6072f
RS
9308 But x_make_frame_invisible clears both
9309 the visible flag and the iconified flag;
9310 and that way, we know the window is not iconified now. */
7a13e894 9311 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9312 {
9313 f->async_iconified = 1;
bddd097c 9314
1aa6072f
RS
9315 bufp->kind = iconify_event;
9316 XSETFRAME (bufp->frame_or_window, f);
9317 bufp++;
9318 count++;
9319 numchars--;
9320 }
7a13e894 9321 }
7a13e894 9322 goto OTHER;
dc6f92b8 9323
7a13e894 9324 case MapNotify:
06a2c219
GM
9325 if (event.xmap.window == tip_window)
9326 /* The tooltip has been drawn already. Avoid
9327 the SET_FRAME_GARBAGED below. */
9328 goto OTHER;
9329
9330 /* We use x_top_window_to_frame because map events can
9331 come for sub-windows and they don't mean that the
9332 frame is visible. */
19126e11 9333 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9334 if (f)
9335 {
9336 f->async_visible = 1;
9337 f->async_iconified = 0;
06c488fd 9338 f->output_data.x->has_been_visible = 1;
dc6f92b8 9339
7a13e894
RS
9340 /* wait_reading_process_input will notice this and update
9341 the frame's display structures. */
9342 SET_FRAME_GARBAGED (f);
bddd097c 9343
d806e720
RS
9344 if (f->iconified)
9345 {
9346 bufp->kind = deiconify_event;
9347 XSETFRAME (bufp->frame_or_window, f);
9348 bufp++;
9349 count++;
9350 numchars--;
9351 }
e73ec6fa 9352 else if (! NILP (Vframe_list)
8e713be6 9353 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9354 /* Force a redisplay sooner or later
9355 to update the frame titles
9356 in case this is the second frame. */
9357 record_asynch_buffer_change ();
7a13e894 9358 }
7a13e894 9359 goto OTHER;
dc6f92b8 9360
7a13e894 9361 case KeyPress:
19126e11 9362 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9363
06a2c219
GM
9364#ifdef USE_MOTIF
9365 /* I couldn't find a way to prevent LessTif scroll bars
9366 from consuming key events. */
9367 if (f == 0)
9368 {
9369 Widget widget = XtWindowToWidget (dpyinfo->display,
9370 event.xkey.window);
9371 if (widget && XmIsScrollBar (widget))
9372 {
9373 widget = XtParent (widget);
9374 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9375 }
9376 }
9377#endif /* USE_MOTIF */
9378
7a13e894
RS
9379 if (f != 0)
9380 {
9381 KeySym keysym, orig_keysym;
9382 /* al%imercury@uunet.uu.net says that making this 81 instead of
9383 80 fixed a bug whereby meta chars made his Emacs hang. */
9384 unsigned char copy_buffer[81];
9385 int modifiers;
64bb1782 9386
7a13e894
RS
9387 event.xkey.state
9388 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9389 extra_keyboard_modifiers);
9390 modifiers = event.xkey.state;
3a2712f9 9391
7a13e894 9392 /* This will have to go some day... */
752a043f 9393
7a13e894
RS
9394 /* make_lispy_event turns chars into control chars.
9395 Don't do it here because XLookupString is too eager. */
9396 event.xkey.state &= ~ControlMask;
5d46f928
RS
9397 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9398 | dpyinfo->super_mod_mask
9399 | dpyinfo->hyper_mod_mask
9400 | dpyinfo->alt_mod_mask);
9401
1cf4a0d1
RS
9402 /* In case Meta is ComposeCharacter,
9403 clear its status. According to Markus Ehrnsperger
9404 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9405 this enables ComposeCharacter to work whether or
9406 not it is combined with Meta. */
9407 if (modifiers & dpyinfo->meta_mod_mask)
9408 bzero (&compose_status, sizeof (compose_status));
9409
6c183ba5
RS
9410#ifdef HAVE_X_I18N
9411 if (FRAME_XIC (f))
9412 {
f5d11644
GM
9413 unsigned char *copy_bufptr = copy_buffer;
9414 int copy_bufsiz = sizeof (copy_buffer);
9415 Status status_return;
9416
6c183ba5 9417 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9418 &event.xkey, copy_bufptr,
9419 copy_bufsiz, &keysym,
6c183ba5 9420 &status_return);
f5d11644
GM
9421 if (status_return == XBufferOverflow)
9422 {
9423 copy_bufsiz = nbytes + 1;
9424 copy_bufptr = (char *) alloca (copy_bufsiz);
9425 nbytes = XmbLookupString (FRAME_XIC (f),
9426 &event.xkey, copy_bufptr,
9427 copy_bufsiz, &keysym,
9428 &status_return);
9429 }
9430
1decb680
PE
9431 if (status_return == XLookupNone)
9432 break;
9433 else if (status_return == XLookupChars)
fdd9d55e
GM
9434 {
9435 keysym = NoSymbol;
9436 modifiers = 0;
9437 }
1decb680
PE
9438 else if (status_return != XLookupKeySym
9439 && status_return != XLookupBoth)
9440 abort ();
6c183ba5
RS
9441 }
9442 else
9443 nbytes = XLookupString (&event.xkey, copy_buffer,
9444 80, &keysym, &compose_status);
9445#else
0299d313
RS
9446 nbytes = XLookupString (&event.xkey, copy_buffer,
9447 80, &keysym, &compose_status);
6c183ba5 9448#endif
dc6f92b8 9449
7a13e894 9450 orig_keysym = keysym;
55123275 9451
7a13e894
RS
9452 if (numchars > 1)
9453 {
9454 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9455 || keysym == XK_Delete
1097aea0 9456#ifdef XK_ISO_Left_Tab
441affdb 9457 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9458#endif
852bff8f 9459 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9460 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9461 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9462#ifdef HPUX
7a13e894
RS
9463 /* This recognizes the "extended function keys".
9464 It seems there's no cleaner way.
9465 Test IsModifierKey to avoid handling mode_switch
9466 incorrectly. */
9467 || ((unsigned) (keysym) >= XK_Select
9468 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9469#endif
9470#ifdef XK_dead_circumflex
7a13e894 9471 || orig_keysym == XK_dead_circumflex
69388238
RS
9472#endif
9473#ifdef XK_dead_grave
7a13e894 9474 || orig_keysym == XK_dead_grave
69388238
RS
9475#endif
9476#ifdef XK_dead_tilde
7a13e894 9477 || orig_keysym == XK_dead_tilde
69388238
RS
9478#endif
9479#ifdef XK_dead_diaeresis
7a13e894 9480 || orig_keysym == XK_dead_diaeresis
69388238
RS
9481#endif
9482#ifdef XK_dead_macron
7a13e894 9483 || orig_keysym == XK_dead_macron
69388238
RS
9484#endif
9485#ifdef XK_dead_degree
7a13e894 9486 || orig_keysym == XK_dead_degree
69388238
RS
9487#endif
9488#ifdef XK_dead_acute
7a13e894 9489 || orig_keysym == XK_dead_acute
69388238
RS
9490#endif
9491#ifdef XK_dead_cedilla
7a13e894 9492 || orig_keysym == XK_dead_cedilla
69388238
RS
9493#endif
9494#ifdef XK_dead_breve
7a13e894 9495 || orig_keysym == XK_dead_breve
69388238
RS
9496#endif
9497#ifdef XK_dead_ogonek
7a13e894 9498 || orig_keysym == XK_dead_ogonek
69388238
RS
9499#endif
9500#ifdef XK_dead_caron
7a13e894 9501 || orig_keysym == XK_dead_caron
69388238
RS
9502#endif
9503#ifdef XK_dead_doubleacute
7a13e894 9504 || orig_keysym == XK_dead_doubleacute
69388238
RS
9505#endif
9506#ifdef XK_dead_abovedot
7a13e894 9507 || orig_keysym == XK_dead_abovedot
c34790e0 9508#endif
7a13e894
RS
9509 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9510 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9511 /* Any "vendor-specific" key is ok. */
9512 || (orig_keysym & (1 << 28)))
9513 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9514#ifndef HAVE_X11R5
9515#ifdef XK_Mode_switch
7a13e894 9516 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9517#endif
9518#ifdef XK_Num_Lock
7a13e894 9519 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9520#endif
9521#endif /* not HAVE_X11R5 */
7a13e894 9522 ))
dc6f92b8 9523 {
10e6549c
RS
9524 if (temp_index == sizeof temp_buffer / sizeof (short))
9525 temp_index = 0;
7a13e894
RS
9526 temp_buffer[temp_index++] = keysym;
9527 bufp->kind = non_ascii_keystroke;
9528 bufp->code = keysym;
e0c1aef2 9529 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
9530 bufp->modifiers
9531 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9532 modifiers);
1113d9db 9533 bufp->timestamp = event.xkey.time;
dc6f92b8 9534 bufp++;
7a13e894
RS
9535 count++;
9536 numchars--;
dc6f92b8 9537 }
7a13e894
RS
9538 else if (numchars > nbytes)
9539 {
9540 register int i;
9541
9542 for (i = 0; i < nbytes; i++)
9543 {
9544 if (temp_index == sizeof temp_buffer / sizeof (short))
9545 temp_index = 0;
9546 temp_buffer[temp_index++] = copy_buffer[i];
9547 bufp->kind = ascii_keystroke;
9548 bufp->code = copy_buffer[i];
9549 XSETFRAME (bufp->frame_or_window, f);
9550 bufp->modifiers
9551 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9552 modifiers);
9553 bufp->timestamp = event.xkey.time;
9554 bufp++;
9555 }
9556
9557 count += nbytes;
9558 numchars -= nbytes;
1decb680
PE
9559
9560 if (keysym == NoSymbol)
9561 break;
7a13e894
RS
9562 }
9563 else
9564 abort ();
dc6f92b8 9565 }
10e6549c
RS
9566 else
9567 abort ();
dc6f92b8 9568 }
59ddecde
GM
9569#ifdef HAVE_X_I18N
9570 /* Don't dispatch this event since XtDispatchEvent calls
9571 XFilterEvent, and two calls in a row may freeze the
9572 client. */
9573 break;
9574#else
717ca130 9575 goto OTHER;
59ddecde 9576#endif
f451eb13 9577
f5d11644 9578 case KeyRelease:
59ddecde
GM
9579#ifdef HAVE_X_I18N
9580 /* Don't dispatch this event since XtDispatchEvent calls
9581 XFilterEvent, and two calls in a row may freeze the
9582 client. */
9583 break;
9584#else
f5d11644 9585 goto OTHER;
59ddecde 9586#endif
f5d11644 9587
7a13e894 9588 /* Here's a possible interpretation of the whole
06a2c219
GM
9589 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9590 you get a FocusIn event, you have to get a FocusOut
9591 event before you relinquish the focus. If you
9592 haven't received a FocusIn event, then a mere
9593 LeaveNotify is enough to free you. */
f451eb13 9594
7a13e894 9595 case EnterNotify:
06a2c219
GM
9596 {
9597 int from_menu_bar_p = 0;
9598
9599 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9600
9601#ifdef LESSTIF_VERSION
9602 /* When clicking outside of a menu bar popup to close
9603 it, we get a FocusIn/ EnterNotify sequence of
9604 events. The flag event.xcrossing.focus is not set
9605 in the EnterNotify event of that sequence because
9606 the focus is in the menu bar,
9607 event.xcrossing.window is the frame's X window.
9608 Unconditionally setting the focus frame to null in
9609 this case is not the right thing, because no event
9610 follows that could set the focus frame to the right
9611 value.
9612
9613 This could be a LessTif bug, but I wasn't able to
9614 reproduce the behavior in a simple test program.
9615
9616 (gerd, LessTif 0.88.1). */
9617
9618 if (!event.xcrossing.focus
9619 && f
9620 && f->output_data.x->menubar_widget)
9621 {
9622 Window focus;
9623 int revert;
9624
9625 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9626 if (focus == XtWindow (f->output_data.x->menubar_widget))
9627 from_menu_bar_p = 1;
9628 }
9629#endif /* LESSTIF_VERSION */
6d4238f3 9630
06a2c219
GM
9631 if (event.xcrossing.focus || from_menu_bar_p)
9632 {
9633 /* Avoid nasty pop/raise loops. */
9634 if (f && (!(f->auto_raise)
9635 || !(f->auto_lower)
9636 || (event.xcrossing.time - enter_timestamp) > 500))
9637 {
9638 x_new_focus_frame (dpyinfo, f);
9639 enter_timestamp = event.xcrossing.time;
9640 }
9641 }
9642 else if (f == dpyinfo->x_focus_frame)
9643 x_new_focus_frame (dpyinfo, 0);
9644
9645 /* EnterNotify counts as mouse movement,
9646 so update things that depend on mouse position. */
9647 if (f && !f->output_data.x->busy_p)
9648 note_mouse_movement (f, &event.xmotion);
9649 goto OTHER;
9650 }
dc6f92b8 9651
7a13e894 9652 case FocusIn:
19126e11 9653 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9654 if (event.xfocus.detail != NotifyPointer)
0f941935 9655 dpyinfo->x_focus_event_frame = f;
7a13e894 9656 if (f)
eb72635f
GM
9657 {
9658 x_new_focus_frame (dpyinfo, f);
9659
9660 /* Don't stop displaying the initial startup message
9661 for a switch-frame event we don't need. */
9662 if (GC_NILP (Vterminal_frame)
9663 && GC_CONSP (Vframe_list)
9664 && !GC_NILP (XCDR (Vframe_list)))
9665 {
9666 bufp->kind = FOCUS_IN_EVENT;
9667 XSETFRAME (bufp->frame_or_window, f);
9668 ++bufp, ++count, --numchars;
9669 }
9670 }
f9e24cb9 9671
6c183ba5
RS
9672#ifdef HAVE_X_I18N
9673 if (f && FRAME_XIC (f))
9674 XSetICFocus (FRAME_XIC (f));
9675#endif
9676
7a13e894 9677 goto OTHER;
10c5e63d 9678
7a13e894 9679 case LeaveNotify:
19126e11 9680 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9681 if (f)
10c5e63d 9682 {
06a2c219
GM
9683 Lisp_Object frame;
9684 int from_menu_bar_p = 0;
9685
7a13e894 9686 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9687 {
9688 /* If we move outside the frame, then we're
9689 certainly no longer on any text in the frame. */
9690 clear_mouse_face (dpyinfo);
9691 dpyinfo->mouse_face_mouse_frame = 0;
9692 }
9693
9694 /* Generate a nil HELP_EVENT to cancel a help-echo.
9695 Do it only if there's something to cancel.
9696 Otherwise, the startup message is cleared when
9697 the mouse leaves the frame. */
9698 if (any_help_event_p)
9699 {
9700 XSETFRAME (frame, f);
9701 bufp->kind = HELP_EVENT;
9702 bufp->frame_or_window = Fcons (frame, Qnil);
9703 ++bufp, ++count, --numchars;
9704 }
7a13e894 9705
06a2c219
GM
9706#ifdef LESSTIF_VERSION
9707 /* Please see the comment at the start of the
9708 EnterNotify case. */
9709 if (!event.xcrossing.focus
9710 && f->output_data.x->menubar_widget)
9711 {
9712 Window focus;
9713 int revert;
9714 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9715 if (focus == XtWindow (f->output_data.x->menubar_widget))
9716 from_menu_bar_p = 1;
9717 }
9718#endif /* LESSTIF_VERSION */
9719
9720 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9721 x_mouse_leave (dpyinfo);
10c5e63d 9722 else
7a13e894 9723 {
0f941935
KH
9724 if (f == dpyinfo->x_focus_event_frame)
9725 dpyinfo->x_focus_event_frame = 0;
9726 if (f == dpyinfo->x_focus_frame)
9727 x_new_focus_frame (dpyinfo, 0);
7a13e894 9728 }
10c5e63d 9729 }
7a13e894 9730 goto OTHER;
dc6f92b8 9731
7a13e894 9732 case FocusOut:
19126e11 9733 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9734 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9735 && f == dpyinfo->x_focus_event_frame)
9736 dpyinfo->x_focus_event_frame = 0;
9737 if (f && f == dpyinfo->x_focus_frame)
9738 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9739
6c183ba5
RS
9740#ifdef HAVE_X_I18N
9741 if (f && FRAME_XIC (f))
9742 XUnsetICFocus (FRAME_XIC (f));
9743#endif
9744
7a13e894 9745 goto OTHER;
dc6f92b8 9746
7a13e894 9747 case MotionNotify:
dc6f92b8 9748 {
06a2c219
GM
9749 previous_help_echo = help_echo;
9750 help_echo = Qnil;
9751
7a13e894
RS
9752 if (dpyinfo->grabbed && last_mouse_frame
9753 && FRAME_LIVE_P (last_mouse_frame))
9754 f = last_mouse_frame;
9755 else
19126e11 9756 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9757
7a13e894
RS
9758 if (f)
9759 note_mouse_movement (f, &event.xmotion);
9760 else
9761 {
e88b3c50 9762#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9763 struct scroll_bar *bar
9764 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9765
7a13e894
RS
9766 if (bar)
9767 x_scroll_bar_note_movement (bar, &event);
e88b3c50 9768#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 9769
06a2c219
GM
9770 /* If we move outside the frame, then we're
9771 certainly no longer on any text in the frame. */
7a13e894
RS
9772 clear_mouse_face (dpyinfo);
9773 }
06a2c219
GM
9774
9775 /* If the contents of the global variable help_echo
9776 has changed, generate a HELP_EVENT. */
9777 if (STRINGP (help_echo)
9778 || STRINGP (previous_help_echo))
9779 {
9780 Lisp_Object frame;
9781
9782 if (f)
9783 XSETFRAME (frame, f);
9784 else
9785 frame = Qnil;
9786
9787 any_help_event_p = 1;
9788 bufp->kind = HELP_EVENT;
9789 bufp->frame_or_window = Fcons (frame, help_echo);
9790 ++bufp, ++count, --numchars;
9791 }
9792
9793 goto OTHER;
dc6f92b8 9794 }
dc6f92b8 9795
7a13e894 9796 case ConfigureNotify:
9829ddba
RS
9797 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9798 if (f)
af395ec1 9799 {
5c187dee 9800#ifndef USE_X_TOOLKIT
bf1b7b30
KH
9801 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9802 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 9803
2d7fc7e8
RS
9804 /* In the toolkit version, change_frame_size
9805 is called by the code that handles resizing
9806 of the EmacsFrame widget. */
7a13e894 9807
7a13e894
RS
9808 /* Even if the number of character rows and columns has
9809 not changed, the font size may have changed, so we need
9810 to check the pixel dimensions as well. */
9811 if (columns != f->width
9812 || rows != f->height
7556890b
RS
9813 || event.xconfigure.width != f->output_data.x->pixel_width
9814 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 9815 {
7d1e984f 9816 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 9817 SET_FRAME_GARBAGED (f);
e687d06e 9818 cancel_mouse_face (f);
7a13e894 9819 }
2d7fc7e8 9820#endif
af395ec1 9821
7556890b
RS
9822 f->output_data.x->pixel_width = event.xconfigure.width;
9823 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
9824
9825 /* What we have now is the position of Emacs's own window.
9826 Convert that to the position of the window manager window. */
dcb07ae9
RS
9827 x_real_positions (f, &f->output_data.x->left_pos,
9828 &f->output_data.x->top_pos);
9829
f5d11644
GM
9830#ifdef HAVE_X_I18N
9831 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9832 xic_set_statusarea (f);
9833#endif
9834
dcb07ae9
RS
9835 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9836 {
9837 /* Since the WM decorations come below top_pos now,
9838 we must put them below top_pos in the future. */
9839 f->output_data.x->win_gravity = NorthWestGravity;
9840 x_wm_set_size_hint (f, (long) 0, 0);
9841 }
8f08dc93
KH
9842#ifdef USE_MOTIF
9843 /* Some window managers pass (0,0) as the location of
9844 the window, and the Motif event handler stores it
9845 in the emacs widget, which messes up Motif menus. */
9846 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9847 {
9848 event.xconfigure.x = f->output_data.x->widget->core.x;
9849 event.xconfigure.y = f->output_data.x->widget->core.y;
9850 }
06a2c219 9851#endif /* USE_MOTIF */
7a13e894 9852 }
2d7fc7e8 9853 goto OTHER;
dc6f92b8 9854
7a13e894
RS
9855 case ButtonPress:
9856 case ButtonRelease:
9857 {
9858 /* If we decide we want to generate an event to be seen
9859 by the rest of Emacs, we put it here. */
9860 struct input_event emacs_event;
9ea173e8 9861 int tool_bar_p = 0;
06a2c219 9862
7a13e894 9863 emacs_event.kind = no_event;
7a13e894 9864 bzero (&compose_status, sizeof (compose_status));
9b07615b 9865
06a2c219
GM
9866 if (dpyinfo->grabbed
9867 && last_mouse_frame
9f67f20b
RS
9868 && FRAME_LIVE_P (last_mouse_frame))
9869 f = last_mouse_frame;
9870 else
2224b905 9871 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 9872
06a2c219
GM
9873 if (f)
9874 {
9ea173e8
GM
9875 /* Is this in the tool-bar? */
9876 if (WINDOWP (f->tool_bar_window)
9877 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
9878 {
9879 Lisp_Object window;
9880 int p, x, y;
9881
9882 x = event.xbutton.x;
9883 y = event.xbutton.y;
9884
9885 /* Set x and y. */
9886 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 9887 if (EQ (window, f->tool_bar_window))
06a2c219 9888 {
9ea173e8
GM
9889 x_handle_tool_bar_click (f, &event.xbutton);
9890 tool_bar_p = 1;
06a2c219
GM
9891 }
9892 }
9893
9ea173e8 9894 if (!tool_bar_p)
06a2c219
GM
9895 if (!dpyinfo->x_focus_frame
9896 || f == dpyinfo->x_focus_frame)
9897 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
9898 }
9899 else
9900 {
06a2c219 9901#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9902 struct scroll_bar *bar
9903 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 9904
7a13e894
RS
9905 if (bar)
9906 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 9907#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9908 }
9909
9910 if (event.type == ButtonPress)
9911 {
9912 dpyinfo->grabbed |= (1 << event.xbutton.button);
9913 last_mouse_frame = f;
edad46f6
KH
9914 /* Ignore any mouse motion that happened
9915 before this event; any subsequent mouse-movement
9916 Emacs events should reflect only motion after
9917 the ButtonPress. */
a00e91cd
KH
9918 if (f != 0)
9919 f->mouse_moved = 0;
06a2c219 9920
9ea173e8
GM
9921 if (!tool_bar_p)
9922 last_tool_bar_item = -1;
7a13e894 9923 }
3afe33e7
RS
9924 else
9925 {
7a13e894 9926 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 9927 }
23faf38f 9928
7a13e894
RS
9929 if (numchars >= 1 && emacs_event.kind != no_event)
9930 {
9931 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9932 bufp++;
9933 count++;
9934 numchars--;
9935 }
3afe33e7
RS
9936
9937#ifdef USE_X_TOOLKIT
2224b905
RS
9938 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9939 /* For a down-event in the menu bar,
9940 don't pass it to Xt right now.
9941 Instead, save it away
9942 and we will pass it to Xt from kbd_buffer_get_event.
9943 That way, we can run some Lisp code first. */
91375f8f
RS
9944 if (f && event.type == ButtonPress
9945 /* Verify the event is really within the menu bar
9946 and not just sent to it due to grabbing. */
9947 && event.xbutton.x >= 0
9948 && event.xbutton.x < f->output_data.x->pixel_width
9949 && event.xbutton.y >= 0
9950 && event.xbutton.y < f->output_data.x->menubar_height
9951 && event.xbutton.same_screen)
2224b905 9952 {
8805890a 9953 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
9954 XSETFRAME (last_mouse_press_frame, f);
9955 }
9956 else if (event.type == ButtonPress)
9957 {
9958 last_mouse_press_frame = Qnil;
30e671c3 9959 goto OTHER;
ce89ef46 9960 }
06a2c219 9961
2237cac9
RS
9962#ifdef USE_MOTIF /* This should do not harm for Lucid,
9963 but I am trying to be cautious. */
ce89ef46
RS
9964 else if (event.type == ButtonRelease)
9965 {
2237cac9 9966 if (!NILP (last_mouse_press_frame))
f10ded1c 9967 {
2237cac9
RS
9968 f = XFRAME (last_mouse_press_frame);
9969 if (f->output_data.x)
06a2c219 9970 SET_SAVED_BUTTON_EVENT;
f10ded1c 9971 }
06a2c219 9972 else
30e671c3 9973 goto OTHER;
2224b905 9974 }
2237cac9 9975#endif /* USE_MOTIF */
2224b905
RS
9976 else
9977 goto OTHER;
3afe33e7 9978#endif /* USE_X_TOOLKIT */
7a13e894
RS
9979 }
9980 break;
dc6f92b8 9981
7a13e894 9982 case CirculateNotify:
06a2c219
GM
9983 goto OTHER;
9984
7a13e894 9985 case CirculateRequest:
06a2c219
GM
9986 goto OTHER;
9987
9988 case VisibilityNotify:
9989 goto OTHER;
dc6f92b8 9990
7a13e894
RS
9991 case MappingNotify:
9992 /* Someone has changed the keyboard mapping - update the
9993 local cache. */
9994 switch (event.xmapping.request)
9995 {
9996 case MappingModifier:
9997 x_find_modifier_meanings (dpyinfo);
9998 /* This is meant to fall through. */
9999 case MappingKeyboard:
10000 XRefreshKeyboardMapping (&event.xmapping);
10001 }
7a13e894 10002 goto OTHER;
dc6f92b8 10003
7a13e894 10004 default:
7a13e894 10005 OTHER:
717ca130 10006#ifdef USE_X_TOOLKIT
7a13e894
RS
10007 BLOCK_INPUT;
10008 XtDispatchEvent (&event);
10009 UNBLOCK_INPUT;
3afe33e7 10010#endif /* USE_X_TOOLKIT */
7a13e894
RS
10011 break;
10012 }
dc6f92b8
JB
10013 }
10014 }
10015
06a2c219
GM
10016 out:;
10017
9a5196d0
RS
10018 /* On some systems, an X bug causes Emacs to get no more events
10019 when the window is destroyed. Detect that. (1994.) */
58769bee 10020 if (! event_found)
ef2a22d0 10021 {
ef2a22d0
RS
10022 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10023 One XNOOP in 100 loops will make Emacs terminate.
10024 B. Bretthauer, 1994 */
10025 x_noop_count++;
58769bee 10026 if (x_noop_count >= 100)
ef2a22d0
RS
10027 {
10028 x_noop_count=0;
2224b905
RS
10029
10030 if (next_noop_dpyinfo == 0)
10031 next_noop_dpyinfo = x_display_list;
10032
10033 XNoOp (next_noop_dpyinfo->display);
10034
10035 /* Each time we get here, cycle through the displays now open. */
10036 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10037 }
10038 }
502add23 10039
06a2c219 10040 /* If the focus was just given to an auto-raising frame,
0134a210 10041 raise it now. */
7a13e894 10042 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10043 if (pending_autoraise_frame)
10044 {
10045 x_raise_frame (pending_autoraise_frame);
10046 pending_autoraise_frame = 0;
10047 }
0134a210 10048
dc6f92b8
JB
10049 UNBLOCK_INPUT;
10050 return count;
10051}
06a2c219
GM
10052
10053
10054
dc6f92b8 10055\f
06a2c219
GM
10056/***********************************************************************
10057 Text Cursor
10058 ***********************************************************************/
10059
10060/* Note if the text cursor of window W has been overwritten by a
10061 drawing operation that outputs N glyphs starting at HPOS in the
10062 line given by output_cursor.vpos. N < 0 means all the rest of the
10063 line after HPOS has been written. */
10064
10065static void
10066note_overwritten_text_cursor (w, hpos, n)
10067 struct window *w;
10068 int hpos, n;
10069{
10070 if (updated_area == TEXT_AREA
10071 && output_cursor.vpos == w->phys_cursor.vpos
10072 && hpos <= w->phys_cursor.hpos
10073 && (n < 0
10074 || hpos + n > w->phys_cursor.hpos))
10075 w->phys_cursor_on_p = 0;
10076}
f451eb13
JB
10077
10078
06a2c219
GM
10079/* Set clipping for output in glyph row ROW. W is the window in which
10080 we operate. GC is the graphics context to set clipping in.
10081 WHOLE_LINE_P non-zero means include the areas used for truncation
10082 mark display and alike in the clipping rectangle.
10083
10084 ROW may be a text row or, e.g., a mode line. Text rows must be
10085 clipped to the interior of the window dedicated to text display,
10086 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10087
10088static void
06a2c219
GM
10089x_clip_to_row (w, row, gc, whole_line_p)
10090 struct window *w;
10091 struct glyph_row *row;
10092 GC gc;
10093 int whole_line_p;
dc6f92b8 10094{
06a2c219
GM
10095 struct frame *f = XFRAME (WINDOW_FRAME (w));
10096 XRectangle clip_rect;
10097 int window_x, window_y, window_width, window_height;
dc6f92b8 10098
06a2c219 10099 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10100
06a2c219
GM
10101 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10102 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10103 clip_rect.y = max (clip_rect.y, window_y);
10104 clip_rect.width = window_width;
10105 clip_rect.height = row->visible_height;
5c1aae96 10106
06a2c219
GM
10107 /* If clipping to the whole line, including trunc marks, extend
10108 the rectangle to the left and increase its width. */
10109 if (whole_line_p)
10110 {
110859fc
GM
10111 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10112 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10113 }
5c1aae96 10114
06a2c219 10115 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10116}
10117
06a2c219
GM
10118
10119/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10120
10121static void
06a2c219
GM
10122x_draw_hollow_cursor (w, row)
10123 struct window *w;
10124 struct glyph_row *row;
dc6f92b8 10125{
06a2c219
GM
10126 struct frame *f = XFRAME (WINDOW_FRAME (w));
10127 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10128 Display *dpy = FRAME_X_DISPLAY (f);
10129 int x, y, wd, h;
10130 XGCValues xgcv;
10131 struct glyph *cursor_glyph;
10132 GC gc;
10133
10134 /* Compute frame-relative coordinates from window-relative
10135 coordinates. */
10136 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10137 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10138 + row->ascent - w->phys_cursor_ascent);
10139 h = row->height - 1;
10140
10141 /* Get the glyph the cursor is on. If we can't tell because
10142 the current matrix is invalid or such, give up. */
10143 cursor_glyph = get_phys_cursor_glyph (w);
10144 if (cursor_glyph == NULL)
dc6f92b8
JB
10145 return;
10146
06a2c219
GM
10147 /* Compute the width of the rectangle to draw. If on a stretch
10148 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10149 rectangle as wide as the glyph, but use a canonical character
10150 width instead. */
10151 wd = cursor_glyph->pixel_width - 1;
10152 if (cursor_glyph->type == STRETCH_GLYPH
10153 && !x_stretch_cursor_p)
10154 wd = min (CANON_X_UNIT (f), wd);
10155
10156 /* The foreground of cursor_gc is typically the same as the normal
10157 background color, which can cause the cursor box to be invisible. */
10158 xgcv.foreground = f->output_data.x->cursor_pixel;
10159 if (dpyinfo->scratch_cursor_gc)
10160 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10161 else
10162 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10163 GCForeground, &xgcv);
10164 gc = dpyinfo->scratch_cursor_gc;
10165
10166 /* Set clipping, draw the rectangle, and reset clipping again. */
10167 x_clip_to_row (w, row, gc, 0);
10168 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10169 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10170}
10171
06a2c219
GM
10172
10173/* Draw a bar cursor on window W in glyph row ROW.
10174
10175 Implementation note: One would like to draw a bar cursor with an
10176 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10177 Unfortunately, I didn't find a font yet that has this property set.
10178 --gerd. */
dc6f92b8
JB
10179
10180static void
f02d8aa0 10181x_draw_bar_cursor (w, row, width)
06a2c219
GM
10182 struct window *w;
10183 struct glyph_row *row;
f02d8aa0 10184 int width;
dc6f92b8 10185{
06a2c219
GM
10186 /* If cursor hpos is out of bounds, don't draw garbage. This can
10187 happen in mini-buffer windows when switching between echo area
10188 glyphs and mini-buffer. */
10189 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10190 {
10191 struct frame *f = XFRAME (w->frame);
10192 struct glyph *cursor_glyph;
10193 GC gc;
10194 int x;
10195 unsigned long mask;
10196 XGCValues xgcv;
10197 Display *dpy;
10198 Window window;
10199
10200 cursor_glyph = get_phys_cursor_glyph (w);
10201 if (cursor_glyph == NULL)
10202 return;
10203
10204 xgcv.background = f->output_data.x->cursor_pixel;
10205 xgcv.foreground = f->output_data.x->cursor_pixel;
10206 xgcv.graphics_exposures = 0;
10207 mask = GCForeground | GCBackground | GCGraphicsExposures;
10208 dpy = FRAME_X_DISPLAY (f);
10209 window = FRAME_X_WINDOW (f);
10210 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10211
10212 if (gc)
10213 XChangeGC (dpy, gc, mask, &xgcv);
10214 else
10215 {
10216 gc = XCreateGC (dpy, window, mask, &xgcv);
10217 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10218 }
10219
f02d8aa0
GM
10220 if (width < 0)
10221 width = f->output_data.x->cursor_width;
10222
06a2c219
GM
10223 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10224 x_clip_to_row (w, row, gc, 0);
10225 XFillRectangle (dpy, window, gc,
10226 x,
10227 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10228 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10229 row->height);
10230 XSetClipMask (dpy, gc, None);
10231 }
dc6f92b8
JB
10232}
10233
06a2c219
GM
10234
10235/* Clear the cursor of window W to background color, and mark the
10236 cursor as not shown. This is used when the text where the cursor
10237 is is about to be rewritten. */
10238
dc6f92b8 10239static void
06a2c219
GM
10240x_clear_cursor (w)
10241 struct window *w;
dc6f92b8 10242{
06a2c219
GM
10243 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10244 x_update_window_cursor (w, 0);
10245}
90e65f07 10246
dbc4e1c1 10247
06a2c219
GM
10248/* Draw the cursor glyph of window W in glyph row ROW. See the
10249 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10250
06a2c219
GM
10251static void
10252x_draw_phys_cursor_glyph (w, row, hl)
10253 struct window *w;
10254 struct glyph_row *row;
10255 enum draw_glyphs_face hl;
10256{
10257 /* If cursor hpos is out of bounds, don't draw garbage. This can
10258 happen in mini-buffer windows when switching between echo area
10259 glyphs and mini-buffer. */
10260 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10261 {
10262 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10263 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10264 hl, 0, 0, 0);
10265
10266 /* When we erase the cursor, and ROW is overlapped by other
10267 rows, make sure that these overlapping parts of other rows
10268 are redrawn. */
10269 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10270 {
10271 if (row > w->current_matrix->rows
10272 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10273 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10274
10275 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10276 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10277 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10278 }
10279 }
06a2c219 10280}
dbc4e1c1 10281
eea6af04 10282
06a2c219 10283/* Erase the image of a cursor of window W from the screen. */
eea6af04 10284
06a2c219
GM
10285static void
10286x_erase_phys_cursor (w)
10287 struct window *w;
10288{
10289 struct frame *f = XFRAME (w->frame);
10290 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10291 int hpos = w->phys_cursor.hpos;
10292 int vpos = w->phys_cursor.vpos;
10293 int mouse_face_here_p = 0;
10294 struct glyph_matrix *active_glyphs = w->current_matrix;
10295 struct glyph_row *cursor_row;
10296 struct glyph *cursor_glyph;
10297 enum draw_glyphs_face hl;
10298
10299 /* No cursor displayed or row invalidated => nothing to do on the
10300 screen. */
10301 if (w->phys_cursor_type == NO_CURSOR)
10302 goto mark_cursor_off;
10303
10304 /* VPOS >= active_glyphs->nrows means that window has been resized.
10305 Don't bother to erase the cursor. */
10306 if (vpos >= active_glyphs->nrows)
10307 goto mark_cursor_off;
10308
10309 /* If row containing cursor is marked invalid, there is nothing we
10310 can do. */
10311 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10312 if (!cursor_row->enabled_p)
10313 goto mark_cursor_off;
10314
10315 /* This can happen when the new row is shorter than the old one.
10316 In this case, either x_draw_glyphs or clear_end_of_line
10317 should have cleared the cursor. Note that we wouldn't be
10318 able to erase the cursor in this case because we don't have a
10319 cursor glyph at hand. */
10320 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10321 goto mark_cursor_off;
10322
10323 /* If the cursor is in the mouse face area, redisplay that when
10324 we clear the cursor. */
8801a864
KR
10325 if (! NILP (dpyinfo->mouse_face_window)
10326 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10327 && (vpos > dpyinfo->mouse_face_beg_row
10328 || (vpos == dpyinfo->mouse_face_beg_row
10329 && hpos >= dpyinfo->mouse_face_beg_col))
10330 && (vpos < dpyinfo->mouse_face_end_row
10331 || (vpos == dpyinfo->mouse_face_end_row
10332 && hpos < dpyinfo->mouse_face_end_col))
10333 /* Don't redraw the cursor's spot in mouse face if it is at the
10334 end of a line (on a newline). The cursor appears there, but
10335 mouse highlighting does not. */
10336 && cursor_row->used[TEXT_AREA] > hpos)
10337 mouse_face_here_p = 1;
10338
10339 /* Maybe clear the display under the cursor. */
10340 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10341 {
10342 int x;
045dee35 10343 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10344
06a2c219
GM
10345 cursor_glyph = get_phys_cursor_glyph (w);
10346 if (cursor_glyph == NULL)
10347 goto mark_cursor_off;
dbc4e1c1 10348
06a2c219
GM
10349 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10350
10351 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10352 x,
045dee35 10353 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10354 cursor_row->y)),
10355 cursor_glyph->pixel_width,
10356 cursor_row->visible_height,
10357 False);
dbc4e1c1 10358 }
06a2c219
GM
10359
10360 /* Erase the cursor by redrawing the character underneath it. */
10361 if (mouse_face_here_p)
10362 hl = DRAW_MOUSE_FACE;
10363 else if (cursor_row->inverse_p)
10364 hl = DRAW_INVERSE_VIDEO;
10365 else
10366 hl = DRAW_NORMAL_TEXT;
10367 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10368
06a2c219
GM
10369 mark_cursor_off:
10370 w->phys_cursor_on_p = 0;
10371 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10372}
10373
10374
06a2c219
GM
10375/* Display or clear cursor of window W. If ON is zero, clear the
10376 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10377 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10378
06a2c219
GM
10379void
10380x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10381 struct window *w;
10382 int on, hpos, vpos, x, y;
dbc4e1c1 10383{
06a2c219
GM
10384 struct frame *f = XFRAME (w->frame);
10385 int new_cursor_type;
f02d8aa0 10386 int new_cursor_width;
06a2c219
GM
10387 struct glyph_matrix *current_glyphs;
10388 struct glyph_row *glyph_row;
10389 struct glyph *glyph;
dbc4e1c1 10390
49d838ea 10391 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10392 windows and frames; in the latter case, the frame or window may
10393 be in the midst of changing its size, and x and y may be off the
10394 window. */
10395 if (! FRAME_VISIBLE_P (f)
10396 || FRAME_GARBAGED_P (f)
10397 || vpos >= w->current_matrix->nrows
10398 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10399 return;
10400
10401 /* If cursor is off and we want it off, return quickly. */
06a2c219 10402 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10403 return;
10404
06a2c219
GM
10405 current_glyphs = w->current_matrix;
10406 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10407 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10408
10409 /* If cursor row is not enabled, we don't really know where to
10410 display the cursor. */
10411 if (!glyph_row->enabled_p)
10412 {
10413 w->phys_cursor_on_p = 0;
10414 return;
10415 }
10416
10417 xassert (interrupt_input_blocked);
10418
10419 /* Set new_cursor_type to the cursor we want to be displayed. In a
10420 mini-buffer window, we want the cursor only to appear if we are
10421 reading input from this window. For the selected window, we want
10422 the cursor type given by the frame parameter. If explicitly
10423 marked off, draw no cursor. In all other cases, we want a hollow
10424 box cursor. */
f02d8aa0 10425 new_cursor_width = -1;
9b4a7047
GM
10426 if (cursor_in_echo_area
10427 && FRAME_HAS_MINIBUF_P (f)
10428 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10429 {
9b4a7047
GM
10430 if (w == XWINDOW (echo_area_window))
10431 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10432 else
10433 new_cursor_type = HOLLOW_BOX_CURSOR;
10434 }
06a2c219 10435 else
9b4a7047
GM
10436 {
10437 if (w != XWINDOW (selected_window)
10438 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10439 {
e55a0b79
GM
10440 extern int cursor_in_non_selected_windows;
10441
10442 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
9b4a7047
GM
10443 new_cursor_type = NO_CURSOR;
10444 else
10445 new_cursor_type = HOLLOW_BOX_CURSOR;
10446 }
10447 else if (w->cursor_off_p)
10448 new_cursor_type = NO_CURSOR;
10449 else
f02d8aa0
GM
10450 {
10451 struct buffer *b = XBUFFER (w->buffer);
10452
10453 if (EQ (b->cursor_type, Qt))
10454 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10455 else
10456 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10457 &new_cursor_width);
10458 }
9b4a7047 10459 }
06a2c219
GM
10460
10461 /* If cursor is currently being shown and we don't want it to be or
10462 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10463 erase it. */
06a2c219 10464 if (w->phys_cursor_on_p
dc6f92b8 10465 && (!on
06a2c219
GM
10466 || w->phys_cursor.x != x
10467 || w->phys_cursor.y != y
10468 || new_cursor_type != w->phys_cursor_type))
10469 x_erase_phys_cursor (w);
10470
10471 /* If the cursor is now invisible and we want it to be visible,
10472 display it. */
10473 if (on && !w->phys_cursor_on_p)
10474 {
10475 w->phys_cursor_ascent = glyph_row->ascent;
10476 w->phys_cursor_height = glyph_row->height;
10477
10478 /* Set phys_cursor_.* before x_draw_.* is called because some
10479 of them may need the information. */
10480 w->phys_cursor.x = x;
10481 w->phys_cursor.y = glyph_row->y;
10482 w->phys_cursor.hpos = hpos;
10483 w->phys_cursor.vpos = vpos;
10484 w->phys_cursor_type = new_cursor_type;
10485 w->phys_cursor_on_p = 1;
10486
10487 switch (new_cursor_type)
dc6f92b8 10488 {
06a2c219
GM
10489 case HOLLOW_BOX_CURSOR:
10490 x_draw_hollow_cursor (w, glyph_row);
10491 break;
10492
10493 case FILLED_BOX_CURSOR:
10494 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10495 break;
10496
10497 case BAR_CURSOR:
f02d8aa0 10498 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10499 break;
10500
10501 case NO_CURSOR:
10502 break;
dc6f92b8 10503
06a2c219
GM
10504 default:
10505 abort ();
10506 }
59ddecde
GM
10507
10508#ifdef HAVE_X_I18N
10509 if (w == XWINDOW (f->selected_window))
10510 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10511 xic_set_preeditarea (w, x, y);
10512#endif
dc6f92b8
JB
10513 }
10514
06a2c219 10515#ifndef XFlush
f676886a 10516 if (updating_frame != f)
334208b7 10517 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10518#endif
dc6f92b8
JB
10519}
10520
06a2c219
GM
10521
10522/* Display the cursor on window W, or clear it. X and Y are window
10523 relative pixel coordinates. HPOS and VPOS are glyph matrix
10524 positions. If W is not the selected window, display a hollow
10525 cursor. ON non-zero means display the cursor at X, Y which
10526 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10527
dfcf069d 10528void
06a2c219
GM
10529x_display_cursor (w, on, hpos, vpos, x, y)
10530 struct window *w;
10531 int on, hpos, vpos, x, y;
dc6f92b8 10532{
f94397b5 10533 BLOCK_INPUT;
06a2c219 10534 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10535 UNBLOCK_INPUT;
10536}
10537
06a2c219
GM
10538
10539/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10540 Don't change the cursor's position. */
10541
dfcf069d 10542void
06a2c219 10543x_update_cursor (f, on_p)
5d46f928 10544 struct frame *f;
5d46f928 10545{
06a2c219
GM
10546 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10547}
10548
10549
10550/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10551 in the window tree rooted at W. */
10552
10553static void
10554x_update_cursor_in_window_tree (w, on_p)
10555 struct window *w;
10556 int on_p;
10557{
10558 while (w)
10559 {
10560 if (!NILP (w->hchild))
10561 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10562 else if (!NILP (w->vchild))
10563 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10564 else
10565 x_update_window_cursor (w, on_p);
10566
10567 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10568 }
10569}
5d46f928 10570
f94397b5 10571
06a2c219
GM
10572/* Switch the display of W's cursor on or off, according to the value
10573 of ON. */
10574
10575static void
10576x_update_window_cursor (w, on)
10577 struct window *w;
10578 int on;
10579{
16b5d424
GM
10580 /* Don't update cursor in windows whose frame is in the process
10581 of being deleted. */
10582 if (w->current_matrix)
10583 {
10584 BLOCK_INPUT;
10585 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10586 w->phys_cursor.x, w->phys_cursor.y);
10587 UNBLOCK_INPUT;
10588 }
dc6f92b8 10589}
06a2c219
GM
10590
10591
10592
dc6f92b8
JB
10593\f
10594/* Icons. */
10595
f676886a 10596/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10597 when we get an expose event for it. */
dc6f92b8 10598
dfcf069d 10599void
f676886a
JB
10600refreshicon (f)
10601 struct frame *f;
dc6f92b8 10602{
06a2c219 10603 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10604}
10605
dbc4e1c1 10606/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10607
10608int
990ba854 10609x_bitmap_icon (f, file)
f676886a 10610 struct frame *f;
990ba854 10611 Lisp_Object file;
dc6f92b8 10612{
06a2c219 10613 int bitmap_id;
dc6f92b8 10614
c118dd06 10615 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10616 return 1;
10617
990ba854 10618 /* Free up our existing icon bitmap if any. */
7556890b
RS
10619 if (f->output_data.x->icon_bitmap > 0)
10620 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10621 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10622
10623 if (STRINGP (file))
7f2ae036
RS
10624 bitmap_id = x_create_bitmap_from_file (f, file);
10625 else
10626 {
990ba854 10627 /* Create the GNU bitmap if necessary. */
5bf01b68 10628 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10629 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10630 = x_create_bitmap_from_data (f, gnu_bits,
10631 gnu_width, gnu_height);
990ba854
RS
10632
10633 /* The first time we create the GNU bitmap,
06a2c219 10634 this increments the ref-count one extra time.
990ba854
RS
10635 As a result, the GNU bitmap is never freed.
10636 That way, we don't have to worry about allocating it again. */
334208b7 10637 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10638
334208b7 10639 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10640 }
10641
10642 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10643 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10644
10645 return 0;
10646}
10647
10648
1be2d067
KH
10649/* Make the x-window of frame F use a rectangle with text.
10650 Use ICON_NAME as the text. */
dc6f92b8
JB
10651
10652int
f676886a
JB
10653x_text_icon (f, icon_name)
10654 struct frame *f;
dc6f92b8
JB
10655 char *icon_name;
10656{
c118dd06 10657 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10658 return 1;
10659
1be2d067
KH
10660#ifdef HAVE_X11R4
10661 {
10662 XTextProperty text;
10663 text.value = (unsigned char *) icon_name;
10664 text.encoding = XA_STRING;
10665 text.format = 8;
10666 text.nitems = strlen (icon_name);
10667#ifdef USE_X_TOOLKIT
7556890b 10668 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10669 &text);
10670#else /* not USE_X_TOOLKIT */
10671 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10672#endif /* not USE_X_TOOLKIT */
10673 }
10674#else /* not HAVE_X11R4 */
10675 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10676#endif /* not HAVE_X11R4 */
58769bee 10677
7556890b
RS
10678 if (f->output_data.x->icon_bitmap > 0)
10679 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10680 f->output_data.x->icon_bitmap = 0;
b1c884c3 10681 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10682
10683 return 0;
10684}
10685\f
e99db5a1
RS
10686#define X_ERROR_MESSAGE_SIZE 200
10687
10688/* If non-nil, this should be a string.
10689 It means catch X errors and store the error message in this string. */
10690
10691static Lisp_Object x_error_message_string;
10692
10693/* An X error handler which stores the error message in
10694 x_error_message_string. This is called from x_error_handler if
10695 x_catch_errors is in effect. */
10696
06a2c219 10697static void
e99db5a1
RS
10698x_error_catcher (display, error)
10699 Display *display;
10700 XErrorEvent *error;
10701{
10702 XGetErrorText (display, error->error_code,
10703 XSTRING (x_error_message_string)->data,
10704 X_ERROR_MESSAGE_SIZE);
10705}
10706
10707/* Begin trapping X errors for display DPY. Actually we trap X errors
10708 for all displays, but DPY should be the display you are actually
10709 operating on.
10710
10711 After calling this function, X protocol errors no longer cause
10712 Emacs to exit; instead, they are recorded in the string
10713 stored in x_error_message_string.
10714
10715 Calling x_check_errors signals an Emacs error if an X error has
10716 occurred since the last call to x_catch_errors or x_check_errors.
10717
10718 Calling x_uncatch_errors resumes the normal error handling. */
10719
10720void x_check_errors ();
10721static Lisp_Object x_catch_errors_unwind ();
10722
10723int
10724x_catch_errors (dpy)
10725 Display *dpy;
10726{
10727 int count = specpdl_ptr - specpdl;
10728
10729 /* Make sure any errors from previous requests have been dealt with. */
10730 XSync (dpy, False);
10731
10732 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10733
10734 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10735 XSTRING (x_error_message_string)->data[0] = 0;
10736
10737 return count;
10738}
10739
10740/* Unbind the binding that we made to check for X errors. */
10741
10742static Lisp_Object
10743x_catch_errors_unwind (old_val)
10744 Lisp_Object old_val;
10745{
10746 x_error_message_string = old_val;
10747 return Qnil;
10748}
10749
10750/* If any X protocol errors have arrived since the last call to
10751 x_catch_errors or x_check_errors, signal an Emacs error using
10752 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10753
10754void
10755x_check_errors (dpy, format)
10756 Display *dpy;
10757 char *format;
10758{
10759 /* Make sure to catch any errors incurred so far. */
10760 XSync (dpy, False);
10761
10762 if (XSTRING (x_error_message_string)->data[0])
10763 error (format, XSTRING (x_error_message_string)->data);
10764}
10765
9829ddba
RS
10766/* Nonzero if we had any X protocol errors
10767 since we did x_catch_errors on DPY. */
e99db5a1
RS
10768
10769int
10770x_had_errors_p (dpy)
10771 Display *dpy;
10772{
10773 /* Make sure to catch any errors incurred so far. */
10774 XSync (dpy, False);
10775
10776 return XSTRING (x_error_message_string)->data[0] != 0;
10777}
10778
9829ddba
RS
10779/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10780
06a2c219 10781void
9829ddba
RS
10782x_clear_errors (dpy)
10783 Display *dpy;
10784{
10785 XSTRING (x_error_message_string)->data[0] = 0;
10786}
10787
e99db5a1
RS
10788/* Stop catching X protocol errors and let them make Emacs die.
10789 DPY should be the display that was passed to x_catch_errors.
10790 COUNT should be the value that was returned by
10791 the corresponding call to x_catch_errors. */
10792
10793void
10794x_uncatch_errors (dpy, count)
10795 Display *dpy;
10796 int count;
10797{
10798 unbind_to (count, Qnil);
10799}
10800
10801#if 0
10802static unsigned int x_wire_count;
10803x_trace_wire ()
10804{
10805 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10806}
10807#endif /* ! 0 */
10808
10809\f
10810/* Handle SIGPIPE, which can happen when the connection to a server
10811 simply goes away. SIGPIPE is handled by x_connection_signal.
10812 Don't need to do anything, because the write which caused the
10813 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 10814 which will do the appropriate cleanup for us. */
e99db5a1
RS
10815
10816static SIGTYPE
10817x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 10818 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
10819{
10820#ifdef USG
10821 /* USG systems forget handlers when they are used;
10822 must reestablish each time */
10823 signal (signalnum, x_connection_signal);
10824#endif /* USG */
10825}
10826\f
4746118a
JB
10827/* Handling X errors. */
10828
7a13e894 10829/* Handle the loss of connection to display DISPLAY. */
16bd92ea 10830
4746118a 10831static SIGTYPE
7a13e894
RS
10832x_connection_closed (display, error_message)
10833 Display *display;
10834 char *error_message;
4746118a 10835{
7a13e894
RS
10836 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10837 Lisp_Object frame, tail;
10838
6186a4a0
RS
10839 /* Indicate that this display is dead. */
10840
2e465cdd 10841#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 10842#ifdef USE_X_TOOLKIT
adabc3a9 10843 XtCloseDisplay (display);
2e465cdd 10844#endif
f613a4c8 10845#endif
adabc3a9 10846
9e80b57d
KR
10847 if (dpyinfo)
10848 dpyinfo->display = 0;
6186a4a0 10849
06a2c219 10850 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
10851 that are on the dead display. */
10852 FOR_EACH_FRAME (tail, frame)
10853 {
10854 Lisp_Object minibuf_frame;
10855 minibuf_frame
10856 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
10857 if (FRAME_X_P (XFRAME (frame))
10858 && FRAME_X_P (XFRAME (minibuf_frame))
10859 && ! EQ (frame, minibuf_frame)
10860 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
10861 Fdelete_frame (frame, Qt);
10862 }
10863
10864 /* Now delete all remaining frames on the dead display.
06a2c219 10865 We are now sure none of these is used as the mini-buffer
7a13e894
RS
10866 for another frame that we need to delete. */
10867 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
10868 if (FRAME_X_P (XFRAME (frame))
10869 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
10870 {
10871 /* Set this to t so that Fdelete_frame won't get confused
10872 trying to find a replacement. */
10873 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10874 Fdelete_frame (frame, Qt);
10875 }
7a13e894 10876
482a1bd2
KH
10877 if (dpyinfo)
10878 x_delete_display (dpyinfo);
7a13e894
RS
10879
10880 if (x_display_list == 0)
10881 {
f8d07b62 10882 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
10883 shut_down_emacs (0, 0, Qnil);
10884 exit (70);
10885 }
12ba150f 10886
7a13e894
RS
10887 /* Ordinary stack unwind doesn't deal with these. */
10888#ifdef SIGIO
10889 sigunblock (sigmask (SIGIO));
10890#endif
10891 sigunblock (sigmask (SIGALRM));
10892 TOTALLY_UNBLOCK_INPUT;
10893
aa4d9a9e 10894 clear_waiting_for_input ();
7a13e894 10895 error ("%s", error_message);
4746118a
JB
10896}
10897
7a13e894
RS
10898/* This is the usual handler for X protocol errors.
10899 It kills all frames on the display that we got the error for.
10900 If that was the only one, it prints an error message and kills Emacs. */
10901
06a2c219 10902static void
c118dd06
JB
10903x_error_quitter (display, error)
10904 Display *display;
10905 XErrorEvent *error;
10906{
7a13e894 10907 char buf[256], buf1[356];
dc6f92b8 10908
58769bee 10909 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 10910 original error handler. */
dc6f92b8 10911
c118dd06 10912 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 10913 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 10914 buf, error->request_code);
7a13e894 10915 x_connection_closed (display, buf1);
dc6f92b8
JB
10916}
10917
e99db5a1
RS
10918/* This is the first-level handler for X protocol errors.
10919 It calls x_error_quitter or x_error_catcher. */
7a13e894 10920
8922af5f 10921static int
e99db5a1 10922x_error_handler (display, error)
8922af5f 10923 Display *display;
e99db5a1 10924 XErrorEvent *error;
8922af5f 10925{
e99db5a1
RS
10926 if (! NILP (x_error_message_string))
10927 x_error_catcher (display, error);
10928 else
10929 x_error_quitter (display, error);
06a2c219 10930 return 0;
f9e24cb9 10931}
c118dd06 10932
e99db5a1
RS
10933/* This is the handler for X IO errors, always.
10934 It kills all frames on the display that we lost touch with.
10935 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 10936
c118dd06 10937static int
e99db5a1 10938x_io_error_quitter (display)
c118dd06 10939 Display *display;
c118dd06 10940{
e99db5a1 10941 char buf[256];
dc6f92b8 10942
e99db5a1
RS
10943 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10944 x_connection_closed (display, buf);
06a2c219 10945 return 0;
dc6f92b8 10946}
dc6f92b8 10947\f
f451eb13
JB
10948/* Changing the font of the frame. */
10949
76bcdf39
RS
10950/* Give frame F the font named FONTNAME as its default font, and
10951 return the full name of that font. FONTNAME may be a wildcard
10952 pattern; in that case, we choose some font that fits the pattern.
10953 The return value shows which font we chose. */
10954
b5cf7a0e 10955Lisp_Object
f676886a
JB
10956x_new_font (f, fontname)
10957 struct frame *f;
dc6f92b8
JB
10958 register char *fontname;
10959{
dc43ef94 10960 struct font_info *fontp
ee569018 10961 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 10962
dc43ef94
KH
10963 if (!fontp)
10964 return Qnil;
2224a5fc 10965
dc43ef94 10966 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 10967 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
10968 f->output_data.x->fontset = -1;
10969
b2cad826
KH
10970 /* Compute the scroll bar width in character columns. */
10971 if (f->scroll_bar_pixel_width > 0)
10972 {
7556890b 10973 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
10974 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10975 }
10976 else
4e61bddf
RS
10977 {
10978 int wid = FONT_WIDTH (f->output_data.x->font);
10979 f->scroll_bar_cols = (14 + wid - 1) / wid;
10980 }
b2cad826 10981
f676886a 10982 /* Now make the frame display the given font. */
c118dd06 10983 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 10984 {
7556890b
RS
10985 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10986 f->output_data.x->font->fid);
10987 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10988 f->output_data.x->font->fid);
10989 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10990 f->output_data.x->font->fid);
f676886a 10991
a27f9f86 10992 frame_update_line_height (f);
0134a210 10993 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 10994 }
a27f9f86
RS
10995 else
10996 /* If we are setting a new frame's font for the first time,
10997 there are no faces yet, so this font's height is the line height. */
7556890b 10998 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 10999
dc43ef94
KH
11000 return build_string (fontp->full_name);
11001}
11002
11003/* Give frame F the fontset named FONTSETNAME as its default font, and
11004 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11005 pattern; in that case, we choose some fontset that fits the pattern.
11006 The return value shows which fontset we chose. */
b5cf7a0e 11007
dc43ef94
KH
11008Lisp_Object
11009x_new_fontset (f, fontsetname)
11010 struct frame *f;
11011 char *fontsetname;
11012{
ee569018 11013 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11014 Lisp_Object result;
b5cf7a0e 11015
dc43ef94
KH
11016 if (fontset < 0)
11017 return Qnil;
b5cf7a0e 11018
2da424f1
KH
11019 if (f->output_data.x->fontset == fontset)
11020 /* This fontset is already set in frame F. There's nothing more
11021 to do. */
ee569018 11022 return fontset_name (fontset);
dc43ef94 11023
ee569018 11024 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11025
11026 if (!STRINGP (result))
11027 /* Can't load ASCII font. */
11028 return Qnil;
11029
11030 /* Since x_new_font doesn't update any fontset information, do it now. */
11031 f->output_data.x->fontset = fontset;
dc43ef94 11032
f5d11644
GM
11033#ifdef HAVE_X_I18N
11034 if (FRAME_XIC (f)
11035 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11036 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11037#endif
11038
dc43ef94 11039 return build_string (fontsetname);
dc6f92b8 11040}
f5d11644
GM
11041
11042\f
11043/***********************************************************************
11044 X Input Methods
11045 ***********************************************************************/
11046
11047#ifdef HAVE_X_I18N
11048
11049#ifdef HAVE_X11R6
11050
11051/* XIM destroy callback function, which is called whenever the
11052 connection to input method XIM dies. CLIENT_DATA contains a
11053 pointer to the x_display_info structure corresponding to XIM. */
11054
11055static void
11056xim_destroy_callback (xim, client_data, call_data)
11057 XIM xim;
11058 XPointer client_data;
11059 XPointer call_data;
11060{
11061 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11062 Lisp_Object frame, tail;
11063
11064 BLOCK_INPUT;
11065
11066 /* No need to call XDestroyIC.. */
11067 FOR_EACH_FRAME (tail, frame)
11068 {
11069 struct frame *f = XFRAME (frame);
11070 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11071 {
11072 FRAME_XIC (f) = NULL;
11073 if (FRAME_XIC_FONTSET (f))
11074 {
11075 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11076 FRAME_XIC_FONTSET (f) = NULL;
11077 }
11078 }
11079 }
11080
11081 /* No need to call XCloseIM. */
11082 dpyinfo->xim = NULL;
11083 XFree (dpyinfo->xim_styles);
11084 UNBLOCK_INPUT;
11085}
11086
11087#endif /* HAVE_X11R6 */
11088
11089/* Open the connection to the XIM server on display DPYINFO.
11090 RESOURCE_NAME is the resource name Emacs uses. */
11091
11092static void
11093xim_open_dpy (dpyinfo, resource_name)
11094 struct x_display_info *dpyinfo;
11095 char *resource_name;
11096{
11097 XIM xim;
11098
11099 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11100 dpyinfo->xim = xim;
11101
11102 if (xim)
11103 {
f5d11644
GM
11104#ifdef HAVE_X11R6
11105 XIMCallback destroy;
11106#endif
11107
11108 /* Get supported styles and XIM values. */
11109 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11110
11111#ifdef HAVE_X11R6
11112 destroy.callback = xim_destroy_callback;
11113 destroy.client_data = (XPointer)dpyinfo;
68642df6 11114 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11115 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11116#endif
11117 }
11118}
11119
11120
b9de836c 11121#ifdef HAVE_X11R6_XIM
f5d11644
GM
11122
11123struct xim_inst_t
11124{
11125 struct x_display_info *dpyinfo;
11126 char *resource_name;
11127};
11128
11129/* XIM instantiate callback function, which is called whenever an XIM
11130 server is available. DISPLAY is teh display of the XIM.
11131 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11132 when the callback was registered. */
11133
11134static void
11135xim_instantiate_callback (display, client_data, call_data)
11136 Display *display;
11137 XPointer client_data;
11138 XPointer call_data;
11139{
11140 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11141 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11142
11143 /* We don't support multiple XIM connections. */
11144 if (dpyinfo->xim)
11145 return;
11146
11147 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11148
11149 /* Create XIC for the existing frames on the same display, as long
11150 as they have no XIC. */
11151 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11152 {
11153 Lisp_Object tail, frame;
11154
11155 BLOCK_INPUT;
11156 FOR_EACH_FRAME (tail, frame)
11157 {
11158 struct frame *f = XFRAME (frame);
11159
11160 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11161 if (FRAME_XIC (f) == NULL)
11162 {
11163 create_frame_xic (f);
11164 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11165 xic_set_statusarea (f);
11166 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11167 {
11168 struct window *w = XWINDOW (f->selected_window);
11169 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11170 }
11171 }
11172 }
11173
11174 UNBLOCK_INPUT;
11175 }
11176}
11177
b9de836c 11178#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11179
11180
11181/* Open a connection to the XIM server on display DPYINFO.
11182 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11183 connection only at the first time. On X11R6, open the connection
11184 in the XIM instantiate callback function. */
11185
11186static void
11187xim_initialize (dpyinfo, resource_name)
11188 struct x_display_info *dpyinfo;
11189 char *resource_name;
11190{
b9de836c 11191#ifdef HAVE_X11R6_XIM
f5d11644
GM
11192 struct xim_inst_t *xim_inst;
11193 int len;
11194
11195 dpyinfo->xim = NULL;
11196 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11197 xim_inst->dpyinfo = dpyinfo;
11198 len = strlen (resource_name);
11199 xim_inst->resource_name = (char *) xmalloc (len + 1);
11200 bcopy (resource_name, xim_inst->resource_name, len + 1);
11201 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11202 resource_name, EMACS_CLASS,
11203 xim_instantiate_callback,
2ebb2f8b
DL
11204 /* Fixme: This is XPointer in
11205 XFree86 but (XPointer *) on
11206 Tru64, at least. */
11207 (XPointer) xim_inst);
b9de836c 11208#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11209 dpyinfo->xim = NULL;
11210 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11211#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11212}
11213
11214
11215/* Close the connection to the XIM server on display DPYINFO. */
11216
11217static void
11218xim_close_dpy (dpyinfo)
11219 struct x_display_info *dpyinfo;
11220{
b9de836c 11221#ifdef HAVE_X11R6_XIM
f5d11644
GM
11222 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11223 NULL, EMACS_CLASS,
11224 xim_instantiate_callback, NULL);
b9de836c 11225#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11226 XCloseIM (dpyinfo->xim);
11227 dpyinfo->xim = NULL;
11228 XFree (dpyinfo->xim_styles);
11229}
11230
b9de836c 11231#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11232
11233
dc6f92b8 11234\f
2e365682
RS
11235/* Calculate the absolute position in frame F
11236 from its current recorded position values and gravity. */
11237
dfcf069d 11238void
43bca5d5 11239x_calc_absolute_position (f)
f676886a 11240 struct frame *f;
dc6f92b8 11241{
06a2c219 11242 Window child;
6dba1858 11243 int win_x = 0, win_y = 0;
7556890b 11244 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11245 int this_window;
11246
9829ddba
RS
11247 /* We have nothing to do if the current position
11248 is already for the top-left corner. */
11249 if (! ((flags & XNegative) || (flags & YNegative)))
11250 return;
11251
c81412a0 11252#ifdef USE_X_TOOLKIT
7556890b 11253 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11254#else
11255 this_window = FRAME_X_WINDOW (f);
11256#endif
6dba1858
RS
11257
11258 /* Find the position of the outside upper-left corner of
9829ddba
RS
11259 the inner window, with respect to the outer window.
11260 But do this only if we will need the results. */
7556890b 11261 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11262 {
9829ddba
RS
11263 int count;
11264
6dba1858 11265 BLOCK_INPUT;
9829ddba
RS
11266 count = x_catch_errors (FRAME_X_DISPLAY (f));
11267 while (1)
11268 {
11269 x_clear_errors (FRAME_X_DISPLAY (f));
11270 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11271
11272 /* From-window, to-window. */
11273 this_window,
11274 f->output_data.x->parent_desc,
11275
11276 /* From-position, to-position. */
11277 0, 0, &win_x, &win_y,
11278
11279 /* Child of win. */
11280 &child);
11281 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11282 {
11283 Window newroot, newparent = 0xdeadbeef;
11284 Window *newchildren;
2ebb2f8b 11285 unsigned int nchildren;
9829ddba
RS
11286
11287 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11288 &newparent, &newchildren, &nchildren))
11289 break;
58769bee 11290
7c3c78a3 11291 XFree ((char *) newchildren);
6dba1858 11292
9829ddba
RS
11293 f->output_data.x->parent_desc = newparent;
11294 }
11295 else
11296 break;
11297 }
6dba1858 11298
9829ddba 11299 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11300 UNBLOCK_INPUT;
11301 }
11302
11303 /* Treat negative positions as relative to the leftmost bottommost
11304 position that fits on the screen. */
20f55f9a 11305 if (flags & XNegative)
7556890b 11306 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11307 - 2 * f->output_data.x->border_width - win_x
11308 - PIXEL_WIDTH (f)
11309 + f->output_data.x->left_pos);
dc6f92b8 11310
20f55f9a 11311 if (flags & YNegative)
06a2c219
GM
11312 {
11313 int menubar_height = 0;
11314
11315#ifdef USE_X_TOOLKIT
11316 if (f->output_data.x->menubar_widget)
11317 menubar_height
11318 = (f->output_data.x->menubar_widget->core.height
11319 + f->output_data.x->menubar_widget->core.border_width);
11320#endif
11321
11322 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11323 - 2 * f->output_data.x->border_width
11324 - win_y
11325 - PIXEL_HEIGHT (f)
11326 - menubar_height
11327 + f->output_data.x->top_pos);
11328 }
2e365682 11329
3a35ab44
RS
11330 /* The left_pos and top_pos
11331 are now relative to the top and left screen edges,
11332 so the flags should correspond. */
7556890b 11333 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11334}
11335
3a35ab44
RS
11336/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11337 to really change the position, and 0 when calling from
11338 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11339 position values). It is -1 when calling from x_set_frame_parameters,
11340 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11341
dfcf069d 11342void
dc05a16b 11343x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11344 struct frame *f;
dc6f92b8 11345 register int xoff, yoff;
dc05a16b 11346 int change_gravity;
dc6f92b8 11347{
4a4cbdd5
KH
11348 int modified_top, modified_left;
11349
aa3ff7c9 11350 if (change_gravity > 0)
3a35ab44 11351 {
7556890b
RS
11352 f->output_data.x->top_pos = yoff;
11353 f->output_data.x->left_pos = xoff;
11354 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11355 if (xoff < 0)
7556890b 11356 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11357 if (yoff < 0)
7556890b
RS
11358 f->output_data.x->size_hint_flags |= YNegative;
11359 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11360 }
43bca5d5 11361 x_calc_absolute_position (f);
dc6f92b8
JB
11362
11363 BLOCK_INPUT;
c32cdd9a 11364 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11365
7556890b
RS
11366 modified_left = f->output_data.x->left_pos;
11367 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11368#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11369 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11370 /* It is a mystery why we need to add the border_width here
11371 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11372 if (change_gravity != 0)
4a4cbdd5 11373 {
7556890b
RS
11374 modified_left += f->output_data.x->border_width;
11375 modified_top += f->output_data.x->border_width;
4a4cbdd5 11376 }
e73ec6fa 11377#endif
4a4cbdd5 11378
3afe33e7 11379#ifdef USE_X_TOOLKIT
7556890b 11380 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11381 modified_left, modified_top);
3afe33e7 11382#else /* not USE_X_TOOLKIT */
334208b7 11383 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11384 modified_left, modified_top);
3afe33e7 11385#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11386 UNBLOCK_INPUT;
11387}
11388
bc20ebbf
FP
11389/* Call this to change the size of frame F's x-window.
11390 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11391 for this size change and subsequent size changes.
11392 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11393
dfcf069d 11394void
bc20ebbf 11395x_set_window_size (f, change_gravity, cols, rows)
f676886a 11396 struct frame *f;
bc20ebbf 11397 int change_gravity;
b1c884c3 11398 int cols, rows;
dc6f92b8 11399{
06a2c219 11400#ifndef USE_X_TOOLKIT
dc6f92b8 11401 int pixelwidth, pixelheight;
06a2c219 11402#endif
dc6f92b8 11403
80fd1fe2 11404 BLOCK_INPUT;
aee9a898
RS
11405
11406#ifdef USE_X_TOOLKIT
3a20653d
RS
11407 {
11408 /* The x and y position of the widget is clobbered by the
11409 call to XtSetValues within EmacsFrameSetCharSize.
11410 This is a real kludge, but I don't understand Xt so I can't
11411 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11412 int xpos = f->output_data.x->widget->core.x;
11413 int ypos = f->output_data.x->widget->core.y;
11414 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11415 f->output_data.x->widget->core.x = xpos;
11416 f->output_data.x->widget->core.y = ypos;
3a20653d 11417 }
80fd1fe2
FP
11418
11419#else /* not USE_X_TOOLKIT */
11420
b1c884c3 11421 check_frame_size (f, &rows, &cols);
7556890b 11422 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11423 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11424 ? 0
11425 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11426 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11427 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11428 f->output_data.x->flags_areas_extra
110859fc 11429 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11430 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11431 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11432
7556890b 11433 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11434 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11435
334208b7
RS
11436 XSync (FRAME_X_DISPLAY (f), False);
11437 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11438 pixelwidth, pixelheight);
b1c884c3
JB
11439
11440 /* Now, strictly speaking, we can't be sure that this is accurate,
11441 but the window manager will get around to dealing with the size
11442 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11443 ConfigureNotify event gets here.
11444
11445 We could just not bother storing any of this information here,
11446 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11447 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11448 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11449 point in the future when the ConfigureNotify event arrives.
11450
11451 We pass 1 for DELAY since we can't run Lisp code inside of
11452 a BLOCK_INPUT. */
7d1e984f 11453 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11454 PIXEL_WIDTH (f) = pixelwidth;
11455 PIXEL_HEIGHT (f) = pixelheight;
11456
aee9a898
RS
11457 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11458 receive in the ConfigureNotify event; if we get what we asked
11459 for, then the event won't cause the screen to become garbaged, so
11460 we have to make sure to do it here. */
11461 SET_FRAME_GARBAGED (f);
11462
11463 XFlush (FRAME_X_DISPLAY (f));
11464
11465#endif /* not USE_X_TOOLKIT */
11466
4d73d038 11467 /* If cursor was outside the new size, mark it as off. */
06a2c219 11468 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11469
aee9a898
RS
11470 /* Clear out any recollection of where the mouse highlighting was,
11471 since it might be in a place that's outside the new frame size.
11472 Actually checking whether it is outside is a pain in the neck,
11473 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11474 cancel_mouse_face (f);
dbc4e1c1 11475
dc6f92b8
JB
11476 UNBLOCK_INPUT;
11477}
dc6f92b8 11478\f
d047c4eb 11479/* Mouse warping. */
dc6f92b8 11480
9b378208 11481void
f676886a
JB
11482x_set_mouse_position (f, x, y)
11483 struct frame *f;
dc6f92b8
JB
11484 int x, y;
11485{
11486 int pix_x, pix_y;
11487
7556890b
RS
11488 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11489 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11490
11491 if (pix_x < 0) pix_x = 0;
11492 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11493
11494 if (pix_y < 0) pix_y = 0;
11495 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11496
11497 BLOCK_INPUT;
dc6f92b8 11498
334208b7
RS
11499 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11500 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11501 UNBLOCK_INPUT;
11502}
11503
9b378208
RS
11504/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11505
11506void
11507x_set_mouse_pixel_position (f, pix_x, pix_y)
11508 struct frame *f;
11509 int pix_x, pix_y;
11510{
11511 BLOCK_INPUT;
11512
334208b7
RS
11513 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11514 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11515 UNBLOCK_INPUT;
11516}
d047c4eb
KH
11517\f
11518/* focus shifting, raising and lowering. */
9b378208 11519
dfcf069d 11520void
f676886a
JB
11521x_focus_on_frame (f)
11522 struct frame *f;
dc6f92b8 11523{
1fb20991 11524#if 0 /* This proves to be unpleasant. */
f676886a 11525 x_raise_frame (f);
1fb20991 11526#endif
6d4238f3
JB
11527#if 0
11528 /* I don't think that the ICCCM allows programs to do things like this
11529 without the interaction of the window manager. Whatever you end up
f676886a 11530 doing with this code, do it to x_unfocus_frame too. */
334208b7 11531 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11532 RevertToPointerRoot, CurrentTime);
c118dd06 11533#endif /* ! 0 */
dc6f92b8
JB
11534}
11535
dfcf069d 11536void
f676886a
JB
11537x_unfocus_frame (f)
11538 struct frame *f;
dc6f92b8 11539{
6d4238f3 11540#if 0
f676886a 11541 /* Look at the remarks in x_focus_on_frame. */
0f941935 11542 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11543 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11544 RevertToPointerRoot, CurrentTime);
c118dd06 11545#endif /* ! 0 */
dc6f92b8
JB
11546}
11547
f676886a 11548/* Raise frame F. */
dc6f92b8 11549
dfcf069d 11550void
f676886a
JB
11551x_raise_frame (f)
11552 struct frame *f;
dc6f92b8 11553{
3a88c238 11554 if (f->async_visible)
dc6f92b8
JB
11555 {
11556 BLOCK_INPUT;
3afe33e7 11557#ifdef USE_X_TOOLKIT
7556890b 11558 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11559#else /* not USE_X_TOOLKIT */
334208b7 11560 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11561#endif /* not USE_X_TOOLKIT */
334208b7 11562 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11563 UNBLOCK_INPUT;
11564 }
11565}
11566
f676886a 11567/* Lower frame F. */
dc6f92b8 11568
dfcf069d 11569void
f676886a
JB
11570x_lower_frame (f)
11571 struct frame *f;
dc6f92b8 11572{
3a88c238 11573 if (f->async_visible)
dc6f92b8
JB
11574 {
11575 BLOCK_INPUT;
3afe33e7 11576#ifdef USE_X_TOOLKIT
7556890b 11577 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11578#else /* not USE_X_TOOLKIT */
334208b7 11579 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11580#endif /* not USE_X_TOOLKIT */
334208b7 11581 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11582 UNBLOCK_INPUT;
11583 }
11584}
11585
dbc4e1c1 11586static void
6b0442dc 11587XTframe_raise_lower (f, raise_flag)
dbc4e1c1 11588 FRAME_PTR f;
6b0442dc 11589 int raise_flag;
dbc4e1c1 11590{
6b0442dc 11591 if (raise_flag)
dbc4e1c1
JB
11592 x_raise_frame (f);
11593 else
11594 x_lower_frame (f);
11595}
d047c4eb
KH
11596\f
11597/* Change of visibility. */
dc6f92b8 11598
9382638d
KH
11599/* This tries to wait until the frame is really visible.
11600 However, if the window manager asks the user where to position
11601 the frame, this will return before the user finishes doing that.
11602 The frame will not actually be visible at that time,
11603 but it will become visible later when the window manager
11604 finishes with it. */
11605
dfcf069d 11606void
f676886a
JB
11607x_make_frame_visible (f)
11608 struct frame *f;
dc6f92b8 11609{
990ba854 11610 Lisp_Object type;
1aa6072f 11611 int original_top, original_left;
dc6f92b8 11612
dc6f92b8 11613 BLOCK_INPUT;
dc6f92b8 11614
990ba854
RS
11615 type = x_icon_type (f);
11616 if (!NILP (type))
11617 x_bitmap_icon (f, type);
bdcd49ba 11618
f676886a 11619 if (! FRAME_VISIBLE_P (f))
90e65f07 11620 {
1aa6072f
RS
11621 /* We test FRAME_GARBAGED_P here to make sure we don't
11622 call x_set_offset a second time
11623 if we get to x_make_frame_visible a second time
11624 before the window gets really visible. */
11625 if (! FRAME_ICONIFIED_P (f)
11626 && ! f->output_data.x->asked_for_visible)
11627 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11628
11629 f->output_data.x->asked_for_visible = 1;
11630
90e65f07 11631 if (! EQ (Vx_no_window_manager, Qt))
f676886a 11632 x_wm_set_window_state (f, NormalState);
3afe33e7 11633#ifdef USE_X_TOOLKIT
d7a38a2e 11634 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11635 XtMapWidget (f->output_data.x->widget);
3afe33e7 11636#else /* not USE_X_TOOLKIT */
7f9c7f94 11637 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11638#endif /* not USE_X_TOOLKIT */
0134a210
RS
11639#if 0 /* This seems to bring back scroll bars in the wrong places
11640 if the window configuration has changed. They seem
11641 to come back ok without this. */
ab648270 11642 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 11643 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 11644#endif
90e65f07 11645 }
dc6f92b8 11646
334208b7 11647 XFlush (FRAME_X_DISPLAY (f));
90e65f07 11648
0dacf791
RS
11649 /* Synchronize to ensure Emacs knows the frame is visible
11650 before we do anything else. We do this loop with input not blocked
11651 so that incoming events are handled. */
11652 {
11653 Lisp_Object frame;
12ce2351 11654 int count;
28c01ffe
RS
11655 /* This must be before UNBLOCK_INPUT
11656 since events that arrive in response to the actions above
11657 will set it when they are handled. */
11658 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
11659
11660 original_left = f->output_data.x->left_pos;
11661 original_top = f->output_data.x->top_pos;
c0a04927
RS
11662
11663 /* This must come after we set COUNT. */
11664 UNBLOCK_INPUT;
11665
2745e6c4 11666 /* We unblock here so that arriving X events are processed. */
1aa6072f 11667
dcb07ae9
RS
11668 /* Now move the window back to where it was "supposed to be".
11669 But don't do it if the gravity is negative.
11670 When the gravity is negative, this uses a position
28c01ffe
RS
11671 that is 3 pixels too low. Perhaps that's really the border width.
11672
11673 Don't do this if the window has never been visible before,
11674 because the window manager may choose the position
11675 and we don't want to override it. */
1aa6072f 11676
4d3f5d9a 11677 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 11678 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 11679 && previously_visible)
1aa6072f 11680 {
2745e6c4
RS
11681 Drawable rootw;
11682 int x, y;
11683 unsigned int width, height, border, depth;
06a2c219 11684
1aa6072f 11685 BLOCK_INPUT;
9829ddba 11686
06a2c219
GM
11687 /* On some window managers (such as FVWM) moving an existing
11688 window, even to the same place, causes the window manager
11689 to introduce an offset. This can cause the window to move
11690 to an unexpected location. Check the geometry (a little
11691 slow here) and then verify that the window is in the right
11692 place. If the window is not in the right place, move it
11693 there, and take the potential window manager hit. */
2745e6c4
RS
11694 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11695 &rootw, &x, &y, &width, &height, &border, &depth);
11696
11697 if (original_left != x || original_top != y)
11698 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11699 original_left, original_top);
11700
1aa6072f
RS
11701 UNBLOCK_INPUT;
11702 }
9829ddba 11703
e0c1aef2 11704 XSETFRAME (frame, f);
c0a04927 11705
12ce2351
GM
11706 /* Wait until the frame is visible. Process X events until a
11707 MapNotify event has been seen, or until we think we won't get a
11708 MapNotify at all.. */
11709 for (count = input_signal_count + 10;
11710 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 11711 {
12ce2351 11712 /* Force processing of queued events. */
334208b7 11713 x_sync (f);
12ce2351
GM
11714
11715 /* Machines that do polling rather than SIGIO have been
11716 observed to go into a busy-wait here. So we'll fake an
11717 alarm signal to let the handler know that there's something
11718 to be read. We used to raise a real alarm, but it seems
11719 that the handler isn't always enabled here. This is
11720 probably a bug. */
8b2f8d4e 11721 if (input_polling_used ())
3b2fa4e6 11722 {
12ce2351
GM
11723 /* It could be confusing if a real alarm arrives while
11724 processing the fake one. Turn it off and let the
11725 handler reset it. */
3e71d8f2 11726 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
11727 int old_poll_suppress_count = poll_suppress_count;
11728 poll_suppress_count = 1;
11729 poll_for_input_1 ();
11730 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 11731 }
12ce2351
GM
11732
11733 /* See if a MapNotify event has been processed. */
11734 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 11735 }
0dacf791 11736 }
dc6f92b8
JB
11737}
11738
06a2c219 11739/* Change from mapped state to withdrawn state. */
dc6f92b8 11740
d047c4eb
KH
11741/* Make the frame visible (mapped and not iconified). */
11742
dfcf069d 11743void
f676886a
JB
11744x_make_frame_invisible (f)
11745 struct frame *f;
dc6f92b8 11746{
546e6d5b
RS
11747 Window window;
11748
11749#ifdef USE_X_TOOLKIT
11750 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11751 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11752#else /* not USE_X_TOOLKIT */
11753 window = FRAME_X_WINDOW (f);
11754#endif /* not USE_X_TOOLKIT */
dc6f92b8 11755
9319ae23 11756 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11757 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11758 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11759
5627c40e 11760#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 11761 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 11762 return;
5627c40e 11763#endif
dc6f92b8
JB
11764
11765 BLOCK_INPUT;
c118dd06 11766
af31d76f
RS
11767 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11768 that the current position of the window is user-specified, rather than
11769 program-specified, so that when the window is mapped again, it will be
11770 placed at the same location, without forcing the user to position it
11771 by hand again (they have already done that once for this window.) */
c32cdd9a 11772 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 11773
c118dd06
JB
11774#ifdef HAVE_X11R4
11775
334208b7
RS
11776 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11777 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
11778 {
11779 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11780 error ("Can't notify window manager of window withdrawal");
c118dd06 11781 }
c118dd06 11782#else /* ! defined (HAVE_X11R4) */
16bd92ea 11783
c118dd06 11784 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
11785 if (! EQ (Vx_no_window_manager, Qt))
11786 {
16bd92ea 11787 XEvent unmap;
dc6f92b8 11788
16bd92ea 11789 unmap.xunmap.type = UnmapNotify;
546e6d5b 11790 unmap.xunmap.window = window;
334208b7 11791 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 11792 unmap.xunmap.from_configure = False;
334208b7
RS
11793 if (! XSendEvent (FRAME_X_DISPLAY (f),
11794 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 11795 False,
06a2c219 11796 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
11797 &unmap))
11798 {
11799 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11800 error ("Can't notify window manager of withdrawal");
16bd92ea 11801 }
dc6f92b8
JB
11802 }
11803
16bd92ea 11804 /* Unmap the window ourselves. Cheeky! */
334208b7 11805 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 11806#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 11807
5627c40e
RS
11808 /* We can't distinguish this from iconification
11809 just by the event that we get from the server.
11810 So we can't win using the usual strategy of letting
11811 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11812 and synchronize with the server to make sure we agree. */
11813 f->visible = 0;
11814 FRAME_ICONIFIED_P (f) = 0;
11815 f->async_visible = 0;
11816 f->async_iconified = 0;
11817
334208b7 11818 x_sync (f);
5627c40e 11819
dc6f92b8
JB
11820 UNBLOCK_INPUT;
11821}
11822
06a2c219 11823/* Change window state from mapped to iconified. */
dc6f92b8 11824
dfcf069d 11825void
f676886a
JB
11826x_iconify_frame (f)
11827 struct frame *f;
dc6f92b8 11828{
3afe33e7 11829 int result;
990ba854 11830 Lisp_Object type;
dc6f92b8 11831
9319ae23 11832 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11833 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11834 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11835
3a88c238 11836 if (f->async_iconified)
dc6f92b8
JB
11837 return;
11838
3afe33e7 11839 BLOCK_INPUT;
546e6d5b 11840
9af3143a
RS
11841 FRAME_SAMPLE_VISIBILITY (f);
11842
990ba854
RS
11843 type = x_icon_type (f);
11844 if (!NILP (type))
11845 x_bitmap_icon (f, type);
bdcd49ba
RS
11846
11847#ifdef USE_X_TOOLKIT
11848
546e6d5b
RS
11849 if (! FRAME_VISIBLE_P (f))
11850 {
11851 if (! EQ (Vx_no_window_manager, Qt))
11852 x_wm_set_window_state (f, IconicState);
11853 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11854 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
11855 /* The server won't give us any event to indicate
11856 that an invisible frame was changed to an icon,
11857 so we have to record it here. */
11858 f->iconified = 1;
1e6bc770 11859 f->visible = 1;
9cf30a30 11860 f->async_iconified = 1;
1e6bc770 11861 f->async_visible = 0;
546e6d5b
RS
11862 UNBLOCK_INPUT;
11863 return;
11864 }
11865
334208b7 11866 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 11867 XtWindow (f->output_data.x->widget),
334208b7 11868 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
11869 UNBLOCK_INPUT;
11870
11871 if (!result)
546e6d5b 11872 error ("Can't notify window manager of iconification");
3afe33e7
RS
11873
11874 f->async_iconified = 1;
1e6bc770
RS
11875 f->async_visible = 0;
11876
8c002a25
KH
11877
11878 BLOCK_INPUT;
334208b7 11879 XFlush (FRAME_X_DISPLAY (f));
8c002a25 11880 UNBLOCK_INPUT;
3afe33e7
RS
11881#else /* not USE_X_TOOLKIT */
11882
fd13dbb2
RS
11883 /* Make sure the X server knows where the window should be positioned,
11884 in case the user deiconifies with the window manager. */
11885 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 11886 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 11887
16bd92ea
JB
11888 /* Since we don't know which revision of X we're running, we'll use both
11889 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11890
11891 /* X11R4: send a ClientMessage to the window manager using the
11892 WM_CHANGE_STATE type. */
11893 {
11894 XEvent message;
58769bee 11895
c118dd06 11896 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 11897 message.xclient.type = ClientMessage;
334208b7 11898 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
11899 message.xclient.format = 32;
11900 message.xclient.data.l[0] = IconicState;
11901
334208b7
RS
11902 if (! XSendEvent (FRAME_X_DISPLAY (f),
11903 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
11904 False,
11905 SubstructureRedirectMask | SubstructureNotifyMask,
11906 &message))
dc6f92b8
JB
11907 {
11908 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11909 error ("Can't notify window manager of iconification");
dc6f92b8 11910 }
16bd92ea 11911 }
dc6f92b8 11912
58769bee 11913 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
11914 IconicState. */
11915 x_wm_set_window_state (f, IconicState);
dc6f92b8 11916
a9c00105
RS
11917 if (!FRAME_VISIBLE_P (f))
11918 {
11919 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 11920 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
11921 }
11922
3a88c238 11923 f->async_iconified = 1;
1e6bc770 11924 f->async_visible = 0;
dc6f92b8 11925
334208b7 11926 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 11927 UNBLOCK_INPUT;
8c002a25 11928#endif /* not USE_X_TOOLKIT */
dc6f92b8 11929}
d047c4eb 11930\f
c0ff3fab 11931/* Destroy the X window of frame F. */
dc6f92b8 11932
dfcf069d 11933void
c0ff3fab 11934x_destroy_window (f)
f676886a 11935 struct frame *f;
dc6f92b8 11936{
7f9c7f94
RS
11937 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11938
dc6f92b8 11939 BLOCK_INPUT;
c0ff3fab 11940
6186a4a0
RS
11941 /* If a display connection is dead, don't try sending more
11942 commands to the X server. */
11943 if (dpyinfo->display != 0)
11944 {
11945 if (f->output_data.x->icon_desc != 0)
11946 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 11947#ifdef HAVE_X_I18N
f5d11644
GM
11948 if (FRAME_XIC (f))
11949 free_frame_xic (f);
31f41daf 11950#endif
6186a4a0 11951 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 11952#ifdef USE_X_TOOLKIT
06a2c219
GM
11953 if (f->output_data.x->widget)
11954 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 11955 free_frame_menubar (f);
3afe33e7
RS
11956#endif /* USE_X_TOOLKIT */
11957
3e71d8f2
GM
11958 unload_color (f, f->output_data.x->foreground_pixel);
11959 unload_color (f, f->output_data.x->background_pixel);
11960 unload_color (f, f->output_data.x->cursor_pixel);
11961 unload_color (f, f->output_data.x->cursor_foreground_pixel);
11962 unload_color (f, f->output_data.x->border_pixel);
11963 unload_color (f, f->output_data.x->mouse_pixel);
11964 if (f->output_data.x->scroll_bar_background_pixel != -1)
11965 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
11966 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
11967 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
11968 if (f->output_data.x->white_relief.allocated_p)
11969 unload_color (f, f->output_data.x->white_relief.pixel);
11970 if (f->output_data.x->black_relief.allocated_p)
11971 unload_color (f, f->output_data.x->black_relief.pixel);
11972
6186a4a0
RS
11973 free_frame_faces (f);
11974 XFlush (FRAME_X_DISPLAY (f));
11975 }
dc6f92b8 11976
df89d8a4 11977 if (f->output_data.x->saved_menu_event)
06a2c219 11978 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 11979
7556890b
RS
11980 xfree (f->output_data.x);
11981 f->output_data.x = 0;
0f941935
KH
11982 if (f == dpyinfo->x_focus_frame)
11983 dpyinfo->x_focus_frame = 0;
11984 if (f == dpyinfo->x_focus_event_frame)
11985 dpyinfo->x_focus_event_frame = 0;
11986 if (f == dpyinfo->x_highlight_frame)
11987 dpyinfo->x_highlight_frame = 0;
c0ff3fab 11988
7f9c7f94
RS
11989 dpyinfo->reference_count--;
11990
11991 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 11992 {
7f9c7f94
RS
11993 dpyinfo->mouse_face_beg_row
11994 = dpyinfo->mouse_face_beg_col = -1;
11995 dpyinfo->mouse_face_end_row
11996 = dpyinfo->mouse_face_end_col = -1;
11997 dpyinfo->mouse_face_window = Qnil;
21323706
RS
11998 dpyinfo->mouse_face_deferred_gc = 0;
11999 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12000 }
0134a210 12001
c0ff3fab 12002 UNBLOCK_INPUT;
dc6f92b8
JB
12003}
12004\f
f451eb13
JB
12005/* Setting window manager hints. */
12006
af31d76f
RS
12007/* Set the normal size hints for the window manager, for frame F.
12008 FLAGS is the flags word to use--or 0 meaning preserve the flags
12009 that the window now has.
12010 If USER_POSITION is nonzero, we set the USPosition
12011 flag (this is useful when FLAGS is 0). */
6dba1858 12012
dfcf069d 12013void
af31d76f 12014x_wm_set_size_hint (f, flags, user_position)
f676886a 12015 struct frame *f;
af31d76f
RS
12016 long flags;
12017 int user_position;
dc6f92b8
JB
12018{
12019 XSizeHints size_hints;
3afe33e7
RS
12020
12021#ifdef USE_X_TOOLKIT
7e4f2521
FP
12022 Arg al[2];
12023 int ac = 0;
12024 Dimension widget_width, widget_height;
7556890b 12025 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12026#else /* not USE_X_TOOLKIT */
c118dd06 12027 Window window = FRAME_X_WINDOW (f);
3afe33e7 12028#endif /* not USE_X_TOOLKIT */
dc6f92b8 12029
b72a58fd
RS
12030 /* Setting PMaxSize caused various problems. */
12031 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12032
7556890b
RS
12033 size_hints.x = f->output_data.x->left_pos;
12034 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12035
7e4f2521
FP
12036#ifdef USE_X_TOOLKIT
12037 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12038 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12039 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12040 size_hints.height = widget_height;
12041 size_hints.width = widget_width;
12042#else /* not USE_X_TOOLKIT */
f676886a
JB
12043 size_hints.height = PIXEL_HEIGHT (f);
12044 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12045#endif /* not USE_X_TOOLKIT */
7553a6b7 12046
7556890b
RS
12047 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12048 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12049 size_hints.max_width
12050 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12051 size_hints.max_height
12052 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12053
d067ea8b
KH
12054 /* Calculate the base and minimum sizes.
12055
12056 (When we use the X toolkit, we don't do it here.
12057 Instead we copy the values that the widgets are using, below.) */
12058#ifndef USE_X_TOOLKIT
b1c884c3 12059 {
b0342f17 12060 int base_width, base_height;
0134a210 12061 int min_rows = 0, min_cols = 0;
b0342f17 12062
f451eb13
JB
12063 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12064 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12065
0134a210 12066 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12067
0134a210
RS
12068 /* The window manager uses the base width hints to calculate the
12069 current number of rows and columns in the frame while
12070 resizing; min_width and min_height aren't useful for this
12071 purpose, since they might not give the dimensions for a
12072 zero-row, zero-column frame.
58769bee 12073
0134a210
RS
12074 We use the base_width and base_height members if we have
12075 them; otherwise, we set the min_width and min_height members
12076 to the size for a zero x zero frame. */
b0342f17
JB
12077
12078#ifdef HAVE_X11R4
0134a210
RS
12079 size_hints.flags |= PBaseSize;
12080 size_hints.base_width = base_width;
12081 size_hints.base_height = base_height;
12082 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12083 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12084#else
0134a210
RS
12085 size_hints.min_width = base_width;
12086 size_hints.min_height = base_height;
b0342f17 12087#endif
b1c884c3 12088 }
dc6f92b8 12089
d067ea8b 12090 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12091 if (flags)
dc6f92b8 12092 {
d067ea8b
KH
12093 size_hints.flags |= flags;
12094 goto no_read;
12095 }
12096#endif /* not USE_X_TOOLKIT */
12097
12098 {
12099 XSizeHints hints; /* Sometimes I hate X Windows... */
12100 long supplied_return;
12101 int value;
af31d76f
RS
12102
12103#ifdef HAVE_X11R4
d067ea8b
KH
12104 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12105 &supplied_return);
af31d76f 12106#else
d067ea8b 12107 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12108#endif
58769bee 12109
d067ea8b
KH
12110#ifdef USE_X_TOOLKIT
12111 size_hints.base_height = hints.base_height;
12112 size_hints.base_width = hints.base_width;
12113 size_hints.min_height = hints.min_height;
12114 size_hints.min_width = hints.min_width;
12115#endif
12116
12117 if (flags)
12118 size_hints.flags |= flags;
12119 else
12120 {
12121 if (value == 0)
12122 hints.flags = 0;
12123 if (hints.flags & PSize)
12124 size_hints.flags |= PSize;
12125 if (hints.flags & PPosition)
12126 size_hints.flags |= PPosition;
12127 if (hints.flags & USPosition)
12128 size_hints.flags |= USPosition;
12129 if (hints.flags & USSize)
12130 size_hints.flags |= USSize;
12131 }
12132 }
12133
06a2c219 12134#ifndef USE_X_TOOLKIT
d067ea8b 12135 no_read:
06a2c219 12136#endif
0134a210 12137
af31d76f 12138#ifdef PWinGravity
7556890b 12139 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12140 size_hints.flags |= PWinGravity;
dc05a16b 12141
af31d76f 12142 if (user_position)
6dba1858 12143 {
af31d76f
RS
12144 size_hints.flags &= ~ PPosition;
12145 size_hints.flags |= USPosition;
6dba1858 12146 }
2554751d 12147#endif /* PWinGravity */
6dba1858 12148
b0342f17 12149#ifdef HAVE_X11R4
334208b7 12150 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12151#else
334208b7 12152 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12153#endif
dc6f92b8
JB
12154}
12155
12156/* Used for IconicState or NormalState */
06a2c219 12157
dfcf069d 12158void
f676886a
JB
12159x_wm_set_window_state (f, state)
12160 struct frame *f;
dc6f92b8
JB
12161 int state;
12162{
3afe33e7 12163#ifdef USE_X_TOOLKIT
546e6d5b
RS
12164 Arg al[1];
12165
12166 XtSetArg (al[0], XtNinitialState, state);
7556890b 12167 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12168#else /* not USE_X_TOOLKIT */
c118dd06 12169 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12170
7556890b
RS
12171 f->output_data.x->wm_hints.flags |= StateHint;
12172 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12173
7556890b 12174 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12175#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12176}
12177
dfcf069d 12178void
7f2ae036 12179x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12180 struct frame *f;
7f2ae036 12181 int pixmap_id;
dc6f92b8 12182{
d2bd6bc4
RS
12183 Pixmap icon_pixmap;
12184
06a2c219 12185#ifndef USE_X_TOOLKIT
c118dd06 12186 Window window = FRAME_X_WINDOW (f);
75231bad 12187#endif
dc6f92b8 12188
7f2ae036 12189 if (pixmap_id > 0)
dbc4e1c1 12190 {
d2bd6bc4 12191 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12192 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12193 }
12194 else
68568555
RS
12195 {
12196 /* It seems there is no way to turn off use of an icon pixmap.
12197 The following line does it, only if no icon has yet been created,
12198 for some window managers. But with mwm it crashes.
12199 Some people say it should clear the IconPixmapHint bit in this case,
12200 but that doesn't work, and the X consortium said it isn't the
12201 right thing at all. Since there is no way to win,
12202 best to explicitly give up. */
12203#if 0
12204 f->output_data.x->wm_hints.icon_pixmap = None;
12205#else
12206 return;
12207#endif
12208 }
b1c884c3 12209
d2bd6bc4
RS
12210#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12211
12212 {
12213 Arg al[1];
12214 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12215 XtSetValues (f->output_data.x->widget, al, 1);
12216 }
12217
12218#else /* not USE_X_TOOLKIT */
12219
7556890b
RS
12220 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12221 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12222
12223#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12224}
12225
dfcf069d 12226void
f676886a
JB
12227x_wm_set_icon_position (f, icon_x, icon_y)
12228 struct frame *f;
dc6f92b8
JB
12229 int icon_x, icon_y;
12230{
75231bad 12231#ifdef USE_X_TOOLKIT
7556890b 12232 Window window = XtWindow (f->output_data.x->widget);
75231bad 12233#else
c118dd06 12234 Window window = FRAME_X_WINDOW (f);
75231bad 12235#endif
dc6f92b8 12236
7556890b
RS
12237 f->output_data.x->wm_hints.flags |= IconPositionHint;
12238 f->output_data.x->wm_hints.icon_x = icon_x;
12239 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12240
7556890b 12241 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12242}
12243
12244\f
06a2c219
GM
12245/***********************************************************************
12246 Fonts
12247 ***********************************************************************/
dc43ef94
KH
12248
12249/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12250
dc43ef94
KH
12251struct font_info *
12252x_get_font_info (f, font_idx)
12253 FRAME_PTR f;
12254 int font_idx;
12255{
12256 return (FRAME_X_FONT_TABLE (f) + font_idx);
12257}
12258
12259
12260/* Return a list of names of available fonts matching PATTERN on frame
12261 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12262 to be listed. Frame F NULL means we have not yet created any
12263 frame on X, and consult the first display in x_display_list.
12264 MAXNAMES sets a limit on how many fonts to match. */
12265
12266Lisp_Object
12267x_list_fonts (f, pattern, size, maxnames)
12268 FRAME_PTR f;
12269 Lisp_Object pattern;
12270 int size;
12271 int maxnames;
12272{
06a2c219
GM
12273 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12274 Lisp_Object tem, second_best;
dc43ef94 12275 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12276 int try_XLoadQueryFont = 0;
53ca4657 12277 int count;
dc43ef94 12278
6b0efe73 12279 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12280 if (NILP (patterns))
12281 patterns = Fcons (pattern, Qnil);
81ba44e5 12282
09c6077f
KH
12283 if (maxnames == 1 && !size)
12284 /* We can return any single font matching PATTERN. */
12285 try_XLoadQueryFont = 1;
9a32686f 12286
8e713be6 12287 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12288 {
dc43ef94 12289 int num_fonts;
3e71d8f2 12290 char **names = NULL;
dc43ef94 12291
8e713be6 12292 pattern = XCAR (patterns);
536f4067
RS
12293 /* See if we cached the result for this particular query.
12294 The cache is an alist of the form:
12295 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12296 */
8e713be6 12297 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12298 key = Fcons (pattern, make_number (maxnames)),
12299 !NILP (list = Fassoc (key, tem))))
12300 {
12301 list = Fcdr_safe (list);
12302 /* We have a cashed list. Don't have to get the list again. */
12303 goto label_cached;
12304 }
12305
12306 /* At first, put PATTERN in the cache. */
09c6077f 12307
dc43ef94 12308 BLOCK_INPUT;
17d85edc
KH
12309 count = x_catch_errors (dpy);
12310
09c6077f
KH
12311 if (try_XLoadQueryFont)
12312 {
12313 XFontStruct *font;
12314 unsigned long value;
12315
12316 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12317 if (x_had_errors_p (dpy))
12318 {
12319 /* This error is perhaps due to insufficient memory on X
12320 server. Let's just ignore it. */
12321 font = NULL;
12322 x_clear_errors (dpy);
12323 }
12324
09c6077f
KH
12325 if (font
12326 && XGetFontProperty (font, XA_FONT, &value))
12327 {
12328 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12329 int len = strlen (name);
01c752b5 12330 char *tmp;
09c6077f 12331
6f6512e8
KH
12332 /* If DXPC (a Differential X Protocol Compressor)
12333 Ver.3.7 is running, XGetAtomName will return null
12334 string. We must avoid such a name. */
12335 if (len == 0)
12336 try_XLoadQueryFont = 0;
12337 else
12338 {
12339 num_fonts = 1;
12340 names = (char **) alloca (sizeof (char *));
12341 /* Some systems only allow alloca assigned to a
12342 simple var. */
12343 tmp = (char *) alloca (len + 1); names[0] = tmp;
12344 bcopy (name, names[0], len + 1);
12345 XFree (name);
12346 }
09c6077f
KH
12347 }
12348 else
12349 try_XLoadQueryFont = 0;
a083fd23
RS
12350
12351 if (font)
12352 XFreeFont (dpy, font);
09c6077f
KH
12353 }
12354
12355 if (!try_XLoadQueryFont)
17d85edc
KH
12356 {
12357 /* We try at least 10 fonts because XListFonts will return
12358 auto-scaled fonts at the head. */
12359 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12360 &num_fonts);
12361 if (x_had_errors_p (dpy))
12362 {
12363 /* This error is perhaps due to insufficient memory on X
12364 server. Let's just ignore it. */
12365 names = NULL;
12366 x_clear_errors (dpy);
12367 }
12368 }
12369
12370 x_uncatch_errors (dpy, count);
dc43ef94
KH
12371 UNBLOCK_INPUT;
12372
12373 if (names)
12374 {
12375 int i;
dc43ef94
KH
12376
12377 /* Make a list of all the fonts we got back.
12378 Store that in the font cache for the display. */
12379 for (i = 0; i < num_fonts; i++)
12380 {
06a2c219 12381 int width = 0;
dc43ef94 12382 char *p = names[i];
06a2c219
GM
12383 int average_width = -1, dashes = 0;
12384
dc43ef94 12385 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12386 14 dashes, and the field value following 12th dash
12387 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12388 is usually too ugly to be used for editing. Let's
12389 ignore it. */
dc43ef94
KH
12390 while (*p)
12391 if (*p++ == '-')
12392 {
12393 dashes++;
12394 if (dashes == 7) /* PIXEL_SIZE field */
12395 width = atoi (p);
12396 else if (dashes == 12) /* AVERAGE_WIDTH field */
12397 average_width = atoi (p);
12398 }
12399 if (dashes < 14 || average_width != 0)
12400 {
12401 tem = build_string (names[i]);
12402 if (NILP (Fassoc (tem, list)))
12403 {
12404 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12405 && ((fast_c_string_match_ignore_case
12406 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12407 >= 0))
12408 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12409 width of this font. */
dc43ef94
KH
12410 list = Fcons (Fcons (tem, make_number (width)), list);
12411 else
12412 /* For the moment, width is not known. */
12413 list = Fcons (Fcons (tem, Qnil), list);
12414 }
12415 }
12416 }
09c6077f
KH
12417 if (!try_XLoadQueryFont)
12418 XFreeFontNames (names);
dc43ef94
KH
12419 }
12420
b5210ea7 12421 /* Now store the result in the cache. */
dc43ef94 12422 if (f != NULL)
8e713be6 12423 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12424 = Fcons (Fcons (key, list),
8e713be6 12425 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12426
b5210ea7
KH
12427 label_cached:
12428 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12429
b5210ea7
KH
12430 newlist = second_best = Qnil;
12431 /* Make a list of the fonts that have the right width. */
8e713be6 12432 for (; CONSP (list); list = XCDR (list))
b5210ea7 12433 {
536f4067
RS
12434 int found_size;
12435
8e713be6 12436 tem = XCAR (list);
dc43ef94 12437
8e713be6 12438 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12439 continue;
12440 if (!size)
12441 {
8e713be6 12442 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12443 continue;
12444 }
dc43ef94 12445
8e713be6 12446 if (!INTEGERP (XCDR (tem)))
dc43ef94 12447 {
b5210ea7
KH
12448 /* Since we have not yet known the size of this font, we
12449 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12450 XFontStruct *thisinfo;
12451
12452 BLOCK_INPUT;
17d85edc 12453 count = x_catch_errors (dpy);
dc43ef94 12454 thisinfo = XLoadQueryFont (dpy,
8e713be6 12455 XSTRING (XCAR (tem))->data);
17d85edc
KH
12456 if (x_had_errors_p (dpy))
12457 {
12458 /* This error is perhaps due to insufficient memory on X
12459 server. Let's just ignore it. */
12460 thisinfo = NULL;
12461 x_clear_errors (dpy);
12462 }
12463 x_uncatch_errors (dpy, count);
dc43ef94
KH
12464 UNBLOCK_INPUT;
12465
12466 if (thisinfo)
12467 {
8e713be6 12468 XCDR (tem)
536f4067
RS
12469 = (thisinfo->min_bounds.width == 0
12470 ? make_number (0)
12471 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12472 XFreeFont (dpy, thisinfo);
12473 }
12474 else
b5210ea7 12475 /* For unknown reason, the previous call of XListFont had
06a2c219 12476 returned a font which can't be opened. Record the size
b5210ea7 12477 as 0 not to try to open it again. */
8e713be6 12478 XCDR (tem) = make_number (0);
dc43ef94 12479 }
536f4067 12480
8e713be6 12481 found_size = XINT (XCDR (tem));
536f4067 12482 if (found_size == size)
8e713be6 12483 newlist = Fcons (XCAR (tem), newlist);
536f4067 12484 else if (found_size > 0)
b5210ea7 12485 {
536f4067 12486 if (NILP (second_best))
b5210ea7 12487 second_best = tem;
536f4067
RS
12488 else if (found_size < size)
12489 {
8e713be6
KR
12490 if (XINT (XCDR (second_best)) > size
12491 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12492 second_best = tem;
12493 }
12494 else
12495 {
8e713be6
KR
12496 if (XINT (XCDR (second_best)) > size
12497 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12498 second_best = tem;
12499 }
b5210ea7
KH
12500 }
12501 }
12502 if (!NILP (newlist))
12503 break;
12504 else if (!NILP (second_best))
12505 {
8e713be6 12506 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12507 break;
dc43ef94 12508 }
dc43ef94
KH
12509 }
12510
12511 return newlist;
12512}
12513
06a2c219
GM
12514
12515#if GLYPH_DEBUG
12516
12517/* Check that FONT is valid on frame F. It is if it can be found in F's
12518 font table. */
12519
12520static void
12521x_check_font (f, font)
12522 struct frame *f;
12523 XFontStruct *font;
12524{
12525 int i;
12526 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12527
12528 xassert (font != NULL);
12529
12530 for (i = 0; i < dpyinfo->n_fonts; i++)
12531 if (dpyinfo->font_table[i].name
12532 && font == dpyinfo->font_table[i].font)
12533 break;
12534
12535 xassert (i < dpyinfo->n_fonts);
12536}
12537
12538#endif /* GLYPH_DEBUG != 0 */
12539
12540/* Set *W to the minimum width, *H to the minimum font height of FONT.
12541 Note: There are (broken) X fonts out there with invalid XFontStruct
12542 min_bounds contents. For example, handa@etl.go.jp reports that
12543 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12544 have font->min_bounds.width == 0. */
12545
12546static INLINE void
12547x_font_min_bounds (font, w, h)
12548 XFontStruct *font;
12549 int *w, *h;
12550{
12551 *h = FONT_HEIGHT (font);
12552 *w = font->min_bounds.width;
12553
12554 /* Try to handle the case where FONT->min_bounds has invalid
12555 contents. Since the only font known to have invalid min_bounds
12556 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12557 if (*w <= 0)
12558 *w = font->max_bounds.width;
12559}
12560
12561
12562/* Compute the smallest character width and smallest font height over
12563 all fonts available on frame F. Set the members smallest_char_width
12564 and smallest_font_height in F's x_display_info structure to
12565 the values computed. Value is non-zero if smallest_font_height or
12566 smallest_char_width become smaller than they were before. */
12567
12568static int
12569x_compute_min_glyph_bounds (f)
12570 struct frame *f;
12571{
12572 int i;
12573 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12574 XFontStruct *font;
12575 int old_width = dpyinfo->smallest_char_width;
12576 int old_height = dpyinfo->smallest_font_height;
12577
12578 dpyinfo->smallest_font_height = 100000;
12579 dpyinfo->smallest_char_width = 100000;
12580
12581 for (i = 0; i < dpyinfo->n_fonts; ++i)
12582 if (dpyinfo->font_table[i].name)
12583 {
12584 struct font_info *fontp = dpyinfo->font_table + i;
12585 int w, h;
12586
12587 font = (XFontStruct *) fontp->font;
12588 xassert (font != (XFontStruct *) ~0);
12589 x_font_min_bounds (font, &w, &h);
12590
12591 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12592 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12593 }
12594
12595 xassert (dpyinfo->smallest_char_width > 0
12596 && dpyinfo->smallest_font_height > 0);
12597
12598 return (dpyinfo->n_fonts == 1
12599 || dpyinfo->smallest_char_width < old_width
12600 || dpyinfo->smallest_font_height < old_height);
12601}
12602
12603
dc43ef94
KH
12604/* Load font named FONTNAME of the size SIZE for frame F, and return a
12605 pointer to the structure font_info while allocating it dynamically.
12606 If SIZE is 0, load any size of font.
12607 If loading is failed, return NULL. */
12608
12609struct font_info *
12610x_load_font (f, fontname, size)
12611 struct frame *f;
12612 register char *fontname;
12613 int size;
12614{
12615 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12616 Lisp_Object font_names;
d645aaa4 12617 int count;
dc43ef94
KH
12618
12619 /* Get a list of all the fonts that match this name. Once we
12620 have a list of matching fonts, we compare them against the fonts
12621 we already have by comparing names. */
09c6077f 12622 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
12623
12624 if (!NILP (font_names))
12625 {
12626 Lisp_Object tail;
12627 int i;
12628
12629 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 12630 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
12631 if (dpyinfo->font_table[i].name
12632 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 12633 XSTRING (XCAR (tail))->data)
06a2c219 12634 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 12635 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
12636 return (dpyinfo->font_table + i);
12637 }
12638
12639 /* Load the font and add it to the table. */
12640 {
12641 char *full_name;
12642 XFontStruct *font;
12643 struct font_info *fontp;
12644 unsigned long value;
06a2c219 12645 int i;
dc43ef94 12646
2da424f1
KH
12647 /* If we have found fonts by x_list_font, load one of them. If
12648 not, we still try to load a font by the name given as FONTNAME
12649 because XListFonts (called in x_list_font) of some X server has
12650 a bug of not finding a font even if the font surely exists and
12651 is loadable by XLoadQueryFont. */
e1d6d5b9 12652 if (size > 0 && !NILP (font_names))
8e713be6 12653 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
12654
12655 BLOCK_INPUT;
d645aaa4 12656 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 12657 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
12658 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12659 {
12660 /* This error is perhaps due to insufficient memory on X
12661 server. Let's just ignore it. */
12662 font = NULL;
12663 x_clear_errors (FRAME_X_DISPLAY (f));
12664 }
12665 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 12666 UNBLOCK_INPUT;
b5210ea7 12667 if (!font)
dc43ef94
KH
12668 return NULL;
12669
06a2c219
GM
12670 /* Find a free slot in the font table. */
12671 for (i = 0; i < dpyinfo->n_fonts; ++i)
12672 if (dpyinfo->font_table[i].name == NULL)
12673 break;
12674
12675 /* If no free slot found, maybe enlarge the font table. */
12676 if (i == dpyinfo->n_fonts
12677 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 12678 {
06a2c219
GM
12679 int sz;
12680 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12681 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 12682 dpyinfo->font_table
06a2c219 12683 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
12684 }
12685
06a2c219
GM
12686 fontp = dpyinfo->font_table + i;
12687 if (i == dpyinfo->n_fonts)
12688 ++dpyinfo->n_fonts;
dc43ef94
KH
12689
12690 /* Now fill in the slots of *FONTP. */
12691 BLOCK_INPUT;
12692 fontp->font = font;
06a2c219 12693 fontp->font_idx = i;
dc43ef94
KH
12694 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12695 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12696
12697 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12698 full_name = 0;
12699 if (XGetFontProperty (font, XA_FONT, &value))
12700 {
12701 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12702 char *p = name;
12703 int dashes = 0;
12704
12705 /* Count the number of dashes in the "full name".
12706 If it is too few, this isn't really the font's full name,
12707 so don't use it.
12708 In X11R4, the fonts did not come with their canonical names
12709 stored in them. */
12710 while (*p)
12711 {
12712 if (*p == '-')
12713 dashes++;
12714 p++;
12715 }
12716
12717 if (dashes >= 13)
12718 {
12719 full_name = (char *) xmalloc (p - name + 1);
12720 bcopy (name, full_name, p - name + 1);
12721 }
12722
12723 XFree (name);
12724 }
12725
12726 if (full_name != 0)
12727 fontp->full_name = full_name;
12728 else
12729 fontp->full_name = fontp->name;
12730
12731 fontp->size = font->max_bounds.width;
d5749adb
KH
12732 fontp->height = FONT_HEIGHT (font);
12733 {
12734 /* For some font, ascent and descent in max_bounds field is
12735 larger than the above value. */
12736 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12737 if (max_height > fontp->height)
74848a96 12738 fontp->height = max_height;
d5749adb 12739 }
dc43ef94 12740
2da424f1
KH
12741 if (NILP (font_names))
12742 {
12743 /* We come here because of a bug of XListFonts mentioned at
12744 the head of this block. Let's store this information in
12745 the cache for x_list_fonts. */
12746 Lisp_Object lispy_name = build_string (fontname);
12747 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12748
8e713be6 12749 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12750 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12751 Fcons (Fcons (lispy_full_name,
12752 make_number (fontp->size)),
12753 Qnil)),
8e713be6 12754 XCDR (dpyinfo->name_list_element));
2da424f1 12755 if (full_name)
8e713be6 12756 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12757 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12758 Fcons (Fcons (lispy_full_name,
12759 make_number (fontp->size)),
12760 Qnil)),
8e713be6 12761 XCDR (dpyinfo->name_list_element));
2da424f1
KH
12762 }
12763
dc43ef94
KH
12764 /* The slot `encoding' specifies how to map a character
12765 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
12766 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12767 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 12768 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 12769 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
12770 which is never used by any charset. If mapping can't be
12771 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
12772 fontp->encoding[1]
12773 = (font->max_byte1 == 0
12774 /* 1-byte font */
12775 ? (font->min_char_or_byte2 < 0x80
12776 ? (font->max_char_or_byte2 < 0x80
12777 ? 0 /* 0x20..0x7F */
8ff102bd 12778 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
12779 : 1) /* 0xA0..0xFF */
12780 /* 2-byte font */
12781 : (font->min_byte1 < 0x80
12782 ? (font->max_byte1 < 0x80
12783 ? (font->min_char_or_byte2 < 0x80
12784 ? (font->max_char_or_byte2 < 0x80
12785 ? 0 /* 0x2020..0x7F7F */
8ff102bd 12786 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 12787 : 3) /* 0x20A0..0x7FFF */
8ff102bd 12788 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
12789 : (font->min_char_or_byte2 < 0x80
12790 ? (font->max_char_or_byte2 < 0x80
12791 ? 2 /* 0xA020..0xFF7F */
8ff102bd 12792 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
12793 : 1))); /* 0xA0A0..0xFFFF */
12794
12795 fontp->baseline_offset
12796 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12797 ? (long) value : 0);
12798 fontp->relative_compose
12799 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12800 ? (long) value : 0);
f78798df
KH
12801 fontp->default_ascent
12802 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12803 ? (long) value : 0);
dc43ef94 12804
06a2c219
GM
12805 /* Set global flag fonts_changed_p to non-zero if the font loaded
12806 has a character with a smaller width than any other character
12807 before, or if the font loaded has a smalle>r height than any
12808 other font loaded before. If this happens, it will make a
12809 glyph matrix reallocation necessary. */
12810 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 12811 UNBLOCK_INPUT;
dc43ef94
KH
12812 return fontp;
12813 }
12814}
12815
06a2c219
GM
12816
12817/* Return a pointer to struct font_info of a font named FONTNAME for
12818 frame F. If no such font is loaded, return NULL. */
12819
dc43ef94
KH
12820struct font_info *
12821x_query_font (f, fontname)
12822 struct frame *f;
12823 register char *fontname;
12824{
12825 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12826 int i;
12827
12828 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
12829 if (dpyinfo->font_table[i].name
12830 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12831 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
12832 return (dpyinfo->font_table + i);
12833 return NULL;
12834}
12835
06a2c219
GM
12836
12837/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
12838 `encoder' of the structure. */
12839
12840void
12841x_find_ccl_program (fontp)
12842 struct font_info *fontp;
12843{
a42f54e6 12844 Lisp_Object list, elt;
a6582676 12845
8e713be6 12846 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 12847 {
8e713be6 12848 elt = XCAR (list);
a6582676 12849 if (CONSP (elt)
8e713be6
KR
12850 && STRINGP (XCAR (elt))
12851 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
a6582676 12852 >= 0))
a42f54e6
KH
12853 break;
12854 }
12855 if (! NILP (list))
12856 {
d27f8ca7
KH
12857 struct ccl_program *ccl
12858 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 12859
8e713be6 12860 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
12861 xfree (ccl);
12862 else
12863 fontp->font_encoder = ccl;
a6582676
KH
12864 }
12865}
12866
06a2c219 12867
dc43ef94 12868\f
06a2c219
GM
12869/***********************************************************************
12870 Initialization
12871 ***********************************************************************/
f451eb13 12872
3afe33e7
RS
12873#ifdef USE_X_TOOLKIT
12874static XrmOptionDescRec emacs_options[] = {
12875 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12876 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12877
12878 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12879 XrmoptionSepArg, NULL},
12880 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12881
12882 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12883 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12884 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12885 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12886 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12887 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12888 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12889};
12890#endif /* USE_X_TOOLKIT */
12891
7a13e894
RS
12892static int x_initialized;
12893
29b38361
KH
12894#ifdef MULTI_KBOARD
12895/* Test whether two display-name strings agree up to the dot that separates
12896 the screen number from the server number. */
12897static int
12898same_x_server (name1, name2)
12899 char *name1, *name2;
12900{
12901 int seen_colon = 0;
cf591cc1
RS
12902 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12903 int system_name_length = strlen (system_name);
12904 int length_until_period = 0;
12905
12906 while (system_name[length_until_period] != 0
12907 && system_name[length_until_period] != '.')
12908 length_until_period++;
12909
12910 /* Treat `unix' like an empty host name. */
12911 if (! strncmp (name1, "unix:", 5))
12912 name1 += 4;
12913 if (! strncmp (name2, "unix:", 5))
12914 name2 += 4;
12915 /* Treat this host's name like an empty host name. */
12916 if (! strncmp (name1, system_name, system_name_length)
12917 && name1[system_name_length] == ':')
12918 name1 += system_name_length;
12919 if (! strncmp (name2, system_name, system_name_length)
12920 && name2[system_name_length] == ':')
12921 name2 += system_name_length;
12922 /* Treat this host's domainless name like an empty host name. */
12923 if (! strncmp (name1, system_name, length_until_period)
12924 && name1[length_until_period] == ':')
12925 name1 += length_until_period;
12926 if (! strncmp (name2, system_name, length_until_period)
12927 && name2[length_until_period] == ':')
12928 name2 += length_until_period;
12929
29b38361
KH
12930 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12931 {
12932 if (*name1 == ':')
12933 seen_colon++;
12934 if (seen_colon && *name1 == '.')
12935 return 1;
12936 }
12937 return (seen_colon
12938 && (*name1 == '.' || *name1 == '\0')
12939 && (*name2 == '.' || *name2 == '\0'));
12940}
12941#endif
12942
334208b7 12943struct x_display_info *
1f8255f2 12944x_term_init (display_name, xrm_option, resource_name)
334208b7 12945 Lisp_Object display_name;
1f8255f2
RS
12946 char *xrm_option;
12947 char *resource_name;
dc6f92b8 12948{
334208b7 12949 int connection;
7a13e894 12950 Display *dpy;
334208b7
RS
12951 struct x_display_info *dpyinfo;
12952 XrmDatabase xrdb;
12953
60439948
KH
12954 BLOCK_INPUT;
12955
7a13e894
RS
12956 if (!x_initialized)
12957 {
12958 x_initialize ();
12959 x_initialized = 1;
12960 }
dc6f92b8 12961
3afe33e7 12962#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
12963 /* weiner@footloose.sps.mot.com reports that this causes
12964 errors with X11R5:
12965 X protocol error: BadAtom (invalid Atom parameter)
12966 on protocol request 18skiloaf.
12967 So let's not use it until R6. */
12968#ifdef HAVE_X11XTR6
bdcd49ba
RS
12969 XtSetLanguageProc (NULL, NULL, NULL);
12970#endif
12971
7f9c7f94
RS
12972 {
12973 int argc = 0;
12974 char *argv[3];
12975
12976 argv[0] = "";
12977 argc = 1;
12978 if (xrm_option)
12979 {
12980 argv[argc++] = "-xrm";
12981 argv[argc++] = xrm_option;
12982 }
12983 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12984 resource_name, EMACS_CLASS,
12985 emacs_options, XtNumber (emacs_options),
12986 &argc, argv);
39d8bb4d
KH
12987
12988#ifdef HAVE_X11XTR6
10537cb1 12989 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 12990 fixup_locale ();
39d8bb4d 12991#endif
7f9c7f94 12992 }
3afe33e7
RS
12993
12994#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
12995#ifdef HAVE_X11R5
12996 XSetLocaleModifiers ("");
12997#endif
7a13e894 12998 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 12999#endif /* not USE_X_TOOLKIT */
334208b7 13000
7a13e894
RS
13001 /* Detect failure. */
13002 if (dpy == 0)
60439948
KH
13003 {
13004 UNBLOCK_INPUT;
13005 return 0;
13006 }
7a13e894
RS
13007
13008 /* We have definitely succeeded. Record the new connection. */
13009
13010 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13011
29b38361
KH
13012#ifdef MULTI_KBOARD
13013 {
13014 struct x_display_info *share;
13015 Lisp_Object tail;
13016
13017 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13018 share = share->next, tail = XCDR (tail))
13019 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13020 XSTRING (display_name)->data))
13021 break;
13022 if (share)
13023 dpyinfo->kboard = share->kboard;
13024 else
13025 {
13026 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13027 init_kboard (dpyinfo->kboard);
59e755be
KH
13028 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13029 {
13030 char *vendor = ServerVendor (dpy);
9b6ed9f3 13031 UNBLOCK_INPUT;
59e755be
KH
13032 dpyinfo->kboard->Vsystem_key_alist
13033 = call1 (Qvendor_specific_keysyms,
13034 build_string (vendor ? vendor : ""));
9b6ed9f3 13035 BLOCK_INPUT;
59e755be
KH
13036 }
13037
29b38361
KH
13038 dpyinfo->kboard->next_kboard = all_kboards;
13039 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13040 /* Don't let the initial kboard remain current longer than necessary.
13041 That would cause problems if a file loaded on startup tries to
06a2c219 13042 prompt in the mini-buffer. */
0ad5446c
KH
13043 if (current_kboard == initial_kboard)
13044 current_kboard = dpyinfo->kboard;
29b38361
KH
13045 }
13046 dpyinfo->kboard->reference_count++;
13047 }
b9737ad3
KH
13048#endif
13049
7a13e894
RS
13050 /* Put this display on the chain. */
13051 dpyinfo->next = x_display_list;
13052 x_display_list = dpyinfo;
13053
13054 /* Put it on x_display_name_list as well, to keep them parallel. */
13055 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13056 x_display_name_list);
8e713be6 13057 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13058
13059 dpyinfo->display = dpy;
dc6f92b8 13060
dc6f92b8 13061#if 0
7a13e894 13062 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13063#endif /* ! 0 */
7a13e894
RS
13064
13065 dpyinfo->x_id_name
fc932ac6
RS
13066 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13067 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13068 + 2);
13069 sprintf (dpyinfo->x_id_name, "%s@%s",
13070 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13071
13072 /* Figure out which modifier bits mean what. */
334208b7 13073 x_find_modifier_meanings (dpyinfo);
f451eb13 13074
ab648270 13075 /* Get the scroll bar cursor. */
7a13e894 13076 dpyinfo->vertical_scroll_bar_cursor
334208b7 13077 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13078
334208b7
RS
13079 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13080 resource_name, EMACS_CLASS);
13081#ifdef HAVE_XRMSETDATABASE
13082 XrmSetDatabase (dpyinfo->display, xrdb);
13083#else
13084 dpyinfo->display->db = xrdb;
13085#endif
547d9db8 13086 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13087 all versions. */
13088 dpyinfo->xrdb = xrdb;
334208b7
RS
13089
13090 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13091 DefaultScreen (dpyinfo->display));
5ff67d81 13092 select_visual (dpyinfo);
43bd1b2b 13093 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13094 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13095 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13096 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13097 dpyinfo->grabbed = 0;
13098 dpyinfo->reference_count = 0;
13099 dpyinfo->icon_bitmap_id = -1;
06a2c219 13100 dpyinfo->font_table = NULL;
7a13e894
RS
13101 dpyinfo->n_fonts = 0;
13102 dpyinfo->font_table_size = 0;
13103 dpyinfo->bitmaps = 0;
13104 dpyinfo->bitmaps_size = 0;
13105 dpyinfo->bitmaps_last = 0;
13106 dpyinfo->scratch_cursor_gc = 0;
13107 dpyinfo->mouse_face_mouse_frame = 0;
13108 dpyinfo->mouse_face_deferred_gc = 0;
13109 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13110 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13111 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13112 dpyinfo->mouse_face_window = Qnil;
13113 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13114 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13115 dpyinfo->x_focus_frame = 0;
13116 dpyinfo->x_focus_event_frame = 0;
13117 dpyinfo->x_highlight_frame = 0;
06a2c219 13118 dpyinfo->image_cache = make_image_cache ();
334208b7 13119
43bd1b2b 13120 /* See if a private colormap is requested. */
5ff67d81
GM
13121 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13122 {
13123 if (dpyinfo->visual->class == PseudoColor)
13124 {
13125 Lisp_Object value;
13126 value = display_x_get_resource (dpyinfo,
13127 build_string ("privateColormap"),
13128 build_string ("PrivateColormap"),
13129 Qnil, Qnil);
13130 if (STRINGP (value)
13131 && (!strcmp (XSTRING (value)->data, "true")
13132 || !strcmp (XSTRING (value)->data, "on")))
13133 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13134 }
43bd1b2b 13135 }
5ff67d81
GM
13136 else
13137 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13138 dpyinfo->visual, AllocNone);
43bd1b2b 13139
06a2c219
GM
13140 {
13141 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13142 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13143 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13144 dpyinfo->resy = pixels * 25.4 / mm;
13145 pixels = DisplayWidth (dpyinfo->display, screen_number);
13146 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13147 dpyinfo->resx = pixels * 25.4 / mm;
13148 }
13149
334208b7
RS
13150 dpyinfo->Xatom_wm_protocols
13151 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13152 dpyinfo->Xatom_wm_take_focus
13153 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13154 dpyinfo->Xatom_wm_save_yourself
13155 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13156 dpyinfo->Xatom_wm_delete_window
13157 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13158 dpyinfo->Xatom_wm_change_state
13159 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13160 dpyinfo->Xatom_wm_configure_denied
13161 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13162 dpyinfo->Xatom_wm_window_moved
13163 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13164 dpyinfo->Xatom_editres
13165 = XInternAtom (dpyinfo->display, "Editres", False);
13166 dpyinfo->Xatom_CLIPBOARD
13167 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13168 dpyinfo->Xatom_TIMESTAMP
13169 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13170 dpyinfo->Xatom_TEXT
13171 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13172 dpyinfo->Xatom_COMPOUND_TEXT
13173 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13174 dpyinfo->Xatom_DELETE
13175 = XInternAtom (dpyinfo->display, "DELETE", False);
13176 dpyinfo->Xatom_MULTIPLE
13177 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13178 dpyinfo->Xatom_INCR
13179 = XInternAtom (dpyinfo->display, "INCR", False);
13180 dpyinfo->Xatom_EMACS_TMP
13181 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13182 dpyinfo->Xatom_TARGETS
13183 = XInternAtom (dpyinfo->display, "TARGETS", False);
13184 dpyinfo->Xatom_NULL
13185 = XInternAtom (dpyinfo->display, "NULL", False);
13186 dpyinfo->Xatom_ATOM_PAIR
13187 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13188 /* For properties of font. */
13189 dpyinfo->Xatom_PIXEL_SIZE
13190 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13191 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13192 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13193 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13194 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13195 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13196 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13197
06a2c219
GM
13198 /* Ghostscript support. */
13199 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13200 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13201
13202 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13203 False);
13204
547d9db8
KH
13205 dpyinfo->cut_buffers_initialized = 0;
13206
334208b7
RS
13207 connection = ConnectionNumber (dpyinfo->display);
13208 dpyinfo->connection = connection;
13209
dc43ef94 13210 {
5d7cc324
RS
13211 char null_bits[1];
13212
13213 null_bits[0] = 0x00;
dc43ef94
KH
13214
13215 dpyinfo->null_pixel
13216 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13217 null_bits, 1, 1, (long) 0, (long) 0,
13218 1);
13219 }
13220
06a2c219
GM
13221 {
13222 extern int gray_bitmap_width, gray_bitmap_height;
13223 extern unsigned char *gray_bitmap_bits;
13224 dpyinfo->gray
13225 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13226 gray_bitmap_bits,
13227 gray_bitmap_width, gray_bitmap_height,
13228 (unsigned long) 1, (unsigned long) 0, 1);
13229 }
13230
f5d11644
GM
13231#ifdef HAVE_X_I18N
13232 xim_initialize (dpyinfo, resource_name);
13233#endif
13234
87485d6f
MW
13235#ifdef subprocesses
13236 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13237 if (connection != 0)
7a13e894 13238 add_keyboard_wait_descriptor (connection);
87485d6f 13239#endif
6d4238f3 13240
041b69ac 13241#ifndef F_SETOWN_BUG
dc6f92b8 13242#ifdef F_SETOWN
dc6f92b8 13243#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13244 /* stdin is a socket here */
334208b7 13245 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13246#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13247 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13248#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13249#endif /* ! defined (F_SETOWN) */
041b69ac 13250#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13251
13252#ifdef SIGIO
eee20f6a
KH
13253 if (interrupt_input)
13254 init_sigio (connection);
c118dd06 13255#endif /* ! defined (SIGIO) */
dc6f92b8 13256
51b592fb 13257#ifdef USE_LUCID
f8c39f51 13258#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13259 /* Make sure that we have a valid font for dialog boxes
13260 so that Xt does not crash. */
13261 {
13262 Display *dpy = dpyinfo->display;
13263 XrmValue d, fr, to;
13264 Font font;
e99db5a1 13265 int count;
51b592fb
RS
13266
13267 d.addr = (XPointer)&dpy;
13268 d.size = sizeof (Display *);
13269 fr.addr = XtDefaultFont;
13270 fr.size = sizeof (XtDefaultFont);
13271 to.size = sizeof (Font *);
13272 to.addr = (XPointer)&font;
e99db5a1 13273 count = x_catch_errors (dpy);
51b592fb
RS
13274 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13275 abort ();
13276 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13277 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13278 x_uncatch_errors (dpy, count);
51b592fb
RS
13279 }
13280#endif
f8c39f51 13281#endif
51b592fb 13282
34e23e5a
GM
13283 /* See if we should run in synchronous mode. This is useful
13284 for debugging X code. */
13285 {
13286 Lisp_Object value;
13287 value = display_x_get_resource (dpyinfo,
13288 build_string ("synchronous"),
13289 build_string ("Synchronous"),
13290 Qnil, Qnil);
13291 if (STRINGP (value)
13292 && (!strcmp (XSTRING (value)->data, "true")
13293 || !strcmp (XSTRING (value)->data, "on")))
13294 XSynchronize (dpyinfo->display, True);
13295 }
13296
60439948
KH
13297 UNBLOCK_INPUT;
13298
7a13e894
RS
13299 return dpyinfo;
13300}
13301\f
13302/* Get rid of display DPYINFO, assuming all frames are already gone,
13303 and without sending any more commands to the X server. */
dc6f92b8 13304
7a13e894
RS
13305void
13306x_delete_display (dpyinfo)
13307 struct x_display_info *dpyinfo;
13308{
13309 delete_keyboard_wait_descriptor (dpyinfo->connection);
13310
13311 /* Discard this display from x_display_name_list and x_display_list.
13312 We can't use Fdelq because that can quit. */
13313 if (! NILP (x_display_name_list)
8e713be6
KR
13314 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13315 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13316 else
13317 {
13318 Lisp_Object tail;
13319
13320 tail = x_display_name_list;
8e713be6 13321 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13322 {
bffcfca9 13323 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13324 {
8e713be6 13325 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13326 break;
13327 }
8e713be6 13328 tail = XCDR (tail);
7a13e894
RS
13329 }
13330 }
13331
9bda743f
GM
13332 if (next_noop_dpyinfo == dpyinfo)
13333 next_noop_dpyinfo = dpyinfo->next;
13334
7a13e894
RS
13335 if (x_display_list == dpyinfo)
13336 x_display_list = dpyinfo->next;
7f9c7f94
RS
13337 else
13338 {
13339 struct x_display_info *tail;
7a13e894 13340
7f9c7f94
RS
13341 for (tail = x_display_list; tail; tail = tail->next)
13342 if (tail->next == dpyinfo)
13343 tail->next = tail->next->next;
13344 }
7a13e894 13345
0d777288
RS
13346#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13347#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13348 XrmDestroyDatabase (dpyinfo->xrdb);
13349#endif
0d777288 13350#endif
29b38361
KH
13351#ifdef MULTI_KBOARD
13352 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13353 delete_kboard (dpyinfo->kboard);
b9737ad3 13354#endif
f5d11644
GM
13355#ifdef HAVE_X_I18N
13356 if (dpyinfo->xim)
13357 xim_close_dpy (dpyinfo);
13358#endif
13359
b9737ad3
KH
13360 xfree (dpyinfo->font_table);
13361 xfree (dpyinfo->x_id_name);
13362 xfree (dpyinfo);
7a13e894
RS
13363}
13364\f
13365/* Set up use of X before we make the first connection. */
13366
06a2c219
GM
13367static struct redisplay_interface x_redisplay_interface =
13368{
13369 x_produce_glyphs,
13370 x_write_glyphs,
13371 x_insert_glyphs,
13372 x_clear_end_of_line,
13373 x_scroll_run,
13374 x_after_update_window_line,
13375 x_update_window_begin,
13376 x_update_window_end,
13377 XTcursor_to,
13378 x_flush,
66ac4b0e
GM
13379 x_get_glyph_overhangs,
13380 x_fix_overlapping_area
06a2c219
GM
13381};
13382
dfcf069d 13383void
7a13e894
RS
13384x_initialize ()
13385{
06a2c219
GM
13386 rif = &x_redisplay_interface;
13387
13388 clear_frame_hook = x_clear_frame;
13389 ins_del_lines_hook = x_ins_del_lines;
13390 change_line_highlight_hook = x_change_line_highlight;
13391 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13392 ring_bell_hook = XTring_bell;
13393 reset_terminal_modes_hook = XTreset_terminal_modes;
13394 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13395 update_begin_hook = x_update_begin;
13396 update_end_hook = x_update_end;
dc6f92b8
JB
13397 set_terminal_window_hook = XTset_terminal_window;
13398 read_socket_hook = XTread_socket;
b8009dd1 13399 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13400 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13401 mouse_position_hook = XTmouse_position;
f451eb13 13402 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13403 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13404 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13405 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13406 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13407 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13408 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13409
f676886a 13410 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13411 char_ins_del_ok = 0; /* just as fast to write the line */
13412 line_ins_del_ok = 1; /* we'll just blt 'em */
13413 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13414 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13415 off the bottom */
13416 baud_rate = 19200;
13417
7a13e894 13418 x_noop_count = 0;
9ea173e8 13419 last_tool_bar_item = -1;
06a2c219
GM
13420 any_help_event_p = 0;
13421
b30b24cb
RS
13422 /* Try to use interrupt input; if we can't, then start polling. */
13423 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13424
7f9c7f94
RS
13425#ifdef USE_X_TOOLKIT
13426 XtToolkitInitialize ();
13427 Xt_app_con = XtCreateApplicationContext ();
665881ad 13428 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13429
13430 /* Install an asynchronous timer that processes Xt timeout events
13431 every 0.1s. This is necessary because some widget sets use
13432 timeouts internally, for example the LessTif menu bar, or the
13433 Xaw3d scroll bar. When Xt timouts aren't processed, these
13434 widgets don't behave normally. */
13435 {
13436 EMACS_TIME interval;
13437 EMACS_SET_SECS_USECS (interval, 0, 100000);
13438 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13439 }
db74249b 13440#endif
bffcfca9 13441
db74249b 13442#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13443 xaw3d_arrow_scroll = False;
13444 xaw3d_pick_top = True;
7f9c7f94
RS
13445#endif
13446
58769bee 13447 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13448 original error handler. */
e99db5a1 13449 XSetErrorHandler (x_error_handler);
334208b7 13450 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13451
06a2c219 13452 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13453#ifdef SIGWINCH
13454 signal (SIGWINCH, SIG_DFL);
c118dd06 13455#endif /* ! defined (SIGWINCH) */
dc6f92b8 13456
92e2441b 13457 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13458}
55123275 13459
06a2c219 13460
55123275
JB
13461void
13462syms_of_xterm ()
13463{
e99db5a1
RS
13464 staticpro (&x_error_message_string);
13465 x_error_message_string = Qnil;
13466
7a13e894
RS
13467 staticpro (&x_display_name_list);
13468 x_display_name_list = Qnil;
334208b7 13469
ab648270 13470 staticpro (&last_mouse_scroll_bar);
e53cb100 13471 last_mouse_scroll_bar = Qnil;
59e755be
KH
13472
13473 staticpro (&Qvendor_specific_keysyms);
13474 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13475
13476 staticpro (&last_mouse_press_frame);
13477 last_mouse_press_frame = Qnil;
06a2c219
GM
13478
13479 staticpro (&help_echo);
13480 help_echo = Qnil;
13481 staticpro (&previous_help_echo);
13482 previous_help_echo = Qnil;
13483
13484 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13485 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13486For example, if a block cursor is over a tab, it will be drawn as\n\
13487wide as that tab on the display.");
13488 x_stretch_cursor_p = 0;
13489
13490 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13491 "If not nil, Emacs uses toolkit scroll bars.");
13492#if USE_TOOLKIT_SCROLL_BARS
13493 x_toolkit_scroll_bars_p = 1;
13494#else
13495 x_toolkit_scroll_bars_p = 0;
13496#endif
13497
06a2c219
GM
13498 staticpro (&last_mouse_motion_frame);
13499 last_mouse_motion_frame = Qnil;
55123275 13500}
6cf0ae86
RS
13501
13502#endif /* not HAVE_X_WINDOWS */
06a2c219 13503