(direct_output_forward_char): Give up if currently
[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 {
06a2c219
GM
1390 glyph->charpos = CHARPOS (it->position);
1391 glyph->object = it->object;
88d75730 1392 glyph->pixel_width = it->pixel_width;
06a2c219 1393 glyph->voffset = it->voffset;
88d75730 1394 glyph->type = CHAR_GLYPH;
06a2c219 1395 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1396 glyph->left_box_line_p = it->start_of_box_run_p;
1397 glyph->right_box_line_p = it->end_of_box_run_p;
66ac4b0e
GM
1398 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1399 || it->phys_descent > it->descent);
88d75730 1400 glyph->padding_p = 0;
ee569018 1401 glyph->glyph_not_available_p = it->glyph_not_available_p;
88d75730
GM
1402 glyph->face_id = it->face_id;
1403 glyph->u.ch = it->char_to_display;
06a2c219
GM
1404 ++it->glyph_row->used[area];
1405 }
1406}
1407
b4192550
KH
1408/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1409 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1410
1411static INLINE void
1412x_append_composite_glyph (it)
1413 struct it *it;
1414{
1415 struct glyph *glyph;
1416 enum glyph_row_area area = it->area;
1417
1418 xassert (it->glyph_row);
1419
1420 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1421 if (glyph < it->glyph_row->glyphs[area + 1])
1422 {
b4192550
KH
1423 glyph->charpos = CHARPOS (it->position);
1424 glyph->object = it->object;
88d75730 1425 glyph->pixel_width = it->pixel_width;
b4192550 1426 glyph->voffset = it->voffset;
88d75730 1427 glyph->type = COMPOSITE_GLYPH;
b4192550 1428 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1429 glyph->left_box_line_p = it->start_of_box_run_p;
1430 glyph->right_box_line_p = it->end_of_box_run_p;
b4192550
KH
1431 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1432 || it->phys_descent > it->descent);
88d75730
GM
1433 glyph->padding_p = 0;
1434 glyph->glyph_not_available_p = 0;
1435 glyph->face_id = it->face_id;
1436 glyph->u.cmp_id = it->cmp_id;
b4192550
KH
1437 ++it->glyph_row->used[area];
1438 }
1439}
1440
06a2c219
GM
1441
1442/* Change IT->ascent and IT->height according to the setting of
1443 IT->voffset. */
1444
1445static INLINE void
1446take_vertical_position_into_account (it)
1447 struct it *it;
1448{
1449 if (it->voffset)
1450 {
1451 if (it->voffset < 0)
1452 /* Increase the ascent so that we can display the text higher
1453 in the line. */
1454 it->ascent += abs (it->voffset);
1455 else
1456 /* Increase the descent so that we can display the text lower
1457 in the line. */
1458 it->descent += it->voffset;
1459 }
1460}
1461
1462
1463/* Produce glyphs/get display metrics for the image IT is loaded with.
1464 See the description of struct display_iterator in dispextern.h for
1465 an overview of struct display_iterator. */
1466
1467static void
1468x_produce_image_glyph (it)
1469 struct it *it;
1470{
1471 struct image *img;
1472 struct face *face;
1473
1474 xassert (it->what == IT_IMAGE);
1475
1476 face = FACE_FROM_ID (it->f, it->face_id);
1477 img = IMAGE_FROM_ID (it->f, it->image_id);
1478 xassert (img);
1479
1480 /* Make sure X resources of the face and image are loaded. */
1481 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1482 prepare_image_for_display (it->f, img);
1483
95af8492 1484 it->ascent = it->phys_ascent = image_ascent (img, face);
66ac4b0e 1485 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
06a2c219
GM
1486 it->pixel_width = img->width + 2 * img->margin;
1487
1488 it->nglyphs = 1;
1489
1490 if (face->box != FACE_NO_BOX)
1491 {
1492 it->ascent += face->box_line_width;
1493 it->descent += face->box_line_width;
1494
1495 if (it->start_of_box_run_p)
1496 it->pixel_width += face->box_line_width;
1497 if (it->end_of_box_run_p)
1498 it->pixel_width += face->box_line_width;
1499 }
1500
1501 take_vertical_position_into_account (it);
1502
1503 if (it->glyph_row)
1504 {
1505 struct glyph *glyph;
1506 enum glyph_row_area area = it->area;
1507
1508 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1509 if (glyph < it->glyph_row->glyphs[area + 1])
1510 {
06a2c219
GM
1511 glyph->charpos = CHARPOS (it->position);
1512 glyph->object = it->object;
88d75730 1513 glyph->pixel_width = it->pixel_width;
06a2c219 1514 glyph->voffset = it->voffset;
88d75730 1515 glyph->type = IMAGE_GLYPH;
06a2c219 1516 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1517 glyph->left_box_line_p = it->start_of_box_run_p;
1518 glyph->right_box_line_p = it->end_of_box_run_p;
1519 glyph->overlaps_vertically_p = 0;
1520 glyph->padding_p = 0;
1521 glyph->glyph_not_available_p = 0;
1522 glyph->face_id = it->face_id;
1523 glyph->u.img_id = img->id;
06a2c219
GM
1524 ++it->glyph_row->used[area];
1525 }
1526 }
1527}
1528
1529
1530/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1531 of the glyph, WIDTH and HEIGHT are the width and height of the
1532 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1533 ascent of the glyph (0 <= ASCENT <= 1). */
1534
1535static void
1536x_append_stretch_glyph (it, object, width, height, ascent)
1537 struct it *it;
1538 Lisp_Object object;
1539 int width, height;
1540 double ascent;
1541{
1542 struct glyph *glyph;
1543 enum glyph_row_area area = it->area;
1544
1545 xassert (ascent >= 0 && ascent <= 1);
1546
1547 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1548 if (glyph < it->glyph_row->glyphs[area + 1])
1549 {
06a2c219
GM
1550 glyph->charpos = CHARPOS (it->position);
1551 glyph->object = object;
88d75730 1552 glyph->pixel_width = width;
06a2c219 1553 glyph->voffset = it->voffset;
88d75730 1554 glyph->type = STRETCH_GLYPH;
06a2c219 1555 glyph->multibyte_p = it->multibyte_p;
88d75730
GM
1556 glyph->left_box_line_p = it->start_of_box_run_p;
1557 glyph->right_box_line_p = it->end_of_box_run_p;
1558 glyph->overlaps_vertically_p = 0;
1559 glyph->padding_p = 0;
1560 glyph->glyph_not_available_p = 0;
1561 glyph->face_id = it->face_id;
1562 glyph->u.stretch.ascent = height * ascent;
1563 glyph->u.stretch.height = height;
06a2c219
GM
1564 ++it->glyph_row->used[area];
1565 }
1566}
1567
1568
1569/* Produce a stretch glyph for iterator IT. IT->object is the value
1570 of the glyph property displayed. The value must be a list
1571 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1572 being recognized:
1573
1574 1. `:width WIDTH' specifies that the space should be WIDTH *
1575 canonical char width wide. WIDTH may be an integer or floating
1576 point number.
1577
1578 2. `:relative-width FACTOR' specifies that the width of the stretch
1579 should be computed from the width of the first character having the
1580 `glyph' property, and should be FACTOR times that width.
1581
1582 3. `:align-to HPOS' specifies that the space should be wide enough
1583 to reach HPOS, a value in canonical character units.
1584
1585 Exactly one of the above pairs must be present.
1586
1587 4. `:height HEIGHT' specifies that the height of the stretch produced
1588 should be HEIGHT, measured in canonical character units.
1589
1590 5. `:relative-height FACTOR' specifies that the height of the the
1591 stretch should be FACTOR times the height of the characters having
1592 the glyph property.
1593
1594 Either none or exactly one of 4 or 5 must be present.
1595
1596 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1597 of the stretch should be used for the ascent of the stretch.
1598 ASCENT must be in the range 0 <= ASCENT <= 100. */
1599
1600#define NUMVAL(X) \
1601 ((INTEGERP (X) || FLOATP (X)) \
1602 ? XFLOATINT (X) \
1603 : - 1)
1604
1605
1606static void
1607x_produce_stretch_glyph (it)
1608 struct it *it;
1609{
1610 /* (space :width WIDTH :height HEIGHT. */
3e71d8f2
GM
1611#if GLYPH_DEBUG
1612 extern Lisp_Object Qspace;
1613#endif
1614 extern Lisp_Object QCwidth, QCheight, QCascent;
06a2c219
GM
1615 extern Lisp_Object QCrelative_width, QCrelative_height;
1616 extern Lisp_Object QCalign_to;
1617 Lisp_Object prop, plist;
1618 double width = 0, height = 0, ascent = 0;
1619 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1620 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1621
1622 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1623
1624 /* List should start with `space'. */
1625 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1626 plist = XCDR (it->object);
1627
1628 /* Compute the width of the stretch. */
1629 if (prop = Fplist_get (plist, QCwidth),
1630 NUMVAL (prop) > 0)
1631 /* Absolute width `:width WIDTH' specified and valid. */
1632 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1633 else if (prop = Fplist_get (plist, QCrelative_width),
1634 NUMVAL (prop) > 0)
1635 {
1636 /* Relative width `:relative-width FACTOR' specified and valid.
1637 Compute the width of the characters having the `glyph'
1638 property. */
1639 struct it it2;
1640 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1641
1642 it2 = *it;
1643 if (it->multibyte_p)
1644 {
1645 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1646 - IT_BYTEPOS (*it));
1647 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1648 }
1649 else
1650 it2.c = *p, it2.len = 1;
1651
1652 it2.glyph_row = NULL;
1653 it2.what = IT_CHARACTER;
1654 x_produce_glyphs (&it2);
1655 width = NUMVAL (prop) * it2.pixel_width;
1656 }
1657 else if (prop = Fplist_get (plist, QCalign_to),
1658 NUMVAL (prop) > 0)
1659 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1660 else
1661 /* Nothing specified -> width defaults to canonical char width. */
1662 width = CANON_X_UNIT (it->f);
1663
1664 /* Compute height. */
1665 if (prop = Fplist_get (plist, QCheight),
1666 NUMVAL (prop) > 0)
1667 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1668 else if (prop = Fplist_get (plist, QCrelative_height),
1669 NUMVAL (prop) > 0)
1670 height = FONT_HEIGHT (font) * NUMVAL (prop);
1671 else
1672 height = FONT_HEIGHT (font);
1673
1674 /* Compute percentage of height used for ascent. If
1675 `:ascent ASCENT' is present and valid, use that. Otherwise,
1676 derive the ascent from the font in use. */
1677 if (prop = Fplist_get (plist, QCascent),
1678 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1679 ascent = NUMVAL (prop) / 100.0;
1680 else
1681 ascent = (double) font->ascent / FONT_HEIGHT (font);
1682
1683 if (width <= 0)
1684 width = 1;
1685 if (height <= 0)
1686 height = 1;
1687
1688 if (it->glyph_row)
1689 {
1690 Lisp_Object object = it->stack[it->sp - 1].string;
1691 if (!STRINGP (object))
1692 object = it->w->buffer;
1693 x_append_stretch_glyph (it, object, width, height, ascent);
1694 }
1695
1696 it->pixel_width = width;
66ac4b0e
GM
1697 it->ascent = it->phys_ascent = height * ascent;
1698 it->descent = it->phys_descent = height - it->ascent;
06a2c219
GM
1699 it->nglyphs = 1;
1700
1701 if (face->box != FACE_NO_BOX)
1702 {
1703 it->ascent += face->box_line_width;
1704 it->descent += face->box_line_width;
1705
1706 if (it->start_of_box_run_p)
1707 it->pixel_width += face->box_line_width;
1708 if (it->end_of_box_run_p)
1709 it->pixel_width += face->box_line_width;
1710 }
1711
1712 take_vertical_position_into_account (it);
1713}
1714
b4192550
KH
1715/* Return proper value to be used as baseline offset of font that has
1716 ASCENT and DESCENT to draw characters by the font at the vertical
1717 center of the line of frame F.
1718
1719 Here, out task is to find the value of BOFF in the following figure;
1720
1721 -------------------------+-----------+-
1722 -+-+---------+-+ | |
1723 | | | | | |
1724 | | | | F_ASCENT F_HEIGHT
1725 | | | ASCENT | |
1726 HEIGHT | | | | |
1727 | | |-|-+------+-----------|------- baseline
1728 | | | | BOFF | |
1729 | |---------|-+-+ | |
1730 | | | DESCENT | |
1731 -+-+---------+-+ F_DESCENT |
1732 -------------------------+-----------+-
1733
1734 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1735 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1736 DESCENT = FONT->descent
1737 HEIGHT = FONT_HEIGHT (FONT)
1738 F_DESCENT = (F->output_data.x->font->descent
1739 - F->output_data.x->baseline_offset)
1740 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1741*/
1742
1743#define VCENTER_BASELINE_OFFSET(FONT, F) \
1744 ((FONT)->descent \
1745 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1746 - ((F)->output_data.x->font->descent - (F)->output_data.x->baseline_offset))
06a2c219
GM
1747
1748/* Produce glyphs/get display metrics for the display element IT is
1749 loaded with. See the description of struct display_iterator in
1750 dispextern.h for an overview of struct display_iterator. */
1751
1752static void
1753x_produce_glyphs (it)
1754 struct it *it;
1755{
ee569018
KH
1756 it->glyph_not_available_p = 0;
1757
06a2c219
GM
1758 if (it->what == IT_CHARACTER)
1759 {
1760 XChar2b char2b;
1761 XFontStruct *font;
ee569018 1762 struct face *face = FACE_FROM_ID (it->f, it->face_id);
06a2c219 1763 XCharStruct *pcm;
06a2c219 1764 int font_not_found_p;
b4192550
KH
1765 struct font_info *font_info;
1766 int boff; /* baseline offset */
06a2c219 1767
ee569018
KH
1768 /* Maybe translate single-byte characters to multibyte, or the
1769 other way. */
06a2c219 1770 it->char_to_display = it->c;
ee569018 1771 if (!ASCII_BYTE_P (it->c))
06a2c219 1772 {
ee569018
KH
1773 if (unibyte_display_via_language_environment
1774 && SINGLE_BYTE_CHAR_P (it->c)
1775 && (it->c >= 0240
1776 || !NILP (Vnonascii_translation_table)))
1777 {
1778 it->char_to_display = unibyte_char_to_multibyte (it->c);
1779 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1780 face = FACE_FROM_ID (it->f, it->face_id);
1781 }
1782 else if (!SINGLE_BYTE_CHAR_P (it->c)
1783 && !it->multibyte_p)
1784 {
1785 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1786 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1787 face = FACE_FROM_ID (it->f, it->face_id);
1788 }
06a2c219
GM
1789 }
1790
ee569018
KH
1791 /* Get font to use. Encode IT->char_to_display. */
1792 x_get_char_face_and_encoding (it->f, it->char_to_display,
1793 it->face_id, &char2b,
1794 it->multibyte_p);
06a2c219
GM
1795 font = face->font;
1796
1797 /* When no suitable font found, use the default font. */
1798 font_not_found_p = font == NULL;
1799 if (font_not_found_p)
b4192550
KH
1800 {
1801 font = FRAME_FONT (it->f);
1802 boff = it->f->output_data.x->baseline_offset;
1803 font_info = NULL;
1804 }
1805 else
1806 {
1807 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1808 boff = font_info->baseline_offset;
1809 if (font_info->vertical_centering)
1810 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1811 }
06a2c219
GM
1812
1813 if (it->char_to_display >= ' '
1814 && (!it->multibyte_p || it->char_to_display < 128))
1815 {
1816 /* Either unibyte or ASCII. */
1817 int stretched_p;
1818
1819 it->nglyphs = 1;
06a2c219
GM
1820
1821 pcm = x_per_char_metric (font, &char2b);
b4192550
KH
1822 it->ascent = font->ascent + boff;
1823 it->descent = font->descent - boff;
474848ac
GM
1824
1825 if (pcm)
1826 {
1827 it->phys_ascent = pcm->ascent + boff;
1828 it->phys_descent = pcm->descent - boff;
1829 it->pixel_width = pcm->width;
1830 }
1831 else
1832 {
1833 it->glyph_not_available_p = 1;
1834 it->phys_ascent = font->ascent + boff;
1835 it->phys_descent = font->descent - boff;
1836 it->pixel_width = FONT_WIDTH (font);
1837 }
06a2c219
GM
1838
1839 /* If this is a space inside a region of text with
1840 `space-width' property, change its width. */
1841 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1842 if (stretched_p)
1843 it->pixel_width *= XFLOATINT (it->space_width);
1844
1845 /* If face has a box, add the box thickness to the character
1846 height. If character has a box line to the left and/or
1847 right, add the box line width to the character's width. */
1848 if (face->box != FACE_NO_BOX)
1849 {
1850 int thick = face->box_line_width;
1851
1852 it->ascent += thick;
1853 it->descent += thick;
1854
1855 if (it->start_of_box_run_p)
1856 it->pixel_width += thick;
1857 if (it->end_of_box_run_p)
1858 it->pixel_width += thick;
1859 }
1860
1861 /* If face has an overline, add the height of the overline
1862 (1 pixel) and a 1 pixel margin to the character height. */
1863 if (face->overline_p)
1864 it->ascent += 2;
1865
1866 take_vertical_position_into_account (it);
1867
1868 /* If we have to actually produce glyphs, do it. */
1869 if (it->glyph_row)
1870 {
1871 if (stretched_p)
1872 {
1873 /* Translate a space with a `space-width' property
1874 into a stretch glyph. */
1875 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1876 x_append_stretch_glyph (it, it->object, it->pixel_width,
1877 it->ascent + it->descent, ascent);
1878 }
1879 else
1880 x_append_glyph (it);
1881
1882 /* If characters with lbearing or rbearing are displayed
1883 in this line, record that fact in a flag of the
1884 glyph row. This is used to optimize X output code. */
1c7e22fd 1885 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
06a2c219
GM
1886 it->glyph_row->contains_overlapping_glyphs_p = 1;
1887 }
1888 }
1889 else if (it->char_to_display == '\n')
1890 {
1891 /* A newline has no width but we need the height of the line. */
1892 it->pixel_width = 0;
1893 it->nglyphs = 0;
b4192550
KH
1894 it->ascent = it->phys_ascent = font->ascent + boff;
1895 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1896
1897 if (face->box != FACE_NO_BOX)
1898 {
1899 int thick = face->box_line_width;
1900 it->ascent += thick;
1901 it->descent += thick;
1902 }
1903 }
1904 else if (it->char_to_display == '\t')
1905 {
1906 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
d365f5bb 1907 int x = it->current_x + it->continuation_lines_width;
06a2c219
GM
1908 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1909
1910 it->pixel_width = next_tab_x - x;
1911 it->nglyphs = 1;
b4192550
KH
1912 it->ascent = it->phys_ascent = font->ascent + boff;
1913 it->descent = it->phys_descent = font->descent - boff;
06a2c219
GM
1914
1915 if (it->glyph_row)
1916 {
1917 double ascent = (double) it->ascent / (it->ascent + it->descent);
1918 x_append_stretch_glyph (it, it->object, it->pixel_width,
1919 it->ascent + it->descent, ascent);
1920 }
1921 }
1922 else
1923 {
1924 /* A multi-byte character. Assume that the display width of the
1925 character is the width of the character multiplied by the
b4192550 1926 width of the font. */
06a2c219 1927
b4192550
KH
1928 /* If we found a font, this font should give us the right
1929 metrics. If we didn't find a font, use the frame's
1930 default font and calculate the width of the character
1931 from the charset width; this is what old redisplay code
1932 did. */
1933 pcm = x_per_char_metric (font, &char2b);
ee569018
KH
1934 if (font_not_found_p || !pcm)
1935 {
1936 int charset = CHAR_CHARSET (it->char_to_display);
1937
1938 it->glyph_not_available_p = 1;
1939 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1940 * CHARSET_WIDTH (charset));
1941 it->phys_ascent = font->ascent + boff;
1942 it->phys_descent = font->descent - boff;
1943 }
1944 else
1945 {
1946 it->pixel_width = pcm->width;
1947 it->phys_ascent = pcm->ascent + boff;
1948 it->phys_descent = pcm->descent - boff;
1949 if (it->glyph_row
1950 && (pcm->lbearing < 0
1951 || pcm->rbearing > pcm->width))
1952 it->glyph_row->contains_overlapping_glyphs_p = 1;
1953 }
b4192550
KH
1954 it->nglyphs = 1;
1955 it->ascent = font->ascent + boff;
1956 it->descent = font->descent - boff;
06a2c219
GM
1957 if (face->box != FACE_NO_BOX)
1958 {
1959 int thick = face->box_line_width;
1960 it->ascent += thick;
1961 it->descent += thick;
1962
1963 if (it->start_of_box_run_p)
1964 it->pixel_width += thick;
1965 if (it->end_of_box_run_p)
1966 it->pixel_width += thick;
1967 }
1968
1969 /* If face has an overline, add the height of the overline
1970 (1 pixel) and a 1 pixel margin to the character height. */
1971 if (face->overline_p)
1972 it->ascent += 2;
1973
1974 take_vertical_position_into_account (it);
1975
1976 if (it->glyph_row)
1977 x_append_glyph (it);
1978 }
1979 }
b4192550
KH
1980 else if (it->what == IT_COMPOSITION)
1981 {
1982 /* Note: A composition is represented as one glyph in the
1983 glyph matrix. There are no padding glyphs. */
1984 XChar2b char2b;
1985 XFontStruct *font;
ee569018 1986 struct face *face = FACE_FROM_ID (it->f, it->face_id);
b4192550
KH
1987 XCharStruct *pcm;
1988 int font_not_found_p;
1989 struct font_info *font_info;
1990 int boff; /* baseline offset */
1991 struct composition *cmp = composition_table[it->cmp_id];
1992
1993 /* Maybe translate single-byte characters to multibyte. */
1994 it->char_to_display = it->c;
1995 if (unibyte_display_via_language_environment
1996 && SINGLE_BYTE_CHAR_P (it->c)
1997 && (it->c >= 0240
1998 || (it->c >= 0200
1999 && !NILP (Vnonascii_translation_table))))
2000 {
2001 it->char_to_display = unibyte_char_to_multibyte (it->c);
b4192550
KH
2002 }
2003
2004 /* Get face and font to use. Encode IT->char_to_display. */
ee569018
KH
2005 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2006 face = FACE_FROM_ID (it->f, it->face_id);
2007 x_get_char_face_and_encoding (it->f, it->char_to_display,
2008 it->face_id, &char2b, it->multibyte_p);
b4192550
KH
2009 font = face->font;
2010
2011 /* When no suitable font found, use the default font. */
2012 font_not_found_p = font == NULL;
2013 if (font_not_found_p)
2014 {
2015 font = FRAME_FONT (it->f);
2016 boff = it->f->output_data.x->baseline_offset;
2017 font_info = NULL;
2018 }
2019 else
2020 {
2021 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2022 boff = font_info->baseline_offset;
2023 if (font_info->vertical_centering)
2024 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2025 }
2026
2027 /* There are no padding glyphs, so there is only one glyph to
2028 produce for the composition. Important is that pixel_width,
2029 ascent and descent are the values of what is drawn by
2030 draw_glyphs (i.e. the values of the overall glyphs composed). */
2031 it->nglyphs = 1;
2032
2033 /* If we have not yet calculated pixel size data of glyphs of
2034 the composition for the current face font, calculate them
2035 now. Theoretically, we have to check all fonts for the
2036 glyphs, but that requires much time and memory space. So,
2037 here we check only the font of the first glyph. This leads
2038 to incorrect display very rarely, and C-l (recenter) can
2039 correct the display anyway. */
2040 if (cmp->font != (void *) font)
2041 {
2042 /* Ascent and descent of the font of the first character of
2043 this composition (adjusted by baseline offset). Ascent
2044 and descent of overall glyphs should not be less than
2045 them respectively. */
2046 int font_ascent = font->ascent + boff;
2047 int font_descent = font->descent - boff;
2048 /* Bounding box of the overall glyphs. */
2049 int leftmost, rightmost, lowest, highest;
329bed06 2050 int i, width, ascent, descent;
b4192550
KH
2051
2052 cmp->font = (void *) font;
2053
2054 /* Initialize the bounding box. */
2055 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2056 if (pcm)
2057 {
2058 width = pcm->width;
2059 ascent = pcm->ascent;
2060 descent = pcm->descent;
2061 }
2062 else
2063 {
2064 width = FONT_WIDTH (font);
2065 ascent = font->ascent;
2066 descent = font->descent;
2067 }
2068
2069 rightmost = width;
2070 lowest = - descent + boff;
2071 highest = ascent + boff;
b4192550 2072 leftmost = 0;
329bed06 2073
b4192550
KH
2074 if (font_info
2075 && font_info->default_ascent
2076 && CHAR_TABLE_P (Vuse_default_ascent)
2077 && !NILP (Faref (Vuse_default_ascent,
2078 make_number (it->char_to_display))))
2079 highest = font_info->default_ascent + boff;
2080
2081 /* Draw the first glyph at the normal position. It may be
2082 shifted to right later if some other glyphs are drawn at
2083 the left. */
2084 cmp->offsets[0] = 0;
2085 cmp->offsets[1] = boff;
2086
2087 /* Set cmp->offsets for the remaining glyphs. */
2088 for (i = 1; i < cmp->glyph_len; i++)
2089 {
2090 int left, right, btm, top;
2091 int ch = COMPOSITION_GLYPH (cmp, i);
ee569018
KH
2092 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2093
2094 face = FACE_FROM_ID (it->f, face_id);
2095 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2096 it->multibyte_p);
b4192550
KH
2097 font = face->font;
2098 if (font == NULL)
2099 {
2100 font = FRAME_FONT (it->f);
2101 boff = it->f->output_data.x->baseline_offset;
2102 font_info = NULL;
2103 }
2104 else
2105 {
2106 font_info
2107 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2108 boff = font_info->baseline_offset;
2109 if (font_info->vertical_centering)
2110 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2111 }
2112
2113 pcm = x_per_char_metric (font, &char2b);
329bed06
GM
2114 if (pcm)
2115 {
2116 width = pcm->width;
2117 ascent = pcm->ascent;
2118 descent = pcm->descent;
2119 }
2120 else
2121 {
2122 width = FONT_WIDTH (font);
2123 ascent = font->ascent;
2124 descent = font->descent;
2125 }
b4192550
KH
2126
2127 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2128 {
2129 /* Relative composition with or without
2130 alternate chars. */
329bed06
GM
2131 left = (leftmost + rightmost - width) / 2;
2132 btm = - descent + boff;
b4192550
KH
2133 if (font_info && font_info->relative_compose
2134 && (! CHAR_TABLE_P (Vignore_relative_composition)
2135 || NILP (Faref (Vignore_relative_composition,
2136 make_number (ch)))))
2137 {
2138
329bed06 2139 if (- descent >= font_info->relative_compose)
b4192550
KH
2140 /* One extra pixel between two glyphs. */
2141 btm = highest + 1;
329bed06 2142 else if (ascent <= 0)
b4192550 2143 /* One extra pixel between two glyphs. */
329bed06 2144 btm = lowest - 1 - ascent - descent;
b4192550
KH
2145 }
2146 }
2147 else
2148 {
2149 /* A composition rule is specified by an integer
2150 value that encodes global and new reference
2151 points (GREF and NREF). GREF and NREF are
2152 specified by numbers as below:
2153
2154 0---1---2 -- ascent
2155 | |
2156 | |
2157 | |
2158 9--10--11 -- center
2159 | |
2160 ---3---4---5--- baseline
2161 | |
2162 6---7---8 -- descent
2163 */
2164 int rule = COMPOSITION_RULE (cmp, i);
2165 int gref, nref, grefx, grefy, nrefx, nrefy;
2166
2167 COMPOSITION_DECODE_RULE (rule, gref, nref);
2168 grefx = gref % 3, nrefx = nref % 3;
2169 grefy = gref / 3, nrefy = nref / 3;
2170
2171 left = (leftmost
2172 + grefx * (rightmost - leftmost) / 2
329bed06 2173 - nrefx * width / 2);
b4192550
KH
2174 btm = ((grefy == 0 ? highest
2175 : grefy == 1 ? 0
2176 : grefy == 2 ? lowest
2177 : (highest + lowest) / 2)
329bed06
GM
2178 - (nrefy == 0 ? ascent + descent
2179 : nrefy == 1 ? descent - boff
b4192550 2180 : nrefy == 2 ? 0
329bed06 2181 : (ascent + descent) / 2));
b4192550
KH
2182 }
2183
2184 cmp->offsets[i * 2] = left;
329bed06 2185 cmp->offsets[i * 2 + 1] = btm + descent;
b4192550
KH
2186
2187 /* Update the bounding box of the overall glyphs. */
329bed06
GM
2188 right = left + width;
2189 top = btm + descent + ascent;
b4192550
KH
2190 if (left < leftmost)
2191 leftmost = left;
2192 if (right > rightmost)
2193 rightmost = right;
2194 if (top > highest)
2195 highest = top;
2196 if (btm < lowest)
2197 lowest = btm;
2198 }
2199
2200 /* If there are glyphs whose x-offsets are negative,
2201 shift all glyphs to the right and make all x-offsets
2202 non-negative. */
2203 if (leftmost < 0)
2204 {
2205 for (i = 0; i < cmp->glyph_len; i++)
2206 cmp->offsets[i * 2] -= leftmost;
2207 rightmost -= leftmost;
2208 }
2209
2210 cmp->pixel_width = rightmost;
2211 cmp->ascent = highest;
2212 cmp->descent = - lowest;
2213 if (cmp->ascent < font_ascent)
2214 cmp->ascent = font_ascent;
2215 if (cmp->descent < font_descent)
2216 cmp->descent = font_descent;
2217 }
2218
2219 it->pixel_width = cmp->pixel_width;
2220 it->ascent = it->phys_ascent = cmp->ascent;
2221 it->descent = it->phys_descent = cmp->descent;
2222
2223 if (face->box != FACE_NO_BOX)
2224 {
2225 int thick = face->box_line_width;
2226 it->ascent += thick;
2227 it->descent += thick;
2228
2229 if (it->start_of_box_run_p)
2230 it->pixel_width += thick;
2231 if (it->end_of_box_run_p)
2232 it->pixel_width += thick;
2233 }
2234
2235 /* If face has an overline, add the height of the overline
2236 (1 pixel) and a 1 pixel margin to the character height. */
2237 if (face->overline_p)
2238 it->ascent += 2;
2239
2240 take_vertical_position_into_account (it);
2241
2242 if (it->glyph_row)
2243 x_append_composite_glyph (it);
2244 }
06a2c219
GM
2245 else if (it->what == IT_IMAGE)
2246 x_produce_image_glyph (it);
2247 else if (it->what == IT_STRETCH)
2248 x_produce_stretch_glyph (it);
2249
3017fdd1
GM
2250 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2251 because this isn't true for images with `:ascent 100'. */
2252 xassert (it->ascent >= 0 && it->descent >= 0);
06a2c219
GM
2253 if (it->area == TEXT_AREA)
2254 it->current_x += it->pixel_width;
66ac4b0e 2255
d365f5bb
GM
2256 it->descent += it->extra_line_spacing;
2257
06a2c219
GM
2258 it->max_ascent = max (it->max_ascent, it->ascent);
2259 it->max_descent = max (it->max_descent, it->descent);
66ac4b0e
GM
2260 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2261 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
06a2c219
GM
2262}
2263
2264
2265/* Estimate the pixel height of the mode or top line on frame F.
2266 FACE_ID specifies what line's height to estimate. */
2267
2268int
2269x_estimate_mode_line_height (f, face_id)
2270 struct frame *f;
2271 enum face_id face_id;
2272{
2273 int height = 1;
2274
2275 /* This function is called so early when Emacs starts that the face
2276 cache and mode line face are not yet initialized. */
2277 if (FRAME_FACE_CACHE (f))
2278 {
2279 struct face *face = FACE_FROM_ID (f, face_id);
2280 if (face)
2281 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2282 }
2283
2284 return height;
2285}
2286
2287\f
2288/***********************************************************************
2289 Glyph display
2290 ***********************************************************************/
2291
2292/* A sequence of glyphs to be drawn in the same face.
2293
2294 This data structure is not really completely X specific, so it
2295 could possibly, at least partially, be useful for other systems. It
2296 is currently not part of the external redisplay interface because
2297 it's not clear what other systems will need. */
2298
2299struct glyph_string
2300{
2301 /* X-origin of the string. */
2302 int x;
2303
2304 /* Y-origin and y-position of the base line of this string. */
2305 int y, ybase;
2306
2307 /* The width of the string, not including a face extension. */
2308 int width;
2309
2310 /* The width of the string, including a face extension. */
2311 int background_width;
2312
2313 /* The height of this string. This is the height of the line this
2314 string is drawn in, and can be different from the height of the
2315 font the string is drawn in. */
2316 int height;
2317
2318 /* Number of pixels this string overwrites in front of its x-origin.
2319 This number is zero if the string has an lbearing >= 0; it is
2320 -lbearing, if the string has an lbearing < 0. */
2321 int left_overhang;
2322
2323 /* Number of pixels this string overwrites past its right-most
2324 nominal x-position, i.e. x + width. Zero if the string's
2325 rbearing is <= its nominal width, rbearing - width otherwise. */
2326 int right_overhang;
2327
2328 /* The frame on which the glyph string is drawn. */
2329 struct frame *f;
2330
2331 /* The window on which the glyph string is drawn. */
2332 struct window *w;
2333
2334 /* X display and window for convenience. */
2335 Display *display;
2336 Window window;
2337
2338 /* The glyph row for which this string was built. It determines the
2339 y-origin and height of the string. */
2340 struct glyph_row *row;
2341
2342 /* The area within row. */
2343 enum glyph_row_area area;
2344
2345 /* Characters to be drawn, and number of characters. */
2346 XChar2b *char2b;
2347 int nchars;
2348
06a2c219
GM
2349 /* A face-override for drawing cursors, mouse face and similar. */
2350 enum draw_glyphs_face hl;
2351
2352 /* Face in which this string is to be drawn. */
2353 struct face *face;
2354
2355 /* Font in which this string is to be drawn. */
2356 XFontStruct *font;
2357
2358 /* Font info for this string. */
2359 struct font_info *font_info;
2360
b4192550
KH
2361 /* Non-null means this string describes (part of) a composition.
2362 All characters from char2b are drawn composed. */
2363 struct composition *cmp;
06a2c219
GM
2364
2365 /* Index of this glyph string's first character in the glyph
b4192550
KH
2366 definition of CMP. If this is zero, this glyph string describes
2367 the first character of a composition. */
06a2c219
GM
2368 int gidx;
2369
2370 /* 1 means this glyph strings face has to be drawn to the right end
2371 of the window's drawing area. */
2372 unsigned extends_to_end_of_line_p : 1;
2373
2374 /* 1 means the background of this string has been drawn. */
2375 unsigned background_filled_p : 1;
2376
2377 /* 1 means glyph string must be drawn with 16-bit functions. */
2378 unsigned two_byte_p : 1;
2379
2380 /* 1 means that the original font determined for drawing this glyph
2381 string could not be loaded. The member `font' has been set to
2382 the frame's default font in this case. */
2383 unsigned font_not_found_p : 1;
2384
2385 /* 1 means that the face in which this glyph string is drawn has a
2386 stipple pattern. */
2387 unsigned stippled_p : 1;
2388
66ac4b0e
GM
2389 /* 1 means only the foreground of this glyph string must be drawn,
2390 and we should use the physical height of the line this glyph
2391 string appears in as clip rect. */
2392 unsigned for_overlaps_p : 1;
2393
06a2c219
GM
2394 /* The GC to use for drawing this glyph string. */
2395 GC gc;
2396
2397 /* A pointer to the first glyph in the string. This glyph
2398 corresponds to char2b[0]. Needed to draw rectangles if
2399 font_not_found_p is 1. */
2400 struct glyph *first_glyph;
2401
2402 /* Image, if any. */
2403 struct image *img;
2404
2405 struct glyph_string *next, *prev;
2406};
2407
2408
5c187dee 2409#if 0
06a2c219
GM
2410
2411static void
2412x_dump_glyph_string (s)
2413 struct glyph_string *s;
2414{
2415 fprintf (stderr, "glyph string\n");
2416 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2417 s->x, s->y, s->width, s->height);
2418 fprintf (stderr, " ybase = %d\n", s->ybase);
2419 fprintf (stderr, " hl = %d\n", s->hl);
2420 fprintf (stderr, " left overhang = %d, right = %d\n",
2421 s->left_overhang, s->right_overhang);
2422 fprintf (stderr, " nchars = %d\n", s->nchars);
2423 fprintf (stderr, " extends to end of line = %d\n",
2424 s->extends_to_end_of_line_p);
2425 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2426 fprintf (stderr, " bg width = %d\n", s->background_width);
2427}
2428
2429#endif /* GLYPH_DEBUG */
2430
2431
2432
2433static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2434 struct glyph_string **,
2435 struct glyph_string *,
2436 struct glyph_string *));
2437static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2438 struct glyph_string **,
2439 struct glyph_string *,
2440 struct glyph_string *));
2441static void x_append_glyph_string P_ ((struct glyph_string **,
2442 struct glyph_string **,
2443 struct glyph_string *));
2444static int x_left_overwritten P_ ((struct glyph_string *));
2445static int x_left_overwriting P_ ((struct glyph_string *));
2446static int x_right_overwritten P_ ((struct glyph_string *));
2447static int x_right_overwriting P_ ((struct glyph_string *));
66ac4b0e
GM
2448static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2449 int));
06a2c219
GM
2450static void x_init_glyph_string P_ ((struct glyph_string *,
2451 XChar2b *, struct window *,
2452 struct glyph_row *,
2453 enum glyph_row_area, int,
2454 enum draw_glyphs_face));
2455static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2456 enum glyph_row_area, int, int,
66ac4b0e 2457 enum draw_glyphs_face, int *, int *, int));
06a2c219
GM
2458static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2459static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2460static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2461 int));
2462static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
b4192550 2463static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
06a2c219
GM
2464static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2465static void x_draw_glyph_string P_ ((struct glyph_string *));
2466static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2467static void x_set_cursor_gc P_ ((struct glyph_string *));
2468static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2469static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2470static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2471 int *, int *));
2472static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2473static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
68c45bf0 2474 unsigned long *, double, int));
06a2c219 2475static void x_setup_relief_color P_ ((struct frame *, struct relief *,
68c45bf0 2476 double, int, unsigned long));
06a2c219
GM
2477static void x_setup_relief_colors P_ ((struct glyph_string *));
2478static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2479static void x_draw_image_relief P_ ((struct glyph_string *));
2480static void x_draw_image_foreground P_ ((struct glyph_string *));
2481static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2482static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2483static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2484 int, int, int));
2485static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2486 int, int, int, int, XRectangle *));
2487static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2488 int, int, int, XRectangle *));
66ac4b0e
GM
2489static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2490 enum glyph_row_area));
209f68d9
GM
2491static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2492 struct glyph_row *,
2493 enum glyph_row_area, int, int));
06a2c219 2494
163dcff3
GM
2495#if GLYPH_DEBUG
2496static void x_check_font P_ ((struct frame *, XFontStruct *));
2497#endif
2498
06a2c219 2499
06a2c219
GM
2500/* Append the list of glyph strings with head H and tail T to the list
2501 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2502
2503static INLINE void
2504x_append_glyph_string_lists (head, tail, h, t)
2505 struct glyph_string **head, **tail;
2506 struct glyph_string *h, *t;
2507{
2508 if (h)
2509 {
2510 if (*head)
2511 (*tail)->next = h;
2512 else
2513 *head = h;
2514 h->prev = *tail;
2515 *tail = t;
2516 }
2517}
2518
2519
2520/* Prepend the list of glyph strings with head H and tail T to the
2521 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2522 result. */
2523
2524static INLINE void
2525x_prepend_glyph_string_lists (head, tail, h, t)
2526 struct glyph_string **head, **tail;
2527 struct glyph_string *h, *t;
2528{
2529 if (h)
2530 {
2531 if (*head)
2532 (*head)->prev = t;
2533 else
2534 *tail = t;
2535 t->next = *head;
2536 *head = h;
2537 }
2538}
2539
2540
2541/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2542 Set *HEAD and *TAIL to the resulting list. */
2543
2544static INLINE void
2545x_append_glyph_string (head, tail, s)
2546 struct glyph_string **head, **tail;
2547 struct glyph_string *s;
2548{
2549 s->next = s->prev = NULL;
2550 x_append_glyph_string_lists (head, tail, s, s);
2551}
2552
2553
2554/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2555 face. */
2556
2557static void
2558x_set_cursor_gc (s)
2559 struct glyph_string *s;
2560{
2561 if (s->font == FRAME_FONT (s->f)
2562 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2563 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
b4192550 2564 && !s->cmp)
06a2c219
GM
2565 s->gc = s->f->output_data.x->cursor_gc;
2566 else
2567 {
2568 /* Cursor on non-default face: must merge. */
2569 XGCValues xgcv;
2570 unsigned long mask;
2571
2572 xgcv.background = s->f->output_data.x->cursor_pixel;
2573 xgcv.foreground = s->face->background;
2574
2575 /* If the glyph would be invisible, try a different foreground. */
2576 if (xgcv.foreground == xgcv.background)
2577 xgcv.foreground = s->face->foreground;
2578 if (xgcv.foreground == xgcv.background)
2579 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2580 if (xgcv.foreground == xgcv.background)
2581 xgcv.foreground = s->face->foreground;
2582
2583 /* Make sure the cursor is distinct from text in this face. */
2584 if (xgcv.background == s->face->background
2585 && xgcv.foreground == s->face->foreground)
2586 {
2587 xgcv.background = s->face->foreground;
2588 xgcv.foreground = s->face->background;
2589 }
2590
2591 IF_DEBUG (x_check_font (s->f, s->font));
2592 xgcv.font = s->font->fid;
2593 xgcv.graphics_exposures = False;
2594 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2595
2596 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2597 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2598 mask, &xgcv);
2599 else
2600 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2601 = XCreateGC (s->display, s->window, mask, &xgcv);
2602
2603 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2604 }
2605}
2606
2607
2608/* Set up S->gc of glyph string S for drawing text in mouse face. */
2609
2610static void
2611x_set_mouse_face_gc (s)
2612 struct glyph_string *s;
2613{
2614 int face_id;
ee569018 2615 struct face *face;
06a2c219
GM
2616
2617 /* What face has to be used for the mouse face? */
2618 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
ee569018 2619 face = FACE_FROM_ID (s->f, face_id);
033e3e18
GM
2620 if (s->first_glyph->type == CHAR_GLYPH)
2621 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2622 else
2623 face_id = FACE_FOR_CHAR (s->f, face, 0);
06a2c219
GM
2624 s->face = FACE_FROM_ID (s->f, face_id);
2625 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2626
2627 /* If font in this face is same as S->font, use it. */
2628 if (s->font == s->face->font)
2629 s->gc = s->face->gc;
2630 else
2631 {
2632 /* Otherwise construct scratch_cursor_gc with values from FACE
2633 but font FONT. */
2634 XGCValues xgcv;
2635 unsigned long mask;
2636
2637 xgcv.background = s->face->background;
2638 xgcv.foreground = s->face->foreground;
2639 IF_DEBUG (x_check_font (s->f, s->font));
2640 xgcv.font = s->font->fid;
2641 xgcv.graphics_exposures = False;
2642 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2643
2644 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2645 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2646 mask, &xgcv);
2647 else
2648 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2649 = XCreateGC (s->display, s->window, mask, &xgcv);
2650
2651 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2652 }
2653
2654 xassert (s->gc != 0);
2655}
2656
2657
2658/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2659 Faces to use in the mode line have already been computed when the
2660 matrix was built, so there isn't much to do, here. */
2661
2662static INLINE void
2663x_set_mode_line_face_gc (s)
2664 struct glyph_string *s;
2665{
2666 s->gc = s->face->gc;
06a2c219
GM
2667}
2668
2669
2670/* Set S->gc of glyph string S for drawing that glyph string. Set
2671 S->stippled_p to a non-zero value if the face of S has a stipple
2672 pattern. */
2673
2674static INLINE void
2675x_set_glyph_string_gc (s)
2676 struct glyph_string *s;
2677{
209f68d9
GM
2678 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2679
06a2c219
GM
2680 if (s->hl == DRAW_NORMAL_TEXT)
2681 {
2682 s->gc = s->face->gc;
2683 s->stippled_p = s->face->stipple != 0;
2684 }
2685 else if (s->hl == DRAW_INVERSE_VIDEO)
2686 {
2687 x_set_mode_line_face_gc (s);
2688 s->stippled_p = s->face->stipple != 0;
2689 }
2690 else if (s->hl == DRAW_CURSOR)
2691 {
2692 x_set_cursor_gc (s);
2693 s->stippled_p = 0;
2694 }
2695 else if (s->hl == DRAW_MOUSE_FACE)
2696 {
2697 x_set_mouse_face_gc (s);
2698 s->stippled_p = s->face->stipple != 0;
2699 }
2700 else if (s->hl == DRAW_IMAGE_RAISED
2701 || s->hl == DRAW_IMAGE_SUNKEN)
2702 {
2703 s->gc = s->face->gc;
2704 s->stippled_p = s->face->stipple != 0;
2705 }
2706 else
2707 {
2708 s->gc = s->face->gc;
2709 s->stippled_p = s->face->stipple != 0;
2710 }
2711
2712 /* GC must have been set. */
2713 xassert (s->gc != 0);
2714}
2715
2716
2717/* Return in *R the clipping rectangle for glyph string S. */
2718
2719static void
2720x_get_glyph_string_clip_rect (s, r)
2721 struct glyph_string *s;
2722 XRectangle *r;
2723{
2724 if (s->row->full_width_p)
2725 {
2726 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2727 int canon_x = CANON_X_UNIT (s->f);
2728
2729 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2730 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2731
2732 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2733 {
1da3fd71 2734 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2735 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2736 r->x -= width;
2737 }
2738
b9432a85 2739 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2740
06a2c219
GM
2741 /* Unless displaying a mode or menu bar line, which are always
2742 fully visible, clip to the visible part of the row. */
2743 if (s->w->pseudo_window_p)
2744 r->height = s->row->visible_height;
2745 else
2746 r->height = s->height;
2747 }
2748 else
2749 {
2750 /* This is a text line that may be partially visible. */
2751 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2752 r->width = window_box_width (s->w, s->area);
2753 r->height = s->row->visible_height;
2754 }
2755
2756 /* Don't use S->y for clipping because it doesn't take partially
2757 visible lines into account. For example, it can be negative for
2758 partially visible lines at the top of a window. */
2759 if (!s->row->full_width_p
2760 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
045dee35 2761 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
06a2c219
GM
2762 else
2763 r->y = max (0, s->row->y);
06a2c219 2764
9ea173e8 2765 /* If drawing a tool-bar window, draw it over the internal border
06a2c219 2766 at the top of the window. */
9ea173e8 2767 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219 2768 r->y -= s->f->output_data.x->internal_border_width;
66ac4b0e
GM
2769
2770 /* If S draws overlapping rows, it's sufficient to use the top and
2771 bottom of the window for clipping because this glyph string
2772 intentionally draws over other lines. */
2773 if (s->for_overlaps_p)
2774 {
045dee35 2775 r->y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
66ac4b0e
GM
2776 r->height = window_text_bottom_y (s->w) - r->y;
2777 }
2778
2779 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
06a2c219
GM
2780}
2781
2782
2783/* Set clipping for output of glyph string S. S may be part of a mode
2784 line or menu if we don't have X toolkit support. */
2785
2786static INLINE void
2787x_set_glyph_string_clipping (s)
2788 struct glyph_string *s;
2789{
2790 XRectangle r;
2791 x_get_glyph_string_clip_rect (s, &r);
2792 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2793}
2794
2795
2796/* Compute left and right overhang of glyph string S. If S is a glyph
b4192550 2797 string for a composition, assume overhangs don't exist. */
06a2c219
GM
2798
2799static INLINE void
2800x_compute_glyph_string_overhangs (s)
2801 struct glyph_string *s;
2802{
b4192550 2803 if (s->cmp == NULL
06a2c219
GM
2804 && s->first_glyph->type == CHAR_GLYPH)
2805 {
2806 XCharStruct cs;
2807 int direction, font_ascent, font_descent;
2808 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2809 &font_ascent, &font_descent, &cs);
2810 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2811 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2812 }
2813}
2814
2815
2816/* Compute overhangs and x-positions for glyph string S and its
2817 predecessors, or successors. X is the starting x-position for S.
2818 BACKWARD_P non-zero means process predecessors. */
2819
2820static void
2821x_compute_overhangs_and_x (s, x, backward_p)
2822 struct glyph_string *s;
2823 int x;
2824 int backward_p;
2825{
2826 if (backward_p)
2827 {
2828 while (s)
2829 {
2830 x_compute_glyph_string_overhangs (s);
2831 x -= s->width;
2832 s->x = x;
2833 s = s->prev;
2834 }
2835 }
2836 else
2837 {
2838 while (s)
2839 {
2840 x_compute_glyph_string_overhangs (s);
2841 s->x = x;
2842 x += s->width;
2843 s = s->next;
2844 }
2845 }
2846}
2847
2848
2849/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
b4192550
KH
2850 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2851 assumed to be zero. */
06a2c219
GM
2852
2853static void
2854x_get_glyph_overhangs (glyph, f, left, right)
2855 struct glyph *glyph;
2856 struct frame *f;
2857 int *left, *right;
2858{
06a2c219
GM
2859 *left = *right = 0;
2860
b4192550 2861 if (glyph->type == CHAR_GLYPH)
06a2c219
GM
2862 {
2863 XFontStruct *font;
2864 struct face *face;
2865 struct font_info *font_info;
2866 XChar2b char2b;
ee569018
KH
2867 XCharStruct *pcm;
2868
2869 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
06a2c219
GM
2870 font = face->font;
2871 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
ee569018
KH
2872 if (font
2873 && (pcm = x_per_char_metric (font, &char2b)))
06a2c219 2874 {
06a2c219
GM
2875 if (pcm->rbearing > pcm->width)
2876 *right = pcm->rbearing - pcm->width;
2877 if (pcm->lbearing < 0)
2878 *left = -pcm->lbearing;
2879 }
2880 }
2881}
2882
2883
2884/* Return the index of the first glyph preceding glyph string S that
2885 is overwritten by S because of S's left overhang. Value is -1
2886 if no glyphs are overwritten. */
2887
2888static int
2889x_left_overwritten (s)
2890 struct glyph_string *s;
2891{
2892 int k;
2893
2894 if (s->left_overhang)
2895 {
2896 int x = 0, i;
2897 struct glyph *glyphs = s->row->glyphs[s->area];
2898 int first = s->first_glyph - glyphs;
2899
2900 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2901 x -= glyphs[i].pixel_width;
2902
2903 k = i + 1;
2904 }
2905 else
2906 k = -1;
2907
2908 return k;
2909}
2910
2911
2912/* Return the index of the first glyph preceding glyph string S that
2913 is overwriting S because of its right overhang. Value is -1 if no
2914 glyph in front of S overwrites S. */
2915
2916static int
2917x_left_overwriting (s)
2918 struct glyph_string *s;
2919{
2920 int i, k, x;
2921 struct glyph *glyphs = s->row->glyphs[s->area];
2922 int first = s->first_glyph - glyphs;
2923
2924 k = -1;
2925 x = 0;
2926 for (i = first - 1; i >= 0; --i)
2927 {
2928 int left, right;
2929 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2930 if (x + right > 0)
2931 k = i;
2932 x -= glyphs[i].pixel_width;
2933 }
2934
2935 return k;
2936}
2937
2938
2939/* Return the index of the last glyph following glyph string S that is
2940 not overwritten by S because of S's right overhang. Value is -1 if
2941 no such glyph is found. */
2942
2943static int
2944x_right_overwritten (s)
2945 struct glyph_string *s;
2946{
2947 int k = -1;
2948
2949 if (s->right_overhang)
2950 {
2951 int x = 0, i;
2952 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2953 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2954 int end = s->row->used[s->area];
2955
2956 for (i = first; i < end && s->right_overhang > x; ++i)
2957 x += glyphs[i].pixel_width;
2958
2959 k = i;
2960 }
2961
2962 return k;
2963}
2964
2965
2966/* Return the index of the last glyph following glyph string S that
2967 overwrites S because of its left overhang. Value is negative
2968 if no such glyph is found. */
2969
2970static int
2971x_right_overwriting (s)
2972 struct glyph_string *s;
2973{
2974 int i, k, x;
2975 int end = s->row->used[s->area];
2976 struct glyph *glyphs = s->row->glyphs[s->area];
b4192550 2977 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
06a2c219
GM
2978
2979 k = -1;
2980 x = 0;
2981 for (i = first; i < end; ++i)
2982 {
2983 int left, right;
2984 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2985 if (x - left < 0)
2986 k = i;
2987 x += glyphs[i].pixel_width;
2988 }
2989
2990 return k;
2991}
2992
2993
2994/* Fill rectangle X, Y, W, H with background color of glyph string S. */
2995
2996static INLINE void
2997x_clear_glyph_string_rect (s, x, y, w, h)
2998 struct glyph_string *s;
2999 int x, y, w, h;
3000{
3001 XGCValues xgcv;
3002 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
3003 XSetForeground (s->display, s->gc, xgcv.background);
3004 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3005 XSetForeground (s->display, s->gc, xgcv.foreground);
3006}
3007
3008
3009/* Draw the background of glyph_string S. If S->background_filled_p
3010 is non-zero don't draw it. FORCE_P non-zero means draw the
3011 background even if it wouldn't be drawn normally. This is used
b4192550
KH
3012 when a string preceding S draws into the background of S, or S
3013 contains the first component of a composition. */
06a2c219
GM
3014
3015static void
3016x_draw_glyph_string_background (s, force_p)
3017 struct glyph_string *s;
3018 int force_p;
3019{
3020 /* Nothing to do if background has already been drawn or if it
3021 shouldn't be drawn in the first place. */
3022 if (!s->background_filled_p)
3023 {
b4192550 3024 if (s->stippled_p)
06a2c219
GM
3025 {
3026 /* Fill background with a stipple pattern. */
3027 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3028 XFillRectangle (s->display, s->window, s->gc, s->x,
3029 s->y + s->face->box_line_width,
3030 s->background_width,
3031 s->height - 2 * s->face->box_line_width);
3032 XSetFillStyle (s->display, s->gc, FillSolid);
3033 s->background_filled_p = 1;
3034 }
3035 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
3036 || s->font_not_found_p
3037 || s->extends_to_end_of_line_p
06a2c219
GM
3038 || force_p)
3039 {
3040 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
3041 s->background_width,
3042 s->height - 2 * s->face->box_line_width);
3043 s->background_filled_p = 1;
3044 }
3045 }
3046}
3047
3048
3049/* Draw the foreground of glyph string S. */
3050
3051static void
3052x_draw_glyph_string_foreground (s)
3053 struct glyph_string *s;
3054{
3055 int i, x;
3056
3057 /* If first glyph of S has a left box line, start drawing the text
3058 of S to the right of that box line. */
3059 if (s->face->box != FACE_NO_BOX
3060 && s->first_glyph->left_box_line_p)
3061 x = s->x + s->face->box_line_width;
3062 else
3063 x = s->x;
3064
b4192550
KH
3065 /* Draw characters of S as rectangles if S's font could not be
3066 loaded. */
3067 if (s->font_not_found_p)
06a2c219 3068 {
b4192550 3069 for (i = 0; i < s->nchars; ++i)
06a2c219 3070 {
b4192550
KH
3071 struct glyph *g = s->first_glyph + i;
3072 XDrawRectangle (s->display, s->window,
3073 s->gc, x, s->y, g->pixel_width - 1,
3074 s->height - 1);
3075 x += g->pixel_width;
06a2c219
GM
3076 }
3077 }
3078 else
3079 {
b4192550
KH
3080 char *char1b = (char *) s->char2b;
3081 int boff = s->font_info->baseline_offset;
06a2c219 3082
b4192550
KH
3083 if (s->font_info->vertical_centering)
3084 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3085
3086 /* If we can use 8-bit functions, condense S->char2b. */
3087 if (!s->two_byte_p)
3088 for (i = 0; i < s->nchars; ++i)
3089 char1b[i] = s->char2b[i].byte2;
3090
3091 /* Draw text with XDrawString if background has already been
3092 filled. Otherwise, use XDrawImageString. (Note that
3093 XDrawImageString is usually faster than XDrawString.) Always
3094 use XDrawImageString when drawing the cursor so that there is
3095 no chance that characters under a box cursor are invisible. */
3096 if (s->for_overlaps_p
3097 || (s->background_filled_p && s->hl != DRAW_CURSOR))
3098 {
3099 /* Draw characters with 16-bit or 8-bit functions. */
3100 if (s->two_byte_p)
3101 XDrawString16 (s->display, s->window, s->gc, x,
3102 s->ybase - boff, s->char2b, s->nchars);
3103 else
3104 XDrawString (s->display, s->window, s->gc, x,
3105 s->ybase - boff, char1b, s->nchars);
3106 }
06a2c219
GM
3107 else
3108 {
b4192550
KH
3109 if (s->two_byte_p)
3110 XDrawImageString16 (s->display, s->window, s->gc, x,
3111 s->ybase - boff, s->char2b, s->nchars);
06a2c219 3112 else
b4192550
KH
3113 XDrawImageString (s->display, s->window, s->gc, x,
3114 s->ybase - boff, char1b, s->nchars);
3115 }
3116 }
3117}
06a2c219 3118
b4192550 3119/* Draw the foreground of composite glyph string S. */
06a2c219 3120
b4192550
KH
3121static void
3122x_draw_composite_glyph_string_foreground (s)
3123 struct glyph_string *s;
3124{
3125 int i, x;
06a2c219 3126
b4192550
KH
3127 /* If first glyph of S has a left box line, start drawing the text
3128 of S to the right of that box line. */
3129 if (s->face->box != FACE_NO_BOX
3130 && s->first_glyph->left_box_line_p)
3131 x = s->x + s->face->box_line_width;
3132 else
3133 x = s->x;
06a2c219 3134
b4192550
KH
3135 /* S is a glyph string for a composition. S->gidx is the index of
3136 the first character drawn for glyphs of this composition.
3137 S->gidx == 0 means we are drawing the very first character of
3138 this composition. */
06a2c219 3139
b4192550
KH
3140 /* Draw a rectangle for the composition if the font for the very
3141 first character of the composition could not be loaded. */
3142 if (s->font_not_found_p)
3143 {
3144 if (s->gidx == 0)
3145 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
3146 s->width - 1, s->height - 1);
3147 }
3148 else
3149 {
3150 for (i = 0; i < s->nchars; i++, ++s->gidx)
3151 XDrawString16 (s->display, s->window, s->gc,
3152 x + s->cmp->offsets[s->gidx * 2],
3153 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3154 s->char2b + i, 1);
06a2c219
GM
3155 }
3156}
3157
3158
80c32bcc
GM
3159#ifdef USE_X_TOOLKIT
3160
3e71d8f2 3161static struct frame *x_frame_of_widget P_ ((Widget));
80c32bcc 3162
3e71d8f2
GM
3163
3164/* Return the frame on which widget WIDGET is used.. Abort if frame
3165 cannot be determined. */
3166
e851c833 3167static struct frame *
3e71d8f2 3168x_frame_of_widget (widget)
80c32bcc 3169 Widget widget;
80c32bcc 3170{
80c32bcc 3171 struct x_display_info *dpyinfo;
5c187dee 3172 Lisp_Object tail;
3e71d8f2
GM
3173 struct frame *f;
3174
80c32bcc
GM
3175 dpyinfo = x_display_info_for_display (XtDisplay (widget));
3176
3177 /* Find the top-level shell of the widget. Note that this function
3178 can be called when the widget is not yet realized, so XtWindow
3179 (widget) == 0. That's the reason we can't simply use
3180 x_any_window_to_frame. */
3181 while (!XtIsTopLevelShell (widget))
3182 widget = XtParent (widget);
3183
3184 /* Look for a frame with that top-level widget. Allocate the color
3185 on that frame to get the right gamma correction value. */
3186 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
3187 if (GC_FRAMEP (XCAR (tail))
3188 && (f = XFRAME (XCAR (tail)),
3189 (f->output_data.nothing != 1
3190 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
3191 && f->output_data.x->widget == widget)
3e71d8f2 3192 return f;
80c32bcc
GM
3193
3194 abort ();
3195}
3196
3e71d8f2
GM
3197
3198/* Allocate the color COLOR->pixel on the screen and display of
3199 widget WIDGET in colormap CMAP. If an exact match cannot be
3200 allocated, try the nearest color available. Value is non-zero
3201 if successful. This is called from lwlib. */
3202
3203int
3204x_alloc_nearest_color_for_widget (widget, cmap, color)
3205 Widget widget;
3206 Colormap cmap;
3207 XColor *color;
3208{
3209 struct frame *f = x_frame_of_widget (widget);
3210 return x_alloc_nearest_color (f, cmap, color);
3211}
3212
3213
80c32bcc
GM
3214#endif /* USE_X_TOOLKIT */
3215
3216
06a2c219
GM
3217/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
3218 CMAP. If an exact match can't be allocated, try the nearest color
3219 available. Value is non-zero if successful. Set *COLOR to the
3220 color allocated. */
3221
3222int
80c32bcc
GM
3223x_alloc_nearest_color (f, cmap, color)
3224 struct frame *f;
06a2c219
GM
3225 Colormap cmap;
3226 XColor *color;
3227{
80c32bcc
GM
3228 Display *display = FRAME_X_DISPLAY (f);
3229 Screen *screen = FRAME_X_SCREEN (f);
3230 int rc;
3231
3232 gamma_correct (f, color);
3233 rc = XAllocColor (display, cmap, color);
06a2c219
GM
3234 if (rc == 0)
3235 {
3236 /* If we got to this point, the colormap is full, so we're going
3237 to try to get the next closest color. The algorithm used is
3238 a least-squares matching, which is what X uses for closest
3239 color matching with StaticColor visuals. */
3240 int nearest, i;
3241 unsigned long nearest_delta = ~0;
3242 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
3243 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
3244
3245 for (i = 0; i < ncells; ++i)
3246 cells[i].pixel = i;
3247 XQueryColors (display, cmap, cells, ncells);
3248
3249 for (nearest = i = 0; i < ncells; ++i)
3250 {
3251 long dred = (color->red >> 8) - (cells[i].red >> 8);
3252 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
3253 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
3254 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
3255
3256 if (delta < nearest_delta)
3257 {
3258 nearest = i;
3259 nearest_delta = delta;
3260 }
3261 }
3262
3263 color->red = cells[nearest].red;
3264 color->green = cells[nearest].green;
3265 color->blue = cells[nearest].blue;
3266 rc = XAllocColor (display, cmap, color);
3267 }
3268
d9c545da
GM
3269#ifdef DEBUG_X_COLORS
3270 if (rc)
3271 register_color (color->pixel);
3272#endif /* DEBUG_X_COLORS */
3273
06a2c219
GM
3274 return rc;
3275}
3276
3277
d9c545da
GM
3278/* Allocate color PIXEL on frame F. PIXEL must already be allocated.
3279 It's necessary to do this instead of just using PIXEL directly to
3280 get color reference counts right. */
3281
3282unsigned long
3283x_copy_color (f, pixel)
3284 struct frame *f;
3285 unsigned long pixel;
3286{
3287 XColor color;
3288
3289 color.pixel = pixel;
3290 BLOCK_INPUT;
3291 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3292 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
3293 UNBLOCK_INPUT;
3294#ifdef DEBUG_X_COLORS
3295 register_color (pixel);
3296#endif
3297 return color.pixel;
3298}
3299
3300
3e71d8f2
GM
3301/* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
3302 It's necessary to do this instead of just using PIXEL directly to
3303 get color reference counts right. */
3304
3305unsigned long
3306x_copy_dpy_color (dpy, cmap, pixel)
3307 Display *dpy;
3308 Colormap cmap;
3309 unsigned long pixel;
3310{
3311 XColor color;
3312
3313 color.pixel = pixel;
3314 BLOCK_INPUT;
3315 XQueryColor (dpy, cmap, &color);
3316 XAllocColor (dpy, cmap, &color);
3317 UNBLOCK_INPUT;
3318#ifdef DEBUG_X_COLORS
3319 register_color (pixel);
3320#endif
3321 return color.pixel;
3322}
3323
3324
06a2c219
GM
3325/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
3326 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3327 If this produces the same color as PIXEL, try a color where all RGB
3328 values have DELTA added. Return the allocated color in *PIXEL.
3329 DISPLAY is the X display, CMAP is the colormap to operate on.
3330 Value is non-zero if successful. */
3331
3332static int
3333x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
3334 struct frame *f;
3335 Display *display;
3336 Colormap cmap;
3337 unsigned long *pixel;
68c45bf0 3338 double factor;
06a2c219
GM
3339 int delta;
3340{
3341 XColor color, new;
3342 int success_p;
3343
3344 /* Get RGB color values. */
3345 color.pixel = *pixel;
3346 XQueryColor (display, cmap, &color);
3347
3348 /* Change RGB values by specified FACTOR. Avoid overflow! */
3349 xassert (factor >= 0);
3350 new.red = min (0xffff, factor * color.red);
3351 new.green = min (0xffff, factor * color.green);
3352 new.blue = min (0xffff, factor * color.blue);
3353
3354 /* Try to allocate the color. */
80c32bcc 3355 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3356 if (success_p)
3357 {
3358 if (new.pixel == *pixel)
3359 {
3360 /* If we end up with the same color as before, try adding
3361 delta to the RGB values. */
0d605c67 3362 x_free_colors (f, &new.pixel, 1);
06a2c219
GM
3363
3364 new.red = min (0xffff, delta + color.red);
3365 new.green = min (0xffff, delta + color.green);
3366 new.blue = min (0xffff, delta + color.blue);
80c32bcc 3367 success_p = x_alloc_nearest_color (f, cmap, &new);
06a2c219
GM
3368 }
3369 else
3370 success_p = 1;
3371 *pixel = new.pixel;
3372 }
3373
3374 return success_p;
3375}
3376
3377
3378/* Set up the foreground color for drawing relief lines of glyph
3379 string S. RELIEF is a pointer to a struct relief containing the GC
3380 with which lines will be drawn. Use a color that is FACTOR or
3381 DELTA lighter or darker than the relief's background which is found
3382 in S->f->output_data.x->relief_background. If such a color cannot
3383 be allocated, use DEFAULT_PIXEL, instead. */
3384
3385static void
3386x_setup_relief_color (f, relief, factor, delta, default_pixel)
3387 struct frame *f;
3388 struct relief *relief;
68c45bf0 3389 double factor;
06a2c219
GM
3390 int delta;
3391 unsigned long default_pixel;
3392{
3393 XGCValues xgcv;
3394 struct x_output *di = f->output_data.x;
3395 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3396 unsigned long pixel;
3397 unsigned long background = di->relief_background;
43bd1b2b 3398 Colormap cmap = FRAME_X_COLORMAP (f);
dcd08bfb
GM
3399 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3400 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3401
3402 xgcv.graphics_exposures = False;
3403 xgcv.line_width = 1;
3404
3405 /* Free previously allocated color. The color cell will be reused
3406 when it has been freed as many times as it was allocated, so this
3407 doesn't affect faces using the same colors. */
3408 if (relief->gc
3409 && relief->allocated_p)
3410 {
0d605c67 3411 x_free_colors (f, &relief->pixel, 1);
06a2c219
GM
3412 relief->allocated_p = 0;
3413 }
3414
3415 /* Allocate new color. */
3416 xgcv.foreground = default_pixel;
3417 pixel = background;
dcd08bfb
GM
3418 if (dpyinfo->n_planes != 1
3419 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3420 {
3421 relief->allocated_p = 1;
3422 xgcv.foreground = relief->pixel = pixel;
3423 }
3424
3425 if (relief->gc == 0)
3426 {
dcd08bfb 3427 xgcv.stipple = dpyinfo->gray;
06a2c219 3428 mask |= GCStipple;
dcd08bfb 3429 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3430 }
3431 else
dcd08bfb 3432 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3433}
3434
3435
3436/* Set up colors for the relief lines around glyph string S. */
3437
3438static void
3439x_setup_relief_colors (s)
3440 struct glyph_string *s;
3441{
3442 struct x_output *di = s->f->output_data.x;
3443 unsigned long color;
3444
3445 if (s->face->use_box_color_for_shadows_p)
3446 color = s->face->box_color;
3447 else
3448 {
3449 XGCValues xgcv;
3450
3451 /* Get the background color of the face. */
3452 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3453 color = xgcv.background;
3454 }
3455
3456 if (di->white_relief.gc == 0
3457 || color != di->relief_background)
3458 {
3459 di->relief_background = color;
3460 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3461 WHITE_PIX_DEFAULT (s->f));
3462 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3463 BLACK_PIX_DEFAULT (s->f));
3464 }
3465}
3466
3467
3468/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3469 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3470 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3471 relief. LEFT_P non-zero means draw a relief on the left side of
3472 the rectangle. RIGHT_P non-zero means draw a relief on the right
3473 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3474 when drawing. */
3475
3476static void
3477x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3478 raised_p, left_p, right_p, clip_rect)
3479 struct frame *f;
3480 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3481 XRectangle *clip_rect;
3482{
3483 int i;
3484 GC gc;
3485
3486 if (raised_p)
3487 gc = f->output_data.x->white_relief.gc;
3488 else
3489 gc = f->output_data.x->black_relief.gc;
3490 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3491
3492 /* Top. */
3493 for (i = 0; i < width; ++i)
3494 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3495 left_x + i * left_p, top_y + i,
3496 right_x + 1 - i * right_p, top_y + i);
3497
3498 /* Left. */
3499 if (left_p)
3500 for (i = 0; i < width; ++i)
3501 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3502 left_x + i, top_y + i, left_x + i, bottom_y - i);
3503
3504 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3505 if (raised_p)
3506 gc = f->output_data.x->black_relief.gc;
3507 else
3508 gc = f->output_data.x->white_relief.gc;
3509 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3510
3511 /* Bottom. */
3512 for (i = 0; i < width; ++i)
3513 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3514 left_x + i * left_p, bottom_y - i,
3515 right_x + 1 - i * right_p, bottom_y - i);
3516
3517 /* Right. */
3518 if (right_p)
3519 for (i = 0; i < width; ++i)
3520 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3521 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3522
3523 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3524}
3525
3526
3527/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3528 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3529 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3530 left side of the rectangle. RIGHT_P non-zero means draw a line
3531 on the right side of the rectangle. CLIP_RECT is the clipping
3532 rectangle to use when drawing. */
3533
3534static void
3535x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3536 left_p, right_p, clip_rect)
3537 struct glyph_string *s;
3538 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3539 XRectangle *clip_rect;
3540{
3541 XGCValues xgcv;
3542
3543 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3544 XSetForeground (s->display, s->gc, s->face->box_color);
3545 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3546
3547 /* Top. */
3548 XFillRectangle (s->display, s->window, s->gc,
3549 left_x, top_y, right_x - left_x, width);
3550
3551 /* Left. */
3552 if (left_p)
3553 XFillRectangle (s->display, s->window, s->gc,
3554 left_x, top_y, width, bottom_y - top_y);
3555
3556 /* Bottom. */
3557 XFillRectangle (s->display, s->window, s->gc,
3558 left_x, bottom_y - width, right_x - left_x, width);
3559
3560 /* Right. */
3561 if (right_p)
3562 XFillRectangle (s->display, s->window, s->gc,
3563 right_x - width, top_y, width, bottom_y - top_y);
3564
3565 XSetForeground (s->display, s->gc, xgcv.foreground);
3566 XSetClipMask (s->display, s->gc, None);
3567}
3568
3569
3570/* Draw a box around glyph string S. */
3571
3572static void
3573x_draw_glyph_string_box (s)
3574 struct glyph_string *s;
3575{
3576 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3577 int left_p, right_p;
3578 struct glyph *last_glyph;
3579 XRectangle clip_rect;
3580
3581 last_x = window_box_right (s->w, s->area);
3582 if (s->row->full_width_p
3583 && !s->w->pseudo_window_p)
3584 {
110859fc 3585 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
06a2c219
GM
3586 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3587 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3588 }
3589
3590 /* The glyph that may have a right box line. */
b4192550 3591 last_glyph = (s->cmp || s->img
06a2c219
GM
3592 ? s->first_glyph
3593 : s->first_glyph + s->nchars - 1);
3594
3595 width = s->face->box_line_width;
3596 raised_p = s->face->box == FACE_RAISED_BOX;
3597 left_x = s->x;
3598 right_x = ((s->row->full_width_p
1da3fd71 3599 ? last_x - 1
a7aeb2de 3600 : min (last_x, s->x + s->background_width) - 1));
06a2c219
GM
3601 top_y = s->y;
3602 bottom_y = top_y + s->height - 1;
3603
3604 left_p = (s->first_glyph->left_box_line_p
3605 || (s->hl == DRAW_MOUSE_FACE
3606 && (s->prev == NULL
3607 || s->prev->hl != s->hl)));
3608 right_p = (last_glyph->right_box_line_p
3609 || (s->hl == DRAW_MOUSE_FACE
3610 && (s->next == NULL
3611 || s->next->hl != s->hl)));
3612
3613 x_get_glyph_string_clip_rect (s, &clip_rect);
3614
3615 if (s->face->box == FACE_SIMPLE_BOX)
3616 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3617 left_p, right_p, &clip_rect);
3618 else
3619 {
3620 x_setup_relief_colors (s);
3621 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3622 width, raised_p, left_p, right_p, &clip_rect);
3623 }
3624}
3625
3626
3627/* Draw foreground of image glyph string S. */
3628
3629static void
3630x_draw_image_foreground (s)
3631 struct glyph_string *s;
3632{
3633 int x;
95af8492 3634 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3635
3636 /* If first glyph of S has a left box line, start drawing it to the
3637 right of that line. */
3638 if (s->face->box != FACE_NO_BOX
3639 && s->first_glyph->left_box_line_p)
3640 x = s->x + s->face->box_line_width;
3641 else
3642 x = s->x;
3643
3644 /* If there is a margin around the image, adjust x- and y-position
3645 by that margin. */
3646 if (s->img->margin)
3647 {
3648 x += s->img->margin;
3649 y += s->img->margin;
3650 }
3651
3652 if (s->img->pixmap)
3653 {
3654 if (s->img->mask)
3655 {
3656 /* We can't set both a clip mask and use XSetClipRectangles
3657 because the latter also sets a clip mask. We also can't
3658 trust on the shape extension to be available
3659 (XShapeCombineRegion). So, compute the rectangle to draw
3660 manually. */
3661 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3662 | GCFunction);
3663 XGCValues xgcv;
3664 XRectangle clip_rect, image_rect, r;
3665
3666 xgcv.clip_mask = s->img->mask;
3667 xgcv.clip_x_origin = x;
3668 xgcv.clip_y_origin = y;
3669 xgcv.function = GXcopy;
3670 XChangeGC (s->display, s->gc, mask, &xgcv);
3671
3672 x_get_glyph_string_clip_rect (s, &clip_rect);
3673 image_rect.x = x;
3674 image_rect.y = y;
3675 image_rect.width = s->img->width;
3676 image_rect.height = s->img->height;
3677 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3678 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3679 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3680 }
3681 else
3682 {
3683 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3684 0, 0, s->img->width, s->img->height, x, y);
3685
3686 /* When the image has a mask, we can expect that at
3687 least part of a mouse highlight or a block cursor will
3688 be visible. If the image doesn't have a mask, make
3689 a block cursor visible by drawing a rectangle around
3690 the image. I believe it's looking better if we do
3691 nothing here for mouse-face. */
3692 if (s->hl == DRAW_CURSOR)
3693 XDrawRectangle (s->display, s->window, s->gc, x, y,
3694 s->img->width - 1, s->img->height - 1);
3695 }
3696 }
3697 else
3698 /* Draw a rectangle if image could not be loaded. */
3699 XDrawRectangle (s->display, s->window, s->gc, x, y,
3700 s->img->width - 1, s->img->height - 1);
3701}
3702
3703
3704/* Draw a relief around the image glyph string S. */
3705
3706static void
3707x_draw_image_relief (s)
3708 struct glyph_string *s;
3709{
3710 int x0, y0, x1, y1, thick, raised_p;
3711 XRectangle r;
3712 int x;
95af8492 3713 int y = s->ybase - image_ascent (s->img, s->face);
06a2c219
GM
3714
3715 /* If first glyph of S has a left box line, start drawing it to the
3716 right of that line. */
3717 if (s->face->box != FACE_NO_BOX
3718 && s->first_glyph->left_box_line_p)
3719 x = s->x + s->face->box_line_width;
3720 else
3721 x = s->x;
3722
3723 /* If there is a margin around the image, adjust x- and y-position
3724 by that margin. */
3725 if (s->img->margin)
3726 {
3727 x += s->img->margin;
3728 y += s->img->margin;
3729 }
3730
3731 if (s->hl == DRAW_IMAGE_SUNKEN
3732 || s->hl == DRAW_IMAGE_RAISED)
3733 {
9ea173e8 3734 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
06a2c219
GM
3735 raised_p = s->hl == DRAW_IMAGE_RAISED;
3736 }
3737 else
3738 {
3739 thick = abs (s->img->relief);
3740 raised_p = s->img->relief > 0;
3741 }
3742
3743 x0 = x - thick;
3744 y0 = y - thick;
3745 x1 = x + s->img->width + thick - 1;
3746 y1 = y + s->img->height + thick - 1;
3747
3748 x_setup_relief_colors (s);
3749 x_get_glyph_string_clip_rect (s, &r);
3750 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3751}
3752
3753
3754/* Draw the foreground of image glyph string S to PIXMAP. */
3755
3756static void
3757x_draw_image_foreground_1 (s, pixmap)
3758 struct glyph_string *s;
3759 Pixmap pixmap;
3760{
3761 int x;
95af8492 3762 int y = s->ybase - s->y - image_ascent (s->img, s->face);
06a2c219
GM
3763
3764 /* If first glyph of S has a left box line, start drawing it to the
3765 right of that line. */
3766 if (s->face->box != FACE_NO_BOX
3767 && s->first_glyph->left_box_line_p)
3768 x = s->face->box_line_width;
3769 else
3770 x = 0;
3771
3772 /* If there is a margin around the image, adjust x- and y-position
3773 by that margin. */
3774 if (s->img->margin)
3775 {
3776 x += s->img->margin;
3777 y += s->img->margin;
3778 }
dc43ef94 3779
06a2c219
GM
3780 if (s->img->pixmap)
3781 {
3782 if (s->img->mask)
3783 {
3784 /* We can't set both a clip mask and use XSetClipRectangles
3785 because the latter also sets a clip mask. We also can't
3786 trust on the shape extension to be available
3787 (XShapeCombineRegion). So, compute the rectangle to draw
3788 manually. */
3789 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3790 | GCFunction);
3791 XGCValues xgcv;
3792
3793 xgcv.clip_mask = s->img->mask;
3794 xgcv.clip_x_origin = x;
3795 xgcv.clip_y_origin = y;
3796 xgcv.function = GXcopy;
3797 XChangeGC (s->display, s->gc, mask, &xgcv);
3798
3799 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3800 0, 0, s->img->width, s->img->height, x, y);
3801 XSetClipMask (s->display, s->gc, None);
3802 }
3803 else
3804 {
3805 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3806 0, 0, s->img->width, s->img->height, x, y);
3807
3808 /* When the image has a mask, we can expect that at
3809 least part of a mouse highlight or a block cursor will
3810 be visible. If the image doesn't have a mask, make
3811 a block cursor visible by drawing a rectangle around
3812 the image. I believe it's looking better if we do
3813 nothing here for mouse-face. */
3814 if (s->hl == DRAW_CURSOR)
3815 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3816 s->img->width - 1, s->img->height - 1);
3817 }
3818 }
3819 else
3820 /* Draw a rectangle if image could not be loaded. */
3821 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3822 s->img->width - 1, s->img->height - 1);
3823}
dc43ef94 3824
990ba854 3825
06a2c219
GM
3826/* Draw part of the background of glyph string S. X, Y, W, and H
3827 give the rectangle to draw. */
a9a5b0a5 3828
06a2c219
GM
3829static void
3830x_draw_glyph_string_bg_rect (s, x, y, w, h)
3831 struct glyph_string *s;
3832 int x, y, w, h;
3833{
3834 if (s->stippled_p)
3835 {
3836 /* Fill background with a stipple pattern. */
3837 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3838 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3839 XSetFillStyle (s->display, s->gc, FillSolid);
3840 }
3841 else
3842 x_clear_glyph_string_rect (s, x, y, w, h);
3843}
07e34cb0 3844
b5210ea7 3845
06a2c219 3846/* Draw image glyph string S.
dc43ef94 3847
06a2c219
GM
3848 s->y
3849 s->x +-------------------------
3850 | s->face->box
3851 |
3852 | +-------------------------
3853 | | s->img->margin
3854 | |
3855 | | +-------------------
3856 | | | the image
dc43ef94 3857
06a2c219 3858 */
dc43ef94 3859
06a2c219
GM
3860static void
3861x_draw_image_glyph_string (s)
3862 struct glyph_string *s;
3863{
3864 int x, y;
3865 int box_line_width = s->face->box_line_width;
3866 int margin = s->img->margin;
3867 int height;
3868 Pixmap pixmap = None;
3869
3870 height = s->height - 2 * box_line_width;
3871
3872 /* Fill background with face under the image. Do it only if row is
3873 taller than image or if image has a clip mask to reduce
3874 flickering. */
3875 s->stippled_p = s->face->stipple != 0;
3876 if (height > s->img->height
3877 || margin
3878 || s->img->mask
3879 || s->img->pixmap == 0
3880 || s->width != s->background_width)
3881 {
3882 if (box_line_width && s->first_glyph->left_box_line_p)
3883 x = s->x + box_line_width;
3884 else
3885 x = s->x;
3886
3887 y = s->y + box_line_width;
3888
3889 if (s->img->mask)
3890 {
3891 /* Create a pixmap as large as the glyph string Fill it with
3892 the background color. Copy the image to it, using its
3893 mask. Copy the temporary pixmap to the display. */
3894 Screen *screen = FRAME_X_SCREEN (s->f);
3895 int depth = DefaultDepthOfScreen (screen);
3896
3897 /* Create a pixmap as large as the glyph string. */
3898 pixmap = XCreatePixmap (s->display, s->window,
3899 s->background_width,
3900 s->height, depth);
3901
3902 /* Don't clip in the following because we're working on the
3903 pixmap. */
3904 XSetClipMask (s->display, s->gc, None);
3905
3906 /* Fill the pixmap with the background color/stipple. */
3907 if (s->stippled_p)
3908 {
3909 /* Fill background with a stipple pattern. */
3910 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3911 XFillRectangle (s->display, pixmap, s->gc,
3912 0, 0, s->background_width, s->height);
3913 XSetFillStyle (s->display, s->gc, FillSolid);
3914 }
3915 else
3916 {
3917 XGCValues xgcv;
3918 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3919 &xgcv);
3920 XSetForeground (s->display, s->gc, xgcv.background);
3921 XFillRectangle (s->display, pixmap, s->gc,
3922 0, 0, s->background_width, s->height);
3923 XSetForeground (s->display, s->gc, xgcv.foreground);
3924 }
3925 }
3926 else
3927 /* Implementation idea: Is it possible to construct a mask?
3928 We could look at the color at the margins of the image, and
3929 say that this color is probably the background color of the
3930 image. */
3931 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3932
3933 s->background_filled_p = 1;
3934 }
dc43ef94 3935
06a2c219
GM
3936 /* Draw the foreground. */
3937 if (pixmap != None)
3938 {
3939 x_draw_image_foreground_1 (s, pixmap);
3940 x_set_glyph_string_clipping (s);
3941 XCopyArea (s->display, pixmap, s->window, s->gc,
3942 0, 0, s->background_width, s->height, s->x, s->y);
3943 XFreePixmap (s->display, pixmap);
3944 }
3945 else
3946 x_draw_image_foreground (s);
b5210ea7 3947
06a2c219
GM
3948 /* If we must draw a relief around the image, do it. */
3949 if (s->img->relief
3950 || s->hl == DRAW_IMAGE_RAISED
3951 || s->hl == DRAW_IMAGE_SUNKEN)
3952 x_draw_image_relief (s);
3953}
8c1a6a84 3954
990ba854 3955
06a2c219 3956/* Draw stretch glyph string S. */
dc43ef94 3957
06a2c219
GM
3958static void
3959x_draw_stretch_glyph_string (s)
3960 struct glyph_string *s;
3961{
3962 xassert (s->first_glyph->type == STRETCH_GLYPH);
3963 s->stippled_p = s->face->stipple != 0;
990ba854 3964
06a2c219
GM
3965 if (s->hl == DRAW_CURSOR
3966 && !x_stretch_cursor_p)
3967 {
3968 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3969 as wide as the stretch glyph. */
3970 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 3971
06a2c219
GM
3972 /* Draw cursor. */
3973 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 3974
06a2c219
GM
3975 /* Clear rest using the GC of the original non-cursor face. */
3976 if (width < s->background_width)
3977 {
3978 GC gc = s->face->gc;
3979 int x = s->x + width, y = s->y;
3980 int w = s->background_width - width, h = s->height;
3981 XRectangle r;
dc43ef94 3982
06a2c219
GM
3983 x_get_glyph_string_clip_rect (s, &r);
3984 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 3985
06a2c219
GM
3986 if (s->face->stipple)
3987 {
3988 /* Fill background with a stipple pattern. */
3989 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3990 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3991 XSetFillStyle (s->display, gc, FillSolid);
3992 }
3993 else
3994 {
3995 XGCValues xgcv;
3996 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3997 XSetForeground (s->display, gc, xgcv.background);
3998 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3999 XSetForeground (s->display, gc, xgcv.foreground);
4000 }
4001 }
4002 }
4003 else
4004 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4005 s->height);
4006
4007 s->background_filled_p = 1;
4008}
4009
4010
4011/* Draw glyph string S. */
4012
4013static void
4014x_draw_glyph_string (s)
4015 struct glyph_string *s;
4016{
4017 /* If S draws into the background of its successor, draw the
4018 background of the successor first so that S can draw into it.
4019 This makes S->next use XDrawString instead of XDrawImageString. */
66ac4b0e 4020 if (s->next && s->right_overhang && !s->for_overlaps_p)
06a2c219
GM
4021 {
4022 xassert (s->next->img == NULL);
4023 x_set_glyph_string_gc (s->next);
4024 x_set_glyph_string_clipping (s->next);
4025 x_draw_glyph_string_background (s->next, 1);
4026 }
97210f4e 4027
06a2c219
GM
4028 /* Set up S->gc, set clipping and draw S. */
4029 x_set_glyph_string_gc (s);
4030 x_set_glyph_string_clipping (s);
4031
4032 switch (s->first_glyph->type)
4033 {
4034 case IMAGE_GLYPH:
4035 x_draw_image_glyph_string (s);
4036 break;
4037
4038 case STRETCH_GLYPH:
4039 x_draw_stretch_glyph_string (s);
4040 break;
4041
4042 case CHAR_GLYPH:
66ac4b0e
GM
4043 if (s->for_overlaps_p)
4044 s->background_filled_p = 1;
4045 else
4046 x_draw_glyph_string_background (s, 0);
06a2c219
GM
4047 x_draw_glyph_string_foreground (s);
4048 break;
4049
b4192550
KH
4050 case COMPOSITE_GLYPH:
4051 if (s->for_overlaps_p || s->gidx > 0)
4052 s->background_filled_p = 1;
4053 else
4054 x_draw_glyph_string_background (s, 1);
4055 x_draw_composite_glyph_string_foreground (s);
4056 break;
4057
06a2c219
GM
4058 default:
4059 abort ();
4060 }
4061
66ac4b0e 4062 if (!s->for_overlaps_p)
06a2c219 4063 {
66ac4b0e
GM
4064 /* Draw underline. */
4065 if (s->face->underline_p)
4066 {
4067 unsigned long dy, h;
06a2c219 4068
66ac4b0e
GM
4069 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
4070 h = 1;
4071 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
4072 dy = s->height - h;
06a2c219 4073
66ac4b0e
GM
4074 if (s->face->underline_defaulted_p)
4075 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4076 s->width, h);
4077 else
4078 {
4079 XGCValues xgcv;
4080 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4081 XSetForeground (s->display, s->gc, s->face->underline_color);
4082 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4083 s->width, h);
4084 XSetForeground (s->display, s->gc, xgcv.foreground);
4085 }
dc6f92b8 4086 }
07e34cb0 4087
66ac4b0e
GM
4088 /* Draw overline. */
4089 if (s->face->overline_p)
06a2c219 4090 {
66ac4b0e
GM
4091 unsigned long dy = 0, h = 1;
4092
4093 if (s->face->overline_color_defaulted_p)
4094 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4095 s->width, h);
4096 else
4097 {
4098 XGCValues xgcv;
4099 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4100 XSetForeground (s->display, s->gc, s->face->overline_color);
4101 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4102 s->width, h);
4103 XSetForeground (s->display, s->gc, xgcv.foreground);
4104 }
06a2c219 4105 }
06a2c219 4106
66ac4b0e
GM
4107 /* Draw strike-through. */
4108 if (s->face->strike_through_p)
06a2c219 4109 {
66ac4b0e
GM
4110 unsigned long h = 1;
4111 unsigned long dy = (s->height - h) / 2;
4112
4113 if (s->face->strike_through_color_defaulted_p)
4114 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4115 s->width, h);
4116 else
4117 {
4118 XGCValues xgcv;
4119 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
4120 XSetForeground (s->display, s->gc, s->face->strike_through_color);
4121 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
4122 s->width, h);
4123 XSetForeground (s->display, s->gc, xgcv.foreground);
4124 }
06a2c219 4125 }
06a2c219 4126
66ac4b0e
GM
4127 /* Draw relief. */
4128 if (s->face->box != FACE_NO_BOX)
4129 x_draw_glyph_string_box (s);
4130 }
06a2c219
GM
4131
4132 /* Reset clipping. */
4133 XSetClipMask (s->display, s->gc, None);
dc6f92b8 4134}
07e34cb0 4135
06a2c219 4136
b4192550
KH
4137static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4138 struct face **, int));
06a2c219 4139
06a2c219 4140
209f68d9
GM
4141/* Fill glyph string S with composition components specified by S->cmp.
4142
b4192550
KH
4143 FACES is an array of faces for all components of this composition.
4144 S->gidx is the index of the first component for S.
4145 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4146 use its physical height for clipping.
06a2c219 4147
b4192550 4148 Value is the index of a component not in S. */
07e34cb0 4149
b4192550
KH
4150static int
4151x_fill_composite_glyph_string (s, faces, overlaps_p)
06a2c219 4152 struct glyph_string *s;
b4192550 4153 struct face **faces;
66ac4b0e 4154 int overlaps_p;
07e34cb0 4155{
b4192550 4156 int i;
06a2c219 4157
b4192550 4158 xassert (s);
06a2c219 4159
b4192550 4160 s->for_overlaps_p = overlaps_p;
06a2c219 4161
b4192550
KH
4162 s->face = faces[s->gidx];
4163 s->font = s->face->font;
4164 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
06a2c219 4165
b4192550
KH
4166 /* For all glyphs of this composition, starting at the offset
4167 S->gidx, until we reach the end of the definition or encounter a
4168 glyph that requires the different face, add it to S. */
4169 ++s->nchars;
4170 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4171 ++s->nchars;
06a2c219 4172
b4192550
KH
4173 /* All glyph strings for the same composition has the same width,
4174 i.e. the width set for the first component of the composition. */
06a2c219 4175
06a2c219
GM
4176 s->width = s->first_glyph->pixel_width;
4177
4178 /* If the specified font could not be loaded, use the frame's
4179 default font, but record the fact that we couldn't load it in
4180 the glyph string so that we can draw rectangles for the
4181 characters of the glyph string. */
4182 if (s->font == NULL)
4183 {
4184 s->font_not_found_p = 1;
4185 s->font = FRAME_FONT (s->f);
4186 }
4187
4188 /* Adjust base line for subscript/superscript text. */
4189 s->ybase += s->first_glyph->voffset;
4190
4191 xassert (s->face && s->face->gc);
4192
4193 /* This glyph string must always be drawn with 16-bit functions. */
4194 s->two_byte_p = 1;
b4192550
KH
4195
4196 return s->gidx + s->nchars;
06a2c219
GM
4197}
4198
4199
209f68d9
GM
4200/* Fill glyph string S from a sequence of character glyphs.
4201
06a2c219 4202 FACE_ID is the face id of the string. START is the index of the
66ac4b0e
GM
4203 first glyph to consider, END is the index of the last + 1.
4204 OVERLAPS_P non-zero means S should draw the foreground only, and
209f68d9 4205 use its physical height for clipping.
66ac4b0e
GM
4206
4207 Value is the index of the first glyph not in S. */
06a2c219
GM
4208
4209static int
66ac4b0e 4210x_fill_glyph_string (s, face_id, start, end, overlaps_p)
06a2c219
GM
4211 struct glyph_string *s;
4212 int face_id;
66ac4b0e 4213 int start, end, overlaps_p;
06a2c219
GM
4214{
4215 struct glyph *glyph, *last;
4216 int voffset;
ee569018 4217 int glyph_not_available_p;
06a2c219 4218
06a2c219
GM
4219 xassert (s->f == XFRAME (s->w->frame));
4220 xassert (s->nchars == 0);
4221 xassert (start >= 0 && end > start);
4222
66ac4b0e 4223 s->for_overlaps_p = overlaps_p,
06a2c219
GM
4224 glyph = s->row->glyphs[s->area] + start;
4225 last = s->row->glyphs[s->area] + end;
4226 voffset = glyph->voffset;
4227
ee569018
KH
4228 glyph_not_available_p = glyph->glyph_not_available_p;
4229
06a2c219
GM
4230 while (glyph < last
4231 && glyph->type == CHAR_GLYPH
4232 && glyph->voffset == voffset
ee569018
KH
4233 /* Same face id implies same font, nowadays. */
4234 && glyph->face_id == face_id
4235 && glyph->glyph_not_available_p == glyph_not_available_p)
06a2c219 4236 {
ee569018
KH
4237 int two_byte_p;
4238
06a2c219 4239 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
ee569018
KH
4240 s->char2b + s->nchars,
4241 &two_byte_p);
4242 s->two_byte_p = two_byte_p;
06a2c219
GM
4243 ++s->nchars;
4244 xassert (s->nchars <= end - start);
4245 s->width += glyph->pixel_width;
4246 ++glyph;
4247 }
4248
4249 s->font = s->face->font;
4250 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4251
4252 /* If the specified font could not be loaded, use the frame's font,
4253 but record the fact that we couldn't load it in
4254 S->font_not_found_p so that we can draw rectangles for the
4255 characters of the glyph string. */
ee569018 4256 if (s->font == NULL || glyph_not_available_p)
06a2c219
GM
4257 {
4258 s->font_not_found_p = 1;
4259 s->font = FRAME_FONT (s->f);
4260 }
4261
4262 /* Adjust base line for subscript/superscript text. */
4263 s->ybase += voffset;
66ac4b0e 4264
06a2c219
GM
4265 xassert (s->face && s->face->gc);
4266 return glyph - s->row->glyphs[s->area];
07e34cb0 4267}
dc6f92b8 4268
06a2c219
GM
4269
4270/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 4271
dfcf069d 4272static void
06a2c219
GM
4273x_fill_image_glyph_string (s)
4274 struct glyph_string *s;
4275{
4276 xassert (s->first_glyph->type == IMAGE_GLYPH);
43d120d8 4277 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
06a2c219 4278 xassert (s->img);
43d120d8 4279 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
06a2c219
GM
4280 s->font = s->face->font;
4281 s->width = s->first_glyph->pixel_width;
4282
4283 /* Adjust base line for subscript/superscript text. */
4284 s->ybase += s->first_glyph->voffset;
4285}
4286
4287
209f68d9 4288/* Fill glyph string S from a sequence of stretch glyphs.
06a2c219 4289
209f68d9
GM
4290 ROW is the glyph row in which the glyphs are found, AREA is the
4291 area within the row. START is the index of the first glyph to
4292 consider, END is the index of the last + 1.
4293
4294 Value is the index of the first glyph not in S. */
4295
4296static int
4297x_fill_stretch_glyph_string (s, row, area, start, end)
06a2c219 4298 struct glyph_string *s;
209f68d9
GM
4299 struct glyph_row *row;
4300 enum glyph_row_area area;
4301 int start, end;
06a2c219 4302{
209f68d9
GM
4303 struct glyph *glyph, *last;
4304 int voffset, face_id;
4305
06a2c219 4306 xassert (s->first_glyph->type == STRETCH_GLYPH);
209f68d9
GM
4307
4308 glyph = s->row->glyphs[s->area] + start;
4309 last = s->row->glyphs[s->area] + end;
4310 face_id = glyph->face_id;
4311 s->face = FACE_FROM_ID (s->f, face_id);
06a2c219 4312 s->font = s->face->font;
209f68d9
GM
4313 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4314 s->width = glyph->pixel_width;
4315 voffset = glyph->voffset;
4316
4317 for (++glyph;
4318 (glyph < last
4319 && glyph->type == STRETCH_GLYPH
4320 && glyph->voffset == voffset
4321 && glyph->face_id == face_id);
4322 ++glyph)
4323 s->width += glyph->pixel_width;
06a2c219
GM
4324
4325 /* Adjust base line for subscript/superscript text. */
209f68d9
GM
4326 s->ybase += voffset;
4327
4328 xassert (s->face && s->face->gc);
4329 return glyph - s->row->glyphs[s->area];
06a2c219
GM
4330}
4331
4332
4333/* Initialize glyph string S. CHAR2B is a suitably allocated vector
4334 of XChar2b structures for S; it can't be allocated in
4335 x_init_glyph_string because it must be allocated via `alloca'. W
4336 is the window on which S is drawn. ROW and AREA are the glyph row
4337 and area within the row from which S is constructed. START is the
4338 index of the first glyph structure covered by S. HL is a
4339 face-override for drawing S. */
4340
4341static void
4342x_init_glyph_string (s, char2b, w, row, area, start, hl)
4343 struct glyph_string *s;
4344 XChar2b *char2b;
4345 struct window *w;
4346 struct glyph_row *row;
4347 enum glyph_row_area area;
4348 int start;
4349 enum draw_glyphs_face hl;
4350{
4351 bzero (s, sizeof *s);
4352 s->w = w;
4353 s->f = XFRAME (w->frame);
4354 s->display = FRAME_X_DISPLAY (s->f);
4355 s->window = FRAME_X_WINDOW (s->f);
4356 s->char2b = char2b;
4357 s->hl = hl;
4358 s->row = row;
4359 s->area = area;
4360 s->first_glyph = row->glyphs[area] + start;
4361 s->height = row->height;
4362 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4363
9ea173e8
GM
4364 /* Display the internal border below the tool-bar window. */
4365 if (s->w == XWINDOW (s->f->tool_bar_window))
06a2c219
GM
4366 s->y -= s->f->output_data.x->internal_border_width;
4367
4368 s->ybase = s->y + row->ascent;
4369}
4370
4371
4372/* Set background width of glyph string S. START is the index of the
4373 first glyph following S. LAST_X is the right-most x-position + 1
4374 in the drawing area. */
4375
4376static INLINE void
4377x_set_glyph_string_background_width (s, start, last_x)
4378 struct glyph_string *s;
4379 int start;
4380 int last_x;
4381{
4382 /* If the face of this glyph string has to be drawn to the end of
4383 the drawing area, set S->extends_to_end_of_line_p. */
4384 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4385
4386 if (start == s->row->used[s->area]
4387 && s->hl == DRAW_NORMAL_TEXT
4388 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4389 || s->face->background != default_face->background
4390 || s->face->stipple != default_face->stipple))
4391 s->extends_to_end_of_line_p = 1;
4392
4393 /* If S extends its face to the end of the line, set its
4394 background_width to the distance to the right edge of the drawing
4395 area. */
4396 if (s->extends_to_end_of_line_p)
1da3fd71 4397 s->background_width = last_x - s->x + 1;
06a2c219
GM
4398 else
4399 s->background_width = s->width;
4400}
4401
4402
4403/* Add a glyph string for a stretch glyph to the list of strings
4404 between HEAD and TAIL. START is the index of the stretch glyph in
4405 row area AREA of glyph row ROW. END is the index of the last glyph
4406 in that glyph row area. X is the current output position assigned
4407 to the new glyph string constructed. HL overrides that face of the
4408 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4409 is the right-most x-position of the drawing area. */
4410
8abee2e1
DL
4411/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
4412 and below -- keep them on one line. */
4413#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4414 do \
4415 { \
4416 s = (struct glyph_string *) alloca (sizeof *s); \
4417 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
209f68d9 4418 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
06a2c219 4419 x_append_glyph_string (&HEAD, &TAIL, s); \
06a2c219
GM
4420 s->x = (X); \
4421 } \
4422 while (0)
4423
4424
4425/* Add a glyph string for an image glyph to the list of strings
4426 between HEAD and TAIL. START is the index of the image glyph in
4427 row area AREA of glyph row ROW. END is the index of the last glyph
4428 in that glyph row area. X is the current output position assigned
4429 to the new glyph string constructed. HL overrides that face of the
4430 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4431 is the right-most x-position of the drawing area. */
4432
8abee2e1 4433#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
06a2c219
GM
4434 do \
4435 { \
4436 s = (struct glyph_string *) alloca (sizeof *s); \
4437 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4438 x_fill_image_glyph_string (s); \
4439 x_append_glyph_string (&HEAD, &TAIL, s); \
4440 ++START; \
4441 s->x = (X); \
4442 } \
4443 while (0)
4444
4445
4446/* Add a glyph string for a sequence of character glyphs to the list
4447 of strings between HEAD and TAIL. START is the index of the first
4448 glyph in row area AREA of glyph row ROW that is part of the new
4449 glyph string. END is the index of the last glyph in that glyph row
4450 area. X is the current output position assigned to the new glyph
4451 string constructed. HL overrides that face of the glyph; e.g. it
4452 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4453 right-most x-position of the drawing area. */
4454
8abee2e1 4455#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4456 do \
4457 { \
3e71d8f2 4458 int c, face_id; \
06a2c219
GM
4459 XChar2b *char2b; \
4460 \
43d120d8 4461 c = (ROW)->glyphs[AREA][START].u.ch; \
43d120d8 4462 face_id = (ROW)->glyphs[AREA][START].face_id; \
06a2c219 4463 \
b4192550
KH
4464 s = (struct glyph_string *) alloca (sizeof *s); \
4465 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4466 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4467 x_append_glyph_string (&HEAD, &TAIL, s); \
b4192550
KH
4468 s->x = (X); \
4469 START = x_fill_glyph_string (s, face_id, START, END, \
66ac4b0e 4470 OVERLAPS_P); \
06a2c219
GM
4471 } \
4472 while (0)
4473
4474
b4192550
KH
4475/* Add a glyph string for a composite sequence to the list of strings
4476 between HEAD and TAIL. START is the index of the first glyph in
4477 row area AREA of glyph row ROW that is part of the new glyph
4478 string. END is the index of the last glyph in that glyph row area.
4479 X is the current output position assigned to the new glyph string
4480 constructed. HL overrides that face of the glyph; e.g. it is
4481 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4482 x-position of the drawing area. */
4483
6c27ec25 4484#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
b4192550 4485 do { \
43d120d8
KH
4486 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4487 int face_id = (ROW)->glyphs[AREA][START].face_id; \
ee569018 4488 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
b4192550
KH
4489 struct composition *cmp = composition_table[cmp_id]; \
4490 int glyph_len = cmp->glyph_len; \
4491 XChar2b *char2b; \
4492 struct face **faces; \
4493 struct glyph_string *first_s = NULL; \
4494 int n; \
4495 \
ee569018 4496 base_face = base_face->ascii_face; \
b4192550
KH
4497 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
4498 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4499 /* At first, fill in `char2b' and `faces'. */ \
4500 for (n = 0; n < glyph_len; n++) \
4501 { \
43d120d8 4502 int c = COMPOSITION_GLYPH (cmp, n); \
ee569018
KH
4503 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4504 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4505 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4506 this_face_id, char2b + n, 1); \
b4192550
KH
4507 } \
4508 \
4509 /* Make glyph_strings for each glyph sequence that is drawable by \
4510 the same face, and append them to HEAD/TAIL. */ \
4511 for (n = 0; n < cmp->glyph_len;) \
4512 { \
4513 s = (struct glyph_string *) alloca (sizeof *s); \
4514 x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
4515 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4516 s->cmp = cmp; \
4517 s->gidx = n; \
b4192550
KH
4518 s->x = (X); \
4519 \
4520 if (n == 0) \
4521 first_s = s; \
4522 \
4523 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4524 } \
4525 \
4526 ++START; \
4527 s = first_s; \
4528 } while (0)
4529
4530
06a2c219
GM
4531/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4532 of AREA of glyph row ROW on window W between indices START and END.
4533 HL overrides the face for drawing glyph strings, e.g. it is
4534 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4535 x-positions of the drawing area.
4536
4537 This is an ugly monster macro construct because we must use alloca
4538 to allocate glyph strings (because x_draw_glyphs can be called
4539 asynchronously). */
4540
8abee2e1 4541#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
06a2c219
GM
4542 do \
4543 { \
4544 HEAD = TAIL = NULL; \
4545 while (START < END) \
4546 { \
4547 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4548 switch (first_glyph->type) \
4549 { \
4550 case CHAR_GLYPH: \
4551 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
66ac4b0e
GM
4552 TAIL, HL, X, LAST_X, \
4553 OVERLAPS_P); \
06a2c219
GM
4554 break; \
4555 \
b4192550
KH
4556 case COMPOSITE_GLYPH: \
4557 BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
4558 HEAD, TAIL, HL, X, LAST_X,\
4559 OVERLAPS_P); \
4560 break; \
4561 \
06a2c219
GM
4562 case STRETCH_GLYPH: \
4563 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4564 HEAD, TAIL, HL, X, LAST_X); \
4565 break; \
4566 \
4567 case IMAGE_GLYPH: \
4568 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4569 TAIL, HL, X, LAST_X); \
4570 break; \
4571 \
4572 default: \
4573 abort (); \
4574 } \
4575 \
4576 x_set_glyph_string_background_width (s, START, LAST_X); \
4577 (X) += s->width; \
4578 } \
4579 } \
4580 while (0)
4581
4582
4583/* Draw glyphs between START and END in AREA of ROW on window W,
4584 starting at x-position X. X is relative to AREA in W. HL is a
4585 face-override with the following meaning:
4586
4587 DRAW_NORMAL_TEXT draw normally
4588 DRAW_CURSOR draw in cursor face
4589 DRAW_MOUSE_FACE draw in mouse face.
4590 DRAW_INVERSE_VIDEO draw in mode line face
4591 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4592 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4593
4594 If REAL_START is non-null, return in *REAL_START the real starting
4595 position for display. This can be different from START in case
4596 overlapping glyphs must be displayed. If REAL_END is non-null,
4597 return in *REAL_END the real end position for display. This can be
4598 different from END in case overlapping glyphs must be displayed.
4599
66ac4b0e
GM
4600 If OVERLAPS_P is non-zero, draw only the foreground of characters
4601 and clip to the physical height of ROW.
4602
06a2c219
GM
4603 Value is the x-position reached, relative to AREA of W. */
4604
4605static int
66ac4b0e
GM
4606x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4607 overlaps_p)
06a2c219
GM
4608 struct window *w;
4609 int x;
4610 struct glyph_row *row;
4611 enum glyph_row_area area;
4612 int start, end;
4613 enum draw_glyphs_face hl;
4614 int *real_start, *real_end;
66ac4b0e 4615 int overlaps_p;
dc6f92b8 4616{
06a2c219
GM
4617 struct glyph_string *head, *tail;
4618 struct glyph_string *s;
4619 int last_x, area_width;
4620 int x_reached;
4621 int i, j;
4622
4623 /* Let's rather be paranoid than getting a SEGV. */
4624 start = max (0, start);
4625 end = min (end, row->used[area]);
4626 if (real_start)
4627 *real_start = start;
4628 if (real_end)
4629 *real_end = end;
4630
4631 /* Translate X to frame coordinates. Set last_x to the right
4632 end of the drawing area. */
4633 if (row->full_width_p)
4634 {
4635 /* X is relative to the left edge of W, without scroll bars
4636 or flag areas. */
4637 struct frame *f = XFRAME (w->frame);
110859fc 4638 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
06a2c219 4639 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4640
06a2c219
GM
4641 x += window_left_x;
4642 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4643 last_x = window_left_x + area_width;
4644
4645 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4646 {
110859fc 4647 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
06a2c219
GM
4648 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4649 last_x += width;
4650 else
4651 x -= width;
4652 }
dc6f92b8 4653
b9432a85
GM
4654 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4655 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4656 }
4657 else
dc6f92b8 4658 {
06a2c219
GM
4659 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4660 area_width = window_box_width (w, area);
4661 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4662 }
4663
06a2c219
GM
4664 /* Build a doubly-linked list of glyph_string structures between
4665 head and tail from what we have to draw. Note that the macro
4666 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4667 the reason we use a separate variable `i'. */
4668 i = start;
66ac4b0e
GM
4669 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
4670 overlaps_p);
06a2c219
GM
4671 if (tail)
4672 x_reached = tail->x + tail->background_width;
4673 else
4674 x_reached = x;
90e65f07 4675
06a2c219
GM
4676 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4677 the row, redraw some glyphs in front or following the glyph
4678 strings built above. */
66ac4b0e 4679 if (!overlaps_p && row->contains_overlapping_glyphs_p)
06a2c219
GM
4680 {
4681 int dummy_x = 0;
4682 struct glyph_string *h, *t;
4683
4684 /* Compute overhangs for all glyph strings. */
4685 for (s = head; s; s = s->next)
4686 x_compute_glyph_string_overhangs (s);
4687
4688 /* Prepend glyph strings for glyphs in front of the first glyph
4689 string that are overwritten because of the first glyph
4690 string's left overhang. The background of all strings
4691 prepended must be drawn because the first glyph string
4692 draws over it. */
4693 i = x_left_overwritten (head);
4694 if (i >= 0)
4695 {
4696 j = i;
4697 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
66ac4b0e
GM
4698 DRAW_NORMAL_TEXT, dummy_x, last_x,
4699 overlaps_p);
06a2c219
GM
4700 start = i;
4701 if (real_start)
4702 *real_start = start;
4703 x_compute_overhangs_and_x (t, head->x, 1);
4704 x_prepend_glyph_string_lists (&head, &tail, h, t);
4705 }
58769bee 4706
06a2c219
GM
4707 /* Prepend glyph strings for glyphs in front of the first glyph
4708 string that overwrite that glyph string because of their
4709 right overhang. For these strings, only the foreground must
4710 be drawn, because it draws over the glyph string at `head'.
4711 The background must not be drawn because this would overwrite
4712 right overhangs of preceding glyphs for which no glyph
4713 strings exist. */
4714 i = x_left_overwriting (head);
4715 if (i >= 0)
4716 {
4717 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
66ac4b0e
GM
4718 DRAW_NORMAL_TEXT, dummy_x, last_x,
4719 overlaps_p);
06a2c219
GM
4720 for (s = h; s; s = s->next)
4721 s->background_filled_p = 1;
4722 if (real_start)
4723 *real_start = i;
4724 x_compute_overhangs_and_x (t, head->x, 1);
4725 x_prepend_glyph_string_lists (&head, &tail, h, t);
4726 }
dbcb258a 4727
06a2c219
GM
4728 /* Append glyphs strings for glyphs following the last glyph
4729 string tail that are overwritten by tail. The background of
4730 these strings has to be drawn because tail's foreground draws
4731 over it. */
4732 i = x_right_overwritten (tail);
4733 if (i >= 0)
4734 {
4735 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4736 DRAW_NORMAL_TEXT, x, last_x,
4737 overlaps_p);
06a2c219
GM
4738 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4739 x_append_glyph_string_lists (&head, &tail, h, t);
4740 if (real_end)
4741 *real_end = i;
4742 }
dc6f92b8 4743
06a2c219
GM
4744 /* Append glyph strings for glyphs following the last glyph
4745 string tail that overwrite tail. The foreground of such
4746 glyphs has to be drawn because it writes into the background
4747 of tail. The background must not be drawn because it could
4748 paint over the foreground of following glyphs. */
4749 i = x_right_overwriting (tail);
4750 if (i >= 0)
4751 {
4752 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
66ac4b0e
GM
4753 DRAW_NORMAL_TEXT, x, last_x,
4754 overlaps_p);
06a2c219
GM
4755 for (s = h; s; s = s->next)
4756 s->background_filled_p = 1;
4757 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4758 x_append_glyph_string_lists (&head, &tail, h, t);
4759 if (real_end)
4760 *real_end = i;
4761 }
4762 }
58769bee 4763
06a2c219
GM
4764 /* Draw all strings. */
4765 for (s = head; s; s = s->next)
4766 x_draw_glyph_string (s);
dc6f92b8 4767
06a2c219
GM
4768 /* Value is the x-position up to which drawn, relative to AREA of W.
4769 This doesn't include parts drawn because of overhangs. */
4770 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4771 if (!row->full_width_p)
4772 {
4773 if (area > LEFT_MARGIN_AREA)
4774 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4775 if (area > TEXT_AREA)
4776 x_reached -= window_box_width (w, TEXT_AREA);
4777 }
4778 return x_reached;
4779}
dc6f92b8 4780
dc6f92b8 4781
66ac4b0e
GM
4782/* Fix the display of area AREA of overlapping row ROW in window W. */
4783
4784static void
4785x_fix_overlapping_area (w, row, area)
4786 struct window *w;
4787 struct glyph_row *row;
4788 enum glyph_row_area area;
4789{
4790 int i, x;
4791
4792 BLOCK_INPUT;
4793
4794 if (area == LEFT_MARGIN_AREA)
4795 x = 0;
4796 else if (area == TEXT_AREA)
4797 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4798 else
4799 x = (window_box_width (w, LEFT_MARGIN_AREA)
4800 + window_box_width (w, TEXT_AREA));
4801
4802 for (i = 0; i < row->used[area];)
4803 {
4804 if (row->glyphs[area][i].overlaps_vertically_p)
4805 {
4806 int start = i, start_x = x;
4807
4808 do
4809 {
4810 x += row->glyphs[area][i].pixel_width;
4811 ++i;
4812 }
4813 while (i < row->used[area]
4814 && row->glyphs[area][i].overlaps_vertically_p);
4815
4816 x_draw_glyphs (w, start_x, row, area, start, i,
4817 (row->inverse_p
4818 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4819 NULL, NULL, 1);
4820 }
4821 else
4822 {
4823 x += row->glyphs[area][i].pixel_width;
4824 ++i;
4825 }
4826 }
4827
4828 UNBLOCK_INPUT;
4829}
4830
4831
06a2c219
GM
4832/* Output LEN glyphs starting at START at the nominal cursor position.
4833 Advance the nominal cursor over the text. The global variable
4834 updated_window contains the window being updated, updated_row is
4835 the glyph row being updated, and updated_area is the area of that
4836 row being updated. */
dc6f92b8 4837
06a2c219
GM
4838static void
4839x_write_glyphs (start, len)
4840 struct glyph *start;
4841 int len;
4842{
4843 int x, hpos, real_start, real_end;
d9cdbb3d 4844
06a2c219 4845 xassert (updated_window && updated_row);
dc6f92b8 4846 BLOCK_INPUT;
06a2c219
GM
4847
4848 /* Write glyphs. */
dc6f92b8 4849
06a2c219
GM
4850 hpos = start - updated_row->glyphs[updated_area];
4851 x = x_draw_glyphs (updated_window, output_cursor.x,
4852 updated_row, updated_area,
4853 hpos, hpos + len,
4854 (updated_row->inverse_p
4855 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
66ac4b0e 4856 &real_start, &real_end, 0);
b30ec466 4857
06a2c219
GM
4858 /* If we drew over the cursor, note that it is not visible any more. */
4859 note_overwritten_text_cursor (updated_window, real_start,
4860 real_end - real_start);
dc6f92b8
JB
4861
4862 UNBLOCK_INPUT;
06a2c219
GM
4863
4864 /* Advance the output cursor. */
4865 output_cursor.hpos += len;
4866 output_cursor.x = x;
dc6f92b8
JB
4867}
4868
0cdd0c9f 4869
06a2c219 4870/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4871
06a2c219
GM
4872static void
4873x_insert_glyphs (start, len)
4874 struct glyph *start;
4875 register int len;
4876{
4877 struct frame *f;
4878 struct window *w;
4879 int line_height, shift_by_width, shifted_region_width;
4880 struct glyph_row *row;
4881 struct glyph *glyph;
4882 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4883
06a2c219 4884 xassert (updated_window && updated_row);
0cdd0c9f 4885 BLOCK_INPUT;
06a2c219
GM
4886 w = updated_window;
4887 f = XFRAME (WINDOW_FRAME (w));
4888
4889 /* Get the height of the line we are in. */
4890 row = updated_row;
4891 line_height = row->height;
4892
4893 /* Get the width of the glyphs to insert. */
4894 shift_by_width = 0;
4895 for (glyph = start; glyph < start + len; ++glyph)
4896 shift_by_width += glyph->pixel_width;
4897
4898 /* Get the width of the region to shift right. */
4899 shifted_region_width = (window_box_width (w, updated_area)
4900 - output_cursor.x
4901 - shift_by_width);
4902
4903 /* Shift right. */
4904 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4905 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4906 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4907 f->output_data.x->normal_gc,
4908 frame_x, frame_y,
4909 shifted_region_width, line_height,
4910 frame_x + shift_by_width, frame_y);
4911
4912 /* Write the glyphs. */
4913 hpos = start - row->glyphs[updated_area];
4914 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
66ac4b0e 4915 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
06a2c219
GM
4916 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4917
4918 /* Advance the output cursor. */
4919 output_cursor.hpos += len;
4920 output_cursor.x += shift_by_width;
0cdd0c9f
RS
4921 UNBLOCK_INPUT;
4922}
0cdd0c9f 4923
0cdd0c9f 4924
06a2c219
GM
4925/* Delete N glyphs at the nominal cursor position. Not implemented
4926 for X frames. */
c83febd7
RS
4927
4928static void
06a2c219
GM
4929x_delete_glyphs (n)
4930 register int n;
c83febd7 4931{
06a2c219 4932 abort ();
c83febd7
RS
4933}
4934
0cdd0c9f 4935
06a2c219
GM
4936/* Erase the current text line from the nominal cursor position
4937 (inclusive) to pixel column TO_X (exclusive). The idea is that
4938 everything from TO_X onward is already erased.
4939
4940 TO_X is a pixel position relative to updated_area of
4941 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 4942
06a2c219
GM
4943static void
4944x_clear_end_of_line (to_x)
4945 int to_x;
4946{
4947 struct frame *f;
4948 struct window *w = updated_window;
4949 int max_x, min_y, max_y;
4950 int from_x, from_y, to_y;
4951
4952 xassert (updated_window && updated_row);
4953 f = XFRAME (w->frame);
4954
4955 if (updated_row->full_width_p)
4956 {
4957 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4958 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4959 && !w->pseudo_window_p)
4960 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 4961 }
06a2c219
GM
4962 else
4963 max_x = window_box_width (w, updated_area);
4964 max_y = window_text_bottom_y (w);
dc6f92b8 4965
06a2c219
GM
4966 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4967 of window. For TO_X > 0, truncate to end of drawing area. */
4968 if (to_x == 0)
4969 return;
4970 else if (to_x < 0)
4971 to_x = max_x;
4972 else
4973 to_x = min (to_x, max_x);
dbc4e1c1 4974
06a2c219
GM
4975 to_y = min (max_y, output_cursor.y + updated_row->height);
4976
4977 /* Notice if the cursor will be cleared by this operation. */
4978 if (!updated_row->full_width_p)
4979 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 4980
06a2c219
GM
4981 from_x = output_cursor.x;
4982
4983 /* Translate to frame coordinates. */
4984 if (updated_row->full_width_p)
4985 {
4986 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4987 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4988 }
0cdd0c9f
RS
4989 else
4990 {
06a2c219
GM
4991 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4992 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4993 }
4994
045dee35 4995 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
06a2c219
GM
4996 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4997 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4998
4999 /* Prevent inadvertently clearing to end of the X window. */
5000 if (to_x > from_x && to_y > from_y)
5001 {
5002 BLOCK_INPUT;
5003 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5004 from_x, from_y, to_x - from_x, to_y - from_y,
5005 False);
5006 UNBLOCK_INPUT;
0cdd0c9f 5007 }
0cdd0c9f 5008}
dbc4e1c1 5009
0cdd0c9f 5010
06a2c219 5011/* Clear entire frame. If updating_frame is non-null, clear that
b86bd3dd 5012 frame. Otherwise clear the selected frame. */
06a2c219
GM
5013
5014static void
5015x_clear_frame ()
0cdd0c9f 5016{
06a2c219 5017 struct frame *f;
0cdd0c9f 5018
06a2c219
GM
5019 if (updating_frame)
5020 f = updating_frame;
0cdd0c9f 5021 else
b86bd3dd 5022 f = SELECTED_FRAME ();
58769bee 5023
06a2c219
GM
5024 /* Clearing the frame will erase any cursor, so mark them all as no
5025 longer visible. */
5026 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5027 output_cursor.hpos = output_cursor.vpos = 0;
5028 output_cursor.x = -1;
5029
5030 /* We don't set the output cursor here because there will always
5031 follow an explicit cursor_to. */
5032 BLOCK_INPUT;
5033 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
5034
5035 /* We have to clear the scroll bars, too. If we have changed
5036 colors or something like that, then they should be notified. */
5037 x_scroll_bar_clear (f);
0cdd0c9f 5038
06a2c219
GM
5039 XFlush (FRAME_X_DISPLAY (f));
5040 UNBLOCK_INPUT;
dc6f92b8 5041}
06a2c219
GM
5042
5043
dc6f92b8 5044\f
dbc4e1c1
JB
5045/* Invert the middle quarter of the frame for .15 sec. */
5046
06a2c219
GM
5047/* We use the select system call to do the waiting, so we have to make
5048 sure it's available. If it isn't, we just won't do visual bells. */
5049
dbc4e1c1
JB
5050#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
5051
06a2c219
GM
5052
5053/* Subtract the `struct timeval' values X and Y, storing the result in
5054 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
5055
5056static int
5057timeval_subtract (result, x, y)
5058 struct timeval *result, x, y;
5059{
06a2c219
GM
5060 /* Perform the carry for the later subtraction by updating y. This
5061 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
5062 if (x.tv_usec < y.tv_usec)
5063 {
5064 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
5065 y.tv_usec -= 1000000 * nsec;
5066 y.tv_sec += nsec;
5067 }
06a2c219 5068
dbc4e1c1
JB
5069 if (x.tv_usec - y.tv_usec > 1000000)
5070 {
5071 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
5072 y.tv_usec += 1000000 * nsec;
5073 y.tv_sec -= nsec;
5074 }
5075
06a2c219
GM
5076 /* Compute the time remaining to wait. tv_usec is certainly
5077 positive. */
dbc4e1c1
JB
5078 result->tv_sec = x.tv_sec - y.tv_sec;
5079 result->tv_usec = x.tv_usec - y.tv_usec;
5080
06a2c219
GM
5081 /* Return indication of whether the result should be considered
5082 negative. */
dbc4e1c1
JB
5083 return x.tv_sec < y.tv_sec;
5084}
dc6f92b8 5085
dfcf069d 5086void
f676886a
JB
5087XTflash (f)
5088 struct frame *f;
dc6f92b8 5089{
dbc4e1c1 5090 BLOCK_INPUT;
dc6f92b8 5091
dbc4e1c1
JB
5092 {
5093 GC gc;
dc6f92b8 5094
06a2c219
GM
5095 /* Create a GC that will use the GXxor function to flip foreground
5096 pixels into background pixels. */
dbc4e1c1
JB
5097 {
5098 XGCValues values;
dc6f92b8 5099
dbc4e1c1 5100 values.function = GXxor;
7556890b
RS
5101 values.foreground = (f->output_data.x->foreground_pixel
5102 ^ f->output_data.x->background_pixel);
58769bee 5103
334208b7 5104 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
5105 GCFunction | GCForeground, &values);
5106 }
dc6f92b8 5107
dbc4e1c1 5108 {
e84e14c3
RS
5109 /* Get the height not including a menu bar widget. */
5110 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
5111 /* Height of each line to flash. */
5112 int flash_height = FRAME_LINE_HEIGHT (f);
5113 /* These will be the left and right margins of the rectangles. */
5114 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
5115 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
5116
5117 int width;
5118
5119 /* Don't flash the area between a scroll bar and the frame
5120 edge it is next to. */
5121 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
5122 {
5123 case vertical_scroll_bar_left:
5124 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5125 break;
5126
5127 case vertical_scroll_bar_right:
5128 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
5129 break;
06a2c219
GM
5130
5131 default:
5132 break;
e84e14c3
RS
5133 }
5134
5135 width = flash_right - flash_left;
5136
5137 /* If window is tall, flash top and bottom line. */
5138 if (height > 3 * FRAME_LINE_HEIGHT (f))
5139 {
5140 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5141 flash_left,
5142 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5143 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5144 width, flash_height);
5145 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5146 flash_left,
5147 (height - flash_height
5148 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5149 width, flash_height);
5150 }
5151 else
5152 /* If it is short, flash it all. */
5153 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5154 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5155 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 5156
06a2c219 5157 x_flush (f);
dc6f92b8 5158
dbc4e1c1 5159 {
06a2c219 5160 struct timeval wakeup;
dc6f92b8 5161
66c30ea1 5162 EMACS_GET_TIME (wakeup);
dc6f92b8 5163
dbc4e1c1
JB
5164 /* Compute time to wait until, propagating carry from usecs. */
5165 wakeup.tv_usec += 150000;
5166 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
5167 wakeup.tv_usec %= 1000000;
5168
5169 /* Keep waiting until past the time wakeup. */
5170 while (1)
5171 {
5172 struct timeval timeout;
5173
66c30ea1 5174 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
5175
5176 /* In effect, timeout = wakeup - timeout.
5177 Break if result would be negative. */
5178 if (timeval_subtract (&timeout, wakeup, timeout))
5179 break;
5180
5181 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 5182 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
5183 }
5184 }
58769bee 5185
e84e14c3
RS
5186 /* If window is tall, flash top and bottom line. */
5187 if (height > 3 * FRAME_LINE_HEIGHT (f))
5188 {
5189 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
5190 flash_left,
5191 (FRAME_INTERNAL_BORDER_WIDTH (f)
9ea173e8 5192 + FRAME_TOOL_BAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
5193 width, flash_height);
5194 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5195 flash_left,
5196 (height - flash_height
5197 - FRAME_INTERNAL_BORDER_WIDTH (f)),
5198 width, flash_height);
5199 }
5200 else
5201 /* If it is short, flash it all. */
5202 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
5203 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
5204 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
5205
334208b7 5206 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 5207 x_flush (f);
dc6f92b8 5208 }
dbc4e1c1
JB
5209 }
5210
5211 UNBLOCK_INPUT;
dc6f92b8
JB
5212}
5213
06a2c219 5214#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
5215
5216
dc6f92b8
JB
5217/* Make audible bell. */
5218
dfcf069d 5219void
dc6f92b8
JB
5220XTring_bell ()
5221{
b86bd3dd
GM
5222 struct frame *f = SELECTED_FRAME ();
5223
5224 if (FRAME_X_DISPLAY (f))
5225 {
dbc4e1c1 5226#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
b86bd3dd
GM
5227 if (visible_bell)
5228 XTflash (f);
5229 else
dbc4e1c1 5230#endif
b86bd3dd
GM
5231 {
5232 BLOCK_INPUT;
5233 XBell (FRAME_X_DISPLAY (f), 0);
5234 XFlush (FRAME_X_DISPLAY (f));
5235 UNBLOCK_INPUT;
5236 }
dc6f92b8
JB
5237 }
5238}
06a2c219 5239
dc6f92b8 5240\f
06a2c219
GM
5241/* Specify how many text lines, from the top of the window,
5242 should be affected by insert-lines and delete-lines operations.
5243 This, and those operations, are used only within an update
5244 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 5245
dfcf069d 5246static void
06a2c219
GM
5247XTset_terminal_window (n)
5248 register int n;
dc6f92b8 5249{
06a2c219 5250 /* This function intentionally left blank. */
dc6f92b8
JB
5251}
5252
06a2c219
GM
5253
5254\f
5255/***********************************************************************
5256 Line Dance
5257 ***********************************************************************/
5258
5259/* Perform an insert-lines or delete-lines operation, inserting N
5260 lines or deleting -N lines at vertical position VPOS. */
5261
dfcf069d 5262static void
06a2c219
GM
5263x_ins_del_lines (vpos, n)
5264 int vpos, n;
dc6f92b8
JB
5265{
5266 abort ();
5267}
06a2c219
GM
5268
5269
5270/* Scroll part of the display as described by RUN. */
dc6f92b8 5271
dfcf069d 5272static void
06a2c219
GM
5273x_scroll_run (w, run)
5274 struct window *w;
5275 struct run *run;
dc6f92b8 5276{
06a2c219
GM
5277 struct frame *f = XFRAME (w->frame);
5278 int x, y, width, height, from_y, to_y, bottom_y;
5279
5280 /* Get frame-relative bounding box of the text display area of W,
5281 without mode lines. Include in this box the flags areas to the
5282 left and right of W. */
5283 window_box (w, -1, &x, &y, &width, &height);
110859fc
GM
5284 width += FRAME_X_FLAGS_AREA_WIDTH (f);
5285 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
06a2c219
GM
5286
5287 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5288 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5289 bottom_y = y + height;
dc6f92b8 5290
06a2c219
GM
5291 if (to_y < from_y)
5292 {
5293 /* Scrolling up. Make sure we don't copy part of the mode
5294 line at the bottom. */
5295 if (from_y + run->height > bottom_y)
5296 height = bottom_y - from_y;
5297 else
5298 height = run->height;
5299 }
dc6f92b8 5300 else
06a2c219
GM
5301 {
5302 /* Scolling down. Make sure we don't copy over the mode line.
5303 at the bottom. */
5304 if (to_y + run->height > bottom_y)
5305 height = bottom_y - to_y;
5306 else
5307 height = run->height;
5308 }
7a13e894 5309
06a2c219
GM
5310 BLOCK_INPUT;
5311
5312 /* Cursor off. Will be switched on again in x_update_window_end. */
5313 updated_window = w;
5314 x_clear_cursor (w);
5315
5316 XCopyArea (FRAME_X_DISPLAY (f),
5317 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
5318 f->output_data.x->normal_gc,
5319 x, from_y,
5320 width, height,
5321 x, to_y);
5322
5323 UNBLOCK_INPUT;
5324}
dc6f92b8 5325
dc6f92b8 5326
06a2c219
GM
5327\f
5328/***********************************************************************
5329 Exposure Events
5330 ***********************************************************************/
5331
5332/* Redisplay an exposed area of frame F. X and Y are the upper-left
5333 corner of the exposed rectangle. W and H are width and height of
5334 the exposed area. All are pixel values. W or H zero means redraw
5335 the entire frame. */
dc6f92b8 5336
06a2c219
GM
5337static void
5338expose_frame (f, x, y, w, h)
5339 struct frame *f;
5340 int x, y, w, h;
dc6f92b8 5341{
06a2c219 5342 XRectangle r;
dc6f92b8 5343
06a2c219 5344 TRACE ((stderr, "expose_frame "));
dc6f92b8 5345
06a2c219
GM
5346 /* No need to redraw if frame will be redrawn soon. */
5347 if (FRAME_GARBAGED_P (f))
dc6f92b8 5348 {
06a2c219
GM
5349 TRACE ((stderr, " garbaged\n"));
5350 return;
5351 }
5352
5353 /* If basic faces haven't been realized yet, there is no point in
5354 trying to redraw anything. This can happen when we get an expose
5355 event while Emacs is starting, e.g. by moving another window. */
5356 if (FRAME_FACE_CACHE (f) == NULL
5357 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5358 {
5359 TRACE ((stderr, " no faces\n"));
5360 return;
58769bee 5361 }
06a2c219
GM
5362
5363 if (w == 0 || h == 0)
58769bee 5364 {
06a2c219
GM
5365 r.x = r.y = 0;
5366 r.width = CANON_X_UNIT (f) * f->width;
5367 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
5368 }
5369 else
5370 {
06a2c219
GM
5371 r.x = x;
5372 r.y = y;
5373 r.width = w;
5374 r.height = h;
5375 }
5376
5377 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
5378 expose_window_tree (XWINDOW (f->root_window), &r);
5379
9ea173e8 5380 if (WINDOWP (f->tool_bar_window))
06a2c219 5381 {
9ea173e8 5382 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
5383 XRectangle window_rect;
5384 XRectangle intersection_rect;
5385 int window_x, window_y, window_width, window_height;
5386
5387
5388 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5389 window_rect.x = window_x;
5390 window_rect.y = window_y;
5391 window_rect.width = window_width;
5392 window_rect.height = window_height;
5393
5394 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5395 expose_window (w, &intersection_rect);
5396 }
5397
5398#ifndef USE_X_TOOLKIT
5399 if (WINDOWP (f->menu_bar_window))
5400 {
5401 struct window *w = XWINDOW (f->menu_bar_window);
5402 XRectangle window_rect;
5403 XRectangle intersection_rect;
5404 int window_x, window_y, window_width, window_height;
5405
5406
5407 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5408 window_rect.x = window_x;
5409 window_rect.y = window_y;
5410 window_rect.width = window_width;
5411 window_rect.height = window_height;
5412
5413 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
5414 expose_window (w, &intersection_rect);
dc6f92b8 5415 }
06a2c219 5416#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
5417}
5418
06a2c219
GM
5419
5420/* Redraw (parts) of all windows in the window tree rooted at W that
5421 intersect R. R contains frame pixel coordinates. */
5422
58769bee 5423static void
06a2c219
GM
5424expose_window_tree (w, r)
5425 struct window *w;
5426 XRectangle *r;
dc6f92b8 5427{
06a2c219
GM
5428 while (w)
5429 {
5430 if (!NILP (w->hchild))
5431 expose_window_tree (XWINDOW (w->hchild), r);
5432 else if (!NILP (w->vchild))
5433 expose_window_tree (XWINDOW (w->vchild), r);
5434 else
5435 {
5436 XRectangle window_rect;
5437 XRectangle intersection_rect;
5438 struct frame *f = XFRAME (w->frame);
5439 int window_x, window_y, window_width, window_height;
5440
5441 /* Frame-relative pixel rectangle of W. */
5442 window_box (w, -1, &window_x, &window_y, &window_width,
5443 &window_height);
5444 window_rect.x
5445 = (window_x
110859fc 5446 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
714dc26c 5447 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
06a2c219
GM
5448 window_rect.y = window_y;
5449 window_rect.width
5450 = (window_width
110859fc 5451 + FRAME_X_FLAGS_AREA_WIDTH (f)
06a2c219
GM
5452 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5453 window_rect.height
5454 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5455
5456 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5457 expose_window (w, &intersection_rect);
5458 }
58769bee 5459
06a2c219
GM
5460 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5461 }
5462}
58769bee 5463
dc6f92b8 5464
06a2c219
GM
5465/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5466 which intersects rectangle R. R is in window-relative coordinates. */
5467
5468static void
5469expose_area (w, row, r, area)
5470 struct window *w;
5471 struct glyph_row *row;
5472 XRectangle *r;
5473 enum glyph_row_area area;
5474{
5475 int x;
5476 struct glyph *first = row->glyphs[area];
5477 struct glyph *end = row->glyphs[area] + row->used[area];
5478 struct glyph *last;
5479 int first_x;
5480
5481 /* Set x to the window-relative start position for drawing glyphs of
5482 AREA. The first glyph of the text area can be partially visible.
5483 The first glyphs of other areas cannot. */
5484 if (area == LEFT_MARGIN_AREA)
5485 x = 0;
5486 else if (area == TEXT_AREA)
5487 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5488 else
5489 x = (window_box_width (w, LEFT_MARGIN_AREA)
5490 + window_box_width (w, TEXT_AREA));
5491
6fb13182
GM
5492 if (area == TEXT_AREA && row->fill_line_p)
5493 /* If row extends face to end of line write the whole line. */
5494 x_draw_glyphs (w, x, row, area,
5495 0, row->used[area],
06a2c219 5496 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5497 NULL, NULL, 0);
6fb13182
GM
5498 else
5499 {
5500 /* Find the first glyph that must be redrawn. */
5501 while (first < end
5502 && x + first->pixel_width < r->x)
5503 {
5504 x += first->pixel_width;
5505 ++first;
5506 }
5507
5508 /* Find the last one. */
5509 last = first;
5510 first_x = x;
5511 while (last < end
5512 && x < r->x + r->width)
5513 {
5514 x += last->pixel_width;
5515 ++last;
5516 }
5517
5518 /* Repaint. */
5519 if (last > first)
5520 x_draw_glyphs (w, first_x, row, area,
5521 first - row->glyphs[area],
5522 last - row->glyphs[area],
5523 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5524 NULL, NULL, 0);
5525 }
06a2c219
GM
5526}
5527
58769bee 5528
06a2c219
GM
5529/* Redraw the parts of the glyph row ROW on window W intersecting
5530 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5531
06a2c219
GM
5532static void
5533expose_line (w, row, r)
5534 struct window *w;
5535 struct glyph_row *row;
5536 XRectangle *r;
5537{
5538 xassert (row->enabled_p);
5539
5540 if (row->mode_line_p || w->pseudo_window_p)
5541 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5542 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
66ac4b0e 5543 NULL, NULL, 0);
06a2c219
GM
5544 else
5545 {
5546 if (row->used[LEFT_MARGIN_AREA])
5547 expose_area (w, row, r, LEFT_MARGIN_AREA);
5548 if (row->used[TEXT_AREA])
5549 expose_area (w, row, r, TEXT_AREA);
5550 if (row->used[RIGHT_MARGIN_AREA])
5551 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5552 x_draw_row_bitmaps (w, row);
5553 }
5554}
dc6f92b8 5555
58769bee 5556
06a2c219
GM
5557/* Return non-zero if W's cursor intersects rectangle R. */
5558
5559static int
5560x_phys_cursor_in_rect_p (w, r)
5561 struct window *w;
5562 XRectangle *r;
5563{
5564 XRectangle cr, result;
5565 struct glyph *cursor_glyph;
5566
5567 cursor_glyph = get_phys_cursor_glyph (w);
5568 if (cursor_glyph)
5569 {
5570 cr.x = w->phys_cursor.x;
5571 cr.y = w->phys_cursor.y;
5572 cr.width = cursor_glyph->pixel_width;
5573 cr.height = w->phys_cursor_height;
5574 return x_intersect_rectangles (&cr, r, &result);
5575 }
5576 else
5577 return 0;
dc6f92b8 5578}
dc6f92b8 5579
06a2c219
GM
5580
5581/* Redraw a rectangle of window W. R is a rectangle in window
5582 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5583
5584static void
06a2c219
GM
5585expose_window (w, r)
5586 struct window *w;
5587 XRectangle *r;
dc6f92b8 5588{
06a2c219
GM
5589 struct glyph_row *row;
5590 int y;
5591 int yb = window_text_bottom_y (w);
5592 int cursor_cleared_p;
dc6f92b8 5593
80c32bcc
GM
5594 /* If window is not yet fully initialized, do nothing. This can
5595 happen when toolkit scroll bars are used and a window is split.
5596 Reconfiguring the scroll bar will generate an expose for a newly
5597 created window. */
5598 if (w->current_matrix == NULL)
5599 return;
5600
06a2c219
GM
5601 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5602 r->x, r->y, r->width, r->height));
dc6f92b8 5603
06a2c219
GM
5604 /* Convert to window coordinates. */
5605 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5606 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5607
06a2c219
GM
5608 /* Turn off the cursor. */
5609 if (!w->pseudo_window_p
5610 && x_phys_cursor_in_rect_p (w, r))
5611 {
5612 x_clear_cursor (w);
5613 cursor_cleared_p = 1;
5614 }
5615 else
5616 cursor_cleared_p = 0;
5617
5618 /* Find the first row intersecting the rectangle R. */
5619 row = w->current_matrix->rows;
5620 y = 0;
5621 while (row->enabled_p
5622 && y < yb
5623 && y + row->height < r->y)
5624 {
5625 y += row->height;
5626 ++row;
5627 }
5628
dc6f92b8 5629 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5630 while (row->enabled_p
5631 && y < yb
5632 && y < r->y + r->height)
5633 {
5634 expose_line (w, row, r);
5635 y += row->height;
5636 ++row;
5637 }
5638
5639 /* Display the mode line if there is one. */
5640 if (WINDOW_WANTS_MODELINE_P (w)
5641 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5642 row->enabled_p)
5643 && row->y < r->y + r->height)
5644 expose_line (w, row, r);
dc6f92b8 5645
06a2c219 5646 if (!w->pseudo_window_p)
dc6f92b8 5647 {
06a2c219
GM
5648 /* Draw border between windows. */
5649 x_draw_vertical_border (w);
5650
5651 /* Turn the cursor on again. */
5652 if (cursor_cleared_p)
5653 x_update_window_cursor (w, 1);
5654 }
5655}
dc6f92b8 5656
dc6f92b8 5657
06a2c219
GM
5658/* Determine the intersection of two rectangles R1 and R2. Return
5659 the intersection in *RESULT. Value is non-zero if RESULT is not
5660 empty. */
5661
5662static int
5663x_intersect_rectangles (r1, r2, result)
5664 XRectangle *r1, *r2, *result;
5665{
5666 XRectangle *left, *right;
5667 XRectangle *upper, *lower;
5668 int intersection_p = 0;
5669
5670 /* Rearrange so that R1 is the left-most rectangle. */
5671 if (r1->x < r2->x)
5672 left = r1, right = r2;
5673 else
5674 left = r2, right = r1;
5675
5676 /* X0 of the intersection is right.x0, if this is inside R1,
5677 otherwise there is no intersection. */
5678 if (right->x <= left->x + left->width)
5679 {
5680 result->x = right->x;
5681
5682 /* The right end of the intersection is the minimum of the
5683 the right ends of left and right. */
5684 result->width = (min (left->x + left->width, right->x + right->width)
5685 - result->x);
5686
5687 /* Same game for Y. */
5688 if (r1->y < r2->y)
5689 upper = r1, lower = r2;
5690 else
5691 upper = r2, lower = r1;
5692
5693 /* The upper end of the intersection is lower.y0, if this is inside
5694 of upper. Otherwise, there is no intersection. */
5695 if (lower->y <= upper->y + upper->height)
dc43ef94 5696 {
06a2c219
GM
5697 result->y = lower->y;
5698
5699 /* The lower end of the intersection is the minimum of the lower
5700 ends of upper and lower. */
5701 result->height = (min (lower->y + lower->height,
5702 upper->y + upper->height)
5703 - result->y);
5704 intersection_p = 1;
dc43ef94 5705 }
dc6f92b8
JB
5706 }
5707
06a2c219 5708 return intersection_p;
dc6f92b8 5709}
06a2c219
GM
5710
5711
5712
5713
dc6f92b8 5714\f
dc6f92b8 5715static void
334208b7
RS
5716frame_highlight (f)
5717 struct frame *f;
dc6f92b8 5718{
b3e1e05c
JB
5719 /* We used to only do this if Vx_no_window_manager was non-nil, but
5720 the ICCCM (section 4.1.6) says that the window's border pixmap
5721 and border pixel are window attributes which are "private to the
5722 client", so we can always change it to whatever we want. */
5723 BLOCK_INPUT;
334208b7 5724 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5725 f->output_data.x->border_pixel);
b3e1e05c 5726 UNBLOCK_INPUT;
5d46f928 5727 x_update_cursor (f, 1);
dc6f92b8
JB
5728}
5729
5730static void
334208b7
RS
5731frame_unhighlight (f)
5732 struct frame *f;
dc6f92b8 5733{
b3e1e05c
JB
5734 /* We used to only do this if Vx_no_window_manager was non-nil, but
5735 the ICCCM (section 4.1.6) says that the window's border pixmap
5736 and border pixel are window attributes which are "private to the
5737 client", so we can always change it to whatever we want. */
5738 BLOCK_INPUT;
334208b7 5739 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5740 f->output_data.x->border_tile);
b3e1e05c 5741 UNBLOCK_INPUT;
5d46f928 5742 x_update_cursor (f, 1);
dc6f92b8 5743}
dc6f92b8 5744
f676886a
JB
5745/* The focus has changed. Update the frames as necessary to reflect
5746 the new situation. Note that we can't change the selected frame
c5acd733 5747 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5748 Each event gets marked with the frame in which it occurred, so the
c5acd733 5749 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5750
6d4238f3 5751static void
0f941935
KH
5752x_new_focus_frame (dpyinfo, frame)
5753 struct x_display_info *dpyinfo;
f676886a 5754 struct frame *frame;
dc6f92b8 5755{
0f941935 5756 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5757
0f941935 5758 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5759 {
58769bee 5760 /* Set this before calling other routines, so that they see
f676886a 5761 the correct value of x_focus_frame. */
0f941935 5762 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5763
5764 if (old_focus && old_focus->auto_lower)
f676886a 5765 x_lower_frame (old_focus);
dc6f92b8
JB
5766
5767#if 0
f676886a 5768 selected_frame = frame;
e0c1aef2
KH
5769 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5770 selected_frame);
f676886a
JB
5771 Fselect_window (selected_frame->selected_window);
5772 choose_minibuf_frame ();
c118dd06 5773#endif /* ! 0 */
dc6f92b8 5774
0f941935
KH
5775 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5776 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5777 else
5778 pending_autoraise_frame = 0;
6d4238f3 5779 }
dc6f92b8 5780
0f941935 5781 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5782}
5783
37c2c98b
RS
5784/* Handle an event saying the mouse has moved out of an Emacs frame. */
5785
5786void
0f941935
KH
5787x_mouse_leave (dpyinfo)
5788 struct x_display_info *dpyinfo;
37c2c98b 5789{
0f941935 5790 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5791}
6d4238f3 5792
f451eb13
JB
5793/* The focus has changed, or we have redirected a frame's focus to
5794 another frame (this happens when a frame uses a surrogate
06a2c219 5795 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5796
5797 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5798 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5799 the appropriate X display info. */
06a2c219 5800
6d4238f3 5801static void
0f941935
KH
5802XTframe_rehighlight (frame)
5803 struct frame *frame;
6d4238f3 5804{
0f941935
KH
5805 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5806}
6d4238f3 5807
0f941935
KH
5808static void
5809x_frame_rehighlight (dpyinfo)
5810 struct x_display_info *dpyinfo;
5811{
5812 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5813
5814 if (dpyinfo->x_focus_frame)
6d4238f3 5815 {
0f941935
KH
5816 dpyinfo->x_highlight_frame
5817 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5818 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5819 : dpyinfo->x_focus_frame);
5820 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5821 {
0f941935
KH
5822 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5823 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5824 }
dc6f92b8 5825 }
6d4238f3 5826 else
0f941935 5827 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5828
0f941935 5829 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5830 {
5831 if (old_highlight)
f676886a 5832 frame_unhighlight (old_highlight);
0f941935
KH
5833 if (dpyinfo->x_highlight_frame)
5834 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5835 }
dc6f92b8 5836}
06a2c219
GM
5837
5838
dc6f92b8 5839\f
06a2c219 5840/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5841
28430d3c
JB
5842/* Initialize mode_switch_bit and modifier_meaning. */
5843static void
334208b7
RS
5844x_find_modifier_meanings (dpyinfo)
5845 struct x_display_info *dpyinfo;
28430d3c 5846{
f689eb05 5847 int min_code, max_code;
28430d3c
JB
5848 KeySym *syms;
5849 int syms_per_code;
5850 XModifierKeymap *mods;
5851
334208b7
RS
5852 dpyinfo->meta_mod_mask = 0;
5853 dpyinfo->shift_lock_mask = 0;
5854 dpyinfo->alt_mod_mask = 0;
5855 dpyinfo->super_mod_mask = 0;
5856 dpyinfo->hyper_mod_mask = 0;
58769bee 5857
9658a521 5858#ifdef HAVE_X11R4
334208b7 5859 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5860#else
4a60f8c5
RS
5861 min_code = dpyinfo->display->min_keycode;
5862 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5863#endif
5864
334208b7 5865 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5866 min_code, max_code - min_code + 1,
5867 &syms_per_code);
334208b7 5868 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5869
58769bee 5870 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5871 Alt keysyms are on. */
28430d3c 5872 {
06a2c219 5873 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5874
5875 for (row = 3; row < 8; row++)
5876 for (col = 0; col < mods->max_keypermod; col++)
5877 {
0299d313
RS
5878 KeyCode code
5879 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5880
af92970c
KH
5881 /* Zeroes are used for filler. Skip them. */
5882 if (code == 0)
5883 continue;
5884
28430d3c
JB
5885 /* Are any of this keycode's keysyms a meta key? */
5886 {
5887 int code_col;
5888
5889 for (code_col = 0; code_col < syms_per_code; code_col++)
5890 {
f689eb05 5891 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5892
f689eb05 5893 switch (sym)
28430d3c 5894 {
f689eb05
JB
5895 case XK_Meta_L:
5896 case XK_Meta_R:
334208b7 5897 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5898 break;
f689eb05
JB
5899
5900 case XK_Alt_L:
5901 case XK_Alt_R:
334208b7 5902 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5903 break;
5904
5905 case XK_Hyper_L:
5906 case XK_Hyper_R:
334208b7 5907 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5908 break;
5909
5910 case XK_Super_L:
5911 case XK_Super_R:
334208b7 5912 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5913 break;
11edeb03
JB
5914
5915 case XK_Shift_Lock:
5916 /* Ignore this if it's not on the lock modifier. */
5917 if ((1 << row) == LockMask)
334208b7 5918 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5919 break;
28430d3c
JB
5920 }
5921 }
5922 }
5923 }
5924 }
5925
f689eb05 5926 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 5927 if (! dpyinfo->meta_mod_mask)
a3c44b14 5928 {
334208b7
RS
5929 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5930 dpyinfo->alt_mod_mask = 0;
a3c44b14 5931 }
f689eb05 5932
148c4b70
RS
5933 /* If some keys are both alt and meta,
5934 make them just meta, not alt. */
334208b7 5935 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 5936 {
334208b7 5937 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 5938 }
58769bee 5939
28430d3c 5940 XFree ((char *) syms);
f689eb05 5941 XFreeModifiermap (mods);
28430d3c
JB
5942}
5943
dfeccd2d
JB
5944/* Convert between the modifier bits X uses and the modifier bits
5945 Emacs uses. */
06a2c219 5946
7c5283e4 5947static unsigned int
334208b7
RS
5948x_x_to_emacs_modifiers (dpyinfo, state)
5949 struct x_display_info *dpyinfo;
dc6f92b8
JB
5950 unsigned int state;
5951{
334208b7
RS
5952 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5953 | ((state & ControlMask) ? ctrl_modifier : 0)
5954 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5955 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5956 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5957 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
5958}
5959
dfeccd2d 5960static unsigned int
334208b7
RS
5961x_emacs_to_x_modifiers (dpyinfo, state)
5962 struct x_display_info *dpyinfo;
dfeccd2d
JB
5963 unsigned int state;
5964{
334208b7
RS
5965 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5966 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5967 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5968 | ((state & shift_modifier) ? ShiftMask : 0)
5969 | ((state & ctrl_modifier) ? ControlMask : 0)
5970 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 5971}
d047c4eb
KH
5972
5973/* Convert a keysym to its name. */
5974
5975char *
5976x_get_keysym_name (keysym)
5977 KeySym keysym;
5978{
5979 char *value;
5980
5981 BLOCK_INPUT;
5982 value = XKeysymToString (keysym);
5983 UNBLOCK_INPUT;
5984
5985 return value;
5986}
06a2c219
GM
5987
5988
e4571a43
JB
5989\f
5990/* Mouse clicks and mouse movement. Rah. */
e4571a43 5991
06a2c219
GM
5992/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5993 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5994 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5995 not force the value into range. */
69388238 5996
c8dba240 5997void
69388238 5998pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 5999 FRAME_PTR f;
69388238 6000 register int pix_x, pix_y;
e4571a43
JB
6001 register int *x, *y;
6002 XRectangle *bounds;
69388238 6003 int noclip;
e4571a43 6004{
06a2c219 6005 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
6006 even for negative values. */
6007 if (pix_x < 0)
7556890b 6008 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 6009 if (pix_y < 0)
7556890b 6010 pix_y -= (f)->output_data.x->line_height - 1;
69388238 6011
e4571a43
JB
6012 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
6013 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
6014
6015 if (bounds)
6016 {
7556890b
RS
6017 bounds->width = FONT_WIDTH (f->output_data.x->font);
6018 bounds->height = f->output_data.x->line_height;
e4571a43
JB
6019 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
6020 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
6021 }
6022
69388238
RS
6023 if (!noclip)
6024 {
6025 if (pix_x < 0)
6026 pix_x = 0;
3cbd2e0b
RS
6027 else if (pix_x > FRAME_WINDOW_WIDTH (f))
6028 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
6029
6030 if (pix_y < 0)
6031 pix_y = 0;
6032 else if (pix_y > f->height)
6033 pix_y = f->height;
6034 }
e4571a43
JB
6035
6036 *x = pix_x;
6037 *y = pix_y;
6038}
6039
06a2c219
GM
6040
6041/* Given HPOS/VPOS in the current matrix of W, return corresponding
6042 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
6043 can't tell the positions because W's display is not up to date,
6044 return 0. */
6045
6046int
6047glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6048 struct window *w;
6049 int hpos, vpos;
6050 int *frame_x, *frame_y;
2b5c9e71 6051{
06a2c219
GM
6052 int success_p;
6053
6054 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6055 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6056
6057 if (display_completed)
6058 {
6059 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6060 struct glyph *glyph = row->glyphs[TEXT_AREA];
6061 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6062
6063 *frame_y = row->y;
6064 *frame_x = row->x;
6065 while (glyph < end)
6066 {
6067 *frame_x += glyph->pixel_width;
6068 ++glyph;
6069 }
6070
6071 success_p = 1;
6072 }
6073 else
6074 {
6075 *frame_y = *frame_x = 0;
6076 success_p = 0;
6077 }
6078
6079 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6080 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6081 return success_p;
2b5c9e71
RS
6082}
6083
06a2c219 6084
dc6f92b8
JB
6085/* Prepare a mouse-event in *RESULT for placement in the input queue.
6086
6087 If the event is a button press, then note that we have grabbed
f451eb13 6088 the mouse. */
dc6f92b8
JB
6089
6090static Lisp_Object
f451eb13 6091construct_mouse_click (result, event, f)
dc6f92b8
JB
6092 struct input_event *result;
6093 XButtonEvent *event;
f676886a 6094 struct frame *f;
dc6f92b8 6095{
f451eb13 6096 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 6097 otherwise. */
f451eb13 6098 result->kind = mouse_click;
69388238 6099 result->code = event->button - Button1;
1113d9db 6100 result->timestamp = event->time;
334208b7
RS
6101 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6102 event->state)
f689eb05 6103 | (event->type == ButtonRelease
58769bee 6104 ? up_modifier
f689eb05 6105 : down_modifier));
dc6f92b8 6106
06a2c219
GM
6107 XSETINT (result->x, event->x);
6108 XSETINT (result->y, event->y);
6109 XSETFRAME (result->frame_or_window, f);
6110 return Qnil;
dc6f92b8 6111}
b849c413 6112
06a2c219
GM
6113#if 0 /* This function isn't called. --gerd */
6114
b849c413
RS
6115/* Prepare a menu-event in *RESULT for placement in the input queue. */
6116
6117static Lisp_Object
6118construct_menu_click (result, event, f)
6119 struct input_event *result;
6120 XButtonEvent *event;
6121 struct frame *f;
6122{
6123 /* Make the event type no_event; we'll change that when we decide
6124 otherwise. */
6125 result->kind = mouse_click;
26459b28 6126 result->code = event->button - Button1;
b849c413 6127 result->timestamp = event->time;
334208b7
RS
6128 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6129 event->state)
b849c413 6130 | (event->type == ButtonRelease
58769bee 6131 ? up_modifier
b849c413
RS
6132 : down_modifier));
6133
e0c1aef2
KH
6134 XSETINT (result->x, event->x);
6135 XSETINT (result->y, -1);
6136 XSETFRAME (result->frame_or_window, f);
b849c413 6137}
06a2c219
GM
6138
6139#endif /* 0 */
6140
69388238 6141\f
90e65f07
JB
6142/* Function to report a mouse movement to the mainstream Emacs code.
6143 The input handler calls this.
6144
6145 We have received a mouse movement event, which is given in *event.
6146 If the mouse is over a different glyph than it was last time, tell
6147 the mainstream emacs code by setting mouse_moved. If not, ask for
6148 another motion event, so we can check again the next time it moves. */
b8009dd1 6149
06a2c219
GM
6150static XMotionEvent last_mouse_motion_event;
6151static Lisp_Object last_mouse_motion_frame;
6152
90e65f07 6153static void
12ba150f 6154note_mouse_movement (frame, event)
f676886a 6155 FRAME_PTR frame;
90e65f07 6156 XMotionEvent *event;
90e65f07 6157{
e5d77022 6158 last_mouse_movement_time = event->time;
06a2c219
GM
6159 last_mouse_motion_event = *event;
6160 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 6161
27f338af
RS
6162 if (event->window != FRAME_X_WINDOW (frame))
6163 {
39d8bb4d 6164 frame->mouse_moved = 1;
27f338af 6165 last_mouse_scroll_bar = Qnil;
27f338af 6166 note_mouse_highlight (frame, -1, -1);
27f338af
RS
6167 }
6168
90e65f07 6169 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
6170 else if (event->x < last_mouse_glyph.x
6171 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
6172 || event->y < last_mouse_glyph.y
6173 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 6174 {
39d8bb4d 6175 frame->mouse_moved = 1;
ab648270 6176 last_mouse_scroll_bar = Qnil;
b8009dd1 6177 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
6178 }
6179}
6180
bf1c0ba1 6181/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 6182
06a2c219
GM
6183 int disable_mouse_highlight;
6184
6185
6186\f
6187/************************************************************************
6188 Mouse Face
6189 ************************************************************************/
6190
6191/* Find the glyph under window-relative coordinates X/Y in window W.
6192 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6193 strings. Return in *HPOS and *VPOS the row and column number of
6194 the glyph found. Return in *AREA the glyph area containing X.
6195 Value is a pointer to the glyph found or null if X/Y is not on
6196 text, or we can't tell because W's current matrix is not up to
6197 date. */
6198
6199static struct glyph *
6200x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
6201 struct window *w;
6202 int x, y;
6203 int *hpos, *vpos, *area;
6204{
6205 struct glyph *glyph, *end;
3e71d8f2 6206 struct glyph_row *row = NULL;
06a2c219
GM
6207 int x0, i, left_area_width;
6208
6209 /* Find row containing Y. Give up if some row is not enabled. */
6210 for (i = 0; i < w->current_matrix->nrows; ++i)
6211 {
6212 row = MATRIX_ROW (w->current_matrix, i);
6213 if (!row->enabled_p)
6214 return NULL;
6215 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6216 break;
6217 }
6218
6219 *vpos = i;
6220 *hpos = 0;
6221
6222 /* Give up if Y is not in the window. */
6223 if (i == w->current_matrix->nrows)
6224 return NULL;
6225
6226 /* Get the glyph area containing X. */
6227 if (w->pseudo_window_p)
6228 {
6229 *area = TEXT_AREA;
6230 x0 = 0;
6231 }
6232 else
6233 {
6234 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6235 if (x < left_area_width)
6236 {
6237 *area = LEFT_MARGIN_AREA;
6238 x0 = 0;
6239 }
6240 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6241 {
6242 *area = TEXT_AREA;
6243 x0 = row->x + left_area_width;
6244 }
6245 else
6246 {
6247 *area = RIGHT_MARGIN_AREA;
6248 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6249 }
6250 }
6251
6252 /* Find glyph containing X. */
6253 glyph = row->glyphs[*area];
6254 end = glyph + row->used[*area];
6255 while (glyph < end)
6256 {
6257 if (x < x0 + glyph->pixel_width)
6258 {
6259 if (w->pseudo_window_p)
6260 break;
6261 else if (BUFFERP (glyph->object))
6262 break;
6263 }
6264
6265 x0 += glyph->pixel_width;
6266 ++glyph;
6267 }
6268
6269 if (glyph == end)
6270 return NULL;
6271
6272 *hpos = glyph - row->glyphs[*area];
6273 return glyph;
6274}
6275
6276
6277/* Convert frame-relative x/y to coordinates relative to window W.
6278 Takes pseudo-windows into account. */
6279
6280static void
6281frame_to_window_pixel_xy (w, x, y)
6282 struct window *w;
6283 int *x, *y;
6284{
6285 if (w->pseudo_window_p)
6286 {
6287 /* A pseudo-window is always full-width, and starts at the
6288 left edge of the frame, plus a frame border. */
6289 struct frame *f = XFRAME (w->frame);
6290 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6291 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6292 }
6293 else
6294 {
6295 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6296 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6297 }
6298}
6299
6300
6301/* Take proper action when mouse has moved to the mode or top line of
6302 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6303 mode line. X is relative to the start of the text display area of
6304 W, so the width of bitmap areas and scroll bars must be subtracted
6305 to get a position relative to the start of the mode line. */
6306
6307static void
6308note_mode_line_highlight (w, x, mode_line_p)
6309 struct window *w;
6310 int x, mode_line_p;
6311{
6312 struct frame *f = XFRAME (w->frame);
6313 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6314 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6315 struct glyph_row *row;
6316
6317 if (mode_line_p)
6318 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6319 else
045dee35 6320 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
06a2c219
GM
6321
6322 if (row->enabled_p)
6323 {
6324 struct glyph *glyph, *end;
6325 Lisp_Object help, map;
6326 int x0;
6327
6328 /* Find the glyph under X. */
6329 glyph = row->glyphs[TEXT_AREA];
6330 end = glyph + row->used[TEXT_AREA];
6331 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
110859fc 6332 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
06a2c219
GM
6333 while (glyph < end
6334 && x >= x0 + glyph->pixel_width)
6335 {
6336 x0 += glyph->pixel_width;
6337 ++glyph;
6338 }
6339
6340 if (glyph < end
6341 && STRINGP (glyph->object)
6342 && XSTRING (glyph->object)->intervals
6343 && glyph->charpos >= 0
6344 && glyph->charpos < XSTRING (glyph->object)->size)
6345 {
6346 /* If we're on a string with `help-echo' text property,
6347 arrange for the help to be displayed. This is done by
6348 setting the global variable help_echo to the help string. */
6349 help = Fget_text_property (make_number (glyph->charpos),
6350 Qhelp_echo, glyph->object);
b7e80413 6351 if (!NILP (help))
06a2c219
GM
6352 help_echo = help;
6353
6354 /* Change the mouse pointer according to what is under X/Y. */
6355 map = Fget_text_property (make_number (glyph->charpos),
6356 Qlocal_map, glyph->object);
6357 if (!NILP (Fkeymapp (map)))
6358 cursor = f->output_data.x->nontext_cursor;
6359 }
6360 }
6361
6362 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6363}
6364
6365
6366/* Take proper action when the mouse has moved to position X, Y on
6367 frame F as regards highlighting characters that have mouse-face
6368 properties. Also de-highlighting chars where the mouse was before.
27f338af 6369 X and Y can be negative or out of range. */
b8009dd1
RS
6370
6371static void
6372note_mouse_highlight (f, x, y)
06a2c219 6373 struct frame *f;
c32cdd9a 6374 int x, y;
b8009dd1 6375{
06a2c219
GM
6376 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6377 int portion;
b8009dd1
RS
6378 Lisp_Object window;
6379 struct window *w;
6380
06a2c219
GM
6381 /* When a menu is active, don't highlight because this looks odd. */
6382#ifdef USE_X_TOOLKIT
6383 if (popup_activated ())
6384 return;
6385#endif
6386
04fff9c0
GM
6387 if (disable_mouse_highlight
6388 || !f->glyphs_initialized_p)
bf1c0ba1
RS
6389 return;
6390
06a2c219
GM
6391 dpyinfo->mouse_face_mouse_x = x;
6392 dpyinfo->mouse_face_mouse_y = y;
6393 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 6394
06a2c219 6395 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
6396 return;
6397
514e4681
RS
6398 if (gc_in_progress)
6399 {
06a2c219 6400 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
6401 return;
6402 }
6403
b8009dd1 6404 /* Which window is that in? */
06a2c219 6405 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
6406
6407 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
6408 if (! EQ (window, dpyinfo->mouse_face_window))
6409 clear_mouse_face (dpyinfo);
6410
6411 /* Not on a window -> return. */
6412 if (!WINDOWP (window))
6413 return;
6414
6415 /* Convert to window-relative pixel coordinates. */
6416 w = XWINDOW (window);
6417 frame_to_window_pixel_xy (w, &x, &y);
6418
9ea173e8 6419 /* Handle tool-bar window differently since it doesn't display a
06a2c219 6420 buffer. */
9ea173e8 6421 if (EQ (window, f->tool_bar_window))
06a2c219 6422 {
9ea173e8 6423 note_tool_bar_highlight (f, x, y);
06a2c219
GM
6424 return;
6425 }
6426
6427 if (portion == 1 || portion == 3)
6428 {
6429 /* Mouse is on the mode or top line. */
6430 note_mode_line_highlight (w, x, portion == 1);
6431 return;
6432 }
6433 else
6434 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6435 f->output_data.x->text_cursor);
b8009dd1 6436
0cdd0c9f
RS
6437 /* Are we in a window whose display is up to date?
6438 And verify the buffer's text has not changed. */
06a2c219
GM
6439 if (/* Within text portion of the window. */
6440 portion == 0
0cdd0c9f 6441 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6442 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6443 && (XFASTINT (w->last_overlay_modified)
6444 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6445 {
06a2c219
GM
6446 int hpos, vpos, pos, i, area;
6447 struct glyph *glyph;
b8009dd1 6448
06a2c219
GM
6449 /* Find the glyph under X/Y. */
6450 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6451
6452 /* Clear mouse face if X/Y not over text. */
6453 if (glyph == NULL
6454 || area != TEXT_AREA
6455 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6456 {
06a2c219
GM
6457 clear_mouse_face (dpyinfo);
6458 return;
6459 }
6460
6461 pos = glyph->charpos;
6462 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6463
6464 /* Check for mouse-face and help-echo. */
6465 {
6466 Lisp_Object mouse_face, overlay, position;
6467 Lisp_Object *overlay_vec;
6468 int len, noverlays;
6469 struct buffer *obuf;
6470 int obegv, ozv;
6471
6472 /* If we get an out-of-range value, return now; avoid an error. */
6473 if (pos > BUF_Z (XBUFFER (w->buffer)))
6474 return;
6475
6476 /* Make the window's buffer temporarily current for
6477 overlays_at and compute_char_face. */
6478 obuf = current_buffer;
6479 current_buffer = XBUFFER (w->buffer);
6480 obegv = BEGV;
6481 ozv = ZV;
6482 BEGV = BEG;
6483 ZV = Z;
6484
6485 /* Is this char mouse-active or does it have help-echo? */
6486 XSETINT (position, pos);
6487
6488 /* Put all the overlays we want in a vector in overlay_vec.
6489 Store the length in len. If there are more than 10, make
6490 enough space for all, and try again. */
6491 len = 10;
6492 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6493 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6494 if (noverlays > len)
6495 {
6496 len = noverlays;
6497 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6498 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6499 }
6500
6501 noverlays = sort_overlays (overlay_vec, noverlays, w);
6502
6503 /* Check mouse-face highlighting. */
6504 if (! (EQ (window, dpyinfo->mouse_face_window)
6505 && vpos >= dpyinfo->mouse_face_beg_row
6506 && vpos <= dpyinfo->mouse_face_end_row
6507 && (vpos > dpyinfo->mouse_face_beg_row
6508 || hpos >= dpyinfo->mouse_face_beg_col)
6509 && (vpos < dpyinfo->mouse_face_end_row
6510 || hpos < dpyinfo->mouse_face_end_col
6511 || dpyinfo->mouse_face_past_end)))
6512 {
6513 /* Clear the display of the old active region, if any. */
6514 clear_mouse_face (dpyinfo);
6515
6516 /* Find the highest priority overlay that has a mouse-face prop. */
6517 overlay = Qnil;
6518 for (i = 0; i < noverlays; i++)
6519 {
6520 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6521 if (!NILP (mouse_face))
6522 {
6523 overlay = overlay_vec[i];
6524 break;
6525 }
6526 }
6527
6528 /* If no overlay applies, get a text property. */
6529 if (NILP (overlay))
6530 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6531
6532 /* Handle the overlay case. */
6533 if (! NILP (overlay))
6534 {
6535 /* Find the range of text around this char that
6536 should be active. */
6537 Lisp_Object before, after;
6538 int ignore;
6539
6540 before = Foverlay_start (overlay);
6541 after = Foverlay_end (overlay);
6542 /* Record this as the current active region. */
6543 fast_find_position (w, XFASTINT (before),
6544 &dpyinfo->mouse_face_beg_col,
6545 &dpyinfo->mouse_face_beg_row,
6546 &dpyinfo->mouse_face_beg_x,
6547 &dpyinfo->mouse_face_beg_y);
6548 dpyinfo->mouse_face_past_end
6549 = !fast_find_position (w, XFASTINT (after),
6550 &dpyinfo->mouse_face_end_col,
6551 &dpyinfo->mouse_face_end_row,
6552 &dpyinfo->mouse_face_end_x,
6553 &dpyinfo->mouse_face_end_y);
6554 dpyinfo->mouse_face_window = window;
6555 dpyinfo->mouse_face_face_id
6556 = face_at_buffer_position (w, pos, 0, 0,
6557 &ignore, pos + 1, 1);
6558
6559 /* Display it as active. */
6560 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6561 }
6562 /* Handle the text property case. */
6563 else if (! NILP (mouse_face))
6564 {
6565 /* Find the range of text around this char that
6566 should be active. */
6567 Lisp_Object before, after, beginning, end;
6568 int ignore;
6569
6570 beginning = Fmarker_position (w->start);
6571 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6572 - XFASTINT (w->window_end_pos)));
6573 before
6574 = Fprevious_single_property_change (make_number (pos + 1),
6575 Qmouse_face,
6576 w->buffer, beginning);
6577 after
6578 = Fnext_single_property_change (position, Qmouse_face,
6579 w->buffer, end);
6580 /* Record this as the current active region. */
6581 fast_find_position (w, XFASTINT (before),
6582 &dpyinfo->mouse_face_beg_col,
6583 &dpyinfo->mouse_face_beg_row,
6584 &dpyinfo->mouse_face_beg_x,
6585 &dpyinfo->mouse_face_beg_y);
6586 dpyinfo->mouse_face_past_end
6587 = !fast_find_position (w, XFASTINT (after),
6588 &dpyinfo->mouse_face_end_col,
6589 &dpyinfo->mouse_face_end_row,
6590 &dpyinfo->mouse_face_end_x,
6591 &dpyinfo->mouse_face_end_y);
6592 dpyinfo->mouse_face_window = window;
6593 dpyinfo->mouse_face_face_id
6594 = face_at_buffer_position (w, pos, 0, 0,
6595 &ignore, pos + 1, 1);
6596
6597 /* Display it as active. */
6598 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6599 }
6600 }
6601
6602 /* Look for a `help-echo' property. */
6603 {
6604 Lisp_Object help;
6605
6606 /* Check overlays first. */
6607 help = Qnil;
b7e80413 6608 for (i = 0; i < noverlays && NILP (help); ++i)
06a2c219
GM
6609 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6610
6611 /* Try text properties. */
b7e80413 6612 if (NILP (help)
06a2c219
GM
6613 && ((STRINGP (glyph->object)
6614 && glyph->charpos >= 0
6615 && glyph->charpos < XSTRING (glyph->object)->size)
6616 || (BUFFERP (glyph->object)
6617 && glyph->charpos >= BEGV
6618 && glyph->charpos < ZV)))
6619 help = Fget_text_property (make_number (glyph->charpos),
6620 Qhelp_echo, glyph->object);
6621
b7e80413 6622 if (!NILP (help))
06a2c219
GM
6623 help_echo = help;
6624 }
6625
6626 BEGV = obegv;
6627 ZV = ozv;
6628 current_buffer = obuf;
6629 }
6630 }
6631}
6632
6633static void
6634redo_mouse_highlight ()
6635{
6636 if (!NILP (last_mouse_motion_frame)
6637 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6638 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6639 last_mouse_motion_event.x,
6640 last_mouse_motion_event.y);
6641}
6642
6643
6644\f
6645/***********************************************************************
9ea173e8 6646 Tool-bars
06a2c219
GM
6647 ***********************************************************************/
6648
9ea173e8
GM
6649static int x_tool_bar_item P_ ((struct frame *, int, int,
6650 struct glyph **, int *, int *, int *));
06a2c219 6651
9ea173e8 6652/* Tool-bar item index of the item on which a mouse button was pressed
06a2c219
GM
6653 or -1. */
6654
9ea173e8 6655static int last_tool_bar_item;
06a2c219
GM
6656
6657
9ea173e8
GM
6658/* Get information about the tool-bar item at position X/Y on frame F.
6659 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6660 the current matrix of the tool-bar window of F, or NULL if not
6661 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6662 item in F->current_tool_bar_items. Value is
06a2c219 6663
9ea173e8 6664 -1 if X/Y is not on a tool-bar item
06a2c219
GM
6665 0 if X/Y is on the same item that was highlighted before.
6666 1 otherwise. */
6667
6668static int
9ea173e8 6669x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
06a2c219
GM
6670 struct frame *f;
6671 int x, y;
6672 struct glyph **glyph;
6673 int *hpos, *vpos, *prop_idx;
6674{
6675 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6676 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6677 int area;
6678
6679 /* Find the glyph under X/Y. */
6680 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6681 if (*glyph == NULL)
6682 return -1;
6683
9ea173e8
GM
6684 /* Get the start of this tool-bar item's properties in
6685 f->current_tool_bar_items. */
6686 if (!tool_bar_item_info (f, *glyph, prop_idx))
06a2c219
GM
6687 return -1;
6688
6689 /* Is mouse on the highlighted item? */
9ea173e8 6690 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
06a2c219
GM
6691 && *vpos >= dpyinfo->mouse_face_beg_row
6692 && *vpos <= dpyinfo->mouse_face_end_row
6693 && (*vpos > dpyinfo->mouse_face_beg_row
6694 || *hpos >= dpyinfo->mouse_face_beg_col)
6695 && (*vpos < dpyinfo->mouse_face_end_row
6696 || *hpos < dpyinfo->mouse_face_end_col
6697 || dpyinfo->mouse_face_past_end))
6698 return 0;
6699
6700 return 1;
6701}
6702
6703
9ea173e8 6704/* Handle mouse button event on the tool-bar of frame F, at
06a2c219
GM
6705 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6706 or ButtonRelase. */
6707
6708static void
9ea173e8 6709x_handle_tool_bar_click (f, button_event)
06a2c219
GM
6710 struct frame *f;
6711 XButtonEvent *button_event;
6712{
6713 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9ea173e8 6714 struct window *w = XWINDOW (f->tool_bar_window);
06a2c219
GM
6715 int hpos, vpos, prop_idx;
6716 struct glyph *glyph;
6717 Lisp_Object enabled_p;
6718 int x = button_event->x;
6719 int y = button_event->y;
6720
9ea173e8 6721 /* If not on the highlighted tool-bar item, return. */
06a2c219 6722 frame_to_window_pixel_xy (w, &x, &y);
9ea173e8 6723 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
06a2c219
GM
6724 return;
6725
6726 /* If item is disabled, do nothing. */
9ea173e8
GM
6727 enabled_p = (XVECTOR (f->current_tool_bar_items)
6728 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6729 if (NILP (enabled_p))
6730 return;
6731
6732 if (button_event->type == ButtonPress)
6733 {
6734 /* Show item in pressed state. */
6735 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6736 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
9ea173e8 6737 last_tool_bar_item = prop_idx;
06a2c219
GM
6738 }
6739 else
6740 {
6741 Lisp_Object key, frame;
6742 struct input_event event;
6743
6744 /* Show item in released state. */
6745 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6746 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6747
9ea173e8
GM
6748 key = (XVECTOR (f->current_tool_bar_items)
6749 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
06a2c219
GM
6750
6751 XSETFRAME (frame, f);
9ea173e8
GM
6752 event.kind = TOOL_BAR_EVENT;
6753 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
06a2c219
GM
6754 kbd_buffer_store_event (&event);
6755
9ea173e8 6756 event.kind = TOOL_BAR_EVENT;
06a2c219
GM
6757 event.frame_or_window = Fcons (frame, key);
6758 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6759 button_event->state);
6760 kbd_buffer_store_event (&event);
9ea173e8 6761 last_tool_bar_item = -1;
06a2c219
GM
6762 }
6763}
6764
6765
9ea173e8
GM
6766/* Possibly highlight a tool-bar item on frame F when mouse moves to
6767 tool-bar window-relative coordinates X/Y. Called from
06a2c219
GM
6768 note_mouse_highlight. */
6769
6770static void
9ea173e8 6771note_tool_bar_highlight (f, x, y)
06a2c219
GM
6772 struct frame *f;
6773 int x, y;
6774{
9ea173e8 6775 Lisp_Object window = f->tool_bar_window;
06a2c219
GM
6776 struct window *w = XWINDOW (window);
6777 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6778 int hpos, vpos;
6779 struct glyph *glyph;
6780 struct glyph_row *row;
5c187dee 6781 int i;
06a2c219
GM
6782 Lisp_Object enabled_p;
6783 int prop_idx;
6784 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
5c187dee 6785 int mouse_down_p, rc;
06a2c219
GM
6786
6787 /* Function note_mouse_highlight is called with negative x(y
6788 values when mouse moves outside of the frame. */
6789 if (x <= 0 || y <= 0)
6790 {
6791 clear_mouse_face (dpyinfo);
6792 return;
6793 }
6794
9ea173e8 6795 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
06a2c219
GM
6796 if (rc < 0)
6797 {
9ea173e8 6798 /* Not on tool-bar item. */
06a2c219
GM
6799 clear_mouse_face (dpyinfo);
6800 return;
6801 }
6802 else if (rc == 0)
9ea173e8 6803 /* On same tool-bar item as before. */
06a2c219 6804 goto set_help_echo;
b8009dd1 6805
06a2c219
GM
6806 clear_mouse_face (dpyinfo);
6807
9ea173e8 6808 /* Mouse is down, but on different tool-bar item? */
06a2c219
GM
6809 mouse_down_p = (dpyinfo->grabbed
6810 && f == last_mouse_frame
6811 && FRAME_LIVE_P (f));
6812 if (mouse_down_p
9ea173e8 6813 && last_tool_bar_item != prop_idx)
06a2c219
GM
6814 return;
6815
6816 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6817 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6818
9ea173e8
GM
6819 /* If tool-bar item is not enabled, don't highlight it. */
6820 enabled_p = (XVECTOR (f->current_tool_bar_items)
6821 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
06a2c219
GM
6822 if (!NILP (enabled_p))
6823 {
6824 /* Compute the x-position of the glyph. In front and past the
6825 image is a space. We include this is the highlighted area. */
6826 row = MATRIX_ROW (w->current_matrix, vpos);
6827 for (i = x = 0; i < hpos; ++i)
6828 x += row->glyphs[TEXT_AREA][i].pixel_width;
6829
6830 /* Record this as the current active region. */
6831 dpyinfo->mouse_face_beg_col = hpos;
6832 dpyinfo->mouse_face_beg_row = vpos;
6833 dpyinfo->mouse_face_beg_x = x;
6834 dpyinfo->mouse_face_beg_y = row->y;
6835 dpyinfo->mouse_face_past_end = 0;
6836
6837 dpyinfo->mouse_face_end_col = hpos + 1;
6838 dpyinfo->mouse_face_end_row = vpos;
6839 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6840 dpyinfo->mouse_face_end_y = row->y;
6841 dpyinfo->mouse_face_window = window;
9ea173e8 6842 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
06a2c219
GM
6843
6844 /* Display it as active. */
6845 show_mouse_face (dpyinfo, draw);
6846 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6847 }
06a2c219
GM
6848
6849 set_help_echo:
6850
9ea173e8 6851 /* Set help_echo to a help string.to display for this tool-bar item.
06a2c219 6852 XTread_socket does the rest. */
9ea173e8
GM
6853 help_echo = (XVECTOR (f->current_tool_bar_items)
6854 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
b7e80413 6855 if (NILP (help_echo))
9ea173e8
GM
6856 help_echo = (XVECTOR (f->current_tool_bar_items)
6857 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
b8009dd1 6858}
4d73d038 6859
06a2c219
GM
6860
6861\f
6862/* Find the glyph matrix position of buffer position POS in window W.
6863 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6864 current glyphs must be up to date. If POS is above window start
6865 return (0, 0, 0, 0). If POS is after end of W, return end of
6866 last line in W. */
b8009dd1
RS
6867
6868static int
06a2c219
GM
6869fast_find_position (w, pos, hpos, vpos, x, y)
6870 struct window *w;
b8009dd1 6871 int pos;
06a2c219 6872 int *hpos, *vpos, *x, *y;
b8009dd1 6873{
b8009dd1 6874 int i;
bf1c0ba1 6875 int lastcol;
06a2c219
GM
6876 int maybe_next_line_p = 0;
6877 int line_start_position;
6878 int yb = window_text_bottom_y (w);
6879 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6880 struct glyph_row *best_row = row;
6881 int row_vpos = 0, best_row_vpos = 0;
6882 int current_x;
6883
6884 while (row->y < yb)
b8009dd1 6885 {
06a2c219
GM
6886 if (row->used[TEXT_AREA])
6887 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6888 else
6889 line_start_position = 0;
6890
6891 if (line_start_position > pos)
b8009dd1 6892 break;
77b68646
RS
6893 /* If the position sought is the end of the buffer,
6894 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6895 else if (line_start_position == pos
6896 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6897 {
06a2c219 6898 maybe_next_line_p = 1;
77b68646
RS
6899 break;
6900 }
06a2c219
GM
6901 else if (line_start_position > 0)
6902 {
6903 best_row = row;
6904 best_row_vpos = row_vpos;
6905 }
4b0bb6f3
GM
6906
6907 if (row->y + row->height >= yb)
6908 break;
06a2c219
GM
6909
6910 ++row;
6911 ++row_vpos;
b8009dd1 6912 }
06a2c219
GM
6913
6914 /* Find the right column within BEST_ROW. */
6915 lastcol = 0;
6916 current_x = best_row->x;
6917 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 6918 {
06a2c219
GM
6919 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6920 int charpos;
6921
6922 charpos = glyph->charpos;
6923 if (charpos == pos)
bf1c0ba1 6924 {
06a2c219
GM
6925 *hpos = i;
6926 *vpos = best_row_vpos;
6927 *x = current_x;
6928 *y = best_row->y;
bf1c0ba1
RS
6929 return 1;
6930 }
06a2c219 6931 else if (charpos > pos)
4d73d038 6932 break;
06a2c219
GM
6933 else if (charpos > 0)
6934 lastcol = i;
6935
6936 current_x += glyph->pixel_width;
bf1c0ba1 6937 }
b8009dd1 6938
77b68646
RS
6939 /* If we're looking for the end of the buffer,
6940 and we didn't find it in the line we scanned,
6941 use the start of the following line. */
06a2c219 6942 if (maybe_next_line_p)
77b68646 6943 {
06a2c219
GM
6944 ++best_row;
6945 ++best_row_vpos;
6946 lastcol = 0;
6947 current_x = best_row->x;
77b68646
RS
6948 }
6949
06a2c219
GM
6950 *vpos = best_row_vpos;
6951 *hpos = lastcol + 1;
6952 *x = current_x;
6953 *y = best_row->y;
b8009dd1
RS
6954 return 0;
6955}
6956
06a2c219 6957
b8009dd1
RS
6958/* Display the active region described by mouse_face_*
6959 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6960
6961static void
06a2c219 6962show_mouse_face (dpyinfo, draw)
7a13e894 6963 struct x_display_info *dpyinfo;
06a2c219 6964 enum draw_glyphs_face draw;
b8009dd1 6965{
7a13e894 6966 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 6967 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 6968 int i;
06a2c219
GM
6969 int cursor_off_p = 0;
6970 struct cursor_pos saved_cursor;
6971
6972 saved_cursor = output_cursor;
6973
6974 /* If window is in the process of being destroyed, don't bother
6975 to do anything. */
6976 if (w->current_matrix == NULL)
6977 goto set_x_cursor;
6978
6979 /* Recognize when we are called to operate on rows that don't exist
6980 anymore. This can happen when a window is split. */
6981 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6982 goto set_x_cursor;
6983
6984 set_output_cursor (&w->phys_cursor);
6985
6986 /* Note that mouse_face_beg_row etc. are window relative. */
6987 for (i = dpyinfo->mouse_face_beg_row;
6988 i <= dpyinfo->mouse_face_end_row;
6989 i++)
6990 {
6991 int start_hpos, end_hpos, start_x;
6992 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6993
6994 /* Don't do anything if row doesn't have valid contents. */
6995 if (!row->enabled_p)
6996 continue;
6997
6998 /* For all but the first row, the highlight starts at column 0. */
6999 if (i == dpyinfo->mouse_face_beg_row)
7000 {
7001 start_hpos = dpyinfo->mouse_face_beg_col;
7002 start_x = dpyinfo->mouse_face_beg_x;
7003 }
7004 else
7005 {
7006 start_hpos = 0;
7007 start_x = 0;
7008 }
7009
7010 if (i == dpyinfo->mouse_face_end_row)
7011 end_hpos = dpyinfo->mouse_face_end_col;
7012 else
7013 end_hpos = row->used[TEXT_AREA];
7014
7015 /* If the cursor's in the text we are about to rewrite, turn the
7016 cursor off. */
7017 if (!w->pseudo_window_p
7018 && i == output_cursor.vpos
7019 && output_cursor.hpos >= start_hpos - 1
7020 && output_cursor.hpos <= end_hpos)
514e4681 7021 {
06a2c219
GM
7022 x_update_window_cursor (w, 0);
7023 cursor_off_p = 1;
514e4681 7024 }
b8009dd1 7025
06a2c219 7026 if (end_hpos > start_hpos)
54a91a0f 7027 x_draw_glyphs (w, start_x, row, TEXT_AREA,
66ac4b0e 7028 start_hpos, end_hpos, draw, NULL, NULL, 0);
b8009dd1
RS
7029 }
7030
514e4681 7031 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
7032 if (cursor_off_p)
7033 x_display_cursor (w, 1,
7034 output_cursor.hpos, output_cursor.vpos,
7035 output_cursor.x, output_cursor.y);
2729a2b5 7036
06a2c219 7037 output_cursor = saved_cursor;
fb3b7de5 7038
06a2c219
GM
7039 set_x_cursor:
7040
7041 /* Change the mouse cursor. */
7042 if (draw == DRAW_NORMAL_TEXT)
7043 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7044 f->output_data.x->text_cursor);
7045 else if (draw == DRAW_MOUSE_FACE)
334208b7 7046 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 7047 f->output_data.x->cross_cursor);
27ead1d5 7048 else
334208b7 7049 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 7050 f->output_data.x->nontext_cursor);
b8009dd1
RS
7051}
7052
7053/* Clear out the mouse-highlighted active region.
06a2c219 7054 Redraw it un-highlighted first. */
b8009dd1 7055
06a2c219 7056void
7a13e894
RS
7057clear_mouse_face (dpyinfo)
7058 struct x_display_info *dpyinfo;
b8009dd1 7059{
06a2c219
GM
7060 if (tip_frame)
7061 return;
7062
7a13e894 7063 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 7064 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 7065
7a13e894
RS
7066 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7067 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7068 dpyinfo->mouse_face_window = Qnil;
b8009dd1 7069}
e687d06e
RS
7070
7071/* Just discard the mouse face information for frame F, if any.
7072 This is used when the size of F is changed. */
7073
dfcf069d 7074void
e687d06e
RS
7075cancel_mouse_face (f)
7076 FRAME_PTR f;
7077{
7078 Lisp_Object window;
7079 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
7080
7081 window = dpyinfo->mouse_face_window;
7082 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7083 {
7084 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7085 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7086 dpyinfo->mouse_face_window = Qnil;
7087 }
7088}
b8009dd1 7089\f
ab648270
JB
7090static struct scroll_bar *x_window_to_scroll_bar ();
7091static void x_scroll_bar_report_motion ();
12ba150f 7092
90e65f07 7093/* Return the current position of the mouse.
2d7fc7e8 7094 *fp should be a frame which indicates which display to ask about.
90e65f07 7095
2d7fc7e8 7096 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 7097 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 7098 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 7099 position on the scroll bar.
12ba150f 7100
2d7fc7e8 7101 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
7102 mouse is on, *bar_window to nil, and *x and *y to the character cell
7103 the mouse is over.
7104
06a2c219 7105 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
7106 was at this position.
7107
a135645a
RS
7108 Don't store anything if we don't have a valid set of values to report.
7109
90e65f07 7110 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 7111 movement. */
90e65f07
JB
7112
7113static void
1cf412ec 7114XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 7115 FRAME_PTR *fp;
1cf412ec 7116 int insist;
12ba150f 7117 Lisp_Object *bar_window;
ab648270 7118 enum scroll_bar_part *part;
90e65f07 7119 Lisp_Object *x, *y;
e5d77022 7120 unsigned long *time;
90e65f07 7121{
a135645a
RS
7122 FRAME_PTR f1;
7123
90e65f07
JB
7124 BLOCK_INPUT;
7125
8bcee03e 7126 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 7127 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
7128 else
7129 {
12ba150f
JB
7130 Window root;
7131 int root_x, root_y;
90e65f07 7132
12ba150f
JB
7133 Window dummy_window;
7134 int dummy;
7135
39d8bb4d
KH
7136 Lisp_Object frame, tail;
7137
7138 /* Clear the mouse-moved flag for every frame on this display. */
7139 FOR_EACH_FRAME (tail, frame)
7140 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
7141 XFRAME (frame)->mouse_moved = 0;
7142
ab648270 7143 last_mouse_scroll_bar = Qnil;
12ba150f
JB
7144
7145 /* Figure out which root window we're on. */
334208b7
RS
7146 XQueryPointer (FRAME_X_DISPLAY (*fp),
7147 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
7148
7149 /* The root window which contains the pointer. */
7150 &root,
7151
7152 /* Trash which we can't trust if the pointer is on
7153 a different screen. */
7154 &dummy_window,
7155
7156 /* The position on that root window. */
58769bee 7157 &root_x, &root_y,
12ba150f
JB
7158
7159 /* More trash we can't trust. */
7160 &dummy, &dummy,
7161
7162 /* Modifier keys and pointer buttons, about which
7163 we don't care. */
7164 (unsigned int *) &dummy);
7165
7166 /* Now we have a position on the root; find the innermost window
7167 containing the pointer. */
7168 {
7169 Window win, child;
7170 int win_x, win_y;
06a2c219 7171 int parent_x = 0, parent_y = 0;
e99db5a1 7172 int count;
12ba150f
JB
7173
7174 win = root;
69388238 7175
2d7fc7e8
RS
7176 /* XTranslateCoordinates can get errors if the window
7177 structure is changing at the same time this function
7178 is running. So at least we must not crash from them. */
7179
e99db5a1 7180 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 7181
334208b7 7182 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 7183 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 7184 {
69388238
RS
7185 /* If mouse was grabbed on a frame, give coords for that frame
7186 even if the mouse is now outside it. */
334208b7 7187 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 7188
12ba150f 7189 /* From-window, to-window. */
69388238 7190 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
7191
7192 /* From-position, to-position. */
7193 root_x, root_y, &win_x, &win_y,
7194
7195 /* Child of win. */
7196 &child);
69388238
RS
7197 f1 = last_mouse_frame;
7198 }
7199 else
7200 {
7201 while (1)
7202 {
334208b7 7203 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 7204
69388238
RS
7205 /* From-window, to-window. */
7206 root, win,
12ba150f 7207
69388238
RS
7208 /* From-position, to-position. */
7209 root_x, root_y, &win_x, &win_y,
7210
7211 /* Child of win. */
7212 &child);
7213
9af3143a 7214 if (child == None || child == win)
69388238
RS
7215 break;
7216
7217 win = child;
7218 parent_x = win_x;
7219 parent_y = win_y;
7220 }
12ba150f 7221
69388238
RS
7222 /* Now we know that:
7223 win is the innermost window containing the pointer
7224 (XTC says it has no child containing the pointer),
7225 win_x and win_y are the pointer's position in it
7226 (XTC did this the last time through), and
7227 parent_x and parent_y are the pointer's position in win's parent.
7228 (They are what win_x and win_y were when win was child.
7229 If win is the root window, it has no parent, and
7230 parent_{x,y} are invalid, but that's okay, because we'll
7231 never use them in that case.) */
7232
7233 /* Is win one of our frames? */
19126e11 7234 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 7235 }
58769bee 7236
2d7fc7e8
RS
7237 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
7238 f1 = 0;
7239
e99db5a1 7240 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 7241
ab648270 7242 /* If not, is it one of our scroll bars? */
a135645a 7243 if (! f1)
12ba150f 7244 {
ab648270 7245 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
7246
7247 if (bar)
7248 {
a135645a 7249 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
7250 win_x = parent_x;
7251 win_y = parent_y;
7252 }
7253 }
90e65f07 7254
8bcee03e 7255 if (f1 == 0 && insist > 0)
b86bd3dd 7256 f1 = SELECTED_FRAME ();
1cf412ec 7257
a135645a 7258 if (f1)
12ba150f 7259 {
06a2c219
GM
7260 /* Ok, we found a frame. Store all the values.
7261 last_mouse_glyph is a rectangle used to reduce the
7262 generation of mouse events. To not miss any motion
7263 events, we must divide the frame into rectangles of the
7264 size of the smallest character that could be displayed
7265 on it, i.e. into the same rectangles that matrices on
7266 the frame are divided into. */
7267
7268#if OLD_REDISPLAY_CODE
2b5c9e71 7269 int ignore1, ignore2;
2b5c9e71 7270 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 7271 &last_mouse_glyph,
1cf412ec
RS
7272 FRAME_X_DISPLAY_INFO (f1)->grabbed
7273 || insist);
06a2c219
GM
7274#else
7275 {
7276 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7277 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7278 int x = win_x;
7279 int y = win_y;
7280
7281 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7282 round down even for negative values. */
7283 if (x < 0)
7284 x -= width - 1;
7285 if (y < 0)
7286 y -= height - 1;
7287
7288 last_mouse_glyph.width = width;
7289 last_mouse_glyph.height = height;
7290 last_mouse_glyph.x = (x + width - 1) / width * width;
7291 last_mouse_glyph.y = (y + height - 1) / height * height;
7292 }
7293#endif
12ba150f
JB
7294
7295 *bar_window = Qnil;
7296 *part = 0;
334208b7 7297 *fp = f1;
e0c1aef2
KH
7298 XSETINT (*x, win_x);
7299 XSETINT (*y, win_y);
12ba150f
JB
7300 *time = last_mouse_movement_time;
7301 }
7302 }
7303 }
90e65f07
JB
7304
7305 UNBLOCK_INPUT;
7306}
f451eb13 7307
06a2c219 7308
06a2c219 7309#ifdef USE_X_TOOLKIT
bffcfca9
GM
7310
7311/* Atimer callback function for TIMER. Called every 0.1s to process
7312 Xt timeouts, if needed. We must avoid calling XtAppPending as
7313 much as possible because that function does an implicit XFlush
7314 that slows us down. */
7315
7316static void
7317x_process_timeouts (timer)
7318 struct atimer *timer;
7319{
7320 if (toolkit_scroll_bar_interaction || popup_activated_flag)
7321 {
7322 BLOCK_INPUT;
7323 while (XtAppPending (Xt_app_con) & XtIMTimer)
7324 XtAppProcessEvent (Xt_app_con, XtIMTimer);
7325 UNBLOCK_INPUT;
7326 }
06a2c219
GM
7327}
7328
bffcfca9 7329#endif /* USE_X_TOOLKIT */
06a2c219
GM
7330
7331\f
7332/* Scroll bar support. */
7333
7334/* Given an X window ID, find the struct scroll_bar which manages it.
7335 This can be called in GC, so we have to make sure to strip off mark
7336 bits. */
bffcfca9 7337
06a2c219
GM
7338static struct scroll_bar *
7339x_window_to_scroll_bar (window_id)
7340 Window window_id;
7341{
7342 Lisp_Object tail;
7343
7344 for (tail = Vframe_list;
7345 XGCTYPE (tail) == Lisp_Cons;
8e713be6 7346 tail = XCDR (tail))
06a2c219
GM
7347 {
7348 Lisp_Object frame, bar, condemned;
7349
8e713be6 7350 frame = XCAR (tail);
06a2c219
GM
7351 /* All elements of Vframe_list should be frames. */
7352 if (! GC_FRAMEP (frame))
7353 abort ();
7354
7355 /* Scan this frame's scroll bar list for a scroll bar with the
7356 right window ID. */
7357 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7358 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7359 /* This trick allows us to search both the ordinary and
7360 condemned scroll bar lists with one loop. */
7361 ! GC_NILP (bar) || (bar = condemned,
7362 condemned = Qnil,
7363 ! GC_NILP (bar));
7364 bar = XSCROLL_BAR (bar)->next)
7365 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
7366 return XSCROLL_BAR (bar);
7367 }
7368
7369 return 0;
7370}
7371
7372
7373\f
7374/************************************************************************
7375 Toolkit scroll bars
7376 ************************************************************************/
7377
7378#if USE_TOOLKIT_SCROLL_BARS
7379
7380static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
7381static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
7382static void x_create_toolkit_scroll_bar P_ ((struct frame *,
7383 struct scroll_bar *));
7384static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
7385 int, int, int));
7386
7387
7388/* Id of action hook installed for scroll bars. */
7389
7390static XtActionHookId action_hook_id;
7391
7392/* Lisp window being scrolled. Set when starting to interact with
7393 a toolkit scroll bar, reset to nil when ending the interaction. */
7394
7395static Lisp_Object window_being_scrolled;
7396
7397/* Last scroll bar part sent in xm_scroll_callback. */
7398
7399static int last_scroll_bar_part;
7400
ec18280f
SM
7401/* Whether this is an Xaw with arrow-scrollbars. This should imply
7402 that movements of 1/20 of the screen size are mapped to up/down. */
7403
7404static Boolean xaw3d_arrow_scroll;
7405
7406/* Whether the drag scrolling maintains the mouse at the top of the
7407 thumb. If not, resizing the thumb needs to be done more carefully
7408 to avoid jerkyness. */
7409
7410static Boolean xaw3d_pick_top;
7411
06a2c219
GM
7412
7413/* Action hook installed via XtAppAddActionHook when toolkit scroll
ec18280f 7414 bars are used.. The hook is responsible for detecting when
06a2c219
GM
7415 the user ends an interaction with the scroll bar, and generates
7416 a `end-scroll' scroll_bar_click' event if so. */
7417
7418static void
7419xt_action_hook (widget, client_data, action_name, event, params,
7420 num_params)
7421 Widget widget;
7422 XtPointer client_data;
7423 String action_name;
7424 XEvent *event;
7425 String *params;
7426 Cardinal *num_params;
7427{
7428 int scroll_bar_p;
7429 char *end_action;
7430
7431#ifdef USE_MOTIF
7432 scroll_bar_p = XmIsScrollBar (widget);
7433 end_action = "Release";
ec18280f 7434#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7435 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
7436 end_action = "EndScroll";
ec18280f 7437#endif /* USE_MOTIF */
06a2c219 7438
06a2c219
GM
7439 if (scroll_bar_p
7440 && strcmp (action_name, end_action) == 0
7441 && WINDOWP (window_being_scrolled))
7442 {
7443 struct window *w;
7444
7445 x_send_scroll_bar_event (window_being_scrolled,
7446 scroll_bar_end_scroll, 0, 0);
7447 w = XWINDOW (window_being_scrolled);
7448 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
7449 window_being_scrolled = Qnil;
7450 last_scroll_bar_part = -1;
bffcfca9
GM
7451
7452 /* Xt timeouts no longer needed. */
7453 toolkit_scroll_bar_interaction = 0;
06a2c219
GM
7454 }
7455}
7456
7457
7458/* Send a client message with message type Xatom_Scrollbar for a
7459 scroll action to the frame of WINDOW. PART is a value identifying
7460 the part of the scroll bar that was clicked on. PORTION is the
7461 amount to scroll of a whole of WHOLE. */
7462
7463static void
7464x_send_scroll_bar_event (window, part, portion, whole)
7465 Lisp_Object window;
7466 int part, portion, whole;
7467{
7468 XEvent event;
7469 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7470 struct frame *f = XFRAME (XWINDOW (window)->frame);
7471
7472 /* Construct a ClientMessage event to send to the frame. */
7473 ev->type = ClientMessage;
7474 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7475 ev->display = FRAME_X_DISPLAY (f);
7476 ev->window = FRAME_X_WINDOW (f);
7477 ev->format = 32;
52e386c2 7478 ev->data.l[0] = (long) XFASTINT (window);
06a2c219
GM
7479 ev->data.l[1] = (long) part;
7480 ev->data.l[2] = (long) 0;
7481 ev->data.l[3] = (long) portion;
7482 ev->data.l[4] = (long) whole;
7483
bffcfca9
GM
7484 /* Make Xt timeouts work while the scroll bar is active. */
7485 toolkit_scroll_bar_interaction = 1;
7486
06a2c219
GM
7487 /* Setting the event mask to zero means that the message will
7488 be sent to the client that created the window, and if that
7489 window no longer exists, no event will be sent. */
7490 BLOCK_INPUT;
7491 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7492 UNBLOCK_INPUT;
7493}
7494
7495
7496/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7497 in *IEVENT. */
7498
7499static void
7500x_scroll_bar_to_input_event (event, ievent)
7501 XEvent *event;
7502 struct input_event *ievent;
7503{
7504 XClientMessageEvent *ev = (XClientMessageEvent *) event;
52e386c2
KR
7505 Lisp_Object window;
7506 struct frame *f;
7507
7508 XSETFASTINT (window, ev->data.l[0]);
7509 f = XFRAME (XWINDOW (window)->frame);
06a2c219
GM
7510
7511 ievent->kind = scroll_bar_click;
7512 ievent->frame_or_window = window;
7513 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7514 ievent->part = ev->data.l[1];
7515 ievent->code = ev->data.l[2];
7516 ievent->x = make_number ((int) ev->data.l[3]);
7517 ievent->y = make_number ((int) ev->data.l[4]);
7518 ievent->modifiers = 0;
7519}
7520
7521
7522#ifdef USE_MOTIF
7523
7524/* Minimum and maximum values used for Motif scroll bars. */
7525
7526#define XM_SB_MIN 1
7527#define XM_SB_MAX 10000000
7528#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7529
7530
7531/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7532 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7533 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7534
7535static void
7536xm_scroll_callback (widget, client_data, call_data)
7537 Widget widget;
7538 XtPointer client_data, call_data;
7539{
7540 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7541 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7542 double percent;
7543 int part = -1, whole = 0, portion = 0;
7544
7545 switch (cs->reason)
7546 {
7547 case XmCR_DECREMENT:
7548 bar->dragging = Qnil;
7549 part = scroll_bar_up_arrow;
7550 break;
7551
7552 case XmCR_INCREMENT:
7553 bar->dragging = Qnil;
7554 part = scroll_bar_down_arrow;
7555 break;
7556
7557 case XmCR_PAGE_DECREMENT:
7558 bar->dragging = Qnil;
7559 part = scroll_bar_above_handle;
7560 break;
7561
7562 case XmCR_PAGE_INCREMENT:
7563 bar->dragging = Qnil;
7564 part = scroll_bar_below_handle;
7565 break;
7566
7567 case XmCR_TO_TOP:
7568 bar->dragging = Qnil;
7569 part = scroll_bar_to_top;
7570 break;
7571
7572 case XmCR_TO_BOTTOM:
7573 bar->dragging = Qnil;
7574 part = scroll_bar_to_bottom;
7575 break;
7576
7577 case XmCR_DRAG:
7578 {
7579 int slider_size;
7580 int dragging_down_p = (INTEGERP (bar->dragging)
7581 && XINT (bar->dragging) <= cs->value);
7582
7583 /* Get the slider size. */
7584 BLOCK_INPUT;
7585 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7586 UNBLOCK_INPUT;
7587
7588 /* At the max position of the scroll bar, do a line-wise
7589 movement. Without doing anything, the LessTif scroll bar
7590 calls us with the same cs->value again and again. If we
7591 want to make sure that we can reach the end of the buffer,
7592 we have to do something.
7593
7594 Implementation note: setting bar->dragging always to
7595 cs->value gives a smoother movement at the max position.
7596 Setting it to nil when doing line-wise movement gives
7597 a better slider behavior. */
7598
7599 if (cs->value + slider_size == XM_SB_MAX
7600 || (dragging_down_p
7601 && last_scroll_bar_part == scroll_bar_down_arrow))
7602 {
7603 part = scroll_bar_down_arrow;
7604 bar->dragging = Qnil;
7605 }
7606 else
7607 {
7608 whole = XM_SB_RANGE;
7609 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7610 part = scroll_bar_handle;
7611 bar->dragging = make_number (cs->value);
7612 }
7613 }
7614 break;
7615
7616 case XmCR_VALUE_CHANGED:
7617 break;
7618 };
7619
7620 if (part >= 0)
7621 {
7622 window_being_scrolled = bar->window;
7623 last_scroll_bar_part = part;
7624 x_send_scroll_bar_event (bar->window, part, portion, whole);
7625 }
7626}
7627
7628
ec18280f 7629#else /* !USE_MOTIF, i.e. Xaw. */
06a2c219
GM
7630
7631
ec18280f 7632/* Xaw scroll bar callback. Invoked when the thumb is dragged.
06a2c219
GM
7633 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7634 scroll bar struct. CALL_DATA is a pointer to a float saying where
7635 the thumb is. */
7636
7637static void
ec18280f 7638xaw_jump_callback (widget, client_data, call_data)
06a2c219
GM
7639 Widget widget;
7640 XtPointer client_data, call_data;
7641{
7642 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7643 float top = *(float *) call_data;
7644 float shown;
ec18280f
SM
7645 int whole, portion, height;
7646 int part;
06a2c219
GM
7647
7648 /* Get the size of the thumb, a value between 0 and 1. */
7649 BLOCK_INPUT;
ec18280f 7650 XtVaGetValues (widget, XtNshown, &shown, XtNheight, &height, NULL);
06a2c219
GM
7651 UNBLOCK_INPUT;
7652
7653 whole = 10000000;
7654 portion = shown < 1 ? top * whole : 0;
06a2c219 7655
ec18280f
SM
7656 if (shown < 1 && (abs (top + shown - 1) < 1.0/height))
7657 /* Some derivatives of Xaw refuse to shrink the thumb when you reach
7658 the bottom, so we force the scrolling whenever we see that we're
7659 too close to the bottom (in x_set_toolkit_scroll_bar_thumb
7660 we try to ensure that we always stay two pixels away from the
7661 bottom). */
06a2c219
GM
7662 part = scroll_bar_down_arrow;
7663 else
7664 part = scroll_bar_handle;
7665
7666 window_being_scrolled = bar->window;
7667 bar->dragging = make_number (portion);
7668 last_scroll_bar_part = part;
7669 x_send_scroll_bar_event (bar->window, part, portion, whole);
7670}
7671
7672
ec18280f
SM
7673/* Xaw scroll bar callback. Invoked for incremental scrolling.,
7674 i.e. line or page up or down. WIDGET is the Xaw scroll bar
06a2c219
GM
7675 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7676 the scroll bar. CALL_DATA is an integer specifying the action that
7677 has taken place. It's magnitude is in the range 0..height of the
7678 scroll bar. Negative values mean scroll towards buffer start.
7679 Values < height of scroll bar mean line-wise movement. */
7680
7681static void
ec18280f 7682xaw_scroll_callback (widget, client_data, call_data)
06a2c219
GM
7683 Widget widget;
7684 XtPointer client_data, call_data;
7685{
7686 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7687 int position = (int) call_data;
7688 Dimension height;
7689 int part;
7690
7691 /* Get the height of the scroll bar. */
7692 BLOCK_INPUT;
7693 XtVaGetValues (widget, XtNheight, &height, NULL);
7694 UNBLOCK_INPUT;
7695
ec18280f
SM
7696 if (abs (position) >= height)
7697 part = (position < 0) ? scroll_bar_above_handle : scroll_bar_below_handle;
7698
7699 /* If Xaw3d was compiled with ARROW_SCROLLBAR,
7700 it maps line-movement to call_data = max(5, height/20). */
7701 else if (xaw3d_arrow_scroll && abs (position) <= max (5, height / 20))
7702 part = (position < 0) ? scroll_bar_up_arrow : scroll_bar_down_arrow;
06a2c219 7703 else
ec18280f 7704 part = scroll_bar_move_ratio;
06a2c219
GM
7705
7706 window_being_scrolled = bar->window;
7707 bar->dragging = Qnil;
7708 last_scroll_bar_part = part;
ec18280f 7709 x_send_scroll_bar_event (bar->window, part, position, height);
06a2c219
GM
7710}
7711
7712
7713#endif /* not USE_MOTIF */
7714
7715
7716/* Create the widget for scroll bar BAR on frame F. Record the widget
7717 and X window of the scroll bar in BAR. */
7718
7719static void
7720x_create_toolkit_scroll_bar (f, bar)
7721 struct frame *f;
7722 struct scroll_bar *bar;
7723{
7724 Window xwindow;
7725 Widget widget;
7726 Arg av[20];
7727 int ac = 0;
7728 char *scroll_bar_name = "verticalScrollBar";
7729 unsigned long pixel;
7730
7731 BLOCK_INPUT;
7732
7733#ifdef USE_MOTIF
7734 /* LessTif 0.85, problems:
7735
7736 1. When the mouse if over the scroll bar, the scroll bar will
7737 get keyboard events. I didn't find a way to turn this off.
7738
7739 2. Do we have to explicitly set the cursor to get an arrow
7740 cursor (see below)? */
7741
7742 /* Set resources. Create the widget. */
7743 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7744 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7745 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7746 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7747 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7748 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7749 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7750
7751 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7752 if (pixel != -1)
7753 {
7754 XtSetArg (av[ac], XmNforeground, pixel);
7755 ++ac;
7756 }
7757
7758 pixel = f->output_data.x->scroll_bar_background_pixel;
7759 if (pixel != -1)
7760 {
7761 XtSetArg (av[ac], XmNbackground, pixel);
7762 ++ac;
7763 }
7764
7765 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7766 scroll_bar_name, av, ac);
7767
7768 /* Add one callback for everything that can happen. */
7769 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7770 (XtPointer) bar);
7771 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7772 (XtPointer) bar);
7773 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7774 (XtPointer) bar);
7775 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7776 (XtPointer) bar);
7777 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7778 (XtPointer) bar);
7779 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7780 (XtPointer) bar);
7781 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7782 (XtPointer) bar);
7783
7784 /* Realize the widget. Only after that is the X window created. */
7785 XtRealizeWidget (widget);
7786
7787 /* Set the cursor to an arrow. I didn't find a resource to do that.
7788 And I'm wondering why it hasn't an arrow cursor by default. */
7789 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7790 f->output_data.x->nontext_cursor);
7791
ec18280f 7792#else /* !USE_MOTIF i.e. use Xaw */
06a2c219
GM
7793
7794 /* Set resources. Create the widget. The background of the
7795 Xaw3d scroll bar widget is a little bit light for my taste.
7796 We don't alter it here to let users change it according
7797 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7798 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7799 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
ec18280f
SM
7800 /* For smoother scrolling with Xaw3d -sm */
7801 /* XtSetArg (av[ac], XtNpickTop, True); ++ac; */
7802 /* XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac; */
06a2c219
GM
7803
7804 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7805 if (pixel != -1)
7806 {
7807 XtSetArg (av[ac], XtNforeground, pixel);
7808 ++ac;
7809 }
7810
7811 pixel = f->output_data.x->scroll_bar_background_pixel;
7812 if (pixel != -1)
7813 {
7814 XtSetArg (av[ac], XtNbackground, pixel);
7815 ++ac;
7816 }
7817
7818 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7819 f->output_data.x->edit_widget, av, ac);
ec18280f
SM
7820
7821 {
7822 char *initial = "";
7823 char *val = initial;
7824 XtVaGetValues (widget, XtNscrollVCursor, (XtPointer) &val,
7825 XtNpickTop, (XtPointer) &xaw3d_pick_top, NULL);
7826 if (val == initial)
7827 { /* ARROW_SCROLL */
7828 xaw3d_arrow_scroll = True;
7829 /* Isn't that just a personal preference ? -sm */
7830 XtVaSetValues (widget, XtNcursorName, "top_left_arrow", NULL);
7831 }
7832 }
06a2c219
GM
7833
7834 /* Define callbacks. */
ec18280f
SM
7835 XtAddCallback (widget, XtNjumpProc, xaw_jump_callback, (XtPointer) bar);
7836 XtAddCallback (widget, XtNscrollProc, xaw_scroll_callback,
06a2c219
GM
7837 (XtPointer) bar);
7838
7839 /* Realize the widget. Only after that is the X window created. */
7840 XtRealizeWidget (widget);
7841
ec18280f 7842#endif /* !USE_MOTIF */
06a2c219
GM
7843
7844 /* Install an action hook that let's us detect when the user
7845 finishes interacting with a scroll bar. */
7846 if (action_hook_id == 0)
7847 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7848
7849 /* Remember X window and widget in the scroll bar vector. */
7850 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7851 xwindow = XtWindow (widget);
7852 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7853
7854 UNBLOCK_INPUT;
7855}
7856
7857
7858/* Set the thumb size and position of scroll bar BAR. We are currently
7859 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7860
7861static void
7862x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7863 struct scroll_bar *bar;
7864 int portion, position, whole;
f451eb13 7865{
06a2c219 7866 float top, shown;
06a2c219 7867 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7868
06a2c219
GM
7869 if (whole == 0)
7870 top = 0, shown = 1;
7871 else
f451eb13 7872 {
06a2c219
GM
7873 top = (float) position / whole;
7874 shown = (float) portion / whole;
7875 }
f451eb13 7876
06a2c219 7877 BLOCK_INPUT;
f451eb13 7878
06a2c219
GM
7879#ifdef USE_MOTIF
7880 {
7881 int size, value;
7882 Boolean arrow1_selected, arrow2_selected;
7883 unsigned char flags;
7884 XmScrollBarWidget sb;
7885
ec18280f 7886 /* Slider size. Must be in the range [1 .. MAX - MIN] where MAX
06a2c219
GM
7887 is the scroll bar's maximum and MIN is the scroll bar's minimum
7888 value. */
7889 size = shown * XM_SB_RANGE;
7890 size = min (size, XM_SB_RANGE);
7891 size = max (size, 1);
7892
7893 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7894 value = top * XM_SB_RANGE;
7895 value = min (value, XM_SB_MAX - size);
7896 value = max (value, XM_SB_MIN);
7897
7898 /* LessTif: Calling XmScrollBarSetValues after an increment or
7899 decrement turns off auto-repeat LessTif-internally. This can
7900 be seen in ScrollBar.c which resets Arrow1Selected and
7901 Arrow2Selected. It also sets internal flags so that LessTif
7902 believes the mouse is in the slider. We either have to change
7903 our code, or work around that by accessing private data. */
7904
7905 sb = (XmScrollBarWidget) widget;
7906 arrow1_selected = sb->scrollBar.arrow1_selected;
7907 arrow2_selected = sb->scrollBar.arrow2_selected;
7908 flags = sb->scrollBar.flags;
7909
7910 if (NILP (bar->dragging))
7911 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7912 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7913 /* This has the negative side effect that the slider value is
ec18280f 7914 not what it would be if we scrolled here using line-wise or
06a2c219
GM
7915 page-wise movement. */
7916 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7917 else
7918 {
7919 /* If currently dragging, only update the slider size.
7920 This reduces flicker effects. */
7921 int old_value, old_size, increment, page_increment;
7922
7923 XmScrollBarGetValues (widget, &old_value, &old_size,
7924 &increment, &page_increment);
7925 XmScrollBarSetValues (widget, old_value,
7926 min (size, XM_SB_RANGE - old_value),
7927 0, 0, False);
7928 }
7929
7930 sb->scrollBar.arrow1_selected = arrow1_selected;
7931 sb->scrollBar.arrow2_selected = arrow2_selected;
7932 sb->scrollBar.flags = flags;
7933 }
ec18280f 7934#else /* !USE_MOTIF i.e. use Xaw */
06a2c219 7935 {
ec18280f
SM
7936 float old_top, old_shown;
7937 Dimension height;
7938 XtVaGetValues (widget,
7939 XtNtopOfThumb, &old_top,
7940 XtNshown, &old_shown,
7941 XtNheight, &height,
7942 NULL);
7943
7944 /* Massage the top+shown values. */
7945 if (NILP (bar->dragging) || last_scroll_bar_part == scroll_bar_down_arrow)
7946 top = max (0, min (1, top));
7947 else
7948 top = old_top;
7949 /* Keep two pixels available for moving the thumb down. */
7950 shown = max (0, min (1 - top - (2.0 / height), shown));
06a2c219
GM
7951
7952 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7953 check that your system's configuration file contains a define
7954 for `NARROWPROTO'. See s/freebsd.h for an example. */
ec18280f 7955 if (top != old_top || shown != old_shown)
eb393530 7956 {
ec18280f 7957 if (NILP (bar->dragging))
eb393530 7958 XawScrollbarSetThumb (widget, top, shown);
06a2c219
GM
7959 else
7960 {
ec18280f
SM
7961#ifdef HAVE_XAW3D
7962 ScrollbarWidget sb = (ScrollbarWidget) widget;
3e71d8f2 7963 int scroll_mode = 0;
ec18280f
SM
7964
7965 /* `scroll_mode' only exists with Xaw3d + ARROW_SCROLLBAR. */
7966 if (xaw3d_arrow_scroll)
7967 {
7968 /* Xaw3d stupidly ignores resize requests while dragging
7969 so we have to make it believe it's not in dragging mode. */
7970 scroll_mode = sb->scrollbar.scroll_mode;
7971 if (scroll_mode == 2)
7972 sb->scrollbar.scroll_mode = 0;
7973 }
7974#endif
7975 /* Try to make the scrolling a tad smoother. */
7976 if (!xaw3d_pick_top)
7977 shown = min (shown, old_shown);
7978
7979 XawScrollbarSetThumb (widget, top, shown);
7980
7981#ifdef HAVE_XAW3D
7982 if (xaw3d_arrow_scroll && scroll_mode == 2)
7983 sb->scrollbar.scroll_mode = scroll_mode;
7984#endif
06a2c219 7985 }
06a2c219
GM
7986 }
7987 }
ec18280f 7988#endif /* !USE_MOTIF */
06a2c219
GM
7989
7990 UNBLOCK_INPUT;
f451eb13
JB
7991}
7992
06a2c219
GM
7993#endif /* USE_TOOLKIT_SCROLL_BARS */
7994
7995
7996\f
7997/************************************************************************
7998 Scroll bars, general
7999 ************************************************************************/
8000
8001/* Create a scroll bar and return the scroll bar vector for it. W is
8002 the Emacs window on which to create the scroll bar. TOP, LEFT,
8003 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
8004 scroll bar. */
8005
ab648270 8006static struct scroll_bar *
06a2c219
GM
8007x_scroll_bar_create (w, top, left, width, height)
8008 struct window *w;
f451eb13
JB
8009 int top, left, width, height;
8010{
06a2c219 8011 struct frame *f = XFRAME (w->frame);
334208b7
RS
8012 struct scroll_bar *bar
8013 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
8014
8015 BLOCK_INPUT;
8016
06a2c219
GM
8017#if USE_TOOLKIT_SCROLL_BARS
8018 x_create_toolkit_scroll_bar (f, bar);
8019#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8020 {
8021 XSetWindowAttributes a;
8022 unsigned long mask;
5c187dee 8023 Window window;
06a2c219
GM
8024
8025 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
8026 if (a.background_pixel == -1)
8027 a.background_pixel = f->output_data.x->background_pixel;
8028
12ba150f 8029 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 8030 | ButtonMotionMask | PointerMotionHintMask
12ba150f 8031 | ExposureMask);
7a13e894 8032 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 8033
dbc4e1c1 8034 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 8035
06a2c219
GM
8036 /* Clear the area of W that will serve as a scroll bar. This is
8037 for the case that a window has been split horizontally. In
8038 this case, no clear_frame is generated to reduce flickering. */
8039 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8040 left, top, width,
8041 window_box_height (w), False);
8042
8043 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8044 /* Position and size of scroll bar. */
8045 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8046 top,
8047 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8048 height,
8049 /* Border width, depth, class, and visual. */
8050 0,
8051 CopyFromParent,
8052 CopyFromParent,
8053 CopyFromParent,
8054 /* Attributes. */
8055 mask, &a);
8056 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 8057 }
06a2c219 8058#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8059
06a2c219 8060 XSETWINDOW (bar->window, w);
e0c1aef2
KH
8061 XSETINT (bar->top, top);
8062 XSETINT (bar->left, left);
8063 XSETINT (bar->width, width);
8064 XSETINT (bar->height, height);
8065 XSETINT (bar->start, 0);
8066 XSETINT (bar->end, 0);
12ba150f 8067 bar->dragging = Qnil;
f451eb13
JB
8068
8069 /* Add bar to its frame's list of scroll bars. */
334208b7 8070 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8071 bar->prev = Qnil;
334208b7 8072 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 8073 if (!NILP (bar->next))
e0c1aef2 8074 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 8075
06a2c219
GM
8076 /* Map the window/widget. */
8077#if USE_TOOLKIT_SCROLL_BARS
8078 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
8079 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
8080 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8081 top,
8082 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8083 height, 0);
8084#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 8085 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 8086#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8087
8088 UNBLOCK_INPUT;
12ba150f 8089 return bar;
f451eb13
JB
8090}
8091
06a2c219 8092
12ba150f 8093/* Draw BAR's handle in the proper position.
06a2c219 8094
12ba150f
JB
8095 If the handle is already drawn from START to END, don't bother
8096 redrawing it, unless REBUILD is non-zero; in that case, always
8097 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 8098 events.)
12ba150f
JB
8099
8100 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
8101 fit inside its rectangle, but if the user is dragging the scroll
8102 bar handle, we want to let them drag it down all the way, so that
8103 the bar's top is as far down as it goes; otherwise, there's no way
8104 to move to the very end of the buffer. */
8105
5c187dee
GM
8106#ifndef USE_TOOLKIT_SCROLL_BARS
8107
f451eb13 8108static void
ab648270
JB
8109x_scroll_bar_set_handle (bar, start, end, rebuild)
8110 struct scroll_bar *bar;
f451eb13 8111 int start, end;
12ba150f 8112 int rebuild;
f451eb13 8113{
12ba150f 8114 int dragging = ! NILP (bar->dragging);
ab648270 8115 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8116 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8117 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
8118
8119 /* If the display is already accurate, do nothing. */
8120 if (! rebuild
8121 && start == XINT (bar->start)
8122 && end == XINT (bar->end))
8123 return;
8124
f451eb13
JB
8125 BLOCK_INPUT;
8126
8127 {
d9cdbb3d
RS
8128 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
8129 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
8130 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
8131
8132 /* Make sure the values are reasonable, and try to preserve
8133 the distance between start and end. */
12ba150f
JB
8134 {
8135 int length = end - start;
8136
8137 if (start < 0)
8138 start = 0;
8139 else if (start > top_range)
8140 start = top_range;
8141 end = start + length;
8142
8143 if (end < start)
8144 end = start;
8145 else if (end > top_range && ! dragging)
8146 end = top_range;
8147 }
f451eb13 8148
ab648270 8149 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
8150 XSETINT (bar->start, start);
8151 XSETINT (bar->end, end);
f451eb13 8152
12ba150f
JB
8153 /* Clip the end position, just for display. */
8154 if (end > top_range)
8155 end = top_range;
f451eb13 8156
ab648270 8157 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
8158 below top positions, to make sure the handle is always at least
8159 that many pixels tall. */
ab648270 8160 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 8161
12ba150f
JB
8162 /* Draw the empty space above the handle. Note that we can't clear
8163 zero-height areas; that means "clear to end of window." */
8164 if (0 < start)
334208b7 8165 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8166
12ba150f 8167 /* x, y, width, height, and exposures. */
ab648270
JB
8168 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8169 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
8170 inside_width, start,
8171 False);
f451eb13 8172
06a2c219
GM
8173 /* Change to proper foreground color if one is specified. */
8174 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8175 XSetForeground (FRAME_X_DISPLAY (f), gc,
8176 f->output_data.x->scroll_bar_foreground_pixel);
8177
12ba150f 8178 /* Draw the handle itself. */
334208b7 8179 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 8180
12ba150f 8181 /* x, y, width, height */
ab648270
JB
8182 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8183 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 8184 inside_width, end - start);
f451eb13 8185
06a2c219
GM
8186 /* Restore the foreground color of the GC if we changed it above. */
8187 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
8188 XSetForeground (FRAME_X_DISPLAY (f), gc,
8189 f->output_data.x->foreground_pixel);
f451eb13 8190
12ba150f
JB
8191 /* Draw the empty space below the handle. Note that we can't
8192 clear zero-height areas; that means "clear to end of window." */
8193 if (end < inside_height)
334208b7 8194 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 8195
12ba150f 8196 /* x, y, width, height, and exposures. */
ab648270
JB
8197 VERTICAL_SCROLL_BAR_LEFT_BORDER,
8198 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
8199 inside_width, inside_height - end,
8200 False);
f451eb13 8201
f451eb13
JB
8202 }
8203
f451eb13
JB
8204 UNBLOCK_INPUT;
8205}
8206
5c187dee 8207#endif /* !USE_TOOLKIT_SCROLL_BARS */
f451eb13 8208
06a2c219
GM
8209/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
8210 nil. */
58769bee 8211
12ba150f 8212static void
ab648270
JB
8213x_scroll_bar_remove (bar)
8214 struct scroll_bar *bar;
12ba150f 8215{
12ba150f
JB
8216 BLOCK_INPUT;
8217
06a2c219
GM
8218#if USE_TOOLKIT_SCROLL_BARS
8219 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
8220#else /* not USE_TOOLKIT_SCROLL_BARS */
5c187dee
GM
8221 {
8222 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8223 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
8224 }
06a2c219
GM
8225#endif /* not USE_TOOLKIT_SCROLL_BARS */
8226
ab648270
JB
8227 /* Disassociate this scroll bar from its window. */
8228 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
8229
8230 UNBLOCK_INPUT;
8231}
8232
06a2c219 8233
12ba150f
JB
8234/* Set the handle of the vertical scroll bar for WINDOW to indicate
8235 that we are displaying PORTION characters out of a total of WHOLE
ab648270 8236 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 8237 create one. */
06a2c219 8238
12ba150f 8239static void
06a2c219
GM
8240XTset_vertical_scroll_bar (w, portion, whole, position)
8241 struct window *w;
f451eb13
JB
8242 int portion, whole, position;
8243{
06a2c219 8244 struct frame *f = XFRAME (w->frame);
ab648270 8245 struct scroll_bar *bar;
3c6ede7b 8246 int top, height, left, sb_left, width, sb_width;
06a2c219 8247 int window_x, window_y, window_width, window_height;
06a2c219 8248
3c6ede7b 8249 /* Get window dimensions. */
06a2c219 8250 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
3c6ede7b
GM
8251 top = window_y;
8252 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8253 height = window_height;
06a2c219 8254
3c6ede7b 8255 /* Compute the left edge of the scroll bar area. */
06a2c219 8256 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3c6ede7b
GM
8257 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8258 else
8259 left = XFASTINT (w->left);
8260 left *= CANON_X_UNIT (f);
8261 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8262
8263 /* Compute the width of the scroll bar which might be less than
8264 the width of the area reserved for the scroll bar. */
8265 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8266 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
06a2c219 8267 else
3c6ede7b 8268 sb_width = width;
12ba150f 8269
3c6ede7b
GM
8270 /* Compute the left edge of the scroll bar. */
8271#ifdef USE_TOOLKIT_SCROLL_BARS
8272 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8273 sb_left = left + width - sb_width - (width - sb_width) / 2;
8274 else
8275 sb_left = left + (width - sb_width) / 2;
8276#else
8277 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8278 sb_left = left + width - sb_width;
8279 else
8280 sb_left = left;
8281#endif
8282
ab648270 8283 /* Does the scroll bar exist yet? */
06a2c219 8284 if (NILP (w->vertical_scroll_bar))
3c6ede7b 8285 {
80c32bcc 8286 BLOCK_INPUT;
3c6ede7b
GM
8287 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8288 left, top, width, height, False);
80c32bcc 8289 UNBLOCK_INPUT;
3c6ede7b
GM
8290 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8291 }
f451eb13 8292 else
12ba150f
JB
8293 {
8294 /* It may just need to be moved and resized. */
06a2c219
GM
8295 unsigned int mask = 0;
8296
8297 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8298
8299 BLOCK_INPUT;
8300
3c6ede7b 8301 if (sb_left != XINT (bar->left))
06a2c219 8302 mask |= CWX;
3c6ede7b 8303 if (top != XINT (bar->top))
06a2c219 8304 mask |= CWY;
3c6ede7b 8305 if (sb_width != XINT (bar->width))
06a2c219 8306 mask |= CWWidth;
3c6ede7b 8307 if (height != XINT (bar->height))
06a2c219
GM
8308 mask |= CWHeight;
8309
8310#ifdef USE_TOOLKIT_SCROLL_BARS
fe6f39d9
GM
8311
8312 /* Since toolkit scroll bars are smaller than the space reserved
8313 for them on the frame, we have to clear "under" them. */
8314 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3c6ede7b 8315 left, top, width, height, False);
06a2c219
GM
8316
8317 /* Move/size the scroll bar widget. */
8318 if (mask)
8319 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
3c6ede7b
GM
8320 sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8321 top,
8322 sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8323 height, 0);
06a2c219
GM
8324
8325#else /* not USE_TOOLKIT_SCROLL_BARS */
8326
e1f6572f
RS
8327 if (VERTICAL_SCROLL_BAR_WIDTH_TRIM)
8328 {
8329 /* Clear areas not covered by the scroll bar. This makes sure a
8330 previous mode line display is cleared after C-x 2 C-x 1, for
8331 example. Non-toolkit scroll bars are as wide as the area
8332 reserved for scroll bars - trim at both sides. */
8333 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8334 left, top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8335 height, False);
8336 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
8337 left + width - VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8338 top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8339 height, False);
8340 }
06a2c219
GM
8341
8342 /* Move/size the scroll bar window. */
8343 if (mask)
8344 {
8345 XWindowChanges wc;
8346
3c6ede7b
GM
8347 wc.x = sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
8348 wc.y = top;
8349 wc.width = sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
8350 wc.height = height;
06a2c219
GM
8351 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
8352 mask, &wc);
8353 }
8354
8355#endif /* not USE_TOOLKIT_SCROLL_BARS */
8356
8357 /* Remember new settings. */
3c6ede7b
GM
8358 XSETINT (bar->left, sb_left);
8359 XSETINT (bar->top, top);
8360 XSETINT (bar->width, sb_width);
8361 XSETINT (bar->height, height);
06a2c219
GM
8362
8363 UNBLOCK_INPUT;
12ba150f 8364 }
f451eb13 8365
06a2c219
GM
8366#if USE_TOOLKIT_SCROLL_BARS
8367 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
8368#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 8369 /* Set the scroll bar's current state, unless we're currently being
f451eb13 8370 dragged. */
12ba150f 8371 if (NILP (bar->dragging))
f451eb13 8372 {
92857db0 8373 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
f451eb13 8374
12ba150f 8375 if (whole == 0)
ab648270 8376 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
8377 else
8378 {
43f868f5
JB
8379 int start = ((double) position * top_range) / whole;
8380 int end = ((double) (position + portion) * top_range) / whole;
ab648270 8381 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 8382 }
f451eb13 8383 }
06a2c219 8384#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 8385
06a2c219 8386 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
8387}
8388
12ba150f 8389
f451eb13 8390/* The following three hooks are used when we're doing a thorough
ab648270 8391 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 8392 are going to be deleted, because keeping track of when windows go
12ba150f
JB
8393 away is a real pain - "Can you say set-window-configuration, boys
8394 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 8395 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 8396 from the fiery pit when we actually redisplay its window. */
f451eb13 8397
ab648270
JB
8398/* Arrange for all scroll bars on FRAME to be removed at the next call
8399 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
8400 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8401
58769bee 8402static void
ab648270 8403XTcondemn_scroll_bars (frame)
f451eb13
JB
8404 FRAME_PTR frame;
8405{
f9e24cb9
RS
8406 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8407 while (! NILP (FRAME_SCROLL_BARS (frame)))
8408 {
8409 Lisp_Object bar;
8410 bar = FRAME_SCROLL_BARS (frame);
8411 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8412 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8413 XSCROLL_BAR (bar)->prev = Qnil;
8414 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8415 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8416 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8417 }
f451eb13
JB
8418}
8419
06a2c219 8420/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 8421 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 8422static void
ab648270 8423XTredeem_scroll_bar (window)
12ba150f 8424 struct window *window;
f451eb13 8425{
ab648270 8426 struct scroll_bar *bar;
12ba150f 8427
ab648270
JB
8428 /* We can't redeem this window's scroll bar if it doesn't have one. */
8429 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
8430 abort ();
8431
ab648270 8432 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
8433
8434 /* Unlink it from the condemned list. */
8435 {
8436 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
8437
8438 if (NILP (bar->prev))
8439 {
8440 /* If the prev pointer is nil, it must be the first in one of
8441 the lists. */
ab648270 8442 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
8443 /* It's not condemned. Everything's fine. */
8444 return;
ab648270
JB
8445 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8446 window->vertical_scroll_bar))
8447 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
8448 else
8449 /* If its prev pointer is nil, it must be at the front of
8450 one or the other! */
8451 abort ();
8452 }
8453 else
ab648270 8454 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
8455
8456 if (! NILP (bar->next))
ab648270 8457 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 8458
ab648270 8459 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 8460 bar->prev = Qnil;
e0c1aef2 8461 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 8462 if (! NILP (bar->next))
e0c1aef2 8463 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 8464 }
f451eb13
JB
8465}
8466
ab648270
JB
8467/* Remove all scroll bars on FRAME that haven't been saved since the
8468 last call to `*condemn_scroll_bars_hook'. */
06a2c219 8469
f451eb13 8470static void
ab648270 8471XTjudge_scroll_bars (f)
12ba150f 8472 FRAME_PTR f;
f451eb13 8473{
12ba150f 8474 Lisp_Object bar, next;
f451eb13 8475
ab648270 8476 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8477
8478 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8479 more events on the hapless scroll bars. */
8480 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8481
8482 for (; ! NILP (bar); bar = next)
f451eb13 8483 {
ab648270 8484 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8485
ab648270 8486 x_scroll_bar_remove (b);
12ba150f
JB
8487
8488 next = b->next;
8489 b->next = b->prev = Qnil;
f451eb13 8490 }
12ba150f 8491
ab648270 8492 /* Now there should be no references to the condemned scroll bars,
12ba150f 8493 and they should get garbage-collected. */
f451eb13
JB
8494}
8495
8496
06a2c219
GM
8497/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8498 is a no-op when using toolkit scroll bars.
ab648270
JB
8499
8500 This may be called from a signal handler, so we have to ignore GC
8501 mark bits. */
06a2c219 8502
f451eb13 8503static void
ab648270
JB
8504x_scroll_bar_expose (bar, event)
8505 struct scroll_bar *bar;
f451eb13
JB
8506 XEvent *event;
8507{
06a2c219
GM
8508#ifndef USE_TOOLKIT_SCROLL_BARS
8509
ab648270 8510 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8511 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8512 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8513 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8514
f451eb13
JB
8515 BLOCK_INPUT;
8516
ab648270 8517 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8518
06a2c219 8519 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8520 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8521
8522 /* x, y, width, height */
d9cdbb3d 8523 0, 0,
3cbd2e0b 8524 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8525 XINT (bar->height) - 1);
8526
f451eb13 8527 UNBLOCK_INPUT;
06a2c219
GM
8528
8529#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8530}
8531
ab648270
JB
8532/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8533 is set to something other than no_event, it is enqueued.
8534
8535 This may be called from a signal handler, so we have to ignore GC
8536 mark bits. */
06a2c219 8537
5c187dee
GM
8538#ifndef USE_TOOLKIT_SCROLL_BARS
8539
f451eb13 8540static void
ab648270
JB
8541x_scroll_bar_handle_click (bar, event, emacs_event)
8542 struct scroll_bar *bar;
f451eb13
JB
8543 XEvent *event;
8544 struct input_event *emacs_event;
8545{
0299d313 8546 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8547 abort ();
8548
ab648270 8549 emacs_event->kind = scroll_bar_click;
69388238 8550 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8551 emacs_event->modifiers
8552 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8553 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8554 event->xbutton.state)
8555 | (event->type == ButtonRelease
8556 ? up_modifier
8557 : down_modifier));
12ba150f 8558 emacs_event->frame_or_window = bar->window;
f451eb13 8559 emacs_event->timestamp = event->xbutton.time;
12ba150f 8560 {
06a2c219 8561#if 0
d9cdbb3d 8562 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8563 int internal_height
d9cdbb3d 8564 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8565#endif
0299d313 8566 int top_range
d9cdbb3d 8567 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8568 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8569
8570 if (y < 0) y = 0;
8571 if (y > top_range) y = top_range;
8572
8573 if (y < XINT (bar->start))
ab648270
JB
8574 emacs_event->part = scroll_bar_above_handle;
8575 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8576 emacs_event->part = scroll_bar_handle;
12ba150f 8577 else
ab648270 8578 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8579
8580 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8581 they want to drag it. Lisp code needs to be able to decide
8582 whether or not we're dragging. */
929787e1 8583#if 0
12ba150f
JB
8584 /* If the user has just clicked on the handle, record where they're
8585 holding it. */
8586 if (event->type == ButtonPress
ab648270 8587 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8588 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8589#endif
12ba150f
JB
8590
8591 /* If the user has released the handle, set it to its final position. */
8592 if (event->type == ButtonRelease
8593 && ! NILP (bar->dragging))
8594 {
8595 int new_start = y - XINT (bar->dragging);
8596 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8597
ab648270 8598 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8599 bar->dragging = Qnil;
8600 }
f451eb13 8601
5116f055
JB
8602 /* Same deal here as the other #if 0. */
8603#if 0
58769bee 8604 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8605 the handle. */
ab648270 8606 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8607 emacs_event->x = bar->start;
8608 else
e0c1aef2 8609 XSETINT (emacs_event->x, y);
5116f055 8610#else
e0c1aef2 8611 XSETINT (emacs_event->x, y);
5116f055 8612#endif
f451eb13 8613
e0c1aef2 8614 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8615 }
8616}
f451eb13 8617
ab648270
JB
8618/* Handle some mouse motion while someone is dragging the scroll bar.
8619
8620 This may be called from a signal handler, so we have to ignore GC
8621 mark bits. */
06a2c219 8622
f451eb13 8623static void
ab648270
JB
8624x_scroll_bar_note_movement (bar, event)
8625 struct scroll_bar *bar;
f451eb13
JB
8626 XEvent *event;
8627{
39d8bb4d
KH
8628 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8629
f451eb13
JB
8630 last_mouse_movement_time = event->xmotion.time;
8631
39d8bb4d 8632 f->mouse_moved = 1;
e0c1aef2 8633 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8634
8635 /* If we're dragging the bar, display it. */
ab648270 8636 if (! GC_NILP (bar->dragging))
f451eb13
JB
8637 {
8638 /* Where should the handle be now? */
12ba150f 8639 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8640
12ba150f 8641 if (new_start != XINT (bar->start))
f451eb13 8642 {
12ba150f 8643 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8644
ab648270 8645 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8646 }
8647 }
f451eb13
JB
8648}
8649
5c187dee
GM
8650#endif /* !USE_TOOLKIT_SCROLL_BARS */
8651
12ba150f 8652/* Return information to the user about the current position of the mouse
ab648270 8653 on the scroll bar. */
06a2c219 8654
12ba150f 8655static void
334208b7
RS
8656x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8657 FRAME_PTR *fp;
12ba150f 8658 Lisp_Object *bar_window;
ab648270 8659 enum scroll_bar_part *part;
12ba150f
JB
8660 Lisp_Object *x, *y;
8661 unsigned long *time;
8662{
ab648270 8663 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8664 Window w = SCROLL_BAR_X_WINDOW (bar);
8665 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8666 int win_x, win_y;
559cb2fb
JB
8667 Window dummy_window;
8668 int dummy_coord;
8669 unsigned int dummy_mask;
12ba150f 8670
cf7cb199
JB
8671 BLOCK_INPUT;
8672
ab648270 8673 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8674 report that. */
334208b7 8675 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8676
559cb2fb
JB
8677 /* Root, child, root x and root y. */
8678 &dummy_window, &dummy_window,
8679 &dummy_coord, &dummy_coord,
12ba150f 8680
559cb2fb
JB
8681 /* Position relative to scroll bar. */
8682 &win_x, &win_y,
12ba150f 8683
559cb2fb
JB
8684 /* Mouse buttons and modifier keys. */
8685 &dummy_mask))
7a13e894 8686 ;
559cb2fb
JB
8687 else
8688 {
06a2c219 8689#if 0
559cb2fb 8690 int inside_height
d9cdbb3d 8691 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8692#endif
559cb2fb 8693 int top_range
d9cdbb3d 8694 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8695
8696 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8697
8698 if (! NILP (bar->dragging))
8699 win_y -= XINT (bar->dragging);
8700
8701 if (win_y < 0)
8702 win_y = 0;
8703 if (win_y > top_range)
8704 win_y = top_range;
8705
334208b7 8706 *fp = f;
7a13e894 8707 *bar_window = bar->window;
559cb2fb
JB
8708
8709 if (! NILP (bar->dragging))
8710 *part = scroll_bar_handle;
8711 else if (win_y < XINT (bar->start))
8712 *part = scroll_bar_above_handle;
8713 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8714 *part = scroll_bar_handle;
8715 else
8716 *part = scroll_bar_below_handle;
12ba150f 8717
e0c1aef2
KH
8718 XSETINT (*x, win_y);
8719 XSETINT (*y, top_range);
12ba150f 8720
39d8bb4d 8721 f->mouse_moved = 0;
559cb2fb
JB
8722 last_mouse_scroll_bar = Qnil;
8723 }
12ba150f 8724
559cb2fb 8725 *time = last_mouse_movement_time;
cf7cb199 8726
cf7cb199 8727 UNBLOCK_INPUT;
12ba150f
JB
8728}
8729
f451eb13 8730
dbc4e1c1 8731/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8732 background colors, and the scroll bars may need to be redrawn.
8733 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8734 redraw them. */
8735
dfcf069d 8736void
ab648270 8737x_scroll_bar_clear (f)
dbc4e1c1
JB
8738 FRAME_PTR f;
8739{
06a2c219 8740#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8741 Lisp_Object bar;
8742
b80c363e
RS
8743 /* We can have scroll bars even if this is 0,
8744 if we just turned off scroll bar mode.
8745 But in that case we should not clear them. */
8746 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8747 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8748 bar = XSCROLL_BAR (bar)->next)
8749 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8750 0, 0, 0, 0, True);
06a2c219 8751#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8752}
8753
06a2c219 8754/* This processes Expose events from the menu-bar specific X event
19126e11 8755 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8756 when handling menu-bar or pop-up items. */
3afe33e7 8757
06a2c219 8758int
3afe33e7
RS
8759process_expose_from_menu (event)
8760 XEvent event;
8761{
8762 FRAME_PTR f;
19126e11 8763 struct x_display_info *dpyinfo;
06a2c219 8764 int frame_exposed_p = 0;
3afe33e7 8765
f94397b5
KH
8766 BLOCK_INPUT;
8767
19126e11
KH
8768 dpyinfo = x_display_info_for_display (event.xexpose.display);
8769 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8770 if (f)
8771 {
8772 if (f->async_visible == 0)
8773 {
8774 f->async_visible = 1;
8775 f->async_iconified = 0;
06c488fd 8776 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8777 SET_FRAME_GARBAGED (f);
8778 }
8779 else
8780 {
06a2c219
GM
8781 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8782 event.xexpose.x, event.xexpose.y,
8783 event.xexpose.width, event.xexpose.height);
8784 frame_exposed_p = 1;
3afe33e7
RS
8785 }
8786 }
8787 else
8788 {
8789 struct scroll_bar *bar
8790 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8791
3afe33e7
RS
8792 if (bar)
8793 x_scroll_bar_expose (bar, &event);
8794 }
f94397b5
KH
8795
8796 UNBLOCK_INPUT;
06a2c219 8797 return frame_exposed_p;
3afe33e7 8798}
09756a85
RS
8799\f
8800/* Define a queue to save up SelectionRequest events for later handling. */
8801
8802struct selection_event_queue
8803 {
8804 XEvent event;
8805 struct selection_event_queue *next;
8806 };
8807
8808static struct selection_event_queue *queue;
8809
8810/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8811
09756a85
RS
8812static int x_queue_selection_requests;
8813
8814/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8815
09756a85 8816static void
334208b7
RS
8817x_queue_event (f, event)
8818 FRAME_PTR f;
09756a85
RS
8819 XEvent *event;
8820{
8821 struct selection_event_queue *queue_tmp
06a2c219 8822 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8823
58769bee 8824 if (queue_tmp != NULL)
09756a85
RS
8825 {
8826 queue_tmp->event = *event;
8827 queue_tmp->next = queue;
8828 queue = queue_tmp;
8829 }
8830}
8831
8832/* Take all the queued events and put them back
8833 so that they get processed afresh. */
8834
8835static void
db3906fd
RS
8836x_unqueue_events (display)
8837 Display *display;
09756a85 8838{
58769bee 8839 while (queue != NULL)
09756a85
RS
8840 {
8841 struct selection_event_queue *queue_tmp = queue;
db3906fd 8842 XPutBackEvent (display, &queue_tmp->event);
09756a85 8843 queue = queue_tmp->next;
06a2c219 8844 xfree ((char *)queue_tmp);
09756a85
RS
8845 }
8846}
8847
8848/* Start queuing SelectionRequest events. */
8849
8850void
db3906fd
RS
8851x_start_queuing_selection_requests (display)
8852 Display *display;
09756a85
RS
8853{
8854 x_queue_selection_requests++;
8855}
8856
8857/* Stop queuing SelectionRequest events. */
8858
8859void
db3906fd
RS
8860x_stop_queuing_selection_requests (display)
8861 Display *display;
09756a85
RS
8862{
8863 x_queue_selection_requests--;
db3906fd 8864 x_unqueue_events (display);
09756a85 8865}
f451eb13
JB
8866\f
8867/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8868
06a2c219 8869/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8870 but we have to put it out here, since static variables within functions
8871 sometimes don't work. */
06a2c219 8872
dc6f92b8
JB
8873static Time enter_timestamp;
8874
11edeb03 8875/* This holds the state XLookupString needs to implement dead keys
58769bee 8876 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8877 says that a portable program can't use this, but Stephen Gildea assures
8878 me that letting the compiler initialize it to zeros will work okay.
8879
8880 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8881 given for enter_time stamp, above. */
8882
11edeb03
JB
8883static XComposeStatus compose_status;
8884
10e6549c
RS
8885/* Record the last 100 characters stored
8886 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8887
2224b905
RS
8888static int temp_index;
8889static short temp_buffer[100];
10e6549c 8890
7a13e894
RS
8891/* Set this to nonzero to fake an "X I/O error"
8892 on a particular display. */
06a2c219 8893
7a13e894
RS
8894struct x_display_info *XTread_socket_fake_io_error;
8895
2224b905
RS
8896/* When we find no input here, we occasionally do a no-op command
8897 to verify that the X server is still running and we can still talk with it.
8898 We try all the open displays, one by one.
8899 This variable is used for cycling thru the displays. */
06a2c219 8900
2224b905
RS
8901static struct x_display_info *next_noop_dpyinfo;
8902
06a2c219
GM
8903#define SET_SAVED_MENU_EVENT(size) \
8904 do \
8905 { \
8906 if (f->output_data.x->saved_menu_event == 0) \
8907 f->output_data.x->saved_menu_event \
8908 = (XEvent *) xmalloc (sizeof (XEvent)); \
8909 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8910 if (numchars >= 1) \
8911 { \
8912 bufp->kind = menu_bar_activate_event; \
8913 XSETFRAME (bufp->frame_or_window, f); \
8914 bufp++; \
8915 count++; \
8916 numchars--; \
8917 } \
8918 } \
8919 while (0)
8920
8805890a 8921#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 8922#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 8923
dc6f92b8
JB
8924/* Read events coming from the X server.
8925 This routine is called by the SIGIO handler.
8926 We return as soon as there are no more events to be read.
8927
8928 Events representing keys are stored in buffer BUFP,
8929 which can hold up to NUMCHARS characters.
8930 We return the number of characters stored into the buffer,
8931 thus pretending to be `read'.
8932
dc6f92b8
JB
8933 EXPECTED is nonzero if the caller knows input is available. */
8934
7c5283e4 8935int
f66868ba 8936XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 8937 register int sd;
8805890a
KH
8938 /* register */ struct input_event *bufp;
8939 /* register */ int numchars;
dc6f92b8
JB
8940 int expected;
8941{
8942 int count = 0;
8943 int nbytes = 0;
dc6f92b8 8944 XEvent event;
f676886a 8945 struct frame *f;
66f55a9d 8946 int event_found = 0;
334208b7 8947 struct x_display_info *dpyinfo;
dc6f92b8 8948
9ac0d9e0 8949 if (interrupt_input_blocked)
dc6f92b8 8950 {
9ac0d9e0 8951 interrupt_input_pending = 1;
dc6f92b8
JB
8952 return -1;
8953 }
8954
9ac0d9e0 8955 interrupt_input_pending = 0;
dc6f92b8 8956 BLOCK_INPUT;
c0a04927
RS
8957
8958 /* So people can tell when we have read the available input. */
8959 input_signal_count++;
8960
dc6f92b8 8961 if (numchars <= 0)
06a2c219 8962 abort (); /* Don't think this happens. */
dc6f92b8 8963
bde5503b
GM
8964 ++handling_signal;
8965
7a13e894
RS
8966 /* Find the display we are supposed to read input for.
8967 It's the one communicating on descriptor SD. */
8968 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8969 {
8970#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 8971#ifdef FIOSNBIO
7a13e894
RS
8972 /* If available, Xlib uses FIOSNBIO to make the socket
8973 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 8974 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 8975 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 8976 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 8977#endif /* ! defined (FIOSNBIO) */
7a13e894 8978#endif
dc6f92b8 8979
7a13e894
RS
8980#if 0 /* This code can't be made to work, with multiple displays,
8981 and appears not to be used on any system any more.
8982 Also keyboard.c doesn't turn O_NDELAY on and off
8983 for X connections. */
dc6f92b8
JB
8984#ifndef SIGIO
8985#ifndef HAVE_SELECT
7a13e894
RS
8986 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8987 {
8988 extern int read_alarm_should_throw;
8989 read_alarm_should_throw = 1;
8990 XPeekEvent (dpyinfo->display, &event);
8991 read_alarm_should_throw = 0;
8992 }
c118dd06
JB
8993#endif /* HAVE_SELECT */
8994#endif /* SIGIO */
7a13e894 8995#endif
dc6f92b8 8996
7a13e894
RS
8997 /* For debugging, this gives a way to fake an I/O error. */
8998 if (dpyinfo == XTread_socket_fake_io_error)
8999 {
9000 XTread_socket_fake_io_error = 0;
9001 x_io_error_quitter (dpyinfo->display);
9002 }
dc6f92b8 9003
06a2c219 9004 while (XPending (dpyinfo->display))
dc6f92b8 9005 {
7a13e894 9006 XNextEvent (dpyinfo->display, &event);
06a2c219 9007
531483fb 9008#ifdef HAVE_X_I18N
d1bc4182 9009 {
f2be1146
GM
9010 /* Filter events for the current X input method.
9011 XFilterEvent returns non-zero if the input method has
9012 consumed the event. We pass the frame's X window to
9013 XFilterEvent because that's the one for which the IC
9014 was created. */
f5d11644
GM
9015 struct frame *f1 = x_any_window_to_frame (dpyinfo,
9016 event.xclient.window);
9017 if (XFilterEvent (&event, f1 ? FRAME_X_WINDOW (f1) : None))
d1bc4182
RS
9018 break;
9019 }
0cd6403b 9020#endif
7a13e894
RS
9021 event_found = 1;
9022
9023 switch (event.type)
9024 {
9025 case ClientMessage:
c047688c 9026 {
7a13e894
RS
9027 if (event.xclient.message_type
9028 == dpyinfo->Xatom_wm_protocols
9029 && event.xclient.format == 32)
c047688c 9030 {
7a13e894
RS
9031 if (event.xclient.data.l[0]
9032 == dpyinfo->Xatom_wm_take_focus)
c047688c 9033 {
8c1a6a84
RS
9034 /* Use x_any_window_to_frame because this
9035 could be the shell widget window
9036 if the frame has no title bar. */
9037 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
9038#ifdef HAVE_X_I18N
9039 /* Not quite sure this is needed -pd */
8c1a6a84 9040 if (f && FRAME_XIC (f))
6c183ba5
RS
9041 XSetICFocus (FRAME_XIC (f));
9042#endif
f1da8f06
GM
9043#if 0 /* Emacs sets WM hints whose `input' field is `true'. This
9044 instructs the WM to set the input focus automatically for
9045 Emacs with a call to XSetInputFocus. Setting WM_TAKE_FOCUS
9046 tells the WM to send us a ClientMessage WM_TAKE_FOCUS after
9047 it has set the focus. So, XSetInputFocus below is not
9048 needed.
9049
9050 The call to XSetInputFocus below has also caused trouble. In
9051 cases where the XSetInputFocus done by the WM and the one
9052 below are temporally close (on a fast machine), the call
9053 below can generate additional FocusIn events which confuse
9054 Emacs. */
9055
bf7253f4
RS
9056 /* Since we set WM_TAKE_FOCUS, we must call
9057 XSetInputFocus explicitly. But not if f is null,
9058 since that might be an event for a deleted frame. */
7a13e894 9059 if (f)
bf7253f4
RS
9060 {
9061 Display *d = event.xclient.display;
9062 /* Catch and ignore errors, in case window has been
9063 iconified by a window manager such as GWM. */
9064 int count = x_catch_errors (d);
9065 XSetInputFocus (d, event.xclient.window,
e1f6572f
RS
9066 /* The ICCCM says this is
9067 the only valid choice. */
9068 RevertToParent,
bf7253f4
RS
9069 event.xclient.data.l[1]);
9070 /* This is needed to detect the error
9071 if there is an error. */
9072 XSync (d, False);
9073 x_uncatch_errors (d, count);
9074 }
7a13e894 9075 /* Not certain about handling scroll bars here */
f1da8f06 9076#endif /* 0 */
c047688c 9077 }
7a13e894
RS
9078 else if (event.xclient.data.l[0]
9079 == dpyinfo->Xatom_wm_save_yourself)
9080 {
9081 /* Save state modify the WM_COMMAND property to
06a2c219 9082 something which can reinstate us. This notifies
7a13e894
RS
9083 the session manager, who's looking for such a
9084 PropertyNotify. Can restart processing when
06a2c219 9085 a keyboard or mouse event arrives. */
7a13e894
RS
9086 if (numchars > 0)
9087 {
19126e11
KH
9088 f = x_top_window_to_frame (dpyinfo,
9089 event.xclient.window);
7a13e894
RS
9090
9091 /* This is just so we only give real data once
9092 for a single Emacs process. */
b86bd3dd 9093 if (f == SELECTED_FRAME ())
7a13e894
RS
9094 XSetCommand (FRAME_X_DISPLAY (f),
9095 event.xclient.window,
9096 initial_argv, initial_argc);
f000f5c5 9097 else if (f)
7a13e894
RS
9098 XSetCommand (FRAME_X_DISPLAY (f),
9099 event.xclient.window,
9100 0, 0);
9101 }
9102 }
9103 else if (event.xclient.data.l[0]
9104 == dpyinfo->Xatom_wm_delete_window)
1fb20991 9105 {
19126e11
KH
9106 struct frame *f
9107 = x_any_window_to_frame (dpyinfo,
9108 event.xclient.window);
1fb20991 9109
7a13e894
RS
9110 if (f)
9111 {
9112 if (numchars == 0)
9113 abort ();
1fb20991 9114
7a13e894
RS
9115 bufp->kind = delete_window_event;
9116 XSETFRAME (bufp->frame_or_window, f);
9117 bufp++;
9118
9119 count += 1;
9120 numchars -= 1;
9121 }
1fb20991 9122 }
c047688c 9123 }
7a13e894
RS
9124 else if (event.xclient.message_type
9125 == dpyinfo->Xatom_wm_configure_denied)
9126 {
9127 }
9128 else if (event.xclient.message_type
9129 == dpyinfo->Xatom_wm_window_moved)
9130 {
9131 int new_x, new_y;
19126e11
KH
9132 struct frame *f
9133 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 9134
7a13e894
RS
9135 new_x = event.xclient.data.s[0];
9136 new_y = event.xclient.data.s[1];
1fb20991 9137
7a13e894
RS
9138 if (f)
9139 {
7556890b
RS
9140 f->output_data.x->left_pos = new_x;
9141 f->output_data.x->top_pos = new_y;
7a13e894 9142 }
1fb20991 9143 }
0fdff6bb 9144#ifdef HACK_EDITRES
7a13e894
RS
9145 else if (event.xclient.message_type
9146 == dpyinfo->Xatom_editres)
9147 {
19126e11
KH
9148 struct frame *f
9149 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 9150 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 9151 &event, NULL);
7a13e894 9152 }
0fdff6bb 9153#endif /* HACK_EDITRES */
06a2c219
GM
9154 else if ((event.xclient.message_type
9155 == dpyinfo->Xatom_DONE)
9156 || (event.xclient.message_type
9157 == dpyinfo->Xatom_PAGE))
9158 {
9159 /* Ghostview job completed. Kill it. We could
9160 reply with "Next" if we received "Page", but we
9161 currently never do because we are interested in
9162 images, only, which should have 1 page. */
06a2c219
GM
9163 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
9164 struct frame *f
9165 = x_window_to_frame (dpyinfo, event.xclient.window);
9166 x_kill_gs_process (pixmap, f);
9167 expose_frame (f, 0, 0, 0, 0);
9168 }
9169#ifdef USE_TOOLKIT_SCROLL_BARS
9170 /* Scroll bar callbacks send a ClientMessage from which
9171 we construct an input_event. */
9172 else if (event.xclient.message_type
9173 == dpyinfo->Xatom_Scrollbar)
9174 {
9175 x_scroll_bar_to_input_event (&event, bufp);
9176 ++bufp, ++count, --numchars;
9177 goto out;
9178 }
9179#endif /* USE_TOOLKIT_SCROLL_BARS */
9180 else
9181 goto OTHER;
7a13e894
RS
9182 }
9183 break;
dc6f92b8 9184
7a13e894 9185 case SelectionNotify:
3afe33e7 9186#ifdef USE_X_TOOLKIT
19126e11 9187 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 9188 goto OTHER;
3afe33e7 9189#endif /* not USE_X_TOOLKIT */
dfcf069d 9190 x_handle_selection_notify (&event.xselection);
7a13e894 9191 break;
d56a553a 9192
06a2c219 9193 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 9194#ifdef USE_X_TOOLKIT
19126e11 9195 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 9196 goto OTHER;
3afe33e7 9197#endif /* USE_X_TOOLKIT */
7a13e894
RS
9198 {
9199 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 9200
7a13e894
RS
9201 if (numchars == 0)
9202 abort ();
d56a553a 9203
7a13e894
RS
9204 bufp->kind = selection_clear_event;
9205 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9206 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9207 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9208 bufp->frame_or_window = Qnil;
7a13e894 9209 bufp++;
d56a553a 9210
7a13e894
RS
9211 count += 1;
9212 numchars -= 1;
9213 }
9214 break;
dc6f92b8 9215
06a2c219 9216 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 9217#ifdef USE_X_TOOLKIT
19126e11 9218 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 9219 goto OTHER;
3afe33e7 9220#endif /* USE_X_TOOLKIT */
7a13e894 9221 if (x_queue_selection_requests)
19126e11 9222 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
9223 &event);
9224 else
9225 {
9226 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 9227
7a13e894
RS
9228 if (numchars == 0)
9229 abort ();
9230
9231 bufp->kind = selection_request_event;
9232 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
9233 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
9234 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
9235 SELECTION_EVENT_TARGET (bufp) = eventp->target;
9236 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
9237 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 9238 bufp->frame_or_window = Qnil;
7a13e894
RS
9239 bufp++;
9240
9241 count += 1;
9242 numchars -= 1;
9243 }
9244 break;
9245
9246 case PropertyNotify:
3afe33e7 9247#ifdef USE_X_TOOLKIT
19126e11 9248 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 9249 goto OTHER;
3afe33e7 9250#endif /* not USE_X_TOOLKIT */
dfcf069d 9251 x_handle_property_notify (&event.xproperty);
7a13e894 9252 break;
dc6f92b8 9253
7a13e894 9254 case ReparentNotify:
19126e11 9255 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
9256 if (f)
9257 {
9258 int x, y;
7556890b 9259 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 9260 x_real_positions (f, &x, &y);
7556890b
RS
9261 f->output_data.x->left_pos = x;
9262 f->output_data.x->top_pos = y;
7a13e894
RS
9263 }
9264 break;
3bd330d4 9265
7a13e894 9266 case Expose:
19126e11 9267 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 9268 if (f)
dc6f92b8 9269 {
7a13e894
RS
9270 if (f->async_visible == 0)
9271 {
9272 f->async_visible = 1;
9273 f->async_iconified = 0;
06c488fd 9274 f->output_data.x->has_been_visible = 1;
7a13e894
RS
9275 SET_FRAME_GARBAGED (f);
9276 }
9277 else
06a2c219
GM
9278 expose_frame (x_window_to_frame (dpyinfo,
9279 event.xexpose.window),
9280 event.xexpose.x, event.xexpose.y,
9281 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
9282 }
9283 else
7a13e894 9284 {
06a2c219
GM
9285#ifdef USE_TOOLKIT_SCROLL_BARS
9286 /* Dispatch event to the widget. */
9287 goto OTHER;
9288#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9289 struct scroll_bar *bar
9290 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 9291
7a13e894
RS
9292 if (bar)
9293 x_scroll_bar_expose (bar, &event);
3afe33e7 9294#ifdef USE_X_TOOLKIT
7a13e894
RS
9295 else
9296 goto OTHER;
3afe33e7 9297#endif /* USE_X_TOOLKIT */
06a2c219 9298#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9299 }
9300 break;
dc6f92b8 9301
7a13e894
RS
9302 case GraphicsExpose: /* This occurs when an XCopyArea's
9303 source area was obscured or not
9304 available.*/
19126e11 9305 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
9306 if (f)
9307 {
06a2c219
GM
9308 expose_frame (f,
9309 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
9310 event.xgraphicsexpose.width,
9311 event.xgraphicsexpose.height);
7a13e894 9312 }
3afe33e7 9313#ifdef USE_X_TOOLKIT
7a13e894
RS
9314 else
9315 goto OTHER;
3afe33e7 9316#endif /* USE_X_TOOLKIT */
7a13e894 9317 break;
dc6f92b8 9318
7a13e894 9319 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
9320 source area was completely
9321 available */
7a13e894 9322 break;
dc6f92b8 9323
7a13e894 9324 case UnmapNotify:
06a2c219
GM
9325 /* Redo the mouse-highlight after the tooltip has gone. */
9326 if (event.xmap.window == tip_window)
9327 {
9328 tip_window = 0;
9329 redo_mouse_highlight ();
9330 }
9331
91ea2a7a 9332 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
9333 if (f) /* F may no longer exist if
9334 the frame was deleted. */
9335 {
9336 /* While a frame is unmapped, display generation is
9337 disabled; you don't want to spend time updating a
9338 display that won't ever be seen. */
9339 f->async_visible = 0;
9340 /* We can't distinguish, from the event, whether the window
9341 has become iconified or invisible. So assume, if it
9342 was previously visible, than now it is iconified.
1aa6072f
RS
9343 But x_make_frame_invisible clears both
9344 the visible flag and the iconified flag;
9345 and that way, we know the window is not iconified now. */
7a13e894 9346 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
9347 {
9348 f->async_iconified = 1;
bddd097c 9349
1aa6072f
RS
9350 bufp->kind = iconify_event;
9351 XSETFRAME (bufp->frame_or_window, f);
9352 bufp++;
9353 count++;
9354 numchars--;
9355 }
7a13e894 9356 }
7a13e894 9357 goto OTHER;
dc6f92b8 9358
7a13e894 9359 case MapNotify:
06a2c219
GM
9360 if (event.xmap.window == tip_window)
9361 /* The tooltip has been drawn already. Avoid
9362 the SET_FRAME_GARBAGED below. */
9363 goto OTHER;
9364
9365 /* We use x_top_window_to_frame because map events can
9366 come for sub-windows and they don't mean that the
9367 frame is visible. */
19126e11 9368 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
9369 if (f)
9370 {
9371 f->async_visible = 1;
9372 f->async_iconified = 0;
06c488fd 9373 f->output_data.x->has_been_visible = 1;
dc6f92b8 9374
7a13e894
RS
9375 /* wait_reading_process_input will notice this and update
9376 the frame's display structures. */
9377 SET_FRAME_GARBAGED (f);
bddd097c 9378
d806e720
RS
9379 if (f->iconified)
9380 {
9381 bufp->kind = deiconify_event;
9382 XSETFRAME (bufp->frame_or_window, f);
9383 bufp++;
9384 count++;
9385 numchars--;
9386 }
e73ec6fa 9387 else if (! NILP (Vframe_list)
8e713be6 9388 && ! NILP (XCDR (Vframe_list)))
78aa2ba5
KH
9389 /* Force a redisplay sooner or later
9390 to update the frame titles
9391 in case this is the second frame. */
9392 record_asynch_buffer_change ();
7a13e894 9393 }
7a13e894 9394 goto OTHER;
dc6f92b8 9395
7a13e894 9396 case KeyPress:
19126e11 9397 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 9398
06a2c219
GM
9399#ifdef USE_MOTIF
9400 /* I couldn't find a way to prevent LessTif scroll bars
9401 from consuming key events. */
9402 if (f == 0)
9403 {
9404 Widget widget = XtWindowToWidget (dpyinfo->display,
9405 event.xkey.window);
9406 if (widget && XmIsScrollBar (widget))
9407 {
9408 widget = XtParent (widget);
9409 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
9410 }
9411 }
9412#endif /* USE_MOTIF */
9413
7a13e894
RS
9414 if (f != 0)
9415 {
9416 KeySym keysym, orig_keysym;
9417 /* al%imercury@uunet.uu.net says that making this 81 instead of
9418 80 fixed a bug whereby meta chars made his Emacs hang. */
9419 unsigned char copy_buffer[81];
9420 int modifiers;
64bb1782 9421
7a13e894
RS
9422 event.xkey.state
9423 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
9424 extra_keyboard_modifiers);
9425 modifiers = event.xkey.state;
3a2712f9 9426
7a13e894 9427 /* This will have to go some day... */
752a043f 9428
7a13e894
RS
9429 /* make_lispy_event turns chars into control chars.
9430 Don't do it here because XLookupString is too eager. */
9431 event.xkey.state &= ~ControlMask;
5d46f928
RS
9432 event.xkey.state &= ~(dpyinfo->meta_mod_mask
9433 | dpyinfo->super_mod_mask
9434 | dpyinfo->hyper_mod_mask
9435 | dpyinfo->alt_mod_mask);
9436
1cf4a0d1
RS
9437 /* In case Meta is ComposeCharacter,
9438 clear its status. According to Markus Ehrnsperger
9439 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
9440 this enables ComposeCharacter to work whether or
9441 not it is combined with Meta. */
9442 if (modifiers & dpyinfo->meta_mod_mask)
9443 bzero (&compose_status, sizeof (compose_status));
9444
6c183ba5
RS
9445#ifdef HAVE_X_I18N
9446 if (FRAME_XIC (f))
9447 {
f5d11644
GM
9448 unsigned char *copy_bufptr = copy_buffer;
9449 int copy_bufsiz = sizeof (copy_buffer);
9450 Status status_return;
9451
6c183ba5 9452 nbytes = XmbLookupString (FRAME_XIC (f),
f5d11644
GM
9453 &event.xkey, copy_bufptr,
9454 copy_bufsiz, &keysym,
6c183ba5 9455 &status_return);
f5d11644
GM
9456 if (status_return == XBufferOverflow)
9457 {
9458 copy_bufsiz = nbytes + 1;
9459 copy_bufptr = (char *) alloca (copy_bufsiz);
9460 nbytes = XmbLookupString (FRAME_XIC (f),
9461 &event.xkey, copy_bufptr,
9462 copy_bufsiz, &keysym,
9463 &status_return);
9464 }
9465
1decb680
PE
9466 if (status_return == XLookupNone)
9467 break;
9468 else if (status_return == XLookupChars)
fdd9d55e
GM
9469 {
9470 keysym = NoSymbol;
9471 modifiers = 0;
9472 }
1decb680
PE
9473 else if (status_return != XLookupKeySym
9474 && status_return != XLookupBoth)
9475 abort ();
6c183ba5
RS
9476 }
9477 else
9478 nbytes = XLookupString (&event.xkey, copy_buffer,
9479 80, &keysym, &compose_status);
9480#else
0299d313
RS
9481 nbytes = XLookupString (&event.xkey, copy_buffer,
9482 80, &keysym, &compose_status);
6c183ba5 9483#endif
dc6f92b8 9484
7a13e894 9485 orig_keysym = keysym;
55123275 9486
7a13e894
RS
9487 if (numchars > 1)
9488 {
9489 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
9490 || keysym == XK_Delete
1097aea0 9491#ifdef XK_ISO_Left_Tab
441affdb 9492 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 9493#endif
852bff8f 9494 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
9495 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9496 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9497#ifdef HPUX
7a13e894
RS
9498 /* This recognizes the "extended function keys".
9499 It seems there's no cleaner way.
9500 Test IsModifierKey to avoid handling mode_switch
9501 incorrectly. */
9502 || ((unsigned) (keysym) >= XK_Select
9503 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9504#endif
9505#ifdef XK_dead_circumflex
7a13e894 9506 || orig_keysym == XK_dead_circumflex
69388238
RS
9507#endif
9508#ifdef XK_dead_grave
7a13e894 9509 || orig_keysym == XK_dead_grave
69388238
RS
9510#endif
9511#ifdef XK_dead_tilde
7a13e894 9512 || orig_keysym == XK_dead_tilde
69388238
RS
9513#endif
9514#ifdef XK_dead_diaeresis
7a13e894 9515 || orig_keysym == XK_dead_diaeresis
69388238
RS
9516#endif
9517#ifdef XK_dead_macron
7a13e894 9518 || orig_keysym == XK_dead_macron
69388238
RS
9519#endif
9520#ifdef XK_dead_degree
7a13e894 9521 || orig_keysym == XK_dead_degree
69388238
RS
9522#endif
9523#ifdef XK_dead_acute
7a13e894 9524 || orig_keysym == XK_dead_acute
69388238
RS
9525#endif
9526#ifdef XK_dead_cedilla
7a13e894 9527 || orig_keysym == XK_dead_cedilla
69388238
RS
9528#endif
9529#ifdef XK_dead_breve
7a13e894 9530 || orig_keysym == XK_dead_breve
69388238
RS
9531#endif
9532#ifdef XK_dead_ogonek
7a13e894 9533 || orig_keysym == XK_dead_ogonek
69388238
RS
9534#endif
9535#ifdef XK_dead_caron
7a13e894 9536 || orig_keysym == XK_dead_caron
69388238
RS
9537#endif
9538#ifdef XK_dead_doubleacute
7a13e894 9539 || orig_keysym == XK_dead_doubleacute
69388238
RS
9540#endif
9541#ifdef XK_dead_abovedot
7a13e894 9542 || orig_keysym == XK_dead_abovedot
c34790e0 9543#endif
7a13e894
RS
9544 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9545 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9546 /* Any "vendor-specific" key is ok. */
9547 || (orig_keysym & (1 << 28)))
9548 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9549#ifndef HAVE_X11R5
9550#ifdef XK_Mode_switch
7a13e894 9551 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9552#endif
9553#ifdef XK_Num_Lock
7a13e894 9554 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9555#endif
9556#endif /* not HAVE_X11R5 */
7a13e894 9557 ))
dc6f92b8 9558 {
10e6549c
RS
9559 if (temp_index == sizeof temp_buffer / sizeof (short))
9560 temp_index = 0;
7a13e894
RS
9561 temp_buffer[temp_index++] = keysym;
9562 bufp->kind = non_ascii_keystroke;
9563 bufp->code = keysym;
e0c1aef2 9564 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
9565 bufp->modifiers
9566 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9567 modifiers);
1113d9db 9568 bufp->timestamp = event.xkey.time;
dc6f92b8 9569 bufp++;
7a13e894
RS
9570 count++;
9571 numchars--;
dc6f92b8 9572 }
7a13e894
RS
9573 else if (numchars > nbytes)
9574 {
9575 register int i;
9576
9577 for (i = 0; i < nbytes; i++)
9578 {
9579 if (temp_index == sizeof temp_buffer / sizeof (short))
9580 temp_index = 0;
9581 temp_buffer[temp_index++] = copy_buffer[i];
9582 bufp->kind = ascii_keystroke;
9583 bufp->code = copy_buffer[i];
9584 XSETFRAME (bufp->frame_or_window, f);
9585 bufp->modifiers
9586 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9587 modifiers);
9588 bufp->timestamp = event.xkey.time;
9589 bufp++;
9590 }
9591
9592 count += nbytes;
9593 numchars -= nbytes;
1decb680
PE
9594
9595 if (keysym == NoSymbol)
9596 break;
7a13e894
RS
9597 }
9598 else
9599 abort ();
dc6f92b8 9600 }
10e6549c
RS
9601 else
9602 abort ();
dc6f92b8 9603 }
59ddecde
GM
9604#ifdef HAVE_X_I18N
9605 /* Don't dispatch this event since XtDispatchEvent calls
9606 XFilterEvent, and two calls in a row may freeze the
9607 client. */
9608 break;
9609#else
717ca130 9610 goto OTHER;
59ddecde 9611#endif
f451eb13 9612
f5d11644 9613 case KeyRelease:
59ddecde
GM
9614#ifdef HAVE_X_I18N
9615 /* Don't dispatch this event since XtDispatchEvent calls
9616 XFilterEvent, and two calls in a row may freeze the
9617 client. */
9618 break;
9619#else
f5d11644 9620 goto OTHER;
59ddecde 9621#endif
f5d11644 9622
7a13e894 9623 /* Here's a possible interpretation of the whole
06a2c219
GM
9624 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9625 you get a FocusIn event, you have to get a FocusOut
9626 event before you relinquish the focus. If you
9627 haven't received a FocusIn event, then a mere
9628 LeaveNotify is enough to free you. */
f451eb13 9629
7a13e894 9630 case EnterNotify:
06a2c219
GM
9631 {
9632 int from_menu_bar_p = 0;
9633
9634 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9635
9636#ifdef LESSTIF_VERSION
9637 /* When clicking outside of a menu bar popup to close
9638 it, we get a FocusIn/ EnterNotify sequence of
9639 events. The flag event.xcrossing.focus is not set
9640 in the EnterNotify event of that sequence because
9641 the focus is in the menu bar,
9642 event.xcrossing.window is the frame's X window.
9643 Unconditionally setting the focus frame to null in
9644 this case is not the right thing, because no event
9645 follows that could set the focus frame to the right
9646 value.
9647
9648 This could be a LessTif bug, but I wasn't able to
9649 reproduce the behavior in a simple test program.
9650
9651 (gerd, LessTif 0.88.1). */
9652
9653 if (!event.xcrossing.focus
9654 && f
9655 && f->output_data.x->menubar_widget)
9656 {
9657 Window focus;
9658 int revert;
9659
9660 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9661 if (focus == XtWindow (f->output_data.x->menubar_widget))
9662 from_menu_bar_p = 1;
9663 }
9664#endif /* LESSTIF_VERSION */
6d4238f3 9665
06a2c219
GM
9666 if (event.xcrossing.focus || from_menu_bar_p)
9667 {
9668 /* Avoid nasty pop/raise loops. */
9669 if (f && (!(f->auto_raise)
9670 || !(f->auto_lower)
9671 || (event.xcrossing.time - enter_timestamp) > 500))
9672 {
9673 x_new_focus_frame (dpyinfo, f);
9674 enter_timestamp = event.xcrossing.time;
9675 }
9676 }
9677 else if (f == dpyinfo->x_focus_frame)
9678 x_new_focus_frame (dpyinfo, 0);
9679
9680 /* EnterNotify counts as mouse movement,
9681 so update things that depend on mouse position. */
9682 if (f && !f->output_data.x->busy_p)
9683 note_mouse_movement (f, &event.xmotion);
9684 goto OTHER;
9685 }
dc6f92b8 9686
7a13e894 9687 case FocusIn:
19126e11 9688 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9689 if (event.xfocus.detail != NotifyPointer)
0f941935 9690 dpyinfo->x_focus_event_frame = f;
7a13e894 9691 if (f)
eb72635f
GM
9692 {
9693 x_new_focus_frame (dpyinfo, f);
9694
9695 /* Don't stop displaying the initial startup message
9696 for a switch-frame event we don't need. */
9697 if (GC_NILP (Vterminal_frame)
9698 && GC_CONSP (Vframe_list)
9699 && !GC_NILP (XCDR (Vframe_list)))
9700 {
9701 bufp->kind = FOCUS_IN_EVENT;
9702 XSETFRAME (bufp->frame_or_window, f);
9703 ++bufp, ++count, --numchars;
9704 }
9705 }
f9e24cb9 9706
6c183ba5
RS
9707#ifdef HAVE_X_I18N
9708 if (f && FRAME_XIC (f))
9709 XSetICFocus (FRAME_XIC (f));
9710#endif
9711
7a13e894 9712 goto OTHER;
10c5e63d 9713
7a13e894 9714 case LeaveNotify:
19126e11 9715 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9716 if (f)
10c5e63d 9717 {
06a2c219
GM
9718 Lisp_Object frame;
9719 int from_menu_bar_p = 0;
9720
7a13e894 9721 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9722 {
9723 /* If we move outside the frame, then we're
9724 certainly no longer on any text in the frame. */
9725 clear_mouse_face (dpyinfo);
9726 dpyinfo->mouse_face_mouse_frame = 0;
9727 }
9728
9729 /* Generate a nil HELP_EVENT to cancel a help-echo.
9730 Do it only if there's something to cancel.
9731 Otherwise, the startup message is cleared when
9732 the mouse leaves the frame. */
9733 if (any_help_event_p)
9734 {
9735 XSETFRAME (frame, f);
9736 bufp->kind = HELP_EVENT;
9737 bufp->frame_or_window = Fcons (frame, Qnil);
9738 ++bufp, ++count, --numchars;
9739 }
7a13e894 9740
06a2c219
GM
9741#ifdef LESSTIF_VERSION
9742 /* Please see the comment at the start of the
9743 EnterNotify case. */
9744 if (!event.xcrossing.focus
9745 && f->output_data.x->menubar_widget)
9746 {
9747 Window focus;
9748 int revert;
9749 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9750 if (focus == XtWindow (f->output_data.x->menubar_widget))
9751 from_menu_bar_p = 1;
9752 }
9753#endif /* LESSTIF_VERSION */
9754
9755 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9756 x_mouse_leave (dpyinfo);
10c5e63d 9757 else
7a13e894 9758 {
0f941935
KH
9759 if (f == dpyinfo->x_focus_event_frame)
9760 dpyinfo->x_focus_event_frame = 0;
9761 if (f == dpyinfo->x_focus_frame)
9762 x_new_focus_frame (dpyinfo, 0);
7a13e894 9763 }
10c5e63d 9764 }
7a13e894 9765 goto OTHER;
dc6f92b8 9766
7a13e894 9767 case FocusOut:
19126e11 9768 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9769 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9770 && f == dpyinfo->x_focus_event_frame)
9771 dpyinfo->x_focus_event_frame = 0;
9772 if (f && f == dpyinfo->x_focus_frame)
9773 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9774
6c183ba5
RS
9775#ifdef HAVE_X_I18N
9776 if (f && FRAME_XIC (f))
9777 XUnsetICFocus (FRAME_XIC (f));
9778#endif
9779
7a13e894 9780 goto OTHER;
dc6f92b8 9781
7a13e894 9782 case MotionNotify:
dc6f92b8 9783 {
06a2c219
GM
9784 previous_help_echo = help_echo;
9785 help_echo = Qnil;
9786
7a13e894
RS
9787 if (dpyinfo->grabbed && last_mouse_frame
9788 && FRAME_LIVE_P (last_mouse_frame))
9789 f = last_mouse_frame;
9790 else
19126e11 9791 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9792
7a13e894
RS
9793 if (f)
9794 note_mouse_movement (f, &event.xmotion);
9795 else
9796 {
e88b3c50 9797#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9798 struct scroll_bar *bar
9799 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9800
7a13e894
RS
9801 if (bar)
9802 x_scroll_bar_note_movement (bar, &event);
e88b3c50 9803#endif /* USE_TOOLKIT_SCROLL_BARS */
b8009dd1 9804
06a2c219
GM
9805 /* If we move outside the frame, then we're
9806 certainly no longer on any text in the frame. */
7a13e894
RS
9807 clear_mouse_face (dpyinfo);
9808 }
06a2c219
GM
9809
9810 /* If the contents of the global variable help_echo
9811 has changed, generate a HELP_EVENT. */
b7e80413
SM
9812 if (!NILP (help_echo)
9813 || !NILP (previous_help_echo))
06a2c219
GM
9814 {
9815 Lisp_Object frame;
9816
9817 if (f)
9818 XSETFRAME (frame, f);
9819 else
9820 frame = Qnil;
9821
9822 any_help_event_p = 1;
9823 bufp->kind = HELP_EVENT;
9824 bufp->frame_or_window = Fcons (frame, help_echo);
9825 ++bufp, ++count, --numchars;
9826 }
9827
9828 goto OTHER;
dc6f92b8 9829 }
dc6f92b8 9830
7a13e894 9831 case ConfigureNotify:
9829ddba
RS
9832 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9833 if (f)
af395ec1 9834 {
5c187dee 9835#ifndef USE_X_TOOLKIT
bf1b7b30
KH
9836 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9837 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
5c187dee 9838
2d7fc7e8
RS
9839 /* In the toolkit version, change_frame_size
9840 is called by the code that handles resizing
9841 of the EmacsFrame widget. */
7a13e894 9842
7a13e894
RS
9843 /* Even if the number of character rows and columns has
9844 not changed, the font size may have changed, so we need
9845 to check the pixel dimensions as well. */
9846 if (columns != f->width
9847 || rows != f->height
7556890b
RS
9848 || event.xconfigure.width != f->output_data.x->pixel_width
9849 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894 9850 {
7d1e984f 9851 change_frame_size (f, rows, columns, 0, 1, 0);
7a13e894 9852 SET_FRAME_GARBAGED (f);
e687d06e 9853 cancel_mouse_face (f);
7a13e894 9854 }
2d7fc7e8 9855#endif
af395ec1 9856
7556890b
RS
9857 f->output_data.x->pixel_width = event.xconfigure.width;
9858 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
9859
9860 /* What we have now is the position of Emacs's own window.
9861 Convert that to the position of the window manager window. */
dcb07ae9
RS
9862 x_real_positions (f, &f->output_data.x->left_pos,
9863 &f->output_data.x->top_pos);
9864
f5d11644
GM
9865#ifdef HAVE_X_I18N
9866 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
9867 xic_set_statusarea (f);
9868#endif
9869
dcb07ae9
RS
9870 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9871 {
9872 /* Since the WM decorations come below top_pos now,
9873 we must put them below top_pos in the future. */
9874 f->output_data.x->win_gravity = NorthWestGravity;
9875 x_wm_set_size_hint (f, (long) 0, 0);
9876 }
8f08dc93
KH
9877#ifdef USE_MOTIF
9878 /* Some window managers pass (0,0) as the location of
9879 the window, and the Motif event handler stores it
9880 in the emacs widget, which messes up Motif menus. */
9881 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9882 {
9883 event.xconfigure.x = f->output_data.x->widget->core.x;
9884 event.xconfigure.y = f->output_data.x->widget->core.y;
9885 }
06a2c219 9886#endif /* USE_MOTIF */
7a13e894 9887 }
2d7fc7e8 9888 goto OTHER;
dc6f92b8 9889
7a13e894
RS
9890 case ButtonPress:
9891 case ButtonRelease:
9892 {
9893 /* If we decide we want to generate an event to be seen
9894 by the rest of Emacs, we put it here. */
9895 struct input_event emacs_event;
9ea173e8 9896 int tool_bar_p = 0;
06a2c219 9897
7a13e894 9898 emacs_event.kind = no_event;
7a13e894 9899 bzero (&compose_status, sizeof (compose_status));
9b07615b 9900
06a2c219
GM
9901 if (dpyinfo->grabbed
9902 && last_mouse_frame
9f67f20b
RS
9903 && FRAME_LIVE_P (last_mouse_frame))
9904 f = last_mouse_frame;
9905 else
2224b905 9906 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 9907
06a2c219
GM
9908 if (f)
9909 {
9ea173e8
GM
9910 /* Is this in the tool-bar? */
9911 if (WINDOWP (f->tool_bar_window)
9912 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
06a2c219
GM
9913 {
9914 Lisp_Object window;
9915 int p, x, y;
9916
9917 x = event.xbutton.x;
9918 y = event.xbutton.y;
9919
9920 /* Set x and y. */
9921 window = window_from_coordinates (f, x, y, &p, 1);
9ea173e8 9922 if (EQ (window, f->tool_bar_window))
06a2c219 9923 {
9ea173e8
GM
9924 x_handle_tool_bar_click (f, &event.xbutton);
9925 tool_bar_p = 1;
06a2c219
GM
9926 }
9927 }
9928
9ea173e8 9929 if (!tool_bar_p)
06a2c219
GM
9930 if (!dpyinfo->x_focus_frame
9931 || f == dpyinfo->x_focus_frame)
9932 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
9933 }
9934 else
9935 {
06a2c219 9936#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9937 struct scroll_bar *bar
9938 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 9939
7a13e894
RS
9940 if (bar)
9941 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 9942#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9943 }
9944
9945 if (event.type == ButtonPress)
9946 {
9947 dpyinfo->grabbed |= (1 << event.xbutton.button);
9948 last_mouse_frame = f;
edad46f6
KH
9949 /* Ignore any mouse motion that happened
9950 before this event; any subsequent mouse-movement
9951 Emacs events should reflect only motion after
9952 the ButtonPress. */
a00e91cd
KH
9953 if (f != 0)
9954 f->mouse_moved = 0;
06a2c219 9955
9ea173e8
GM
9956 if (!tool_bar_p)
9957 last_tool_bar_item = -1;
7a13e894 9958 }
3afe33e7
RS
9959 else
9960 {
7a13e894 9961 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 9962 }
23faf38f 9963
7a13e894
RS
9964 if (numchars >= 1 && emacs_event.kind != no_event)
9965 {
9966 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9967 bufp++;
9968 count++;
9969 numchars--;
9970 }
3afe33e7
RS
9971
9972#ifdef USE_X_TOOLKIT
2224b905
RS
9973 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9974 /* For a down-event in the menu bar,
9975 don't pass it to Xt right now.
9976 Instead, save it away
9977 and we will pass it to Xt from kbd_buffer_get_event.
9978 That way, we can run some Lisp code first. */
91375f8f
RS
9979 if (f && event.type == ButtonPress
9980 /* Verify the event is really within the menu bar
9981 and not just sent to it due to grabbing. */
9982 && event.xbutton.x >= 0
9983 && event.xbutton.x < f->output_data.x->pixel_width
9984 && event.xbutton.y >= 0
9985 && event.xbutton.y < f->output_data.x->menubar_height
9986 && event.xbutton.same_screen)
2224b905 9987 {
8805890a 9988 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
9989 XSETFRAME (last_mouse_press_frame, f);
9990 }
9991 else if (event.type == ButtonPress)
9992 {
9993 last_mouse_press_frame = Qnil;
30e671c3 9994 goto OTHER;
ce89ef46 9995 }
06a2c219 9996
2237cac9
RS
9997#ifdef USE_MOTIF /* This should do not harm for Lucid,
9998 but I am trying to be cautious. */
ce89ef46
RS
9999 else if (event.type == ButtonRelease)
10000 {
2237cac9 10001 if (!NILP (last_mouse_press_frame))
f10ded1c 10002 {
2237cac9
RS
10003 f = XFRAME (last_mouse_press_frame);
10004 if (f->output_data.x)
06a2c219 10005 SET_SAVED_BUTTON_EVENT;
f10ded1c 10006 }
06a2c219 10007 else
30e671c3 10008 goto OTHER;
2224b905 10009 }
2237cac9 10010#endif /* USE_MOTIF */
2224b905
RS
10011 else
10012 goto OTHER;
3afe33e7 10013#endif /* USE_X_TOOLKIT */
7a13e894
RS
10014 }
10015 break;
dc6f92b8 10016
7a13e894 10017 case CirculateNotify:
06a2c219
GM
10018 goto OTHER;
10019
7a13e894 10020 case CirculateRequest:
06a2c219
GM
10021 goto OTHER;
10022
10023 case VisibilityNotify:
10024 goto OTHER;
dc6f92b8 10025
7a13e894
RS
10026 case MappingNotify:
10027 /* Someone has changed the keyboard mapping - update the
10028 local cache. */
10029 switch (event.xmapping.request)
10030 {
10031 case MappingModifier:
10032 x_find_modifier_meanings (dpyinfo);
10033 /* This is meant to fall through. */
10034 case MappingKeyboard:
10035 XRefreshKeyboardMapping (&event.xmapping);
10036 }
7a13e894 10037 goto OTHER;
dc6f92b8 10038
7a13e894 10039 default:
7a13e894 10040 OTHER:
717ca130 10041#ifdef USE_X_TOOLKIT
7a13e894
RS
10042 BLOCK_INPUT;
10043 XtDispatchEvent (&event);
10044 UNBLOCK_INPUT;
3afe33e7 10045#endif /* USE_X_TOOLKIT */
7a13e894
RS
10046 break;
10047 }
dc6f92b8
JB
10048 }
10049 }
10050
06a2c219
GM
10051 out:;
10052
9a5196d0
RS
10053 /* On some systems, an X bug causes Emacs to get no more events
10054 when the window is destroyed. Detect that. (1994.) */
58769bee 10055 if (! event_found)
ef2a22d0 10056 {
ef2a22d0
RS
10057 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
10058 One XNOOP in 100 loops will make Emacs terminate.
10059 B. Bretthauer, 1994 */
10060 x_noop_count++;
58769bee 10061 if (x_noop_count >= 100)
ef2a22d0
RS
10062 {
10063 x_noop_count=0;
2224b905
RS
10064
10065 if (next_noop_dpyinfo == 0)
10066 next_noop_dpyinfo = x_display_list;
10067
10068 XNoOp (next_noop_dpyinfo->display);
10069
10070 /* Each time we get here, cycle through the displays now open. */
10071 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
10072 }
10073 }
502add23 10074
06a2c219 10075 /* If the focus was just given to an auto-raising frame,
0134a210 10076 raise it now. */
7a13e894 10077 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
10078 if (pending_autoraise_frame)
10079 {
10080 x_raise_frame (pending_autoraise_frame);
10081 pending_autoraise_frame = 0;
10082 }
0134a210 10083
dc6f92b8 10084 UNBLOCK_INPUT;
bde5503b 10085 --handling_signal;
dc6f92b8
JB
10086 return count;
10087}
06a2c219
GM
10088
10089
10090
dc6f92b8 10091\f
06a2c219
GM
10092/***********************************************************************
10093 Text Cursor
10094 ***********************************************************************/
10095
10096/* Note if the text cursor of window W has been overwritten by a
10097 drawing operation that outputs N glyphs starting at HPOS in the
10098 line given by output_cursor.vpos. N < 0 means all the rest of the
10099 line after HPOS has been written. */
10100
10101static void
10102note_overwritten_text_cursor (w, hpos, n)
10103 struct window *w;
10104 int hpos, n;
10105{
10106 if (updated_area == TEXT_AREA
10107 && output_cursor.vpos == w->phys_cursor.vpos
10108 && hpos <= w->phys_cursor.hpos
10109 && (n < 0
10110 || hpos + n > w->phys_cursor.hpos))
10111 w->phys_cursor_on_p = 0;
10112}
f451eb13
JB
10113
10114
06a2c219
GM
10115/* Set clipping for output in glyph row ROW. W is the window in which
10116 we operate. GC is the graphics context to set clipping in.
10117 WHOLE_LINE_P non-zero means include the areas used for truncation
10118 mark display and alike in the clipping rectangle.
10119
10120 ROW may be a text row or, e.g., a mode line. Text rows must be
10121 clipped to the interior of the window dedicated to text display,
10122 mode lines must be clipped to the whole window. */
dc6f92b8
JB
10123
10124static void
06a2c219
GM
10125x_clip_to_row (w, row, gc, whole_line_p)
10126 struct window *w;
10127 struct glyph_row *row;
10128 GC gc;
10129 int whole_line_p;
dc6f92b8 10130{
06a2c219
GM
10131 struct frame *f = XFRAME (WINDOW_FRAME (w));
10132 XRectangle clip_rect;
10133 int window_x, window_y, window_width, window_height;
dc6f92b8 10134
06a2c219 10135 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 10136
06a2c219
GM
10137 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
10138 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
10139 clip_rect.y = max (clip_rect.y, window_y);
10140 clip_rect.width = window_width;
10141 clip_rect.height = row->visible_height;
5c1aae96 10142
06a2c219
GM
10143 /* If clipping to the whole line, including trunc marks, extend
10144 the rectangle to the left and increase its width. */
10145 if (whole_line_p)
10146 {
110859fc
GM
10147 clip_rect.x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
10148 clip_rect.width += FRAME_X_FLAGS_AREA_WIDTH (f);
06a2c219 10149 }
5c1aae96 10150
06a2c219 10151 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
10152}
10153
06a2c219
GM
10154
10155/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
10156
10157static void
06a2c219
GM
10158x_draw_hollow_cursor (w, row)
10159 struct window *w;
10160 struct glyph_row *row;
dc6f92b8 10161{
06a2c219
GM
10162 struct frame *f = XFRAME (WINDOW_FRAME (w));
10163 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10164 Display *dpy = FRAME_X_DISPLAY (f);
10165 int x, y, wd, h;
10166 XGCValues xgcv;
10167 struct glyph *cursor_glyph;
10168 GC gc;
10169
10170 /* Compute frame-relative coordinates from window-relative
10171 coordinates. */
10172 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10173 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
10174 + row->ascent - w->phys_cursor_ascent);
10175 h = row->height - 1;
10176
10177 /* Get the glyph the cursor is on. If we can't tell because
10178 the current matrix is invalid or such, give up. */
10179 cursor_glyph = get_phys_cursor_glyph (w);
10180 if (cursor_glyph == NULL)
dc6f92b8
JB
10181 return;
10182
06a2c219
GM
10183 /* Compute the width of the rectangle to draw. If on a stretch
10184 glyph, and `x-stretch-block-cursor' is nil, don't draw a
10185 rectangle as wide as the glyph, but use a canonical character
10186 width instead. */
10187 wd = cursor_glyph->pixel_width - 1;
10188 if (cursor_glyph->type == STRETCH_GLYPH
10189 && !x_stretch_cursor_p)
10190 wd = min (CANON_X_UNIT (f), wd);
10191
10192 /* The foreground of cursor_gc is typically the same as the normal
10193 background color, which can cause the cursor box to be invisible. */
10194 xgcv.foreground = f->output_data.x->cursor_pixel;
10195 if (dpyinfo->scratch_cursor_gc)
10196 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
10197 else
10198 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
10199 GCForeground, &xgcv);
10200 gc = dpyinfo->scratch_cursor_gc;
10201
10202 /* Set clipping, draw the rectangle, and reset clipping again. */
10203 x_clip_to_row (w, row, gc, 0);
10204 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
10205 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
10206}
10207
06a2c219
GM
10208
10209/* Draw a bar cursor on window W in glyph row ROW.
10210
10211 Implementation note: One would like to draw a bar cursor with an
10212 angle equal to the one given by the font property XA_ITALIC_ANGLE.
10213 Unfortunately, I didn't find a font yet that has this property set.
10214 --gerd. */
dc6f92b8
JB
10215
10216static void
f02d8aa0 10217x_draw_bar_cursor (w, row, width)
06a2c219
GM
10218 struct window *w;
10219 struct glyph_row *row;
f02d8aa0 10220 int width;
dc6f92b8 10221{
06a2c219
GM
10222 /* If cursor hpos is out of bounds, don't draw garbage. This can
10223 happen in mini-buffer windows when switching between echo area
10224 glyphs and mini-buffer. */
10225 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
10226 {
10227 struct frame *f = XFRAME (w->frame);
10228 struct glyph *cursor_glyph;
10229 GC gc;
10230 int x;
10231 unsigned long mask;
10232 XGCValues xgcv;
10233 Display *dpy;
10234 Window window;
10235
10236 cursor_glyph = get_phys_cursor_glyph (w);
10237 if (cursor_glyph == NULL)
10238 return;
10239
10240 xgcv.background = f->output_data.x->cursor_pixel;
10241 xgcv.foreground = f->output_data.x->cursor_pixel;
10242 xgcv.graphics_exposures = 0;
10243 mask = GCForeground | GCBackground | GCGraphicsExposures;
10244 dpy = FRAME_X_DISPLAY (f);
10245 window = FRAME_X_WINDOW (f);
10246 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
10247
10248 if (gc)
10249 XChangeGC (dpy, gc, mask, &xgcv);
10250 else
10251 {
10252 gc = XCreateGC (dpy, window, mask, &xgcv);
10253 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
10254 }
10255
f02d8aa0
GM
10256 if (width < 0)
10257 width = f->output_data.x->cursor_width;
10258
06a2c219
GM
10259 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
10260 x_clip_to_row (w, row, gc, 0);
10261 XFillRectangle (dpy, window, gc,
10262 x,
10263 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
f02d8aa0 10264 min (cursor_glyph->pixel_width, width),
06a2c219
GM
10265 row->height);
10266 XSetClipMask (dpy, gc, None);
10267 }
dc6f92b8
JB
10268}
10269
06a2c219
GM
10270
10271/* Clear the cursor of window W to background color, and mark the
10272 cursor as not shown. This is used when the text where the cursor
10273 is is about to be rewritten. */
10274
dc6f92b8 10275static void
06a2c219
GM
10276x_clear_cursor (w)
10277 struct window *w;
dc6f92b8 10278{
06a2c219
GM
10279 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
10280 x_update_window_cursor (w, 0);
10281}
90e65f07 10282
dbc4e1c1 10283
06a2c219
GM
10284/* Draw the cursor glyph of window W in glyph row ROW. See the
10285 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 10286
06a2c219
GM
10287static void
10288x_draw_phys_cursor_glyph (w, row, hl)
10289 struct window *w;
10290 struct glyph_row *row;
10291 enum draw_glyphs_face hl;
10292{
10293 /* If cursor hpos is out of bounds, don't draw garbage. This can
10294 happen in mini-buffer windows when switching between echo area
10295 glyphs and mini-buffer. */
10296 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
66ac4b0e
GM
10297 {
10298 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
10299 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
10300 hl, 0, 0, 0);
10301
10302 /* When we erase the cursor, and ROW is overlapped by other
10303 rows, make sure that these overlapping parts of other rows
10304 are redrawn. */
10305 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
10306 {
10307 if (row > w->current_matrix->rows
10308 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
10309 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
10310
10311 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
10312 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
10313 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
10314 }
10315 }
06a2c219 10316}
dbc4e1c1 10317
eea6af04 10318
06a2c219 10319/* Erase the image of a cursor of window W from the screen. */
eea6af04 10320
06a2c219
GM
10321static void
10322x_erase_phys_cursor (w)
10323 struct window *w;
10324{
10325 struct frame *f = XFRAME (w->frame);
10326 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
10327 int hpos = w->phys_cursor.hpos;
10328 int vpos = w->phys_cursor.vpos;
10329 int mouse_face_here_p = 0;
10330 struct glyph_matrix *active_glyphs = w->current_matrix;
10331 struct glyph_row *cursor_row;
10332 struct glyph *cursor_glyph;
10333 enum draw_glyphs_face hl;
10334
10335 /* No cursor displayed or row invalidated => nothing to do on the
10336 screen. */
10337 if (w->phys_cursor_type == NO_CURSOR)
10338 goto mark_cursor_off;
10339
10340 /* VPOS >= active_glyphs->nrows means that window has been resized.
10341 Don't bother to erase the cursor. */
10342 if (vpos >= active_glyphs->nrows)
10343 goto mark_cursor_off;
10344
10345 /* If row containing cursor is marked invalid, there is nothing we
10346 can do. */
10347 cursor_row = MATRIX_ROW (active_glyphs, vpos);
10348 if (!cursor_row->enabled_p)
10349 goto mark_cursor_off;
10350
10351 /* This can happen when the new row is shorter than the old one.
10352 In this case, either x_draw_glyphs or clear_end_of_line
10353 should have cleared the cursor. Note that we wouldn't be
10354 able to erase the cursor in this case because we don't have a
10355 cursor glyph at hand. */
10356 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
10357 goto mark_cursor_off;
10358
10359 /* If the cursor is in the mouse face area, redisplay that when
10360 we clear the cursor. */
8801a864
KR
10361 if (! NILP (dpyinfo->mouse_face_window)
10362 && w == XWINDOW (dpyinfo->mouse_face_window)
06a2c219
GM
10363 && (vpos > dpyinfo->mouse_face_beg_row
10364 || (vpos == dpyinfo->mouse_face_beg_row
10365 && hpos >= dpyinfo->mouse_face_beg_col))
10366 && (vpos < dpyinfo->mouse_face_end_row
10367 || (vpos == dpyinfo->mouse_face_end_row
10368 && hpos < dpyinfo->mouse_face_end_col))
10369 /* Don't redraw the cursor's spot in mouse face if it is at the
10370 end of a line (on a newline). The cursor appears there, but
10371 mouse highlighting does not. */
10372 && cursor_row->used[TEXT_AREA] > hpos)
10373 mouse_face_here_p = 1;
10374
10375 /* Maybe clear the display under the cursor. */
10376 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
10377 {
10378 int x;
045dee35 10379 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
dbc4e1c1 10380
06a2c219
GM
10381 cursor_glyph = get_phys_cursor_glyph (w);
10382 if (cursor_glyph == NULL)
10383 goto mark_cursor_off;
dbc4e1c1 10384
06a2c219
GM
10385 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
10386
10387 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10388 x,
045dee35 10389 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
06a2c219
GM
10390 cursor_row->y)),
10391 cursor_glyph->pixel_width,
10392 cursor_row->visible_height,
10393 False);
dbc4e1c1 10394 }
06a2c219
GM
10395
10396 /* Erase the cursor by redrawing the character underneath it. */
10397 if (mouse_face_here_p)
10398 hl = DRAW_MOUSE_FACE;
10399 else if (cursor_row->inverse_p)
10400 hl = DRAW_INVERSE_VIDEO;
10401 else
10402 hl = DRAW_NORMAL_TEXT;
10403 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 10404
06a2c219
GM
10405 mark_cursor_off:
10406 w->phys_cursor_on_p = 0;
10407 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
10408}
10409
10410
06a2c219
GM
10411/* Display or clear cursor of window W. If ON is zero, clear the
10412 cursor. If it is non-zero, display the cursor. If ON is nonzero,
10413 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 10414
06a2c219
GM
10415void
10416x_display_and_set_cursor (w, on, hpos, vpos, x, y)
10417 struct window *w;
10418 int on, hpos, vpos, x, y;
dbc4e1c1 10419{
06a2c219
GM
10420 struct frame *f = XFRAME (w->frame);
10421 int new_cursor_type;
f02d8aa0 10422 int new_cursor_width;
06a2c219
GM
10423 struct glyph_matrix *current_glyphs;
10424 struct glyph_row *glyph_row;
10425 struct glyph *glyph;
dbc4e1c1 10426
49d838ea 10427 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
10428 windows and frames; in the latter case, the frame or window may
10429 be in the midst of changing its size, and x and y may be off the
10430 window. */
10431 if (! FRAME_VISIBLE_P (f)
10432 || FRAME_GARBAGED_P (f)
10433 || vpos >= w->current_matrix->nrows
10434 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
10435 return;
10436
10437 /* If cursor is off and we want it off, return quickly. */
06a2c219 10438 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
10439 return;
10440
06a2c219
GM
10441 current_glyphs = w->current_matrix;
10442 glyph_row = MATRIX_ROW (current_glyphs, vpos);
10443 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
10444
10445 /* If cursor row is not enabled, we don't really know where to
10446 display the cursor. */
10447 if (!glyph_row->enabled_p)
10448 {
10449 w->phys_cursor_on_p = 0;
10450 return;
10451 }
10452
10453 xassert (interrupt_input_blocked);
10454
10455 /* Set new_cursor_type to the cursor we want to be displayed. In a
10456 mini-buffer window, we want the cursor only to appear if we are
10457 reading input from this window. For the selected window, we want
10458 the cursor type given by the frame parameter. If explicitly
10459 marked off, draw no cursor. In all other cases, we want a hollow
10460 box cursor. */
f02d8aa0 10461 new_cursor_width = -1;
9b4a7047
GM
10462 if (cursor_in_echo_area
10463 && FRAME_HAS_MINIBUF_P (f)
10464 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
06a2c219 10465 {
9b4a7047
GM
10466 if (w == XWINDOW (echo_area_window))
10467 new_cursor_type = FRAME_DESIRED_CURSOR (f);
06a2c219
GM
10468 else
10469 new_cursor_type = HOLLOW_BOX_CURSOR;
10470 }
06a2c219 10471 else
9b4a7047
GM
10472 {
10473 if (w != XWINDOW (selected_window)
10474 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
10475 {
e55a0b79
GM
10476 extern int cursor_in_non_selected_windows;
10477
10478 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
9b4a7047
GM
10479 new_cursor_type = NO_CURSOR;
10480 else
10481 new_cursor_type = HOLLOW_BOX_CURSOR;
10482 }
10483 else if (w->cursor_off_p)
10484 new_cursor_type = NO_CURSOR;
10485 else
f02d8aa0
GM
10486 {
10487 struct buffer *b = XBUFFER (w->buffer);
10488
10489 if (EQ (b->cursor_type, Qt))
10490 new_cursor_type = FRAME_DESIRED_CURSOR (f);
10491 else
10492 new_cursor_type = x_specified_cursor_type (b->cursor_type,
10493 &new_cursor_width);
10494 }
9b4a7047 10495 }
06a2c219
GM
10496
10497 /* If cursor is currently being shown and we don't want it to be or
10498 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 10499 erase it. */
06a2c219 10500 if (w->phys_cursor_on_p
dc6f92b8 10501 && (!on
06a2c219
GM
10502 || w->phys_cursor.x != x
10503 || w->phys_cursor.y != y
10504 || new_cursor_type != w->phys_cursor_type))
10505 x_erase_phys_cursor (w);
10506
10507 /* If the cursor is now invisible and we want it to be visible,
10508 display it. */
10509 if (on && !w->phys_cursor_on_p)
10510 {
10511 w->phys_cursor_ascent = glyph_row->ascent;
10512 w->phys_cursor_height = glyph_row->height;
10513
10514 /* Set phys_cursor_.* before x_draw_.* is called because some
10515 of them may need the information. */
10516 w->phys_cursor.x = x;
10517 w->phys_cursor.y = glyph_row->y;
10518 w->phys_cursor.hpos = hpos;
10519 w->phys_cursor.vpos = vpos;
10520 w->phys_cursor_type = new_cursor_type;
10521 w->phys_cursor_on_p = 1;
10522
10523 switch (new_cursor_type)
dc6f92b8 10524 {
06a2c219
GM
10525 case HOLLOW_BOX_CURSOR:
10526 x_draw_hollow_cursor (w, glyph_row);
10527 break;
10528
10529 case FILLED_BOX_CURSOR:
10530 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
10531 break;
10532
10533 case BAR_CURSOR:
f02d8aa0 10534 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
06a2c219
GM
10535 break;
10536
10537 case NO_CURSOR:
10538 break;
dc6f92b8 10539
06a2c219
GM
10540 default:
10541 abort ();
10542 }
59ddecde
GM
10543
10544#ifdef HAVE_X_I18N
10545 if (w == XWINDOW (f->selected_window))
10546 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
10547 xic_set_preeditarea (w, x, y);
10548#endif
dc6f92b8
JB
10549 }
10550
06a2c219 10551#ifndef XFlush
f676886a 10552 if (updating_frame != f)
334208b7 10553 XFlush (FRAME_X_DISPLAY (f));
06a2c219 10554#endif
dc6f92b8
JB
10555}
10556
06a2c219
GM
10557
10558/* Display the cursor on window W, or clear it. X and Y are window
10559 relative pixel coordinates. HPOS and VPOS are glyph matrix
10560 positions. If W is not the selected window, display a hollow
10561 cursor. ON non-zero means display the cursor at X, Y which
10562 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 10563
dfcf069d 10564void
06a2c219
GM
10565x_display_cursor (w, on, hpos, vpos, x, y)
10566 struct window *w;
10567 int on, hpos, vpos, x, y;
dc6f92b8 10568{
f94397b5 10569 BLOCK_INPUT;
06a2c219 10570 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
10571 UNBLOCK_INPUT;
10572}
10573
06a2c219
GM
10574
10575/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
10576 Don't change the cursor's position. */
10577
dfcf069d 10578void
06a2c219 10579x_update_cursor (f, on_p)
5d46f928 10580 struct frame *f;
5d46f928 10581{
06a2c219
GM
10582 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10583}
10584
10585
10586/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10587 in the window tree rooted at W. */
10588
10589static void
10590x_update_cursor_in_window_tree (w, on_p)
10591 struct window *w;
10592 int on_p;
10593{
10594 while (w)
10595 {
10596 if (!NILP (w->hchild))
10597 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10598 else if (!NILP (w->vchild))
10599 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10600 else
10601 x_update_window_cursor (w, on_p);
10602
10603 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10604 }
10605}
5d46f928 10606
f94397b5 10607
06a2c219
GM
10608/* Switch the display of W's cursor on or off, according to the value
10609 of ON. */
10610
10611static void
10612x_update_window_cursor (w, on)
10613 struct window *w;
10614 int on;
10615{
16b5d424
GM
10616 /* Don't update cursor in windows whose frame is in the process
10617 of being deleted. */
10618 if (w->current_matrix)
10619 {
10620 BLOCK_INPUT;
10621 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10622 w->phys_cursor.x, w->phys_cursor.y);
10623 UNBLOCK_INPUT;
10624 }
dc6f92b8 10625}
06a2c219
GM
10626
10627
10628
dc6f92b8
JB
10629\f
10630/* Icons. */
10631
f676886a 10632/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10633 when we get an expose event for it. */
dc6f92b8 10634
dfcf069d 10635void
f676886a
JB
10636refreshicon (f)
10637 struct frame *f;
dc6f92b8 10638{
06a2c219 10639 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10640}
10641
dbc4e1c1 10642/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10643
10644int
990ba854 10645x_bitmap_icon (f, file)
f676886a 10646 struct frame *f;
990ba854 10647 Lisp_Object file;
dc6f92b8 10648{
06a2c219 10649 int bitmap_id;
dc6f92b8 10650
c118dd06 10651 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10652 return 1;
10653
990ba854 10654 /* Free up our existing icon bitmap if any. */
7556890b
RS
10655 if (f->output_data.x->icon_bitmap > 0)
10656 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10657 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10658
10659 if (STRINGP (file))
7f2ae036
RS
10660 bitmap_id = x_create_bitmap_from_file (f, file);
10661 else
10662 {
990ba854 10663 /* Create the GNU bitmap if necessary. */
5bf01b68 10664 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10665 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10666 = x_create_bitmap_from_data (f, gnu_bits,
10667 gnu_width, gnu_height);
990ba854
RS
10668
10669 /* The first time we create the GNU bitmap,
06a2c219 10670 this increments the ref-count one extra time.
990ba854
RS
10671 As a result, the GNU bitmap is never freed.
10672 That way, we don't have to worry about allocating it again. */
334208b7 10673 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10674
334208b7 10675 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10676 }
10677
10678 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10679 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10680
10681 return 0;
10682}
10683
10684
1be2d067
KH
10685/* Make the x-window of frame F use a rectangle with text.
10686 Use ICON_NAME as the text. */
dc6f92b8
JB
10687
10688int
f676886a
JB
10689x_text_icon (f, icon_name)
10690 struct frame *f;
dc6f92b8
JB
10691 char *icon_name;
10692{
c118dd06 10693 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10694 return 1;
10695
1be2d067
KH
10696#ifdef HAVE_X11R4
10697 {
10698 XTextProperty text;
10699 text.value = (unsigned char *) icon_name;
10700 text.encoding = XA_STRING;
10701 text.format = 8;
10702 text.nitems = strlen (icon_name);
10703#ifdef USE_X_TOOLKIT
7556890b 10704 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10705 &text);
10706#else /* not USE_X_TOOLKIT */
10707 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10708#endif /* not USE_X_TOOLKIT */
10709 }
10710#else /* not HAVE_X11R4 */
10711 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10712#endif /* not HAVE_X11R4 */
58769bee 10713
7556890b
RS
10714 if (f->output_data.x->icon_bitmap > 0)
10715 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10716 f->output_data.x->icon_bitmap = 0;
b1c884c3 10717 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10718
10719 return 0;
10720}
10721\f
e99db5a1
RS
10722#define X_ERROR_MESSAGE_SIZE 200
10723
10724/* If non-nil, this should be a string.
10725 It means catch X errors and store the error message in this string. */
10726
10727static Lisp_Object x_error_message_string;
10728
10729/* An X error handler which stores the error message in
10730 x_error_message_string. This is called from x_error_handler if
10731 x_catch_errors is in effect. */
10732
06a2c219 10733static void
e99db5a1
RS
10734x_error_catcher (display, error)
10735 Display *display;
10736 XErrorEvent *error;
10737{
10738 XGetErrorText (display, error->error_code,
10739 XSTRING (x_error_message_string)->data,
10740 X_ERROR_MESSAGE_SIZE);
10741}
10742
10743/* Begin trapping X errors for display DPY. Actually we trap X errors
10744 for all displays, but DPY should be the display you are actually
10745 operating on.
10746
10747 After calling this function, X protocol errors no longer cause
10748 Emacs to exit; instead, they are recorded in the string
10749 stored in x_error_message_string.
10750
10751 Calling x_check_errors signals an Emacs error if an X error has
10752 occurred since the last call to x_catch_errors or x_check_errors.
10753
10754 Calling x_uncatch_errors resumes the normal error handling. */
10755
10756void x_check_errors ();
10757static Lisp_Object x_catch_errors_unwind ();
10758
10759int
10760x_catch_errors (dpy)
10761 Display *dpy;
10762{
10763 int count = specpdl_ptr - specpdl;
10764
10765 /* Make sure any errors from previous requests have been dealt with. */
10766 XSync (dpy, False);
10767
10768 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10769
10770 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10771 XSTRING (x_error_message_string)->data[0] = 0;
10772
10773 return count;
10774}
10775
10776/* Unbind the binding that we made to check for X errors. */
10777
10778static Lisp_Object
10779x_catch_errors_unwind (old_val)
10780 Lisp_Object old_val;
10781{
10782 x_error_message_string = old_val;
10783 return Qnil;
10784}
10785
10786/* If any X protocol errors have arrived since the last call to
10787 x_catch_errors or x_check_errors, signal an Emacs error using
10788 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10789
10790void
10791x_check_errors (dpy, format)
10792 Display *dpy;
10793 char *format;
10794{
10795 /* Make sure to catch any errors incurred so far. */
10796 XSync (dpy, False);
10797
10798 if (XSTRING (x_error_message_string)->data[0])
10799 error (format, XSTRING (x_error_message_string)->data);
10800}
10801
9829ddba
RS
10802/* Nonzero if we had any X protocol errors
10803 since we did x_catch_errors on DPY. */
e99db5a1
RS
10804
10805int
10806x_had_errors_p (dpy)
10807 Display *dpy;
10808{
10809 /* Make sure to catch any errors incurred so far. */
10810 XSync (dpy, False);
10811
10812 return XSTRING (x_error_message_string)->data[0] != 0;
10813}
10814
9829ddba
RS
10815/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10816
06a2c219 10817void
9829ddba
RS
10818x_clear_errors (dpy)
10819 Display *dpy;
10820{
10821 XSTRING (x_error_message_string)->data[0] = 0;
10822}
10823
e99db5a1
RS
10824/* Stop catching X protocol errors and let them make Emacs die.
10825 DPY should be the display that was passed to x_catch_errors.
10826 COUNT should be the value that was returned by
10827 the corresponding call to x_catch_errors. */
10828
10829void
10830x_uncatch_errors (dpy, count)
10831 Display *dpy;
10832 int count;
10833{
10834 unbind_to (count, Qnil);
10835}
10836
10837#if 0
10838static unsigned int x_wire_count;
10839x_trace_wire ()
10840{
10841 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10842}
10843#endif /* ! 0 */
10844
10845\f
10846/* Handle SIGPIPE, which can happen when the connection to a server
10847 simply goes away. SIGPIPE is handled by x_connection_signal.
10848 Don't need to do anything, because the write which caused the
10849 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 10850 which will do the appropriate cleanup for us. */
e99db5a1
RS
10851
10852static SIGTYPE
10853x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 10854 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
10855{
10856#ifdef USG
10857 /* USG systems forget handlers when they are used;
10858 must reestablish each time */
10859 signal (signalnum, x_connection_signal);
10860#endif /* USG */
10861}
10862\f
4746118a
JB
10863/* Handling X errors. */
10864
7a13e894 10865/* Handle the loss of connection to display DISPLAY. */
16bd92ea 10866
4746118a 10867static SIGTYPE
7a13e894
RS
10868x_connection_closed (display, error_message)
10869 Display *display;
10870 char *error_message;
4746118a 10871{
7a13e894
RS
10872 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10873 Lisp_Object frame, tail;
10874
6186a4a0
RS
10875 /* Indicate that this display is dead. */
10876
2e465cdd 10877#if 0 /* Closing the display caused a bus error on OpenWindows. */
f613a4c8 10878#ifdef USE_X_TOOLKIT
adabc3a9 10879 XtCloseDisplay (display);
2e465cdd 10880#endif
f613a4c8 10881#endif
adabc3a9 10882
9e80b57d
KR
10883 if (dpyinfo)
10884 dpyinfo->display = 0;
6186a4a0 10885
06a2c219 10886 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
10887 that are on the dead display. */
10888 FOR_EACH_FRAME (tail, frame)
10889 {
10890 Lisp_Object minibuf_frame;
10891 minibuf_frame
10892 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
10893 if (FRAME_X_P (XFRAME (frame))
10894 && FRAME_X_P (XFRAME (minibuf_frame))
10895 && ! EQ (frame, minibuf_frame)
10896 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
10897 Fdelete_frame (frame, Qt);
10898 }
10899
10900 /* Now delete all remaining frames on the dead display.
06a2c219 10901 We are now sure none of these is used as the mini-buffer
7a13e894
RS
10902 for another frame that we need to delete. */
10903 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
10904 if (FRAME_X_P (XFRAME (frame))
10905 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
10906 {
10907 /* Set this to t so that Fdelete_frame won't get confused
10908 trying to find a replacement. */
10909 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10910 Fdelete_frame (frame, Qt);
10911 }
7a13e894 10912
482a1bd2
KH
10913 if (dpyinfo)
10914 x_delete_display (dpyinfo);
7a13e894
RS
10915
10916 if (x_display_list == 0)
10917 {
f8d07b62 10918 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
10919 shut_down_emacs (0, 0, Qnil);
10920 exit (70);
10921 }
12ba150f 10922
7a13e894
RS
10923 /* Ordinary stack unwind doesn't deal with these. */
10924#ifdef SIGIO
10925 sigunblock (sigmask (SIGIO));
10926#endif
10927 sigunblock (sigmask (SIGALRM));
10928 TOTALLY_UNBLOCK_INPUT;
10929
aa4d9a9e 10930 clear_waiting_for_input ();
7a13e894 10931 error ("%s", error_message);
4746118a
JB
10932}
10933
7a13e894
RS
10934/* This is the usual handler for X protocol errors.
10935 It kills all frames on the display that we got the error for.
10936 If that was the only one, it prints an error message and kills Emacs. */
10937
06a2c219 10938static void
c118dd06
JB
10939x_error_quitter (display, error)
10940 Display *display;
10941 XErrorEvent *error;
10942{
7a13e894 10943 char buf[256], buf1[356];
dc6f92b8 10944
58769bee 10945 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 10946 original error handler. */
dc6f92b8 10947
c118dd06 10948 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 10949 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 10950 buf, error->request_code);
7a13e894 10951 x_connection_closed (display, buf1);
dc6f92b8
JB
10952}
10953
e99db5a1
RS
10954/* This is the first-level handler for X protocol errors.
10955 It calls x_error_quitter or x_error_catcher. */
7a13e894 10956
8922af5f 10957static int
e99db5a1 10958x_error_handler (display, error)
8922af5f 10959 Display *display;
e99db5a1 10960 XErrorEvent *error;
8922af5f 10961{
e99db5a1
RS
10962 if (! NILP (x_error_message_string))
10963 x_error_catcher (display, error);
10964 else
10965 x_error_quitter (display, error);
06a2c219 10966 return 0;
f9e24cb9 10967}
c118dd06 10968
e99db5a1
RS
10969/* This is the handler for X IO errors, always.
10970 It kills all frames on the display that we lost touch with.
10971 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 10972
c118dd06 10973static int
e99db5a1 10974x_io_error_quitter (display)
c118dd06 10975 Display *display;
c118dd06 10976{
e99db5a1 10977 char buf[256];
dc6f92b8 10978
e99db5a1
RS
10979 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10980 x_connection_closed (display, buf);
06a2c219 10981 return 0;
dc6f92b8 10982}
dc6f92b8 10983\f
f451eb13
JB
10984/* Changing the font of the frame. */
10985
76bcdf39
RS
10986/* Give frame F the font named FONTNAME as its default font, and
10987 return the full name of that font. FONTNAME may be a wildcard
10988 pattern; in that case, we choose some font that fits the pattern.
10989 The return value shows which font we chose. */
10990
b5cf7a0e 10991Lisp_Object
f676886a
JB
10992x_new_font (f, fontname)
10993 struct frame *f;
dc6f92b8
JB
10994 register char *fontname;
10995{
dc43ef94 10996 struct font_info *fontp
ee569018 10997 = FS_LOAD_FONT (f, 0, fontname, -1);
dc6f92b8 10998
dc43ef94
KH
10999 if (!fontp)
11000 return Qnil;
2224a5fc 11001
dc43ef94 11002 f->output_data.x->font = (XFontStruct *) (fontp->font);
b4192550 11003 f->output_data.x->baseline_offset = fontp->baseline_offset;
dc43ef94
KH
11004 f->output_data.x->fontset = -1;
11005
b2cad826
KH
11006 /* Compute the scroll bar width in character columns. */
11007 if (f->scroll_bar_pixel_width > 0)
11008 {
7556890b 11009 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
11010 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
11011 }
11012 else
4e61bddf
RS
11013 {
11014 int wid = FONT_WIDTH (f->output_data.x->font);
11015 f->scroll_bar_cols = (14 + wid - 1) / wid;
11016 }
b2cad826 11017
f676886a 11018 /* Now make the frame display the given font. */
c118dd06 11019 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 11020 {
7556890b
RS
11021 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
11022 f->output_data.x->font->fid);
11023 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
11024 f->output_data.x->font->fid);
11025 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
11026 f->output_data.x->font->fid);
f676886a 11027
a27f9f86 11028 frame_update_line_height (f);
0134a210 11029 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 11030 }
a27f9f86
RS
11031 else
11032 /* If we are setting a new frame's font for the first time,
11033 there are no faces yet, so this font's height is the line height. */
7556890b 11034 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 11035
dc43ef94
KH
11036 return build_string (fontp->full_name);
11037}
11038
11039/* Give frame F the fontset named FONTSETNAME as its default font, and
11040 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
11041 pattern; in that case, we choose some fontset that fits the pattern.
11042 The return value shows which fontset we chose. */
b5cf7a0e 11043
dc43ef94
KH
11044Lisp_Object
11045x_new_fontset (f, fontsetname)
11046 struct frame *f;
11047 char *fontsetname;
11048{
ee569018 11049 int fontset = fs_query_fontset (build_string (fontsetname), 0);
dc43ef94 11050 Lisp_Object result;
b5cf7a0e 11051
dc43ef94
KH
11052 if (fontset < 0)
11053 return Qnil;
b5cf7a0e 11054
2da424f1
KH
11055 if (f->output_data.x->fontset == fontset)
11056 /* This fontset is already set in frame F. There's nothing more
11057 to do. */
ee569018 11058 return fontset_name (fontset);
dc43ef94 11059
ee569018 11060 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
dc43ef94
KH
11061
11062 if (!STRINGP (result))
11063 /* Can't load ASCII font. */
11064 return Qnil;
11065
11066 /* Since x_new_font doesn't update any fontset information, do it now. */
11067 f->output_data.x->fontset = fontset;
dc43ef94 11068
f5d11644
GM
11069#ifdef HAVE_X_I18N
11070 if (FRAME_XIC (f)
11071 && (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
ee569018 11072 xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
f5d11644
GM
11073#endif
11074
dc43ef94 11075 return build_string (fontsetname);
dc6f92b8 11076}
f5d11644
GM
11077
11078\f
11079/***********************************************************************
11080 X Input Methods
11081 ***********************************************************************/
11082
11083#ifdef HAVE_X_I18N
11084
11085#ifdef HAVE_X11R6
11086
11087/* XIM destroy callback function, which is called whenever the
11088 connection to input method XIM dies. CLIENT_DATA contains a
11089 pointer to the x_display_info structure corresponding to XIM. */
11090
11091static void
11092xim_destroy_callback (xim, client_data, call_data)
11093 XIM xim;
11094 XPointer client_data;
11095 XPointer call_data;
11096{
11097 struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
11098 Lisp_Object frame, tail;
11099
11100 BLOCK_INPUT;
11101
11102 /* No need to call XDestroyIC.. */
11103 FOR_EACH_FRAME (tail, frame)
11104 {
11105 struct frame *f = XFRAME (frame);
11106 if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
11107 {
11108 FRAME_XIC (f) = NULL;
11109 if (FRAME_XIC_FONTSET (f))
11110 {
11111 XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
11112 FRAME_XIC_FONTSET (f) = NULL;
11113 }
11114 }
11115 }
11116
11117 /* No need to call XCloseIM. */
11118 dpyinfo->xim = NULL;
11119 XFree (dpyinfo->xim_styles);
11120 UNBLOCK_INPUT;
11121}
11122
11123#endif /* HAVE_X11R6 */
11124
11125/* Open the connection to the XIM server on display DPYINFO.
11126 RESOURCE_NAME is the resource name Emacs uses. */
11127
11128static void
11129xim_open_dpy (dpyinfo, resource_name)
11130 struct x_display_info *dpyinfo;
11131 char *resource_name;
11132{
287f7dd6 11133#ifdef USE_XIM
f5d11644
GM
11134 XIM xim;
11135
11136 xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
11137 dpyinfo->xim = xim;
11138
11139 if (xim)
11140 {
f5d11644
GM
11141#ifdef HAVE_X11R6
11142 XIMCallback destroy;
11143#endif
11144
11145 /* Get supported styles and XIM values. */
11146 XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
11147
11148#ifdef HAVE_X11R6
11149 destroy.callback = xim_destroy_callback;
11150 destroy.client_data = (XPointer)dpyinfo;
68642df6 11151 /* This isn't prptotyped in OSF 5.0. */
f5d11644
GM
11152 XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
11153#endif
11154 }
287f7dd6
GM
11155
11156#else /* not USE_XIM */
11157 dpyinfo->xim = NULL;
11158#endif /* not USE_XIM */
f5d11644
GM
11159}
11160
11161
b9de836c 11162#ifdef HAVE_X11R6_XIM
f5d11644
GM
11163
11164struct xim_inst_t
11165{
11166 struct x_display_info *dpyinfo;
11167 char *resource_name;
11168};
11169
11170/* XIM instantiate callback function, which is called whenever an XIM
11171 server is available. DISPLAY is teh display of the XIM.
11172 CLIENT_DATA contains a pointer to an xim_inst_t structure created
11173 when the callback was registered. */
11174
11175static void
11176xim_instantiate_callback (display, client_data, call_data)
11177 Display *display;
11178 XPointer client_data;
11179 XPointer call_data;
11180{
11181 struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
11182 struct x_display_info *dpyinfo = xim_inst->dpyinfo;
11183
11184 /* We don't support multiple XIM connections. */
11185 if (dpyinfo->xim)
11186 return;
11187
11188 xim_open_dpy (dpyinfo, xim_inst->resource_name);
11189
11190 /* Create XIC for the existing frames on the same display, as long
11191 as they have no XIC. */
11192 if (dpyinfo->xim && dpyinfo->reference_count > 0)
11193 {
11194 Lisp_Object tail, frame;
11195
11196 BLOCK_INPUT;
11197 FOR_EACH_FRAME (tail, frame)
11198 {
11199 struct frame *f = XFRAME (frame);
11200
11201 if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
11202 if (FRAME_XIC (f) == NULL)
11203 {
11204 create_frame_xic (f);
11205 if (FRAME_XIC_STYLE (f) & XIMStatusArea)
11206 xic_set_statusarea (f);
11207 if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
11208 {
11209 struct window *w = XWINDOW (f->selected_window);
11210 xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
11211 }
11212 }
11213 }
11214
11215 UNBLOCK_INPUT;
11216 }
11217}
11218
b9de836c 11219#endif /* HAVE_X11R6_XIM */
f5d11644
GM
11220
11221
11222/* Open a connection to the XIM server on display DPYINFO.
11223 RESOURCE_NAME is the resource name for Emacs. On X11R5, open the
11224 connection only at the first time. On X11R6, open the connection
11225 in the XIM instantiate callback function. */
11226
11227static void
11228xim_initialize (dpyinfo, resource_name)
11229 struct x_display_info *dpyinfo;
11230 char *resource_name;
11231{
287f7dd6 11232#ifdef USE_XIM
b9de836c 11233#ifdef HAVE_X11R6_XIM
f5d11644
GM
11234 struct xim_inst_t *xim_inst;
11235 int len;
11236
11237 dpyinfo->xim = NULL;
11238 xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
11239 xim_inst->dpyinfo = dpyinfo;
11240 len = strlen (resource_name);
11241 xim_inst->resource_name = (char *) xmalloc (len + 1);
11242 bcopy (resource_name, xim_inst->resource_name, len + 1);
11243 XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11244 resource_name, EMACS_CLASS,
11245 xim_instantiate_callback,
2ebb2f8b
DL
11246 /* Fixme: This is XPointer in
11247 XFree86 but (XPointer *) on
11248 Tru64, at least. */
11249 (XPointer) xim_inst);
b9de836c 11250#else /* not HAVE_X11R6_XIM */
f5d11644
GM
11251 dpyinfo->xim = NULL;
11252 xim_open_dpy (dpyinfo, resource_name);
b9de836c 11253#endif /* not HAVE_X11R6_XIM */
287f7dd6
GM
11254
11255#else /* not USE_XIM */
11256 dpyinfo->xim = NULL;
11257#endif /* not USE_XIM */
f5d11644
GM
11258}
11259
11260
11261/* Close the connection to the XIM server on display DPYINFO. */
11262
11263static void
11264xim_close_dpy (dpyinfo)
11265 struct x_display_info *dpyinfo;
11266{
287f7dd6 11267#ifdef USE_XIM
b9de836c 11268#ifdef HAVE_X11R6_XIM
f5d11644
GM
11269 XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
11270 NULL, EMACS_CLASS,
11271 xim_instantiate_callback, NULL);
b9de836c 11272#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11273 XCloseIM (dpyinfo->xim);
11274 dpyinfo->xim = NULL;
11275 XFree (dpyinfo->xim_styles);
287f7dd6 11276#endif /* USE_XIM */
f5d11644
GM
11277}
11278
b9de836c 11279#endif /* not HAVE_X11R6_XIM */
f5d11644
GM
11280
11281
dc6f92b8 11282\f
2e365682
RS
11283/* Calculate the absolute position in frame F
11284 from its current recorded position values and gravity. */
11285
dfcf069d 11286void
43bca5d5 11287x_calc_absolute_position (f)
f676886a 11288 struct frame *f;
dc6f92b8 11289{
06a2c219 11290 Window child;
6dba1858 11291 int win_x = 0, win_y = 0;
7556890b 11292 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
11293 int this_window;
11294
9829ddba
RS
11295 /* We have nothing to do if the current position
11296 is already for the top-left corner. */
11297 if (! ((flags & XNegative) || (flags & YNegative)))
11298 return;
11299
c81412a0 11300#ifdef USE_X_TOOLKIT
7556890b 11301 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
11302#else
11303 this_window = FRAME_X_WINDOW (f);
11304#endif
6dba1858
RS
11305
11306 /* Find the position of the outside upper-left corner of
9829ddba
RS
11307 the inner window, with respect to the outer window.
11308 But do this only if we will need the results. */
7556890b 11309 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 11310 {
9829ddba
RS
11311 int count;
11312
6dba1858 11313 BLOCK_INPUT;
9829ddba
RS
11314 count = x_catch_errors (FRAME_X_DISPLAY (f));
11315 while (1)
11316 {
11317 x_clear_errors (FRAME_X_DISPLAY (f));
11318 XTranslateCoordinates (FRAME_X_DISPLAY (f),
11319
11320 /* From-window, to-window. */
11321 this_window,
11322 f->output_data.x->parent_desc,
11323
11324 /* From-position, to-position. */
11325 0, 0, &win_x, &win_y,
11326
11327 /* Child of win. */
11328 &child);
11329 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11330 {
11331 Window newroot, newparent = 0xdeadbeef;
11332 Window *newchildren;
2ebb2f8b 11333 unsigned int nchildren;
9829ddba
RS
11334
11335 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
11336 &newparent, &newchildren, &nchildren))
11337 break;
58769bee 11338
7c3c78a3 11339 XFree ((char *) newchildren);
6dba1858 11340
9829ddba
RS
11341 f->output_data.x->parent_desc = newparent;
11342 }
11343 else
11344 break;
11345 }
6dba1858 11346
9829ddba 11347 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
11348 UNBLOCK_INPUT;
11349 }
11350
11351 /* Treat negative positions as relative to the leftmost bottommost
11352 position that fits on the screen. */
20f55f9a 11353 if (flags & XNegative)
7556890b 11354 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
11355 - 2 * f->output_data.x->border_width - win_x
11356 - PIXEL_WIDTH (f)
11357 + f->output_data.x->left_pos);
dc6f92b8 11358
20f55f9a 11359 if (flags & YNegative)
06a2c219
GM
11360 {
11361 int menubar_height = 0;
11362
11363#ifdef USE_X_TOOLKIT
11364 if (f->output_data.x->menubar_widget)
11365 menubar_height
11366 = (f->output_data.x->menubar_widget->core.height
11367 + f->output_data.x->menubar_widget->core.border_width);
11368#endif
11369
11370 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
11371 - 2 * f->output_data.x->border_width
11372 - win_y
11373 - PIXEL_HEIGHT (f)
11374 - menubar_height
11375 + f->output_data.x->top_pos);
11376 }
2e365682 11377
3a35ab44
RS
11378 /* The left_pos and top_pos
11379 are now relative to the top and left screen edges,
11380 so the flags should correspond. */
7556890b 11381 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
11382}
11383
3a35ab44
RS
11384/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
11385 to really change the position, and 0 when calling from
11386 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
11387 position values). It is -1 when calling from x_set_frame_parameters,
11388 which means, do adjust for borders but don't change the gravity. */
3a35ab44 11389
dfcf069d 11390void
dc05a16b 11391x_set_offset (f, xoff, yoff, change_gravity)
f676886a 11392 struct frame *f;
dc6f92b8 11393 register int xoff, yoff;
dc05a16b 11394 int change_gravity;
dc6f92b8 11395{
4a4cbdd5
KH
11396 int modified_top, modified_left;
11397
aa3ff7c9 11398 if (change_gravity > 0)
3a35ab44 11399 {
7556890b
RS
11400 f->output_data.x->top_pos = yoff;
11401 f->output_data.x->left_pos = xoff;
11402 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 11403 if (xoff < 0)
7556890b 11404 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 11405 if (yoff < 0)
7556890b
RS
11406 f->output_data.x->size_hint_flags |= YNegative;
11407 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 11408 }
43bca5d5 11409 x_calc_absolute_position (f);
dc6f92b8
JB
11410
11411 BLOCK_INPUT;
c32cdd9a 11412 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 11413
7556890b
RS
11414 modified_left = f->output_data.x->left_pos;
11415 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
11416#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
11417 this seems to be unnecessary and incorrect. rms, 4/17/97. */
11418 /* It is a mystery why we need to add the border_width here
11419 when the frame is already visible, but experiment says we do. */
aa3ff7c9 11420 if (change_gravity != 0)
4a4cbdd5 11421 {
7556890b
RS
11422 modified_left += f->output_data.x->border_width;
11423 modified_top += f->output_data.x->border_width;
4a4cbdd5 11424 }
e73ec6fa 11425#endif
4a4cbdd5 11426
3afe33e7 11427#ifdef USE_X_TOOLKIT
7556890b 11428 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 11429 modified_left, modified_top);
3afe33e7 11430#else /* not USE_X_TOOLKIT */
334208b7 11431 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 11432 modified_left, modified_top);
3afe33e7 11433#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11434 UNBLOCK_INPUT;
11435}
11436
bc20ebbf
FP
11437/* Call this to change the size of frame F's x-window.
11438 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
11439 for this size change and subsequent size changes.
11440 Otherwise we leave the window gravity unchanged. */
dc6f92b8 11441
dfcf069d 11442void
bc20ebbf 11443x_set_window_size (f, change_gravity, cols, rows)
f676886a 11444 struct frame *f;
bc20ebbf 11445 int change_gravity;
b1c884c3 11446 int cols, rows;
dc6f92b8 11447{
06a2c219 11448#ifndef USE_X_TOOLKIT
dc6f92b8 11449 int pixelwidth, pixelheight;
06a2c219 11450#endif
dc6f92b8 11451
80fd1fe2 11452 BLOCK_INPUT;
aee9a898
RS
11453
11454#ifdef USE_X_TOOLKIT
3a20653d
RS
11455 {
11456 /* The x and y position of the widget is clobbered by the
11457 call to XtSetValues within EmacsFrameSetCharSize.
11458 This is a real kludge, but I don't understand Xt so I can't
11459 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
11460 int xpos = f->output_data.x->widget->core.x;
11461 int ypos = f->output_data.x->widget->core.y;
11462 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
11463 f->output_data.x->widget->core.x = xpos;
11464 f->output_data.x->widget->core.y = ypos;
3a20653d 11465 }
80fd1fe2
FP
11466
11467#else /* not USE_X_TOOLKIT */
11468
b1c884c3 11469 check_frame_size (f, &rows, &cols);
7556890b 11470 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
11471 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
11472 ? 0
11473 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 11474 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 11475 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219 11476 f->output_data.x->flags_areas_extra
110859fc 11477 = FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
11478 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
11479 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 11480
7556890b 11481 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 11482 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 11483
334208b7
RS
11484 XSync (FRAME_X_DISPLAY (f), False);
11485 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
11486 pixelwidth, pixelheight);
b1c884c3
JB
11487
11488 /* Now, strictly speaking, we can't be sure that this is accurate,
11489 but the window manager will get around to dealing with the size
11490 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
11491 ConfigureNotify event gets here.
11492
11493 We could just not bother storing any of this information here,
11494 and let the ConfigureNotify event set everything up, but that
fddd5ceb 11495 might be kind of confusing to the Lisp code, since size changes
dbc4e1c1 11496 wouldn't be reported in the frame parameters until some random
fddd5ceb
RS
11497 point in the future when the ConfigureNotify event arrives.
11498
11499 We pass 1 for DELAY since we can't run Lisp code inside of
11500 a BLOCK_INPUT. */
7d1e984f 11501 change_frame_size (f, rows, cols, 0, 1, 0);
b1c884c3
JB
11502 PIXEL_WIDTH (f) = pixelwidth;
11503 PIXEL_HEIGHT (f) = pixelheight;
11504
aee9a898
RS
11505 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
11506 receive in the ConfigureNotify event; if we get what we asked
11507 for, then the event won't cause the screen to become garbaged, so
11508 we have to make sure to do it here. */
11509 SET_FRAME_GARBAGED (f);
11510
11511 XFlush (FRAME_X_DISPLAY (f));
11512
11513#endif /* not USE_X_TOOLKIT */
11514
4d73d038 11515 /* If cursor was outside the new size, mark it as off. */
06a2c219 11516 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 11517
aee9a898
RS
11518 /* Clear out any recollection of where the mouse highlighting was,
11519 since it might be in a place that's outside the new frame size.
11520 Actually checking whether it is outside is a pain in the neck,
11521 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 11522 cancel_mouse_face (f);
dbc4e1c1 11523
dc6f92b8
JB
11524 UNBLOCK_INPUT;
11525}
dc6f92b8 11526\f
d047c4eb 11527/* Mouse warping. */
dc6f92b8 11528
9b378208 11529void
f676886a
JB
11530x_set_mouse_position (f, x, y)
11531 struct frame *f;
dc6f92b8
JB
11532 int x, y;
11533{
11534 int pix_x, pix_y;
11535
7556890b
RS
11536 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
11537 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
11538
11539 if (pix_x < 0) pix_x = 0;
11540 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
11541
11542 if (pix_y < 0) pix_y = 0;
11543 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
11544
11545 BLOCK_INPUT;
dc6f92b8 11546
334208b7
RS
11547 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11548 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
11549 UNBLOCK_INPUT;
11550}
11551
9b378208
RS
11552/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
11553
11554void
11555x_set_mouse_pixel_position (f, pix_x, pix_y)
11556 struct frame *f;
11557 int pix_x, pix_y;
11558{
11559 BLOCK_INPUT;
11560
334208b7
RS
11561 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
11562 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
11563 UNBLOCK_INPUT;
11564}
d047c4eb
KH
11565\f
11566/* focus shifting, raising and lowering. */
9b378208 11567
dfcf069d 11568void
f676886a
JB
11569x_focus_on_frame (f)
11570 struct frame *f;
dc6f92b8 11571{
1fb20991 11572#if 0 /* This proves to be unpleasant. */
f676886a 11573 x_raise_frame (f);
1fb20991 11574#endif
6d4238f3
JB
11575#if 0
11576 /* I don't think that the ICCCM allows programs to do things like this
11577 without the interaction of the window manager. Whatever you end up
f676886a 11578 doing with this code, do it to x_unfocus_frame too. */
334208b7 11579 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 11580 RevertToPointerRoot, CurrentTime);
c118dd06 11581#endif /* ! 0 */
dc6f92b8
JB
11582}
11583
dfcf069d 11584void
f676886a
JB
11585x_unfocus_frame (f)
11586 struct frame *f;
dc6f92b8 11587{
6d4238f3 11588#if 0
f676886a 11589 /* Look at the remarks in x_focus_on_frame. */
0f941935 11590 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 11591 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 11592 RevertToPointerRoot, CurrentTime);
c118dd06 11593#endif /* ! 0 */
dc6f92b8
JB
11594}
11595
f676886a 11596/* Raise frame F. */
dc6f92b8 11597
dfcf069d 11598void
f676886a
JB
11599x_raise_frame (f)
11600 struct frame *f;
dc6f92b8 11601{
3a88c238 11602 if (f->async_visible)
dc6f92b8
JB
11603 {
11604 BLOCK_INPUT;
3afe33e7 11605#ifdef USE_X_TOOLKIT
7556890b 11606 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11607#else /* not USE_X_TOOLKIT */
334208b7 11608 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11609#endif /* not USE_X_TOOLKIT */
334208b7 11610 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11611 UNBLOCK_INPUT;
11612 }
11613}
11614
f676886a 11615/* Lower frame F. */
dc6f92b8 11616
dfcf069d 11617void
f676886a
JB
11618x_lower_frame (f)
11619 struct frame *f;
dc6f92b8 11620{
3a88c238 11621 if (f->async_visible)
dc6f92b8
JB
11622 {
11623 BLOCK_INPUT;
3afe33e7 11624#ifdef USE_X_TOOLKIT
7556890b 11625 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 11626#else /* not USE_X_TOOLKIT */
334208b7 11627 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11628#endif /* not USE_X_TOOLKIT */
334208b7 11629 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
11630 UNBLOCK_INPUT;
11631 }
11632}
11633
dbc4e1c1 11634static void
6b0442dc 11635XTframe_raise_lower (f, raise_flag)
dbc4e1c1 11636 FRAME_PTR f;
6b0442dc 11637 int raise_flag;
dbc4e1c1 11638{
6b0442dc 11639 if (raise_flag)
dbc4e1c1
JB
11640 x_raise_frame (f);
11641 else
11642 x_lower_frame (f);
11643}
d047c4eb
KH
11644\f
11645/* Change of visibility. */
dc6f92b8 11646
9382638d
KH
11647/* This tries to wait until the frame is really visible.
11648 However, if the window manager asks the user where to position
11649 the frame, this will return before the user finishes doing that.
11650 The frame will not actually be visible at that time,
11651 but it will become visible later when the window manager
11652 finishes with it. */
11653
dfcf069d 11654void
f676886a
JB
11655x_make_frame_visible (f)
11656 struct frame *f;
dc6f92b8 11657{
990ba854 11658 Lisp_Object type;
1aa6072f 11659 int original_top, original_left;
dc6f92b8 11660
dc6f92b8 11661 BLOCK_INPUT;
dc6f92b8 11662
990ba854
RS
11663 type = x_icon_type (f);
11664 if (!NILP (type))
11665 x_bitmap_icon (f, type);
bdcd49ba 11666
f676886a 11667 if (! FRAME_VISIBLE_P (f))
90e65f07 11668 {
1aa6072f
RS
11669 /* We test FRAME_GARBAGED_P here to make sure we don't
11670 call x_set_offset a second time
11671 if we get to x_make_frame_visible a second time
11672 before the window gets really visible. */
11673 if (! FRAME_ICONIFIED_P (f)
11674 && ! f->output_data.x->asked_for_visible)
11675 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
11676
11677 f->output_data.x->asked_for_visible = 1;
11678
90e65f07 11679 if (! EQ (Vx_no_window_manager, Qt))
f676886a 11680 x_wm_set_window_state (f, NormalState);
3afe33e7 11681#ifdef USE_X_TOOLKIT
d7a38a2e 11682 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11683 XtMapWidget (f->output_data.x->widget);
3afe33e7 11684#else /* not USE_X_TOOLKIT */
7f9c7f94 11685 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 11686#endif /* not USE_X_TOOLKIT */
0134a210
RS
11687#if 0 /* This seems to bring back scroll bars in the wrong places
11688 if the window configuration has changed. They seem
11689 to come back ok without this. */
ab648270 11690 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 11691 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 11692#endif
90e65f07 11693 }
dc6f92b8 11694
334208b7 11695 XFlush (FRAME_X_DISPLAY (f));
90e65f07 11696
0dacf791
RS
11697 /* Synchronize to ensure Emacs knows the frame is visible
11698 before we do anything else. We do this loop with input not blocked
11699 so that incoming events are handled. */
11700 {
11701 Lisp_Object frame;
12ce2351 11702 int count;
28c01ffe
RS
11703 /* This must be before UNBLOCK_INPUT
11704 since events that arrive in response to the actions above
11705 will set it when they are handled. */
11706 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
11707
11708 original_left = f->output_data.x->left_pos;
11709 original_top = f->output_data.x->top_pos;
c0a04927
RS
11710
11711 /* This must come after we set COUNT. */
11712 UNBLOCK_INPUT;
11713
2745e6c4 11714 /* We unblock here so that arriving X events are processed. */
1aa6072f 11715
dcb07ae9
RS
11716 /* Now move the window back to where it was "supposed to be".
11717 But don't do it if the gravity is negative.
11718 When the gravity is negative, this uses a position
28c01ffe
RS
11719 that is 3 pixels too low. Perhaps that's really the border width.
11720
11721 Don't do this if the window has never been visible before,
11722 because the window manager may choose the position
11723 and we don't want to override it. */
1aa6072f 11724
4d3f5d9a 11725 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 11726 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 11727 && previously_visible)
1aa6072f 11728 {
2745e6c4
RS
11729 Drawable rootw;
11730 int x, y;
11731 unsigned int width, height, border, depth;
06a2c219 11732
1aa6072f 11733 BLOCK_INPUT;
9829ddba 11734
06a2c219
GM
11735 /* On some window managers (such as FVWM) moving an existing
11736 window, even to the same place, causes the window manager
11737 to introduce an offset. This can cause the window to move
11738 to an unexpected location. Check the geometry (a little
11739 slow here) and then verify that the window is in the right
11740 place. If the window is not in the right place, move it
11741 there, and take the potential window manager hit. */
2745e6c4
RS
11742 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11743 &rootw, &x, &y, &width, &height, &border, &depth);
11744
11745 if (original_left != x || original_top != y)
11746 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11747 original_left, original_top);
11748
1aa6072f
RS
11749 UNBLOCK_INPUT;
11750 }
9829ddba 11751
e0c1aef2 11752 XSETFRAME (frame, f);
c0a04927 11753
12ce2351
GM
11754 /* Wait until the frame is visible. Process X events until a
11755 MapNotify event has been seen, or until we think we won't get a
11756 MapNotify at all.. */
11757 for (count = input_signal_count + 10;
11758 input_signal_count < count && !FRAME_VISIBLE_P (f);)
2a6cf806 11759 {
12ce2351 11760 /* Force processing of queued events. */
334208b7 11761 x_sync (f);
12ce2351
GM
11762
11763 /* Machines that do polling rather than SIGIO have been
11764 observed to go into a busy-wait here. So we'll fake an
11765 alarm signal to let the handler know that there's something
11766 to be read. We used to raise a real alarm, but it seems
11767 that the handler isn't always enabled here. This is
11768 probably a bug. */
8b2f8d4e 11769 if (input_polling_used ())
3b2fa4e6 11770 {
12ce2351
GM
11771 /* It could be confusing if a real alarm arrives while
11772 processing the fake one. Turn it off and let the
11773 handler reset it. */
3e71d8f2 11774 extern void poll_for_input_1 P_ ((void));
bffcfca9
GM
11775 int old_poll_suppress_count = poll_suppress_count;
11776 poll_suppress_count = 1;
11777 poll_for_input_1 ();
11778 poll_suppress_count = old_poll_suppress_count;
3b2fa4e6 11779 }
12ce2351
GM
11780
11781 /* See if a MapNotify event has been processed. */
11782 FRAME_SAMPLE_VISIBILITY (f);
2a6cf806 11783 }
0dacf791 11784 }
dc6f92b8
JB
11785}
11786
06a2c219 11787/* Change from mapped state to withdrawn state. */
dc6f92b8 11788
d047c4eb
KH
11789/* Make the frame visible (mapped and not iconified). */
11790
dfcf069d 11791void
f676886a
JB
11792x_make_frame_invisible (f)
11793 struct frame *f;
dc6f92b8 11794{
546e6d5b
RS
11795 Window window;
11796
11797#ifdef USE_X_TOOLKIT
11798 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11799 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11800#else /* not USE_X_TOOLKIT */
11801 window = FRAME_X_WINDOW (f);
11802#endif /* not USE_X_TOOLKIT */
dc6f92b8 11803
9319ae23 11804 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11805 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11806 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11807
5627c40e 11808#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 11809 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 11810 return;
5627c40e 11811#endif
dc6f92b8
JB
11812
11813 BLOCK_INPUT;
c118dd06 11814
af31d76f
RS
11815 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11816 that the current position of the window is user-specified, rather than
11817 program-specified, so that when the window is mapped again, it will be
11818 placed at the same location, without forcing the user to position it
11819 by hand again (they have already done that once for this window.) */
c32cdd9a 11820 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 11821
c118dd06
JB
11822#ifdef HAVE_X11R4
11823
334208b7
RS
11824 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11825 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
11826 {
11827 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11828 error ("Can't notify window manager of window withdrawal");
c118dd06 11829 }
c118dd06 11830#else /* ! defined (HAVE_X11R4) */
16bd92ea 11831
c118dd06 11832 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
11833 if (! EQ (Vx_no_window_manager, Qt))
11834 {
16bd92ea 11835 XEvent unmap;
dc6f92b8 11836
16bd92ea 11837 unmap.xunmap.type = UnmapNotify;
546e6d5b 11838 unmap.xunmap.window = window;
334208b7 11839 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 11840 unmap.xunmap.from_configure = False;
334208b7
RS
11841 if (! XSendEvent (FRAME_X_DISPLAY (f),
11842 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 11843 False,
06a2c219 11844 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
11845 &unmap))
11846 {
11847 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11848 error ("Can't notify window manager of withdrawal");
16bd92ea 11849 }
dc6f92b8
JB
11850 }
11851
16bd92ea 11852 /* Unmap the window ourselves. Cheeky! */
334208b7 11853 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 11854#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 11855
5627c40e
RS
11856 /* We can't distinguish this from iconification
11857 just by the event that we get from the server.
11858 So we can't win using the usual strategy of letting
11859 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11860 and synchronize with the server to make sure we agree. */
11861 f->visible = 0;
11862 FRAME_ICONIFIED_P (f) = 0;
11863 f->async_visible = 0;
11864 f->async_iconified = 0;
11865
334208b7 11866 x_sync (f);
5627c40e 11867
dc6f92b8
JB
11868 UNBLOCK_INPUT;
11869}
11870
06a2c219 11871/* Change window state from mapped to iconified. */
dc6f92b8 11872
dfcf069d 11873void
f676886a
JB
11874x_iconify_frame (f)
11875 struct frame *f;
dc6f92b8 11876{
3afe33e7 11877 int result;
990ba854 11878 Lisp_Object type;
dc6f92b8 11879
9319ae23 11880 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11881 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11882 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11883
3a88c238 11884 if (f->async_iconified)
dc6f92b8
JB
11885 return;
11886
3afe33e7 11887 BLOCK_INPUT;
546e6d5b 11888
9af3143a
RS
11889 FRAME_SAMPLE_VISIBILITY (f);
11890
990ba854
RS
11891 type = x_icon_type (f);
11892 if (!NILP (type))
11893 x_bitmap_icon (f, type);
bdcd49ba
RS
11894
11895#ifdef USE_X_TOOLKIT
11896
546e6d5b
RS
11897 if (! FRAME_VISIBLE_P (f))
11898 {
11899 if (! EQ (Vx_no_window_manager, Qt))
11900 x_wm_set_window_state (f, IconicState);
11901 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11902 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
11903 /* The server won't give us any event to indicate
11904 that an invisible frame was changed to an icon,
11905 so we have to record it here. */
11906 f->iconified = 1;
1e6bc770 11907 f->visible = 1;
9cf30a30 11908 f->async_iconified = 1;
1e6bc770 11909 f->async_visible = 0;
546e6d5b
RS
11910 UNBLOCK_INPUT;
11911 return;
11912 }
11913
334208b7 11914 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 11915 XtWindow (f->output_data.x->widget),
334208b7 11916 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
11917 UNBLOCK_INPUT;
11918
11919 if (!result)
546e6d5b 11920 error ("Can't notify window manager of iconification");
3afe33e7
RS
11921
11922 f->async_iconified = 1;
1e6bc770
RS
11923 f->async_visible = 0;
11924
8c002a25
KH
11925
11926 BLOCK_INPUT;
334208b7 11927 XFlush (FRAME_X_DISPLAY (f));
8c002a25 11928 UNBLOCK_INPUT;
3afe33e7
RS
11929#else /* not USE_X_TOOLKIT */
11930
fd13dbb2
RS
11931 /* Make sure the X server knows where the window should be positioned,
11932 in case the user deiconifies with the window manager. */
11933 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 11934 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 11935
16bd92ea
JB
11936 /* Since we don't know which revision of X we're running, we'll use both
11937 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11938
11939 /* X11R4: send a ClientMessage to the window manager using the
11940 WM_CHANGE_STATE type. */
11941 {
11942 XEvent message;
58769bee 11943
c118dd06 11944 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 11945 message.xclient.type = ClientMessage;
334208b7 11946 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
11947 message.xclient.format = 32;
11948 message.xclient.data.l[0] = IconicState;
11949
334208b7
RS
11950 if (! XSendEvent (FRAME_X_DISPLAY (f),
11951 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
11952 False,
11953 SubstructureRedirectMask | SubstructureNotifyMask,
11954 &message))
dc6f92b8
JB
11955 {
11956 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11957 error ("Can't notify window manager of iconification");
dc6f92b8 11958 }
16bd92ea 11959 }
dc6f92b8 11960
58769bee 11961 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
11962 IconicState. */
11963 x_wm_set_window_state (f, IconicState);
dc6f92b8 11964
a9c00105
RS
11965 if (!FRAME_VISIBLE_P (f))
11966 {
11967 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 11968 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
11969 }
11970
3a88c238 11971 f->async_iconified = 1;
1e6bc770 11972 f->async_visible = 0;
dc6f92b8 11973
334208b7 11974 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 11975 UNBLOCK_INPUT;
8c002a25 11976#endif /* not USE_X_TOOLKIT */
dc6f92b8 11977}
d047c4eb 11978\f
c0ff3fab 11979/* Destroy the X window of frame F. */
dc6f92b8 11980
dfcf069d 11981void
c0ff3fab 11982x_destroy_window (f)
f676886a 11983 struct frame *f;
dc6f92b8 11984{
7f9c7f94
RS
11985 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11986
dc6f92b8 11987 BLOCK_INPUT;
c0ff3fab 11988
6186a4a0
RS
11989 /* If a display connection is dead, don't try sending more
11990 commands to the X server. */
11991 if (dpyinfo->display != 0)
11992 {
11993 if (f->output_data.x->icon_desc != 0)
11994 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf 11995#ifdef HAVE_X_I18N
f5d11644
GM
11996 if (FRAME_XIC (f))
11997 free_frame_xic (f);
31f41daf 11998#endif
6186a4a0 11999 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 12000#ifdef USE_X_TOOLKIT
06a2c219
GM
12001 if (f->output_data.x->widget)
12002 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 12003 free_frame_menubar (f);
3afe33e7
RS
12004#endif /* USE_X_TOOLKIT */
12005
3e71d8f2
GM
12006 unload_color (f, f->output_data.x->foreground_pixel);
12007 unload_color (f, f->output_data.x->background_pixel);
12008 unload_color (f, f->output_data.x->cursor_pixel);
12009 unload_color (f, f->output_data.x->cursor_foreground_pixel);
12010 unload_color (f, f->output_data.x->border_pixel);
12011 unload_color (f, f->output_data.x->mouse_pixel);
12012 if (f->output_data.x->scroll_bar_background_pixel != -1)
12013 unload_color (f, f->output_data.x->scroll_bar_background_pixel);
12014 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
12015 unload_color (f, f->output_data.x->scroll_bar_foreground_pixel);
12016 if (f->output_data.x->white_relief.allocated_p)
12017 unload_color (f, f->output_data.x->white_relief.pixel);
12018 if (f->output_data.x->black_relief.allocated_p)
12019 unload_color (f, f->output_data.x->black_relief.pixel);
12020
6186a4a0
RS
12021 free_frame_faces (f);
12022 XFlush (FRAME_X_DISPLAY (f));
12023 }
dc6f92b8 12024
df89d8a4 12025 if (f->output_data.x->saved_menu_event)
06a2c219 12026 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 12027
7556890b
RS
12028 xfree (f->output_data.x);
12029 f->output_data.x = 0;
0f941935
KH
12030 if (f == dpyinfo->x_focus_frame)
12031 dpyinfo->x_focus_frame = 0;
12032 if (f == dpyinfo->x_focus_event_frame)
12033 dpyinfo->x_focus_event_frame = 0;
12034 if (f == dpyinfo->x_highlight_frame)
12035 dpyinfo->x_highlight_frame = 0;
c0ff3fab 12036
7f9c7f94
RS
12037 dpyinfo->reference_count--;
12038
12039 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 12040 {
7f9c7f94
RS
12041 dpyinfo->mouse_face_beg_row
12042 = dpyinfo->mouse_face_beg_col = -1;
12043 dpyinfo->mouse_face_end_row
12044 = dpyinfo->mouse_face_end_col = -1;
12045 dpyinfo->mouse_face_window = Qnil;
21323706
RS
12046 dpyinfo->mouse_face_deferred_gc = 0;
12047 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 12048 }
0134a210 12049
c0ff3fab 12050 UNBLOCK_INPUT;
dc6f92b8
JB
12051}
12052\f
f451eb13
JB
12053/* Setting window manager hints. */
12054
af31d76f
RS
12055/* Set the normal size hints for the window manager, for frame F.
12056 FLAGS is the flags word to use--or 0 meaning preserve the flags
12057 that the window now has.
12058 If USER_POSITION is nonzero, we set the USPosition
12059 flag (this is useful when FLAGS is 0). */
6dba1858 12060
dfcf069d 12061void
af31d76f 12062x_wm_set_size_hint (f, flags, user_position)
f676886a 12063 struct frame *f;
af31d76f
RS
12064 long flags;
12065 int user_position;
dc6f92b8
JB
12066{
12067 XSizeHints size_hints;
3afe33e7
RS
12068
12069#ifdef USE_X_TOOLKIT
7e4f2521
FP
12070 Arg al[2];
12071 int ac = 0;
12072 Dimension widget_width, widget_height;
7556890b 12073 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 12074#else /* not USE_X_TOOLKIT */
c118dd06 12075 Window window = FRAME_X_WINDOW (f);
3afe33e7 12076#endif /* not USE_X_TOOLKIT */
dc6f92b8 12077
b72a58fd
RS
12078 /* Setting PMaxSize caused various problems. */
12079 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 12080
7556890b
RS
12081 size_hints.x = f->output_data.x->left_pos;
12082 size_hints.y = f->output_data.x->top_pos;
7553a6b7 12083
7e4f2521
FP
12084#ifdef USE_X_TOOLKIT
12085 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
12086 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 12087 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
12088 size_hints.height = widget_height;
12089 size_hints.width = widget_width;
12090#else /* not USE_X_TOOLKIT */
f676886a
JB
12091 size_hints.height = PIXEL_HEIGHT (f);
12092 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 12093#endif /* not USE_X_TOOLKIT */
7553a6b7 12094
7556890b
RS
12095 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
12096 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
12097 size_hints.max_width
12098 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
12099 size_hints.max_height
12100 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 12101
d067ea8b
KH
12102 /* Calculate the base and minimum sizes.
12103
12104 (When we use the X toolkit, we don't do it here.
12105 Instead we copy the values that the widgets are using, below.) */
12106#ifndef USE_X_TOOLKIT
b1c884c3 12107 {
b0342f17 12108 int base_width, base_height;
0134a210 12109 int min_rows = 0, min_cols = 0;
b0342f17 12110
f451eb13
JB
12111 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
12112 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 12113
0134a210 12114 check_frame_size (f, &min_rows, &min_cols);
b0342f17 12115
0134a210
RS
12116 /* The window manager uses the base width hints to calculate the
12117 current number of rows and columns in the frame while
12118 resizing; min_width and min_height aren't useful for this
12119 purpose, since they might not give the dimensions for a
12120 zero-row, zero-column frame.
58769bee 12121
0134a210
RS
12122 We use the base_width and base_height members if we have
12123 them; otherwise, we set the min_width and min_height members
12124 to the size for a zero x zero frame. */
b0342f17
JB
12125
12126#ifdef HAVE_X11R4
0134a210
RS
12127 size_hints.flags |= PBaseSize;
12128 size_hints.base_width = base_width;
12129 size_hints.base_height = base_height;
12130 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
12131 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 12132#else
0134a210
RS
12133 size_hints.min_width = base_width;
12134 size_hints.min_height = base_height;
b0342f17 12135#endif
b1c884c3 12136 }
dc6f92b8 12137
d067ea8b 12138 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 12139 if (flags)
dc6f92b8 12140 {
d067ea8b
KH
12141 size_hints.flags |= flags;
12142 goto no_read;
12143 }
12144#endif /* not USE_X_TOOLKIT */
12145
12146 {
12147 XSizeHints hints; /* Sometimes I hate X Windows... */
12148 long supplied_return;
12149 int value;
af31d76f
RS
12150
12151#ifdef HAVE_X11R4
d067ea8b
KH
12152 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
12153 &supplied_return);
af31d76f 12154#else
d067ea8b 12155 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 12156#endif
58769bee 12157
d067ea8b
KH
12158#ifdef USE_X_TOOLKIT
12159 size_hints.base_height = hints.base_height;
12160 size_hints.base_width = hints.base_width;
12161 size_hints.min_height = hints.min_height;
12162 size_hints.min_width = hints.min_width;
12163#endif
12164
12165 if (flags)
12166 size_hints.flags |= flags;
12167 else
12168 {
12169 if (value == 0)
12170 hints.flags = 0;
12171 if (hints.flags & PSize)
12172 size_hints.flags |= PSize;
12173 if (hints.flags & PPosition)
12174 size_hints.flags |= PPosition;
12175 if (hints.flags & USPosition)
12176 size_hints.flags |= USPosition;
12177 if (hints.flags & USSize)
12178 size_hints.flags |= USSize;
12179 }
12180 }
12181
06a2c219 12182#ifndef USE_X_TOOLKIT
d067ea8b 12183 no_read:
06a2c219 12184#endif
0134a210 12185
af31d76f 12186#ifdef PWinGravity
7556890b 12187 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 12188 size_hints.flags |= PWinGravity;
dc05a16b 12189
af31d76f 12190 if (user_position)
6dba1858 12191 {
af31d76f
RS
12192 size_hints.flags &= ~ PPosition;
12193 size_hints.flags |= USPosition;
6dba1858 12194 }
2554751d 12195#endif /* PWinGravity */
6dba1858 12196
b0342f17 12197#ifdef HAVE_X11R4
334208b7 12198 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12199#else
334208b7 12200 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 12201#endif
dc6f92b8
JB
12202}
12203
12204/* Used for IconicState or NormalState */
06a2c219 12205
dfcf069d 12206void
f676886a
JB
12207x_wm_set_window_state (f, state)
12208 struct frame *f;
dc6f92b8
JB
12209 int state;
12210{
3afe33e7 12211#ifdef USE_X_TOOLKIT
546e6d5b
RS
12212 Arg al[1];
12213
12214 XtSetArg (al[0], XtNinitialState, state);
7556890b 12215 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 12216#else /* not USE_X_TOOLKIT */
c118dd06 12217 Window window = FRAME_X_WINDOW (f);
dc6f92b8 12218
7556890b
RS
12219 f->output_data.x->wm_hints.flags |= StateHint;
12220 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 12221
7556890b 12222 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 12223#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12224}
12225
dfcf069d 12226void
7f2ae036 12227x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 12228 struct frame *f;
7f2ae036 12229 int pixmap_id;
dc6f92b8 12230{
d2bd6bc4
RS
12231 Pixmap icon_pixmap;
12232
06a2c219 12233#ifndef USE_X_TOOLKIT
c118dd06 12234 Window window = FRAME_X_WINDOW (f);
75231bad 12235#endif
dc6f92b8 12236
7f2ae036 12237 if (pixmap_id > 0)
dbc4e1c1 12238 {
d2bd6bc4 12239 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 12240 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
12241 }
12242 else
68568555
RS
12243 {
12244 /* It seems there is no way to turn off use of an icon pixmap.
12245 The following line does it, only if no icon has yet been created,
12246 for some window managers. But with mwm it crashes.
12247 Some people say it should clear the IconPixmapHint bit in this case,
12248 but that doesn't work, and the X consortium said it isn't the
12249 right thing at all. Since there is no way to win,
12250 best to explicitly give up. */
12251#if 0
12252 f->output_data.x->wm_hints.icon_pixmap = None;
12253#else
12254 return;
12255#endif
12256 }
b1c884c3 12257
d2bd6bc4
RS
12258#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
12259
12260 {
12261 Arg al[1];
12262 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
12263 XtSetValues (f->output_data.x->widget, al, 1);
12264 }
12265
12266#else /* not USE_X_TOOLKIT */
12267
7556890b
RS
12268 f->output_data.x->wm_hints.flags |= IconPixmapHint;
12269 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
12270
12271#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
12272}
12273
dfcf069d 12274void
f676886a
JB
12275x_wm_set_icon_position (f, icon_x, icon_y)
12276 struct frame *f;
dc6f92b8
JB
12277 int icon_x, icon_y;
12278{
75231bad 12279#ifdef USE_X_TOOLKIT
7556890b 12280 Window window = XtWindow (f->output_data.x->widget);
75231bad 12281#else
c118dd06 12282 Window window = FRAME_X_WINDOW (f);
75231bad 12283#endif
dc6f92b8 12284
7556890b
RS
12285 f->output_data.x->wm_hints.flags |= IconPositionHint;
12286 f->output_data.x->wm_hints.icon_x = icon_x;
12287 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 12288
7556890b 12289 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
12290}
12291
12292\f
06a2c219
GM
12293/***********************************************************************
12294 Fonts
12295 ***********************************************************************/
dc43ef94
KH
12296
12297/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 12298
dc43ef94
KH
12299struct font_info *
12300x_get_font_info (f, font_idx)
12301 FRAME_PTR f;
12302 int font_idx;
12303{
12304 return (FRAME_X_FONT_TABLE (f) + font_idx);
12305}
12306
12307
12308/* Return a list of names of available fonts matching PATTERN on frame
12309 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
12310 to be listed. Frame F NULL means we have not yet created any
12311 frame on X, and consult the first display in x_display_list.
12312 MAXNAMES sets a limit on how many fonts to match. */
12313
12314Lisp_Object
12315x_list_fonts (f, pattern, size, maxnames)
12316 FRAME_PTR f;
12317 Lisp_Object pattern;
12318 int size;
12319 int maxnames;
12320{
06a2c219
GM
12321 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
12322 Lisp_Object tem, second_best;
dc43ef94 12323 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 12324 int try_XLoadQueryFont = 0;
53ca4657 12325 int count;
dc43ef94 12326
6b0efe73 12327 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
12328 if (NILP (patterns))
12329 patterns = Fcons (pattern, Qnil);
81ba44e5 12330
09c6077f
KH
12331 if (maxnames == 1 && !size)
12332 /* We can return any single font matching PATTERN. */
12333 try_XLoadQueryFont = 1;
9a32686f 12334
8e713be6 12335 for (; CONSP (patterns); patterns = XCDR (patterns))
dc43ef94 12336 {
dc43ef94 12337 int num_fonts;
3e71d8f2 12338 char **names = NULL;
dc43ef94 12339
8e713be6 12340 pattern = XCAR (patterns);
536f4067
RS
12341 /* See if we cached the result for this particular query.
12342 The cache is an alist of the form:
12343 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
12344 */
8e713be6 12345 if (f && (tem = XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element),
b5210ea7
KH
12346 key = Fcons (pattern, make_number (maxnames)),
12347 !NILP (list = Fassoc (key, tem))))
12348 {
12349 list = Fcdr_safe (list);
12350 /* We have a cashed list. Don't have to get the list again. */
12351 goto label_cached;
12352 }
12353
12354 /* At first, put PATTERN in the cache. */
09c6077f 12355
dc43ef94 12356 BLOCK_INPUT;
17d85edc
KH
12357 count = x_catch_errors (dpy);
12358
09c6077f
KH
12359 if (try_XLoadQueryFont)
12360 {
12361 XFontStruct *font;
12362 unsigned long value;
12363
12364 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
12365 if (x_had_errors_p (dpy))
12366 {
12367 /* This error is perhaps due to insufficient memory on X
12368 server. Let's just ignore it. */
12369 font = NULL;
12370 x_clear_errors (dpy);
12371 }
12372
09c6077f
KH
12373 if (font
12374 && XGetFontProperty (font, XA_FONT, &value))
12375 {
12376 char *name = (char *) XGetAtomName (dpy, (Atom) value);
12377 int len = strlen (name);
01c752b5 12378 char *tmp;
09c6077f 12379
6f6512e8
KH
12380 /* If DXPC (a Differential X Protocol Compressor)
12381 Ver.3.7 is running, XGetAtomName will return null
12382 string. We must avoid such a name. */
12383 if (len == 0)
12384 try_XLoadQueryFont = 0;
12385 else
12386 {
12387 num_fonts = 1;
12388 names = (char **) alloca (sizeof (char *));
12389 /* Some systems only allow alloca assigned to a
12390 simple var. */
12391 tmp = (char *) alloca (len + 1); names[0] = tmp;
12392 bcopy (name, names[0], len + 1);
12393 XFree (name);
12394 }
09c6077f
KH
12395 }
12396 else
12397 try_XLoadQueryFont = 0;
a083fd23
RS
12398
12399 if (font)
12400 XFreeFont (dpy, font);
09c6077f
KH
12401 }
12402
12403 if (!try_XLoadQueryFont)
17d85edc
KH
12404 {
12405 /* We try at least 10 fonts because XListFonts will return
12406 auto-scaled fonts at the head. */
12407 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
12408 &num_fonts);
12409 if (x_had_errors_p (dpy))
12410 {
12411 /* This error is perhaps due to insufficient memory on X
12412 server. Let's just ignore it. */
12413 names = NULL;
12414 x_clear_errors (dpy);
12415 }
12416 }
12417
12418 x_uncatch_errors (dpy, count);
dc43ef94
KH
12419 UNBLOCK_INPUT;
12420
12421 if (names)
12422 {
12423 int i;
dc43ef94
KH
12424
12425 /* Make a list of all the fonts we got back.
12426 Store that in the font cache for the display. */
12427 for (i = 0; i < num_fonts; i++)
12428 {
06a2c219 12429 int width = 0;
dc43ef94 12430 char *p = names[i];
06a2c219
GM
12431 int average_width = -1, dashes = 0;
12432
dc43ef94 12433 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
12434 14 dashes, and the field value following 12th dash
12435 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
12436 is usually too ugly to be used for editing. Let's
12437 ignore it. */
dc43ef94
KH
12438 while (*p)
12439 if (*p++ == '-')
12440 {
12441 dashes++;
12442 if (dashes == 7) /* PIXEL_SIZE field */
12443 width = atoi (p);
12444 else if (dashes == 12) /* AVERAGE_WIDTH field */
12445 average_width = atoi (p);
12446 }
12447 if (dashes < 14 || average_width != 0)
12448 {
12449 tem = build_string (names[i]);
12450 if (NILP (Fassoc (tem, list)))
12451 {
12452 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
12453 && ((fast_c_string_match_ignore_case
12454 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
12455 >= 0))
12456 /* We can set the value of PIXEL_SIZE to the
b5210ea7 12457 width of this font. */
dc43ef94
KH
12458 list = Fcons (Fcons (tem, make_number (width)), list);
12459 else
12460 /* For the moment, width is not known. */
12461 list = Fcons (Fcons (tem, Qnil), list);
12462 }
12463 }
12464 }
09c6077f
KH
12465 if (!try_XLoadQueryFont)
12466 XFreeFontNames (names);
dc43ef94
KH
12467 }
12468
b5210ea7 12469 /* Now store the result in the cache. */
dc43ef94 12470 if (f != NULL)
8e713be6 12471 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element)
dc43ef94 12472 = Fcons (Fcons (key, list),
8e713be6 12473 XCDR (FRAME_X_DISPLAY_INFO (f)->name_list_element));
dc43ef94 12474
b5210ea7
KH
12475 label_cached:
12476 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 12477
b5210ea7
KH
12478 newlist = second_best = Qnil;
12479 /* Make a list of the fonts that have the right width. */
8e713be6 12480 for (; CONSP (list); list = XCDR (list))
b5210ea7 12481 {
536f4067
RS
12482 int found_size;
12483
8e713be6 12484 tem = XCAR (list);
dc43ef94 12485
8e713be6 12486 if (!CONSP (tem) || NILP (XCAR (tem)))
b5210ea7
KH
12487 continue;
12488 if (!size)
12489 {
8e713be6 12490 newlist = Fcons (XCAR (tem), newlist);
b5210ea7
KH
12491 continue;
12492 }
dc43ef94 12493
8e713be6 12494 if (!INTEGERP (XCDR (tem)))
dc43ef94 12495 {
b5210ea7
KH
12496 /* Since we have not yet known the size of this font, we
12497 must try slow function call XLoadQueryFont. */
dc43ef94
KH
12498 XFontStruct *thisinfo;
12499
12500 BLOCK_INPUT;
17d85edc 12501 count = x_catch_errors (dpy);
dc43ef94 12502 thisinfo = XLoadQueryFont (dpy,
8e713be6 12503 XSTRING (XCAR (tem))->data);
17d85edc
KH
12504 if (x_had_errors_p (dpy))
12505 {
12506 /* This error is perhaps due to insufficient memory on X
12507 server. Let's just ignore it. */
12508 thisinfo = NULL;
12509 x_clear_errors (dpy);
12510 }
12511 x_uncatch_errors (dpy, count);
dc43ef94
KH
12512 UNBLOCK_INPUT;
12513
12514 if (thisinfo)
12515 {
8e713be6 12516 XCDR (tem)
536f4067
RS
12517 = (thisinfo->min_bounds.width == 0
12518 ? make_number (0)
12519 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
12520 XFreeFont (dpy, thisinfo);
12521 }
12522 else
b5210ea7 12523 /* For unknown reason, the previous call of XListFont had
06a2c219 12524 returned a font which can't be opened. Record the size
b5210ea7 12525 as 0 not to try to open it again. */
8e713be6 12526 XCDR (tem) = make_number (0);
dc43ef94 12527 }
536f4067 12528
8e713be6 12529 found_size = XINT (XCDR (tem));
536f4067 12530 if (found_size == size)
8e713be6 12531 newlist = Fcons (XCAR (tem), newlist);
536f4067 12532 else if (found_size > 0)
b5210ea7 12533 {
536f4067 12534 if (NILP (second_best))
b5210ea7 12535 second_best = tem;
536f4067
RS
12536 else if (found_size < size)
12537 {
8e713be6
KR
12538 if (XINT (XCDR (second_best)) > size
12539 || XINT (XCDR (second_best)) < found_size)
536f4067
RS
12540 second_best = tem;
12541 }
12542 else
12543 {
8e713be6
KR
12544 if (XINT (XCDR (second_best)) > size
12545 && XINT (XCDR (second_best)) > found_size)
536f4067
RS
12546 second_best = tem;
12547 }
b5210ea7
KH
12548 }
12549 }
12550 if (!NILP (newlist))
12551 break;
12552 else if (!NILP (second_best))
12553 {
8e713be6 12554 newlist = Fcons (XCAR (second_best), Qnil);
b5210ea7 12555 break;
dc43ef94 12556 }
dc43ef94
KH
12557 }
12558
12559 return newlist;
12560}
12561
06a2c219
GM
12562
12563#if GLYPH_DEBUG
12564
12565/* Check that FONT is valid on frame F. It is if it can be found in F's
12566 font table. */
12567
12568static void
12569x_check_font (f, font)
12570 struct frame *f;
12571 XFontStruct *font;
12572{
12573 int i;
12574 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12575
12576 xassert (font != NULL);
12577
12578 for (i = 0; i < dpyinfo->n_fonts; i++)
12579 if (dpyinfo->font_table[i].name
12580 && font == dpyinfo->font_table[i].font)
12581 break;
12582
12583 xassert (i < dpyinfo->n_fonts);
12584}
12585
12586#endif /* GLYPH_DEBUG != 0 */
12587
12588/* Set *W to the minimum width, *H to the minimum font height of FONT.
12589 Note: There are (broken) X fonts out there with invalid XFontStruct
12590 min_bounds contents. For example, handa@etl.go.jp reports that
12591 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
12592 have font->min_bounds.width == 0. */
12593
12594static INLINE void
12595x_font_min_bounds (font, w, h)
12596 XFontStruct *font;
12597 int *w, *h;
12598{
12599 *h = FONT_HEIGHT (font);
12600 *w = font->min_bounds.width;
12601
12602 /* Try to handle the case where FONT->min_bounds has invalid
12603 contents. Since the only font known to have invalid min_bounds
12604 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
12605 if (*w <= 0)
12606 *w = font->max_bounds.width;
12607}
12608
12609
12610/* Compute the smallest character width and smallest font height over
12611 all fonts available on frame F. Set the members smallest_char_width
12612 and smallest_font_height in F's x_display_info structure to
12613 the values computed. Value is non-zero if smallest_font_height or
12614 smallest_char_width become smaller than they were before. */
12615
12616static int
12617x_compute_min_glyph_bounds (f)
12618 struct frame *f;
12619{
12620 int i;
12621 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12622 XFontStruct *font;
12623 int old_width = dpyinfo->smallest_char_width;
12624 int old_height = dpyinfo->smallest_font_height;
12625
12626 dpyinfo->smallest_font_height = 100000;
12627 dpyinfo->smallest_char_width = 100000;
12628
12629 for (i = 0; i < dpyinfo->n_fonts; ++i)
12630 if (dpyinfo->font_table[i].name)
12631 {
12632 struct font_info *fontp = dpyinfo->font_table + i;
12633 int w, h;
12634
12635 font = (XFontStruct *) fontp->font;
12636 xassert (font != (XFontStruct *) ~0);
12637 x_font_min_bounds (font, &w, &h);
12638
12639 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
12640 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
12641 }
12642
12643 xassert (dpyinfo->smallest_char_width > 0
12644 && dpyinfo->smallest_font_height > 0);
12645
12646 return (dpyinfo->n_fonts == 1
12647 || dpyinfo->smallest_char_width < old_width
12648 || dpyinfo->smallest_font_height < old_height);
12649}
12650
12651
dc43ef94
KH
12652/* Load font named FONTNAME of the size SIZE for frame F, and return a
12653 pointer to the structure font_info while allocating it dynamically.
12654 If SIZE is 0, load any size of font.
12655 If loading is failed, return NULL. */
12656
12657struct font_info *
12658x_load_font (f, fontname, size)
12659 struct frame *f;
12660 register char *fontname;
12661 int size;
12662{
12663 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12664 Lisp_Object font_names;
d645aaa4 12665 int count;
dc43ef94
KH
12666
12667 /* Get a list of all the fonts that match this name. Once we
12668 have a list of matching fonts, we compare them against the fonts
12669 we already have by comparing names. */
09c6077f 12670 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
12671
12672 if (!NILP (font_names))
12673 {
12674 Lisp_Object tail;
12675 int i;
12676
12677 for (i = 0; i < dpyinfo->n_fonts; i++)
8e713be6 12678 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
06a2c219
GM
12679 if (dpyinfo->font_table[i].name
12680 && (!strcmp (dpyinfo->font_table[i].name,
8e713be6 12681 XSTRING (XCAR (tail))->data)
06a2c219 12682 || !strcmp (dpyinfo->font_table[i].full_name,
8e713be6 12683 XSTRING (XCAR (tail))->data)))
dc43ef94
KH
12684 return (dpyinfo->font_table + i);
12685 }
12686
12687 /* Load the font and add it to the table. */
12688 {
12689 char *full_name;
12690 XFontStruct *font;
12691 struct font_info *fontp;
12692 unsigned long value;
06a2c219 12693 int i;
dc43ef94 12694
2da424f1
KH
12695 /* If we have found fonts by x_list_font, load one of them. If
12696 not, we still try to load a font by the name given as FONTNAME
12697 because XListFonts (called in x_list_font) of some X server has
12698 a bug of not finding a font even if the font surely exists and
12699 is loadable by XLoadQueryFont. */
e1d6d5b9 12700 if (size > 0 && !NILP (font_names))
8e713be6 12701 fontname = (char *) XSTRING (XCAR (font_names))->data;
dc43ef94
KH
12702
12703 BLOCK_INPUT;
d645aaa4 12704 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 12705 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
12706 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
12707 {
12708 /* This error is perhaps due to insufficient memory on X
12709 server. Let's just ignore it. */
12710 font = NULL;
12711 x_clear_errors (FRAME_X_DISPLAY (f));
12712 }
12713 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 12714 UNBLOCK_INPUT;
b5210ea7 12715 if (!font)
dc43ef94
KH
12716 return NULL;
12717
06a2c219
GM
12718 /* Find a free slot in the font table. */
12719 for (i = 0; i < dpyinfo->n_fonts; ++i)
12720 if (dpyinfo->font_table[i].name == NULL)
12721 break;
12722
12723 /* If no free slot found, maybe enlarge the font table. */
12724 if (i == dpyinfo->n_fonts
12725 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 12726 {
06a2c219
GM
12727 int sz;
12728 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
12729 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 12730 dpyinfo->font_table
06a2c219 12731 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
12732 }
12733
06a2c219
GM
12734 fontp = dpyinfo->font_table + i;
12735 if (i == dpyinfo->n_fonts)
12736 ++dpyinfo->n_fonts;
dc43ef94
KH
12737
12738 /* Now fill in the slots of *FONTP. */
12739 BLOCK_INPUT;
12740 fontp->font = font;
06a2c219 12741 fontp->font_idx = i;
dc43ef94
KH
12742 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
12743 bcopy (fontname, fontp->name, strlen (fontname) + 1);
12744
12745 /* Try to get the full name of FONT. Put it in FULL_NAME. */
12746 full_name = 0;
12747 if (XGetFontProperty (font, XA_FONT, &value))
12748 {
12749 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
12750 char *p = name;
12751 int dashes = 0;
12752
12753 /* Count the number of dashes in the "full name".
12754 If it is too few, this isn't really the font's full name,
12755 so don't use it.
12756 In X11R4, the fonts did not come with their canonical names
12757 stored in them. */
12758 while (*p)
12759 {
12760 if (*p == '-')
12761 dashes++;
12762 p++;
12763 }
12764
12765 if (dashes >= 13)
12766 {
12767 full_name = (char *) xmalloc (p - name + 1);
12768 bcopy (name, full_name, p - name + 1);
12769 }
12770
12771 XFree (name);
12772 }
12773
12774 if (full_name != 0)
12775 fontp->full_name = full_name;
12776 else
12777 fontp->full_name = fontp->name;
12778
12779 fontp->size = font->max_bounds.width;
d5749adb
KH
12780 fontp->height = FONT_HEIGHT (font);
12781 {
12782 /* For some font, ascent and descent in max_bounds field is
12783 larger than the above value. */
12784 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
12785 if (max_height > fontp->height)
74848a96 12786 fontp->height = max_height;
d5749adb 12787 }
dc43ef94 12788
2da424f1
KH
12789 if (NILP (font_names))
12790 {
12791 /* We come here because of a bug of XListFonts mentioned at
12792 the head of this block. Let's store this information in
12793 the cache for x_list_fonts. */
12794 Lisp_Object lispy_name = build_string (fontname);
12795 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12796
8e713be6 12797 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12798 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12799 Fcons (Fcons (lispy_full_name,
12800 make_number (fontp->size)),
12801 Qnil)),
8e713be6 12802 XCDR (dpyinfo->name_list_element));
2da424f1 12803 if (full_name)
8e713be6 12804 XCDR (dpyinfo->name_list_element)
2da424f1
KH
12805 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12806 Fcons (Fcons (lispy_full_name,
12807 make_number (fontp->size)),
12808 Qnil)),
8e713be6 12809 XCDR (dpyinfo->name_list_element));
2da424f1
KH
12810 }
12811
dc43ef94
KH
12812 /* The slot `encoding' specifies how to map a character
12813 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ee569018
KH
12814 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
12815 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
8ff102bd 12816 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 12817 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
12818 which is never used by any charset. If mapping can't be
12819 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
12820 fontp->encoding[1]
12821 = (font->max_byte1 == 0
12822 /* 1-byte font */
12823 ? (font->min_char_or_byte2 < 0x80
12824 ? (font->max_char_or_byte2 < 0x80
12825 ? 0 /* 0x20..0x7F */
8ff102bd 12826 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
12827 : 1) /* 0xA0..0xFF */
12828 /* 2-byte font */
12829 : (font->min_byte1 < 0x80
12830 ? (font->max_byte1 < 0x80
12831 ? (font->min_char_or_byte2 < 0x80
12832 ? (font->max_char_or_byte2 < 0x80
12833 ? 0 /* 0x2020..0x7F7F */
8ff102bd 12834 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 12835 : 3) /* 0x20A0..0x7FFF */
8ff102bd 12836 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
12837 : (font->min_char_or_byte2 < 0x80
12838 ? (font->max_char_or_byte2 < 0x80
12839 ? 2 /* 0xA020..0xFF7F */
8ff102bd 12840 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
12841 : 1))); /* 0xA0A0..0xFFFF */
12842
12843 fontp->baseline_offset
12844 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12845 ? (long) value : 0);
12846 fontp->relative_compose
12847 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12848 ? (long) value : 0);
f78798df
KH
12849 fontp->default_ascent
12850 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12851 ? (long) value : 0);
dc43ef94 12852
06a2c219
GM
12853 /* Set global flag fonts_changed_p to non-zero if the font loaded
12854 has a character with a smaller width than any other character
12855 before, or if the font loaded has a smalle>r height than any
12856 other font loaded before. If this happens, it will make a
12857 glyph matrix reallocation necessary. */
12858 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 12859 UNBLOCK_INPUT;
dc43ef94
KH
12860 return fontp;
12861 }
12862}
12863
06a2c219
GM
12864
12865/* Return a pointer to struct font_info of a font named FONTNAME for
12866 frame F. If no such font is loaded, return NULL. */
12867
dc43ef94
KH
12868struct font_info *
12869x_query_font (f, fontname)
12870 struct frame *f;
12871 register char *fontname;
12872{
12873 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12874 int i;
12875
12876 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
12877 if (dpyinfo->font_table[i].name
12878 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12879 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
12880 return (dpyinfo->font_table + i);
12881 return NULL;
12882}
12883
06a2c219
GM
12884
12885/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
12886 `encoder' of the structure. */
12887
12888void
12889x_find_ccl_program (fontp)
12890 struct font_info *fontp;
12891{
a42f54e6 12892 Lisp_Object list, elt;
a6582676 12893
8e713be6 12894 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
a6582676 12895 {
8e713be6 12896 elt = XCAR (list);
a6582676 12897 if (CONSP (elt)
8e713be6
KR
12898 && STRINGP (XCAR (elt))
12899 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
a6582676 12900 >= 0))
a42f54e6
KH
12901 break;
12902 }
12903 if (! NILP (list))
12904 {
d27f8ca7
KH
12905 struct ccl_program *ccl
12906 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6 12907
8e713be6 12908 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
a42f54e6
KH
12909 xfree (ccl);
12910 else
12911 fontp->font_encoder = ccl;
a6582676
KH
12912 }
12913}
12914
06a2c219 12915
dc43ef94 12916\f
06a2c219
GM
12917/***********************************************************************
12918 Initialization
12919 ***********************************************************************/
f451eb13 12920
3afe33e7
RS
12921#ifdef USE_X_TOOLKIT
12922static XrmOptionDescRec emacs_options[] = {
12923 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12924 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12925
12926 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12927 XrmoptionSepArg, NULL},
12928 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12929
12930 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12931 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12932 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12933 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12934 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12935 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12936 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12937};
12938#endif /* USE_X_TOOLKIT */
12939
7a13e894
RS
12940static int x_initialized;
12941
29b38361
KH
12942#ifdef MULTI_KBOARD
12943/* Test whether two display-name strings agree up to the dot that separates
12944 the screen number from the server number. */
12945static int
12946same_x_server (name1, name2)
12947 char *name1, *name2;
12948{
12949 int seen_colon = 0;
cf591cc1
RS
12950 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12951 int system_name_length = strlen (system_name);
12952 int length_until_period = 0;
12953
12954 while (system_name[length_until_period] != 0
12955 && system_name[length_until_period] != '.')
12956 length_until_period++;
12957
12958 /* Treat `unix' like an empty host name. */
12959 if (! strncmp (name1, "unix:", 5))
12960 name1 += 4;
12961 if (! strncmp (name2, "unix:", 5))
12962 name2 += 4;
12963 /* Treat this host's name like an empty host name. */
12964 if (! strncmp (name1, system_name, system_name_length)
12965 && name1[system_name_length] == ':')
12966 name1 += system_name_length;
12967 if (! strncmp (name2, system_name, system_name_length)
12968 && name2[system_name_length] == ':')
12969 name2 += system_name_length;
12970 /* Treat this host's domainless name like an empty host name. */
12971 if (! strncmp (name1, system_name, length_until_period)
12972 && name1[length_until_period] == ':')
12973 name1 += length_until_period;
12974 if (! strncmp (name2, system_name, length_until_period)
12975 && name2[length_until_period] == ':')
12976 name2 += length_until_period;
12977
29b38361
KH
12978 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12979 {
12980 if (*name1 == ':')
12981 seen_colon++;
12982 if (seen_colon && *name1 == '.')
12983 return 1;
12984 }
12985 return (seen_colon
12986 && (*name1 == '.' || *name1 == '\0')
12987 && (*name2 == '.' || *name2 == '\0'));
12988}
12989#endif
12990
334208b7 12991struct x_display_info *
1f8255f2 12992x_term_init (display_name, xrm_option, resource_name)
334208b7 12993 Lisp_Object display_name;
1f8255f2
RS
12994 char *xrm_option;
12995 char *resource_name;
dc6f92b8 12996{
334208b7 12997 int connection;
7a13e894 12998 Display *dpy;
334208b7
RS
12999 struct x_display_info *dpyinfo;
13000 XrmDatabase xrdb;
13001
60439948
KH
13002 BLOCK_INPUT;
13003
7a13e894
RS
13004 if (!x_initialized)
13005 {
13006 x_initialize ();
13007 x_initialized = 1;
13008 }
dc6f92b8 13009
3afe33e7 13010#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
13011 /* weiner@footloose.sps.mot.com reports that this causes
13012 errors with X11R5:
13013 X protocol error: BadAtom (invalid Atom parameter)
13014 on protocol request 18skiloaf.
13015 So let's not use it until R6. */
13016#ifdef HAVE_X11XTR6
bdcd49ba
RS
13017 XtSetLanguageProc (NULL, NULL, NULL);
13018#endif
13019
7f9c7f94
RS
13020 {
13021 int argc = 0;
13022 char *argv[3];
13023
13024 argv[0] = "";
13025 argc = 1;
13026 if (xrm_option)
13027 {
13028 argv[argc++] = "-xrm";
13029 argv[argc++] = xrm_option;
13030 }
13031 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
13032 resource_name, EMACS_CLASS,
13033 emacs_options, XtNumber (emacs_options),
13034 &argc, argv);
39d8bb4d
KH
13035
13036#ifdef HAVE_X11XTR6
10537cb1 13037 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 13038 fixup_locale ();
39d8bb4d 13039#endif
7f9c7f94 13040 }
3afe33e7
RS
13041
13042#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
13043#ifdef HAVE_X11R5
13044 XSetLocaleModifiers ("");
13045#endif
7a13e894 13046 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 13047#endif /* not USE_X_TOOLKIT */
334208b7 13048
7a13e894
RS
13049 /* Detect failure. */
13050 if (dpy == 0)
60439948
KH
13051 {
13052 UNBLOCK_INPUT;
13053 return 0;
13054 }
7a13e894
RS
13055
13056 /* We have definitely succeeded. Record the new connection. */
13057
13058 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
13059
29b38361
KH
13060#ifdef MULTI_KBOARD
13061 {
13062 struct x_display_info *share;
13063 Lisp_Object tail;
13064
13065 for (share = x_display_list, tail = x_display_name_list; share;
8e713be6
KR
13066 share = share->next, tail = XCDR (tail))
13067 if (same_x_server (XSTRING (XCAR (XCAR (tail)))->data,
29b38361
KH
13068 XSTRING (display_name)->data))
13069 break;
13070 if (share)
13071 dpyinfo->kboard = share->kboard;
13072 else
13073 {
13074 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
13075 init_kboard (dpyinfo->kboard);
59e755be
KH
13076 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
13077 {
13078 char *vendor = ServerVendor (dpy);
9b6ed9f3 13079 UNBLOCK_INPUT;
59e755be
KH
13080 dpyinfo->kboard->Vsystem_key_alist
13081 = call1 (Qvendor_specific_keysyms,
13082 build_string (vendor ? vendor : ""));
9b6ed9f3 13083 BLOCK_INPUT;
59e755be
KH
13084 }
13085
29b38361
KH
13086 dpyinfo->kboard->next_kboard = all_kboards;
13087 all_kboards = dpyinfo->kboard;
0ad5446c
KH
13088 /* Don't let the initial kboard remain current longer than necessary.
13089 That would cause problems if a file loaded on startup tries to
06a2c219 13090 prompt in the mini-buffer. */
0ad5446c
KH
13091 if (current_kboard == initial_kboard)
13092 current_kboard = dpyinfo->kboard;
29b38361
KH
13093 }
13094 dpyinfo->kboard->reference_count++;
13095 }
b9737ad3
KH
13096#endif
13097
7a13e894
RS
13098 /* Put this display on the chain. */
13099 dpyinfo->next = x_display_list;
13100 x_display_list = dpyinfo;
13101
13102 /* Put it on x_display_name_list as well, to keep them parallel. */
13103 x_display_name_list = Fcons (Fcons (display_name, Qnil),
13104 x_display_name_list);
8e713be6 13105 dpyinfo->name_list_element = XCAR (x_display_name_list);
7a13e894
RS
13106
13107 dpyinfo->display = dpy;
dc6f92b8 13108
dc6f92b8 13109#if 0
7a13e894 13110 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 13111#endif /* ! 0 */
7a13e894
RS
13112
13113 dpyinfo->x_id_name
fc932ac6
RS
13114 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
13115 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
13116 + 2);
13117 sprintf (dpyinfo->x_id_name, "%s@%s",
13118 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
13119
13120 /* Figure out which modifier bits mean what. */
334208b7 13121 x_find_modifier_meanings (dpyinfo);
f451eb13 13122
ab648270 13123 /* Get the scroll bar cursor. */
7a13e894 13124 dpyinfo->vertical_scroll_bar_cursor
334208b7 13125 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 13126
334208b7
RS
13127 xrdb = x_load_resources (dpyinfo->display, xrm_option,
13128 resource_name, EMACS_CLASS);
13129#ifdef HAVE_XRMSETDATABASE
13130 XrmSetDatabase (dpyinfo->display, xrdb);
13131#else
13132 dpyinfo->display->db = xrdb;
13133#endif
547d9db8 13134 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
13135 all versions. */
13136 dpyinfo->xrdb = xrdb;
334208b7
RS
13137
13138 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
13139 DefaultScreen (dpyinfo->display));
5ff67d81 13140 select_visual (dpyinfo);
43bd1b2b 13141 dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
334208b7
RS
13142 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
13143 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
13144 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
13145 dpyinfo->grabbed = 0;
13146 dpyinfo->reference_count = 0;
13147 dpyinfo->icon_bitmap_id = -1;
06a2c219 13148 dpyinfo->font_table = NULL;
7a13e894
RS
13149 dpyinfo->n_fonts = 0;
13150 dpyinfo->font_table_size = 0;
13151 dpyinfo->bitmaps = 0;
13152 dpyinfo->bitmaps_size = 0;
13153 dpyinfo->bitmaps_last = 0;
13154 dpyinfo->scratch_cursor_gc = 0;
13155 dpyinfo->mouse_face_mouse_frame = 0;
13156 dpyinfo->mouse_face_deferred_gc = 0;
13157 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
13158 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 13159 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
13160 dpyinfo->mouse_face_window = Qnil;
13161 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
13162 dpyinfo->mouse_face_defer = 0;
0f941935
KH
13163 dpyinfo->x_focus_frame = 0;
13164 dpyinfo->x_focus_event_frame = 0;
13165 dpyinfo->x_highlight_frame = 0;
06a2c219 13166 dpyinfo->image_cache = make_image_cache ();
334208b7 13167
43bd1b2b 13168 /* See if a private colormap is requested. */
5ff67d81
GM
13169 if (dpyinfo->visual == DefaultVisualOfScreen (dpyinfo->screen))
13170 {
13171 if (dpyinfo->visual->class == PseudoColor)
13172 {
13173 Lisp_Object value;
13174 value = display_x_get_resource (dpyinfo,
13175 build_string ("privateColormap"),
13176 build_string ("PrivateColormap"),
13177 Qnil, Qnil);
13178 if (STRINGP (value)
13179 && (!strcmp (XSTRING (value)->data, "true")
13180 || !strcmp (XSTRING (value)->data, "on")))
13181 dpyinfo->cmap = XCopyColormapAndFree (dpyinfo->display, dpyinfo->cmap);
13182 }
43bd1b2b 13183 }
5ff67d81
GM
13184 else
13185 dpyinfo->cmap = XCreateColormap (dpyinfo->display, dpyinfo->root_window,
13186 dpyinfo->visual, AllocNone);
43bd1b2b 13187
06a2c219
GM
13188 {
13189 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
13190 double pixels = DisplayHeight (dpyinfo->display, screen_number);
13191 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
13192 dpyinfo->resy = pixels * 25.4 / mm;
13193 pixels = DisplayWidth (dpyinfo->display, screen_number);
13194 mm = DisplayWidthMM (dpyinfo->display, screen_number);
13195 dpyinfo->resx = pixels * 25.4 / mm;
13196 }
13197
334208b7
RS
13198 dpyinfo->Xatom_wm_protocols
13199 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
13200 dpyinfo->Xatom_wm_take_focus
13201 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
13202 dpyinfo->Xatom_wm_save_yourself
13203 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
13204 dpyinfo->Xatom_wm_delete_window
13205 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
13206 dpyinfo->Xatom_wm_change_state
13207 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
13208 dpyinfo->Xatom_wm_configure_denied
13209 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
13210 dpyinfo->Xatom_wm_window_moved
13211 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
13212 dpyinfo->Xatom_editres
13213 = XInternAtom (dpyinfo->display, "Editres", False);
13214 dpyinfo->Xatom_CLIPBOARD
13215 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
13216 dpyinfo->Xatom_TIMESTAMP
13217 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
13218 dpyinfo->Xatom_TEXT
13219 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
13220 dpyinfo->Xatom_COMPOUND_TEXT
13221 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
13222 dpyinfo->Xatom_DELETE
13223 = XInternAtom (dpyinfo->display, "DELETE", False);
13224 dpyinfo->Xatom_MULTIPLE
13225 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
13226 dpyinfo->Xatom_INCR
13227 = XInternAtom (dpyinfo->display, "INCR", False);
13228 dpyinfo->Xatom_EMACS_TMP
13229 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
13230 dpyinfo->Xatom_TARGETS
13231 = XInternAtom (dpyinfo->display, "TARGETS", False);
13232 dpyinfo->Xatom_NULL
13233 = XInternAtom (dpyinfo->display, "NULL", False);
13234 dpyinfo->Xatom_ATOM_PAIR
13235 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
13236 /* For properties of font. */
13237 dpyinfo->Xatom_PIXEL_SIZE
13238 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
13239 dpyinfo->Xatom_MULE_BASELINE_OFFSET
13240 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
13241 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
13242 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
13243 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
13244 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 13245
06a2c219
GM
13246 /* Ghostscript support. */
13247 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
13248 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
13249
13250 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
13251 False);
13252
547d9db8
KH
13253 dpyinfo->cut_buffers_initialized = 0;
13254
334208b7
RS
13255 connection = ConnectionNumber (dpyinfo->display);
13256 dpyinfo->connection = connection;
13257
dc43ef94 13258 {
5d7cc324
RS
13259 char null_bits[1];
13260
13261 null_bits[0] = 0x00;
dc43ef94
KH
13262
13263 dpyinfo->null_pixel
13264 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13265 null_bits, 1, 1, (long) 0, (long) 0,
13266 1);
13267 }
13268
06a2c219
GM
13269 {
13270 extern int gray_bitmap_width, gray_bitmap_height;
13271 extern unsigned char *gray_bitmap_bits;
13272 dpyinfo->gray
13273 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
13274 gray_bitmap_bits,
13275 gray_bitmap_width, gray_bitmap_height,
13276 (unsigned long) 1, (unsigned long) 0, 1);
13277 }
13278
f5d11644
GM
13279#ifdef HAVE_X_I18N
13280 xim_initialize (dpyinfo, resource_name);
13281#endif
13282
87485d6f
MW
13283#ifdef subprocesses
13284 /* This is only needed for distinguishing keyboard and process input. */
334208b7 13285 if (connection != 0)
7a13e894 13286 add_keyboard_wait_descriptor (connection);
87485d6f 13287#endif
6d4238f3 13288
041b69ac 13289#ifndef F_SETOWN_BUG
dc6f92b8 13290#ifdef F_SETOWN
dc6f92b8 13291#ifdef F_SETOWN_SOCK_NEG
61c3ce62 13292 /* stdin is a socket here */
334208b7 13293 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 13294#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 13295 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
13296#endif /* ! defined (F_SETOWN_SOCK_NEG) */
13297#endif /* ! defined (F_SETOWN) */
041b69ac 13298#endif /* F_SETOWN_BUG */
dc6f92b8
JB
13299
13300#ifdef SIGIO
eee20f6a
KH
13301 if (interrupt_input)
13302 init_sigio (connection);
c118dd06 13303#endif /* ! defined (SIGIO) */
dc6f92b8 13304
51b592fb 13305#ifdef USE_LUCID
f8c39f51 13306#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
13307 /* Make sure that we have a valid font for dialog boxes
13308 so that Xt does not crash. */
13309 {
13310 Display *dpy = dpyinfo->display;
13311 XrmValue d, fr, to;
13312 Font font;
e99db5a1 13313 int count;
51b592fb
RS
13314
13315 d.addr = (XPointer)&dpy;
13316 d.size = sizeof (Display *);
13317 fr.addr = XtDefaultFont;
13318 fr.size = sizeof (XtDefaultFont);
13319 to.size = sizeof (Font *);
13320 to.addr = (XPointer)&font;
e99db5a1 13321 count = x_catch_errors (dpy);
51b592fb
RS
13322 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
13323 abort ();
13324 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
13325 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 13326 x_uncatch_errors (dpy, count);
51b592fb
RS
13327 }
13328#endif
f8c39f51 13329#endif
51b592fb 13330
34e23e5a
GM
13331 /* See if we should run in synchronous mode. This is useful
13332 for debugging X code. */
13333 {
13334 Lisp_Object value;
13335 value = display_x_get_resource (dpyinfo,
13336 build_string ("synchronous"),
13337 build_string ("Synchronous"),
13338 Qnil, Qnil);
13339 if (STRINGP (value)
13340 && (!strcmp (XSTRING (value)->data, "true")
13341 || !strcmp (XSTRING (value)->data, "on")))
13342 XSynchronize (dpyinfo->display, True);
13343 }
13344
60439948
KH
13345 UNBLOCK_INPUT;
13346
7a13e894
RS
13347 return dpyinfo;
13348}
13349\f
13350/* Get rid of display DPYINFO, assuming all frames are already gone,
13351 and without sending any more commands to the X server. */
dc6f92b8 13352
7a13e894
RS
13353void
13354x_delete_display (dpyinfo)
13355 struct x_display_info *dpyinfo;
13356{
13357 delete_keyboard_wait_descriptor (dpyinfo->connection);
13358
13359 /* Discard this display from x_display_name_list and x_display_list.
13360 We can't use Fdelq because that can quit. */
13361 if (! NILP (x_display_name_list)
8e713be6
KR
13362 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
13363 x_display_name_list = XCDR (x_display_name_list);
7a13e894
RS
13364 else
13365 {
13366 Lisp_Object tail;
13367
13368 tail = x_display_name_list;
8e713be6 13369 while (CONSP (tail) && CONSP (XCDR (tail)))
7a13e894 13370 {
bffcfca9 13371 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
7a13e894 13372 {
8e713be6 13373 XCDR (tail) = XCDR (XCDR (tail));
7a13e894
RS
13374 break;
13375 }
8e713be6 13376 tail = XCDR (tail);
7a13e894
RS
13377 }
13378 }
13379
9bda743f
GM
13380 if (next_noop_dpyinfo == dpyinfo)
13381 next_noop_dpyinfo = dpyinfo->next;
13382
7a13e894
RS
13383 if (x_display_list == dpyinfo)
13384 x_display_list = dpyinfo->next;
7f9c7f94
RS
13385 else
13386 {
13387 struct x_display_info *tail;
7a13e894 13388
7f9c7f94
RS
13389 for (tail = x_display_list; tail; tail = tail->next)
13390 if (tail->next == dpyinfo)
13391 tail->next = tail->next->next;
13392 }
7a13e894 13393
0d777288
RS
13394#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
13395#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
13396 XrmDestroyDatabase (dpyinfo->xrdb);
13397#endif
0d777288 13398#endif
29b38361
KH
13399#ifdef MULTI_KBOARD
13400 if (--dpyinfo->kboard->reference_count == 0)
39f79001 13401 delete_kboard (dpyinfo->kboard);
b9737ad3 13402#endif
f5d11644
GM
13403#ifdef HAVE_X_I18N
13404 if (dpyinfo->xim)
13405 xim_close_dpy (dpyinfo);
13406#endif
13407
b9737ad3
KH
13408 xfree (dpyinfo->font_table);
13409 xfree (dpyinfo->x_id_name);
13410 xfree (dpyinfo);
7a13e894
RS
13411}
13412\f
13413/* Set up use of X before we make the first connection. */
13414
06a2c219
GM
13415static struct redisplay_interface x_redisplay_interface =
13416{
13417 x_produce_glyphs,
13418 x_write_glyphs,
13419 x_insert_glyphs,
13420 x_clear_end_of_line,
13421 x_scroll_run,
13422 x_after_update_window_line,
13423 x_update_window_begin,
13424 x_update_window_end,
13425 XTcursor_to,
13426 x_flush,
66ac4b0e
GM
13427 x_get_glyph_overhangs,
13428 x_fix_overlapping_area
06a2c219
GM
13429};
13430
dfcf069d 13431void
7a13e894
RS
13432x_initialize ()
13433{
06a2c219
GM
13434 rif = &x_redisplay_interface;
13435
13436 clear_frame_hook = x_clear_frame;
13437 ins_del_lines_hook = x_ins_del_lines;
13438 change_line_highlight_hook = x_change_line_highlight;
13439 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
13440 ring_bell_hook = XTring_bell;
13441 reset_terminal_modes_hook = XTreset_terminal_modes;
13442 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
13443 update_begin_hook = x_update_begin;
13444 update_end_hook = x_update_end;
dc6f92b8
JB
13445 set_terminal_window_hook = XTset_terminal_window;
13446 read_socket_hook = XTread_socket;
b8009dd1 13447 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 13448 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 13449 mouse_position_hook = XTmouse_position;
f451eb13 13450 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 13451 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
13452 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
13453 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
13454 redeem_scroll_bar_hook = XTredeem_scroll_bar;
13455 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 13456 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 13457
f676886a 13458 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
13459 char_ins_del_ok = 0; /* just as fast to write the line */
13460 line_ins_del_ok = 1; /* we'll just blt 'em */
13461 fast_clear_end_of_line = 1; /* X does this well */
58769bee 13462 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
13463 off the bottom */
13464 baud_rate = 19200;
13465
7a13e894 13466 x_noop_count = 0;
9ea173e8 13467 last_tool_bar_item = -1;
06a2c219
GM
13468 any_help_event_p = 0;
13469
b30b24cb
RS
13470 /* Try to use interrupt input; if we can't, then start polling. */
13471 Fset_input_mode (Qt, Qnil, Qt, Qnil);
13472
7f9c7f94
RS
13473#ifdef USE_X_TOOLKIT
13474 XtToolkitInitialize ();
13475 Xt_app_con = XtCreateApplicationContext ();
665881ad 13476 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
bffcfca9
GM
13477
13478 /* Install an asynchronous timer that processes Xt timeout events
13479 every 0.1s. This is necessary because some widget sets use
13480 timeouts internally, for example the LessTif menu bar, or the
13481 Xaw3d scroll bar. When Xt timouts aren't processed, these
13482 widgets don't behave normally. */
13483 {
13484 EMACS_TIME interval;
13485 EMACS_SET_SECS_USECS (interval, 0, 100000);
13486 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
13487 }
db74249b 13488#endif
bffcfca9 13489
db74249b 13490#if USE_TOOLKIT_SCROLL_BARS
ec18280f
SM
13491 xaw3d_arrow_scroll = False;
13492 xaw3d_pick_top = True;
7f9c7f94
RS
13493#endif
13494
58769bee 13495 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 13496 original error handler. */
e99db5a1 13497 XSetErrorHandler (x_error_handler);
334208b7 13498 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 13499
06a2c219 13500 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
13501#ifdef SIGWINCH
13502 signal (SIGWINCH, SIG_DFL);
c118dd06 13503#endif /* ! defined (SIGWINCH) */
dc6f92b8 13504
92e2441b 13505 signal (SIGPIPE, x_connection_signal);
dc6f92b8 13506}
55123275 13507
06a2c219 13508
55123275
JB
13509void
13510syms_of_xterm ()
13511{
e99db5a1
RS
13512 staticpro (&x_error_message_string);
13513 x_error_message_string = Qnil;
13514
7a13e894
RS
13515 staticpro (&x_display_name_list);
13516 x_display_name_list = Qnil;
334208b7 13517
ab648270 13518 staticpro (&last_mouse_scroll_bar);
e53cb100 13519 last_mouse_scroll_bar = Qnil;
59e755be
KH
13520
13521 staticpro (&Qvendor_specific_keysyms);
13522 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
13523
13524 staticpro (&last_mouse_press_frame);
13525 last_mouse_press_frame = Qnil;
06a2c219
GM
13526
13527 staticpro (&help_echo);
13528 help_echo = Qnil;
13529 staticpro (&previous_help_echo);
13530 previous_help_echo = Qnil;
13531
13532 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
13533 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
13534For example, if a block cursor is over a tab, it will be drawn as\n\
13535wide as that tab on the display.");
13536 x_stretch_cursor_p = 0;
13537
13538 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
13539 "If not nil, Emacs uses toolkit scroll bars.");
13540#if USE_TOOLKIT_SCROLL_BARS
13541 x_toolkit_scroll_bars_p = 1;
13542#else
13543 x_toolkit_scroll_bars_p = 0;
13544#endif
13545
06a2c219
GM
13546 staticpro (&last_mouse_motion_frame);
13547 last_mouse_motion_frame = Qnil;
55123275 13548}
6cf0ae86
RS
13549
13550#endif /* not HAVE_X_WINDOWS */
06a2c219 13551