(getdefdir): Don't return failure indication when
[bpt/emacs.git] / src / xterm.c
CommitLineData
dc6f92b8 1/* X Communication module for terminals which understand the X protocol.
06a2c219
GM
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999
3 Free Software Foundation, Inc.
dc6f92b8
JB
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
4746118a 9the Free Software Foundation; either version 2, or (at your option)
dc6f92b8
JB
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
3b7ad313
EN
19the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20Boston, MA 02111-1307, USA. */
dc6f92b8 21
06a2c219 22/* New display code by Gerd Moellmann <gerd@gnu.org>. */
3afe33e7
RS
23/* Xt features made by Fred Pierresteguy. */
24
039440c4
RS
25/* On 4.3 these lose if they come after xterm.h. */
26/* On HP-UX 8.0 signal.h loses if it comes after config.h. */
27/* Putting these at the beginning seems to be standard for other .c files. */
039440c4
RS
28#include <signal.h>
29
18160b98 30#include <config.h>
dc6f92b8 31
4846819e 32#include <stdio.h>
06a2c219
GM
33#ifdef STDC_HEADERS
34#include <stdlib.h>
35#endif
4846819e 36
dc6f92b8
JB
37#ifdef HAVE_X_WINDOWS
38
39#include "lisp.h"
9ac0d9e0 40#include "blockinput.h"
dc6f92b8 41
ae79c227
AS
42/* Need syssignal.h for various externs and definitions that may be required
43 by some configurations for calls to signal later in this source file. */
44#include "syssignal.h"
45
dc6f92b8
JB
46/* This may include sys/types.h, and that somehow loses
47 if this is not done before the other system files. */
48#include "xterm.h"
f451eb13 49#include <X11/cursorfont.h>
dc6f92b8 50
16bd92ea 51#ifndef USG
dc6f92b8
JB
52/* Load sys/types.h if not already loaded.
53 In some systems loading it twice is suicidal. */
54#ifndef makedev
55#include <sys/types.h>
c118dd06
JB
56#endif /* makedev */
57#endif /* USG */
dc6f92b8 58
6df54671 59#ifdef BSD_SYSTEM
dc6f92b8 60#include <sys/ioctl.h>
6df54671 61#endif /* ! defined (BSD_SYSTEM) */
dc6f92b8 62
2d368234 63#include "systty.h"
3a2712f9 64#include "systime.h"
dc6f92b8 65
b8009dd1 66#ifndef INCLUDED_FCNTL
dc6f92b8 67#include <fcntl.h>
b8009dd1 68#endif
dc6f92b8
JB
69#include <ctype.h>
70#include <errno.h>
71#include <setjmp.h>
72#include <sys/stat.h>
a0a7635f
RS
73/* Caused redefinition of DBL_DIG on Netbsd; seems not to be needed. */
74/* #include <sys/param.h> */
dc6f92b8 75
dc43ef94
KH
76#include "charset.h"
77#include "ccl.h"
7a13e894 78#include "frame.h"
a1dfb88a 79#include "fontset.h"
dc6f92b8
JB
80#include "dispextern.h"
81#include "termhooks.h"
82#include "termopts.h"
83#include "termchar.h"
84#if 0
85#include "sink.h"
86#include "sinkmask.h"
c118dd06 87#endif /* ! 0 */
dc6f92b8 88#include "gnu.h"
dc6f92b8 89#include "disptab.h"
dc6f92b8 90#include "buffer.h"
f451eb13 91#include "window.h"
3b2fa4e6 92#include "keyboard.h"
bde7c500 93#include "intervals.h"
dfcf069d 94#include "process.h"
dc6f92b8 95
d2bd6bc4
RS
96#ifdef USE_X_TOOLKIT
97#include <X11/Shell.h>
98#endif
99
06a2c219
GM
100#include <sys/types.h>
101#ifdef HAVE_SYS_TIME_H
102#include <sys/time.h>
103#endif
104#ifdef HAVE_UNISTD_H
105#include <unistd.h>
106#endif
107
3afe33e7 108#ifdef USE_X_TOOLKIT
06a2c219 109
9d7e2e3e 110extern void free_frame_menubar ();
2224b905 111extern FRAME_PTR x_menubar_window_to_frame ();
06a2c219 112
0fdff6bb
RS
113#if (XtSpecificationRelease >= 5) && !defined(NO_EDITRES)
114#define HACK_EDITRES
115extern void _XEditResCheckMessages ();
116#endif /* not NO_EDITRES */
06a2c219
GM
117
118/* Include toolkit specific headers for the scroll bar widget. */
119
120#ifdef USE_TOOLKIT_SCROLL_BARS
121#if defined USE_MOTIF
122#include <Xm/Xm.h> /* for LESSTIF_VERSION */
123#include <Xm/ScrollBar.h>
124#include <Xm/ScrollBarP.h>
125#elif defined HAVE_XAW3D
126#include <X11/Xaw3d/Simple.h>
127#include <X11/Xaw3d/ThreeD.h>
128#include <X11/Xaw3d/Scrollbar.h>
129#define ARROW_SCROLLBAR
130#include <X11/Xaw3d/ScrollbarP.h>
131#endif /* HAVE_XAW3D */
132#endif /* USE_TOOLKIT_SCROLL_BARS */
133
3afe33e7
RS
134#endif /* USE_X_TOOLKIT */
135
b849c413
RS
136#ifndef USE_X_TOOLKIT
137#define x_any_window_to_frame x_window_to_frame
5627c40e 138#define x_top_window_to_frame x_window_to_frame
b849c413
RS
139#endif
140
546e6d5b 141#ifdef USE_X_TOOLKIT
d067ea8b 142#include "widget.h"
546e6d5b
RS
143#ifndef XtNinitialState
144#define XtNinitialState "initialState"
145#endif
146#endif
147
10537cb1 148#ifdef HAVE_SETLOCALE
39d8bb4d
KH
149/* So we can do setlocale. */
150#include <locale.h>
151#endif
152
80528801
KH
153#ifdef SOLARIS2
154/* memmove will be defined as a macro in Xfuncs.h unless
155 <string.h> is included beforehand. The declaration for memmove in
156 <string.h> will cause a syntax error when Xfuncs.h later includes it. */
157#include <string.h>
158#endif
159
e4b68333 160#ifndef min
06a2c219 161#define min(a,b) ((a) < (b) ? (a) : (b))
e4b68333
RS
162#endif
163#ifndef max
06a2c219
GM
164#define max(a,b) ((a) > (b) ? (a) : (b))
165#endif
166
167#define abs(x) ((x) < 0 ? -(x) : (x))
168
169#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
170
171\f
172/* Bitmaps for truncated lines. */
173
174enum bitmap_type
175{
176 NO_BITMAP,
177 LEFT_TRUNCATION_BITMAP,
178 RIGHT_TRUNCATION_BITMAP,
179 OVERLAY_ARROW_BITMAP,
180 CONTINUED_LINE_BITMAP,
181 CONTINUATION_LINE_BITMAP,
182 ZV_LINE_BITMAP
183};
184
185/* Bitmap drawn to indicate lines not displaying text if
186 `indicate-empty-lines' is non-nil. */
187
188#define zv_width 8
189#define zv_height 8
190static unsigned char zv_bits[] = {
191 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x1e, 0x00, 0x00};
192
193/* An arrow like this: `<-'. */
194
195#define left_width 8
196#define left_height 8
197static unsigned char left_bits[] = {
198 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
199
200/* Marker for continued lines. */
201
202#define continued_width 8
203#define continued_height 8
204static unsigned char continued_bits[] = {
205 0x30, 0x30, 0x30, 0x30, 0xb4, 0xfc, 0x78, 0x30};
206
207#define continuation_width 8
208#define continuation_height 8
209static unsigned char continuation_bits[] = {
210 0x0c, 0x1e, 0x3f, 0x2d, 0x0c, 0x0c, 0x0c, 0x0c};
211
212/* Right truncation arrow bitmap `->'. */
213
214#define right_width 8
215#define right_height 8
216static unsigned char right_bits[] = {
217 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
218
219/* Overlay arrow bitmap; a filled `<>'. */
220
221#if 1
222#define ov_width 8
223#define ov_height 8
224static unsigned char ov_bits[] = {
225 0x30, 0x08, 0x3c, 0x7e, 0x7a, 0x7a, 0x62, 0x3c};
226
227#elif 0
228#define ov_width 8
229#define ov_height 8
230static unsigned char ov_bits[] = {
231 0x18, 0x04, 0x08, 0x1c, 0x3e, 0x3a, 0x32, 0x1c};
232#else
233#define ov_width 8
234#define ov_height 8
235static unsigned char ov_bits[] = {
236 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x3c, 0x18};
e4b68333 237#endif
06a2c219
GM
238
239extern Lisp_Object Qhelp_echo;
240
69388238 241\f
06a2c219
GM
242/* Non-zero means Emacs uses toolkit scroll bars. */
243
244int x_toolkit_scroll_bars_p;
245
246/* If a string, XTread_socket generates an event to display that string.
247 (The display is done in read_char.) */
248
249static Lisp_Object help_echo;
250
251/* Temporary variable for XTread_socket. */
252
253static Lisp_Object previous_help_echo;
254
255/* Non-zero means that a HELP_EVENT has been generated since Emacs
256 start. */
257
258static int any_help_event_p;
259
260/* Non-zero means draw block and hollow cursor as wide as the glyph
261 under it. For example, if a block cursor is over a tab, it will be
262 drawn as wide as that tab on the display. */
263
264int x_stretch_cursor_p;
265
266/* This is a chain of structures for all the X displays currently in
267 use. */
268
334208b7 269struct x_display_info *x_display_list;
dc6f92b8 270
06a2c219
GM
271/* This is a list of cons cells, each of the form (NAME
272 . FONT-LIST-CACHE), one for each element of x_display_list and in
273 the same order. NAME is the name of the frame. FONT-LIST-CACHE
274 records previous values returned by x-list-fonts. */
275
7a13e894 276Lisp_Object x_display_name_list;
f451eb13 277
987d2ad1 278/* Frame being updated by update_frame. This is declared in term.c.
06a2c219
GM
279 This is set by update_begin and looked at by all the XT functions.
280 It is zero while not inside an update. In that case, the XT
281 functions assume that `selected_frame' is the frame to apply to. */
282
d0386f2a 283extern struct frame *updating_frame;
dc6f92b8 284
dfcf069d 285extern int waiting_for_input;
0e81d8cd 286
06a2c219
GM
287/* This is a frame waiting to be auto-raised, within XTread_socket. */
288
0134a210
RS
289struct frame *pending_autoraise_frame;
290
7f9c7f94
RS
291#ifdef USE_X_TOOLKIT
292/* The application context for Xt use. */
293XtAppContext Xt_app_con;
06a2c219
GM
294static String Xt_default_resources[] = {0};
295#endif /* USE_X_TOOLKIT */
665881ad 296
06a2c219
GM
297/* Nominal cursor position -- where to draw output.
298 HPOS and VPOS are window relative glyph matrix coordinates.
299 X and Y are window relative pixel coordinates. */
dc6f92b8 300
06a2c219 301struct cursor_pos output_cursor;
dc6f92b8 302
dc6f92b8 303
69388238
RS
304/* Mouse movement.
305
06a2c219 306 Formerly, we used PointerMotionHintMask (in standard_event_mask)
f5bb65ec
RS
307 so that we would have to call XQueryPointer after each MotionNotify
308 event to ask for another such event. However, this made mouse tracking
309 slow, and there was a bug that made it eventually stop.
310
311 Simply asking for MotionNotify all the time seems to work better.
312
69388238
RS
313 In order to avoid asking for motion events and then throwing most
314 of them away or busy-polling the server for mouse positions, we ask
315 the server for pointer motion hints. This means that we get only
316 one event per group of mouse movements. "Groups" are delimited by
317 other kinds of events (focus changes and button clicks, for
318 example), or by XQueryPointer calls; when one of these happens, we
319 get another MotionNotify event the next time the mouse moves. This
320 is at least as efficient as getting motion events when mouse
321 tracking is on, and I suspect only negligibly worse when tracking
f5bb65ec 322 is off. */
69388238
RS
323
324/* Where the mouse was last time we reported a mouse event. */
69388238 325
06a2c219
GM
326FRAME_PTR last_mouse_frame;
327static XRectangle last_mouse_glyph;
2237cac9
RS
328static Lisp_Object last_mouse_press_frame;
329
69388238
RS
330/* The scroll bar in which the last X motion event occurred.
331
06a2c219
GM
332 If the last X motion event occurred in a scroll bar, we set this so
333 XTmouse_position can know whether to report a scroll bar motion or
69388238
RS
334 an ordinary motion.
335
06a2c219
GM
336 If the last X motion event didn't occur in a scroll bar, we set
337 this to Qnil, to tell XTmouse_position to return an ordinary motion
338 event. */
339
69388238
RS
340static Lisp_Object last_mouse_scroll_bar;
341
69388238
RS
342/* This is a hack. We would really prefer that XTmouse_position would
343 return the time associated with the position it returns, but there
06a2c219 344 doesn't seem to be any way to wrest the time-stamp from the server
69388238
RS
345 along with the position query. So, we just keep track of the time
346 of the last movement we received, and return that in hopes that
347 it's somewhat accurate. */
06a2c219 348
69388238
RS
349static Time last_mouse_movement_time;
350
06a2c219
GM
351/* Incremented by XTread_socket whenever it really tries to read
352 events. */
353
c0a04927
RS
354#ifdef __STDC__
355static int volatile input_signal_count;
356#else
357static int input_signal_count;
358#endif
359
7a13e894 360/* Used locally within XTread_socket. */
06a2c219 361
7a13e894 362static int x_noop_count;
dc6f92b8 363
7a13e894 364/* Initial values of argv and argc. */
06a2c219 365
7a13e894
RS
366extern char **initial_argv;
367extern int initial_argc;
dc6f92b8 368
7a13e894 369extern Lisp_Object Vcommand_line_args, Vsystem_name;
dc6f92b8 370
06a2c219 371/* Tells if a window manager is present or not. */
7a13e894
RS
372
373extern Lisp_Object Vx_no_window_manager;
dc6f92b8 374
c2df547c 375extern Lisp_Object Qface, Qmouse_face;
b8009dd1 376
dc6f92b8
JB
377extern int errno;
378
dfeccd2d 379/* A mask of extra modifier bits to put into every keyboard char. */
06a2c219 380
64bb1782
RS
381extern int extra_keyboard_modifiers;
382
59e755be
KH
383static Lisp_Object Qvendor_specific_keysyms;
384
334208b7 385extern XrmDatabase x_load_resources ();
c32cdd9a
KH
386extern Lisp_Object x_icon_type ();
387
7a13e894 388
06a2c219
GM
389/* Enumeration for overriding/changing the face to use for drawing
390 glyphs in x_draw_glyphs. */
391
392enum draw_glyphs_face
393{
394 DRAW_NORMAL_TEXT,
395 DRAW_INVERSE_VIDEO,
396 DRAW_CURSOR,
397 DRAW_MOUSE_FACE,
398 DRAW_IMAGE_RAISED,
399 DRAW_IMAGE_SUNKEN
400};
401
402static void x_update_window_end P_ ((struct window *, int));
403static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
404void x_delete_display P_ ((struct x_display_info *));
405static unsigned int x_x_to_emacs_modifiers P_ ((struct x_display_info *,
406 unsigned));
407static int fast_find_position P_ ((struct window *, int, int *, int *,
408 int *, int *));
409static void set_output_cursor P_ ((struct cursor_pos *));
410static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
411 int *, int *, int *));
412static void note_mode_line_highlight P_ ((struct window *, int, int));
413static void x_check_font P_ ((struct frame *, XFontStruct *));
414static void note_mouse_highlight P_ ((struct frame *, int, int));
415static void note_toolbar_highlight P_ ((struct frame *f, int, int));
416static void x_handle_toolbar_click P_ ((struct frame *, XButtonEvent *));
417static void show_mouse_face P_ ((struct x_display_info *,
418 enum draw_glyphs_face));
419static int x_io_error_quitter P_ ((Display *));
420int x_catch_errors P_ ((Display *));
421void x_uncatch_errors P_ ((Display *, int));
422void x_lower_frame P_ ((struct frame *));
423void x_scroll_bar_clear P_ ((struct frame *));
424int x_had_errors_p P_ ((Display *));
425void x_wm_set_size_hint P_ ((struct frame *, long, int));
426void x_raise_frame P_ ((struct frame *));
427void x_set_window_size P_ ((struct frame *, int, int, int));
428void x_wm_set_window_state P_ ((struct frame *, int));
429void x_wm_set_icon_pixmap P_ ((struct frame *, int));
430void x_initialize P_ ((void));
431static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
432static int x_compute_min_glyph_bounds P_ ((struct frame *));
433static void x_draw_phys_cursor_glyph P_ ((struct window *,
434 struct glyph_row *,
435 enum draw_glyphs_face));
436static void x_update_end P_ ((struct frame *));
437static void XTframe_up_to_date P_ ((struct frame *));
438static void XTreassert_line_highlight P_ ((int, int));
439static void x_change_line_highlight P_ ((int, int, int, int));
440static void XTset_terminal_modes P_ ((void));
441static void XTreset_terminal_modes P_ ((void));
442static void XTcursor_to P_ ((int, int, int, int));
443static void x_write_glyphs P_ ((struct glyph *, int));
444static void x_clear_end_of_line P_ ((int));
445static void x_clear_frame P_ ((void));
446static void x_clear_cursor P_ ((struct window *));
447static void frame_highlight P_ ((struct frame *));
448static void frame_unhighlight P_ ((struct frame *));
449static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
450static void XTframe_rehighlight P_ ((struct frame *));
451static void x_frame_rehighlight P_ ((struct x_display_info *));
452static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
453static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
454static int x_intersect_rectangles P_ ((XRectangle *, XRectangle *,
455 XRectangle *));
456static void expose_frame P_ ((struct frame *, int, int, int, int));
457static void expose_window_tree P_ ((struct window *, XRectangle *));
458static void expose_window P_ ((struct window *, XRectangle *));
459static void expose_area P_ ((struct window *, struct glyph_row *,
460 XRectangle *, enum glyph_row_area));
461static void expose_line P_ ((struct window *, struct glyph_row *,
462 XRectangle *));
463static void x_update_cursor_in_window_tree P_ ((struct window *, int));
464static void x_update_window_cursor P_ ((struct window *, int));
465static void x_erase_phys_cursor P_ ((struct window *));
466void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
467static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
468 enum bitmap_type));
469
470static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
471 GC, int));
472static int x_phys_cursor_in_rect_p P_ ((struct window *, XRectangle *));
473static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
474static void note_overwritten_text_cursor P_ ((struct window *, int, int));
475static void x_flush P_ ((struct frame *f));
476
477
478/* Flush display of frame F, or of all frames if F is null. */
479
480static void
481x_flush (f)
482 struct frame *f;
483{
484 BLOCK_INPUT;
485 if (f == NULL)
486 {
487 Lisp_Object rest, frame;
488 FOR_EACH_FRAME (rest, frame)
489 x_flush (XFRAME (frame));
490 }
491 else if (FRAME_X_P (f))
492 XFlush (FRAME_X_DISPLAY (f));
493 UNBLOCK_INPUT;
494}
495
dc6f92b8 496
06a2c219
GM
497/* Remove calls to XFlush by defining XFlush to an empty replacement.
498 Calls to XFlush should be unnecessary because the X output buffer
499 is flushed automatically as needed by calls to XPending,
500 XNextEvent, or XWindowEvent according to the XFlush man page.
501 XTread_socket calls XPending. Removing XFlush improves
502 performance. */
503
504#define XFlush(DISPLAY) (void) 0
b8009dd1 505
334208b7 506\f
06a2c219
GM
507/***********************************************************************
508 Debugging
509 ***********************************************************************/
510
9382638d 511#if 0
06a2c219
GM
512
513/* This is a function useful for recording debugging information about
514 the sequence of occurrences in this file. */
9382638d
KH
515
516struct record
517{
518 char *locus;
519 int type;
520};
521
522struct record event_record[100];
523
524int event_record_index;
525
526record_event (locus, type)
527 char *locus;
528 int type;
529{
530 if (event_record_index == sizeof (event_record) / sizeof (struct record))
531 event_record_index = 0;
532
533 event_record[event_record_index].locus = locus;
534 event_record[event_record_index].type = type;
535 event_record_index++;
536}
537
538#endif /* 0 */
06a2c219
GM
539
540
9382638d 541\f
334208b7
RS
542/* Return the struct x_display_info corresponding to DPY. */
543
544struct x_display_info *
545x_display_info_for_display (dpy)
546 Display *dpy;
547{
548 struct x_display_info *dpyinfo;
549
550 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
551 if (dpyinfo->display == dpy)
552 return dpyinfo;
16bd92ea 553
334208b7
RS
554 return 0;
555}
f451eb13 556
06a2c219
GM
557
558\f
559/***********************************************************************
560 Starting and ending an update
561 ***********************************************************************/
562
563/* Start an update of frame F. This function is installed as a hook
564 for update_begin, i.e. it is called when update_begin is called.
565 This function is called prior to calls to x_update_window_begin for
566 each window being updated. Currently, there is nothing to do here
567 because all interesting stuff is done on a window basis. */
dc6f92b8 568
dfcf069d 569static void
06a2c219 570x_update_begin (f)
f676886a 571 struct frame *f;
58769bee 572{
06a2c219
GM
573 /* Nothing to do. */
574}
dc6f92b8 575
dc6f92b8 576
06a2c219
GM
577/* Start update of window W. Set the global variable updated_window
578 to the window being updated and set output_cursor to the cursor
579 position of W. */
dc6f92b8 580
06a2c219
GM
581static void
582x_update_window_begin (w)
583 struct window *w;
584{
585 struct frame *f = XFRAME (WINDOW_FRAME (w));
586 struct x_display_info *display_info = FRAME_X_DISPLAY_INFO (f);
587
588 updated_window = w;
589 set_output_cursor (&w->cursor);
b8009dd1 590
06a2c219 591 BLOCK_INPUT;
d1bc4182 592
06a2c219 593 if (f == display_info->mouse_face_mouse_frame)
b8009dd1 594 {
514e4681 595 /* Don't do highlighting for mouse motion during the update. */
06a2c219 596 display_info->mouse_face_defer = 1;
37c2c98b 597
06a2c219
GM
598 /* If F needs to be redrawn, simply forget about any prior mouse
599 highlighting. */
9f67f20b 600 if (FRAME_GARBAGED_P (f))
06a2c219
GM
601 display_info->mouse_face_window = Qnil;
602
603 /* Can we tell that this update does not affect the window
604 where the mouse highlight is? If so, no need to turn off.
605 Likewise, don't do anything if the frame is garbaged;
606 in that case, the frame's current matrix that we would use
607 is all wrong, and we will redisplay that line anyway. */
608 if (!NILP (display_info->mouse_face_window)
609 && w == XWINDOW (display_info->mouse_face_window))
514e4681 610 {
06a2c219 611 int i;
514e4681 612
06a2c219
GM
613 for (i = 0; i < w->desired_matrix->nrows; ++i)
614 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
514e4681
RS
615 break;
616
06a2c219
GM
617 if (i < w->desired_matrix->nrows)
618 clear_mouse_face (display_info);
514e4681 619 }
b8009dd1 620 }
6ccf47d1 621
dc6f92b8
JB
622 UNBLOCK_INPUT;
623}
624
06a2c219
GM
625
626/* Draw a vertical window border to the right of window W if W doesn't
627 have vertical scroll bars. */
628
dfcf069d 629static void
06a2c219
GM
630x_draw_vertical_border (w)
631 struct window *w;
58769bee 632{
06a2c219
GM
633 struct frame *f = XFRAME (WINDOW_FRAME (w));
634
635 /* Redraw borders between horizontally adjacent windows. Don't
636 do it for frames with vertical scroll bars because either the
637 right scroll bar of a window, or the left scroll bar of its
638 neighbor will suffice as a border. */
639 if (!WINDOW_RIGHTMOST_P (w)
640 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
641 {
642 int x0, x1, y0, y1;
dc6f92b8 643
06a2c219
GM
644 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
645 x1 += FRAME_X_FLAGS_AREA_WIDTH (f);
646 y1 -= 1;
647
648 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
649 f->output_data.x->normal_gc, x1, y0, x1, y1);
650 }
651}
652
653
654/* End update of window W (which is equal to updated_window). Draw
655 vertical borders between horizontally adjacent windows, and display
656 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
657 pseudo-window in case we don't have X toolkit support. Such
658 windows don't have a cursor, so don't display it here. */
659
660static void
661x_update_window_end (w, cursor_on_p)
662 struct window *w;
663 int cursor_on_p;
664{
665 if (!w->pseudo_window_p)
666 {
667 BLOCK_INPUT;
668 if (cursor_on_p)
669 x_display_and_set_cursor (w, 1, output_cursor.hpos,
670 output_cursor.vpos,
671 output_cursor.x, output_cursor.y);
672 x_draw_vertical_border (w);
673 UNBLOCK_INPUT;
674 }
675
676 updated_window = NULL;
677}
dc6f92b8 678
dc6f92b8 679
06a2c219
GM
680/* End update of frame F. This function is installed as a hook in
681 update_end. */
682
683static void
684x_update_end (f)
685 struct frame *f;
686{
687 /* Mouse highlight may be displayed again. */
aa8bff2e 688 FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
b8009dd1 689
06a2c219 690 BLOCK_INPUT;
334208b7 691 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
692 UNBLOCK_INPUT;
693}
b8009dd1 694
06a2c219
GM
695
696/* This function is called from various places in xdisp.c whenever a
697 complete update has been performed. The global variable
698 updated_window is not available here. */
b8009dd1 699
dfcf069d 700static void
b8009dd1 701XTframe_up_to_date (f)
06a2c219 702 struct frame *f;
b8009dd1 703{
06a2c219 704 if (FRAME_X_P (f))
514e4681 705 {
06a2c219
GM
706 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
707 if (dpyinfo->mouse_face_deferred_gc
708 || f == dpyinfo->mouse_face_mouse_frame)
709 {
710 BLOCK_INPUT;
711 if (dpyinfo->mouse_face_mouse_frame)
712 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
713 dpyinfo->mouse_face_mouse_x,
714 dpyinfo->mouse_face_mouse_y);
715 dpyinfo->mouse_face_deferred_gc = 0;
716 UNBLOCK_INPUT;
717 }
514e4681 718 }
b8009dd1 719}
06a2c219
GM
720
721
722/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
723 arrow bitmaps, or clear the areas where they would be displayed
724 before DESIRED_ROW is made current. The window being updated is
725 found in updated_window. This function It is called from
726 update_window_line only if it is known that there are differences
727 between bitmaps to be drawn between current row and DESIRED_ROW. */
728
729static void
730x_after_update_window_line (desired_row)
731 struct glyph_row *desired_row;
732{
733 struct window *w = updated_window;
734
735 xassert (w);
736
737 if (!desired_row->mode_line_p && !w->pseudo_window_p)
738 {
739 BLOCK_INPUT;
740 x_draw_row_bitmaps (w, desired_row);
741
742 /* When a window has disappeared, make sure that no rest of
743 full-width rows stays visible in the internal border. */
744 if (windows_or_buffers_changed)
745 {
746 struct frame *f = XFRAME (w->frame);
747 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
748 int height = desired_row->visible_height;
749 int x = window_box_right (w, -1) + FRAME_X_FLAGS_AREA_WIDTH (f);
750 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
751
752 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
753 x, y, width, height, False);
754 }
755
756 UNBLOCK_INPUT;
757 }
758}
759
760
761/* Draw the bitmap WHICH in one of the areas to the left or right of
762 window W. ROW is the glyph row for which to display the bitmap; it
763 determines the vertical position at which the bitmap has to be
764 drawn. */
765
766static void
767x_draw_bitmap (w, row, which)
768 struct window *w;
769 struct glyph_row *row;
770 enum bitmap_type which;
771{
772 struct frame *f = XFRAME (WINDOW_FRAME (w));
773 Display *display = FRAME_X_DISPLAY (f);
774 Window window = FRAME_X_WINDOW (f);
775 int x, y, wd, h, dy;
776 unsigned char *bits;
777 Pixmap pixmap;
778 GC gc = f->output_data.x->normal_gc;
779 struct face *face;
780 int depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
781
782 /* Must clip because of partially visible lines. */
783 x_clip_to_row (w, row, gc, 1);
784
785 switch (which)
786 {
787 case LEFT_TRUNCATION_BITMAP:
788 wd = left_width;
789 h = left_height;
790 bits = left_bits;
791 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
792 - wd
793 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
794 break;
795
796 case OVERLAY_ARROW_BITMAP:
797 wd = left_width;
798 h = left_height;
799 bits = ov_bits;
800 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
801 - wd
802 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
803 break;
804
805 case RIGHT_TRUNCATION_BITMAP:
806 wd = right_width;
807 h = right_height;
808 bits = right_bits;
809 x = window_box_right (w, -1);
810 x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2;
811 break;
812
813 case CONTINUED_LINE_BITMAP:
814 wd = right_width;
815 h = right_height;
816 bits = continued_bits;
817 x = window_box_right (w, -1);
818 x += (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2;
819 break;
820
821 case CONTINUATION_LINE_BITMAP:
822 wd = continuation_width;
823 h = continuation_height;
824 bits = continuation_bits;
825 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
826 - wd
827 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
828 break;
829
830 case ZV_LINE_BITMAP:
831 wd = zv_width;
832 h = zv_height;
833 bits = zv_bits;
834 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
835 - wd
836 - (FRAME_X_FLAGS_AREA_WIDTH (f) - wd) / 2);
837 break;
838
839 default:
840 abort ();
841 }
842
843 /* Convert to frame coordinates. Set dy to the offset in the row to
844 start drawing the bitmap. */
845 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
846 dy = (row->height - h) / 2;
847
848 /* Draw the bitmap. I believe these small pixmaps can be cached
849 by the server. */
850 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
851 pixmap = XCreatePixmapFromBitmapData (display, window, bits, wd, h,
852 face->foreground,
853 face->background, depth);
854 XCopyArea (display, pixmap, window, gc, 0, 0, wd, h, x, y + dy);
855 XFreePixmap (display, pixmap);
856 XSetClipMask (display, gc, None);
857}
858
859
860/* Draw flags bitmaps for glyph row ROW on window W. Call this
861 function with input blocked. */
862
863static void
864x_draw_row_bitmaps (w, row)
865 struct window *w;
866 struct glyph_row *row;
867{
868 struct frame *f = XFRAME (w->frame);
869 enum bitmap_type bitmap;
870 struct face *face;
871 int top_line_height = -1;
872
873 xassert (interrupt_input_blocked);
874
875 /* If row is completely invisible, because of vscrolling, we
876 don't have to draw anything. */
877 if (row->visible_height <= 0)
878 return;
879
880 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
881 PREPARE_FACE_FOR_DISPLAY (f, face);
882
883 /* Decide which bitmap to draw at the left side. */
884 if (row->overlay_arrow_p)
885 bitmap = OVERLAY_ARROW_BITMAP;
886 else if (row->truncated_on_left_p)
887 bitmap = LEFT_TRUNCATION_BITMAP;
888 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
889 bitmap = CONTINUATION_LINE_BITMAP;
890 else if (row->indicate_empty_line_p)
891 bitmap = ZV_LINE_BITMAP;
892 else
893 bitmap = NO_BITMAP;
894
895 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
896 the flags area. */
897 if (bitmap == NO_BITMAP
898 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f)
899 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
900 {
901 /* If W has a vertical border to its left, don't draw over it. */
902 int border = ((XFASTINT (w->left) > 0
903 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
904 ? 1 : 0);
905 int left = window_box_left (w, -1);
906
907 if (top_line_height < 0)
908 top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
dcd08bfb
GM
909
910 /* In case the same realized face is used for bitmap areas and
911 for something displayed in the text (e.g. face `region' on
912 mono-displays, the fill style may have been changed to
913 FillSolid in x_draw_glyph_string_background. */
914 if (face->stipple)
915 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
916 else
917 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
918
06a2c219
GM
919 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
920 face->gc,
921 (left
922 - FRAME_X_FLAGS_AREA_WIDTH (f)
923 + border),
924 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
925 row->y)),
926 FRAME_X_FLAGS_AREA_WIDTH (f) - border,
927 row->visible_height);
dcd08bfb
GM
928 if (!face->stipple)
929 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
930 }
931
932 /* Draw the left bitmap. */
933 if (bitmap != NO_BITMAP)
934 x_draw_bitmap (w, row, bitmap);
935
936 /* Decide which bitmap to draw at the right side. */
937 if (row->truncated_on_right_p)
938 bitmap = RIGHT_TRUNCATION_BITMAP;
939 else if (row->continued_p)
940 bitmap = CONTINUED_LINE_BITMAP;
941 else
942 bitmap = NO_BITMAP;
943
944 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
945 the flags area. */
946 if (bitmap == NO_BITMAP
947 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_FLAGS_AREA_WIDTH (f)
948 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
949 {
950 int right = window_box_right (w, -1);
951
952 if (top_line_height < 0)
953 top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
dcd08bfb
GM
954
955 /* In case the same realized face is used for bitmap areas and
956 for something displayed in the text (e.g. face `region' on
957 mono-displays, the fill style may have been changed to
958 FillSolid in x_draw_glyph_string_background. */
959 if (face->stipple)
960 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
961 else
962 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
06a2c219
GM
963 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
964 face->gc,
965 right,
966 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
967 row->y)),
968 FRAME_X_FLAGS_AREA_WIDTH (f),
969 row->visible_height);
dcd08bfb
GM
970 if (!face->stipple)
971 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
06a2c219
GM
972 }
973
974 /* Draw the right bitmap. */
975 if (bitmap != NO_BITMAP)
976 x_draw_bitmap (w, row, bitmap);
977}
978
dc6f92b8 979\f
06a2c219
GM
980/***********************************************************************
981 Line Highlighting
982 ***********************************************************************/
dc6f92b8 983
06a2c219
GM
984/* External interface to control of standout mode. Not used for X
985 frames. Aborts when called. */
986
987static void
dc6f92b8
JB
988XTreassert_line_highlight (new, vpos)
989 int new, vpos;
990{
06a2c219 991 abort ();
dc6f92b8
JB
992}
993
06a2c219
GM
994
995/* Call this when about to modify line at position VPOS and change
996 whether it is highlighted. Not used for X frames. Aborts when
997 called. */
dc6f92b8 998
dfcf069d 999static void
06a2c219
GM
1000x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
1001 int new_highlight, vpos, y, first_unused_hpos;
dc6f92b8 1002{
06a2c219 1003 abort ();
dc6f92b8
JB
1004}
1005
06a2c219
GM
1006
1007/* This is called when starting Emacs and when restarting after
1008 suspend. When starting Emacs, no X window is mapped. And nothing
1009 must be done to Emacs's own window if it is suspended (though that
1010 rarely happens). */
dc6f92b8 1011
dfcf069d 1012static void
dc6f92b8
JB
1013XTset_terminal_modes ()
1014{
1015}
1016
06a2c219
GM
1017/* This is called when exiting or suspending Emacs. Exiting will make
1018 the X-windows go away, and suspending requires no action. */
dc6f92b8 1019
dfcf069d 1020static void
dc6f92b8
JB
1021XTreset_terminal_modes ()
1022{
dc6f92b8 1023}
06a2c219
GM
1024
1025
dc6f92b8 1026\f
06a2c219
GM
1027/***********************************************************************
1028 Output Cursor
1029 ***********************************************************************/
1030
1031/* Set the global variable output_cursor to CURSOR. All cursor
1032 positions are relative to updated_window. */
dc6f92b8 1033
dfcf069d 1034static void
06a2c219
GM
1035set_output_cursor (cursor)
1036 struct cursor_pos *cursor;
dc6f92b8 1037{
06a2c219
GM
1038 output_cursor.hpos = cursor->hpos;
1039 output_cursor.vpos = cursor->vpos;
1040 output_cursor.x = cursor->x;
1041 output_cursor.y = cursor->y;
1042}
1043
1044
1045/* Set a nominal cursor position.
dc6f92b8 1046
06a2c219
GM
1047 HPOS and VPOS are column/row positions in a window glyph matrix. X
1048 and Y are window text area relative pixel positions.
1049
1050 If this is done during an update, updated_window will contain the
1051 window that is being updated and the position is the future output
1052 cursor position for that window. If updated_window is null, use
1053 selected_window and display the cursor at the given position. */
1054
1055static void
1056XTcursor_to (vpos, hpos, y, x)
1057 int vpos, hpos, y, x;
1058{
1059 struct window *w;
1060
1061 /* If updated_window is not set, work on selected_window. */
1062 if (updated_window)
1063 w = updated_window;
1064 else
1065 w = XWINDOW (selected_window);
dbcb258a 1066
06a2c219
GM
1067 /* Set the output cursor. */
1068 output_cursor.hpos = hpos;
1069 output_cursor.vpos = vpos;
1070 output_cursor.x = x;
1071 output_cursor.y = y;
dc6f92b8 1072
06a2c219
GM
1073 /* If not called as part of an update, really display the cursor.
1074 This will also set the cursor position of W. */
1075 if (updated_window == NULL)
dc6f92b8
JB
1076 {
1077 BLOCK_INPUT;
06a2c219 1078 x_display_cursor (w, 1, hpos, vpos, x, y);
334208b7 1079 XFlush (FRAME_X_DISPLAY (selected_frame));
dc6f92b8
JB
1080 UNBLOCK_INPUT;
1081 }
1082}
dc43ef94 1083
06a2c219
GM
1084
1085\f
1086/***********************************************************************
1087 Display Iterator
1088 ***********************************************************************/
1089
1090/* Function prototypes of this page. */
1091
1092static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1093 struct glyph *,
1094 XChar2b *));
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 *));
1100static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1101 int, int, double));
1102static void x_produce_glyphs P_ ((struct it *));
1103static void x_produce_special_glyphs P_ ((struct it *, enum display_element_type));
1104static void x_produce_image_glyph P_ ((struct it *it));
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. */
dc43ef94
KH
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))
1118
dc6f92b8 1119
06a2c219
GM
1120/* Get metrics of character CHAR2B in FONT. Value is always non-null.
1121 If CHAR2B is not contained in FONT, the font's default character
1122 metric is returned. */
dc43ef94 1123
06a2c219
GM
1124static INLINE XCharStruct *
1125x_per_char_metric (font, char2b)
1126 XFontStruct *font;
1127 XChar2b *char2b;
1128{
1129 /* The result metric information. */
1130 XCharStruct *pcm = NULL;
dc6f92b8 1131
06a2c219 1132 xassert (font && char2b);
dc6f92b8 1133
06a2c219 1134 if (font->per_char != NULL)
dc6f92b8 1135 {
06a2c219 1136 if (font->min_byte1 == 0 && font->max_byte1 == 0)
dc43ef94 1137 {
06a2c219
GM
1138 /* min_char_or_byte2 specifies the linear character index
1139 corresponding to the first element of the per_char array,
1140 max_char_or_byte2 is the index of the last character. A
1141 character with non-zero CHAR2B->byte1 is not in the font.
1142 A character with byte2 less than min_char_or_byte2 or
1143 greater max_char_or_byte2 is not in the font. */
1144 if (char2b->byte1 == 0
1145 && char2b->byte2 >= font->min_char_or_byte2
1146 && char2b->byte2 <= font->max_char_or_byte2)
1147 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
dc43ef94 1148 }
06a2c219 1149 else
dc6f92b8 1150 {
06a2c219
GM
1151 /* If either min_byte1 or max_byte1 are nonzero, both
1152 min_char_or_byte2 and max_char_or_byte2 are less than
1153 256, and the 2-byte character index values corresponding
1154 to the per_char array element N (counting from 0) are:
1155
1156 byte1 = N/D + min_byte1
1157 byte2 = N\D + min_char_or_byte2
1158
1159 where:
1160
1161 D = max_char_or_byte2 - min_char_or_byte2 + 1
1162 / = integer division
1163 \ = integer modulus */
1164 if (char2b->byte1 >= font->min_byte1
1165 && char2b->byte1 <= font->max_byte1
1166 && char2b->byte2 >= font->min_char_or_byte2
1167 && char2b->byte2 <= font->max_char_or_byte2)
1168 {
1169 pcm = (font->per_char
1170 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1171 * (char2b->byte1 - font->min_byte1))
1172 + (char2b->byte2 - font->min_char_or_byte2));
1173 }
dc6f92b8 1174 }
06a2c219
GM
1175 }
1176 else
1177 {
1178 /* If the per_char pointer is null, all glyphs between the first
1179 and last character indexes inclusive have the same
1180 information, as given by both min_bounds and max_bounds. */
1181 if (char2b->byte2 >= font->min_char_or_byte2
1182 && char2b->byte2 <= font->max_char_or_byte2)
1183 pcm = &font->max_bounds;
1184 }
dc6f92b8 1185
4a4dc352 1186
06a2c219
GM
1187 if (pcm == NULL || pcm->width == 0)
1188 {
1189 /* Character not contained in the font. FONT->default_char
1190 gives the character that will be printed. FONT->default_char
1191 is a 16-bit character code with byte1 in the most significant
1192 byte and byte2 in the least significant byte. */
1193 XChar2b default_char;
1194 default_char.byte1 = (font->default_char >> BITS_PER_CHAR) & 0xff;
1195 default_char.byte2 = font->default_char & 0xff;
1196
1197 /* Avoid an endless recursion if FONT->default_char itself
1198 hasn't per char metrics. handa@etl.go.jp reports that some
1199 fonts have this problem. */
1200 if (default_char.byte1 != char2b->byte1
1201 || default_char.byte2 != char2b->byte2)
1202 pcm = x_per_char_metric (font, &default_char);
1203 else
1204 pcm = &font->max_bounds;
1205 }
1206
1207 return pcm;
1208}
b73b6aaf 1209
57b03282 1210
06a2c219
GM
1211/* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1212 the two-byte form of C. Encoding is returned in *CHAR2B. */
dc43ef94 1213
06a2c219
GM
1214static INLINE void
1215x_encode_char (c, char2b, font_info)
1216 int c;
1217 XChar2b *char2b;
1218 struct font_info *font_info;
1219{
1220 int charset = CHAR_CHARSET (c);
1221 XFontStruct *font = font_info->font;
1222
1223 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1224 This may be either a program in a special encoder language or a
1225 fixed encoding. */
1226 if (font_info->font_encoder)
1227 {
1228 /* It's a program. */
1229 struct ccl_program *ccl = font_info->font_encoder;
1230
1231 if (CHARSET_DIMENSION (charset) == 1)
1232 {
1233 ccl->reg[0] = charset;
1234 ccl->reg[1] = char2b->byte2;
1235 }
1236 else
1237 {
1238 ccl->reg[0] = charset;
1239 ccl->reg[1] = char2b->byte1;
1240 ccl->reg[2] = char2b->byte2;
1241 }
1242
1243 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1244
1245 /* We assume that MSBs are appropriately set/reset by CCL
1246 program. */
1247 if (font->max_byte1 == 0) /* 1-byte font */
1248 char2b->byte2 = ccl->reg[1];
1249 else
1250 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1251 }
1252 else if (font_info->encoding[charset])
1253 {
1254 /* Fixed encoding scheme. See fontset.h for the meaning of the
1255 encoding numbers. */
1256 int enc = font_info->encoding[charset];
1257
1258 if ((enc == 1 || enc == 2)
1259 && CHARSET_DIMENSION (charset) == 2)
1260 char2b->byte1 |= 0x80;
1261
1262 if (enc == 1 || enc == 3)
1263 char2b->byte2 |= 0x80;
1264 }
1265}
1266
1267
1268/* Get face and two-byte form of character C in face FACE_ID on frame
1269 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1270 means we want to display multibyte text. Value is a pointer to a
1271 realized face that is ready for display. */
1272
1273static INLINE struct face *
1274x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1275 struct frame *f;
1276 int c, face_id;
1277 XChar2b *char2b;
1278 int multibyte_p;
1279{
1280 struct face *face = FACE_FROM_ID (f, face_id);
1281
1282 if (!multibyte_p)
1283 {
1284 /* Unibyte case. We don't have to encode, but we have to make
1285 sure to use a face suitable for unibyte. */
1286 char2b->byte1 = 0;
1287 char2b->byte2 = c;
1288
1289 if (!FACE_SUITABLE_FOR_CHARSET_P (face, -1))
1290 {
1291 face_id = FACE_FOR_CHARSET (f, face_id, -1);
1292 face = FACE_FROM_ID (f, face_id);
1293 }
1294 }
1295 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1296 {
1297 /* Case of ASCII in a face known to fit ASCII. */
1298 char2b->byte1 = 0;
1299 char2b->byte2 = c;
1300 }
1301 else
1302 {
1303 int c1, c2, charset;
1304
1305 /* Split characters into bytes. If c2 is -1 afterwards, C is
1306 really a one-byte character so that byte1 is zero. */
1307 SPLIT_CHAR (c, charset, c1, c2);
1308 if (c2 > 0)
1309 char2b->byte1 = c1, char2b->byte2 = c2;
1310 else
1311 char2b->byte1 = 0, char2b->byte2 = c1;
1312
1313 /* Get the face for displaying C. If `face' is not suitable for
1314 charset, get the one that fits. (This can happen for the
1315 translations of composite characters where the glyph
1316 specifies a face for ASCII, but translations have a different
1317 charset.) */
1318 if (!FACE_SUITABLE_FOR_CHARSET_P (face, charset))
1319 {
1320 face_id = FACE_FOR_CHARSET (f, face_id, charset);
1321 face = FACE_FROM_ID (f, face_id);
1322 }
1323
1324 /* Maybe encode the character in *CHAR2B. */
1325 if (charset != CHARSET_ASCII)
1326 {
1327 struct font_info *font_info
1328 = FONT_INFO_FROM_ID (f, face->font_info_id);
1329 if (font_info)
1330 {
1331 x_encode_char (c, char2b, font_info);
1332 if (charset == charset_latin_iso8859_1)
1333 {
1334 xassert (((XFontStruct *) font_info->font)->max_char_or_byte2
1335 >= 0x80);
1336 char2b->byte2 |= 0x80;
1337 }
1338 }
1339 }
1340 }
1341
1342 /* Make sure X resources of the face are allocated. */
1343 xassert (face != NULL);
1344 PREPARE_FACE_FOR_DISPLAY (f, face);
1345
1346 return face;
1347}
1348
1349
1350/* Get face and two-byte form of character glyph GLYPH on frame F.
1351 The encoding of GLYPH->u.ch.code is returned in *CHAR2B. Value is
1352 a pointer to a realized face that is ready for display. */
1353
1354static INLINE struct face *
1355x_get_glyph_face_and_encoding (f, glyph, char2b)
1356 struct frame *f;
1357 struct glyph *glyph;
1358 XChar2b *char2b;
1359{
1360 struct face *face;
1361
1362 xassert (glyph->type == CHAR_GLYPH);
1363 face = FACE_FROM_ID (f, glyph->u.ch.face_id);
1364
1365 if (!glyph->multibyte_p)
1366 {
1367 /* Unibyte case. We don't have to encode, but we have to make
1368 sure to use a face suitable for unibyte. */
1369 char2b->byte1 = 0;
1370 char2b->byte2 = glyph->u.ch.code;
1371 }
1372 else if (glyph->u.ch.code < 128
1373 && glyph->u.ch.face_id < BASIC_FACE_ID_SENTINEL)
1374 {
1375 /* Case of ASCII in a face known to fit ASCII. */
1376 char2b->byte1 = 0;
1377 char2b->byte2 = glyph->u.ch.code;
1378 }
1379 else
1380 {
1381 int c1, c2, charset;
1382
1383 /* Split characters into bytes. If c2 is -1 afterwards, C is
1384 really a one-byte character so that byte1 is zero. */
1385 SPLIT_CHAR (glyph->u.ch.code, charset, c1, c2);
1386 if (c2 > 0)
1387 char2b->byte1 = c1, char2b->byte2 = c2;
1388 else
1389 char2b->byte1 = 0, char2b->byte2 = c1;
1390
1391 /* Maybe encode the character in *CHAR2B. */
1392 if (charset != CHARSET_ASCII)
1393 {
1394 struct font_info *font_info
1395 = FONT_INFO_FROM_ID (f, face->font_info_id);
1396 if (font_info)
1397 {
1398 x_encode_char (glyph->u.ch.code, char2b, font_info);
1399 if (charset == charset_latin_iso8859_1)
1400 char2b->byte2 |= 0x80;
1401 }
1402 }
1403 }
1404
1405 /* Make sure X resources of the face are allocated. */
1406 xassert (face != NULL);
1407 PREPARE_FACE_FOR_DISPLAY (f, face);
1408 return face;
1409}
1410
1411
1412/* Store one glyph for IT->char_to_display in IT->glyph_row.
1413 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1414
1415static INLINE void
1416x_append_glyph (it)
1417 struct it *it;
1418{
1419 struct glyph *glyph;
1420 enum glyph_row_area area = it->area;
1421
1422 xassert (it->glyph_row);
1423 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1424
1425 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1426 if (glyph < it->glyph_row->glyphs[area + 1])
1427 {
1428 /* Play it safe. If sub-structures of the glyph are not all the
1429 same size, it otherwise be that some bits stay set. This
1430 would prevent a comparison with GLYPH_EQUAL_P. */
1431 glyph->u.val = 0;
1432
1433 glyph->type = CHAR_GLYPH;
1434 glyph->pixel_width = it->pixel_width;
1435 glyph->u.ch.code = it->char_to_display;
1436 glyph->u.ch.face_id = it->face_id;
1437 glyph->charpos = CHARPOS (it->position);
1438 glyph->object = it->object;
1439 glyph->left_box_line_p = it->start_of_box_run_p;
1440 glyph->right_box_line_p = it->end_of_box_run_p;
1441 glyph->voffset = it->voffset;
1442 glyph->multibyte_p = it->multibyte_p;
1443 ++it->glyph_row->used[area];
1444 }
1445}
1446
1447
1448/* Change IT->ascent and IT->height according to the setting of
1449 IT->voffset. */
1450
1451static INLINE void
1452take_vertical_position_into_account (it)
1453 struct it *it;
1454{
1455 if (it->voffset)
1456 {
1457 if (it->voffset < 0)
1458 /* Increase the ascent so that we can display the text higher
1459 in the line. */
1460 it->ascent += abs (it->voffset);
1461 else
1462 /* Increase the descent so that we can display the text lower
1463 in the line. */
1464 it->descent += it->voffset;
1465 }
1466}
1467
1468
1469/* Produce glyphs/get display metrics for the image IT is loaded with.
1470 See the description of struct display_iterator in dispextern.h for
1471 an overview of struct display_iterator. */
1472
1473static void
1474x_produce_image_glyph (it)
1475 struct it *it;
1476{
1477 struct image *img;
1478 struct face *face;
1479
1480 xassert (it->what == IT_IMAGE);
1481
1482 face = FACE_FROM_ID (it->f, it->face_id);
1483 img = IMAGE_FROM_ID (it->f, it->image_id);
1484 xassert (img);
1485
1486 /* Make sure X resources of the face and image are loaded. */
1487 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1488 prepare_image_for_display (it->f, img);
1489
1490 it->ascent = IMAGE_ASCENT (img);
1491 it->descent = img->height + 2 * img->margin - it->ascent;
1492 it->pixel_width = img->width + 2 * img->margin;
1493
1494 it->nglyphs = 1;
1495
1496 if (face->box != FACE_NO_BOX)
1497 {
1498 it->ascent += face->box_line_width;
1499 it->descent += face->box_line_width;
1500
1501 if (it->start_of_box_run_p)
1502 it->pixel_width += face->box_line_width;
1503 if (it->end_of_box_run_p)
1504 it->pixel_width += face->box_line_width;
1505 }
1506
1507 take_vertical_position_into_account (it);
1508
1509 if (it->glyph_row)
1510 {
1511 struct glyph *glyph;
1512 enum glyph_row_area area = it->area;
1513
1514 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1515 if (glyph < it->glyph_row->glyphs[area + 1])
1516 {
1517 glyph->type = IMAGE_GLYPH;
1518 glyph->u.img.id = img->id;
1519 glyph->u.img.face_id = it->face_id;
1520 glyph->pixel_width = it->pixel_width;
1521 glyph->charpos = CHARPOS (it->position);
1522 glyph->object = it->object;
1523 glyph->left_box_line_p = it->start_of_box_run_p;
1524 glyph->right_box_line_p = it->end_of_box_run_p;
1525 glyph->voffset = it->voffset;
1526 glyph->multibyte_p = it->multibyte_p;
1527 ++it->glyph_row->used[area];
1528 }
1529 }
1530}
1531
1532
1533/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1534 of the glyph, WIDTH and HEIGHT are the width and height of the
1535 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1536 ascent of the glyph (0 <= ASCENT <= 1). */
1537
1538static void
1539x_append_stretch_glyph (it, object, width, height, ascent)
1540 struct it *it;
1541 Lisp_Object object;
1542 int width, height;
1543 double ascent;
1544{
1545 struct glyph *glyph;
1546 enum glyph_row_area area = it->area;
1547
1548 xassert (ascent >= 0 && ascent <= 1);
1549
1550 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1551 if (glyph < it->glyph_row->glyphs[area + 1])
1552 {
1553 glyph->type = STRETCH_GLYPH;
1554 glyph->u.stretch.ascent = height * ascent;
1555 glyph->u.stretch.height = height;
1556 glyph->u.stretch.face_id = it->face_id;
1557 glyph->pixel_width = width;
1558 glyph->charpos = CHARPOS (it->position);
1559 glyph->object = object;
1560 glyph->left_box_line_p = it->start_of_box_run_p;
1561 glyph->right_box_line_p = it->end_of_box_run_p;
1562 glyph->voffset = it->voffset;
1563 glyph->multibyte_p = it->multibyte_p;
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. */
1611 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1612 extern Lisp_Object QCrelative_width, QCrelative_height;
1613 extern Lisp_Object QCalign_to;
1614 Lisp_Object prop, plist;
1615 double width = 0, height = 0, ascent = 0;
1616 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1617 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1618
1619 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1620
1621 /* List should start with `space'. */
1622 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1623 plist = XCDR (it->object);
1624
1625 /* Compute the width of the stretch. */
1626 if (prop = Fplist_get (plist, QCwidth),
1627 NUMVAL (prop) > 0)
1628 /* Absolute width `:width WIDTH' specified and valid. */
1629 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1630 else if (prop = Fplist_get (plist, QCrelative_width),
1631 NUMVAL (prop) > 0)
1632 {
1633 /* Relative width `:relative-width FACTOR' specified and valid.
1634 Compute the width of the characters having the `glyph'
1635 property. */
1636 struct it it2;
1637 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1638
1639 it2 = *it;
1640 if (it->multibyte_p)
1641 {
1642 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1643 - IT_BYTEPOS (*it));
1644 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1645 }
1646 else
1647 it2.c = *p, it2.len = 1;
1648
1649 it2.glyph_row = NULL;
1650 it2.what = IT_CHARACTER;
1651 x_produce_glyphs (&it2);
1652 width = NUMVAL (prop) * it2.pixel_width;
1653 }
1654 else if (prop = Fplist_get (plist, QCalign_to),
1655 NUMVAL (prop) > 0)
1656 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1657 else
1658 /* Nothing specified -> width defaults to canonical char width. */
1659 width = CANON_X_UNIT (it->f);
1660
1661 /* Compute height. */
1662 if (prop = Fplist_get (plist, QCheight),
1663 NUMVAL (prop) > 0)
1664 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1665 else if (prop = Fplist_get (plist, QCrelative_height),
1666 NUMVAL (prop) > 0)
1667 height = FONT_HEIGHT (font) * NUMVAL (prop);
1668 else
1669 height = FONT_HEIGHT (font);
1670
1671 /* Compute percentage of height used for ascent. If
1672 `:ascent ASCENT' is present and valid, use that. Otherwise,
1673 derive the ascent from the font in use. */
1674 if (prop = Fplist_get (plist, QCascent),
1675 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1676 ascent = NUMVAL (prop) / 100.0;
1677 else
1678 ascent = (double) font->ascent / FONT_HEIGHT (font);
1679
1680 if (width <= 0)
1681 width = 1;
1682 if (height <= 0)
1683 height = 1;
1684
1685 if (it->glyph_row)
1686 {
1687 Lisp_Object object = it->stack[it->sp - 1].string;
1688 if (!STRINGP (object))
1689 object = it->w->buffer;
1690 x_append_stretch_glyph (it, object, width, height, ascent);
1691 }
1692
1693 it->pixel_width = width;
1694 it->ascent = height * ascent;
1695 it->descent = height - it->ascent;
1696 it->nglyphs = 1;
1697
1698 if (face->box != FACE_NO_BOX)
1699 {
1700 it->ascent += face->box_line_width;
1701 it->descent += face->box_line_width;
1702
1703 if (it->start_of_box_run_p)
1704 it->pixel_width += face->box_line_width;
1705 if (it->end_of_box_run_p)
1706 it->pixel_width += face->box_line_width;
1707 }
1708
1709 take_vertical_position_into_account (it);
1710}
1711
1712
1713/* Produce glyphs/get display metrics for the display element IT is
1714 loaded with. See the description of struct display_iterator in
1715 dispextern.h for an overview of struct display_iterator. */
1716
1717static void
1718x_produce_glyphs (it)
1719 struct it *it;
1720{
1721 if (it->what == IT_CHARACTER)
1722 {
1723 XChar2b char2b;
1724 XFontStruct *font;
1725 struct face *face;
1726 XCharStruct *pcm;
1727 struct it ci;
1728 int font_not_found_p;
1729 int c;
1730
1731 /* Maybe translate single-byte characters to multibyte. */
1732 it->char_to_display = it->c;
1733 if (unibyte_display_via_language_environment
1734 && SINGLE_BYTE_CHAR_P (it->c)
1735 && (it->c >= 0240
1736 || (it->c >= 0200
1737 && !NILP (Vnonascii_translation_table))))
1738 {
1739 it->char_to_display = unibyte_char_to_multibyte (it->c);
1740 it->charset = CHAR_CHARSET (it->char_to_display);
1741 }
1742
1743 /* Get face and font to use. Encode IT->char_to_display. */
1744 face = x_get_char_face_and_encoding (it->f, it->char_to_display,
1745 it->face_id, &char2b,
1746 it->multibyte_p);
1747 font = face->font;
1748
1749 /* When no suitable font found, use the default font. */
1750 font_not_found_p = font == NULL;
1751 if (font_not_found_p)
1752 font = FRAME_FONT (it->f);
1753
1754 if (it->char_to_display >= ' '
1755 && (!it->multibyte_p || it->char_to_display < 128))
1756 {
1757 /* Either unibyte or ASCII. */
1758 int stretched_p;
1759
1760 it->nglyphs = 1;
1761 it->ascent = font->ascent;
1762 it->descent = font->descent;
1763
1764 pcm = x_per_char_metric (font, &char2b);
1765 it->pixel_width = pcm->width;
1766
1767 /* If this is a space inside a region of text with
1768 `space-width' property, change its width. */
1769 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1770 if (stretched_p)
1771 it->pixel_width *= XFLOATINT (it->space_width);
1772
1773 /* If face has a box, add the box thickness to the character
1774 height. If character has a box line to the left and/or
1775 right, add the box line width to the character's width. */
1776 if (face->box != FACE_NO_BOX)
1777 {
1778 int thick = face->box_line_width;
1779
1780 it->ascent += thick;
1781 it->descent += thick;
1782
1783 if (it->start_of_box_run_p)
1784 it->pixel_width += thick;
1785 if (it->end_of_box_run_p)
1786 it->pixel_width += thick;
1787 }
1788
1789 /* If face has an overline, add the height of the overline
1790 (1 pixel) and a 1 pixel margin to the character height. */
1791 if (face->overline_p)
1792 it->ascent += 2;
1793
1794 take_vertical_position_into_account (it);
1795
1796 /* If we have to actually produce glyphs, do it. */
1797 if (it->glyph_row)
1798 {
1799 if (stretched_p)
1800 {
1801 /* Translate a space with a `space-width' property
1802 into a stretch glyph. */
1803 double ascent = (double) font->ascent / FONT_HEIGHT (font);
1804 x_append_stretch_glyph (it, it->object, it->pixel_width,
1805 it->ascent + it->descent, ascent);
1806 }
1807 else
1808 x_append_glyph (it);
1809
1810 /* If characters with lbearing or rbearing are displayed
1811 in this line, record that fact in a flag of the
1812 glyph row. This is used to optimize X output code. */
1813 if (pcm->lbearing < 0
1814 || pcm->rbearing > pcm->width)
1815 it->glyph_row->contains_overlapping_glyphs_p = 1;
1816 }
1817 }
1818 else if (it->char_to_display == '\n')
1819 {
1820 /* A newline has no width but we need the height of the line. */
1821 it->pixel_width = 0;
1822 it->nglyphs = 0;
1823 it->ascent = font->ascent;
1824 it->descent = font->descent;
1825
1826 if (face->box != FACE_NO_BOX)
1827 {
1828 int thick = face->box_line_width;
1829 it->ascent += thick;
1830 it->descent += thick;
1831 }
1832 }
1833 else if (it->char_to_display == '\t')
1834 {
1835 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1836 int x = (it->current_x
1837 - it->prompt_width
1838 + it->continuation_lines_width);
1839 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1840
1841 it->pixel_width = next_tab_x - x;
1842 it->nglyphs = 1;
1843 it->ascent = font->ascent;
1844 it->descent = font->descent;
1845
1846 if (it->glyph_row)
1847 {
1848 double ascent = (double) it->ascent / (it->ascent + it->descent);
1849 x_append_stretch_glyph (it, it->object, it->pixel_width,
1850 it->ascent + it->descent, ascent);
1851 }
1852 }
1853 else
1854 {
1855 /* A multi-byte character. Assume that the display width of the
1856 character is the width of the character multiplied by the
1857 width of the font. There has to be better support for
1858 variable sizes in cmpchar_info to do anything better than
1859 that.
1860
1861 Note: composite characters are represented as one glyph in
1862 the glyph matrix. There are no padding glyphs. */
1863 if (it->charset == CHARSET_COMPOSITION)
1864 {
1865 struct cmpchar_info *cmpcharp;
1866 int idx;
1867
1868 idx = COMPOSITE_CHAR_ID (it->char_to_display);
1869 cmpcharp = cmpchar_table[idx];
1870 it->pixel_width = font->max_bounds.width * cmpcharp->width;
1871
1872 /* There are no padding glyphs, so there is only one glyph
1873 to produce for the composite char. Important is that
1874 pixel_width, ascent and descent are the values of what is
1875 drawn by draw_glyphs. */
1876 it->nglyphs = 1;
1877
1878 /* These settings may not be correct. We must have more
1879 information in cmpcharp to do the correct setting. */
1880 it->ascent = font->ascent;
1881 it->descent = font->descent;
1882 }
1883 else
1884 {
1885 /* If we found a font, this font should give us the right
1886 metrics. If we didn't find a font, use the frame's
1887 default font and calculate the width of the character
1888 from the charset width; this is what old redisplay code
1889 did. */
1890 pcm = x_per_char_metric (font, &char2b);
1891 it->pixel_width = pcm->width;
1892 if (font_not_found_p)
1893 it->pixel_width *= CHARSET_WIDTH (it->charset);
1894 it->nglyphs = 1;
1895 it->ascent = font->ascent;
1896 it->descent = font->descent;
1897 if (it->glyph_row
1898 && (pcm->lbearing < 0
1899 || pcm->rbearing > pcm->width))
1900 it->glyph_row->contains_overlapping_glyphs_p = 1;
1901 }
1902
1903 if (face->box != FACE_NO_BOX)
1904 {
1905 int thick = face->box_line_width;
1906 it->ascent += thick;
1907 it->descent += thick;
1908
1909 if (it->start_of_box_run_p)
1910 it->pixel_width += thick;
1911 if (it->end_of_box_run_p)
1912 it->pixel_width += thick;
1913 }
1914
1915 /* If face has an overline, add the height of the overline
1916 (1 pixel) and a 1 pixel margin to the character height. */
1917 if (face->overline_p)
1918 it->ascent += 2;
1919
1920 take_vertical_position_into_account (it);
1921
1922 if (it->glyph_row)
1923 x_append_glyph (it);
1924 }
1925 }
1926 else if (it->what == IT_IMAGE)
1927 x_produce_image_glyph (it);
1928 else if (it->what == IT_STRETCH)
1929 x_produce_stretch_glyph (it);
1930
1931 /* Accumulate dimensions. */
1932 xassert (it->ascent >= 0 && it->descent > 0);
1933 if (it->area == TEXT_AREA)
1934 it->current_x += it->pixel_width;
1935 it->max_ascent = max (it->max_ascent, it->ascent);
1936 it->max_descent = max (it->max_descent, it->descent);
1937}
1938
1939
1940/* Estimate the pixel height of the mode or top line on frame F.
1941 FACE_ID specifies what line's height to estimate. */
1942
1943int
1944x_estimate_mode_line_height (f, face_id)
1945 struct frame *f;
1946 enum face_id face_id;
1947{
1948 int height = 1;
1949
1950 /* This function is called so early when Emacs starts that the face
1951 cache and mode line face are not yet initialized. */
1952 if (FRAME_FACE_CACHE (f))
1953 {
1954 struct face *face = FACE_FROM_ID (f, face_id);
1955 if (face)
1956 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
1957 }
1958
1959 return height;
1960}
1961
1962\f
1963/***********************************************************************
1964 Glyph display
1965 ***********************************************************************/
1966
1967/* A sequence of glyphs to be drawn in the same face.
1968
1969 This data structure is not really completely X specific, so it
1970 could possibly, at least partially, be useful for other systems. It
1971 is currently not part of the external redisplay interface because
1972 it's not clear what other systems will need. */
1973
1974struct glyph_string
1975{
1976 /* X-origin of the string. */
1977 int x;
1978
1979 /* Y-origin and y-position of the base line of this string. */
1980 int y, ybase;
1981
1982 /* The width of the string, not including a face extension. */
1983 int width;
1984
1985 /* The width of the string, including a face extension. */
1986 int background_width;
1987
1988 /* The height of this string. This is the height of the line this
1989 string is drawn in, and can be different from the height of the
1990 font the string is drawn in. */
1991 int height;
1992
1993 /* Number of pixels this string overwrites in front of its x-origin.
1994 This number is zero if the string has an lbearing >= 0; it is
1995 -lbearing, if the string has an lbearing < 0. */
1996 int left_overhang;
1997
1998 /* Number of pixels this string overwrites past its right-most
1999 nominal x-position, i.e. x + width. Zero if the string's
2000 rbearing is <= its nominal width, rbearing - width otherwise. */
2001 int right_overhang;
2002
2003 /* The frame on which the glyph string is drawn. */
2004 struct frame *f;
2005
2006 /* The window on which the glyph string is drawn. */
2007 struct window *w;
2008
2009 /* X display and window for convenience. */
2010 Display *display;
2011 Window window;
2012
2013 /* The glyph row for which this string was built. It determines the
2014 y-origin and height of the string. */
2015 struct glyph_row *row;
2016
2017 /* The area within row. */
2018 enum glyph_row_area area;
2019
2020 /* Characters to be drawn, and number of characters. */
2021 XChar2b *char2b;
2022 int nchars;
2023
2024 /* Character set of this glyph string. */
2025 int charset;
2026
2027 /* A face-override for drawing cursors, mouse face and similar. */
2028 enum draw_glyphs_face hl;
2029
2030 /* Face in which this string is to be drawn. */
2031 struct face *face;
2032
2033 /* Font in which this string is to be drawn. */
2034 XFontStruct *font;
2035
2036 /* Font info for this string. */
2037 struct font_info *font_info;
2038
2039 /* Non-null means this string describes (part of) a composite
2040 character. All characters from char2b are drawn at the same
2041 x-origin in that case. */
2042 struct cmpchar_info *cmpcharp;
2043
2044 /* Index of this glyph string's first character in the glyph
2045 definition of cmpcharp. If this is zero, this glyph string
2046 describes the first character of a composite character. */
2047 int gidx;
2048
2049 /* 1 means this glyph strings face has to be drawn to the right end
2050 of the window's drawing area. */
2051 unsigned extends_to_end_of_line_p : 1;
2052
2053 /* 1 means the background of this string has been drawn. */
2054 unsigned background_filled_p : 1;
2055
2056 /* 1 means glyph string must be drawn with 16-bit functions. */
2057 unsigned two_byte_p : 1;
2058
2059 /* 1 means that the original font determined for drawing this glyph
2060 string could not be loaded. The member `font' has been set to
2061 the frame's default font in this case. */
2062 unsigned font_not_found_p : 1;
2063
2064 /* 1 means that the face in which this glyph string is drawn has a
2065 stipple pattern. */
2066 unsigned stippled_p : 1;
2067
2068 /* The GC to use for drawing this glyph string. */
2069 GC gc;
2070
2071 /* A pointer to the first glyph in the string. This glyph
2072 corresponds to char2b[0]. Needed to draw rectangles if
2073 font_not_found_p is 1. */
2074 struct glyph *first_glyph;
2075
2076 /* Image, if any. */
2077 struct image *img;
2078
2079 struct glyph_string *next, *prev;
2080};
2081
2082
2083#if GLYPH_DEBUG
2084
2085static void
2086x_dump_glyph_string (s)
2087 struct glyph_string *s;
2088{
2089 fprintf (stderr, "glyph string\n");
2090 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2091 s->x, s->y, s->width, s->height);
2092 fprintf (stderr, " ybase = %d\n", s->ybase);
2093 fprintf (stderr, " hl = %d\n", s->hl);
2094 fprintf (stderr, " left overhang = %d, right = %d\n",
2095 s->left_overhang, s->right_overhang);
2096 fprintf (stderr, " nchars = %d\n", s->nchars);
2097 fprintf (stderr, " extends to end of line = %d\n",
2098 s->extends_to_end_of_line_p);
2099 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2100 fprintf (stderr, " bg width = %d\n", s->background_width);
2101}
2102
2103#endif /* GLYPH_DEBUG */
2104
2105
2106
2107static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2108 struct glyph_string **,
2109 struct glyph_string *,
2110 struct glyph_string *));
2111static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2112 struct glyph_string **,
2113 struct glyph_string *,
2114 struct glyph_string *));
2115static void x_append_glyph_string P_ ((struct glyph_string **,
2116 struct glyph_string **,
2117 struct glyph_string *));
2118static int x_left_overwritten P_ ((struct glyph_string *));
2119static int x_left_overwriting P_ ((struct glyph_string *));
2120static int x_right_overwritten P_ ((struct glyph_string *));
2121static int x_right_overwriting P_ ((struct glyph_string *));
2122static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int));
2123static void x_init_glyph_string P_ ((struct glyph_string *,
2124 XChar2b *, struct window *,
2125 struct glyph_row *,
2126 enum glyph_row_area, int,
2127 enum draw_glyphs_face));
2128static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2129 enum glyph_row_area, int, int,
2130 enum draw_glyphs_face, int *, int *));
2131static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2132static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2133static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2134 int));
2135static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2136static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
2137static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2138static void x_draw_glyph_string P_ ((struct glyph_string *));
2139static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2140static void x_set_cursor_gc P_ ((struct glyph_string *));
2141static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2142static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2143static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
2144 int *, int *));
2145static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2146static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
2147 unsigned long *, float, int));
2148static void x_setup_relief_color P_ ((struct frame *, struct relief *,
2149 float, int, unsigned long));
2150static void x_setup_relief_colors P_ ((struct glyph_string *));
2151static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2152static void x_draw_image_relief P_ ((struct glyph_string *));
2153static void x_draw_image_foreground P_ ((struct glyph_string *));
2154static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
2155static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2156static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2157 int, int, int));
2158static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2159 int, int, int, int, XRectangle *));
2160static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2161 int, int, int, XRectangle *));
2162
2163
2164
2165/* Append the list of glyph strings with head H and tail T to the list
2166 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2167
2168static INLINE void
2169x_append_glyph_string_lists (head, tail, h, t)
2170 struct glyph_string **head, **tail;
2171 struct glyph_string *h, *t;
2172{
2173 if (h)
2174 {
2175 if (*head)
2176 (*tail)->next = h;
2177 else
2178 *head = h;
2179 h->prev = *tail;
2180 *tail = t;
2181 }
2182}
2183
2184
2185/* Prepend the list of glyph strings with head H and tail T to the
2186 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2187 result. */
2188
2189static INLINE void
2190x_prepend_glyph_string_lists (head, tail, h, t)
2191 struct glyph_string **head, **tail;
2192 struct glyph_string *h, *t;
2193{
2194 if (h)
2195 {
2196 if (*head)
2197 (*head)->prev = t;
2198 else
2199 *tail = t;
2200 t->next = *head;
2201 *head = h;
2202 }
2203}
2204
2205
2206/* Append glyph string S to the list with head *HEAD and tail *TAIL.
2207 Set *HEAD and *TAIL to the resulting list. */
2208
2209static INLINE void
2210x_append_glyph_string (head, tail, s)
2211 struct glyph_string **head, **tail;
2212 struct glyph_string *s;
2213{
2214 s->next = s->prev = NULL;
2215 x_append_glyph_string_lists (head, tail, s, s);
2216}
2217
2218
2219/* Set S->gc to a suitable GC for drawing glyph string S in cursor
2220 face. */
2221
2222static void
2223x_set_cursor_gc (s)
2224 struct glyph_string *s;
2225{
2226 if (s->font == FRAME_FONT (s->f)
2227 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2228 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2229 && !s->cmpcharp)
2230 s->gc = s->f->output_data.x->cursor_gc;
2231 else
2232 {
2233 /* Cursor on non-default face: must merge. */
2234 XGCValues xgcv;
2235 unsigned long mask;
2236
2237 xgcv.background = s->f->output_data.x->cursor_pixel;
2238 xgcv.foreground = s->face->background;
2239
2240 /* If the glyph would be invisible, try a different foreground. */
2241 if (xgcv.foreground == xgcv.background)
2242 xgcv.foreground = s->face->foreground;
2243 if (xgcv.foreground == xgcv.background)
2244 xgcv.foreground = s->f->output_data.x->cursor_foreground_pixel;
2245 if (xgcv.foreground == xgcv.background)
2246 xgcv.foreground = s->face->foreground;
2247
2248 /* Make sure the cursor is distinct from text in this face. */
2249 if (xgcv.background == s->face->background
2250 && xgcv.foreground == s->face->foreground)
2251 {
2252 xgcv.background = s->face->foreground;
2253 xgcv.foreground = s->face->background;
2254 }
2255
2256 IF_DEBUG (x_check_font (s->f, s->font));
2257 xgcv.font = s->font->fid;
2258 xgcv.graphics_exposures = False;
2259 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2260
2261 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2262 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2263 mask, &xgcv);
2264 else
2265 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2266 = XCreateGC (s->display, s->window, mask, &xgcv);
2267
2268 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2269 }
2270}
2271
2272
2273/* Set up S->gc of glyph string S for drawing text in mouse face. */
2274
2275static void
2276x_set_mouse_face_gc (s)
2277 struct glyph_string *s;
2278{
2279 int face_id;
2280
2281 /* What face has to be used for the mouse face? */
2282 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
2283 face_id = FACE_FOR_CHARSET (s->f, face_id, s->charset);
2284 s->face = FACE_FROM_ID (s->f, face_id);
2285 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2286
2287 /* If font in this face is same as S->font, use it. */
2288 if (s->font == s->face->font)
2289 s->gc = s->face->gc;
2290 else
2291 {
2292 /* Otherwise construct scratch_cursor_gc with values from FACE
2293 but font FONT. */
2294 XGCValues xgcv;
2295 unsigned long mask;
2296
2297 xgcv.background = s->face->background;
2298 xgcv.foreground = s->face->foreground;
2299 IF_DEBUG (x_check_font (s->f, s->font));
2300 xgcv.font = s->font->fid;
2301 xgcv.graphics_exposures = False;
2302 mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
2303
2304 if (FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2305 XChangeGC (s->display, FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2306 mask, &xgcv);
2307 else
2308 FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc
2309 = XCreateGC (s->display, s->window, mask, &xgcv);
2310
2311 s->gc = FRAME_X_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2312 }
2313
2314 xassert (s->gc != 0);
2315}
2316
2317
2318/* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2319 Faces to use in the mode line have already been computed when the
2320 matrix was built, so there isn't much to do, here. */
2321
2322static INLINE void
2323x_set_mode_line_face_gc (s)
2324 struct glyph_string *s;
2325{
2326 s->gc = s->face->gc;
2327 xassert (s->gc != 0);
2328}
2329
2330
2331/* Set S->gc of glyph string S for drawing that glyph string. Set
2332 S->stippled_p to a non-zero value if the face of S has a stipple
2333 pattern. */
2334
2335static INLINE void
2336x_set_glyph_string_gc (s)
2337 struct glyph_string *s;
2338{
2339 if (s->hl == DRAW_NORMAL_TEXT)
2340 {
2341 s->gc = s->face->gc;
2342 s->stippled_p = s->face->stipple != 0;
2343 }
2344 else if (s->hl == DRAW_INVERSE_VIDEO)
2345 {
2346 x_set_mode_line_face_gc (s);
2347 s->stippled_p = s->face->stipple != 0;
2348 }
2349 else if (s->hl == DRAW_CURSOR)
2350 {
2351 x_set_cursor_gc (s);
2352 s->stippled_p = 0;
2353 }
2354 else if (s->hl == DRAW_MOUSE_FACE)
2355 {
2356 x_set_mouse_face_gc (s);
2357 s->stippled_p = s->face->stipple != 0;
2358 }
2359 else if (s->hl == DRAW_IMAGE_RAISED
2360 || s->hl == DRAW_IMAGE_SUNKEN)
2361 {
2362 s->gc = s->face->gc;
2363 s->stippled_p = s->face->stipple != 0;
2364 }
2365 else
2366 {
2367 s->gc = s->face->gc;
2368 s->stippled_p = s->face->stipple != 0;
2369 }
2370
2371 /* GC must have been set. */
2372 xassert (s->gc != 0);
2373}
2374
2375
2376/* Return in *R the clipping rectangle for glyph string S. */
2377
2378static void
2379x_get_glyph_string_clip_rect (s, r)
2380 struct glyph_string *s;
2381 XRectangle *r;
2382{
2383 if (s->row->full_width_p)
2384 {
2385 /* Draw full-width. X coordinates are relative to S->w->left. */
1da3fd71
GM
2386 int canon_x = CANON_X_UNIT (s->f);
2387
2388 r->x = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2389 r->width = XFASTINT (s->w->width) * canon_x;
06a2c219
GM
2390
2391 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2392 {
1da3fd71 2393 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
06a2c219
GM
2394 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2395 r->x -= width;
2396 }
2397
b9432a85 2398 r->x += FRAME_INTERNAL_BORDER_WIDTH (s->f);
1da3fd71 2399
06a2c219
GM
2400 /* Unless displaying a mode or menu bar line, which are always
2401 fully visible, clip to the visible part of the row. */
2402 if (s->w->pseudo_window_p)
2403 r->height = s->row->visible_height;
2404 else
2405 r->height = s->height;
2406 }
2407 else
2408 {
2409 /* This is a text line that may be partially visible. */
2410 r->x = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2411 r->width = window_box_width (s->w, s->area);
2412 r->height = s->row->visible_height;
2413 }
2414
2415 /* Don't use S->y for clipping because it doesn't take partially
2416 visible lines into account. For example, it can be negative for
2417 partially visible lines at the top of a window. */
2418 if (!s->row->full_width_p
2419 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2420 r->y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (s->w);
2421 else
2422 r->y = max (0, s->row->y);
2423 r->y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->y);
2424
2425 /* If drawing a toolbar window, draw it over the internal border
2426 at the top of the window. */
2427 if (s->w == XWINDOW (s->f->toolbar_window))
2428 r->y -= s->f->output_data.x->internal_border_width;
2429}
2430
2431
2432/* Set clipping for output of glyph string S. S may be part of a mode
2433 line or menu if we don't have X toolkit support. */
2434
2435static INLINE void
2436x_set_glyph_string_clipping (s)
2437 struct glyph_string *s;
2438{
2439 XRectangle r;
2440 x_get_glyph_string_clip_rect (s, &r);
2441 XSetClipRectangles (s->display, s->gc, 0, 0, &r, 1, Unsorted);
2442}
2443
2444
2445/* Compute left and right overhang of glyph string S. If S is a glyph
2446 string for a composite character, assume overhangs don't exist. */
2447
2448static INLINE void
2449x_compute_glyph_string_overhangs (s)
2450 struct glyph_string *s;
2451{
2452 if (s->cmpcharp == NULL
2453 && s->first_glyph->type == CHAR_GLYPH)
2454 {
2455 XCharStruct cs;
2456 int direction, font_ascent, font_descent;
2457 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2458 &font_ascent, &font_descent, &cs);
2459 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2460 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2461 }
2462}
2463
2464
2465/* Compute overhangs and x-positions for glyph string S and its
2466 predecessors, or successors. X is the starting x-position for S.
2467 BACKWARD_P non-zero means process predecessors. */
2468
2469static void
2470x_compute_overhangs_and_x (s, x, backward_p)
2471 struct glyph_string *s;
2472 int x;
2473 int backward_p;
2474{
2475 if (backward_p)
2476 {
2477 while (s)
2478 {
2479 x_compute_glyph_string_overhangs (s);
2480 x -= s->width;
2481 s->x = x;
2482 s = s->prev;
2483 }
2484 }
2485 else
2486 {
2487 while (s)
2488 {
2489 x_compute_glyph_string_overhangs (s);
2490 s->x = x;
2491 x += s->width;
2492 s = s->next;
2493 }
2494 }
2495}
2496
2497
2498/* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2499 frame F. Overhangs of glyphs other than type CHAR_GLYPH or of
2500 character glyphs for composite characters are assumed to be zero. */
2501
2502static void
2503x_get_glyph_overhangs (glyph, f, left, right)
2504 struct glyph *glyph;
2505 struct frame *f;
2506 int *left, *right;
2507{
2508 int c;
2509
2510 *left = *right = 0;
2511
2512 if (glyph->type == CHAR_GLYPH
2513 && (c = glyph->u.ch.code,
2514 CHAR_CHARSET (c) != CHARSET_COMPOSITION))
2515 {
2516 XFontStruct *font;
2517 struct face *face;
2518 struct font_info *font_info;
2519 XChar2b char2b;
2520
2521 face = x_get_glyph_face_and_encoding (f, glyph, &char2b);
2522 font = face->font;
2523 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2524 if (font)
2525 {
2526 XCharStruct *pcm = x_per_char_metric (font, &char2b);
2527
2528 if (pcm->rbearing > pcm->width)
2529 *right = pcm->rbearing - pcm->width;
2530 if (pcm->lbearing < 0)
2531 *left = -pcm->lbearing;
2532 }
2533 }
2534}
2535
2536
2537/* Return the index of the first glyph preceding glyph string S that
2538 is overwritten by S because of S's left overhang. Value is -1
2539 if no glyphs are overwritten. */
2540
2541static int
2542x_left_overwritten (s)
2543 struct glyph_string *s;
2544{
2545 int k;
2546
2547 if (s->left_overhang)
2548 {
2549 int x = 0, i;
2550 struct glyph *glyphs = s->row->glyphs[s->area];
2551 int first = s->first_glyph - glyphs;
2552
2553 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2554 x -= glyphs[i].pixel_width;
2555
2556 k = i + 1;
2557 }
2558 else
2559 k = -1;
2560
2561 return k;
2562}
2563
2564
2565/* Return the index of the first glyph preceding glyph string S that
2566 is overwriting S because of its right overhang. Value is -1 if no
2567 glyph in front of S overwrites S. */
2568
2569static int
2570x_left_overwriting (s)
2571 struct glyph_string *s;
2572{
2573 int i, k, x;
2574 struct glyph *glyphs = s->row->glyphs[s->area];
2575 int first = s->first_glyph - glyphs;
2576
2577 k = -1;
2578 x = 0;
2579 for (i = first - 1; i >= 0; --i)
2580 {
2581 int left, right;
2582 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2583 if (x + right > 0)
2584 k = i;
2585 x -= glyphs[i].pixel_width;
2586 }
2587
2588 return k;
2589}
2590
2591
2592/* Return the index of the last glyph following glyph string S that is
2593 not overwritten by S because of S's right overhang. Value is -1 if
2594 no such glyph is found. */
2595
2596static int
2597x_right_overwritten (s)
2598 struct glyph_string *s;
2599{
2600 int k = -1;
2601
2602 if (s->right_overhang)
2603 {
2604 int x = 0, i;
2605 struct glyph *glyphs = s->row->glyphs[s->area];
2606 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2607 int end = s->row->used[s->area];
2608
2609 for (i = first; i < end && s->right_overhang > x; ++i)
2610 x += glyphs[i].pixel_width;
2611
2612 k = i;
2613 }
2614
2615 return k;
2616}
2617
2618
2619/* Return the index of the last glyph following glyph string S that
2620 overwrites S because of its left overhang. Value is negative
2621 if no such glyph is found. */
2622
2623static int
2624x_right_overwriting (s)
2625 struct glyph_string *s;
2626{
2627 int i, k, x;
2628 int end = s->row->used[s->area];
2629 struct glyph *glyphs = s->row->glyphs[s->area];
2630 int first = (s->first_glyph - glyphs) + (s->cmpcharp ? 1 : s->nchars);
2631
2632 k = -1;
2633 x = 0;
2634 for (i = first; i < end; ++i)
2635 {
2636 int left, right;
2637 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
2638 if (x - left < 0)
2639 k = i;
2640 x += glyphs[i].pixel_width;
2641 }
2642
2643 return k;
2644}
2645
2646
2647/* Fill rectangle X, Y, W, H with background color of glyph string S. */
2648
2649static INLINE void
2650x_clear_glyph_string_rect (s, x, y, w, h)
2651 struct glyph_string *s;
2652 int x, y, w, h;
2653{
2654 XGCValues xgcv;
2655 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
2656 XSetForeground (s->display, s->gc, xgcv.background);
2657 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2658 XSetForeground (s->display, s->gc, xgcv.foreground);
2659}
2660
2661
2662/* Draw the background of glyph_string S. If S->background_filled_p
2663 is non-zero don't draw it. FORCE_P non-zero means draw the
2664 background even if it wouldn't be drawn normally. This is used
2665 when a string preceding S draws into the background of S. */
2666
2667static void
2668x_draw_glyph_string_background (s, force_p)
2669 struct glyph_string *s;
2670 int force_p;
2671{
2672 /* Nothing to do if background has already been drawn or if it
2673 shouldn't be drawn in the first place. */
2674 if (!s->background_filled_p)
2675 {
2676 if (s->cmpcharp
2677 && s->gidx > 0
2678 && !s->font_not_found_p
2679 && !s->extends_to_end_of_line_p)
2680 {
2681 /* Don't draw background for glyphs of a composite
2682 characters, except for the first one. */
2683 s->background_filled_p = 1;
2684 }
2685 else if (s->stippled_p)
2686 {
2687 /* Fill background with a stipple pattern. */
2688 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2689 XFillRectangle (s->display, s->window, s->gc, s->x,
2690 s->y + s->face->box_line_width,
2691 s->background_width,
2692 s->height - 2 * s->face->box_line_width);
2693 XSetFillStyle (s->display, s->gc, FillSolid);
2694 s->background_filled_p = 1;
2695 }
2696 else if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2697 || s->font_not_found_p
2698 || s->extends_to_end_of_line_p
2699 || s->cmpcharp
2700 || force_p)
2701 {
2702 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2703 s->background_width,
2704 s->height - 2 * s->face->box_line_width);
2705 s->background_filled_p = 1;
2706 }
2707 }
2708}
2709
2710
2711/* Draw the foreground of glyph string S. */
2712
2713static void
2714x_draw_glyph_string_foreground (s)
2715 struct glyph_string *s;
2716{
2717 int i, x;
2718
2719 /* If first glyph of S has a left box line, start drawing the text
2720 of S to the right of that box line. */
2721 if (s->face->box != FACE_NO_BOX
2722 && s->first_glyph->left_box_line_p)
2723 x = s->x + s->face->box_line_width;
2724 else
2725 x = s->x;
2726
2727 if (s->cmpcharp == NULL)
2728 {
2729 /* Not a composite character. Draw characters of S as
2730 rectangles if S's font could not be loaded. */
2731 if (s->font_not_found_p)
2732 {
2733 for (i = 0; i < s->nchars; ++i)
2734 {
2735 struct glyph *g = s->first_glyph + i;
2736 XDrawRectangle (s->display, s->window,
2737 s->gc, x, s->y, g->pixel_width - 1,
2738 s->height - 1);
2739 x += g->pixel_width;
2740 }
2741 }
2742 else
2743 {
2744 char *char1b = (char *) s->char2b;
2745
2746 /* If we can use 8-bit functions, condense S->char2b. */
2747 if (!s->two_byte_p)
2748 for (i = 0; i < s->nchars; ++i)
2749 char1b[i] = s->char2b[i].byte2;
2750
2751 /* Draw text with XDrawString if background has already been
2752 filled. Otherwise, use XDrawImageString. (Note that
2753 XDrawImageString is usually faster than XDrawString.)
2754 Always use XDrawImageString when drawing the cursor so
2755 that there is no chance that characters under a box
2756 cursor are invisible. */
2757 if (s->background_filled_p && s->hl != DRAW_CURSOR)
2758 {
2759 /* Draw characters with 16-bit or 8-bit functions. */
2760 if (s->two_byte_p)
2761 XDrawString16 (s->display, s->window, s->gc, x, s->ybase,
2762 s->char2b, s->nchars);
2763 else
2764 XDrawString (s->display, s->window, s->gc, x, s->ybase,
2765 char1b, s->nchars);
2766 }
2767 else
2768 {
2769 if (s->two_byte_p)
2770 XDrawImageString16 (s->display, s->window, s->gc,
2771 x, s->ybase, s->char2b, s->nchars);
2772 else
2773 XDrawImageString (s->display, s->window, s->gc,
2774 x, s->ybase, char1b, s->nchars);
2775 }
2776 }
2777 }
2778 else
2779 {
2780 /* S is a glyph string for a composite character. S->gidx is the
2781 index of the first character drawn in the vector
2782 S->cmpcharp->glyph. S->gidx == 0 means we are drawing the
2783 very first component character of a composite char. */
2784
2785 /* Draw a single rectangle for the composite character if S's
2786 font could not be loaded. */
2787 if (s->font_not_found_p && s->gidx == 0)
2788 XDrawRectangle (s->display, s->window, s->gc, x, s->y,
2789 s->width - 1, s->height - 1);
2790 else
2791 {
2792 XCharStruct *pcm;
2793 int relative_compose, default_ascent, i;
2794 int highest = 0, lowest = 0;
2795
2796 /* The value of font_info my be null if we couldn't find it
2797 in x_get_char_face_and_encoding. */
2798 if (s->cmpcharp->cmp_rule == NULL && s->font_info)
2799 {
2800 relative_compose = s->font_info->relative_compose;
2801 default_ascent = s->font_info->default_ascent;
2802 }
2803 else
2804 relative_compose = default_ascent = 0;
2805
2806 if ((s->cmpcharp->cmp_rule || relative_compose)
2807 && s->gidx == 0)
2808 {
2809 /* This is the first character. Initialize variables.
2810 Highest is the highest position of glyphs ever
2811 written, lowest the lowest position. */
2812 int x_offset = 0;
2813 int first_ch = s->first_glyph->u.ch.code;
2814
2815 if (default_ascent
2816 && CHAR_TABLE_P (Vuse_default_ascent)
2817 && !NILP (Faref (Vuse_default_ascent, first_ch)))
2818 {
2819 highest = default_ascent;
2820 lowest = 0;
2821 }
2822 else
2823 {
2824 pcm = PER_CHAR_METRIC (s->font, s->char2b);
2825 highest = pcm->ascent + 1;
2826 lowest = - pcm->descent;
2827 }
2828
2829 if (s->cmpcharp->cmp_rule)
2830 x_offset = (s->cmpcharp->col_offset[0]
2831 * FONT_WIDTH (s->f->output_data.x->font));
2832
2833 /* Draw the first character at the normal position. */
2834 XDrawString16 (s->display, s->window, s->gc,
2835 x + x_offset,
2836 s->ybase, s->char2b, 1);
2837 i = 1;
2838 ++s->gidx;
2839 }
2840 else
2841 i = 0;
2842
2843 for (; i < s->nchars; i++, ++s->gidx)
2844 {
2845 int x_offset = 0, y_offset = 0;
2846
2847 if (relative_compose)
2848 {
2849 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2850 if (NILP (Vignore_relative_composition)
2851 || NILP (Faref (Vignore_relative_composition,
2852 make_number (s->cmpcharp->glyph[s->gidx]))))
2853 {
2854 if (- pcm->descent >= relative_compose)
2855 {
2856 /* Draw above the current glyphs. */
2857 y_offset = highest + pcm->descent;
2858 highest += pcm->ascent + pcm->descent;
2859 }
2860 else if (pcm->ascent <= 0)
2861 {
2862 /* Draw beneath the current glyphs. */
2863 y_offset = lowest - pcm->ascent;
2864 lowest -= pcm->ascent + pcm->descent;
2865 }
2866 }
2867 else
2868 {
2869 /* Draw the glyph at normal position. If
2870 it sticks out of HIGHEST or LOWEST,
2871 update them appropriately. */
2872 if (pcm->ascent > highest)
2873 highest = pcm->ascent;
2874 else if (- pcm->descent < lowest)
2875 lowest = - pcm->descent;
2876 }
2877 }
2878 else if (s->cmpcharp->cmp_rule)
2879 {
2880 int gref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) / 9;
2881 int nref = (s->cmpcharp->cmp_rule[s->gidx] - 0xA0) % 9;
2882 int bottom, top;
2883
2884 /* Re-encode GREF and NREF so that they specify
2885 only Y-axis information:
2886 0:top, 1:base, 2:bottom, 3:center */
2887 gref = gref / 3 + (gref == 4) * 2;
2888 nref = nref / 3 + (nref == 4) * 2;
2889
2890 pcm = PER_CHAR_METRIC (s->font, s->char2b + i);
2891 bottom = ((gref == 0 ? highest : gref == 1 ? 0
2892 : gref == 2 ? lowest
2893 : (highest + lowest) / 2)
2894 - (nref == 0 ? pcm->ascent + pcm->descent
2895 : nref == 1 ? pcm->descent : nref == 2 ? 0
2896 : (pcm->ascent + pcm->descent) / 2));
2897 top = bottom + (pcm->ascent + pcm->descent);
2898 if (top > highest)
2899 highest = top;
2900 if (bottom < lowest)
2901 lowest = bottom;
2902 y_offset = bottom + pcm->descent;
2903 x_offset = (s->cmpcharp->col_offset[s->gidx]
2904 * FONT_WIDTH (FRAME_FONT (s->f)));
2905 }
2906
2907 XDrawString16 (s->display, s->window, s->gc,
2908 x + x_offset, s->ybase - y_offset,
2909 s->char2b + i, 1);
2910 }
2911 }
2912 }
2913}
2914
2915
2916/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2917 CMAP. If an exact match can't be allocated, try the nearest color
2918 available. Value is non-zero if successful. Set *COLOR to the
2919 color allocated. */
2920
2921int
2922x_alloc_nearest_color (display, screen, cmap, color)
2923 Display *display;
2924 Screen *screen;
2925 Colormap cmap;
2926 XColor *color;
2927{
2928 int rc = XAllocColor (display, cmap, color);
2929 if (rc == 0)
2930 {
2931 /* If we got to this point, the colormap is full, so we're going
2932 to try to get the next closest color. The algorithm used is
2933 a least-squares matching, which is what X uses for closest
2934 color matching with StaticColor visuals. */
2935 int nearest, i;
2936 unsigned long nearest_delta = ~0;
2937 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2938 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2939
2940 for (i = 0; i < ncells; ++i)
2941 cells[i].pixel = i;
2942 XQueryColors (display, cmap, cells, ncells);
2943
2944 for (nearest = i = 0; i < ncells; ++i)
2945 {
2946 long dred = (color->red >> 8) - (cells[i].red >> 8);
2947 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2948 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2949 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2950
2951 if (delta < nearest_delta)
2952 {
2953 nearest = i;
2954 nearest_delta = delta;
2955 }
2956 }
2957
2958 color->red = cells[nearest].red;
2959 color->green = cells[nearest].green;
2960 color->blue = cells[nearest].blue;
2961 rc = XAllocColor (display, cmap, color);
2962 }
2963
2964 return rc;
2965}
2966
2967
2968/* Allocate a color which is lighter or darker than *PIXEL by FACTOR
2969 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2970 If this produces the same color as PIXEL, try a color where all RGB
2971 values have DELTA added. Return the allocated color in *PIXEL.
2972 DISPLAY is the X display, CMAP is the colormap to operate on.
2973 Value is non-zero if successful. */
2974
2975static int
2976x_alloc_lighter_color (f, display, cmap, pixel, factor, delta)
2977 struct frame *f;
2978 Display *display;
2979 Colormap cmap;
2980 unsigned long *pixel;
2981 float factor;
2982 int delta;
2983{
2984 XColor color, new;
2985 int success_p;
2986
2987 /* Get RGB color values. */
2988 color.pixel = *pixel;
2989 XQueryColor (display, cmap, &color);
2990
2991 /* Change RGB values by specified FACTOR. Avoid overflow! */
2992 xassert (factor >= 0);
2993 new.red = min (0xffff, factor * color.red);
2994 new.green = min (0xffff, factor * color.green);
2995 new.blue = min (0xffff, factor * color.blue);
2996
2997 /* Try to allocate the color. */
2998 success_p = x_alloc_nearest_color (display, FRAME_X_SCREEN (f), cmap, &new);
2999 if (success_p)
3000 {
3001 if (new.pixel == *pixel)
3002 {
3003 /* If we end up with the same color as before, try adding
3004 delta to the RGB values. */
3005 int class = FRAME_X_DISPLAY_INFO (f)->visual->class;
3006
3007 /* If display has an immutable color map, freeing colors is
3008 not necessary and some servers don't allow it. So don't
3009 do it. */
3010 if (class != StaticColor
3011 && class != StaticGray
3012 && class != TrueColor)
3013 XFreeColors (display, cmap, &new.pixel, 1, 0);
3014
3015 new.red = min (0xffff, delta + color.red);
3016 new.green = min (0xffff, delta + color.green);
3017 new.blue = min (0xffff, delta + color.blue);
3018 success_p = x_alloc_nearest_color (display, FRAME_X_SCREEN (f),
3019 cmap, &new);
3020 }
3021 else
3022 success_p = 1;
3023 *pixel = new.pixel;
3024 }
3025
3026 return success_p;
3027}
3028
3029
3030/* Set up the foreground color for drawing relief lines of glyph
3031 string S. RELIEF is a pointer to a struct relief containing the GC
3032 with which lines will be drawn. Use a color that is FACTOR or
3033 DELTA lighter or darker than the relief's background which is found
3034 in S->f->output_data.x->relief_background. If such a color cannot
3035 be allocated, use DEFAULT_PIXEL, instead. */
3036
3037static void
3038x_setup_relief_color (f, relief, factor, delta, default_pixel)
3039 struct frame *f;
3040 struct relief *relief;
3041 float factor;
3042 int delta;
3043 unsigned long default_pixel;
3044{
3045 XGCValues xgcv;
3046 struct x_output *di = f->output_data.x;
3047 unsigned long mask = GCForeground | GCLineWidth | GCGraphicsExposures;
3048 unsigned long pixel;
3049 unsigned long background = di->relief_background;
3050 Colormap cmap = DefaultColormapOfScreen (FRAME_X_SCREEN (f));
dcd08bfb
GM
3051 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
3052 Display *dpy = FRAME_X_DISPLAY (f);
06a2c219
GM
3053
3054 xgcv.graphics_exposures = False;
3055 xgcv.line_width = 1;
3056
3057 /* Free previously allocated color. The color cell will be reused
3058 when it has been freed as many times as it was allocated, so this
3059 doesn't affect faces using the same colors. */
3060 if (relief->gc
3061 && relief->allocated_p)
3062 {
3063 /* If display has an immutable color map, freeing colors is not
3064 necessary and some servers don't allow it. So don't do it. */
dcd08bfb 3065 int class = dpyinfo->visual->class;
06a2c219
GM
3066 if (class != StaticColor
3067 && class != StaticGray
3068 && class != TrueColor)
dcd08bfb 3069 XFreeColors (dpy, cmap, &relief->pixel, 1, 0);
06a2c219
GM
3070 relief->allocated_p = 0;
3071 }
3072
3073 /* Allocate new color. */
3074 xgcv.foreground = default_pixel;
3075 pixel = background;
dcd08bfb
GM
3076 if (dpyinfo->n_planes != 1
3077 && x_alloc_lighter_color (f, dpy, cmap, &pixel, factor, delta))
06a2c219
GM
3078 {
3079 relief->allocated_p = 1;
3080 xgcv.foreground = relief->pixel = pixel;
3081 }
3082
3083 if (relief->gc == 0)
3084 {
dcd08bfb 3085 xgcv.stipple = dpyinfo->gray;
06a2c219 3086 mask |= GCStipple;
dcd08bfb 3087 relief->gc = XCreateGC (dpy, FRAME_X_WINDOW (f), mask, &xgcv);
06a2c219
GM
3088 }
3089 else
dcd08bfb 3090 XChangeGC (dpy, relief->gc, mask, &xgcv);
06a2c219
GM
3091}
3092
3093
3094/* Set up colors for the relief lines around glyph string S. */
3095
3096static void
3097x_setup_relief_colors (s)
3098 struct glyph_string *s;
3099{
3100 struct x_output *di = s->f->output_data.x;
3101 unsigned long color;
3102
3103 if (s->face->use_box_color_for_shadows_p)
3104 color = s->face->box_color;
3105 else
3106 {
3107 XGCValues xgcv;
3108
3109 /* Get the background color of the face. */
3110 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
3111 color = xgcv.background;
3112 }
3113
3114 if (di->white_relief.gc == 0
3115 || color != di->relief_background)
3116 {
3117 di->relief_background = color;
3118 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3119 WHITE_PIX_DEFAULT (s->f));
3120 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3121 BLACK_PIX_DEFAULT (s->f));
3122 }
3123}
3124
3125
3126/* Draw a relief on frame F inside the rectangle given by LEFT_X,
3127 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3128 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3129 relief. LEFT_P non-zero means draw a relief on the left side of
3130 the rectangle. RIGHT_P non-zero means draw a relief on the right
3131 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3132 when drawing. */
3133
3134static void
3135x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3136 raised_p, left_p, right_p, clip_rect)
3137 struct frame *f;
3138 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3139 XRectangle *clip_rect;
3140{
3141 int i;
3142 GC gc;
3143
3144 if (raised_p)
3145 gc = f->output_data.x->white_relief.gc;
3146 else
3147 gc = f->output_data.x->black_relief.gc;
3148 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3149
3150 /* Top. */
3151 for (i = 0; i < width; ++i)
3152 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3153 left_x + i * left_p, top_y + i,
3154 right_x + 1 - i * right_p, top_y + i);
3155
3156 /* Left. */
3157 if (left_p)
3158 for (i = 0; i < width; ++i)
3159 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3160 left_x + i, top_y + i, left_x + i, bottom_y - i);
3161
3162 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3163 if (raised_p)
3164 gc = f->output_data.x->black_relief.gc;
3165 else
3166 gc = f->output_data.x->white_relief.gc;
3167 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, clip_rect, 1, Unsorted);
3168
3169 /* Bottom. */
3170 for (i = 0; i < width; ++i)
3171 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3172 left_x + i * left_p, bottom_y - i,
3173 right_x + 1 - i * right_p, bottom_y - i);
3174
3175 /* Right. */
3176 if (right_p)
3177 for (i = 0; i < width; ++i)
3178 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
3179 right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
3180
3181 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
3182}
3183
3184
3185/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3186 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3187 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3188 left side of the rectangle. RIGHT_P non-zero means draw a line
3189 on the right side of the rectangle. CLIP_RECT is the clipping
3190 rectangle to use when drawing. */
3191
3192static void
3193x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3194 left_p, right_p, clip_rect)
3195 struct glyph_string *s;
3196 int left_x, top_y, right_x, bottom_y, left_p, right_p;
3197 XRectangle *clip_rect;
3198{
3199 XGCValues xgcv;
3200
3201 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3202 XSetForeground (s->display, s->gc, s->face->box_color);
3203 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted);
3204
3205 /* Top. */
3206 XFillRectangle (s->display, s->window, s->gc,
3207 left_x, top_y, right_x - left_x, width);
3208
3209 /* Left. */
3210 if (left_p)
3211 XFillRectangle (s->display, s->window, s->gc,
3212 left_x, top_y, width, bottom_y - top_y);
3213
3214 /* Bottom. */
3215 XFillRectangle (s->display, s->window, s->gc,
3216 left_x, bottom_y - width, right_x - left_x, width);
3217
3218 /* Right. */
3219 if (right_p)
3220 XFillRectangle (s->display, s->window, s->gc,
3221 right_x - width, top_y, width, bottom_y - top_y);
3222
3223 XSetForeground (s->display, s->gc, xgcv.foreground);
3224 XSetClipMask (s->display, s->gc, None);
3225}
3226
3227
3228/* Draw a box around glyph string S. */
3229
3230static void
3231x_draw_glyph_string_box (s)
3232 struct glyph_string *s;
3233{
3234 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3235 int left_p, right_p;
3236 struct glyph *last_glyph;
3237 XRectangle clip_rect;
3238
3239 last_x = window_box_right (s->w, s->area);
3240 if (s->row->full_width_p
3241 && !s->w->pseudo_window_p)
3242 {
3243 last_x += FRAME_X_FLAGS_AREA_WIDTH (s->f);
3244 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3245 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3246 }
3247
3248 /* The glyph that may have a right box line. */
3249 last_glyph = (s->cmpcharp || s->img
3250 ? s->first_glyph
3251 : s->first_glyph + s->nchars - 1);
3252
3253 width = s->face->box_line_width;
3254 raised_p = s->face->box == FACE_RAISED_BOX;
3255 left_x = s->x;
3256 right_x = ((s->row->full_width_p
1da3fd71 3257 ? last_x - 1
06a2c219
GM
3258 : min (last_x, s->x + s->width) - 1));
3259 top_y = s->y;
3260 bottom_y = top_y + s->height - 1;
3261
3262 left_p = (s->first_glyph->left_box_line_p
3263 || (s->hl == DRAW_MOUSE_FACE
3264 && (s->prev == NULL
3265 || s->prev->hl != s->hl)));
3266 right_p = (last_glyph->right_box_line_p
3267 || (s->hl == DRAW_MOUSE_FACE
3268 && (s->next == NULL
3269 || s->next->hl != s->hl)));
3270
3271 x_get_glyph_string_clip_rect (s, &clip_rect);
3272
3273 if (s->face->box == FACE_SIMPLE_BOX)
3274 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3275 left_p, right_p, &clip_rect);
3276 else
3277 {
3278 x_setup_relief_colors (s);
3279 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3280 width, raised_p, left_p, right_p, &clip_rect);
3281 }
3282}
3283
3284
3285/* Draw foreground of image glyph string S. */
3286
3287static void
3288x_draw_image_foreground (s)
3289 struct glyph_string *s;
3290{
3291 int x;
3292 int y = s->ybase - IMAGE_ASCENT (s->img);
3293
3294 /* If first glyph of S has a left box line, start drawing it to the
3295 right of that line. */
3296 if (s->face->box != FACE_NO_BOX
3297 && s->first_glyph->left_box_line_p)
3298 x = s->x + s->face->box_line_width;
3299 else
3300 x = s->x;
3301
3302 /* If there is a margin around the image, adjust x- and y-position
3303 by that margin. */
3304 if (s->img->margin)
3305 {
3306 x += s->img->margin;
3307 y += s->img->margin;
3308 }
3309
3310 if (s->img->pixmap)
3311 {
3312 if (s->img->mask)
3313 {
3314 /* We can't set both a clip mask and use XSetClipRectangles
3315 because the latter also sets a clip mask. We also can't
3316 trust on the shape extension to be available
3317 (XShapeCombineRegion). So, compute the rectangle to draw
3318 manually. */
3319 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3320 | GCFunction);
3321 XGCValues xgcv;
3322 XRectangle clip_rect, image_rect, r;
3323
3324 xgcv.clip_mask = s->img->mask;
3325 xgcv.clip_x_origin = x;
3326 xgcv.clip_y_origin = y;
3327 xgcv.function = GXcopy;
3328 XChangeGC (s->display, s->gc, mask, &xgcv);
3329
3330 x_get_glyph_string_clip_rect (s, &clip_rect);
3331 image_rect.x = x;
3332 image_rect.y = y;
3333 image_rect.width = s->img->width;
3334 image_rect.height = s->img->height;
3335 if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
3336 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3337 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3338 }
3339 else
3340 {
3341 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3342 0, 0, s->img->width, s->img->height, x, y);
3343
3344 /* When the image has a mask, we can expect that at
3345 least part of a mouse highlight or a block cursor will
3346 be visible. If the image doesn't have a mask, make
3347 a block cursor visible by drawing a rectangle around
3348 the image. I believe it's looking better if we do
3349 nothing here for mouse-face. */
3350 if (s->hl == DRAW_CURSOR)
3351 XDrawRectangle (s->display, s->window, s->gc, x, y,
3352 s->img->width - 1, s->img->height - 1);
3353 }
3354 }
3355 else
3356 /* Draw a rectangle if image could not be loaded. */
3357 XDrawRectangle (s->display, s->window, s->gc, x, y,
3358 s->img->width - 1, s->img->height - 1);
3359}
3360
3361
3362/* Draw a relief around the image glyph string S. */
3363
3364static void
3365x_draw_image_relief (s)
3366 struct glyph_string *s;
3367{
3368 int x0, y0, x1, y1, thick, raised_p;
3369 XRectangle r;
3370 int x;
3371 int y = s->ybase - IMAGE_ASCENT (s->img);
3372
3373 /* If first glyph of S has a left box line, start drawing it to the
3374 right of that line. */
3375 if (s->face->box != FACE_NO_BOX
3376 && s->first_glyph->left_box_line_p)
3377 x = s->x + s->face->box_line_width;
3378 else
3379 x = s->x;
3380
3381 /* If there is a margin around the image, adjust x- and y-position
3382 by that margin. */
3383 if (s->img->margin)
3384 {
3385 x += s->img->margin;
3386 y += s->img->margin;
3387 }
3388
3389 if (s->hl == DRAW_IMAGE_SUNKEN
3390 || s->hl == DRAW_IMAGE_RAISED)
3391 {
3392 thick = toolbar_button_relief > 0 ? toolbar_button_relief : 3;
3393 raised_p = s->hl == DRAW_IMAGE_RAISED;
3394 }
3395 else
3396 {
3397 thick = abs (s->img->relief);
3398 raised_p = s->img->relief > 0;
3399 }
3400
3401 x0 = x - thick;
3402 y0 = y - thick;
3403 x1 = x + s->img->width + thick - 1;
3404 y1 = y + s->img->height + thick - 1;
3405
3406 x_setup_relief_colors (s);
3407 x_get_glyph_string_clip_rect (s, &r);
3408 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3409}
3410
3411
3412/* Draw the foreground of image glyph string S to PIXMAP. */
3413
3414static void
3415x_draw_image_foreground_1 (s, pixmap)
3416 struct glyph_string *s;
3417 Pixmap pixmap;
3418{
3419 int x;
3420 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3421
3422 /* If first glyph of S has a left box line, start drawing it to the
3423 right of that line. */
3424 if (s->face->box != FACE_NO_BOX
3425 && s->first_glyph->left_box_line_p)
3426 x = s->face->box_line_width;
3427 else
3428 x = 0;
3429
3430 /* If there is a margin around the image, adjust x- and y-position
3431 by that margin. */
3432 if (s->img->margin)
3433 {
3434 x += s->img->margin;
3435 y += s->img->margin;
3436 }
dc43ef94 3437
06a2c219
GM
3438 if (s->img->pixmap)
3439 {
3440 if (s->img->mask)
3441 {
3442 /* We can't set both a clip mask and use XSetClipRectangles
3443 because the latter also sets a clip mask. We also can't
3444 trust on the shape extension to be available
3445 (XShapeCombineRegion). So, compute the rectangle to draw
3446 manually. */
3447 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3448 | GCFunction);
3449 XGCValues xgcv;
3450
3451 xgcv.clip_mask = s->img->mask;
3452 xgcv.clip_x_origin = x;
3453 xgcv.clip_y_origin = y;
3454 xgcv.function = GXcopy;
3455 XChangeGC (s->display, s->gc, mask, &xgcv);
3456
3457 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3458 0, 0, s->img->width, s->img->height, x, y);
3459 XSetClipMask (s->display, s->gc, None);
3460 }
3461 else
3462 {
3463 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3464 0, 0, s->img->width, s->img->height, x, y);
3465
3466 /* When the image has a mask, we can expect that at
3467 least part of a mouse highlight or a block cursor will
3468 be visible. If the image doesn't have a mask, make
3469 a block cursor visible by drawing a rectangle around
3470 the image. I believe it's looking better if we do
3471 nothing here for mouse-face. */
3472 if (s->hl == DRAW_CURSOR)
3473 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3474 s->img->width - 1, s->img->height - 1);
3475 }
3476 }
3477 else
3478 /* Draw a rectangle if image could not be loaded. */
3479 XDrawRectangle (s->display, pixmap, s->gc, x, y,
3480 s->img->width - 1, s->img->height - 1);
3481}
dc43ef94 3482
990ba854 3483
06a2c219
GM
3484/* Draw part of the background of glyph string S. X, Y, W, and H
3485 give the rectangle to draw. */
a9a5b0a5 3486
06a2c219
GM
3487static void
3488x_draw_glyph_string_bg_rect (s, x, y, w, h)
3489 struct glyph_string *s;
3490 int x, y, w, h;
3491{
3492 if (s->stippled_p)
3493 {
3494 /* Fill background with a stipple pattern. */
3495 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3496 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3497 XSetFillStyle (s->display, s->gc, FillSolid);
3498 }
3499 else
3500 x_clear_glyph_string_rect (s, x, y, w, h);
3501}
07e34cb0 3502
b5210ea7 3503
06a2c219 3504/* Draw image glyph string S.
dc43ef94 3505
06a2c219
GM
3506 s->y
3507 s->x +-------------------------
3508 | s->face->box
3509 |
3510 | +-------------------------
3511 | | s->img->margin
3512 | |
3513 | | +-------------------
3514 | | | the image
dc43ef94 3515
06a2c219 3516 */
dc43ef94 3517
06a2c219
GM
3518static void
3519x_draw_image_glyph_string (s)
3520 struct glyph_string *s;
3521{
3522 int x, y;
3523 int box_line_width = s->face->box_line_width;
3524 int margin = s->img->margin;
3525 int height;
3526 Pixmap pixmap = None;
3527
3528 height = s->height - 2 * box_line_width;
3529
3530 /* Fill background with face under the image. Do it only if row is
3531 taller than image or if image has a clip mask to reduce
3532 flickering. */
3533 s->stippled_p = s->face->stipple != 0;
3534 if (height > s->img->height
3535 || margin
3536 || s->img->mask
3537 || s->img->pixmap == 0
3538 || s->width != s->background_width)
3539 {
3540 if (box_line_width && s->first_glyph->left_box_line_p)
3541 x = s->x + box_line_width;
3542 else
3543 x = s->x;
3544
3545 y = s->y + box_line_width;
3546
3547 if (s->img->mask)
3548 {
3549 /* Create a pixmap as large as the glyph string Fill it with
3550 the background color. Copy the image to it, using its
3551 mask. Copy the temporary pixmap to the display. */
3552 Screen *screen = FRAME_X_SCREEN (s->f);
3553 int depth = DefaultDepthOfScreen (screen);
3554
3555 /* Create a pixmap as large as the glyph string. */
3556 pixmap = XCreatePixmap (s->display, s->window,
3557 s->background_width,
3558 s->height, depth);
3559
3560 /* Don't clip in the following because we're working on the
3561 pixmap. */
3562 XSetClipMask (s->display, s->gc, None);
3563
3564 /* Fill the pixmap with the background color/stipple. */
3565 if (s->stippled_p)
3566 {
3567 /* Fill background with a stipple pattern. */
3568 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3569 XFillRectangle (s->display, pixmap, s->gc,
3570 0, 0, s->background_width, s->height);
3571 XSetFillStyle (s->display, s->gc, FillSolid);
3572 }
3573 else
3574 {
3575 XGCValues xgcv;
3576 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3577 &xgcv);
3578 XSetForeground (s->display, s->gc, xgcv.background);
3579 XFillRectangle (s->display, pixmap, s->gc,
3580 0, 0, s->background_width, s->height);
3581 XSetForeground (s->display, s->gc, xgcv.foreground);
3582 }
3583 }
3584 else
3585 /* Implementation idea: Is it possible to construct a mask?
3586 We could look at the color at the margins of the image, and
3587 say that this color is probably the background color of the
3588 image. */
3589 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3590
3591 s->background_filled_p = 1;
3592 }
dc43ef94 3593
06a2c219
GM
3594 /* Draw the foreground. */
3595 if (pixmap != None)
3596 {
3597 x_draw_image_foreground_1 (s, pixmap);
3598 x_set_glyph_string_clipping (s);
3599 XCopyArea (s->display, pixmap, s->window, s->gc,
3600 0, 0, s->background_width, s->height, s->x, s->y);
3601 XFreePixmap (s->display, pixmap);
3602 }
3603 else
3604 x_draw_image_foreground (s);
b5210ea7 3605
06a2c219
GM
3606 /* If we must draw a relief around the image, do it. */
3607 if (s->img->relief
3608 || s->hl == DRAW_IMAGE_RAISED
3609 || s->hl == DRAW_IMAGE_SUNKEN)
3610 x_draw_image_relief (s);
3611}
8c1a6a84 3612
990ba854 3613
06a2c219 3614/* Draw stretch glyph string S. */
dc43ef94 3615
06a2c219
GM
3616static void
3617x_draw_stretch_glyph_string (s)
3618 struct glyph_string *s;
3619{
3620 xassert (s->first_glyph->type == STRETCH_GLYPH);
3621 s->stippled_p = s->face->stipple != 0;
990ba854 3622
06a2c219
GM
3623 if (s->hl == DRAW_CURSOR
3624 && !x_stretch_cursor_p)
3625 {
3626 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3627 as wide as the stretch glyph. */
3628 int width = min (CANON_X_UNIT (s->f), s->background_width);
990ba854 3629
06a2c219
GM
3630 /* Draw cursor. */
3631 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
0cdd0c9f 3632
06a2c219
GM
3633 /* Clear rest using the GC of the original non-cursor face. */
3634 if (width < s->background_width)
3635 {
3636 GC gc = s->face->gc;
3637 int x = s->x + width, y = s->y;
3638 int w = s->background_width - width, h = s->height;
3639 XRectangle r;
dc43ef94 3640
06a2c219
GM
3641 x_get_glyph_string_clip_rect (s, &r);
3642 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted);
97210f4e 3643
06a2c219
GM
3644 if (s->face->stipple)
3645 {
3646 /* Fill background with a stipple pattern. */
3647 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3648 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3649 XSetFillStyle (s->display, gc, FillSolid);
3650 }
3651 else
3652 {
3653 XGCValues xgcv;
3654 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3655 XSetForeground (s->display, gc, xgcv.background);
3656 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3657 XSetForeground (s->display, gc, xgcv.foreground);
3658 }
3659 }
3660 }
3661 else
3662 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3663 s->height);
3664
3665 s->background_filled_p = 1;
3666}
3667
3668
3669/* Draw glyph string S. */
3670
3671static void
3672x_draw_glyph_string (s)
3673 struct glyph_string *s;
3674{
3675 /* If S draws into the background of its successor, draw the
3676 background of the successor first so that S can draw into it.
3677 This makes S->next use XDrawString instead of XDrawImageString. */
3678 if (s->next && s->right_overhang)
3679 {
3680 xassert (s->next->img == NULL);
3681 x_set_glyph_string_gc (s->next);
3682 x_set_glyph_string_clipping (s->next);
3683 x_draw_glyph_string_background (s->next, 1);
3684 }
97210f4e 3685
06a2c219
GM
3686 /* Set up S->gc, set clipping and draw S. */
3687 x_set_glyph_string_gc (s);
3688 x_set_glyph_string_clipping (s);
3689
3690 switch (s->first_glyph->type)
3691 {
3692 case IMAGE_GLYPH:
3693 x_draw_image_glyph_string (s);
3694 break;
3695
3696 case STRETCH_GLYPH:
3697 x_draw_stretch_glyph_string (s);
3698 break;
3699
3700 case CHAR_GLYPH:
3701 x_draw_glyph_string_background (s, 0);
3702 x_draw_glyph_string_foreground (s);
3703 break;
3704
3705 default:
3706 abort ();
3707 }
3708
3709 /* Draw underline. */
3710 if (s->face->underline_p)
3711 {
3712 unsigned long dy, h;
3713
3714 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h))
3715 h = 1;
3716 if (!XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &dy))
3717 dy = s->height - h;
3718
3719 if (s->face->underline_defaulted_p)
3720 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3721 s->width, h);
3722 else
dc6f92b8 3723 {
06a2c219
GM
3724 XGCValues xgcv;
3725 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3726 XSetForeground (s->display, s->gc, s->face->underline_color);
3727 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3728 s->width, h);
3729 XSetForeground (s->display, s->gc, xgcv.foreground);
dc6f92b8 3730 }
06a2c219 3731 }
07e34cb0 3732
06a2c219
GM
3733 /* Draw overline. */
3734 if (s->face->overline_p)
3735 {
3736 unsigned long dy = 0, h = 1;
3737
3738 if (s->face->overline_color_defaulted_p)
3739 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3740 s->width, h);
3741 else
3742 {
3743 XGCValues xgcv;
3744 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3745 XSetForeground (s->display, s->gc, s->face->overline_color);
3746 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3747 s->width, h);
3748 XSetForeground (s->display, s->gc, xgcv.foreground);
3749 }
dc6f92b8 3750 }
06a2c219
GM
3751
3752 /* Draw strike-through. */
3753 if (s->face->strike_through_p)
3754 {
3755 unsigned long h = 1;
3756 unsigned long dy = (s->height - h) / 2;
dc43ef94 3757
06a2c219
GM
3758 if (s->face->strike_through_color_defaulted_p)
3759 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3760 s->width, h);
3761 else
3762 {
3763 XGCValues xgcv;
3764 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3765 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3766 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3767 s->width, h);
3768 XSetForeground (s->display, s->gc, xgcv.foreground);
3769 }
3770 }
3771
3772 /* Draw relief. */
3773 if (s->face->box != FACE_NO_BOX)
3774 x_draw_glyph_string_box (s);
3775
3776 /* Reset clipping. */
3777 XSetClipMask (s->display, s->gc, None);
dc6f92b8 3778}
07e34cb0 3779
06a2c219
GM
3780
3781/* A work-list entry used during the construction of glyph_string
3782 structures for a composite character. */
3783
3784struct work
3785{
3786 /* Pointer to composite char info defining has the composite
3787 character is drawn. */
3788 struct cmpchar_info *cmpcharp;
3789
3790 /* Start index in compcharp->glyph[]. */
3791 int gidx;
3792
3793 /* Next in stack. */
3794 struct work *next;
3795};
3796
3797
3798static void x_fill_composite_glyph_string P_ ((struct glyph_string *,
3799 int, struct work **,
3800 struct work **));
3801
3802
3803/* Load glyph string S with information from the top of *STACK for a
3804 composite character. FACE_ID is the id of the face in which S is
3805 drawn. *NEW is a pointer to a struct work not on the stack, that
3806 can be used if this function needs to push a new structure on the
3807 stack. If it uses it, *NEW is set to null. */
07e34cb0
JB
3808
3809static void
06a2c219
GM
3810x_fill_composite_glyph_string (s, face_id, stack, new)
3811 struct glyph_string *s;
3812 int face_id;
3813 struct work **stack, **new;
07e34cb0 3814{
06a2c219
GM
3815 int i, c;
3816 struct work *work;
3817
3818 xassert (s && *new && *stack);
3819
3820 /* Pop the work stack. */
3821 work = *stack;
3822 *stack = work->next;
3823
3824 /* For all glyphs of cmpcharp->glyph, starting at the offset
3825 work->offset, until we reach the end of the definition or
3826 encounter another composite char, get the font and face to use,
3827 and add it to S. */
3828 for (i = work->gidx; i < work->cmpcharp->glyph_len; ++i)
3829 {
3830 c = FAST_GLYPH_CHAR (work->cmpcharp->glyph[i]);
3831 if (CHAR_CHARSET (c) == CHARSET_COMPOSITION)
3832 break;
3833 s->face = x_get_char_face_and_encoding (s->f, c, face_id,
3834 s->char2b + s->nchars, 1);
3835 s->font = s->face->font;
3836 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3837 ++s->nchars;
3838 }
3839
3840 /* If we find another composite char in the glyph definition of
3841 work->cmpcharp, put back the rest of the glyphs on the work
3842 stack, and make a new entry for the composite char. */
3843 if (i < work->cmpcharp->glyph_len)
3844 {
3845 /* Push back an unprocessed rest of this glyph spec. */
3846 if (i < work->cmpcharp->glyph_len - 1)
3847 {
3848 work->gidx = i + 1;
3849 work->next = *stack;
3850 *stack = work;
3851 work = *new;
3852 *new = NULL;
3853 }
3854
3855 /* Make an entry for the composite char on the work stack. */
3856 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)];
3857 work->gidx = 0;
3858 work->next = *stack;
3859 *stack = work;
3860 }
3861
3862 /* The width of this glyph string equals the width of the first
3863 glyph. All characters are drawn at the same x-position. */
3864 s->width = s->first_glyph->pixel_width;
3865
3866 /* If the specified font could not be loaded, use the frame's
3867 default font, but record the fact that we couldn't load it in
3868 the glyph string so that we can draw rectangles for the
3869 characters of the glyph string. */
3870 if (s->font == NULL)
3871 {
3872 s->font_not_found_p = 1;
3873 s->font = FRAME_FONT (s->f);
3874 }
3875
3876 /* Adjust base line for subscript/superscript text. */
3877 s->ybase += s->first_glyph->voffset;
3878
3879 xassert (s->face && s->face->gc);
3880
3881 /* This glyph string must always be drawn with 16-bit functions. */
3882 s->two_byte_p = 1;
3883}
3884
3885
3886/* Load glyph string S with a sequence of non-composite characters.
3887 FACE_ID is the face id of the string. START is the index of the
3888 first glyph to consider, END is the index of the last + 1. Value
3889 is the index of the first glyph not in S. */
3890
3891static int
3892x_fill_glyph_string (s, face_id, start, end)
3893 struct glyph_string *s;
3894 int face_id;
3895 int start, end;
3896{
3897 struct glyph *glyph, *last;
3898 int voffset;
3899
3900 xassert (s->charset != CHARSET_COMPOSITION);
3901 xassert (s->f == XFRAME (s->w->frame));
3902 xassert (s->nchars == 0);
3903 xassert (start >= 0 && end > start);
3904
3905 glyph = s->row->glyphs[s->area] + start;
3906 last = s->row->glyphs[s->area] + end;
3907 voffset = glyph->voffset;
3908
3909 while (glyph < last
3910 && glyph->type == CHAR_GLYPH
3911 && glyph->voffset == voffset
3912 /* Same face id implies same charset, nowadays. */
3913 && glyph->u.ch.face_id == face_id)
3914 {
3915 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
3916 s->char2b + s->nchars);
3917 if (s->char2b[s->nchars].byte2 != 0)
3918 s->two_byte_p = 1;
3919
3920 ++s->nchars;
3921 xassert (s->nchars <= end - start);
3922 s->width += glyph->pixel_width;
3923 ++glyph;
3924 }
3925
3926 s->font = s->face->font;
3927 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3928
3929 /* If the specified font could not be loaded, use the frame's font,
3930 but record the fact that we couldn't load it in
3931 S->font_not_found_p so that we can draw rectangles for the
3932 characters of the glyph string. */
3933 if (s->font == NULL)
3934 {
3935 s->font_not_found_p = 1;
3936 s->font = FRAME_FONT (s->f);
3937 }
3938
3939 /* Adjust base line for subscript/superscript text. */
3940 s->ybase += voffset;
3941
3942 xassert (s->face && s->face->gc);
3943 return glyph - s->row->glyphs[s->area];
07e34cb0 3944}
dc6f92b8 3945
06a2c219
GM
3946
3947/* Fill glyph string S from image glyph S->first_glyph. */
dc6f92b8 3948
dfcf069d 3949static void
06a2c219
GM
3950x_fill_image_glyph_string (s)
3951 struct glyph_string *s;
3952{
3953 xassert (s->first_glyph->type == IMAGE_GLYPH);
3954 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img.id);
3955 xassert (s->img);
3956 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.img.face_id);
3957 s->font = s->face->font;
3958 s->width = s->first_glyph->pixel_width;
3959
3960 /* Adjust base line for subscript/superscript text. */
3961 s->ybase += s->first_glyph->voffset;
3962}
3963
3964
3965/* Fill glyph string S from stretch glyph S->first_glyph. */
3966
3967static void
3968x_fill_stretch_glyph_string (s)
3969 struct glyph_string *s;
3970{
3971 xassert (s->first_glyph->type == STRETCH_GLYPH);
3972 s->face = FACE_FROM_ID (s->f, s->first_glyph->u.stretch.face_id);
3973 s->font = s->face->font;
3974 s->width = s->first_glyph->pixel_width;
3975
3976 /* Adjust base line for subscript/superscript text. */
3977 s->ybase += s->first_glyph->voffset;
3978}
3979
3980
3981/* Initialize glyph string S. CHAR2B is a suitably allocated vector
3982 of XChar2b structures for S; it can't be allocated in
3983 x_init_glyph_string because it must be allocated via `alloca'. W
3984 is the window on which S is drawn. ROW and AREA are the glyph row
3985 and area within the row from which S is constructed. START is the
3986 index of the first glyph structure covered by S. HL is a
3987 face-override for drawing S. */
3988
3989static void
3990x_init_glyph_string (s, char2b, w, row, area, start, hl)
3991 struct glyph_string *s;
3992 XChar2b *char2b;
3993 struct window *w;
3994 struct glyph_row *row;
3995 enum glyph_row_area area;
3996 int start;
3997 enum draw_glyphs_face hl;
3998{
3999 bzero (s, sizeof *s);
4000 s->w = w;
4001 s->f = XFRAME (w->frame);
4002 s->display = FRAME_X_DISPLAY (s->f);
4003 s->window = FRAME_X_WINDOW (s->f);
4004 s->char2b = char2b;
4005 s->hl = hl;
4006 s->row = row;
4007 s->area = area;
4008 s->first_glyph = row->glyphs[area] + start;
4009 s->height = row->height;
4010 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4011
4012 /* Display the internal border below the toolbar window. */
4013 if (s->w == XWINDOW (s->f->toolbar_window))
4014 s->y -= s->f->output_data.x->internal_border_width;
4015
4016 s->ybase = s->y + row->ascent;
4017}
4018
4019
4020/* Set background width of glyph string S. START is the index of the
4021 first glyph following S. LAST_X is the right-most x-position + 1
4022 in the drawing area. */
4023
4024static INLINE void
4025x_set_glyph_string_background_width (s, start, last_x)
4026 struct glyph_string *s;
4027 int start;
4028 int last_x;
4029{
4030 /* If the face of this glyph string has to be drawn to the end of
4031 the drawing area, set S->extends_to_end_of_line_p. */
4032 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4033
4034 if (start == s->row->used[s->area]
4035 && s->hl == DRAW_NORMAL_TEXT
4036 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4037 || s->face->background != default_face->background
4038 || s->face->stipple != default_face->stipple))
4039 s->extends_to_end_of_line_p = 1;
4040
4041 /* If S extends its face to the end of the line, set its
4042 background_width to the distance to the right edge of the drawing
4043 area. */
4044 if (s->extends_to_end_of_line_p)
1da3fd71 4045 s->background_width = last_x - s->x + 1;
06a2c219
GM
4046 else
4047 s->background_width = s->width;
4048}
4049
4050
4051/* Add a glyph string for a stretch glyph to the list of strings
4052 between HEAD and TAIL. START is the index of the stretch glyph in
4053 row area AREA of glyph row ROW. END is the index of the last glyph
4054 in that glyph row area. X is the current output position assigned
4055 to the new glyph string constructed. HL overrides that face of the
4056 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4057 is the right-most x-position of the drawing area. */
4058
4059#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \
4060 HL, X, LAST_X) \
4061 do \
4062 { \
4063 s = (struct glyph_string *) alloca (sizeof *s); \
4064 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4065 x_fill_stretch_glyph_string (s); \
4066 x_append_glyph_string (&HEAD, &TAIL, s); \
4067 ++START; \
4068 s->x = (X); \
4069 } \
4070 while (0)
4071
4072
4073/* Add a glyph string for an image glyph to the list of strings
4074 between HEAD and TAIL. START is the index of the image glyph in
4075 row area AREA of glyph row ROW. END is the index of the last glyph
4076 in that glyph row area. X is the current output position assigned
4077 to the new glyph string constructed. HL overrides that face of the
4078 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4079 is the right-most x-position of the drawing area. */
4080
4081#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, \
4082 HL, X, LAST_X) \
4083 do \
4084 { \
4085 s = (struct glyph_string *) alloca (sizeof *s); \
4086 x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
4087 x_fill_image_glyph_string (s); \
4088 x_append_glyph_string (&HEAD, &TAIL, s); \
4089 ++START; \
4090 s->x = (X); \
4091 } \
4092 while (0)
4093
4094
4095/* Add a glyph string for a sequence of character glyphs to the list
4096 of strings between HEAD and TAIL. START is the index of the first
4097 glyph in row area AREA of glyph row ROW that is part of the new
4098 glyph string. END is the index of the last glyph in that glyph row
4099 area. X is the current output position assigned to the new glyph
4100 string constructed. HL overrides that face of the glyph; e.g. it
4101 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4102 right-most x-position of the drawing area. */
4103
4104#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \
4105 X, LAST_X) \
4106 do \
4107 { \
4108 int c, charset, face_id; \
4109 XChar2b *char2b; \
4110 \
4111 c = (ROW)->glyphs[AREA][START].u.ch.code; \
4112 charset = CHAR_CHARSET (c); \
4113 face_id = (ROW)->glyphs[AREA][START].u.ch.face_id; \
4114 \
4115 if (charset == CHARSET_COMPOSITION) \
4116 { \
4117 struct work *stack, *work, *new = NULL; \
4118 int n = 0; \
4119 struct glyph_string *first_s = NULL; \
4120 \
4121 /* Push an initial entry for character c on the stack. */ \
4122 stack = NULL; \
4123 work = (struct work *) alloca (sizeof *work); \
4124 work->cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (c)]; \
4125 work->gidx = 0; \
4126 work->next = stack; \
4127 stack = work; \
4128 \
4129 /* While the stack is not empty, append glyph_strings \
4130 to head/tail for glyphs to draw. */ \
4131 while (stack) \
4132 { \
4133 s = (struct glyph_string *) alloca (sizeof *s); \
4134 char2b = (XChar2b *) alloca (stack->cmpcharp->glyph_len \
4135 * sizeof (XChar2b)); \
4136 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4137 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4138 s->cmpcharp = stack->cmpcharp; \
4139 s->gidx = stack->gidx; \
4140 s->charset = charset; \
4141 s->x = (X); \
4142 \
4143 if (n == 0) \
4144 { \
4145 /* Don't draw the background except for the \
4146 first glyph string. */ \
4147 s->background_filled_p = n > 0; \
4148 first_s = s; \
4149 } \
4150 ++n; \
4151 \
4152 if (new == NULL) \
4153 new = (struct work *) alloca (sizeof *new); \
4154 x_fill_composite_glyph_string (s, face_id, &stack, \
4155 &new); \
4156 } \
4157 \
4158 ++START; \
4159 s = first_s; \
4160 } \
4161 else \
4162 { \
4163 s = (struct glyph_string *) alloca (sizeof *s); \
4164 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
4165 x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
4166 x_append_glyph_string (&HEAD, &TAIL, s); \
4167 s->charset = charset; \
4168 s->x = (X); \
4169 START = x_fill_glyph_string (s, face_id, START, END); \
4170 } \
4171 } \
4172 while (0)
4173
4174
4175/* Build a list of glyph strings between HEAD and TAIL for the glyphs
4176 of AREA of glyph row ROW on window W between indices START and END.
4177 HL overrides the face for drawing glyph strings, e.g. it is
4178 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4179 x-positions of the drawing area.
4180
4181 This is an ugly monster macro construct because we must use alloca
4182 to allocate glyph strings (because x_draw_glyphs can be called
4183 asynchronously). */
4184
4185#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, \
4186 X, LAST_X) \
4187 do \
4188 { \
4189 HEAD = TAIL = NULL; \
4190 while (START < END) \
4191 { \
4192 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4193 switch (first_glyph->type) \
4194 { \
4195 case CHAR_GLYPH: \
4196 BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
4197 TAIL, HL, X, LAST_X); \
4198 break; \
4199 \
4200 case STRETCH_GLYPH: \
4201 BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
4202 HEAD, TAIL, HL, X, LAST_X); \
4203 break; \
4204 \
4205 case IMAGE_GLYPH: \
4206 BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
4207 TAIL, HL, X, LAST_X); \
4208 break; \
4209 \
4210 default: \
4211 abort (); \
4212 } \
4213 \
4214 x_set_glyph_string_background_width (s, START, LAST_X); \
4215 (X) += s->width; \
4216 } \
4217 } \
4218 while (0)
4219
4220
4221/* Draw glyphs between START and END in AREA of ROW on window W,
4222 starting at x-position X. X is relative to AREA in W. HL is a
4223 face-override with the following meaning:
4224
4225 DRAW_NORMAL_TEXT draw normally
4226 DRAW_CURSOR draw in cursor face
4227 DRAW_MOUSE_FACE draw in mouse face.
4228 DRAW_INVERSE_VIDEO draw in mode line face
4229 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4230 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4231
4232 If REAL_START is non-null, return in *REAL_START the real starting
4233 position for display. This can be different from START in case
4234 overlapping glyphs must be displayed. If REAL_END is non-null,
4235 return in *REAL_END the real end position for display. This can be
4236 different from END in case overlapping glyphs must be displayed.
4237
4238 Value is the x-position reached, relative to AREA of W. */
4239
4240static int
4241x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end)
4242 struct window *w;
4243 int x;
4244 struct glyph_row *row;
4245 enum glyph_row_area area;
4246 int start, end;
4247 enum draw_glyphs_face hl;
4248 int *real_start, *real_end;
dc6f92b8 4249{
06a2c219
GM
4250 struct glyph_string *head, *tail;
4251 struct glyph_string *s;
4252 int last_x, area_width;
4253 int x_reached;
4254 int i, j;
4255
4256 /* Let's rather be paranoid than getting a SEGV. */
4257 start = max (0, start);
4258 end = min (end, row->used[area]);
4259 if (real_start)
4260 *real_start = start;
4261 if (real_end)
4262 *real_end = end;
4263
4264 /* Translate X to frame coordinates. Set last_x to the right
4265 end of the drawing area. */
4266 if (row->full_width_p)
4267 {
4268 /* X is relative to the left edge of W, without scroll bars
4269 or flag areas. */
4270 struct frame *f = XFRAME (w->frame);
4271 int width = FRAME_FLAGS_AREA_WIDTH (f);
4272 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
dc6f92b8 4273
06a2c219
GM
4274 x += window_left_x;
4275 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4276 last_x = window_left_x + area_width;
4277
4278 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4279 {
4280 width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4281 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4282 last_x += width;
4283 else
4284 x -= width;
4285 }
dc6f92b8 4286
b9432a85
GM
4287 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4288 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
06a2c219
GM
4289 }
4290 else
dc6f92b8 4291 {
06a2c219
GM
4292 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4293 area_width = window_box_width (w, area);
4294 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
dc6f92b8
JB
4295 }
4296
06a2c219
GM
4297 /* Build a doubly-linked list of glyph_string structures between
4298 head and tail from what we have to draw. Note that the macro
4299 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4300 the reason we use a separate variable `i'. */
4301 i = start;
4302 BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x);
4303 if (tail)
4304 x_reached = tail->x + tail->background_width;
4305 else
4306 x_reached = x;
90e65f07 4307
06a2c219
GM
4308 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4309 the row, redraw some glyphs in front or following the glyph
4310 strings built above. */
4311 if (row->contains_overlapping_glyphs_p)
4312 {
4313 int dummy_x = 0;
4314 struct glyph_string *h, *t;
4315
4316 /* Compute overhangs for all glyph strings. */
4317 for (s = head; s; s = s->next)
4318 x_compute_glyph_string_overhangs (s);
4319
4320 /* Prepend glyph strings for glyphs in front of the first glyph
4321 string that are overwritten because of the first glyph
4322 string's left overhang. The background of all strings
4323 prepended must be drawn because the first glyph string
4324 draws over it. */
4325 i = x_left_overwritten (head);
4326 if (i >= 0)
4327 {
4328 j = i;
4329 BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
4330 DRAW_NORMAL_TEXT, dummy_x, last_x);
4331 start = i;
4332 if (real_start)
4333 *real_start = start;
4334 x_compute_overhangs_and_x (t, head->x, 1);
4335 x_prepend_glyph_string_lists (&head, &tail, h, t);
4336 }
58769bee 4337
06a2c219
GM
4338 /* Prepend glyph strings for glyphs in front of the first glyph
4339 string that overwrite that glyph string because of their
4340 right overhang. For these strings, only the foreground must
4341 be drawn, because it draws over the glyph string at `head'.
4342 The background must not be drawn because this would overwrite
4343 right overhangs of preceding glyphs for which no glyph
4344 strings exist. */
4345 i = x_left_overwriting (head);
4346 if (i >= 0)
4347 {
4348 BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
4349 DRAW_NORMAL_TEXT, dummy_x, last_x);
4350 for (s = h; s; s = s->next)
4351 s->background_filled_p = 1;
4352 if (real_start)
4353 *real_start = i;
4354 x_compute_overhangs_and_x (t, head->x, 1);
4355 x_prepend_glyph_string_lists (&head, &tail, h, t);
4356 }
dbcb258a 4357
06a2c219
GM
4358 /* Append glyphs strings for glyphs following the last glyph
4359 string tail that are overwritten by tail. The background of
4360 these strings has to be drawn because tail's foreground draws
4361 over it. */
4362 i = x_right_overwritten (tail);
4363 if (i >= 0)
4364 {
4365 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4366 DRAW_NORMAL_TEXT, x, last_x);
4367 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4368 x_append_glyph_string_lists (&head, &tail, h, t);
4369 if (real_end)
4370 *real_end = i;
4371 }
dc6f92b8 4372
06a2c219
GM
4373 /* Append glyph strings for glyphs following the last glyph
4374 string tail that overwrite tail. The foreground of such
4375 glyphs has to be drawn because it writes into the background
4376 of tail. The background must not be drawn because it could
4377 paint over the foreground of following glyphs. */
4378 i = x_right_overwriting (tail);
4379 if (i >= 0)
4380 {
4381 BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
4382 DRAW_NORMAL_TEXT, x, last_x);
4383 for (s = h; s; s = s->next)
4384 s->background_filled_p = 1;
4385 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4386 x_append_glyph_string_lists (&head, &tail, h, t);
4387 if (real_end)
4388 *real_end = i;
4389 }
4390 }
58769bee 4391
06a2c219
GM
4392 /* Draw all strings. */
4393 for (s = head; s; s = s->next)
4394 x_draw_glyph_string (s);
dc6f92b8 4395
06a2c219
GM
4396 /* Value is the x-position up to which drawn, relative to AREA of W.
4397 This doesn't include parts drawn because of overhangs. */
4398 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4399 if (!row->full_width_p)
4400 {
4401 if (area > LEFT_MARGIN_AREA)
4402 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4403 if (area > TEXT_AREA)
4404 x_reached -= window_box_width (w, TEXT_AREA);
4405 }
4406 return x_reached;
4407}
dc6f92b8 4408
dc6f92b8 4409
06a2c219
GM
4410/* Output LEN glyphs starting at START at the nominal cursor position.
4411 Advance the nominal cursor over the text. The global variable
4412 updated_window contains the window being updated, updated_row is
4413 the glyph row being updated, and updated_area is the area of that
4414 row being updated. */
dc6f92b8 4415
06a2c219
GM
4416static void
4417x_write_glyphs (start, len)
4418 struct glyph *start;
4419 int len;
4420{
4421 int x, hpos, real_start, real_end;
d9cdbb3d 4422
06a2c219 4423 xassert (updated_window && updated_row);
dc6f92b8 4424 BLOCK_INPUT;
06a2c219
GM
4425
4426 /* Write glyphs. */
dc6f92b8 4427
06a2c219
GM
4428 hpos = start - updated_row->glyphs[updated_area];
4429 x = x_draw_glyphs (updated_window, output_cursor.x,
4430 updated_row, updated_area,
4431 hpos, hpos + len,
4432 (updated_row->inverse_p
4433 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4434 &real_start, &real_end);
b30ec466 4435
06a2c219
GM
4436 /* If we drew over the cursor, note that it is not visible any more. */
4437 note_overwritten_text_cursor (updated_window, real_start,
4438 real_end - real_start);
dc6f92b8
JB
4439
4440 UNBLOCK_INPUT;
06a2c219
GM
4441
4442 /* Advance the output cursor. */
4443 output_cursor.hpos += len;
4444 output_cursor.x = x;
dc6f92b8
JB
4445}
4446
0cdd0c9f 4447
06a2c219 4448/* Insert LEN glyphs from START at the nominal cursor position. */
0cdd0c9f 4449
06a2c219
GM
4450static void
4451x_insert_glyphs (start, len)
4452 struct glyph *start;
4453 register int len;
4454{
4455 struct frame *f;
4456 struct window *w;
4457 int line_height, shift_by_width, shifted_region_width;
4458 struct glyph_row *row;
4459 struct glyph *glyph;
4460 int frame_x, frame_y, hpos, real_start, real_end;
58769bee 4461
06a2c219 4462 xassert (updated_window && updated_row);
0cdd0c9f 4463 BLOCK_INPUT;
06a2c219
GM
4464 w = updated_window;
4465 f = XFRAME (WINDOW_FRAME (w));
4466
4467 /* Get the height of the line we are in. */
4468 row = updated_row;
4469 line_height = row->height;
4470
4471 /* Get the width of the glyphs to insert. */
4472 shift_by_width = 0;
4473 for (glyph = start; glyph < start + len; ++glyph)
4474 shift_by_width += glyph->pixel_width;
4475
4476 /* Get the width of the region to shift right. */
4477 shifted_region_width = (window_box_width (w, updated_area)
4478 - output_cursor.x
4479 - shift_by_width);
4480
4481 /* Shift right. */
4482 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4483 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4484 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4485 f->output_data.x->normal_gc,
4486 frame_x, frame_y,
4487 shifted_region_width, line_height,
4488 frame_x + shift_by_width, frame_y);
4489
4490 /* Write the glyphs. */
4491 hpos = start - row->glyphs[updated_area];
4492 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4493 DRAW_NORMAL_TEXT, &real_start, &real_end);
4494 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4495
4496 /* Advance the output cursor. */
4497 output_cursor.hpos += len;
4498 output_cursor.x += shift_by_width;
0cdd0c9f
RS
4499 UNBLOCK_INPUT;
4500}
0cdd0c9f 4501
0cdd0c9f 4502
06a2c219
GM
4503/* Delete N glyphs at the nominal cursor position. Not implemented
4504 for X frames. */
c83febd7
RS
4505
4506static void
06a2c219
GM
4507x_delete_glyphs (n)
4508 register int n;
c83febd7 4509{
06a2c219 4510 abort ();
c83febd7
RS
4511}
4512
0cdd0c9f 4513
06a2c219
GM
4514/* Erase the current text line from the nominal cursor position
4515 (inclusive) to pixel column TO_X (exclusive). The idea is that
4516 everything from TO_X onward is already erased.
4517
4518 TO_X is a pixel position relative to updated_area of
4519 updated_window. TO_X == -1 means clear to the end of this area. */
dc6f92b8 4520
06a2c219
GM
4521static void
4522x_clear_end_of_line (to_x)
4523 int to_x;
4524{
4525 struct frame *f;
4526 struct window *w = updated_window;
4527 int max_x, min_y, max_y;
4528 int from_x, from_y, to_y;
4529
4530 xassert (updated_window && updated_row);
4531 f = XFRAME (w->frame);
4532
4533 if (updated_row->full_width_p)
4534 {
4535 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4536 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4537 && !w->pseudo_window_p)
4538 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
0cdd0c9f 4539 }
06a2c219
GM
4540 else
4541 max_x = window_box_width (w, updated_area);
4542 max_y = window_text_bottom_y (w);
dc6f92b8 4543
06a2c219
GM
4544 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4545 of window. For TO_X > 0, truncate to end of drawing area. */
4546 if (to_x == 0)
4547 return;
4548 else if (to_x < 0)
4549 to_x = max_x;
4550 else
4551 to_x = min (to_x, max_x);
dbc4e1c1 4552
06a2c219
GM
4553 to_y = min (max_y, output_cursor.y + updated_row->height);
4554
4555 /* Notice if the cursor will be cleared by this operation. */
4556 if (!updated_row->full_width_p)
4557 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
dbc4e1c1 4558
06a2c219
GM
4559 from_x = output_cursor.x;
4560
4561 /* Translate to frame coordinates. */
4562 if (updated_row->full_width_p)
4563 {
4564 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4565 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4566 }
0cdd0c9f
RS
4567 else
4568 {
06a2c219
GM
4569 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4570 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4571 }
4572
4573 min_y = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
4574 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4575 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4576
4577 /* Prevent inadvertently clearing to end of the X window. */
4578 if (to_x > from_x && to_y > from_y)
4579 {
4580 BLOCK_INPUT;
4581 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4582 from_x, from_y, to_x - from_x, to_y - from_y,
4583 False);
4584 UNBLOCK_INPUT;
0cdd0c9f 4585 }
0cdd0c9f 4586}
dbc4e1c1 4587
0cdd0c9f 4588
06a2c219
GM
4589/* Clear entire frame. If updating_frame is non-null, clear that
4590 frame. Otherwise clear selected_frame. */
4591
4592static void
4593x_clear_frame ()
0cdd0c9f 4594{
06a2c219 4595 struct frame *f;
0cdd0c9f 4596
06a2c219
GM
4597 if (updating_frame)
4598 f = updating_frame;
0cdd0c9f 4599 else
06a2c219 4600 f = selected_frame;
58769bee 4601
06a2c219
GM
4602 /* Clearing the frame will erase any cursor, so mark them all as no
4603 longer visible. */
4604 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4605 output_cursor.hpos = output_cursor.vpos = 0;
4606 output_cursor.x = -1;
4607
4608 /* We don't set the output cursor here because there will always
4609 follow an explicit cursor_to. */
4610 BLOCK_INPUT;
4611 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
4612
4613 /* We have to clear the scroll bars, too. If we have changed
4614 colors or something like that, then they should be notified. */
4615 x_scroll_bar_clear (f);
0cdd0c9f 4616
06a2c219
GM
4617 XFlush (FRAME_X_DISPLAY (f));
4618 UNBLOCK_INPUT;
dc6f92b8 4619}
06a2c219
GM
4620
4621
dc6f92b8 4622\f
dbc4e1c1
JB
4623/* Invert the middle quarter of the frame for .15 sec. */
4624
06a2c219
GM
4625/* We use the select system call to do the waiting, so we have to make
4626 sure it's available. If it isn't, we just won't do visual bells. */
4627
dbc4e1c1
JB
4628#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
4629
06a2c219
GM
4630
4631/* Subtract the `struct timeval' values X and Y, storing the result in
4632 *RESULT. Return 1 if the difference is negative, otherwise 0. */
dbc4e1c1
JB
4633
4634static int
4635timeval_subtract (result, x, y)
4636 struct timeval *result, x, y;
4637{
06a2c219
GM
4638 /* Perform the carry for the later subtraction by updating y. This
4639 is safer because on some systems the tv_sec member is unsigned. */
dbc4e1c1
JB
4640 if (x.tv_usec < y.tv_usec)
4641 {
4642 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
4643 y.tv_usec -= 1000000 * nsec;
4644 y.tv_sec += nsec;
4645 }
06a2c219 4646
dbc4e1c1
JB
4647 if (x.tv_usec - y.tv_usec > 1000000)
4648 {
4649 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
4650 y.tv_usec += 1000000 * nsec;
4651 y.tv_sec -= nsec;
4652 }
4653
06a2c219
GM
4654 /* Compute the time remaining to wait. tv_usec is certainly
4655 positive. */
dbc4e1c1
JB
4656 result->tv_sec = x.tv_sec - y.tv_sec;
4657 result->tv_usec = x.tv_usec - y.tv_usec;
4658
06a2c219
GM
4659 /* Return indication of whether the result should be considered
4660 negative. */
dbc4e1c1
JB
4661 return x.tv_sec < y.tv_sec;
4662}
dc6f92b8 4663
dfcf069d 4664void
f676886a
JB
4665XTflash (f)
4666 struct frame *f;
dc6f92b8 4667{
dbc4e1c1 4668 BLOCK_INPUT;
dc6f92b8 4669
dbc4e1c1
JB
4670 {
4671 GC gc;
dc6f92b8 4672
06a2c219
GM
4673 /* Create a GC that will use the GXxor function to flip foreground
4674 pixels into background pixels. */
dbc4e1c1
JB
4675 {
4676 XGCValues values;
dc6f92b8 4677
dbc4e1c1 4678 values.function = GXxor;
7556890b
RS
4679 values.foreground = (f->output_data.x->foreground_pixel
4680 ^ f->output_data.x->background_pixel);
58769bee 4681
334208b7 4682 gc = XCreateGC (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dbc4e1c1
JB
4683 GCFunction | GCForeground, &values);
4684 }
dc6f92b8 4685
dbc4e1c1 4686 {
e84e14c3
RS
4687 /* Get the height not including a menu bar widget. */
4688 int height = CHAR_TO_PIXEL_HEIGHT (f, FRAME_HEIGHT (f));
4689 /* Height of each line to flash. */
4690 int flash_height = FRAME_LINE_HEIGHT (f);
4691 /* These will be the left and right margins of the rectangles. */
4692 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f);
4693 int flash_right = PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f);
4694
4695 int width;
4696
4697 /* Don't flash the area between a scroll bar and the frame
4698 edge it is next to. */
4699 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f))
4700 {
4701 case vertical_scroll_bar_left:
4702 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4703 break;
4704
4705 case vertical_scroll_bar_right:
4706 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM;
4707 break;
06a2c219
GM
4708
4709 default:
4710 break;
e84e14c3
RS
4711 }
4712
4713 width = flash_right - flash_left;
4714
4715 /* If window is tall, flash top and bottom line. */
4716 if (height > 3 * FRAME_LINE_HEIGHT (f))
4717 {
4718 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
4719 flash_left,
4720 (FRAME_INTERNAL_BORDER_WIDTH (f)
4721 + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
4722 width, flash_height);
4723 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4724 flash_left,
4725 (height - flash_height
4726 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4727 width, flash_height);
4728 }
4729 else
4730 /* If it is short, flash it all. */
4731 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4732 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4733 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
dc6f92b8 4734
06a2c219 4735 x_flush (f);
dc6f92b8 4736
dbc4e1c1 4737 {
06a2c219 4738 struct timeval wakeup;
dc6f92b8 4739
66c30ea1 4740 EMACS_GET_TIME (wakeup);
dc6f92b8 4741
dbc4e1c1
JB
4742 /* Compute time to wait until, propagating carry from usecs. */
4743 wakeup.tv_usec += 150000;
4744 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
4745 wakeup.tv_usec %= 1000000;
4746
4747 /* Keep waiting until past the time wakeup. */
4748 while (1)
4749 {
4750 struct timeval timeout;
4751
66c30ea1 4752 EMACS_GET_TIME (timeout);
dbc4e1c1
JB
4753
4754 /* In effect, timeout = wakeup - timeout.
4755 Break if result would be negative. */
4756 if (timeval_subtract (&timeout, wakeup, timeout))
4757 break;
4758
4759 /* Try to wait that long--but we might wake up sooner. */
c32cdd9a 4760 select (0, NULL, NULL, NULL, &timeout);
dbc4e1c1
JB
4761 }
4762 }
58769bee 4763
e84e14c3
RS
4764 /* If window is tall, flash top and bottom line. */
4765 if (height > 3 * FRAME_LINE_HEIGHT (f))
4766 {
4767 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
06a2c219
GM
4768 flash_left,
4769 (FRAME_INTERNAL_BORDER_WIDTH (f)
4770 + FRAME_TOOLBAR_LINES (f) * CANON_Y_UNIT (f)),
e84e14c3
RS
4771 width, flash_height);
4772 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4773 flash_left,
4774 (height - flash_height
4775 - FRAME_INTERNAL_BORDER_WIDTH (f)),
4776 width, flash_height);
4777 }
4778 else
4779 /* If it is short, flash it all. */
4780 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), gc,
4781 flash_left, FRAME_INTERNAL_BORDER_WIDTH (f),
4782 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
4783
334208b7 4784 XFreeGC (FRAME_X_DISPLAY (f), gc);
06a2c219 4785 x_flush (f);
dc6f92b8 4786 }
dbc4e1c1
JB
4787 }
4788
4789 UNBLOCK_INPUT;
dc6f92b8
JB
4790}
4791
06a2c219 4792#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
dbc4e1c1
JB
4793
4794
dc6f92b8
JB
4795/* Make audible bell. */
4796
334208b7 4797#define XRINGBELL XBell (FRAME_X_DISPLAY (selected_frame), 0)
dc6f92b8 4798
dfcf069d 4799void
dc6f92b8
JB
4800XTring_bell ()
4801{
334208b7 4802 if (FRAME_X_DISPLAY (selected_frame) == 0)
5a6ef893
RS
4803 return;
4804
dbc4e1c1 4805#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
dc6f92b8 4806 if (visible_bell)
f676886a 4807 XTflash (selected_frame);
dc6f92b8 4808 else
dbc4e1c1 4809#endif
dc6f92b8
JB
4810 {
4811 BLOCK_INPUT;
4812 XRINGBELL;
334208b7 4813 XFlush (FRAME_X_DISPLAY (selected_frame));
dc6f92b8
JB
4814 UNBLOCK_INPUT;
4815 }
4816}
06a2c219 4817
dc6f92b8 4818\f
06a2c219
GM
4819/* Specify how many text lines, from the top of the window,
4820 should be affected by insert-lines and delete-lines operations.
4821 This, and those operations, are used only within an update
4822 that is bounded by calls to x_update_begin and x_update_end. */
dc6f92b8 4823
dfcf069d 4824static void
06a2c219
GM
4825XTset_terminal_window (n)
4826 register int n;
dc6f92b8 4827{
06a2c219 4828 /* This function intentionally left blank. */
dc6f92b8
JB
4829}
4830
06a2c219
GM
4831
4832\f
4833/***********************************************************************
4834 Line Dance
4835 ***********************************************************************/
4836
4837/* Perform an insert-lines or delete-lines operation, inserting N
4838 lines or deleting -N lines at vertical position VPOS. */
4839
dfcf069d 4840static void
06a2c219
GM
4841x_ins_del_lines (vpos, n)
4842 int vpos, n;
dc6f92b8
JB
4843{
4844 abort ();
4845}
06a2c219
GM
4846
4847
4848/* Scroll part of the display as described by RUN. */
dc6f92b8 4849
dfcf069d 4850static void
06a2c219
GM
4851x_scroll_run (w, run)
4852 struct window *w;
4853 struct run *run;
dc6f92b8 4854{
06a2c219
GM
4855 struct frame *f = XFRAME (w->frame);
4856 int x, y, width, height, from_y, to_y, bottom_y;
4857
4858 /* Get frame-relative bounding box of the text display area of W,
4859 without mode lines. Include in this box the flags areas to the
4860 left and right of W. */
4861 window_box (w, -1, &x, &y, &width, &height);
4862 width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f);
4863 x -= FRAME_X_FLAGS_AREA_WIDTH (f);
4864
4865 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4866 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4867 bottom_y = y + height;
dc6f92b8 4868
06a2c219
GM
4869 if (to_y < from_y)
4870 {
4871 /* Scrolling up. Make sure we don't copy part of the mode
4872 line at the bottom. */
4873 if (from_y + run->height > bottom_y)
4874 height = bottom_y - from_y;
4875 else
4876 height = run->height;
4877 }
dc6f92b8 4878 else
06a2c219
GM
4879 {
4880 /* Scolling down. Make sure we don't copy over the mode line.
4881 at the bottom. */
4882 if (to_y + run->height > bottom_y)
4883 height = bottom_y - to_y;
4884 else
4885 height = run->height;
4886 }
7a13e894 4887
06a2c219
GM
4888 BLOCK_INPUT;
4889
4890 /* Cursor off. Will be switched on again in x_update_window_end. */
4891 updated_window = w;
4892 x_clear_cursor (w);
4893
4894 XCopyArea (FRAME_X_DISPLAY (f),
4895 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
4896 f->output_data.x->normal_gc,
4897 x, from_y,
4898 width, height,
4899 x, to_y);
4900
4901 UNBLOCK_INPUT;
4902}
dc6f92b8 4903
dc6f92b8 4904
06a2c219
GM
4905\f
4906/***********************************************************************
4907 Exposure Events
4908 ***********************************************************************/
4909
4910/* Redisplay an exposed area of frame F. X and Y are the upper-left
4911 corner of the exposed rectangle. W and H are width and height of
4912 the exposed area. All are pixel values. W or H zero means redraw
4913 the entire frame. */
dc6f92b8 4914
06a2c219
GM
4915static void
4916expose_frame (f, x, y, w, h)
4917 struct frame *f;
4918 int x, y, w, h;
dc6f92b8 4919{
06a2c219 4920 XRectangle r;
dc6f92b8 4921
06a2c219 4922 TRACE ((stderr, "expose_frame "));
dc6f92b8 4923
06a2c219
GM
4924 /* No need to redraw if frame will be redrawn soon. */
4925 if (FRAME_GARBAGED_P (f))
dc6f92b8 4926 {
06a2c219
GM
4927 TRACE ((stderr, " garbaged\n"));
4928 return;
4929 }
4930
4931 /* If basic faces haven't been realized yet, there is no point in
4932 trying to redraw anything. This can happen when we get an expose
4933 event while Emacs is starting, e.g. by moving another window. */
4934 if (FRAME_FACE_CACHE (f) == NULL
4935 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
4936 {
4937 TRACE ((stderr, " no faces\n"));
4938 return;
58769bee 4939 }
06a2c219
GM
4940
4941 if (w == 0 || h == 0)
58769bee 4942 {
06a2c219
GM
4943 r.x = r.y = 0;
4944 r.width = CANON_X_UNIT (f) * f->width;
4945 r.height = CANON_Y_UNIT (f) * f->height;
dc6f92b8
JB
4946 }
4947 else
4948 {
06a2c219
GM
4949 r.x = x;
4950 r.y = y;
4951 r.width = w;
4952 r.height = h;
4953 }
4954
4955 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
4956 expose_window_tree (XWINDOW (f->root_window), &r);
4957
4958 if (WINDOWP (f->toolbar_window))
4959 {
4960 struct window *w = XWINDOW (f->toolbar_window);
4961 XRectangle window_rect;
4962 XRectangle intersection_rect;
4963 int window_x, window_y, window_width, window_height;
4964
4965
4966 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
4967 window_rect.x = window_x;
4968 window_rect.y = window_y;
4969 window_rect.width = window_width;
4970 window_rect.height = window_height;
4971
4972 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
4973 expose_window (w, &intersection_rect);
4974 }
4975
4976#ifndef USE_X_TOOLKIT
4977 if (WINDOWP (f->menu_bar_window))
4978 {
4979 struct window *w = XWINDOW (f->menu_bar_window);
4980 XRectangle window_rect;
4981 XRectangle intersection_rect;
4982 int window_x, window_y, window_width, window_height;
4983
4984
4985 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
4986 window_rect.x = window_x;
4987 window_rect.y = window_y;
4988 window_rect.width = window_width;
4989 window_rect.height = window_height;
4990
4991 if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
4992 expose_window (w, &intersection_rect);
dc6f92b8 4993 }
06a2c219 4994#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
4995}
4996
06a2c219
GM
4997
4998/* Redraw (parts) of all windows in the window tree rooted at W that
4999 intersect R. R contains frame pixel coordinates. */
5000
58769bee 5001static void
06a2c219
GM
5002expose_window_tree (w, r)
5003 struct window *w;
5004 XRectangle *r;
dc6f92b8 5005{
06a2c219
GM
5006 while (w)
5007 {
5008 if (!NILP (w->hchild))
5009 expose_window_tree (XWINDOW (w->hchild), r);
5010 else if (!NILP (w->vchild))
5011 expose_window_tree (XWINDOW (w->vchild), r);
5012 else
5013 {
5014 XRectangle window_rect;
5015 XRectangle intersection_rect;
5016 struct frame *f = XFRAME (w->frame);
5017 int window_x, window_y, window_width, window_height;
5018
5019 /* Frame-relative pixel rectangle of W. */
5020 window_box (w, -1, &window_x, &window_y, &window_width,
5021 &window_height);
5022 window_rect.x
5023 = (window_x
5024 - FRAME_X_FLAGS_AREA_WIDTH (f)
5025 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
5026 window_rect.y = window_y;
5027 window_rect.width
5028 = (window_width
5029 + 2 * FRAME_X_FLAGS_AREA_WIDTH (f)
5030 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
5031 window_rect.height
5032 = window_height + CURRENT_MODE_LINE_HEIGHT (w);
5033
5034 if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
5035 expose_window (w, &intersection_rect);
5036 }
58769bee 5037
06a2c219
GM
5038 w = NILP (w->next) ? 0 : XWINDOW (w->next);
5039 }
5040}
58769bee 5041
dc6f92b8 5042
06a2c219
GM
5043/* Redraw the part of glyph row area AREA of glyph row ROW on window W
5044 which intersects rectangle R. R is in window-relative coordinates. */
5045
5046static void
5047expose_area (w, row, r, area)
5048 struct window *w;
5049 struct glyph_row *row;
5050 XRectangle *r;
5051 enum glyph_row_area area;
5052{
5053 int x;
5054 struct glyph *first = row->glyphs[area];
5055 struct glyph *end = row->glyphs[area] + row->used[area];
5056 struct glyph *last;
5057 int first_x;
5058
5059 /* Set x to the window-relative start position for drawing glyphs of
5060 AREA. The first glyph of the text area can be partially visible.
5061 The first glyphs of other areas cannot. */
5062 if (area == LEFT_MARGIN_AREA)
5063 x = 0;
5064 else if (area == TEXT_AREA)
5065 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5066 else
5067 x = (window_box_width (w, LEFT_MARGIN_AREA)
5068 + window_box_width (w, TEXT_AREA));
5069
5070 /* Find the first glyph that must be redrawn. */
5071 while (first < end
5072 && x + first->pixel_width < r->x)
5073 {
5074 x += first->pixel_width;
5075 ++first;
5076 }
5077
5078 /* Find the last one. */
5079 last = first;
5080 first_x = x;
5081 while (last < end
5082 && x < r->x + r->width)
5083 {
5084 x += last->pixel_width;
5085 ++last;
5086 }
5087
5088 /* Repaint. */
5089 if (last > first)
5090 x_draw_glyphs (w, first_x, row, area,
5091 first - row->glyphs[area],
5092 last - row->glyphs[area],
5093 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5094 NULL, NULL);
5095}
5096
58769bee 5097
06a2c219
GM
5098/* Redraw the parts of the glyph row ROW on window W intersecting
5099 rectangle R. R is in window-relative coordinates. */
dc6f92b8 5100
06a2c219
GM
5101static void
5102expose_line (w, row, r)
5103 struct window *w;
5104 struct glyph_row *row;
5105 XRectangle *r;
5106{
5107 xassert (row->enabled_p);
5108
5109 if (row->mode_line_p || w->pseudo_window_p)
5110 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5111 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5112 NULL, NULL);
5113 else
5114 {
5115 if (row->used[LEFT_MARGIN_AREA])
5116 expose_area (w, row, r, LEFT_MARGIN_AREA);
5117 if (row->used[TEXT_AREA])
5118 expose_area (w, row, r, TEXT_AREA);
5119 if (row->used[RIGHT_MARGIN_AREA])
5120 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5121 x_draw_row_bitmaps (w, row);
5122 }
5123}
dc6f92b8 5124
58769bee 5125
06a2c219
GM
5126/* Return non-zero if W's cursor intersects rectangle R. */
5127
5128static int
5129x_phys_cursor_in_rect_p (w, r)
5130 struct window *w;
5131 XRectangle *r;
5132{
5133 XRectangle cr, result;
5134 struct glyph *cursor_glyph;
5135
5136 cursor_glyph = get_phys_cursor_glyph (w);
5137 if (cursor_glyph)
5138 {
5139 cr.x = w->phys_cursor.x;
5140 cr.y = w->phys_cursor.y;
5141 cr.width = cursor_glyph->pixel_width;
5142 cr.height = w->phys_cursor_height;
5143 return x_intersect_rectangles (&cr, r, &result);
5144 }
5145 else
5146 return 0;
dc6f92b8 5147}
dc6f92b8 5148
06a2c219
GM
5149
5150/* Redraw a rectangle of window W. R is a rectangle in window
5151 relative coordinates. Call this function with input blocked. */
dc6f92b8
JB
5152
5153static void
06a2c219
GM
5154expose_window (w, r)
5155 struct window *w;
5156 XRectangle *r;
dc6f92b8 5157{
06a2c219
GM
5158 struct glyph_row *row;
5159 int y;
5160 int yb = window_text_bottom_y (w);
5161 int cursor_cleared_p;
dc6f92b8 5162
06a2c219
GM
5163 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5164 r->x, r->y, r->width, r->height));
dc6f92b8 5165
06a2c219
GM
5166 /* Convert to window coordinates. */
5167 r->x = FRAME_TO_WINDOW_PIXEL_X (w, r->x);
5168 r->y = FRAME_TO_WINDOW_PIXEL_Y (w, r->y);
dc6f92b8 5169
06a2c219
GM
5170 /* Turn off the cursor. */
5171 if (!w->pseudo_window_p
5172 && x_phys_cursor_in_rect_p (w, r))
5173 {
5174 x_clear_cursor (w);
5175 cursor_cleared_p = 1;
5176 }
5177 else
5178 cursor_cleared_p = 0;
5179
5180 /* Find the first row intersecting the rectangle R. */
5181 row = w->current_matrix->rows;
5182 y = 0;
5183 while (row->enabled_p
5184 && y < yb
5185 && y + row->height < r->y)
5186 {
5187 y += row->height;
5188 ++row;
5189 }
5190
dc6f92b8 5191 /* Display the text in the rectangle, one text line at a time. */
06a2c219
GM
5192 while (row->enabled_p
5193 && y < yb
5194 && y < r->y + r->height)
5195 {
5196 expose_line (w, row, r);
5197 y += row->height;
5198 ++row;
5199 }
5200
5201 /* Display the mode line if there is one. */
5202 if (WINDOW_WANTS_MODELINE_P (w)
5203 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5204 row->enabled_p)
5205 && row->y < r->y + r->height)
5206 expose_line (w, row, r);
dc6f92b8 5207
06a2c219 5208 if (!w->pseudo_window_p)
dc6f92b8 5209 {
06a2c219
GM
5210 /* Draw border between windows. */
5211 x_draw_vertical_border (w);
5212
5213 /* Turn the cursor on again. */
5214 if (cursor_cleared_p)
5215 x_update_window_cursor (w, 1);
5216 }
5217}
dc6f92b8 5218
dc6f92b8 5219
06a2c219
GM
5220/* Determine the intersection of two rectangles R1 and R2. Return
5221 the intersection in *RESULT. Value is non-zero if RESULT is not
5222 empty. */
5223
5224static int
5225x_intersect_rectangles (r1, r2, result)
5226 XRectangle *r1, *r2, *result;
5227{
5228 XRectangle *left, *right;
5229 XRectangle *upper, *lower;
5230 int intersection_p = 0;
5231
5232 /* Rearrange so that R1 is the left-most rectangle. */
5233 if (r1->x < r2->x)
5234 left = r1, right = r2;
5235 else
5236 left = r2, right = r1;
5237
5238 /* X0 of the intersection is right.x0, if this is inside R1,
5239 otherwise there is no intersection. */
5240 if (right->x <= left->x + left->width)
5241 {
5242 result->x = right->x;
5243
5244 /* The right end of the intersection is the minimum of the
5245 the right ends of left and right. */
5246 result->width = (min (left->x + left->width, right->x + right->width)
5247 - result->x);
5248
5249 /* Same game for Y. */
5250 if (r1->y < r2->y)
5251 upper = r1, lower = r2;
5252 else
5253 upper = r2, lower = r1;
5254
5255 /* The upper end of the intersection is lower.y0, if this is inside
5256 of upper. Otherwise, there is no intersection. */
5257 if (lower->y <= upper->y + upper->height)
dc43ef94 5258 {
06a2c219
GM
5259 result->y = lower->y;
5260
5261 /* The lower end of the intersection is the minimum of the lower
5262 ends of upper and lower. */
5263 result->height = (min (lower->y + lower->height,
5264 upper->y + upper->height)
5265 - result->y);
5266 intersection_p = 1;
dc43ef94 5267 }
dc6f92b8
JB
5268 }
5269
06a2c219 5270 return intersection_p;
dc6f92b8 5271}
06a2c219
GM
5272
5273
5274
5275
dc6f92b8 5276\f
dc6f92b8 5277static void
334208b7
RS
5278frame_highlight (f)
5279 struct frame *f;
dc6f92b8 5280{
b3e1e05c
JB
5281 /* We used to only do this if Vx_no_window_manager was non-nil, but
5282 the ICCCM (section 4.1.6) says that the window's border pixmap
5283 and border pixel are window attributes which are "private to the
5284 client", so we can always change it to whatever we want. */
5285 BLOCK_INPUT;
334208b7 5286 XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5287 f->output_data.x->border_pixel);
b3e1e05c 5288 UNBLOCK_INPUT;
5d46f928 5289 x_update_cursor (f, 1);
dc6f92b8
JB
5290}
5291
5292static void
334208b7
RS
5293frame_unhighlight (f)
5294 struct frame *f;
dc6f92b8 5295{
b3e1e05c
JB
5296 /* We used to only do this if Vx_no_window_manager was non-nil, but
5297 the ICCCM (section 4.1.6) says that the window's border pixmap
5298 and border pixel are window attributes which are "private to the
5299 client", so we can always change it to whatever we want. */
5300 BLOCK_INPUT;
334208b7 5301 XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 5302 f->output_data.x->border_tile);
b3e1e05c 5303 UNBLOCK_INPUT;
5d46f928 5304 x_update_cursor (f, 1);
dc6f92b8 5305}
dc6f92b8 5306
f676886a
JB
5307/* The focus has changed. Update the frames as necessary to reflect
5308 the new situation. Note that we can't change the selected frame
c5acd733 5309 here, because the Lisp code we are interrupting might become confused.
eb8c3be9 5310 Each event gets marked with the frame in which it occurred, so the
c5acd733 5311 Lisp code can tell when the switch took place by examining the events. */
dc6f92b8 5312
6d4238f3 5313static void
0f941935
KH
5314x_new_focus_frame (dpyinfo, frame)
5315 struct x_display_info *dpyinfo;
f676886a 5316 struct frame *frame;
dc6f92b8 5317{
0f941935 5318 struct frame *old_focus = dpyinfo->x_focus_frame;
dc6f92b8 5319
0f941935 5320 if (frame != dpyinfo->x_focus_frame)
dc6f92b8 5321 {
58769bee 5322 /* Set this before calling other routines, so that they see
f676886a 5323 the correct value of x_focus_frame. */
0f941935 5324 dpyinfo->x_focus_frame = frame;
6d4238f3
JB
5325
5326 if (old_focus && old_focus->auto_lower)
f676886a 5327 x_lower_frame (old_focus);
dc6f92b8
JB
5328
5329#if 0
f676886a 5330 selected_frame = frame;
e0c1aef2
KH
5331 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
5332 selected_frame);
f676886a
JB
5333 Fselect_window (selected_frame->selected_window);
5334 choose_minibuf_frame ();
c118dd06 5335#endif /* ! 0 */
dc6f92b8 5336
0f941935
KH
5337 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
5338 pending_autoraise_frame = dpyinfo->x_focus_frame;
0134a210
RS
5339 else
5340 pending_autoraise_frame = 0;
6d4238f3 5341 }
dc6f92b8 5342
0f941935 5343 x_frame_rehighlight (dpyinfo);
6d4238f3
JB
5344}
5345
37c2c98b
RS
5346/* Handle an event saying the mouse has moved out of an Emacs frame. */
5347
5348void
0f941935
KH
5349x_mouse_leave (dpyinfo)
5350 struct x_display_info *dpyinfo;
37c2c98b 5351{
0f941935 5352 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
37c2c98b 5353}
6d4238f3 5354
f451eb13
JB
5355/* The focus has changed, or we have redirected a frame's focus to
5356 another frame (this happens when a frame uses a surrogate
06a2c219 5357 mini-buffer frame). Shift the highlight as appropriate.
0f941935
KH
5358
5359 The FRAME argument doesn't necessarily have anything to do with which
06a2c219 5360 frame is being highlighted or un-highlighted; we only use it to find
0f941935 5361 the appropriate X display info. */
06a2c219 5362
6d4238f3 5363static void
0f941935
KH
5364XTframe_rehighlight (frame)
5365 struct frame *frame;
6d4238f3 5366{
0f941935
KH
5367 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
5368}
6d4238f3 5369
0f941935
KH
5370static void
5371x_frame_rehighlight (dpyinfo)
5372 struct x_display_info *dpyinfo;
5373{
5374 struct frame *old_highlight = dpyinfo->x_highlight_frame;
5375
5376 if (dpyinfo->x_focus_frame)
6d4238f3 5377 {
0f941935
KH
5378 dpyinfo->x_highlight_frame
5379 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
5380 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
5381 : dpyinfo->x_focus_frame);
5382 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
f451eb13 5383 {
0f941935
KH
5384 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
5385 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
f451eb13 5386 }
dc6f92b8 5387 }
6d4238f3 5388 else
0f941935 5389 dpyinfo->x_highlight_frame = 0;
dc6f92b8 5390
0f941935 5391 if (dpyinfo->x_highlight_frame != old_highlight)
6d4238f3
JB
5392 {
5393 if (old_highlight)
f676886a 5394 frame_unhighlight (old_highlight);
0f941935
KH
5395 if (dpyinfo->x_highlight_frame)
5396 frame_highlight (dpyinfo->x_highlight_frame);
6d4238f3 5397 }
dc6f92b8 5398}
06a2c219
GM
5399
5400
dc6f92b8 5401\f
06a2c219 5402/* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
dc6f92b8 5403
28430d3c
JB
5404/* Initialize mode_switch_bit and modifier_meaning. */
5405static void
334208b7
RS
5406x_find_modifier_meanings (dpyinfo)
5407 struct x_display_info *dpyinfo;
28430d3c 5408{
f689eb05 5409 int min_code, max_code;
28430d3c
JB
5410 KeySym *syms;
5411 int syms_per_code;
5412 XModifierKeymap *mods;
5413
334208b7
RS
5414 dpyinfo->meta_mod_mask = 0;
5415 dpyinfo->shift_lock_mask = 0;
5416 dpyinfo->alt_mod_mask = 0;
5417 dpyinfo->super_mod_mask = 0;
5418 dpyinfo->hyper_mod_mask = 0;
58769bee 5419
9658a521 5420#ifdef HAVE_X11R4
334208b7 5421 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
9658a521 5422#else
4a60f8c5
RS
5423 min_code = dpyinfo->display->min_keycode;
5424 max_code = dpyinfo->display->max_keycode;
9658a521
JB
5425#endif
5426
334208b7 5427 syms = XGetKeyboardMapping (dpyinfo->display,
28430d3c
JB
5428 min_code, max_code - min_code + 1,
5429 &syms_per_code);
334208b7 5430 mods = XGetModifierMapping (dpyinfo->display);
28430d3c 5431
58769bee 5432 /* Scan the modifier table to see which modifier bits the Meta and
11edeb03 5433 Alt keysyms are on. */
28430d3c 5434 {
06a2c219 5435 int row, col; /* The row and column in the modifier table. */
28430d3c
JB
5436
5437 for (row = 3; row < 8; row++)
5438 for (col = 0; col < mods->max_keypermod; col++)
5439 {
0299d313
RS
5440 KeyCode code
5441 = mods->modifiermap[(row * mods->max_keypermod) + col];
28430d3c 5442
af92970c
KH
5443 /* Zeroes are used for filler. Skip them. */
5444 if (code == 0)
5445 continue;
5446
28430d3c
JB
5447 /* Are any of this keycode's keysyms a meta key? */
5448 {
5449 int code_col;
5450
5451 for (code_col = 0; code_col < syms_per_code; code_col++)
5452 {
f689eb05 5453 int sym = syms[((code - min_code) * syms_per_code) + code_col];
28430d3c 5454
f689eb05 5455 switch (sym)
28430d3c 5456 {
f689eb05
JB
5457 case XK_Meta_L:
5458 case XK_Meta_R:
334208b7 5459 dpyinfo->meta_mod_mask |= (1 << row);
28430d3c 5460 break;
f689eb05
JB
5461
5462 case XK_Alt_L:
5463 case XK_Alt_R:
334208b7 5464 dpyinfo->alt_mod_mask |= (1 << row);
a3c44b14
RS
5465 break;
5466
5467 case XK_Hyper_L:
5468 case XK_Hyper_R:
334208b7 5469 dpyinfo->hyper_mod_mask |= (1 << row);
a3c44b14
RS
5470 break;
5471
5472 case XK_Super_L:
5473 case XK_Super_R:
334208b7 5474 dpyinfo->super_mod_mask |= (1 << row);
f689eb05 5475 break;
11edeb03
JB
5476
5477 case XK_Shift_Lock:
5478 /* Ignore this if it's not on the lock modifier. */
5479 if ((1 << row) == LockMask)
334208b7 5480 dpyinfo->shift_lock_mask = LockMask;
11edeb03 5481 break;
28430d3c
JB
5482 }
5483 }
5484 }
5485 }
5486 }
5487
f689eb05 5488 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
334208b7 5489 if (! dpyinfo->meta_mod_mask)
a3c44b14 5490 {
334208b7
RS
5491 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
5492 dpyinfo->alt_mod_mask = 0;
a3c44b14 5493 }
f689eb05 5494
148c4b70
RS
5495 /* If some keys are both alt and meta,
5496 make them just meta, not alt. */
334208b7 5497 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
148c4b70 5498 {
334208b7 5499 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
148c4b70 5500 }
58769bee 5501
28430d3c 5502 XFree ((char *) syms);
f689eb05 5503 XFreeModifiermap (mods);
28430d3c
JB
5504}
5505
dfeccd2d
JB
5506/* Convert between the modifier bits X uses and the modifier bits
5507 Emacs uses. */
06a2c219 5508
7c5283e4 5509static unsigned int
334208b7
RS
5510x_x_to_emacs_modifiers (dpyinfo, state)
5511 struct x_display_info *dpyinfo;
dc6f92b8
JB
5512 unsigned int state;
5513{
334208b7
RS
5514 return ( ((state & (ShiftMask | dpyinfo->shift_lock_mask)) ? shift_modifier : 0)
5515 | ((state & ControlMask) ? ctrl_modifier : 0)
5516 | ((state & dpyinfo->meta_mod_mask) ? meta_modifier : 0)
5517 | ((state & dpyinfo->alt_mod_mask) ? alt_modifier : 0)
5518 | ((state & dpyinfo->super_mod_mask) ? super_modifier : 0)
5519 | ((state & dpyinfo->hyper_mod_mask) ? hyper_modifier : 0));
dc6f92b8
JB
5520}
5521
dfeccd2d 5522static unsigned int
334208b7
RS
5523x_emacs_to_x_modifiers (dpyinfo, state)
5524 struct x_display_info *dpyinfo;
dfeccd2d
JB
5525 unsigned int state;
5526{
334208b7
RS
5527 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
5528 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
5529 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
5530 | ((state & shift_modifier) ? ShiftMask : 0)
5531 | ((state & ctrl_modifier) ? ControlMask : 0)
5532 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
dfeccd2d 5533}
d047c4eb
KH
5534
5535/* Convert a keysym to its name. */
5536
5537char *
5538x_get_keysym_name (keysym)
5539 KeySym keysym;
5540{
5541 char *value;
5542
5543 BLOCK_INPUT;
5544 value = XKeysymToString (keysym);
5545 UNBLOCK_INPUT;
5546
5547 return value;
5548}
06a2c219
GM
5549
5550
e4571a43
JB
5551\f
5552/* Mouse clicks and mouse movement. Rah. */
e4571a43 5553
06a2c219
GM
5554/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5555 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5556 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5557 not force the value into range. */
69388238 5558
c8dba240 5559void
69388238 5560pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
e4571a43 5561 FRAME_PTR f;
69388238 5562 register int pix_x, pix_y;
e4571a43
JB
5563 register int *x, *y;
5564 XRectangle *bounds;
69388238 5565 int noclip;
e4571a43 5566{
06a2c219 5567 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
69388238
RS
5568 even for negative values. */
5569 if (pix_x < 0)
7556890b 5570 pix_x -= FONT_WIDTH ((f)->output_data.x->font) - 1;
69388238 5571 if (pix_y < 0)
7556890b 5572 pix_y -= (f)->output_data.x->line_height - 1;
69388238 5573
e4571a43
JB
5574 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5575 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5576
5577 if (bounds)
5578 {
7556890b
RS
5579 bounds->width = FONT_WIDTH (f->output_data.x->font);
5580 bounds->height = f->output_data.x->line_height;
e4571a43
JB
5581 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x);
5582 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y);
5583 }
5584
69388238
RS
5585 if (!noclip)
5586 {
5587 if (pix_x < 0)
5588 pix_x = 0;
3cbd2e0b
RS
5589 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5590 pix_x = FRAME_WINDOW_WIDTH (f);
69388238
RS
5591
5592 if (pix_y < 0)
5593 pix_y = 0;
5594 else if (pix_y > f->height)
5595 pix_y = f->height;
5596 }
e4571a43
JB
5597
5598 *x = pix_x;
5599 *y = pix_y;
5600}
5601
06a2c219
GM
5602
5603/* Given HPOS/VPOS in the current matrix of W, return corresponding
5604 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5605 can't tell the positions because W's display is not up to date,
5606 return 0. */
5607
5608int
5609glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5610 struct window *w;
5611 int hpos, vpos;
5612 int *frame_x, *frame_y;
2b5c9e71 5613{
06a2c219
GM
5614 int success_p;
5615
5616 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5617 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5618
5619 if (display_completed)
5620 {
5621 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5622 struct glyph *glyph = row->glyphs[TEXT_AREA];
5623 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5624
5625 *frame_y = row->y;
5626 *frame_x = row->x;
5627 while (glyph < end)
5628 {
5629 *frame_x += glyph->pixel_width;
5630 ++glyph;
5631 }
5632
5633 success_p = 1;
5634 }
5635 else
5636 {
5637 *frame_y = *frame_x = 0;
5638 success_p = 0;
5639 }
5640
5641 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5642 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5643 return success_p;
2b5c9e71
RS
5644}
5645
06a2c219 5646
dc6f92b8
JB
5647/* Prepare a mouse-event in *RESULT for placement in the input queue.
5648
5649 If the event is a button press, then note that we have grabbed
f451eb13 5650 the mouse. */
dc6f92b8
JB
5651
5652static Lisp_Object
f451eb13 5653construct_mouse_click (result, event, f)
dc6f92b8
JB
5654 struct input_event *result;
5655 XButtonEvent *event;
f676886a 5656 struct frame *f;
dc6f92b8 5657{
f451eb13 5658 /* Make the event type no_event; we'll change that when we decide
dc6f92b8 5659 otherwise. */
f451eb13 5660 result->kind = mouse_click;
69388238 5661 result->code = event->button - Button1;
1113d9db 5662 result->timestamp = event->time;
334208b7
RS
5663 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5664 event->state)
f689eb05 5665 | (event->type == ButtonRelease
58769bee 5666 ? up_modifier
f689eb05 5667 : down_modifier));
dc6f92b8 5668
06a2c219
GM
5669 XSETINT (result->x, event->x);
5670 XSETINT (result->y, event->y);
5671 XSETFRAME (result->frame_or_window, f);
5672 return Qnil;
dc6f92b8 5673}
b849c413 5674
06a2c219
GM
5675#if 0 /* This function isn't called. --gerd */
5676
b849c413
RS
5677/* Prepare a menu-event in *RESULT for placement in the input queue. */
5678
5679static Lisp_Object
5680construct_menu_click (result, event, f)
5681 struct input_event *result;
5682 XButtonEvent *event;
5683 struct frame *f;
5684{
5685 /* Make the event type no_event; we'll change that when we decide
5686 otherwise. */
5687 result->kind = mouse_click;
26459b28 5688 result->code = event->button - Button1;
b849c413 5689 result->timestamp = event->time;
334208b7
RS
5690 result->modifiers = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
5691 event->state)
b849c413 5692 | (event->type == ButtonRelease
58769bee 5693 ? up_modifier
b849c413
RS
5694 : down_modifier));
5695
e0c1aef2
KH
5696 XSETINT (result->x, event->x);
5697 XSETINT (result->y, -1);
5698 XSETFRAME (result->frame_or_window, f);
b849c413 5699}
06a2c219
GM
5700
5701#endif /* 0 */
5702
69388238 5703\f
90e65f07
JB
5704/* Function to report a mouse movement to the mainstream Emacs code.
5705 The input handler calls this.
5706
5707 We have received a mouse movement event, which is given in *event.
5708 If the mouse is over a different glyph than it was last time, tell
5709 the mainstream emacs code by setting mouse_moved. If not, ask for
5710 another motion event, so we can check again the next time it moves. */
b8009dd1 5711
06a2c219
GM
5712static XMotionEvent last_mouse_motion_event;
5713static Lisp_Object last_mouse_motion_frame;
5714
90e65f07 5715static void
12ba150f 5716note_mouse_movement (frame, event)
f676886a 5717 FRAME_PTR frame;
90e65f07 5718 XMotionEvent *event;
90e65f07 5719{
e5d77022 5720 last_mouse_movement_time = event->time;
06a2c219
GM
5721 last_mouse_motion_event = *event;
5722 XSETFRAME (last_mouse_motion_frame, frame);
e5d77022 5723
27f338af
RS
5724 if (event->window != FRAME_X_WINDOW (frame))
5725 {
39d8bb4d 5726 frame->mouse_moved = 1;
27f338af 5727 last_mouse_scroll_bar = Qnil;
27f338af 5728 note_mouse_highlight (frame, -1, -1);
27f338af
RS
5729 }
5730
90e65f07 5731 /* Has the mouse moved off the glyph it was on at the last sighting? */
27f338af
RS
5732 else if (event->x < last_mouse_glyph.x
5733 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width
5734 || event->y < last_mouse_glyph.y
5735 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height)
12ba150f 5736 {
39d8bb4d 5737 frame->mouse_moved = 1;
ab648270 5738 last_mouse_scroll_bar = Qnil;
b8009dd1 5739 note_mouse_highlight (frame, event->x, event->y);
90e65f07
JB
5740 }
5741}
5742
bf1c0ba1 5743/* This is used for debugging, to turn off note_mouse_highlight. */
bf1c0ba1 5744
06a2c219
GM
5745 int disable_mouse_highlight;
5746
5747
5748\f
5749/************************************************************************
5750 Mouse Face
5751 ************************************************************************/
5752
5753/* Find the glyph under window-relative coordinates X/Y in window W.
5754 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5755 strings. Return in *HPOS and *VPOS the row and column number of
5756 the glyph found. Return in *AREA the glyph area containing X.
5757 Value is a pointer to the glyph found or null if X/Y is not on
5758 text, or we can't tell because W's current matrix is not up to
5759 date. */
5760
5761static struct glyph *
5762x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5763 struct window *w;
5764 int x, y;
5765 int *hpos, *vpos, *area;
5766{
5767 struct glyph *glyph, *end;
5768 struct glyph_row *row;
5769 int x0, i, left_area_width;
5770
5771 /* Find row containing Y. Give up if some row is not enabled. */
5772 for (i = 0; i < w->current_matrix->nrows; ++i)
5773 {
5774 row = MATRIX_ROW (w->current_matrix, i);
5775 if (!row->enabled_p)
5776 return NULL;
5777 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5778 break;
5779 }
5780
5781 *vpos = i;
5782 *hpos = 0;
5783
5784 /* Give up if Y is not in the window. */
5785 if (i == w->current_matrix->nrows)
5786 return NULL;
5787
5788 /* Get the glyph area containing X. */
5789 if (w->pseudo_window_p)
5790 {
5791 *area = TEXT_AREA;
5792 x0 = 0;
5793 }
5794 else
5795 {
5796 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5797 if (x < left_area_width)
5798 {
5799 *area = LEFT_MARGIN_AREA;
5800 x0 = 0;
5801 }
5802 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5803 {
5804 *area = TEXT_AREA;
5805 x0 = row->x + left_area_width;
5806 }
5807 else
5808 {
5809 *area = RIGHT_MARGIN_AREA;
5810 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5811 }
5812 }
5813
5814 /* Find glyph containing X. */
5815 glyph = row->glyphs[*area];
5816 end = glyph + row->used[*area];
5817 while (glyph < end)
5818 {
5819 if (x < x0 + glyph->pixel_width)
5820 {
5821 if (w->pseudo_window_p)
5822 break;
5823 else if (BUFFERP (glyph->object))
5824 break;
5825 }
5826
5827 x0 += glyph->pixel_width;
5828 ++glyph;
5829 }
5830
5831 if (glyph == end)
5832 return NULL;
5833
5834 *hpos = glyph - row->glyphs[*area];
5835 return glyph;
5836}
5837
5838
5839/* Convert frame-relative x/y to coordinates relative to window W.
5840 Takes pseudo-windows into account. */
5841
5842static void
5843frame_to_window_pixel_xy (w, x, y)
5844 struct window *w;
5845 int *x, *y;
5846{
5847 if (w->pseudo_window_p)
5848 {
5849 /* A pseudo-window is always full-width, and starts at the
5850 left edge of the frame, plus a frame border. */
5851 struct frame *f = XFRAME (w->frame);
5852 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
5853 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5854 }
5855 else
5856 {
5857 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
5858 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5859 }
5860}
5861
5862
5863/* Take proper action when mouse has moved to the mode or top line of
5864 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5865 mode line. X is relative to the start of the text display area of
5866 W, so the width of bitmap areas and scroll bars must be subtracted
5867 to get a position relative to the start of the mode line. */
5868
5869static void
5870note_mode_line_highlight (w, x, mode_line_p)
5871 struct window *w;
5872 int x, mode_line_p;
5873{
5874 struct frame *f = XFRAME (w->frame);
5875 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5876 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
5877 struct glyph_row *row;
5878
5879 if (mode_line_p)
5880 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5881 else
5882 row = MATRIX_TOP_LINE_ROW (w->current_matrix);
5883
5884 if (row->enabled_p)
5885 {
5886 struct glyph *glyph, *end;
5887 Lisp_Object help, map;
5888 int x0;
5889
5890 /* Find the glyph under X. */
5891 glyph = row->glyphs[TEXT_AREA];
5892 end = glyph + row->used[TEXT_AREA];
5893 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
5894 + FRAME_X_FLAGS_AREA_WIDTH (f));
5895 while (glyph < end
5896 && x >= x0 + glyph->pixel_width)
5897 {
5898 x0 += glyph->pixel_width;
5899 ++glyph;
5900 }
5901
5902 if (glyph < end
5903 && STRINGP (glyph->object)
5904 && XSTRING (glyph->object)->intervals
5905 && glyph->charpos >= 0
5906 && glyph->charpos < XSTRING (glyph->object)->size)
5907 {
5908 /* If we're on a string with `help-echo' text property,
5909 arrange for the help to be displayed. This is done by
5910 setting the global variable help_echo to the help string. */
5911 help = Fget_text_property (make_number (glyph->charpos),
5912 Qhelp_echo, glyph->object);
5913 if (STRINGP (help))
5914 help_echo = help;
5915
5916 /* Change the mouse pointer according to what is under X/Y. */
5917 map = Fget_text_property (make_number (glyph->charpos),
5918 Qlocal_map, glyph->object);
5919 if (!NILP (Fkeymapp (map)))
5920 cursor = f->output_data.x->nontext_cursor;
5921 }
5922 }
5923
5924 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
5925}
5926
5927
5928/* Take proper action when the mouse has moved to position X, Y on
5929 frame F as regards highlighting characters that have mouse-face
5930 properties. Also de-highlighting chars where the mouse was before.
27f338af 5931 X and Y can be negative or out of range. */
b8009dd1
RS
5932
5933static void
5934note_mouse_highlight (f, x, y)
06a2c219 5935 struct frame *f;
c32cdd9a 5936 int x, y;
b8009dd1 5937{
06a2c219
GM
5938 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
5939 int portion;
b8009dd1
RS
5940 Lisp_Object window;
5941 struct window *w;
5942
06a2c219
GM
5943 /* When a menu is active, don't highlight because this looks odd. */
5944#ifdef USE_X_TOOLKIT
5945 if (popup_activated ())
5946 return;
5947#endif
5948
bf1c0ba1
RS
5949 if (disable_mouse_highlight)
5950 return;
5951
06a2c219
GM
5952 dpyinfo->mouse_face_mouse_x = x;
5953 dpyinfo->mouse_face_mouse_y = y;
5954 dpyinfo->mouse_face_mouse_frame = f;
b8009dd1 5955
06a2c219 5956 if (dpyinfo->mouse_face_defer)
b8009dd1
RS
5957 return;
5958
514e4681
RS
5959 if (gc_in_progress)
5960 {
06a2c219 5961 dpyinfo->mouse_face_deferred_gc = 1;
514e4681
RS
5962 return;
5963 }
5964
b8009dd1 5965 /* Which window is that in? */
06a2c219 5966 window = window_from_coordinates (f, x, y, &portion, 1);
b8009dd1
RS
5967
5968 /* If we were displaying active text in another window, clear that. */
06a2c219
GM
5969 if (! EQ (window, dpyinfo->mouse_face_window))
5970 clear_mouse_face (dpyinfo);
5971
5972 /* Not on a window -> return. */
5973 if (!WINDOWP (window))
5974 return;
5975
5976 /* Convert to window-relative pixel coordinates. */
5977 w = XWINDOW (window);
5978 frame_to_window_pixel_xy (w, &x, &y);
5979
5980 /* Handle toolbar window differently since it doesn't display a
5981 buffer. */
5982 if (EQ (window, f->toolbar_window))
5983 {
5984 note_toolbar_highlight (f, x, y);
5985 return;
5986 }
5987
5988 if (portion == 1 || portion == 3)
5989 {
5990 /* Mouse is on the mode or top line. */
5991 note_mode_line_highlight (w, x, portion == 1);
5992 return;
5993 }
5994 else
5995 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5996 f->output_data.x->text_cursor);
b8009dd1 5997
0cdd0c9f
RS
5998 /* Are we in a window whose display is up to date?
5999 And verify the buffer's text has not changed. */
06a2c219
GM
6000 if (/* Within text portion of the window. */
6001 portion == 0
0cdd0c9f 6002 && EQ (w->window_end_valid, w->buffer)
26459b28
KH
6003 && XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
6004 && (XFASTINT (w->last_overlay_modified)
6005 == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
b8009dd1 6006 {
06a2c219
GM
6007 int hpos, vpos, pos, i, area;
6008 struct glyph *glyph;
b8009dd1 6009
06a2c219
GM
6010 /* Find the glyph under X/Y. */
6011 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
6012
6013 /* Clear mouse face if X/Y not over text. */
6014 if (glyph == NULL
6015 || area != TEXT_AREA
6016 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
b8009dd1 6017 {
06a2c219
GM
6018 clear_mouse_face (dpyinfo);
6019 return;
6020 }
6021
6022 pos = glyph->charpos;
6023 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
6024
6025 /* Check for mouse-face and help-echo. */
6026 {
6027 Lisp_Object mouse_face, overlay, position;
6028 Lisp_Object *overlay_vec;
6029 int len, noverlays;
6030 struct buffer *obuf;
6031 int obegv, ozv;
6032
6033 /* If we get an out-of-range value, return now; avoid an error. */
6034 if (pos > BUF_Z (XBUFFER (w->buffer)))
6035 return;
6036
6037 /* Make the window's buffer temporarily current for
6038 overlays_at and compute_char_face. */
6039 obuf = current_buffer;
6040 current_buffer = XBUFFER (w->buffer);
6041 obegv = BEGV;
6042 ozv = ZV;
6043 BEGV = BEG;
6044 ZV = Z;
6045
6046 /* Is this char mouse-active or does it have help-echo? */
6047 XSETINT (position, pos);
6048
6049 /* Put all the overlays we want in a vector in overlay_vec.
6050 Store the length in len. If there are more than 10, make
6051 enough space for all, and try again. */
6052 len = 10;
6053 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6054 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6055 if (noverlays > len)
6056 {
6057 len = noverlays;
6058 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6059 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
6060 }
6061
6062 noverlays = sort_overlays (overlay_vec, noverlays, w);
6063
6064 /* Check mouse-face highlighting. */
6065 if (! (EQ (window, dpyinfo->mouse_face_window)
6066 && vpos >= dpyinfo->mouse_face_beg_row
6067 && vpos <= dpyinfo->mouse_face_end_row
6068 && (vpos > dpyinfo->mouse_face_beg_row
6069 || hpos >= dpyinfo->mouse_face_beg_col)
6070 && (vpos < dpyinfo->mouse_face_end_row
6071 || hpos < dpyinfo->mouse_face_end_col
6072 || dpyinfo->mouse_face_past_end)))
6073 {
6074 /* Clear the display of the old active region, if any. */
6075 clear_mouse_face (dpyinfo);
6076
6077 /* Find the highest priority overlay that has a mouse-face prop. */
6078 overlay = Qnil;
6079 for (i = 0; i < noverlays; i++)
6080 {
6081 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6082 if (!NILP (mouse_face))
6083 {
6084 overlay = overlay_vec[i];
6085 break;
6086 }
6087 }
6088
6089 /* If no overlay applies, get a text property. */
6090 if (NILP (overlay))
6091 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
6092
6093 /* Handle the overlay case. */
6094 if (! NILP (overlay))
6095 {
6096 /* Find the range of text around this char that
6097 should be active. */
6098 Lisp_Object before, after;
6099 int ignore;
6100
6101 before = Foverlay_start (overlay);
6102 after = Foverlay_end (overlay);
6103 /* Record this as the current active region. */
6104 fast_find_position (w, XFASTINT (before),
6105 &dpyinfo->mouse_face_beg_col,
6106 &dpyinfo->mouse_face_beg_row,
6107 &dpyinfo->mouse_face_beg_x,
6108 &dpyinfo->mouse_face_beg_y);
6109 dpyinfo->mouse_face_past_end
6110 = !fast_find_position (w, XFASTINT (after),
6111 &dpyinfo->mouse_face_end_col,
6112 &dpyinfo->mouse_face_end_row,
6113 &dpyinfo->mouse_face_end_x,
6114 &dpyinfo->mouse_face_end_y);
6115 dpyinfo->mouse_face_window = window;
6116 dpyinfo->mouse_face_face_id
6117 = face_at_buffer_position (w, pos, 0, 0,
6118 &ignore, pos + 1, 1);
6119
6120 /* Display it as active. */
6121 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6122 }
6123 /* Handle the text property case. */
6124 else if (! NILP (mouse_face))
6125 {
6126 /* Find the range of text around this char that
6127 should be active. */
6128 Lisp_Object before, after, beginning, end;
6129 int ignore;
6130
6131 beginning = Fmarker_position (w->start);
6132 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6133 - XFASTINT (w->window_end_pos)));
6134 before
6135 = Fprevious_single_property_change (make_number (pos + 1),
6136 Qmouse_face,
6137 w->buffer, beginning);
6138 after
6139 = Fnext_single_property_change (position, Qmouse_face,
6140 w->buffer, end);
6141 /* Record this as the current active region. */
6142 fast_find_position (w, XFASTINT (before),
6143 &dpyinfo->mouse_face_beg_col,
6144 &dpyinfo->mouse_face_beg_row,
6145 &dpyinfo->mouse_face_beg_x,
6146 &dpyinfo->mouse_face_beg_y);
6147 dpyinfo->mouse_face_past_end
6148 = !fast_find_position (w, XFASTINT (after),
6149 &dpyinfo->mouse_face_end_col,
6150 &dpyinfo->mouse_face_end_row,
6151 &dpyinfo->mouse_face_end_x,
6152 &dpyinfo->mouse_face_end_y);
6153 dpyinfo->mouse_face_window = window;
6154 dpyinfo->mouse_face_face_id
6155 = face_at_buffer_position (w, pos, 0, 0,
6156 &ignore, pos + 1, 1);
6157
6158 /* Display it as active. */
6159 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6160 }
6161 }
6162
6163 /* Look for a `help-echo' property. */
6164 {
6165 Lisp_Object help;
6166
6167 /* Check overlays first. */
6168 help = Qnil;
6169 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6170 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6171
6172 /* Try text properties. */
6173 if (!STRINGP (help)
6174 && ((STRINGP (glyph->object)
6175 && glyph->charpos >= 0
6176 && glyph->charpos < XSTRING (glyph->object)->size)
6177 || (BUFFERP (glyph->object)
6178 && glyph->charpos >= BEGV
6179 && glyph->charpos < ZV)))
6180 help = Fget_text_property (make_number (glyph->charpos),
6181 Qhelp_echo, glyph->object);
6182
6183 if (STRINGP (help))
6184 help_echo = help;
6185 }
6186
6187 BEGV = obegv;
6188 ZV = ozv;
6189 current_buffer = obuf;
6190 }
6191 }
6192}
6193
6194static void
6195redo_mouse_highlight ()
6196{
6197 if (!NILP (last_mouse_motion_frame)
6198 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6199 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6200 last_mouse_motion_event.x,
6201 last_mouse_motion_event.y);
6202}
6203
6204
6205\f
6206/***********************************************************************
6207 Toolbars
6208 ***********************************************************************/
6209
6210static int x_toolbar_item P_ ((struct frame *, int, int,
6211 struct glyph **, int *, int *, int *));
6212
6213/* Toolbar item index of the item on which a mouse button was pressed
6214 or -1. */
6215
6216static int last_toolbar_item;
6217
6218
6219/* Get information about the toolbar item at position X/Y on frame F.
6220 Return in *GLYPH a pointer to the glyph of the toolbar item in
6221 the current matrix of the toolbar window of F, or NULL if not
6222 on a toolbar item. Return in *PROP_IDX the index of the toolbar
6223 item in F->current_toolbar_items. Value is
6224
6225 -1 if X/Y is not on a toolbar item
6226 0 if X/Y is on the same item that was highlighted before.
6227 1 otherwise. */
6228
6229static int
6230x_toolbar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6231 struct frame *f;
6232 int x, y;
6233 struct glyph **glyph;
6234 int *hpos, *vpos, *prop_idx;
6235{
6236 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6237 struct window *w = XWINDOW (f->toolbar_window);
6238 int area;
6239
6240 /* Find the glyph under X/Y. */
6241 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6242 if (*glyph == NULL)
6243 return -1;
6244
6245 /* Get the start of this toolbar item's properties in
6246 f->current_toolbar_items. */
6247 if (!toolbar_item_info (f, *glyph, prop_idx))
6248 return -1;
6249
6250 /* Is mouse on the highlighted item? */
6251 if (EQ (f->toolbar_window, dpyinfo->mouse_face_window)
6252 && *vpos >= dpyinfo->mouse_face_beg_row
6253 && *vpos <= dpyinfo->mouse_face_end_row
6254 && (*vpos > dpyinfo->mouse_face_beg_row
6255 || *hpos >= dpyinfo->mouse_face_beg_col)
6256 && (*vpos < dpyinfo->mouse_face_end_row
6257 || *hpos < dpyinfo->mouse_face_end_col
6258 || dpyinfo->mouse_face_past_end))
6259 return 0;
6260
6261 return 1;
6262}
6263
6264
6265/* Handle mouse button event on the toolbar of frame F, at
6266 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6267 or ButtonRelase. */
6268
6269static void
6270x_handle_toolbar_click (f, button_event)
6271 struct frame *f;
6272 XButtonEvent *button_event;
6273{
6274 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6275 struct window *w = XWINDOW (f->toolbar_window);
6276 int hpos, vpos, prop_idx;
6277 struct glyph *glyph;
6278 Lisp_Object enabled_p;
6279 int x = button_event->x;
6280 int y = button_event->y;
6281
6282 /* If not on the highlighted toolbar item, return. */
6283 frame_to_window_pixel_xy (w, &x, &y);
6284 if (x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6285 return;
6286
6287 /* If item is disabled, do nothing. */
6288 enabled_p = (XVECTOR (f->current_toolbar_items)
6289 ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]);
6290 if (NILP (enabled_p))
6291 return;
6292
6293 if (button_event->type == ButtonPress)
6294 {
6295 /* Show item in pressed state. */
6296 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6297 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6298 last_toolbar_item = prop_idx;
6299 }
6300 else
6301 {
6302 Lisp_Object key, frame;
6303 struct input_event event;
6304
6305 /* Show item in released state. */
6306 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6307 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6308
6309 key = (XVECTOR (f->current_toolbar_items)
6310 ->contents[prop_idx + TOOLBAR_ITEM_KEY]);
6311
6312 XSETFRAME (frame, f);
6313 event.kind = TOOLBAR_EVENT;
6314 event.frame_or_window = Fcons (frame, Fcons (Qtoolbar, Qnil));
6315 kbd_buffer_store_event (&event);
6316
6317 event.kind = TOOLBAR_EVENT;
6318 event.frame_or_window = Fcons (frame, key);
6319 event.modifiers = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
6320 button_event->state);
6321 kbd_buffer_store_event (&event);
6322 last_toolbar_item = -1;
6323 }
6324}
6325
6326
6327/* Possibly highlight a toolbar item on frame F when mouse moves to
6328 toolbar window-relative coordinates X/Y. Called from
6329 note_mouse_highlight. */
6330
6331static void
6332note_toolbar_highlight (f, x, y)
6333 struct frame *f;
6334 int x, y;
6335{
6336 Lisp_Object window = f->toolbar_window;
6337 struct window *w = XWINDOW (window);
6338 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6339 int hpos, vpos;
6340 struct glyph *glyph;
6341 struct glyph_row *row;
6342 int i, j, area;
6343 Lisp_Object enabled_p;
6344 int prop_idx;
6345 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6346 int on_highlight_p, mouse_down_p, rc;
6347
6348 /* Function note_mouse_highlight is called with negative x(y
6349 values when mouse moves outside of the frame. */
6350 if (x <= 0 || y <= 0)
6351 {
6352 clear_mouse_face (dpyinfo);
6353 return;
6354 }
6355
6356 rc = x_toolbar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6357 if (rc < 0)
6358 {
6359 /* Not on toolbar item. */
6360 clear_mouse_face (dpyinfo);
6361 return;
6362 }
6363 else if (rc == 0)
6364 /* On same toolbar item as before. */
6365 goto set_help_echo;
b8009dd1 6366
06a2c219
GM
6367 clear_mouse_face (dpyinfo);
6368
6369 /* Mouse is down, but on different toolbar item? */
6370 mouse_down_p = (dpyinfo->grabbed
6371 && f == last_mouse_frame
6372 && FRAME_LIVE_P (f));
6373 if (mouse_down_p
6374 && last_toolbar_item != prop_idx)
6375 return;
6376
6377 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6378 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6379
6380 /* If toolbar item is not enabled, don't highlight it. */
6381 enabled_p = (XVECTOR (f->current_toolbar_items)
6382 ->contents[prop_idx + TOOLBAR_ITEM_ENABLED_P]);
6383 if (!NILP (enabled_p))
6384 {
6385 /* Compute the x-position of the glyph. In front and past the
6386 image is a space. We include this is the highlighted area. */
6387 row = MATRIX_ROW (w->current_matrix, vpos);
6388 for (i = x = 0; i < hpos; ++i)
6389 x += row->glyphs[TEXT_AREA][i].pixel_width;
6390
6391 /* Record this as the current active region. */
6392 dpyinfo->mouse_face_beg_col = hpos;
6393 dpyinfo->mouse_face_beg_row = vpos;
6394 dpyinfo->mouse_face_beg_x = x;
6395 dpyinfo->mouse_face_beg_y = row->y;
6396 dpyinfo->mouse_face_past_end = 0;
6397
6398 dpyinfo->mouse_face_end_col = hpos + 1;
6399 dpyinfo->mouse_face_end_row = vpos;
6400 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6401 dpyinfo->mouse_face_end_y = row->y;
6402 dpyinfo->mouse_face_window = window;
6403 dpyinfo->mouse_face_face_id = TOOLBAR_FACE_ID;
6404
6405 /* Display it as active. */
6406 show_mouse_face (dpyinfo, draw);
6407 dpyinfo->mouse_face_image_state = draw;
b8009dd1 6408 }
06a2c219
GM
6409
6410 set_help_echo:
6411
6412 /* Set help_echo to a help string.to display for this toolbar item.
6413 XTread_socket does the rest. */
6414 help_echo = (XVECTOR (f->current_toolbar_items)
6415 ->contents[prop_idx + TOOLBAR_ITEM_HELP]);
6416 if (!STRINGP (help_echo))
6417 help_echo = (XVECTOR (f->current_toolbar_items)
6418 ->contents[prop_idx + TOOLBAR_ITEM_CAPTION]);
b8009dd1 6419}
4d73d038 6420
06a2c219
GM
6421
6422\f
6423/* Find the glyph matrix position of buffer position POS in window W.
6424 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6425 current glyphs must be up to date. If POS is above window start
6426 return (0, 0, 0, 0). If POS is after end of W, return end of
6427 last line in W. */
b8009dd1
RS
6428
6429static int
06a2c219
GM
6430fast_find_position (w, pos, hpos, vpos, x, y)
6431 struct window *w;
b8009dd1 6432 int pos;
06a2c219 6433 int *hpos, *vpos, *x, *y;
b8009dd1 6434{
b8009dd1 6435 int i;
bf1c0ba1 6436 int lastcol;
06a2c219
GM
6437 int maybe_next_line_p = 0;
6438 int line_start_position;
6439 int yb = window_text_bottom_y (w);
6440 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6441 struct glyph_row *best_row = row;
6442 int row_vpos = 0, best_row_vpos = 0;
6443 int current_x;
6444
6445 while (row->y < yb)
b8009dd1 6446 {
06a2c219
GM
6447 if (row->used[TEXT_AREA])
6448 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6449 else
6450 line_start_position = 0;
6451
6452 if (line_start_position > pos)
b8009dd1 6453 break;
77b68646
RS
6454 /* If the position sought is the end of the buffer,
6455 don't include the blank lines at the bottom of the window. */
06a2c219
GM
6456 else if (line_start_position == pos
6457 && pos == BUF_ZV (XBUFFER (w->buffer)))
77b68646 6458 {
06a2c219 6459 maybe_next_line_p = 1;
77b68646
RS
6460 break;
6461 }
06a2c219
GM
6462 else if (line_start_position > 0)
6463 {
6464 best_row = row;
6465 best_row_vpos = row_vpos;
6466 }
6467
6468 ++row;
6469 ++row_vpos;
b8009dd1 6470 }
06a2c219
GM
6471
6472 /* Find the right column within BEST_ROW. */
6473 lastcol = 0;
6474 current_x = best_row->x;
6475 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
bf1c0ba1 6476 {
06a2c219
GM
6477 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6478 int charpos;
6479
6480 charpos = glyph->charpos;
6481 if (charpos == pos)
bf1c0ba1 6482 {
06a2c219
GM
6483 *hpos = i;
6484 *vpos = best_row_vpos;
6485 *x = current_x;
6486 *y = best_row->y;
bf1c0ba1
RS
6487 return 1;
6488 }
06a2c219 6489 else if (charpos > pos)
4d73d038 6490 break;
06a2c219
GM
6491 else if (charpos > 0)
6492 lastcol = i;
6493
6494 current_x += glyph->pixel_width;
bf1c0ba1 6495 }
b8009dd1 6496
77b68646
RS
6497 /* If we're looking for the end of the buffer,
6498 and we didn't find it in the line we scanned,
6499 use the start of the following line. */
06a2c219 6500 if (maybe_next_line_p)
77b68646 6501 {
06a2c219
GM
6502 ++best_row;
6503 ++best_row_vpos;
6504 lastcol = 0;
6505 current_x = best_row->x;
77b68646
RS
6506 }
6507
06a2c219
GM
6508 *vpos = best_row_vpos;
6509 *hpos = lastcol + 1;
6510 *x = current_x;
6511 *y = best_row->y;
b8009dd1
RS
6512 return 0;
6513}
6514
06a2c219 6515
b8009dd1
RS
6516/* Display the active region described by mouse_face_*
6517 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6518
6519static void
06a2c219 6520show_mouse_face (dpyinfo, draw)
7a13e894 6521 struct x_display_info *dpyinfo;
06a2c219 6522 enum draw_glyphs_face draw;
b8009dd1 6523{
7a13e894 6524 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
06a2c219 6525 struct frame *f = XFRAME (WINDOW_FRAME (w));
b8009dd1 6526 int i;
06a2c219
GM
6527 int cursor_off_p = 0;
6528 struct cursor_pos saved_cursor;
6529
6530 saved_cursor = output_cursor;
6531
6532 /* If window is in the process of being destroyed, don't bother
6533 to do anything. */
6534 if (w->current_matrix == NULL)
6535 goto set_x_cursor;
6536
6537 /* Recognize when we are called to operate on rows that don't exist
6538 anymore. This can happen when a window is split. */
6539 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6540 goto set_x_cursor;
6541
6542 set_output_cursor (&w->phys_cursor);
6543
6544 /* Note that mouse_face_beg_row etc. are window relative. */
6545 for (i = dpyinfo->mouse_face_beg_row;
6546 i <= dpyinfo->mouse_face_end_row;
6547 i++)
6548 {
6549 int start_hpos, end_hpos, start_x;
6550 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6551
6552 /* Don't do anything if row doesn't have valid contents. */
6553 if (!row->enabled_p)
6554 continue;
6555
6556 /* For all but the first row, the highlight starts at column 0. */
6557 if (i == dpyinfo->mouse_face_beg_row)
6558 {
6559 start_hpos = dpyinfo->mouse_face_beg_col;
6560 start_x = dpyinfo->mouse_face_beg_x;
6561 }
6562 else
6563 {
6564 start_hpos = 0;
6565 start_x = 0;
6566 }
6567
6568 if (i == dpyinfo->mouse_face_end_row)
6569 end_hpos = dpyinfo->mouse_face_end_col;
6570 else
6571 end_hpos = row->used[TEXT_AREA];
6572
6573 /* If the cursor's in the text we are about to rewrite, turn the
6574 cursor off. */
6575 if (!w->pseudo_window_p
6576 && i == output_cursor.vpos
6577 && output_cursor.hpos >= start_hpos - 1
6578 && output_cursor.hpos <= end_hpos)
514e4681 6579 {
06a2c219
GM
6580 x_update_window_cursor (w, 0);
6581 cursor_off_p = 1;
514e4681 6582 }
b8009dd1 6583
06a2c219
GM
6584 if (end_hpos > start_hpos)
6585 x_draw_glyphs (w, start_x, row, updated_area,
6586 start_hpos, end_hpos, draw, NULL, NULL);
b8009dd1
RS
6587 }
6588
514e4681 6589 /* If we turned the cursor off, turn it back on. */
06a2c219
GM
6590 if (cursor_off_p)
6591 x_display_cursor (w, 1,
6592 output_cursor.hpos, output_cursor.vpos,
6593 output_cursor.x, output_cursor.y);
2729a2b5 6594
06a2c219 6595 output_cursor = saved_cursor;
fb3b7de5 6596
06a2c219
GM
6597 set_x_cursor:
6598
6599 /* Change the mouse cursor. */
6600 if (draw == DRAW_NORMAL_TEXT)
6601 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6602 f->output_data.x->text_cursor);
6603 else if (draw == DRAW_MOUSE_FACE)
334208b7 6604 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7556890b 6605 f->output_data.x->cross_cursor);
27ead1d5 6606 else
334208b7 6607 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
06a2c219 6608 f->output_data.x->nontext_cursor);
b8009dd1
RS
6609}
6610
6611/* Clear out the mouse-highlighted active region.
06a2c219 6612 Redraw it un-highlighted first. */
b8009dd1 6613
06a2c219 6614void
7a13e894
RS
6615clear_mouse_face (dpyinfo)
6616 struct x_display_info *dpyinfo;
b8009dd1 6617{
06a2c219
GM
6618 if (tip_frame)
6619 return;
6620
7a13e894 6621 if (! NILP (dpyinfo->mouse_face_window))
06a2c219 6622 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
b8009dd1 6623
7a13e894
RS
6624 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6625 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6626 dpyinfo->mouse_face_window = Qnil;
b8009dd1 6627}
e687d06e
RS
6628
6629/* Just discard the mouse face information for frame F, if any.
6630 This is used when the size of F is changed. */
6631
dfcf069d 6632void
e687d06e
RS
6633cancel_mouse_face (f)
6634 FRAME_PTR f;
6635{
6636 Lisp_Object window;
6637 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6638
6639 window = dpyinfo->mouse_face_window;
6640 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6641 {
6642 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6643 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6644 dpyinfo->mouse_face_window = Qnil;
6645 }
6646}
b8009dd1 6647\f
ab648270
JB
6648static struct scroll_bar *x_window_to_scroll_bar ();
6649static void x_scroll_bar_report_motion ();
12ba150f 6650
90e65f07 6651/* Return the current position of the mouse.
2d7fc7e8 6652 *fp should be a frame which indicates which display to ask about.
90e65f07 6653
2d7fc7e8 6654 If the mouse movement started in a scroll bar, set *fp, *bar_window,
ab648270 6655 and *part to the frame, window, and scroll bar part that the mouse
12ba150f 6656 is over. Set *x and *y to the portion and whole of the mouse's
ab648270 6657 position on the scroll bar.
12ba150f 6658
2d7fc7e8 6659 If the mouse movement started elsewhere, set *fp to the frame the
12ba150f
JB
6660 mouse is on, *bar_window to nil, and *x and *y to the character cell
6661 the mouse is over.
6662
06a2c219 6663 Set *time to the server time-stamp for the time at which the mouse
12ba150f
JB
6664 was at this position.
6665
a135645a
RS
6666 Don't store anything if we don't have a valid set of values to report.
6667
90e65f07 6668 This clears the mouse_moved flag, so we can wait for the next mouse
f5bb65ec 6669 movement. */
90e65f07
JB
6670
6671static void
1cf412ec 6672XTmouse_position (fp, insist, bar_window, part, x, y, time)
334208b7 6673 FRAME_PTR *fp;
1cf412ec 6674 int insist;
12ba150f 6675 Lisp_Object *bar_window;
ab648270 6676 enum scroll_bar_part *part;
90e65f07 6677 Lisp_Object *x, *y;
e5d77022 6678 unsigned long *time;
90e65f07 6679{
a135645a
RS
6680 FRAME_PTR f1;
6681
90e65f07
JB
6682 BLOCK_INPUT;
6683
8bcee03e 6684 if (! NILP (last_mouse_scroll_bar) && insist == 0)
334208b7 6685 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
90e65f07
JB
6686 else
6687 {
12ba150f
JB
6688 Window root;
6689 int root_x, root_y;
90e65f07 6690
12ba150f
JB
6691 Window dummy_window;
6692 int dummy;
6693
39d8bb4d
KH
6694 Lisp_Object frame, tail;
6695
6696 /* Clear the mouse-moved flag for every frame on this display. */
6697 FOR_EACH_FRAME (tail, frame)
6698 if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
6699 XFRAME (frame)->mouse_moved = 0;
6700
ab648270 6701 last_mouse_scroll_bar = Qnil;
12ba150f
JB
6702
6703 /* Figure out which root window we're on. */
334208b7
RS
6704 XQueryPointer (FRAME_X_DISPLAY (*fp),
6705 DefaultRootWindow (FRAME_X_DISPLAY (*fp)),
12ba150f
JB
6706
6707 /* The root window which contains the pointer. */
6708 &root,
6709
6710 /* Trash which we can't trust if the pointer is on
6711 a different screen. */
6712 &dummy_window,
6713
6714 /* The position on that root window. */
58769bee 6715 &root_x, &root_y,
12ba150f
JB
6716
6717 /* More trash we can't trust. */
6718 &dummy, &dummy,
6719
6720 /* Modifier keys and pointer buttons, about which
6721 we don't care. */
6722 (unsigned int *) &dummy);
6723
6724 /* Now we have a position on the root; find the innermost window
6725 containing the pointer. */
6726 {
6727 Window win, child;
6728 int win_x, win_y;
06a2c219 6729 int parent_x = 0, parent_y = 0;
e99db5a1 6730 int count;
12ba150f
JB
6731
6732 win = root;
69388238 6733
2d7fc7e8
RS
6734 /* XTranslateCoordinates can get errors if the window
6735 structure is changing at the same time this function
6736 is running. So at least we must not crash from them. */
6737
e99db5a1 6738 count = x_catch_errors (FRAME_X_DISPLAY (*fp));
2d7fc7e8 6739
334208b7 6740 if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
23faf38f 6741 && FRAME_LIVE_P (last_mouse_frame))
12ba150f 6742 {
69388238
RS
6743 /* If mouse was grabbed on a frame, give coords for that frame
6744 even if the mouse is now outside it. */
334208b7 6745 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
69388238 6746
12ba150f 6747 /* From-window, to-window. */
69388238 6748 root, FRAME_X_WINDOW (last_mouse_frame),
12ba150f
JB
6749
6750 /* From-position, to-position. */
6751 root_x, root_y, &win_x, &win_y,
6752
6753 /* Child of win. */
6754 &child);
69388238
RS
6755 f1 = last_mouse_frame;
6756 }
6757 else
6758 {
6759 while (1)
6760 {
334208b7 6761 XTranslateCoordinates (FRAME_X_DISPLAY (*fp),
12ba150f 6762
69388238
RS
6763 /* From-window, to-window. */
6764 root, win,
12ba150f 6765
69388238
RS
6766 /* From-position, to-position. */
6767 root_x, root_y, &win_x, &win_y,
6768
6769 /* Child of win. */
6770 &child);
6771
9af3143a 6772 if (child == None || child == win)
69388238
RS
6773 break;
6774
6775 win = child;
6776 parent_x = win_x;
6777 parent_y = win_y;
6778 }
12ba150f 6779
69388238
RS
6780 /* Now we know that:
6781 win is the innermost window containing the pointer
6782 (XTC says it has no child containing the pointer),
6783 win_x and win_y are the pointer's position in it
6784 (XTC did this the last time through), and
6785 parent_x and parent_y are the pointer's position in win's parent.
6786 (They are what win_x and win_y were when win was child.
6787 If win is the root window, it has no parent, and
6788 parent_{x,y} are invalid, but that's okay, because we'll
6789 never use them in that case.) */
6790
6791 /* Is win one of our frames? */
19126e11 6792 f1 = x_any_window_to_frame (FRAME_X_DISPLAY_INFO (*fp), win);
69388238 6793 }
58769bee 6794
2d7fc7e8
RS
6795 if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
6796 f1 = 0;
6797
e99db5a1 6798 x_uncatch_errors (FRAME_X_DISPLAY (*fp), count);
2d7fc7e8 6799
ab648270 6800 /* If not, is it one of our scroll bars? */
a135645a 6801 if (! f1)
12ba150f 6802 {
ab648270 6803 struct scroll_bar *bar = x_window_to_scroll_bar (win);
12ba150f
JB
6804
6805 if (bar)
6806 {
a135645a 6807 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f
JB
6808 win_x = parent_x;
6809 win_y = parent_y;
6810 }
6811 }
90e65f07 6812
8bcee03e 6813 if (f1 == 0 && insist > 0)
1cf412ec
RS
6814 f1 = selected_frame;
6815
a135645a 6816 if (f1)
12ba150f 6817 {
06a2c219
GM
6818 /* Ok, we found a frame. Store all the values.
6819 last_mouse_glyph is a rectangle used to reduce the
6820 generation of mouse events. To not miss any motion
6821 events, we must divide the frame into rectangles of the
6822 size of the smallest character that could be displayed
6823 on it, i.e. into the same rectangles that matrices on
6824 the frame are divided into. */
6825
6826#if OLD_REDISPLAY_CODE
2b5c9e71 6827 int ignore1, ignore2;
2b5c9e71 6828 pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
334208b7 6829 &last_mouse_glyph,
1cf412ec
RS
6830 FRAME_X_DISPLAY_INFO (f1)->grabbed
6831 || insist);
06a2c219
GM
6832#else
6833 {
6834 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6835 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6836 int x = win_x;
6837 int y = win_y;
6838
6839 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6840 round down even for negative values. */
6841 if (x < 0)
6842 x -= width - 1;
6843 if (y < 0)
6844 y -= height - 1;
6845
6846 last_mouse_glyph.width = width;
6847 last_mouse_glyph.height = height;
6848 last_mouse_glyph.x = (x + width - 1) / width * width;
6849 last_mouse_glyph.y = (y + height - 1) / height * height;
6850 }
6851#endif
12ba150f
JB
6852
6853 *bar_window = Qnil;
6854 *part = 0;
334208b7 6855 *fp = f1;
e0c1aef2
KH
6856 XSETINT (*x, win_x);
6857 XSETINT (*y, win_y);
12ba150f
JB
6858 *time = last_mouse_movement_time;
6859 }
6860 }
6861 }
90e65f07
JB
6862
6863 UNBLOCK_INPUT;
6864}
f451eb13 6865
06a2c219
GM
6866
6867DEFUN ("xt-process-timeouts", Fxt_process_timeouts, Sxt_process_timeouts,
6868 0, 0, 0,
6869 "Arrange for Xt timeout callbacks to be called.")
6870 ()
6871{
6872#ifdef USE_X_TOOLKIT
6873 BLOCK_INPUT;
6874 while (XtAppPending (Xt_app_con) & XtIMTimer)
6875 XtAppProcessEvent (Xt_app_con, XtIMTimer);
6876 UNBLOCK_INPUT;
6877#endif /* USE_X_TOOLKIT */
6878
6879 return Qnil;
6880}
6881
6882
6883\f
6884/* Scroll bar support. */
6885
6886/* Given an X window ID, find the struct scroll_bar which manages it.
6887 This can be called in GC, so we have to make sure to strip off mark
6888 bits. */
6889static struct scroll_bar *
6890x_window_to_scroll_bar (window_id)
6891 Window window_id;
6892{
6893 Lisp_Object tail;
6894
6895 for (tail = Vframe_list;
6896 XGCTYPE (tail) == Lisp_Cons;
6897 tail = XCONS (tail)->cdr)
6898 {
6899 Lisp_Object frame, bar, condemned;
6900
6901 frame = XCONS (tail)->car;
6902 /* All elements of Vframe_list should be frames. */
6903 if (! GC_FRAMEP (frame))
6904 abort ();
6905
6906 /* Scan this frame's scroll bar list for a scroll bar with the
6907 right window ID. */
6908 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
6909 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
6910 /* This trick allows us to search both the ordinary and
6911 condemned scroll bar lists with one loop. */
6912 ! GC_NILP (bar) || (bar = condemned,
6913 condemned = Qnil,
6914 ! GC_NILP (bar));
6915 bar = XSCROLL_BAR (bar)->next)
6916 if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
6917 return XSCROLL_BAR (bar);
6918 }
6919
6920 return 0;
6921}
6922
6923
6924\f
6925/************************************************************************
6926 Toolkit scroll bars
6927 ************************************************************************/
6928
6929#if USE_TOOLKIT_SCROLL_BARS
6930
6931static void x_scroll_bar_to_input_event P_ ((XEvent *, struct input_event *));
6932static void x_send_scroll_bar_event P_ ((Lisp_Object, int, int, int));
6933static void x_create_toolkit_scroll_bar P_ ((struct frame *,
6934 struct scroll_bar *));
6935static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
6936 int, int, int));
6937
6938
6939/* Id of action hook installed for scroll bars. */
6940
6941static XtActionHookId action_hook_id;
6942
6943/* Lisp window being scrolled. Set when starting to interact with
6944 a toolkit scroll bar, reset to nil when ending the interaction. */
6945
6946static Lisp_Object window_being_scrolled;
6947
6948/* Last scroll bar part sent in xm_scroll_callback. */
6949
6950static int last_scroll_bar_part;
6951
6952
6953/* Action hook installed via XtAppAddActionHook when toolkit scroll
6954 bars are used.. The hoos is responsible for detecting when
6955 the user ends an interaction with the scroll bar, and generates
6956 a `end-scroll' scroll_bar_click' event if so. */
6957
6958static void
6959xt_action_hook (widget, client_data, action_name, event, params,
6960 num_params)
6961 Widget widget;
6962 XtPointer client_data;
6963 String action_name;
6964 XEvent *event;
6965 String *params;
6966 Cardinal *num_params;
6967{
6968 int scroll_bar_p;
6969 char *end_action;
6970
6971#ifdef USE_MOTIF
6972 scroll_bar_p = XmIsScrollBar (widget);
6973 end_action = "Release";
6974#elif defined HAVE_XAW3D
6975 scroll_bar_p = XtIsSubclass (widget, scrollbarWidgetClass);
6976 end_action = "EndScroll";
6977#else
6978#error unknown scroll bar toolkit
6979#endif /* HAVE_XAW3D */
6980
6981 /* Although LessTif uses XtTimeouts like Xaw3d, the timer hack to
6982 let Xt timeouts be processed doesn't work. */
6983 if (scroll_bar_p
6984 && strcmp (action_name, end_action) == 0
6985 && WINDOWP (window_being_scrolled))
6986 {
6987 struct window *w;
6988
6989 x_send_scroll_bar_event (window_being_scrolled,
6990 scroll_bar_end_scroll, 0, 0);
6991 w = XWINDOW (window_being_scrolled);
6992 XSCROLL_BAR (w->vertical_scroll_bar)->dragging = Qnil;
6993 window_being_scrolled = Qnil;
6994 last_scroll_bar_part = -1;
6995 }
6996}
6997
6998
6999/* Send a client message with message type Xatom_Scrollbar for a
7000 scroll action to the frame of WINDOW. PART is a value identifying
7001 the part of the scroll bar that was clicked on. PORTION is the
7002 amount to scroll of a whole of WHOLE. */
7003
7004static void
7005x_send_scroll_bar_event (window, part, portion, whole)
7006 Lisp_Object window;
7007 int part, portion, whole;
7008{
7009 XEvent event;
7010 XClientMessageEvent *ev = (XClientMessageEvent *) &event;
7011 struct frame *f = XFRAME (XWINDOW (window)->frame);
7012
7013 /* Construct a ClientMessage event to send to the frame. */
7014 ev->type = ClientMessage;
7015 ev->message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_Scrollbar;
7016 ev->display = FRAME_X_DISPLAY (f);
7017 ev->window = FRAME_X_WINDOW (f);
7018 ev->format = 32;
7019 ev->data.l[0] = (long) window;
7020 ev->data.l[1] = (long) part;
7021 ev->data.l[2] = (long) 0;
7022 ev->data.l[3] = (long) portion;
7023 ev->data.l[4] = (long) whole;
7024
7025 /* Setting the event mask to zero means that the message will
7026 be sent to the client that created the window, and if that
7027 window no longer exists, no event will be sent. */
7028 BLOCK_INPUT;
7029 XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), False, 0, &event);
7030 UNBLOCK_INPUT;
7031}
7032
7033
7034/* Transform a scroll bar ClientMessage EVENT to an Emacs input event
7035 in *IEVENT. */
7036
7037static void
7038x_scroll_bar_to_input_event (event, ievent)
7039 XEvent *event;
7040 struct input_event *ievent;
7041{
7042 XClientMessageEvent *ev = (XClientMessageEvent *) event;
7043 Lisp_Object window = (Lisp_Object) ev->data.l[0];
7044 struct frame *f = XFRAME (XWINDOW (window)->frame);
7045
7046 ievent->kind = scroll_bar_click;
7047 ievent->frame_or_window = window;
7048 ievent->timestamp = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
7049 ievent->part = ev->data.l[1];
7050 ievent->code = ev->data.l[2];
7051 ievent->x = make_number ((int) ev->data.l[3]);
7052 ievent->y = make_number ((int) ev->data.l[4]);
7053 ievent->modifiers = 0;
7054}
7055
7056
7057#ifdef USE_MOTIF
7058
7059/* Minimum and maximum values used for Motif scroll bars. */
7060
7061#define XM_SB_MIN 1
7062#define XM_SB_MAX 10000000
7063#define XM_SB_RANGE (XM_SB_MAX - XM_SB_MIN)
7064
7065
7066/* Scroll bar callback for Motif scroll bars. WIDGET is the scroll
7067 bar widget. CLIENT_DATA is a pointer to the scroll_bar structure.
7068 CALL_DATA is a pointer a a XmScrollBarCallbackStruct. */
7069
7070static void
7071xm_scroll_callback (widget, client_data, call_data)
7072 Widget widget;
7073 XtPointer client_data, call_data;
7074{
7075 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7076 XmScrollBarCallbackStruct *cs = (XmScrollBarCallbackStruct *) call_data;
7077 double percent;
7078 int part = -1, whole = 0, portion = 0;
7079
7080 switch (cs->reason)
7081 {
7082 case XmCR_DECREMENT:
7083 bar->dragging = Qnil;
7084 part = scroll_bar_up_arrow;
7085 break;
7086
7087 case XmCR_INCREMENT:
7088 bar->dragging = Qnil;
7089 part = scroll_bar_down_arrow;
7090 break;
7091
7092 case XmCR_PAGE_DECREMENT:
7093 bar->dragging = Qnil;
7094 part = scroll_bar_above_handle;
7095 break;
7096
7097 case XmCR_PAGE_INCREMENT:
7098 bar->dragging = Qnil;
7099 part = scroll_bar_below_handle;
7100 break;
7101
7102 case XmCR_TO_TOP:
7103 bar->dragging = Qnil;
7104 part = scroll_bar_to_top;
7105 break;
7106
7107 case XmCR_TO_BOTTOM:
7108 bar->dragging = Qnil;
7109 part = scroll_bar_to_bottom;
7110 break;
7111
7112 case XmCR_DRAG:
7113 {
7114 int slider_size;
7115 int dragging_down_p = (INTEGERP (bar->dragging)
7116 && XINT (bar->dragging) <= cs->value);
7117
7118 /* Get the slider size. */
7119 BLOCK_INPUT;
7120 XtVaGetValues (widget, XmNsliderSize, &slider_size, NULL);
7121 UNBLOCK_INPUT;
7122
7123 /* At the max position of the scroll bar, do a line-wise
7124 movement. Without doing anything, the LessTif scroll bar
7125 calls us with the same cs->value again and again. If we
7126 want to make sure that we can reach the end of the buffer,
7127 we have to do something.
7128
7129 Implementation note: setting bar->dragging always to
7130 cs->value gives a smoother movement at the max position.
7131 Setting it to nil when doing line-wise movement gives
7132 a better slider behavior. */
7133
7134 if (cs->value + slider_size == XM_SB_MAX
7135 || (dragging_down_p
7136 && last_scroll_bar_part == scroll_bar_down_arrow))
7137 {
7138 part = scroll_bar_down_arrow;
7139 bar->dragging = Qnil;
7140 }
7141 else
7142 {
7143 whole = XM_SB_RANGE;
7144 portion = min (cs->value - XM_SB_MIN, XM_SB_MAX - slider_size);
7145 part = scroll_bar_handle;
7146 bar->dragging = make_number (cs->value);
7147 }
7148 }
7149 break;
7150
7151 case XmCR_VALUE_CHANGED:
7152 break;
7153 };
7154
7155 if (part >= 0)
7156 {
7157 window_being_scrolled = bar->window;
7158 last_scroll_bar_part = part;
7159 x_send_scroll_bar_event (bar->window, part, portion, whole);
7160 }
7161}
7162
7163
7164#else /* not USE_MOTIF, i.e. XAW3D. */
7165
7166
7167/* Xaw3d scroll bar callback. Invoked when the thumb is dragged.
7168 WIDGET is the scroll bar widget. CLIENT_DATA is a pointer to the
7169 scroll bar struct. CALL_DATA is a pointer to a float saying where
7170 the thumb is. */
7171
7172static void
7173xaw3d_jump_callback (widget, client_data, call_data)
7174 Widget widget;
7175 XtPointer client_data, call_data;
7176{
7177 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7178 float top = *(float *) call_data;
7179 float shown;
7180 int whole, portion;
7181 int dragging_down_p, part;
7182 double epsilon = 0.01;
7183
7184 /* Get the size of the thumb, a value between 0 and 1. */
7185 BLOCK_INPUT;
7186 XtVaGetValues (widget, XtNshown, &shown, NULL);
7187 UNBLOCK_INPUT;
7188
7189 whole = 10000000;
7190 portion = shown < 1 ? top * whole : 0;
7191 dragging_down_p = (INTEGERP (bar->dragging)
7192 && XINT (bar->dragging) < portion);
7193
7194 if (shown < 1
7195 && (abs (top + shown - 1) < epsilon
7196 || (dragging_down_p
7197 && last_scroll_bar_part == scroll_bar_down_arrow)))
7198 part = scroll_bar_down_arrow;
7199 else
7200 part = scroll_bar_handle;
7201
7202 window_being_scrolled = bar->window;
7203 bar->dragging = make_number (portion);
7204 last_scroll_bar_part = part;
7205 x_send_scroll_bar_event (bar->window, part, portion, whole);
7206}
7207
7208
7209/* Xaw3d scroll bar callback. Invoked for incremental scrolling.,
7210 i.e. line or page up or down. WIDGET is the Xaw3d scroll bar
7211 widget. CLIENT_DATA is a pointer to the scroll_bar structure for
7212 the scroll bar. CALL_DATA is an integer specifying the action that
7213 has taken place. It's magnitude is in the range 0..height of the
7214 scroll bar. Negative values mean scroll towards buffer start.
7215 Values < height of scroll bar mean line-wise movement. */
7216
7217static void
7218xaw3d_scroll_callback (widget, client_data, call_data)
7219 Widget widget;
7220 XtPointer client_data, call_data;
7221{
7222 struct scroll_bar *bar = (struct scroll_bar *) client_data;
7223 int position = (int) call_data;
7224 Dimension height;
7225 int part;
7226
7227 /* Get the height of the scroll bar. */
7228 BLOCK_INPUT;
7229 XtVaGetValues (widget, XtNheight, &height, NULL);
7230 UNBLOCK_INPUT;
7231
7232 if (position < 0)
7233 {
7234 if (abs (position) < height)
7235 part = scroll_bar_up_arrow;
7236 else
7237 part = scroll_bar_above_handle;
7238 }
7239 else
7240 {
7241 if (abs (position) < height)
7242 part = scroll_bar_down_arrow;
7243 else
7244 part = scroll_bar_below_handle;
7245 }
7246
7247 window_being_scrolled = bar->window;
7248 bar->dragging = Qnil;
7249 last_scroll_bar_part = part;
7250 x_send_scroll_bar_event (bar->window, part, 0, 0);
7251}
7252
7253
7254#endif /* not USE_MOTIF */
7255
7256
7257/* Create the widget for scroll bar BAR on frame F. Record the widget
7258 and X window of the scroll bar in BAR. */
7259
7260static void
7261x_create_toolkit_scroll_bar (f, bar)
7262 struct frame *f;
7263 struct scroll_bar *bar;
7264{
7265 Window xwindow;
7266 Widget widget;
7267 Arg av[20];
7268 int ac = 0;
7269 char *scroll_bar_name = "verticalScrollBar";
7270 unsigned long pixel;
7271
7272 BLOCK_INPUT;
7273
7274#ifdef USE_MOTIF
7275 /* LessTif 0.85, problems:
7276
7277 1. When the mouse if over the scroll bar, the scroll bar will
7278 get keyboard events. I didn't find a way to turn this off.
7279
7280 2. Do we have to explicitly set the cursor to get an arrow
7281 cursor (see below)? */
7282
7283 /* Set resources. Create the widget. */
7284 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7285 XtSetArg (av[ac], XmNminimum, XM_SB_MIN); ++ac;
7286 XtSetArg (av[ac], XmNmaximum, XM_SB_MAX); ++ac;
7287 XtSetArg (av[ac], XmNorientation, XmVERTICAL); ++ac;
7288 XtSetArg (av[ac], XmNprocessingDirection, XmMAX_ON_BOTTOM), ++ac;
7289 XtSetArg (av[ac], XmNincrement, 1); ++ac;
7290 XtSetArg (av[ac], XmNpageIncrement, 1); ++ac;
7291
7292 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7293 if (pixel != -1)
7294 {
7295 XtSetArg (av[ac], XmNforeground, pixel);
7296 ++ac;
7297 }
7298
7299 pixel = f->output_data.x->scroll_bar_background_pixel;
7300 if (pixel != -1)
7301 {
7302 XtSetArg (av[ac], XmNbackground, pixel);
7303 ++ac;
7304 }
7305
7306 widget = XmCreateScrollBar (f->output_data.x->edit_widget,
7307 scroll_bar_name, av, ac);
7308
7309 /* Add one callback for everything that can happen. */
7310 XtAddCallback (widget, XmNdecrementCallback, xm_scroll_callback,
7311 (XtPointer) bar);
7312 XtAddCallback (widget, XmNdragCallback, xm_scroll_callback,
7313 (XtPointer) bar);
7314 XtAddCallback (widget, XmNincrementCallback, xm_scroll_callback,
7315 (XtPointer) bar);
7316 XtAddCallback (widget, XmNpageDecrementCallback, xm_scroll_callback,
7317 (XtPointer) bar);
7318 XtAddCallback (widget, XmNpageIncrementCallback, xm_scroll_callback,
7319 (XtPointer) bar);
7320 XtAddCallback (widget, XmNtoBottomCallback, xm_scroll_callback,
7321 (XtPointer) bar);
7322 XtAddCallback (widget, XmNtoTopCallback, xm_scroll_callback,
7323 (XtPointer) bar);
7324
7325 /* Realize the widget. Only after that is the X window created. */
7326 XtRealizeWidget (widget);
7327
7328 /* Set the cursor to an arrow. I didn't find a resource to do that.
7329 And I'm wondering why it hasn't an arrow cursor by default. */
7330 XDefineCursor (XtDisplay (widget), XtWindow (widget),
7331 f->output_data.x->nontext_cursor);
7332
7333#elif defined HAVE_XAW3D
7334
7335 /* Set resources. Create the widget. The background of the
7336 Xaw3d scroll bar widget is a little bit light for my taste.
7337 We don't alter it here to let users change it according
7338 to their taste with `emacs*verticalScrollBar.background: xxx'. */
7339 XtSetArg (av[ac], XtNmappedWhenManaged, False); ++ac;
7340 XtSetArg (av[ac], XtNorientation, XtorientVertical); ++ac;
7341 XtSetArg (av[ac], XtNcursorName, "left_ptr"); ++ac;
7342 XtSetArg (av[ac], XtNbeNiceToColormap, True); ++ac;
7343
7344 pixel = f->output_data.x->scroll_bar_foreground_pixel;
7345 if (pixel != -1)
7346 {
7347 XtSetArg (av[ac], XtNforeground, pixel);
7348 ++ac;
7349 }
7350
7351 pixel = f->output_data.x->scroll_bar_background_pixel;
7352 if (pixel != -1)
7353 {
7354 XtSetArg (av[ac], XtNbackground, pixel);
7355 ++ac;
7356 }
7357
7358 widget = XtCreateWidget (scroll_bar_name, scrollbarWidgetClass,
7359 f->output_data.x->edit_widget, av, ac);
7360
7361 /* Define callbacks. */
7362 XtAddCallback (widget, XtNjumpProc, xaw3d_jump_callback, (XtPointer) bar);
7363 XtAddCallback (widget, XtNscrollProc, xaw3d_scroll_callback,
7364 (XtPointer) bar);
7365
7366 /* Realize the widget. Only after that is the X window created. */
7367 XtRealizeWidget (widget);
7368
7369#endif /* HAVE_XAW3D */
7370
7371 /* Install an action hook that let's us detect when the user
7372 finishes interacting with a scroll bar. */
7373 if (action_hook_id == 0)
7374 action_hook_id = XtAppAddActionHook (Xt_app_con, xt_action_hook, 0);
7375
7376 /* Remember X window and widget in the scroll bar vector. */
7377 SET_SCROLL_BAR_X_WIDGET (bar, widget);
7378 xwindow = XtWindow (widget);
7379 SET_SCROLL_BAR_X_WINDOW (bar, xwindow);
7380
7381 UNBLOCK_INPUT;
7382}
7383
7384
7385/* Set the thumb size and position of scroll bar BAR. We are currently
7386 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7387
7388static void
7389x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole)
7390 struct scroll_bar *bar;
7391 int portion, position, whole;
f451eb13 7392{
06a2c219
GM
7393 float top, shown;
7394 Arg av[2];
7395 Widget widget = SCROLL_BAR_X_WIDGET (bar);
f451eb13 7396
06a2c219
GM
7397 if (whole == 0)
7398 top = 0, shown = 1;
7399 else
f451eb13 7400 {
06a2c219
GM
7401 top = (float) position / whole;
7402 shown = (float) portion / whole;
7403 }
f451eb13 7404
06a2c219 7405 BLOCK_INPUT;
f451eb13 7406
06a2c219
GM
7407#ifdef USE_MOTIF
7408 {
7409 int size, value;
7410 Boolean arrow1_selected, arrow2_selected;
7411 unsigned char flags;
7412 XmScrollBarWidget sb;
7413
7414 /* Slider size. Must be in the range [1 .. MAX - MIN] where NAX
7415 is the scroll bar's maximum and MIN is the scroll bar's minimum
7416 value. */
7417 size = shown * XM_SB_RANGE;
7418 size = min (size, XM_SB_RANGE);
7419 size = max (size, 1);
7420
7421 /* Position. Must be in the range [MIN .. MAX - SLIDER_SIZE]. */
7422 value = top * XM_SB_RANGE;
7423 value = min (value, XM_SB_MAX - size);
7424 value = max (value, XM_SB_MIN);
7425
7426 /* LessTif: Calling XmScrollBarSetValues after an increment or
7427 decrement turns off auto-repeat LessTif-internally. This can
7428 be seen in ScrollBar.c which resets Arrow1Selected and
7429 Arrow2Selected. It also sets internal flags so that LessTif
7430 believes the mouse is in the slider. We either have to change
7431 our code, or work around that by accessing private data. */
7432
7433 sb = (XmScrollBarWidget) widget;
7434 arrow1_selected = sb->scrollBar.arrow1_selected;
7435 arrow2_selected = sb->scrollBar.arrow2_selected;
7436 flags = sb->scrollBar.flags;
7437
7438 if (NILP (bar->dragging))
7439 XmScrollBarSetValues (widget, value, size, 0, 0, False);
7440 else if (last_scroll_bar_part == scroll_bar_down_arrow)
7441 /* This has the negative side effect that the slider value is
7442 not would it would be if we scrolled here using line-wise or
7443 page-wise movement. */
7444 XmScrollBarSetValues (widget, value, XM_SB_RANGE - value, 0, 0, False);
7445 else
7446 {
7447 /* If currently dragging, only update the slider size.
7448 This reduces flicker effects. */
7449 int old_value, old_size, increment, page_increment;
7450
7451 XmScrollBarGetValues (widget, &old_value, &old_size,
7452 &increment, &page_increment);
7453 XmScrollBarSetValues (widget, old_value,
7454 min (size, XM_SB_RANGE - old_value),
7455 0, 0, False);
7456 }
7457
7458 sb->scrollBar.arrow1_selected = arrow1_selected;
7459 sb->scrollBar.arrow2_selected = arrow2_selected;
7460 sb->scrollBar.flags = flags;
7461 }
7462#elif defined HAVE_XAW3D
7463 {
7464 /* Restrict to [0 1]. */
7465 top = max (0, min (1, top));
7466 shown = max (0, min (1, shown));
7467
7468 /* If the call to XawScrollbarSetThumb below doesn't seem to work,
7469 check that your system's configuration file contains a define
7470 for `NARROWPROTO'. See s/freebsd.h for an example. */
7471 if (NILP (bar->dragging))
7472 XawScrollbarSetThumb (widget, top, shown);
7473 else
7474 {
7475 ScrollbarWidget sb = (ScrollbarWidget) widget;
7476 int scroll_mode = sb->scrollbar.scroll_mode;
f451eb13 7477
06a2c219
GM
7478 sb->scrollbar.scroll_mode = 0;
7479
7480 if (last_scroll_bar_part == scroll_bar_down_arrow)
7481 XawScrollbarSetThumb (widget, top, 1 - top);
7482 else
7483 {
7484 float old_top;
7485 XtVaGetValues (widget, XtNtopOfThumb, &old_top, NULL);
7486 XawScrollbarSetThumb (widget, old_top, min (shown, 1 - old_top));
7487 }
7488
7489 sb->scrollbar.scroll_mode = scroll_mode;
7490 }
7491 }
7492#endif /* HAVE_XAW3D */
7493
7494 UNBLOCK_INPUT;
f451eb13
JB
7495}
7496
06a2c219
GM
7497#endif /* USE_TOOLKIT_SCROLL_BARS */
7498
7499
7500\f
7501/************************************************************************
7502 Scroll bars, general
7503 ************************************************************************/
7504
7505/* Create a scroll bar and return the scroll bar vector for it. W is
7506 the Emacs window on which to create the scroll bar. TOP, LEFT,
7507 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7508 scroll bar. */
7509
ab648270 7510static struct scroll_bar *
06a2c219
GM
7511x_scroll_bar_create (w, top, left, width, height)
7512 struct window *w;
f451eb13
JB
7513 int top, left, width, height;
7514{
06a2c219
GM
7515 struct frame *f = XFRAME (w->frame);
7516#ifdef USE_X_TOOLKIT
7517 Arg av[10];
7518#endif
7519 int ac = 0;
7520 Window window;
334208b7
RS
7521 struct scroll_bar *bar
7522 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
f451eb13
JB
7523
7524 BLOCK_INPUT;
7525
06a2c219
GM
7526#if USE_TOOLKIT_SCROLL_BARS
7527 x_create_toolkit_scroll_bar (f, bar);
7528#else /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7529 {
7530 XSetWindowAttributes a;
7531 unsigned long mask;
06a2c219
GM
7532
7533 a.background_pixel = f->output_data.x->scroll_bar_background_pixel;
7534 if (a.background_pixel == -1)
7535 a.background_pixel = f->output_data.x->background_pixel;
7536
12ba150f 7537 a.event_mask = (ButtonPressMask | ButtonReleaseMask
9a572e2a 7538 | ButtonMotionMask | PointerMotionHintMask
12ba150f 7539 | ExposureMask);
7a13e894 7540 a.cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
f451eb13 7541
dbc4e1c1 7542 mask = (CWBackPixel | CWEventMask | CWCursor);
f451eb13 7543
06a2c219
GM
7544 /* Clear the area of W that will serve as a scroll bar. This is
7545 for the case that a window has been split horizontally. In
7546 this case, no clear_frame is generated to reduce flickering. */
7547 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7548 left, top, width,
7549 window_box_height (w), False);
7550
7551 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7552 /* Position and size of scroll bar. */
7553 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7554 top,
7555 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7556 height,
7557 /* Border width, depth, class, and visual. */
7558 0,
7559 CopyFromParent,
7560 CopyFromParent,
7561 CopyFromParent,
7562 /* Attributes. */
7563 mask, &a);
7564 SET_SCROLL_BAR_X_WINDOW (bar, window);
f451eb13 7565 }
06a2c219 7566#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 7567
06a2c219 7568 XSETWINDOW (bar->window, w);
e0c1aef2
KH
7569 XSETINT (bar->top, top);
7570 XSETINT (bar->left, left);
7571 XSETINT (bar->width, width);
7572 XSETINT (bar->height, height);
7573 XSETINT (bar->start, 0);
7574 XSETINT (bar->end, 0);
12ba150f 7575 bar->dragging = Qnil;
f451eb13
JB
7576
7577 /* Add bar to its frame's list of scroll bars. */
334208b7 7578 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 7579 bar->prev = Qnil;
334208b7 7580 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
06a2c219 7581 if (!NILP (bar->next))
e0c1aef2 7582 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
f451eb13 7583
06a2c219
GM
7584 /* Map the window/widget. */
7585#if USE_TOOLKIT_SCROLL_BARS
7586 XtMapWidget (SCROLL_BAR_X_WIDGET (bar));
7587 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7588 left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7589 top,
7590 width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7591 height, 0);
7592#else /* not USE_TOOLKIT_SCROLL_BARS */
7f9c7f94 7593 XMapRaised (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219 7594#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7595
7596 UNBLOCK_INPUT;
12ba150f 7597 return bar;
f451eb13
JB
7598}
7599
06a2c219 7600
12ba150f 7601/* Draw BAR's handle in the proper position.
06a2c219 7602
12ba150f
JB
7603 If the handle is already drawn from START to END, don't bother
7604 redrawing it, unless REBUILD is non-zero; in that case, always
7605 redraw it. (REBUILD is handy for drawing the handle after expose
58769bee 7606 events.)
12ba150f
JB
7607
7608 Normally, we want to constrain the start and end of the handle to
06a2c219
GM
7609 fit inside its rectangle, but if the user is dragging the scroll
7610 bar handle, we want to let them drag it down all the way, so that
7611 the bar's top is as far down as it goes; otherwise, there's no way
7612 to move to the very end of the buffer. */
7613
f451eb13 7614static void
ab648270
JB
7615x_scroll_bar_set_handle (bar, start, end, rebuild)
7616 struct scroll_bar *bar;
f451eb13 7617 int start, end;
12ba150f 7618 int rebuild;
f451eb13 7619{
06a2c219 7620#ifndef USE_TOOLKIT_SCROLL_BARS
12ba150f 7621 int dragging = ! NILP (bar->dragging);
ab648270 7622 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 7623 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 7624 GC gc = f->output_data.x->normal_gc;
12ba150f
JB
7625
7626 /* If the display is already accurate, do nothing. */
7627 if (! rebuild
7628 && start == XINT (bar->start)
7629 && end == XINT (bar->end))
7630 return;
7631
f451eb13
JB
7632 BLOCK_INPUT;
7633
7634 {
d9cdbb3d
RS
7635 int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
7636 int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
7637 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
f451eb13
JB
7638
7639 /* Make sure the values are reasonable, and try to preserve
7640 the distance between start and end. */
12ba150f
JB
7641 {
7642 int length = end - start;
7643
7644 if (start < 0)
7645 start = 0;
7646 else if (start > top_range)
7647 start = top_range;
7648 end = start + length;
7649
7650 if (end < start)
7651 end = start;
7652 else if (end > top_range && ! dragging)
7653 end = top_range;
7654 }
f451eb13 7655
ab648270 7656 /* Store the adjusted setting in the scroll bar. */
e0c1aef2
KH
7657 XSETINT (bar->start, start);
7658 XSETINT (bar->end, end);
f451eb13 7659
12ba150f
JB
7660 /* Clip the end position, just for display. */
7661 if (end > top_range)
7662 end = top_range;
f451eb13 7663
ab648270 7664 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels
12ba150f
JB
7665 below top positions, to make sure the handle is always at least
7666 that many pixels tall. */
ab648270 7667 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
f451eb13 7668
12ba150f
JB
7669 /* Draw the empty space above the handle. Note that we can't clear
7670 zero-height areas; that means "clear to end of window." */
7671 if (0 < start)
334208b7 7672 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 7673
12ba150f 7674 /* x, y, width, height, and exposures. */
ab648270
JB
7675 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7676 VERTICAL_SCROLL_BAR_TOP_BORDER,
12ba150f
JB
7677 inside_width, start,
7678 False);
f451eb13 7679
06a2c219
GM
7680 /* Change to proper foreground color if one is specified. */
7681 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7682 XSetForeground (FRAME_X_DISPLAY (f), gc,
7683 f->output_data.x->scroll_bar_foreground_pixel);
7684
12ba150f 7685 /* Draw the handle itself. */
334208b7 7686 XFillRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13 7687
12ba150f 7688 /* x, y, width, height */
ab648270
JB
7689 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7690 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
12ba150f 7691 inside_width, end - start);
f451eb13 7692
06a2c219
GM
7693 /* Restore the foreground color of the GC if we changed it above. */
7694 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7695 XSetForeground (FRAME_X_DISPLAY (f), gc,
7696 f->output_data.x->foreground_pixel);
f451eb13 7697
12ba150f
JB
7698 /* Draw the empty space below the handle. Note that we can't
7699 clear zero-height areas; that means "clear to end of window." */
7700 if (end < inside_height)
334208b7 7701 XClearArea (FRAME_X_DISPLAY (f), w,
f451eb13 7702
12ba150f 7703 /* x, y, width, height, and exposures. */
ab648270
JB
7704 VERTICAL_SCROLL_BAR_LEFT_BORDER,
7705 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
12ba150f
JB
7706 inside_width, inside_height - end,
7707 False);
f451eb13 7708
f451eb13
JB
7709 }
7710
f451eb13 7711 UNBLOCK_INPUT;
06a2c219 7712#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
7713}
7714
f451eb13 7715
06a2c219
GM
7716/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7717 nil. */
58769bee 7718
12ba150f 7719static void
ab648270
JB
7720x_scroll_bar_remove (bar)
7721 struct scroll_bar *bar;
12ba150f
JB
7722{
7723 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7724
7725 BLOCK_INPUT;
7726
06a2c219
GM
7727#if USE_TOOLKIT_SCROLL_BARS
7728 XtDestroyWidget (SCROLL_BAR_X_WIDGET (bar));
7729#else /* not USE_TOOLKIT_SCROLL_BARS */
334208b7 7730 XDestroyWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar));
06a2c219
GM
7731#endif /* not USE_TOOLKIT_SCROLL_BARS */
7732
ab648270
JB
7733 /* Disassociate this scroll bar from its window. */
7734 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
12ba150f
JB
7735
7736 UNBLOCK_INPUT;
7737}
7738
06a2c219 7739
12ba150f
JB
7740/* Set the handle of the vertical scroll bar for WINDOW to indicate
7741 that we are displaying PORTION characters out of a total of WHOLE
ab648270 7742 characters, starting at POSITION. If WINDOW has no scroll bar,
12ba150f 7743 create one. */
06a2c219 7744
12ba150f 7745static void
06a2c219
GM
7746XTset_vertical_scroll_bar (w, portion, whole, position)
7747 struct window *w;
f451eb13
JB
7748 int portion, whole, position;
7749{
06a2c219 7750 struct frame *f = XFRAME (w->frame);
ab648270 7751 struct scroll_bar *bar;
06a2c219
GM
7752 int pixel_top, pixel_left, pixel_width, pixel_height;
7753 int window_x, window_y, window_width, window_height;
7754 int scroll_bar_area_width;
7755
7756 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7757
7758 /* Where should this scroll bar be, pixel-wise? */
7759 pixel_top = window_y;
7760 pixel_height = window_height;
7761
7762 /* The width of the scroll bar itself. */
7763 pixel_width = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
7764 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7765 : (FRAME_SCROLL_BAR_COLS (f)
7766 * FONT_WIDTH (FRAME_FONT (f))));
7767
7768 /* The width on the screen reserved for the scroll bar plus maybe
7769 some empty room at both sides of the scroll bar. */
7770 scroll_bar_area_width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
7771
7772 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7773 pixel_left = (window_x
7774 + window_width
7775 + FRAME_FLAGS_AREA_WIDTH (f)
7776 + scroll_bar_area_width
7777 - pixel_width + 1);
7778 else
7779 pixel_left = (window_x
7780 - FRAME_FLAGS_AREA_WIDTH (f)
7781 - scroll_bar_area_width);
12ba150f 7782
ab648270 7783 /* Does the scroll bar exist yet? */
06a2c219
GM
7784 if (NILP (w->vertical_scroll_bar))
7785 bar = x_scroll_bar_create (w, pixel_top, pixel_left, pixel_width,
7786 pixel_height);
f451eb13 7787 else
12ba150f
JB
7788 {
7789 /* It may just need to be moved and resized. */
06a2c219
GM
7790 unsigned int mask = 0;
7791
7792 bar = XSCROLL_BAR (w->vertical_scroll_bar);
7793
7794 BLOCK_INPUT;
7795
7796 if (pixel_left != XINT (bar->left))
7797 mask |= CWX;
7798 if (pixel_top != XINT (bar->top))
7799 mask |= CWY;
7800 if (pixel_width != XINT (bar->width))
7801 mask |= CWWidth;
7802 if (pixel_height != XINT (bar->height))
7803 mask |= CWHeight;
7804
7805#ifdef USE_TOOLKIT_SCROLL_BARS
7806
7807 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
7808 {
7809 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7810 pixel_left + pixel_width - scroll_bar_area_width,
7811 pixel_top,
7812 (scroll_bar_area_width
7813 - pixel_width
7814 + VERTICAL_SCROLL_BAR_WIDTH_TRIM),
7815 pixel_height, False);
7816 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7817 (pixel_left
7818 + pixel_width
7819 - VERTICAL_SCROLL_BAR_WIDTH_TRIM),
7820 pixel_top,
7821 VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7822 pixel_height, False);
7823 }
7824 else
7825 {
7826 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7827 pixel_left, pixel_top,
7828 VERTICAL_SCROLL_BAR_WIDTH_TRIM, pixel_height, False);
7829 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7830 (pixel_left
7831 + pixel_width
7832 - VERTICAL_SCROLL_BAR_WIDTH_TRIM),
7833 pixel_top,
7834 (scroll_bar_area_width
7835 - pixel_width
7836 + VERTICAL_SCROLL_BAR_WIDTH_TRIM),
7837 pixel_height, False);
7838 }
7839
7840 /* Move/size the scroll bar widget. */
7841 if (mask)
7842 XtConfigureWidget (SCROLL_BAR_X_WIDGET (bar),
7843 pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7844 pixel_top,
7845 pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
7846 pixel_height, 0);
7847
7848#else /* not USE_TOOLKIT_SCROLL_BARS */
7849
7850 /* Clear areas not covered by the scroll bar. This makes sure a
7851 previous mode line display is cleared after C-x 2 C-x 1, for
7852 example. Non-toolkit scroll bars are as wide as the area
7853 reserved for scroll bars - trim at both sides. */
7854 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7855 pixel_left, pixel_top, VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7856 pixel_height, False);
7857 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7858 (pixel_left
7859 + pixel_width
7860 - VERTICAL_SCROLL_BAR_WIDTH_TRIM),
7861 pixel_top,
7862 VERTICAL_SCROLL_BAR_WIDTH_TRIM,
7863 pixel_height, False);
7864
7865 /* Move/size the scroll bar window. */
7866 if (mask)
7867 {
7868 XWindowChanges wc;
7869
7870 wc.x = pixel_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM;
7871 wc.y = pixel_top;
7872 wc.width = pixel_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2;
7873 wc.height = pixel_height;
7874 XConfigureWindow (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (bar),
7875 mask, &wc);
7876 }
7877
7878#endif /* not USE_TOOLKIT_SCROLL_BARS */
7879
7880 /* Remember new settings. */
7881 XSETINT (bar->left, pixel_left);
7882 XSETINT (bar->top, pixel_top);
7883 XSETINT (bar->width, pixel_width);
7884 XSETINT (bar->height, pixel_height);
7885
7886 UNBLOCK_INPUT;
12ba150f 7887 }
f451eb13 7888
06a2c219
GM
7889#if USE_TOOLKIT_SCROLL_BARS
7890 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole);
7891#else /* not USE_TOOLKIT_SCROLL_BARS */
ab648270 7892 /* Set the scroll bar's current state, unless we're currently being
f451eb13 7893 dragged. */
12ba150f 7894 if (NILP (bar->dragging))
f451eb13 7895 {
d9cdbb3d 7896 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, pixel_height);
f451eb13 7897
12ba150f 7898 if (whole == 0)
ab648270 7899 x_scroll_bar_set_handle (bar, 0, top_range, 0);
12ba150f
JB
7900 else
7901 {
43f868f5
JB
7902 int start = ((double) position * top_range) / whole;
7903 int end = ((double) (position + portion) * top_range) / whole;
ab648270 7904 x_scroll_bar_set_handle (bar, start, end, 0);
12ba150f 7905 }
f451eb13 7906 }
06a2c219 7907#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13 7908
06a2c219 7909 XSETVECTOR (w->vertical_scroll_bar, bar);
f451eb13
JB
7910}
7911
12ba150f 7912
f451eb13 7913/* The following three hooks are used when we're doing a thorough
ab648270 7914 redisplay of the frame. We don't explicitly know which scroll bars
f451eb13 7915 are going to be deleted, because keeping track of when windows go
12ba150f
JB
7916 away is a real pain - "Can you say set-window-configuration, boys
7917 and girls?" Instead, we just assert at the beginning of redisplay
ab648270 7918 that *all* scroll bars are to be removed, and then save a scroll bar
12ba150f 7919 from the fiery pit when we actually redisplay its window. */
f451eb13 7920
ab648270
JB
7921/* Arrange for all scroll bars on FRAME to be removed at the next call
7922 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
06a2c219
GM
7923 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
7924
58769bee 7925static void
ab648270 7926XTcondemn_scroll_bars (frame)
f451eb13
JB
7927 FRAME_PTR frame;
7928{
f9e24cb9
RS
7929 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7930 while (! NILP (FRAME_SCROLL_BARS (frame)))
7931 {
7932 Lisp_Object bar;
7933 bar = FRAME_SCROLL_BARS (frame);
7934 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
7935 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7936 XSCROLL_BAR (bar)->prev = Qnil;
7937 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7938 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
7939 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
7940 }
f451eb13
JB
7941}
7942
06a2c219 7943/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
12ba150f 7944 Note that WINDOW isn't necessarily condemned at all. */
f451eb13 7945static void
ab648270 7946XTredeem_scroll_bar (window)
12ba150f 7947 struct window *window;
f451eb13 7948{
ab648270 7949 struct scroll_bar *bar;
12ba150f 7950
ab648270
JB
7951 /* We can't redeem this window's scroll bar if it doesn't have one. */
7952 if (NILP (window->vertical_scroll_bar))
12ba150f
JB
7953 abort ();
7954
ab648270 7955 bar = XSCROLL_BAR (window->vertical_scroll_bar);
12ba150f
JB
7956
7957 /* Unlink it from the condemned list. */
7958 {
7959 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
7960
7961 if (NILP (bar->prev))
7962 {
7963 /* If the prev pointer is nil, it must be the first in one of
7964 the lists. */
ab648270 7965 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
12ba150f
JB
7966 /* It's not condemned. Everything's fine. */
7967 return;
ab648270
JB
7968 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7969 window->vertical_scroll_bar))
7970 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
12ba150f
JB
7971 else
7972 /* If its prev pointer is nil, it must be at the front of
7973 one or the other! */
7974 abort ();
7975 }
7976 else
ab648270 7977 XSCROLL_BAR (bar->prev)->next = bar->next;
12ba150f
JB
7978
7979 if (! NILP (bar->next))
ab648270 7980 XSCROLL_BAR (bar->next)->prev = bar->prev;
12ba150f 7981
ab648270 7982 bar->next = FRAME_SCROLL_BARS (f);
12ba150f 7983 bar->prev = Qnil;
e0c1aef2 7984 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
12ba150f 7985 if (! NILP (bar->next))
e0c1aef2 7986 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
12ba150f 7987 }
f451eb13
JB
7988}
7989
ab648270
JB
7990/* Remove all scroll bars on FRAME that haven't been saved since the
7991 last call to `*condemn_scroll_bars_hook'. */
06a2c219 7992
f451eb13 7993static void
ab648270 7994XTjudge_scroll_bars (f)
12ba150f 7995 FRAME_PTR f;
f451eb13 7996{
12ba150f 7997 Lisp_Object bar, next;
f451eb13 7998
ab648270 7999 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
cf7cb199
JB
8000
8001 /* Clear out the condemned list now so we won't try to process any
ab648270
JB
8002 more events on the hapless scroll bars. */
8003 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
cf7cb199
JB
8004
8005 for (; ! NILP (bar); bar = next)
f451eb13 8006 {
ab648270 8007 struct scroll_bar *b = XSCROLL_BAR (bar);
12ba150f 8008
ab648270 8009 x_scroll_bar_remove (b);
12ba150f
JB
8010
8011 next = b->next;
8012 b->next = b->prev = Qnil;
f451eb13 8013 }
12ba150f 8014
ab648270 8015 /* Now there should be no references to the condemned scroll bars,
12ba150f 8016 and they should get garbage-collected. */
f451eb13
JB
8017}
8018
8019
06a2c219
GM
8020/* Handle an Expose or GraphicsExpose event on a scroll bar. This
8021 is a no-op when using toolkit scroll bars.
ab648270
JB
8022
8023 This may be called from a signal handler, so we have to ignore GC
8024 mark bits. */
06a2c219 8025
f451eb13 8026static void
ab648270
JB
8027x_scroll_bar_expose (bar, event)
8028 struct scroll_bar *bar;
f451eb13
JB
8029 XEvent *event;
8030{
06a2c219
GM
8031#ifndef USE_TOOLKIT_SCROLL_BARS
8032
ab648270 8033 Window w = SCROLL_BAR_X_WINDOW (bar);
334208b7 8034 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7556890b 8035 GC gc = f->output_data.x->normal_gc;
3cbd2e0b 8036 int width_trim = VERTICAL_SCROLL_BAR_WIDTH_TRIM;
12ba150f 8037
f451eb13
JB
8038 BLOCK_INPUT;
8039
ab648270 8040 x_scroll_bar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1);
f451eb13 8041
06a2c219 8042 /* Draw a one-pixel border just inside the edges of the scroll bar. */
334208b7 8043 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc,
f451eb13
JB
8044
8045 /* x, y, width, height */
d9cdbb3d 8046 0, 0,
3cbd2e0b 8047 XINT (bar->width) - 1 - width_trim - width_trim,
d9cdbb3d
RS
8048 XINT (bar->height) - 1);
8049
f451eb13 8050 UNBLOCK_INPUT;
06a2c219
GM
8051
8052#endif /* not USE_TOOLKIT_SCROLL_BARS */
f451eb13
JB
8053}
8054
ab648270
JB
8055/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8056 is set to something other than no_event, it is enqueued.
8057
8058 This may be called from a signal handler, so we have to ignore GC
8059 mark bits. */
06a2c219 8060
f451eb13 8061static void
ab648270
JB
8062x_scroll_bar_handle_click (bar, event, emacs_event)
8063 struct scroll_bar *bar;
f451eb13
JB
8064 XEvent *event;
8065 struct input_event *emacs_event;
8066{
0299d313 8067 if (! GC_WINDOWP (bar->window))
12ba150f
JB
8068 abort ();
8069
ab648270 8070 emacs_event->kind = scroll_bar_click;
69388238 8071 emacs_event->code = event->xbutton.button - Button1;
0299d313
RS
8072 emacs_event->modifiers
8073 = (x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO
8074 (XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))),
8075 event->xbutton.state)
8076 | (event->type == ButtonRelease
8077 ? up_modifier
8078 : down_modifier));
12ba150f 8079 emacs_event->frame_or_window = bar->window;
f451eb13 8080 emacs_event->timestamp = event->xbutton.time;
12ba150f 8081 {
06a2c219 8082#if 0
d9cdbb3d 8083 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
0299d313 8084 int internal_height
d9cdbb3d 8085 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8086#endif
0299d313 8087 int top_range
d9cdbb3d 8088 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
ab648270 8089 int y = event->xbutton.y - VERTICAL_SCROLL_BAR_TOP_BORDER;
12ba150f
JB
8090
8091 if (y < 0) y = 0;
8092 if (y > top_range) y = top_range;
8093
8094 if (y < XINT (bar->start))
ab648270
JB
8095 emacs_event->part = scroll_bar_above_handle;
8096 else if (y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8097 emacs_event->part = scroll_bar_handle;
12ba150f 8098 else
ab648270 8099 emacs_event->part = scroll_bar_below_handle;
929787e1
JB
8100
8101 /* Just because the user has clicked on the handle doesn't mean
5116f055
JB
8102 they want to drag it. Lisp code needs to be able to decide
8103 whether or not we're dragging. */
929787e1 8104#if 0
12ba150f
JB
8105 /* If the user has just clicked on the handle, record where they're
8106 holding it. */
8107 if (event->type == ButtonPress
ab648270 8108 && emacs_event->part == scroll_bar_handle)
e0c1aef2 8109 XSETINT (bar->dragging, y - XINT (bar->start));
929787e1 8110#endif
12ba150f
JB
8111
8112 /* If the user has released the handle, set it to its final position. */
8113 if (event->type == ButtonRelease
8114 && ! NILP (bar->dragging))
8115 {
8116 int new_start = y - XINT (bar->dragging);
8117 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
f451eb13 8118
ab648270 8119 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
12ba150f
JB
8120 bar->dragging = Qnil;
8121 }
f451eb13 8122
5116f055
JB
8123 /* Same deal here as the other #if 0. */
8124#if 0
58769bee 8125 /* Clicks on the handle are always reported as occurring at the top of
12ba150f 8126 the handle. */
ab648270 8127 if (emacs_event->part == scroll_bar_handle)
12ba150f
JB
8128 emacs_event->x = bar->start;
8129 else
e0c1aef2 8130 XSETINT (emacs_event->x, y);
5116f055 8131#else
e0c1aef2 8132 XSETINT (emacs_event->x, y);
5116f055 8133#endif
f451eb13 8134
e0c1aef2 8135 XSETINT (emacs_event->y, top_range);
12ba150f
JB
8136 }
8137}
f451eb13 8138
ab648270
JB
8139/* Handle some mouse motion while someone is dragging the scroll bar.
8140
8141 This may be called from a signal handler, so we have to ignore GC
8142 mark bits. */
06a2c219 8143
f451eb13 8144static void
ab648270
JB
8145x_scroll_bar_note_movement (bar, event)
8146 struct scroll_bar *bar;
f451eb13
JB
8147 XEvent *event;
8148{
39d8bb4d
KH
8149 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
8150
f451eb13
JB
8151 last_mouse_movement_time = event->xmotion.time;
8152
39d8bb4d 8153 f->mouse_moved = 1;
e0c1aef2 8154 XSETVECTOR (last_mouse_scroll_bar, bar);
f451eb13
JB
8155
8156 /* If we're dragging the bar, display it. */
ab648270 8157 if (! GC_NILP (bar->dragging))
f451eb13
JB
8158 {
8159 /* Where should the handle be now? */
12ba150f 8160 int new_start = event->xmotion.y - XINT (bar->dragging);
f451eb13 8161
12ba150f 8162 if (new_start != XINT (bar->start))
f451eb13 8163 {
12ba150f 8164 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
58769bee 8165
ab648270 8166 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
f451eb13
JB
8167 }
8168 }
f451eb13
JB
8169}
8170
12ba150f 8171/* Return information to the user about the current position of the mouse
ab648270 8172 on the scroll bar. */
06a2c219 8173
12ba150f 8174static void
334208b7
RS
8175x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8176 FRAME_PTR *fp;
12ba150f 8177 Lisp_Object *bar_window;
ab648270 8178 enum scroll_bar_part *part;
12ba150f
JB
8179 Lisp_Object *x, *y;
8180 unsigned long *time;
8181{
ab648270 8182 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
334208b7
RS
8183 Window w = SCROLL_BAR_X_WINDOW (bar);
8184 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
12ba150f 8185 int win_x, win_y;
559cb2fb
JB
8186 Window dummy_window;
8187 int dummy_coord;
8188 unsigned int dummy_mask;
12ba150f 8189
cf7cb199
JB
8190 BLOCK_INPUT;
8191
ab648270 8192 /* Get the mouse's position relative to the scroll bar window, and
12ba150f 8193 report that. */
334208b7 8194 if (! XQueryPointer (FRAME_X_DISPLAY (f), w,
12ba150f 8195
559cb2fb
JB
8196 /* Root, child, root x and root y. */
8197 &dummy_window, &dummy_window,
8198 &dummy_coord, &dummy_coord,
12ba150f 8199
559cb2fb
JB
8200 /* Position relative to scroll bar. */
8201 &win_x, &win_y,
12ba150f 8202
559cb2fb
JB
8203 /* Mouse buttons and modifier keys. */
8204 &dummy_mask))
7a13e894 8205 ;
559cb2fb
JB
8206 else
8207 {
06a2c219 8208#if 0
559cb2fb 8209 int inside_height
d9cdbb3d 8210 = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
06a2c219 8211#endif
559cb2fb 8212 int top_range
d9cdbb3d 8213 = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
559cb2fb
JB
8214
8215 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
8216
8217 if (! NILP (bar->dragging))
8218 win_y -= XINT (bar->dragging);
8219
8220 if (win_y < 0)
8221 win_y = 0;
8222 if (win_y > top_range)
8223 win_y = top_range;
8224
334208b7 8225 *fp = f;
7a13e894 8226 *bar_window = bar->window;
559cb2fb
JB
8227
8228 if (! NILP (bar->dragging))
8229 *part = scroll_bar_handle;
8230 else if (win_y < XINT (bar->start))
8231 *part = scroll_bar_above_handle;
8232 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
8233 *part = scroll_bar_handle;
8234 else
8235 *part = scroll_bar_below_handle;
12ba150f 8236
e0c1aef2
KH
8237 XSETINT (*x, win_y);
8238 XSETINT (*y, top_range);
12ba150f 8239
39d8bb4d 8240 f->mouse_moved = 0;
559cb2fb
JB
8241 last_mouse_scroll_bar = Qnil;
8242 }
12ba150f 8243
559cb2fb 8244 *time = last_mouse_movement_time;
cf7cb199 8245
cf7cb199 8246 UNBLOCK_INPUT;
12ba150f
JB
8247}
8248
f451eb13 8249
dbc4e1c1 8250/* The screen has been cleared so we may have changed foreground or
ab648270
JB
8251 background colors, and the scroll bars may need to be redrawn.
8252 Clear out the scroll bars, and ask for expose events, so we can
dbc4e1c1
JB
8253 redraw them. */
8254
dfcf069d 8255void
ab648270 8256x_scroll_bar_clear (f)
dbc4e1c1
JB
8257 FRAME_PTR f;
8258{
06a2c219 8259#ifndef USE_TOOLKIT_SCROLL_BARS
dbc4e1c1
JB
8260 Lisp_Object bar;
8261
b80c363e
RS
8262 /* We can have scroll bars even if this is 0,
8263 if we just turned off scroll bar mode.
8264 But in that case we should not clear them. */
8265 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8266 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8267 bar = XSCROLL_BAR (bar)->next)
8268 XClearArea (FRAME_X_DISPLAY (f), SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)),
8269 0, 0, 0, 0, True);
06a2c219 8270#endif /* not USE_TOOLKIT_SCROLL_BARS */
dbc4e1c1
JB
8271}
8272
06a2c219 8273/* This processes Expose events from the menu-bar specific X event
19126e11 8274 loop in xmenu.c. This allows to redisplay the frame if necessary
06a2c219 8275 when handling menu-bar or pop-up items. */
3afe33e7 8276
06a2c219 8277int
3afe33e7
RS
8278process_expose_from_menu (event)
8279 XEvent event;
8280{
8281 FRAME_PTR f;
19126e11 8282 struct x_display_info *dpyinfo;
06a2c219 8283 int frame_exposed_p = 0;
3afe33e7 8284
f94397b5
KH
8285 BLOCK_INPUT;
8286
19126e11
KH
8287 dpyinfo = x_display_info_for_display (event.xexpose.display);
8288 f = x_window_to_frame (dpyinfo, event.xexpose.window);
3afe33e7
RS
8289 if (f)
8290 {
8291 if (f->async_visible == 0)
8292 {
8293 f->async_visible = 1;
8294 f->async_iconified = 0;
06c488fd 8295 f->output_data.x->has_been_visible = 1;
3afe33e7
RS
8296 SET_FRAME_GARBAGED (f);
8297 }
8298 else
8299 {
06a2c219
GM
8300 expose_frame (x_window_to_frame (dpyinfo, event.xexpose.window),
8301 event.xexpose.x, event.xexpose.y,
8302 event.xexpose.width, event.xexpose.height);
8303 frame_exposed_p = 1;
3afe33e7
RS
8304 }
8305 }
8306 else
8307 {
8308 struct scroll_bar *bar
8309 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8310
3afe33e7
RS
8311 if (bar)
8312 x_scroll_bar_expose (bar, &event);
8313 }
f94397b5
KH
8314
8315 UNBLOCK_INPUT;
06a2c219 8316 return frame_exposed_p;
3afe33e7 8317}
09756a85
RS
8318\f
8319/* Define a queue to save up SelectionRequest events for later handling. */
8320
8321struct selection_event_queue
8322 {
8323 XEvent event;
8324 struct selection_event_queue *next;
8325 };
8326
8327static struct selection_event_queue *queue;
8328
8329/* Nonzero means queue up certain events--don't process them yet. */
06a2c219 8330
09756a85
RS
8331static int x_queue_selection_requests;
8332
8333/* Queue up an X event *EVENT, to be processed later. */
dbc4e1c1 8334
09756a85 8335static void
334208b7
RS
8336x_queue_event (f, event)
8337 FRAME_PTR f;
09756a85
RS
8338 XEvent *event;
8339{
8340 struct selection_event_queue *queue_tmp
06a2c219 8341 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
09756a85 8342
58769bee 8343 if (queue_tmp != NULL)
09756a85
RS
8344 {
8345 queue_tmp->event = *event;
8346 queue_tmp->next = queue;
8347 queue = queue_tmp;
8348 }
8349}
8350
8351/* Take all the queued events and put them back
8352 so that they get processed afresh. */
8353
8354static void
db3906fd
RS
8355x_unqueue_events (display)
8356 Display *display;
09756a85 8357{
58769bee 8358 while (queue != NULL)
09756a85
RS
8359 {
8360 struct selection_event_queue *queue_tmp = queue;
db3906fd 8361 XPutBackEvent (display, &queue_tmp->event);
09756a85 8362 queue = queue_tmp->next;
06a2c219 8363 xfree ((char *)queue_tmp);
09756a85
RS
8364 }
8365}
8366
8367/* Start queuing SelectionRequest events. */
8368
8369void
db3906fd
RS
8370x_start_queuing_selection_requests (display)
8371 Display *display;
09756a85
RS
8372{
8373 x_queue_selection_requests++;
8374}
8375
8376/* Stop queuing SelectionRequest events. */
8377
8378void
db3906fd
RS
8379x_stop_queuing_selection_requests (display)
8380 Display *display;
09756a85
RS
8381{
8382 x_queue_selection_requests--;
db3906fd 8383 x_unqueue_events (display);
09756a85 8384}
f451eb13
JB
8385\f
8386/* The main X event-reading loop - XTread_socket. */
dc6f92b8 8387
06a2c219 8388/* Time stamp of enter window event. This is only used by XTread_socket,
dc6f92b8
JB
8389 but we have to put it out here, since static variables within functions
8390 sometimes don't work. */
06a2c219 8391
dc6f92b8
JB
8392static Time enter_timestamp;
8393
11edeb03 8394/* This holds the state XLookupString needs to implement dead keys
58769bee 8395 and other tricks known as "compose processing". _X Window System_
11edeb03
JB
8396 says that a portable program can't use this, but Stephen Gildea assures
8397 me that letting the compiler initialize it to zeros will work okay.
8398
8399 This must be defined outside of XTread_socket, for the same reasons
06a2c219
GM
8400 given for enter_time stamp, above. */
8401
11edeb03
JB
8402static XComposeStatus compose_status;
8403
10e6549c
RS
8404/* Record the last 100 characters stored
8405 to help debug the loss-of-chars-during-GC problem. */
06a2c219 8406
2224b905
RS
8407static int temp_index;
8408static short temp_buffer[100];
10e6549c 8409
7a13e894
RS
8410/* Set this to nonzero to fake an "X I/O error"
8411 on a particular display. */
06a2c219 8412
7a13e894
RS
8413struct x_display_info *XTread_socket_fake_io_error;
8414
2224b905
RS
8415/* When we find no input here, we occasionally do a no-op command
8416 to verify that the X server is still running and we can still talk with it.
8417 We try all the open displays, one by one.
8418 This variable is used for cycling thru the displays. */
06a2c219 8419
2224b905
RS
8420static struct x_display_info *next_noop_dpyinfo;
8421
06a2c219
GM
8422#define SET_SAVED_MENU_EVENT(size) \
8423 do \
8424 { \
8425 if (f->output_data.x->saved_menu_event == 0) \
8426 f->output_data.x->saved_menu_event \
8427 = (XEvent *) xmalloc (sizeof (XEvent)); \
8428 bcopy (&event, f->output_data.x->saved_menu_event, size); \
8429 if (numchars >= 1) \
8430 { \
8431 bufp->kind = menu_bar_activate_event; \
8432 XSETFRAME (bufp->frame_or_window, f); \
8433 bufp++; \
8434 count++; \
8435 numchars--; \
8436 } \
8437 } \
8438 while (0)
8439
8805890a 8440#define SET_SAVED_BUTTON_EVENT SET_SAVED_MENU_EVENT (sizeof (XButtonEvent))
06a2c219 8441#define SET_SAVED_KEY_EVENT SET_SAVED_MENU_EVENT (sizeof (XKeyEvent))
8805890a 8442
dc6f92b8
JB
8443/* Read events coming from the X server.
8444 This routine is called by the SIGIO handler.
8445 We return as soon as there are no more events to be read.
8446
8447 Events representing keys are stored in buffer BUFP,
8448 which can hold up to NUMCHARS characters.
8449 We return the number of characters stored into the buffer,
8450 thus pretending to be `read'.
8451
dc6f92b8
JB
8452 EXPECTED is nonzero if the caller knows input is available. */
8453
7c5283e4 8454int
f66868ba 8455XTread_socket (sd, bufp, numchars, expected)
dc6f92b8 8456 register int sd;
8805890a
KH
8457 /* register */ struct input_event *bufp;
8458 /* register */ int numchars;
dc6f92b8
JB
8459 int expected;
8460{
8461 int count = 0;
8462 int nbytes = 0;
dc6f92b8 8463 XEvent event;
f676886a 8464 struct frame *f;
66f55a9d 8465 int event_found = 0;
334208b7 8466 struct x_display_info *dpyinfo;
6c183ba5
RS
8467#ifdef HAVE_X_I18N
8468 Status status_return;
8469#endif
dc6f92b8 8470
9ac0d9e0 8471 if (interrupt_input_blocked)
dc6f92b8 8472 {
9ac0d9e0 8473 interrupt_input_pending = 1;
dc6f92b8
JB
8474 return -1;
8475 }
8476
9ac0d9e0 8477 interrupt_input_pending = 0;
dc6f92b8 8478 BLOCK_INPUT;
c0a04927
RS
8479
8480 /* So people can tell when we have read the available input. */
8481 input_signal_count++;
8482
dc6f92b8 8483 if (numchars <= 0)
06a2c219 8484 abort (); /* Don't think this happens. */
dc6f92b8 8485
7a13e894
RS
8486 /* Find the display we are supposed to read input for.
8487 It's the one communicating on descriptor SD. */
8488 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
8489 {
8490#if 0 /* This ought to be unnecessary; let's verify it. */
dc6f92b8 8491#ifdef FIOSNBIO
7a13e894
RS
8492 /* If available, Xlib uses FIOSNBIO to make the socket
8493 non-blocking, and then looks for EWOULDBLOCK. If O_NDELAY is set,
e6cbea31 8494 FIOSNBIO is ignored, and instead of signaling EWOULDBLOCK,
06a2c219 8495 a read returns 0, which Xlib interprets as equivalent to EPIPE. */
7a13e894 8496 fcntl (dpyinfo->connection, F_SETFL, 0);
c118dd06 8497#endif /* ! defined (FIOSNBIO) */
7a13e894 8498#endif
dc6f92b8 8499
7a13e894
RS
8500#if 0 /* This code can't be made to work, with multiple displays,
8501 and appears not to be used on any system any more.
8502 Also keyboard.c doesn't turn O_NDELAY on and off
8503 for X connections. */
dc6f92b8
JB
8504#ifndef SIGIO
8505#ifndef HAVE_SELECT
7a13e894
RS
8506 if (! (fcntl (dpyinfo->connection, F_GETFL, 0) & O_NDELAY))
8507 {
8508 extern int read_alarm_should_throw;
8509 read_alarm_should_throw = 1;
8510 XPeekEvent (dpyinfo->display, &event);
8511 read_alarm_should_throw = 0;
8512 }
c118dd06
JB
8513#endif /* HAVE_SELECT */
8514#endif /* SIGIO */
7a13e894 8515#endif
dc6f92b8 8516
7a13e894
RS
8517 /* For debugging, this gives a way to fake an I/O error. */
8518 if (dpyinfo == XTread_socket_fake_io_error)
8519 {
8520 XTread_socket_fake_io_error = 0;
8521 x_io_error_quitter (dpyinfo->display);
8522 }
dc6f92b8 8523
06a2c219 8524 while (XPending (dpyinfo->display))
dc6f92b8 8525 {
7a13e894 8526 XNextEvent (dpyinfo->display, &event);
06a2c219
GM
8527
8528 if (display_busy_cursor_p)
8529 {
8530 /* Setting inhibit_busy_cursor to 2 inhibits busy-cursor
8531 display until the next X event is read and we come
8532 here again. Setting it to 1 inhibits busy-cursor
8533 display for direct commands. */
8534 if (event.type == MotionNotify
8535 || event.type == EnterNotify
8536 || (dpyinfo->grabbed
8537 && event.type != ButtonRelease))
8538 inhibit_busy_cursor = 2;
8539 else
8540 inhibit_busy_cursor = 1;
8541 }
8542
531483fb 8543#ifdef HAVE_X_I18N
d1bc4182
RS
8544 {
8545 struct frame *f1 = x_any_window_to_frame (dpyinfo,
c99babf2 8546 event.xclient.window);
d1bc4182
RS
8547 /* The necessity of the following line took me
8548 a full work-day to decipher from the docs!! */
8549 if (f1 != 0 && FRAME_XIC (f1) && XFilterEvent (&event, None))
8550 break;
8551 }
0cd6403b 8552#endif
7a13e894
RS
8553 event_found = 1;
8554
8555 switch (event.type)
8556 {
8557 case ClientMessage:
c047688c 8558 {
7a13e894
RS
8559 if (event.xclient.message_type
8560 == dpyinfo->Xatom_wm_protocols
8561 && event.xclient.format == 32)
c047688c 8562 {
7a13e894
RS
8563 if (event.xclient.data.l[0]
8564 == dpyinfo->Xatom_wm_take_focus)
c047688c 8565 {
8c1a6a84
RS
8566 /* Use x_any_window_to_frame because this
8567 could be the shell widget window
8568 if the frame has no title bar. */
8569 f = x_any_window_to_frame (dpyinfo, event.xclient.window);
6c183ba5
RS
8570#ifdef HAVE_X_I18N
8571 /* Not quite sure this is needed -pd */
8c1a6a84 8572 if (f && FRAME_XIC (f))
6c183ba5
RS
8573 XSetICFocus (FRAME_XIC (f));
8574#endif
bf7253f4
RS
8575 /* Since we set WM_TAKE_FOCUS, we must call
8576 XSetInputFocus explicitly. But not if f is null,
8577 since that might be an event for a deleted frame. */
7a13e894 8578 if (f)
bf7253f4
RS
8579 {
8580 Display *d = event.xclient.display;
8581 /* Catch and ignore errors, in case window has been
8582 iconified by a window manager such as GWM. */
8583 int count = x_catch_errors (d);
8584 XSetInputFocus (d, event.xclient.window,
8585 RevertToPointerRoot,
8586 event.xclient.data.l[1]);
8587 /* This is needed to detect the error
8588 if there is an error. */
8589 XSync (d, False);
8590 x_uncatch_errors (d, count);
8591 }
7a13e894 8592 /* Not certain about handling scroll bars here */
c047688c 8593 }
7a13e894
RS
8594 else if (event.xclient.data.l[0]
8595 == dpyinfo->Xatom_wm_save_yourself)
8596 {
8597 /* Save state modify the WM_COMMAND property to
06a2c219 8598 something which can reinstate us. This notifies
7a13e894
RS
8599 the session manager, who's looking for such a
8600 PropertyNotify. Can restart processing when
06a2c219 8601 a keyboard or mouse event arrives. */
7a13e894
RS
8602 if (numchars > 0)
8603 {
19126e11
KH
8604 f = x_top_window_to_frame (dpyinfo,
8605 event.xclient.window);
7a13e894
RS
8606
8607 /* This is just so we only give real data once
8608 for a single Emacs process. */
8609 if (f == selected_frame)
8610 XSetCommand (FRAME_X_DISPLAY (f),
8611 event.xclient.window,
8612 initial_argv, initial_argc);
f000f5c5 8613 else if (f)
7a13e894
RS
8614 XSetCommand (FRAME_X_DISPLAY (f),
8615 event.xclient.window,
8616 0, 0);
8617 }
8618 }
8619 else if (event.xclient.data.l[0]
8620 == dpyinfo->Xatom_wm_delete_window)
1fb20991 8621 {
19126e11
KH
8622 struct frame *f
8623 = x_any_window_to_frame (dpyinfo,
8624 event.xclient.window);
1fb20991 8625
7a13e894
RS
8626 if (f)
8627 {
8628 if (numchars == 0)
8629 abort ();
1fb20991 8630
7a13e894
RS
8631 bufp->kind = delete_window_event;
8632 XSETFRAME (bufp->frame_or_window, f);
8633 bufp++;
8634
8635 count += 1;
8636 numchars -= 1;
8637 }
1fb20991 8638 }
c047688c 8639 }
7a13e894
RS
8640 else if (event.xclient.message_type
8641 == dpyinfo->Xatom_wm_configure_denied)
8642 {
8643 }
8644 else if (event.xclient.message_type
8645 == dpyinfo->Xatom_wm_window_moved)
8646 {
8647 int new_x, new_y;
19126e11
KH
8648 struct frame *f
8649 = x_window_to_frame (dpyinfo, event.xclient.window);
58769bee 8650
7a13e894
RS
8651 new_x = event.xclient.data.s[0];
8652 new_y = event.xclient.data.s[1];
1fb20991 8653
7a13e894
RS
8654 if (f)
8655 {
7556890b
RS
8656 f->output_data.x->left_pos = new_x;
8657 f->output_data.x->top_pos = new_y;
7a13e894 8658 }
1fb20991 8659 }
0fdff6bb 8660#ifdef HACK_EDITRES
7a13e894
RS
8661 else if (event.xclient.message_type
8662 == dpyinfo->Xatom_editres)
8663 {
19126e11
KH
8664 struct frame *f
8665 = x_any_window_to_frame (dpyinfo, event.xclient.window);
7556890b 8666 _XEditResCheckMessages (f->output_data.x->widget, NULL,
19126e11 8667 &event, NULL);
7a13e894 8668 }
0fdff6bb 8669#endif /* HACK_EDITRES */
06a2c219
GM
8670 else if ((event.xclient.message_type
8671 == dpyinfo->Xatom_DONE)
8672 || (event.xclient.message_type
8673 == dpyinfo->Xatom_PAGE))
8674 {
8675 /* Ghostview job completed. Kill it. We could
8676 reply with "Next" if we received "Page", but we
8677 currently never do because we are interested in
8678 images, only, which should have 1 page. */
8679 Window gs_window = (Window) event.xclient.data.l[0];
8680 Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
8681 struct frame *f
8682 = x_window_to_frame (dpyinfo, event.xclient.window);
8683 x_kill_gs_process (pixmap, f);
8684 expose_frame (f, 0, 0, 0, 0);
8685 }
8686#ifdef USE_TOOLKIT_SCROLL_BARS
8687 /* Scroll bar callbacks send a ClientMessage from which
8688 we construct an input_event. */
8689 else if (event.xclient.message_type
8690 == dpyinfo->Xatom_Scrollbar)
8691 {
8692 x_scroll_bar_to_input_event (&event, bufp);
8693 ++bufp, ++count, --numchars;
8694 goto out;
8695 }
8696#endif /* USE_TOOLKIT_SCROLL_BARS */
8697 else
8698 goto OTHER;
7a13e894
RS
8699 }
8700 break;
dc6f92b8 8701
7a13e894 8702 case SelectionNotify:
3afe33e7 8703#ifdef USE_X_TOOLKIT
19126e11 8704 if (! x_window_to_frame (dpyinfo, event.xselection.requestor))
7a13e894 8705 goto OTHER;
3afe33e7 8706#endif /* not USE_X_TOOLKIT */
dfcf069d 8707 x_handle_selection_notify (&event.xselection);
7a13e894 8708 break;
d56a553a 8709
06a2c219 8710 case SelectionClear: /* Someone has grabbed ownership. */
3afe33e7 8711#ifdef USE_X_TOOLKIT
19126e11 8712 if (! x_window_to_frame (dpyinfo, event.xselectionclear.window))
7a13e894 8713 goto OTHER;
3afe33e7 8714#endif /* USE_X_TOOLKIT */
7a13e894
RS
8715 {
8716 XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
d56a553a 8717
7a13e894
RS
8718 if (numchars == 0)
8719 abort ();
d56a553a 8720
7a13e894
RS
8721 bufp->kind = selection_clear_event;
8722 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8723 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8724 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 8725 bufp->frame_or_window = Qnil;
7a13e894 8726 bufp++;
d56a553a 8727
7a13e894
RS
8728 count += 1;
8729 numchars -= 1;
8730 }
8731 break;
dc6f92b8 8732
06a2c219 8733 case SelectionRequest: /* Someone wants our selection. */
3afe33e7 8734#ifdef USE_X_TOOLKIT
19126e11 8735 if (!x_window_to_frame (dpyinfo, event.xselectionrequest.owner))
7a13e894 8736 goto OTHER;
3afe33e7 8737#endif /* USE_X_TOOLKIT */
7a13e894 8738 if (x_queue_selection_requests)
19126e11 8739 x_queue_event (x_window_to_frame (dpyinfo, event.xselectionrequest.owner),
7a13e894
RS
8740 &event);
8741 else
8742 {
8743 XSelectionRequestEvent *eventp = (XSelectionRequestEvent *) &event;
dc6f92b8 8744
7a13e894
RS
8745 if (numchars == 0)
8746 abort ();
8747
8748 bufp->kind = selection_request_event;
8749 SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
8750 SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
8751 SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
8752 SELECTION_EVENT_TARGET (bufp) = eventp->target;
8753 SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
8754 SELECTION_EVENT_TIME (bufp) = eventp->time;
e6cbea31 8755 bufp->frame_or_window = Qnil;
7a13e894
RS
8756 bufp++;
8757
8758 count += 1;
8759 numchars -= 1;
8760 }
8761 break;
8762
8763 case PropertyNotify:
3afe33e7 8764#ifdef USE_X_TOOLKIT
19126e11 8765 if (!x_any_window_to_frame (dpyinfo, event.xproperty.window))
7a13e894 8766 goto OTHER;
3afe33e7 8767#endif /* not USE_X_TOOLKIT */
dfcf069d 8768 x_handle_property_notify (&event.xproperty);
7a13e894 8769 break;
dc6f92b8 8770
7a13e894 8771 case ReparentNotify:
19126e11 8772 f = x_top_window_to_frame (dpyinfo, event.xreparent.window);
7a13e894
RS
8773 if (f)
8774 {
8775 int x, y;
7556890b 8776 f->output_data.x->parent_desc = event.xreparent.parent;
7a13e894 8777 x_real_positions (f, &x, &y);
7556890b
RS
8778 f->output_data.x->left_pos = x;
8779 f->output_data.x->top_pos = y;
7a13e894
RS
8780 }
8781 break;
3bd330d4 8782
7a13e894 8783 case Expose:
19126e11 8784 f = x_window_to_frame (dpyinfo, event.xexpose.window);
7a13e894 8785 if (f)
dc6f92b8 8786 {
7a13e894
RS
8787 if (f->async_visible == 0)
8788 {
8789 f->async_visible = 1;
8790 f->async_iconified = 0;
06c488fd 8791 f->output_data.x->has_been_visible = 1;
7a13e894
RS
8792 SET_FRAME_GARBAGED (f);
8793 }
8794 else
06a2c219
GM
8795 expose_frame (x_window_to_frame (dpyinfo,
8796 event.xexpose.window),
8797 event.xexpose.x, event.xexpose.y,
8798 event.xexpose.width, event.xexpose.height);
dc6f92b8
JB
8799 }
8800 else
7a13e894 8801 {
06a2c219
GM
8802#ifdef USE_TOOLKIT_SCROLL_BARS
8803 /* Dispatch event to the widget. */
8804 goto OTHER;
8805#else /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
8806 struct scroll_bar *bar
8807 = x_window_to_scroll_bar (event.xexpose.window);
58769bee 8808
7a13e894
RS
8809 if (bar)
8810 x_scroll_bar_expose (bar, &event);
3afe33e7 8811#ifdef USE_X_TOOLKIT
7a13e894
RS
8812 else
8813 goto OTHER;
3afe33e7 8814#endif /* USE_X_TOOLKIT */
06a2c219 8815#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
8816 }
8817 break;
dc6f92b8 8818
7a13e894
RS
8819 case GraphicsExpose: /* This occurs when an XCopyArea's
8820 source area was obscured or not
8821 available.*/
19126e11 8822 f = x_window_to_frame (dpyinfo, event.xgraphicsexpose.drawable);
7a13e894
RS
8823 if (f)
8824 {
06a2c219
GM
8825 expose_frame (f,
8826 event.xgraphicsexpose.x, event.xgraphicsexpose.y,
8827 event.xgraphicsexpose.width,
8828 event.xgraphicsexpose.height);
7a13e894 8829 }
3afe33e7 8830#ifdef USE_X_TOOLKIT
7a13e894
RS
8831 else
8832 goto OTHER;
3afe33e7 8833#endif /* USE_X_TOOLKIT */
7a13e894 8834 break;
dc6f92b8 8835
7a13e894 8836 case NoExpose: /* This occurs when an XCopyArea's
06a2c219
GM
8837 source area was completely
8838 available */
7a13e894 8839 break;
dc6f92b8 8840
7a13e894 8841 case UnmapNotify:
06a2c219
GM
8842 /* Redo the mouse-highlight after the tooltip has gone. */
8843 if (event.xmap.window == tip_window)
8844 {
8845 tip_window = 0;
8846 redo_mouse_highlight ();
8847 }
8848
91ea2a7a 8849 f = x_top_window_to_frame (dpyinfo, event.xunmap.window);
7a13e894
RS
8850 if (f) /* F may no longer exist if
8851 the frame was deleted. */
8852 {
8853 /* While a frame is unmapped, display generation is
8854 disabled; you don't want to spend time updating a
8855 display that won't ever be seen. */
8856 f->async_visible = 0;
8857 /* We can't distinguish, from the event, whether the window
8858 has become iconified or invisible. So assume, if it
8859 was previously visible, than now it is iconified.
1aa6072f
RS
8860 But x_make_frame_invisible clears both
8861 the visible flag and the iconified flag;
8862 and that way, we know the window is not iconified now. */
7a13e894 8863 if (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f))
1aa6072f
RS
8864 {
8865 f->async_iconified = 1;
bddd097c 8866
1aa6072f
RS
8867 bufp->kind = iconify_event;
8868 XSETFRAME (bufp->frame_or_window, f);
8869 bufp++;
8870 count++;
8871 numchars--;
8872 }
7a13e894 8873 }
7a13e894 8874 goto OTHER;
dc6f92b8 8875
7a13e894 8876 case MapNotify:
06a2c219
GM
8877 if (event.xmap.window == tip_window)
8878 /* The tooltip has been drawn already. Avoid
8879 the SET_FRAME_GARBAGED below. */
8880 goto OTHER;
8881
8882 /* We use x_top_window_to_frame because map events can
8883 come for sub-windows and they don't mean that the
8884 frame is visible. */
19126e11 8885 f = x_top_window_to_frame (dpyinfo, event.xmap.window);
7a13e894
RS
8886 if (f)
8887 {
8888 f->async_visible = 1;
8889 f->async_iconified = 0;
06c488fd 8890 f->output_data.x->has_been_visible = 1;
dc6f92b8 8891
7a13e894
RS
8892 /* wait_reading_process_input will notice this and update
8893 the frame's display structures. */
8894 SET_FRAME_GARBAGED (f);
bddd097c 8895
d806e720
RS
8896 if (f->iconified)
8897 {
8898 bufp->kind = deiconify_event;
8899 XSETFRAME (bufp->frame_or_window, f);
8900 bufp++;
8901 count++;
8902 numchars--;
8903 }
e73ec6fa 8904 else if (! NILP (Vframe_list)
8c29f6bf 8905 && ! NILP (XCONS (Vframe_list)->cdr))
78aa2ba5
KH
8906 /* Force a redisplay sooner or later
8907 to update the frame titles
8908 in case this is the second frame. */
8909 record_asynch_buffer_change ();
7a13e894 8910 }
7a13e894 8911 goto OTHER;
dc6f92b8 8912
7a13e894 8913 case KeyPress:
19126e11 8914 f = x_any_window_to_frame (dpyinfo, event.xkey.window);
f451eb13 8915
06a2c219
GM
8916#ifdef USE_MOTIF
8917 /* I couldn't find a way to prevent LessTif scroll bars
8918 from consuming key events. */
8919 if (f == 0)
8920 {
8921 Widget widget = XtWindowToWidget (dpyinfo->display,
8922 event.xkey.window);
8923 if (widget && XmIsScrollBar (widget))
8924 {
8925 widget = XtParent (widget);
8926 f = x_any_window_to_frame (dpyinfo, XtWindow (widget));
8927 }
8928 }
8929#endif /* USE_MOTIF */
8930
7a13e894
RS
8931 if (f != 0)
8932 {
8933 KeySym keysym, orig_keysym;
8934 /* al%imercury@uunet.uu.net says that making this 81 instead of
8935 80 fixed a bug whereby meta chars made his Emacs hang. */
8936 unsigned char copy_buffer[81];
8937 int modifiers;
64bb1782 8938
7a13e894
RS
8939 event.xkey.state
8940 |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
8941 extra_keyboard_modifiers);
8942 modifiers = event.xkey.state;
3a2712f9 8943
7a13e894 8944 /* This will have to go some day... */
752a043f 8945
7a13e894
RS
8946 /* make_lispy_event turns chars into control chars.
8947 Don't do it here because XLookupString is too eager. */
8948 event.xkey.state &= ~ControlMask;
5d46f928
RS
8949 event.xkey.state &= ~(dpyinfo->meta_mod_mask
8950 | dpyinfo->super_mod_mask
8951 | dpyinfo->hyper_mod_mask
8952 | dpyinfo->alt_mod_mask);
8953
1cf4a0d1
RS
8954 /* In case Meta is ComposeCharacter,
8955 clear its status. According to Markus Ehrnsperger
8956 Markus.Ehrnsperger@lehrstuhl-bross.physik.uni-muenchen.de
8957 this enables ComposeCharacter to work whether or
8958 not it is combined with Meta. */
8959 if (modifiers & dpyinfo->meta_mod_mask)
8960 bzero (&compose_status, sizeof (compose_status));
8961
6c183ba5
RS
8962#ifdef HAVE_X_I18N
8963 if (FRAME_XIC (f))
8964 {
5d7cc324
RS
8965 /* The necessity of the following line took me
8966 a full work-day to decipher from the docs!! */
8967 if (XFilterEvent (&event, None))
8968 break;
6c183ba5
RS
8969 nbytes = XmbLookupString (FRAME_XIC (f),
8970 &event.xkey, copy_buffer,
8971 80, &keysym,
8972 &status_return);
1decb680
PE
8973 if (status_return == XLookupNone)
8974 break;
8975 else if (status_return == XLookupChars)
8976 keysym = NoSymbol;
8977 else if (status_return != XLookupKeySym
8978 && status_return != XLookupBoth)
8979 abort ();
6c183ba5
RS
8980 }
8981 else
8982 nbytes = XLookupString (&event.xkey, copy_buffer,
8983 80, &keysym, &compose_status);
8984#else
0299d313
RS
8985 nbytes = XLookupString (&event.xkey, copy_buffer,
8986 80, &keysym, &compose_status);
6c183ba5 8987#endif
dc6f92b8 8988
7a13e894 8989 orig_keysym = keysym;
55123275 8990
7a13e894
RS
8991 if (numchars > 1)
8992 {
8993 if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
8994 || keysym == XK_Delete
1097aea0 8995#ifdef XK_ISO_Left_Tab
441affdb 8996 || (keysym >= XK_ISO_Left_Tab && keysym <= XK_ISO_Enter)
1097aea0 8997#endif
852bff8f 8998 || (keysym >= XK_Kanji && keysym <= XK_Eisu_toggle)
7a13e894
RS
8999 || IsCursorKey (keysym) /* 0xff50 <= x < 0xff60 */
9000 || IsMiscFunctionKey (keysym) /* 0xff60 <= x < VARIES */
c34790e0 9001#ifdef HPUX
7a13e894
RS
9002 /* This recognizes the "extended function keys".
9003 It seems there's no cleaner way.
9004 Test IsModifierKey to avoid handling mode_switch
9005 incorrectly. */
9006 || ((unsigned) (keysym) >= XK_Select
9007 && (unsigned)(keysym) < XK_KP_Space)
69388238
RS
9008#endif
9009#ifdef XK_dead_circumflex
7a13e894 9010 || orig_keysym == XK_dead_circumflex
69388238
RS
9011#endif
9012#ifdef XK_dead_grave
7a13e894 9013 || orig_keysym == XK_dead_grave
69388238
RS
9014#endif
9015#ifdef XK_dead_tilde
7a13e894 9016 || orig_keysym == XK_dead_tilde
69388238
RS
9017#endif
9018#ifdef XK_dead_diaeresis
7a13e894 9019 || orig_keysym == XK_dead_diaeresis
69388238
RS
9020#endif
9021#ifdef XK_dead_macron
7a13e894 9022 || orig_keysym == XK_dead_macron
69388238
RS
9023#endif
9024#ifdef XK_dead_degree
7a13e894 9025 || orig_keysym == XK_dead_degree
69388238
RS
9026#endif
9027#ifdef XK_dead_acute
7a13e894 9028 || orig_keysym == XK_dead_acute
69388238
RS
9029#endif
9030#ifdef XK_dead_cedilla
7a13e894 9031 || orig_keysym == XK_dead_cedilla
69388238
RS
9032#endif
9033#ifdef XK_dead_breve
7a13e894 9034 || orig_keysym == XK_dead_breve
69388238
RS
9035#endif
9036#ifdef XK_dead_ogonek
7a13e894 9037 || orig_keysym == XK_dead_ogonek
69388238
RS
9038#endif
9039#ifdef XK_dead_caron
7a13e894 9040 || orig_keysym == XK_dead_caron
69388238
RS
9041#endif
9042#ifdef XK_dead_doubleacute
7a13e894 9043 || orig_keysym == XK_dead_doubleacute
69388238
RS
9044#endif
9045#ifdef XK_dead_abovedot
7a13e894 9046 || orig_keysym == XK_dead_abovedot
c34790e0 9047#endif
7a13e894
RS
9048 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */
9049 || IsFunctionKey (keysym) /* 0xffbe <= x < 0xffe1 */
9050 /* Any "vendor-specific" key is ok. */
9051 || (orig_keysym & (1 << 28)))
9052 && ! (IsModifierKey (orig_keysym)
7719aa06
RS
9053#ifndef HAVE_X11R5
9054#ifdef XK_Mode_switch
7a13e894 9055 || ((unsigned)(orig_keysym) == XK_Mode_switch)
7719aa06
RS
9056#endif
9057#ifdef XK_Num_Lock
7a13e894 9058 || ((unsigned)(orig_keysym) == XK_Num_Lock)
7719aa06
RS
9059#endif
9060#endif /* not HAVE_X11R5 */
7a13e894 9061 ))
dc6f92b8 9062 {
10e6549c
RS
9063 if (temp_index == sizeof temp_buffer / sizeof (short))
9064 temp_index = 0;
7a13e894
RS
9065 temp_buffer[temp_index++] = keysym;
9066 bufp->kind = non_ascii_keystroke;
9067 bufp->code = keysym;
e0c1aef2 9068 XSETFRAME (bufp->frame_or_window, f);
334208b7
RS
9069 bufp->modifiers
9070 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9071 modifiers);
1113d9db 9072 bufp->timestamp = event.xkey.time;
dc6f92b8 9073 bufp++;
7a13e894
RS
9074 count++;
9075 numchars--;
06a2c219
GM
9076
9077 if (display_busy_cursor_p)
9078 if (keysym != XK_Return || minibuf_level == 0)
9079 inhibit_busy_cursor = 2;
dc6f92b8 9080 }
7a13e894
RS
9081 else if (numchars > nbytes)
9082 {
9083 register int i;
9084
9085 for (i = 0; i < nbytes; i++)
9086 {
9087 if (temp_index == sizeof temp_buffer / sizeof (short))
9088 temp_index = 0;
9089 temp_buffer[temp_index++] = copy_buffer[i];
9090 bufp->kind = ascii_keystroke;
9091 bufp->code = copy_buffer[i];
9092 XSETFRAME (bufp->frame_or_window, f);
9093 bufp->modifiers
9094 = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
9095 modifiers);
9096 bufp->timestamp = event.xkey.time;
9097 bufp++;
9098 }
9099
9100 count += nbytes;
9101 numchars -= nbytes;
1decb680
PE
9102
9103 if (keysym == NoSymbol)
9104 break;
7a13e894
RS
9105 }
9106 else
9107 abort ();
dc6f92b8 9108 }
10e6549c
RS
9109 else
9110 abort ();
dc6f92b8 9111 }
717ca130 9112 goto OTHER;
f451eb13 9113
7a13e894 9114 /* Here's a possible interpretation of the whole
06a2c219
GM
9115 FocusIn-EnterNotify FocusOut-LeaveNotify mess. If
9116 you get a FocusIn event, you have to get a FocusOut
9117 event before you relinquish the focus. If you
9118 haven't received a FocusIn event, then a mere
9119 LeaveNotify is enough to free you. */
f451eb13 9120
7a13e894 9121 case EnterNotify:
06a2c219
GM
9122 {
9123 int from_menu_bar_p = 0;
9124
9125 f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
9126
9127#ifdef LESSTIF_VERSION
9128 /* When clicking outside of a menu bar popup to close
9129 it, we get a FocusIn/ EnterNotify sequence of
9130 events. The flag event.xcrossing.focus is not set
9131 in the EnterNotify event of that sequence because
9132 the focus is in the menu bar,
9133 event.xcrossing.window is the frame's X window.
9134 Unconditionally setting the focus frame to null in
9135 this case is not the right thing, because no event
9136 follows that could set the focus frame to the right
9137 value.
9138
9139 This could be a LessTif bug, but I wasn't able to
9140 reproduce the behavior in a simple test program.
9141
9142 (gerd, LessTif 0.88.1). */
9143
9144 if (!event.xcrossing.focus
9145 && f
9146 && f->output_data.x->menubar_widget)
9147 {
9148 Window focus;
9149 int revert;
9150
9151 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9152 if (focus == XtWindow (f->output_data.x->menubar_widget))
9153 from_menu_bar_p = 1;
9154 }
9155#endif /* LESSTIF_VERSION */
6d4238f3 9156
06a2c219
GM
9157 if (event.xcrossing.focus || from_menu_bar_p)
9158 {
9159 /* Avoid nasty pop/raise loops. */
9160 if (f && (!(f->auto_raise)
9161 || !(f->auto_lower)
9162 || (event.xcrossing.time - enter_timestamp) > 500))
9163 {
9164 x_new_focus_frame (dpyinfo, f);
9165 enter_timestamp = event.xcrossing.time;
9166 }
9167 }
9168 else if (f == dpyinfo->x_focus_frame)
9169 x_new_focus_frame (dpyinfo, 0);
9170
9171 /* EnterNotify counts as mouse movement,
9172 so update things that depend on mouse position. */
9173 if (f && !f->output_data.x->busy_p)
9174 note_mouse_movement (f, &event.xmotion);
9175 goto OTHER;
9176 }
dc6f92b8 9177
7a13e894 9178 case FocusIn:
19126e11 9179 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9180 if (event.xfocus.detail != NotifyPointer)
0f941935 9181 dpyinfo->x_focus_event_frame = f;
7a13e894 9182 if (f)
0f941935 9183 x_new_focus_frame (dpyinfo, f);
f9e24cb9 9184
6c183ba5
RS
9185#ifdef HAVE_X_I18N
9186 if (f && FRAME_XIC (f))
9187 XSetICFocus (FRAME_XIC (f));
9188#endif
9189
7a13e894 9190 goto OTHER;
10c5e63d 9191
7a13e894 9192 case LeaveNotify:
19126e11 9193 f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
7a13e894 9194 if (f)
10c5e63d 9195 {
06a2c219
GM
9196 Lisp_Object frame;
9197 int from_menu_bar_p = 0;
9198
7a13e894 9199 if (f == dpyinfo->mouse_face_mouse_frame)
06a2c219
GM
9200 {
9201 /* If we move outside the frame, then we're
9202 certainly no longer on any text in the frame. */
9203 clear_mouse_face (dpyinfo);
9204 dpyinfo->mouse_face_mouse_frame = 0;
9205 }
9206
9207 /* Generate a nil HELP_EVENT to cancel a help-echo.
9208 Do it only if there's something to cancel.
9209 Otherwise, the startup message is cleared when
9210 the mouse leaves the frame. */
9211 if (any_help_event_p)
9212 {
9213 XSETFRAME (frame, f);
9214 bufp->kind = HELP_EVENT;
9215 bufp->frame_or_window = Fcons (frame, Qnil);
9216 ++bufp, ++count, --numchars;
9217 }
7a13e894 9218
06a2c219
GM
9219#ifdef LESSTIF_VERSION
9220 /* Please see the comment at the start of the
9221 EnterNotify case. */
9222 if (!event.xcrossing.focus
9223 && f->output_data.x->menubar_widget)
9224 {
9225 Window focus;
9226 int revert;
9227 XGetInputFocus (FRAME_X_DISPLAY (f), &focus, &revert);
9228 if (focus == XtWindow (f->output_data.x->menubar_widget))
9229 from_menu_bar_p = 1;
9230 }
9231#endif /* LESSTIF_VERSION */
9232
9233 if (event.xcrossing.focus || from_menu_bar_p)
0f941935 9234 x_mouse_leave (dpyinfo);
10c5e63d 9235 else
7a13e894 9236 {
0f941935
KH
9237 if (f == dpyinfo->x_focus_event_frame)
9238 dpyinfo->x_focus_event_frame = 0;
9239 if (f == dpyinfo->x_focus_frame)
9240 x_new_focus_frame (dpyinfo, 0);
7a13e894 9241 }
10c5e63d 9242 }
7a13e894 9243 goto OTHER;
dc6f92b8 9244
7a13e894 9245 case FocusOut:
19126e11 9246 f = x_any_window_to_frame (dpyinfo, event.xfocus.window);
7a13e894 9247 if (event.xfocus.detail != NotifyPointer
0f941935
KH
9248 && f == dpyinfo->x_focus_event_frame)
9249 dpyinfo->x_focus_event_frame = 0;
9250 if (f && f == dpyinfo->x_focus_frame)
9251 x_new_focus_frame (dpyinfo, 0);
f9e24cb9 9252
6c183ba5
RS
9253#ifdef HAVE_X_I18N
9254 if (f && FRAME_XIC (f))
9255 XUnsetICFocus (FRAME_XIC (f));
9256#endif
9257
7a13e894 9258 goto OTHER;
dc6f92b8 9259
7a13e894 9260 case MotionNotify:
dc6f92b8 9261 {
06a2c219
GM
9262 previous_help_echo = help_echo;
9263 help_echo = Qnil;
9264
7a13e894
RS
9265 if (dpyinfo->grabbed && last_mouse_frame
9266 && FRAME_LIVE_P (last_mouse_frame))
9267 f = last_mouse_frame;
9268 else
19126e11 9269 f = x_window_to_frame (dpyinfo, event.xmotion.window);
06a2c219 9270
7a13e894
RS
9271 if (f)
9272 note_mouse_movement (f, &event.xmotion);
9273 else
9274 {
06a2c219 9275#ifndef USE_X_TOOLKIT
7a13e894
RS
9276 struct scroll_bar *bar
9277 = x_window_to_scroll_bar (event.xmotion.window);
f451eb13 9278
7a13e894
RS
9279 if (bar)
9280 x_scroll_bar_note_movement (bar, &event);
06a2c219 9281#endif /* USE_X_TOOLKIT */
b8009dd1 9282
06a2c219
GM
9283 /* If we move outside the frame, then we're
9284 certainly no longer on any text in the frame. */
7a13e894
RS
9285 clear_mouse_face (dpyinfo);
9286 }
06a2c219
GM
9287
9288 /* If the contents of the global variable help_echo
9289 has changed, generate a HELP_EVENT. */
9290 if (STRINGP (help_echo)
9291 || STRINGP (previous_help_echo))
9292 {
9293 Lisp_Object frame;
9294
9295 if (f)
9296 XSETFRAME (frame, f);
9297 else
9298 frame = Qnil;
9299
9300 any_help_event_p = 1;
9301 bufp->kind = HELP_EVENT;
9302 bufp->frame_or_window = Fcons (frame, help_echo);
9303 ++bufp, ++count, --numchars;
9304 }
9305
9306 goto OTHER;
dc6f92b8 9307 }
dc6f92b8 9308
7a13e894 9309 case ConfigureNotify:
9829ddba
RS
9310 f = x_top_window_to_frame (dpyinfo, event.xconfigure.window);
9311 if (f)
af395ec1 9312 {
bf1b7b30
KH
9313 int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
9314 int columns = PIXEL_TO_CHAR_WIDTH (f, event.xconfigure.width);
06a2c219 9315
2d7fc7e8
RS
9316#ifndef USE_X_TOOLKIT
9317 /* In the toolkit version, change_frame_size
9318 is called by the code that handles resizing
9319 of the EmacsFrame widget. */
7a13e894 9320
7a13e894
RS
9321 /* Even if the number of character rows and columns has
9322 not changed, the font size may have changed, so we need
9323 to check the pixel dimensions as well. */
9324 if (columns != f->width
9325 || rows != f->height
7556890b
RS
9326 || event.xconfigure.width != f->output_data.x->pixel_width
9327 || event.xconfigure.height != f->output_data.x->pixel_height)
7a13e894
RS
9328 {
9329 change_frame_size (f, rows, columns, 0, 1);
9330 SET_FRAME_GARBAGED (f);
e687d06e 9331 cancel_mouse_face (f);
7a13e894 9332 }
2d7fc7e8 9333#endif
af395ec1 9334
7556890b
RS
9335 f->output_data.x->pixel_width = event.xconfigure.width;
9336 f->output_data.x->pixel_height = event.xconfigure.height;
7a13e894
RS
9337
9338 /* What we have now is the position of Emacs's own window.
9339 Convert that to the position of the window manager window. */
dcb07ae9
RS
9340 x_real_positions (f, &f->output_data.x->left_pos,
9341 &f->output_data.x->top_pos);
9342
9343 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
9344 {
9345 /* Since the WM decorations come below top_pos now,
9346 we must put them below top_pos in the future. */
9347 f->output_data.x->win_gravity = NorthWestGravity;
9348 x_wm_set_size_hint (f, (long) 0, 0);
9349 }
8f08dc93
KH
9350#ifdef USE_MOTIF
9351 /* Some window managers pass (0,0) as the location of
9352 the window, and the Motif event handler stores it
9353 in the emacs widget, which messes up Motif menus. */
9354 if (event.xconfigure.x == 0 && event.xconfigure.y == 0)
9355 {
9356 event.xconfigure.x = f->output_data.x->widget->core.x;
9357 event.xconfigure.y = f->output_data.x->widget->core.y;
9358 }
06a2c219 9359#endif /* USE_MOTIF */
7a13e894 9360 }
2d7fc7e8 9361 goto OTHER;
dc6f92b8 9362
7a13e894
RS
9363 case ButtonPress:
9364 case ButtonRelease:
9365 {
9366 /* If we decide we want to generate an event to be seen
9367 by the rest of Emacs, we put it here. */
9368 struct input_event emacs_event;
06a2c219
GM
9369 int toolbar_p = 0;
9370
7a13e894 9371 emacs_event.kind = no_event;
7a13e894 9372 bzero (&compose_status, sizeof (compose_status));
9b07615b 9373
06a2c219
GM
9374 if (dpyinfo->grabbed
9375 && last_mouse_frame
9f67f20b
RS
9376 && FRAME_LIVE_P (last_mouse_frame))
9377 f = last_mouse_frame;
9378 else
2224b905 9379 f = x_window_to_frame (dpyinfo, event.xbutton.window);
9f67f20b 9380
06a2c219
GM
9381 if (f)
9382 {
9383 /* Is this in the toolbar? */
9384 if (WINDOWP (f->toolbar_window)
9385 && XFASTINT (XWINDOW (f->toolbar_window)->height))
9386 {
9387 Lisp_Object window;
9388 int p, x, y;
9389
9390 x = event.xbutton.x;
9391 y = event.xbutton.y;
9392
9393 /* Set x and y. */
9394 window = window_from_coordinates (f, x, y, &p, 1);
9395 if (EQ (window, f->toolbar_window))
9396 {
9397 x_handle_toolbar_click (f, &event.xbutton);
9398 toolbar_p = 1;
9399 }
9400 }
9401
9402 if (!toolbar_p)
9403 if (!dpyinfo->x_focus_frame
9404 || f == dpyinfo->x_focus_frame)
9405 construct_mouse_click (&emacs_event, &event, f);
7a13e894
RS
9406 }
9407 else
9408 {
06a2c219 9409#ifndef USE_TOOLKIT_SCROLL_BARS
7a13e894
RS
9410 struct scroll_bar *bar
9411 = x_window_to_scroll_bar (event.xbutton.window);
f451eb13 9412
7a13e894
RS
9413 if (bar)
9414 x_scroll_bar_handle_click (bar, &event, &emacs_event);
06a2c219 9415#endif /* not USE_TOOLKIT_SCROLL_BARS */
7a13e894
RS
9416 }
9417
9418 if (event.type == ButtonPress)
9419 {
9420 dpyinfo->grabbed |= (1 << event.xbutton.button);
9421 last_mouse_frame = f;
edad46f6
KH
9422 /* Ignore any mouse motion that happened
9423 before this event; any subsequent mouse-movement
9424 Emacs events should reflect only motion after
9425 the ButtonPress. */
a00e91cd
KH
9426 if (f != 0)
9427 f->mouse_moved = 0;
06a2c219
GM
9428
9429 if (!toolbar_p)
9430 last_toolbar_item = -1;
9431 if (display_busy_cursor_p)
9432 inhibit_busy_cursor = 2;
7a13e894 9433 }
3afe33e7
RS
9434 else
9435 {
7a13e894 9436 dpyinfo->grabbed &= ~(1 << event.xbutton.button);
3afe33e7 9437 }
23faf38f 9438
7a13e894
RS
9439 if (numchars >= 1 && emacs_event.kind != no_event)
9440 {
9441 bcopy (&emacs_event, bufp, sizeof (struct input_event));
9442 bufp++;
9443 count++;
9444 numchars--;
9445 }
3afe33e7
RS
9446
9447#ifdef USE_X_TOOLKIT
2224b905
RS
9448 f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
9449 /* For a down-event in the menu bar,
9450 don't pass it to Xt right now.
9451 Instead, save it away
9452 and we will pass it to Xt from kbd_buffer_get_event.
9453 That way, we can run some Lisp code first. */
91375f8f
RS
9454 if (f && event.type == ButtonPress
9455 /* Verify the event is really within the menu bar
9456 and not just sent to it due to grabbing. */
9457 && event.xbutton.x >= 0
9458 && event.xbutton.x < f->output_data.x->pixel_width
9459 && event.xbutton.y >= 0
9460 && event.xbutton.y < f->output_data.x->menubar_height
9461 && event.xbutton.same_screen)
2224b905 9462 {
8805890a 9463 SET_SAVED_BUTTON_EVENT;
2237cac9
RS
9464 XSETFRAME (last_mouse_press_frame, f);
9465 }
9466 else if (event.type == ButtonPress)
9467 {
9468 last_mouse_press_frame = Qnil;
30e671c3 9469 goto OTHER;
ce89ef46 9470 }
06a2c219 9471
2237cac9
RS
9472#ifdef USE_MOTIF /* This should do not harm for Lucid,
9473 but I am trying to be cautious. */
ce89ef46
RS
9474 else if (event.type == ButtonRelease)
9475 {
2237cac9 9476 if (!NILP (last_mouse_press_frame))
f10ded1c 9477 {
2237cac9
RS
9478 f = XFRAME (last_mouse_press_frame);
9479 if (f->output_data.x)
06a2c219 9480 SET_SAVED_BUTTON_EVENT;
f10ded1c 9481 }
06a2c219 9482 else
30e671c3 9483 goto OTHER;
2224b905 9484 }
2237cac9 9485#endif /* USE_MOTIF */
2224b905
RS
9486 else
9487 goto OTHER;
3afe33e7 9488#endif /* USE_X_TOOLKIT */
7a13e894
RS
9489 }
9490 break;
dc6f92b8 9491
7a13e894 9492 case CirculateNotify:
06a2c219
GM
9493 goto OTHER;
9494
7a13e894 9495 case CirculateRequest:
06a2c219
GM
9496 goto OTHER;
9497
9498 case VisibilityNotify:
9499 goto OTHER;
dc6f92b8 9500
7a13e894
RS
9501 case MappingNotify:
9502 /* Someone has changed the keyboard mapping - update the
9503 local cache. */
9504 switch (event.xmapping.request)
9505 {
9506 case MappingModifier:
9507 x_find_modifier_meanings (dpyinfo);
9508 /* This is meant to fall through. */
9509 case MappingKeyboard:
9510 XRefreshKeyboardMapping (&event.xmapping);
9511 }
7a13e894 9512 goto OTHER;
dc6f92b8 9513
7a13e894 9514 default:
7a13e894 9515 OTHER:
717ca130 9516#ifdef USE_X_TOOLKIT
7a13e894
RS
9517 BLOCK_INPUT;
9518 XtDispatchEvent (&event);
9519 UNBLOCK_INPUT;
3afe33e7 9520#endif /* USE_X_TOOLKIT */
7a13e894
RS
9521 break;
9522 }
dc6f92b8
JB
9523 }
9524 }
9525
06a2c219
GM
9526 out:;
9527
9a5196d0
RS
9528 /* On some systems, an X bug causes Emacs to get no more events
9529 when the window is destroyed. Detect that. (1994.) */
58769bee 9530 if (! event_found)
ef2a22d0 9531 {
ef2a22d0
RS
9532 /* Emacs and the X Server eats up CPU time if XNoOp is done every time.
9533 One XNOOP in 100 loops will make Emacs terminate.
9534 B. Bretthauer, 1994 */
9535 x_noop_count++;
58769bee 9536 if (x_noop_count >= 100)
ef2a22d0
RS
9537 {
9538 x_noop_count=0;
2224b905
RS
9539
9540 if (next_noop_dpyinfo == 0)
9541 next_noop_dpyinfo = x_display_list;
9542
9543 XNoOp (next_noop_dpyinfo->display);
9544
9545 /* Each time we get here, cycle through the displays now open. */
9546 next_noop_dpyinfo = next_noop_dpyinfo->next;
ef2a22d0
RS
9547 }
9548 }
502add23 9549
06a2c219 9550 /* If the focus was just given to an auto-raising frame,
0134a210 9551 raise it now. */
7a13e894 9552 /* ??? This ought to be able to handle more than one such frame. */
0134a210
RS
9553 if (pending_autoraise_frame)
9554 {
9555 x_raise_frame (pending_autoraise_frame);
9556 pending_autoraise_frame = 0;
9557 }
0134a210 9558
dc6f92b8
JB
9559 UNBLOCK_INPUT;
9560 return count;
9561}
06a2c219
GM
9562
9563
9564
dc6f92b8 9565\f
06a2c219
GM
9566/***********************************************************************
9567 Text Cursor
9568 ***********************************************************************/
9569
9570/* Note if the text cursor of window W has been overwritten by a
9571 drawing operation that outputs N glyphs starting at HPOS in the
9572 line given by output_cursor.vpos. N < 0 means all the rest of the
9573 line after HPOS has been written. */
9574
9575static void
9576note_overwritten_text_cursor (w, hpos, n)
9577 struct window *w;
9578 int hpos, n;
9579{
9580 if (updated_area == TEXT_AREA
9581 && output_cursor.vpos == w->phys_cursor.vpos
9582 && hpos <= w->phys_cursor.hpos
9583 && (n < 0
9584 || hpos + n > w->phys_cursor.hpos))
9585 w->phys_cursor_on_p = 0;
9586}
f451eb13
JB
9587
9588
06a2c219
GM
9589/* Set clipping for output in glyph row ROW. W is the window in which
9590 we operate. GC is the graphics context to set clipping in.
9591 WHOLE_LINE_P non-zero means include the areas used for truncation
9592 mark display and alike in the clipping rectangle.
9593
9594 ROW may be a text row or, e.g., a mode line. Text rows must be
9595 clipped to the interior of the window dedicated to text display,
9596 mode lines must be clipped to the whole window. */
dc6f92b8
JB
9597
9598static void
06a2c219
GM
9599x_clip_to_row (w, row, gc, whole_line_p)
9600 struct window *w;
9601 struct glyph_row *row;
9602 GC gc;
9603 int whole_line_p;
dc6f92b8 9604{
06a2c219
GM
9605 struct frame *f = XFRAME (WINDOW_FRAME (w));
9606 XRectangle clip_rect;
9607 int window_x, window_y, window_width, window_height;
dc6f92b8 9608
06a2c219 9609 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
5c1aae96 9610
06a2c219
GM
9611 clip_rect.x = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9612 clip_rect.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9613 clip_rect.y = max (clip_rect.y, window_y);
9614 clip_rect.width = window_width;
9615 clip_rect.height = row->visible_height;
5c1aae96 9616
06a2c219
GM
9617 /* If clipping to the whole line, including trunc marks, extend
9618 the rectangle to the left and increase its width. */
9619 if (whole_line_p)
9620 {
9621 clip_rect.x -= FRAME_X_FLAGS_AREA_WIDTH (f);
9622 clip_rect.width += 2 * FRAME_X_FLAGS_AREA_WIDTH (f);
9623 }
5c1aae96 9624
06a2c219 9625 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted);
dc6f92b8
JB
9626}
9627
06a2c219
GM
9628
9629/* Draw a hollow box cursor on window W in glyph row ROW. */
dc6f92b8
JB
9630
9631static void
06a2c219
GM
9632x_draw_hollow_cursor (w, row)
9633 struct window *w;
9634 struct glyph_row *row;
dc6f92b8 9635{
06a2c219
GM
9636 struct frame *f = XFRAME (WINDOW_FRAME (w));
9637 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9638 Display *dpy = FRAME_X_DISPLAY (f);
9639 int x, y, wd, h;
9640 XGCValues xgcv;
9641 struct glyph *cursor_glyph;
9642 GC gc;
9643
9644 /* Compute frame-relative coordinates from window-relative
9645 coordinates. */
9646 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9647 y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9648 + row->ascent - w->phys_cursor_ascent);
9649 h = row->height - 1;
9650
9651 /* Get the glyph the cursor is on. If we can't tell because
9652 the current matrix is invalid or such, give up. */
9653 cursor_glyph = get_phys_cursor_glyph (w);
9654 if (cursor_glyph == NULL)
dc6f92b8
JB
9655 return;
9656
06a2c219
GM
9657 /* Compute the width of the rectangle to draw. If on a stretch
9658 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9659 rectangle as wide as the glyph, but use a canonical character
9660 width instead. */
9661 wd = cursor_glyph->pixel_width - 1;
9662 if (cursor_glyph->type == STRETCH_GLYPH
9663 && !x_stretch_cursor_p)
9664 wd = min (CANON_X_UNIT (f), wd);
9665
9666 /* The foreground of cursor_gc is typically the same as the normal
9667 background color, which can cause the cursor box to be invisible. */
9668 xgcv.foreground = f->output_data.x->cursor_pixel;
9669 if (dpyinfo->scratch_cursor_gc)
9670 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
9671 else
9672 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_X_WINDOW (f),
9673 GCForeground, &xgcv);
9674 gc = dpyinfo->scratch_cursor_gc;
9675
9676 /* Set clipping, draw the rectangle, and reset clipping again. */
9677 x_clip_to_row (w, row, gc, 0);
9678 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h);
9679 XSetClipMask (dpy, gc, None);
dc6f92b8
JB
9680}
9681
06a2c219
GM
9682
9683/* Draw a bar cursor on window W in glyph row ROW.
9684
9685 Implementation note: One would like to draw a bar cursor with an
9686 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9687 Unfortunately, I didn't find a font yet that has this property set.
9688 --gerd. */
dc6f92b8
JB
9689
9690static void
06a2c219
GM
9691x_draw_bar_cursor (w, row)
9692 struct window *w;
9693 struct glyph_row *row;
dc6f92b8 9694{
06a2c219
GM
9695 /* If cursor hpos is out of bounds, don't draw garbage. This can
9696 happen in mini-buffer windows when switching between echo area
9697 glyphs and mini-buffer. */
9698 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9699 {
9700 struct frame *f = XFRAME (w->frame);
9701 struct glyph *cursor_glyph;
9702 GC gc;
9703 int x;
9704 unsigned long mask;
9705 XGCValues xgcv;
9706 Display *dpy;
9707 Window window;
9708
9709 cursor_glyph = get_phys_cursor_glyph (w);
9710 if (cursor_glyph == NULL)
9711 return;
9712
9713 xgcv.background = f->output_data.x->cursor_pixel;
9714 xgcv.foreground = f->output_data.x->cursor_pixel;
9715 xgcv.graphics_exposures = 0;
9716 mask = GCForeground | GCBackground | GCGraphicsExposures;
9717 dpy = FRAME_X_DISPLAY (f);
9718 window = FRAME_X_WINDOW (f);
9719 gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
9720
9721 if (gc)
9722 XChangeGC (dpy, gc, mask, &xgcv);
9723 else
9724 {
9725 gc = XCreateGC (dpy, window, mask, &xgcv);
9726 FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
9727 }
9728
9729 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9730 x_clip_to_row (w, row, gc, 0);
9731 XFillRectangle (dpy, window, gc,
9732 x,
9733 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9734 min (cursor_glyph->pixel_width,
9735 f->output_data.x->cursor_width),
9736 row->height);
9737 XSetClipMask (dpy, gc, None);
9738 }
dc6f92b8
JB
9739}
9740
06a2c219
GM
9741
9742/* Clear the cursor of window W to background color, and mark the
9743 cursor as not shown. This is used when the text where the cursor
9744 is is about to be rewritten. */
9745
dc6f92b8 9746static void
06a2c219
GM
9747x_clear_cursor (w)
9748 struct window *w;
dc6f92b8 9749{
06a2c219
GM
9750 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9751 x_update_window_cursor (w, 0);
9752}
90e65f07 9753
dbc4e1c1 9754
06a2c219
GM
9755/* Draw the cursor glyph of window W in glyph row ROW. See the
9756 comment of x_draw_glyphs for the meaning of HL. */
dbc4e1c1 9757
06a2c219
GM
9758static void
9759x_draw_phys_cursor_glyph (w, row, hl)
9760 struct window *w;
9761 struct glyph_row *row;
9762 enum draw_glyphs_face hl;
9763{
9764 /* If cursor hpos is out of bounds, don't draw garbage. This can
9765 happen in mini-buffer windows when switching between echo area
9766 glyphs and mini-buffer. */
9767 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9768 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9769 w->phys_cursor.hpos, w->phys_cursor.hpos + 1, hl, 0, 0);
9770}
dbc4e1c1 9771
eea6af04 9772
06a2c219 9773/* Erase the image of a cursor of window W from the screen. */
eea6af04 9774
06a2c219
GM
9775static void
9776x_erase_phys_cursor (w)
9777 struct window *w;
9778{
9779 struct frame *f = XFRAME (w->frame);
9780 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
9781 int hpos = w->phys_cursor.hpos;
9782 int vpos = w->phys_cursor.vpos;
9783 int mouse_face_here_p = 0;
9784 struct glyph_matrix *active_glyphs = w->current_matrix;
9785 struct glyph_row *cursor_row;
9786 struct glyph *cursor_glyph;
9787 enum draw_glyphs_face hl;
9788
9789 /* No cursor displayed or row invalidated => nothing to do on the
9790 screen. */
9791 if (w->phys_cursor_type == NO_CURSOR)
9792 goto mark_cursor_off;
9793
9794 /* VPOS >= active_glyphs->nrows means that window has been resized.
9795 Don't bother to erase the cursor. */
9796 if (vpos >= active_glyphs->nrows)
9797 goto mark_cursor_off;
9798
9799 /* If row containing cursor is marked invalid, there is nothing we
9800 can do. */
9801 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9802 if (!cursor_row->enabled_p)
9803 goto mark_cursor_off;
9804
9805 /* This can happen when the new row is shorter than the old one.
9806 In this case, either x_draw_glyphs or clear_end_of_line
9807 should have cleared the cursor. Note that we wouldn't be
9808 able to erase the cursor in this case because we don't have a
9809 cursor glyph at hand. */
9810 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9811 goto mark_cursor_off;
9812
9813 /* If the cursor is in the mouse face area, redisplay that when
9814 we clear the cursor. */
9815 if (w == XWINDOW (dpyinfo->mouse_face_window)
9816 && (vpos > dpyinfo->mouse_face_beg_row
9817 || (vpos == dpyinfo->mouse_face_beg_row
9818 && hpos >= dpyinfo->mouse_face_beg_col))
9819 && (vpos < dpyinfo->mouse_face_end_row
9820 || (vpos == dpyinfo->mouse_face_end_row
9821 && hpos < dpyinfo->mouse_face_end_col))
9822 /* Don't redraw the cursor's spot in mouse face if it is at the
9823 end of a line (on a newline). The cursor appears there, but
9824 mouse highlighting does not. */
9825 && cursor_row->used[TEXT_AREA] > hpos)
9826 mouse_face_here_p = 1;
9827
9828 /* Maybe clear the display under the cursor. */
9829 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9830 {
9831 int x;
9832 int top_line_height = WINDOW_DISPLAY_TOP_LINE_HEIGHT (w);
dbc4e1c1 9833
06a2c219
GM
9834 cursor_glyph = get_phys_cursor_glyph (w);
9835 if (cursor_glyph == NULL)
9836 goto mark_cursor_off;
dbc4e1c1 9837
06a2c219
GM
9838 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
9839
9840 XClearArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
9841 x,
9842 WINDOW_TO_FRAME_PIXEL_Y (w, max (top_line_height,
9843 cursor_row->y)),
9844 cursor_glyph->pixel_width,
9845 cursor_row->visible_height,
9846 False);
dbc4e1c1 9847 }
06a2c219
GM
9848
9849 /* Erase the cursor by redrawing the character underneath it. */
9850 if (mouse_face_here_p)
9851 hl = DRAW_MOUSE_FACE;
9852 else if (cursor_row->inverse_p)
9853 hl = DRAW_INVERSE_VIDEO;
9854 else
9855 hl = DRAW_NORMAL_TEXT;
9856 x_draw_phys_cursor_glyph (w, cursor_row, hl);
dbc4e1c1 9857
06a2c219
GM
9858 mark_cursor_off:
9859 w->phys_cursor_on_p = 0;
9860 w->phys_cursor_type = NO_CURSOR;
dbc4e1c1
JB
9861}
9862
9863
06a2c219
GM
9864/* Display or clear cursor of window W. If ON is zero, clear the
9865 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9866 where to put the cursor is specified by HPOS, VPOS, X and Y. */
dbc4e1c1 9867
06a2c219
GM
9868void
9869x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9870 struct window *w;
9871 int on, hpos, vpos, x, y;
dbc4e1c1 9872{
06a2c219
GM
9873 struct frame *f = XFRAME (w->frame);
9874 int new_cursor_type;
9875 struct glyph_matrix *current_glyphs;
9876 struct glyph_row *glyph_row;
9877 struct glyph *glyph;
dbc4e1c1 9878
49d838ea 9879 /* This is pointless on invisible frames, and dangerous on garbaged
06a2c219
GM
9880 windows and frames; in the latter case, the frame or window may
9881 be in the midst of changing its size, and x and y may be off the
9882 window. */
9883 if (! FRAME_VISIBLE_P (f)
9884 || FRAME_GARBAGED_P (f)
9885 || vpos >= w->current_matrix->nrows
9886 || hpos >= w->current_matrix->matrix_w)
dc6f92b8
JB
9887 return;
9888
9889 /* If cursor is off and we want it off, return quickly. */
06a2c219 9890 if (!on && !w->phys_cursor_on_p)
dc6f92b8
JB
9891 return;
9892
06a2c219
GM
9893 current_glyphs = w->current_matrix;
9894 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9895 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9896
9897 /* If cursor row is not enabled, we don't really know where to
9898 display the cursor. */
9899 if (!glyph_row->enabled_p)
9900 {
9901 w->phys_cursor_on_p = 0;
9902 return;
9903 }
9904
9905 xassert (interrupt_input_blocked);
9906
9907 /* Set new_cursor_type to the cursor we want to be displayed. In a
9908 mini-buffer window, we want the cursor only to appear if we are
9909 reading input from this window. For the selected window, we want
9910 the cursor type given by the frame parameter. If explicitly
9911 marked off, draw no cursor. In all other cases, we want a hollow
9912 box cursor. */
9913 if (w != XWINDOW (selected_window)
9914 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
9915 {
9916 if (MINI_WINDOW_P (w))
9917 new_cursor_type = NO_CURSOR;
9918 else
9919 new_cursor_type = HOLLOW_BOX_CURSOR;
9920 }
9921 else if (w->cursor_off_p)
9922 new_cursor_type = NO_CURSOR;
9923 else
9924 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9925
9926 /* If cursor is currently being shown and we don't want it to be or
9927 it is in the wrong place, or the cursor type is not what we want,
dc6f92b8 9928 erase it. */
06a2c219 9929 if (w->phys_cursor_on_p
dc6f92b8 9930 && (!on
06a2c219
GM
9931 || w->phys_cursor.x != x
9932 || w->phys_cursor.y != y
9933 || new_cursor_type != w->phys_cursor_type))
9934 x_erase_phys_cursor (w);
9935
9936 /* If the cursor is now invisible and we want it to be visible,
9937 display it. */
9938 if (on && !w->phys_cursor_on_p)
9939 {
9940 w->phys_cursor_ascent = glyph_row->ascent;
9941 w->phys_cursor_height = glyph_row->height;
9942
9943 /* Set phys_cursor_.* before x_draw_.* is called because some
9944 of them may need the information. */
9945 w->phys_cursor.x = x;
9946 w->phys_cursor.y = glyph_row->y;
9947 w->phys_cursor.hpos = hpos;
9948 w->phys_cursor.vpos = vpos;
9949 w->phys_cursor_type = new_cursor_type;
9950 w->phys_cursor_on_p = 1;
9951
9952 switch (new_cursor_type)
dc6f92b8 9953 {
06a2c219
GM
9954 case HOLLOW_BOX_CURSOR:
9955 x_draw_hollow_cursor (w, glyph_row);
9956 break;
9957
9958 case FILLED_BOX_CURSOR:
9959 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9960 break;
9961
9962 case BAR_CURSOR:
9963 x_draw_bar_cursor (w, glyph_row);
9964 break;
9965
9966 case NO_CURSOR:
9967 break;
dc6f92b8 9968
06a2c219
GM
9969 default:
9970 abort ();
9971 }
dc6f92b8
JB
9972 }
9973
06a2c219 9974#ifndef XFlush
f676886a 9975 if (updating_frame != f)
334208b7 9976 XFlush (FRAME_X_DISPLAY (f));
06a2c219 9977#endif
dc6f92b8
JB
9978}
9979
06a2c219
GM
9980
9981/* Display the cursor on window W, or clear it. X and Y are window
9982 relative pixel coordinates. HPOS and VPOS are glyph matrix
9983 positions. If W is not the selected window, display a hollow
9984 cursor. ON non-zero means display the cursor at X, Y which
9985 correspond to HPOS, VPOS, otherwise it is cleared. */
5d46f928 9986
dfcf069d 9987void
06a2c219
GM
9988x_display_cursor (w, on, hpos, vpos, x, y)
9989 struct window *w;
9990 int on, hpos, vpos, x, y;
dc6f92b8 9991{
f94397b5 9992 BLOCK_INPUT;
06a2c219 9993 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
5d46f928
RS
9994 UNBLOCK_INPUT;
9995}
9996
06a2c219
GM
9997
9998/* Display the cursor on window W, or clear it, according to ON_P.
5d46f928
RS
9999 Don't change the cursor's position. */
10000
dfcf069d 10001void
06a2c219 10002x_update_cursor (f, on_p)
5d46f928 10003 struct frame *f;
5d46f928 10004{
06a2c219
GM
10005 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
10006}
10007
10008
10009/* Call x_update_window_cursor with parameter ON_P on all leaf windows
10010 in the window tree rooted at W. */
10011
10012static void
10013x_update_cursor_in_window_tree (w, on_p)
10014 struct window *w;
10015 int on_p;
10016{
10017 while (w)
10018 {
10019 if (!NILP (w->hchild))
10020 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
10021 else if (!NILP (w->vchild))
10022 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
10023 else
10024 x_update_window_cursor (w, on_p);
10025
10026 w = NILP (w->next) ? 0 : XWINDOW (w->next);
10027 }
10028}
5d46f928 10029
f94397b5 10030
06a2c219
GM
10031/* Switch the display of W's cursor on or off, according to the value
10032 of ON. */
10033
10034static void
10035x_update_window_cursor (w, on)
10036 struct window *w;
10037 int on;
10038{
10039 BLOCK_INPUT;
10040 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
10041 w->phys_cursor.x, w->phys_cursor.y);
f94397b5 10042 UNBLOCK_INPUT;
dc6f92b8 10043}
06a2c219
GM
10044
10045
10046
dc6f92b8
JB
10047\f
10048/* Icons. */
10049
f676886a 10050/* Refresh bitmap kitchen sink icon for frame F
06a2c219 10051 when we get an expose event for it. */
dc6f92b8 10052
dfcf069d 10053void
f676886a
JB
10054refreshicon (f)
10055 struct frame *f;
dc6f92b8 10056{
06a2c219 10057 /* Normally, the window manager handles this function. */
dc6f92b8
JB
10058}
10059
dbc4e1c1 10060/* Make the x-window of frame F use the gnu icon bitmap. */
dc6f92b8
JB
10061
10062int
990ba854 10063x_bitmap_icon (f, file)
f676886a 10064 struct frame *f;
990ba854 10065 Lisp_Object file;
dc6f92b8 10066{
06a2c219 10067 int bitmap_id;
dc6f92b8 10068
c118dd06 10069 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10070 return 1;
10071
990ba854 10072 /* Free up our existing icon bitmap if any. */
7556890b
RS
10073 if (f->output_data.x->icon_bitmap > 0)
10074 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10075 f->output_data.x->icon_bitmap = 0;
990ba854
RS
10076
10077 if (STRINGP (file))
7f2ae036
RS
10078 bitmap_id = x_create_bitmap_from_file (f, file);
10079 else
10080 {
990ba854 10081 /* Create the GNU bitmap if necessary. */
5bf01b68 10082 if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
334208b7
RS
10083 FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
10084 = x_create_bitmap_from_data (f, gnu_bits,
10085 gnu_width, gnu_height);
990ba854
RS
10086
10087 /* The first time we create the GNU bitmap,
06a2c219 10088 this increments the ref-count one extra time.
990ba854
RS
10089 As a result, the GNU bitmap is never freed.
10090 That way, we don't have to worry about allocating it again. */
334208b7 10091 x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
990ba854 10092
334208b7 10093 bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
7f2ae036
RS
10094 }
10095
10096 x_wm_set_icon_pixmap (f, bitmap_id);
7556890b 10097 f->output_data.x->icon_bitmap = bitmap_id;
dc6f92b8
JB
10098
10099 return 0;
10100}
10101
10102
1be2d067
KH
10103/* Make the x-window of frame F use a rectangle with text.
10104 Use ICON_NAME as the text. */
dc6f92b8
JB
10105
10106int
f676886a
JB
10107x_text_icon (f, icon_name)
10108 struct frame *f;
dc6f92b8
JB
10109 char *icon_name;
10110{
c118dd06 10111 if (FRAME_X_WINDOW (f) == 0)
dc6f92b8
JB
10112 return 1;
10113
1be2d067
KH
10114#ifdef HAVE_X11R4
10115 {
10116 XTextProperty text;
10117 text.value = (unsigned char *) icon_name;
10118 text.encoding = XA_STRING;
10119 text.format = 8;
10120 text.nitems = strlen (icon_name);
10121#ifdef USE_X_TOOLKIT
7556890b 10122 XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
1be2d067
KH
10123 &text);
10124#else /* not USE_X_TOOLKIT */
10125 XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
10126#endif /* not USE_X_TOOLKIT */
10127 }
10128#else /* not HAVE_X11R4 */
10129 XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
10130#endif /* not HAVE_X11R4 */
58769bee 10131
7556890b
RS
10132 if (f->output_data.x->icon_bitmap > 0)
10133 x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
10134 f->output_data.x->icon_bitmap = 0;
b1c884c3 10135 x_wm_set_icon_pixmap (f, 0);
dc6f92b8
JB
10136
10137 return 0;
10138}
10139\f
e99db5a1
RS
10140#define X_ERROR_MESSAGE_SIZE 200
10141
10142/* If non-nil, this should be a string.
10143 It means catch X errors and store the error message in this string. */
10144
10145static Lisp_Object x_error_message_string;
10146
10147/* An X error handler which stores the error message in
10148 x_error_message_string. This is called from x_error_handler if
10149 x_catch_errors is in effect. */
10150
06a2c219 10151static void
e99db5a1
RS
10152x_error_catcher (display, error)
10153 Display *display;
10154 XErrorEvent *error;
10155{
10156 XGetErrorText (display, error->error_code,
10157 XSTRING (x_error_message_string)->data,
10158 X_ERROR_MESSAGE_SIZE);
10159}
10160
10161/* Begin trapping X errors for display DPY. Actually we trap X errors
10162 for all displays, but DPY should be the display you are actually
10163 operating on.
10164
10165 After calling this function, X protocol errors no longer cause
10166 Emacs to exit; instead, they are recorded in the string
10167 stored in x_error_message_string.
10168
10169 Calling x_check_errors signals an Emacs error if an X error has
10170 occurred since the last call to x_catch_errors or x_check_errors.
10171
10172 Calling x_uncatch_errors resumes the normal error handling. */
10173
10174void x_check_errors ();
10175static Lisp_Object x_catch_errors_unwind ();
10176
10177int
10178x_catch_errors (dpy)
10179 Display *dpy;
10180{
10181 int count = specpdl_ptr - specpdl;
10182
10183 /* Make sure any errors from previous requests have been dealt with. */
10184 XSync (dpy, False);
10185
10186 record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
10187
10188 x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
10189 XSTRING (x_error_message_string)->data[0] = 0;
10190
10191 return count;
10192}
10193
10194/* Unbind the binding that we made to check for X errors. */
10195
10196static Lisp_Object
10197x_catch_errors_unwind (old_val)
10198 Lisp_Object old_val;
10199{
10200 x_error_message_string = old_val;
10201 return Qnil;
10202}
10203
10204/* If any X protocol errors have arrived since the last call to
10205 x_catch_errors or x_check_errors, signal an Emacs error using
10206 sprintf (a buffer, FORMAT, the x error message text) as the text. */
10207
10208void
10209x_check_errors (dpy, format)
10210 Display *dpy;
10211 char *format;
10212{
10213 /* Make sure to catch any errors incurred so far. */
10214 XSync (dpy, False);
10215
10216 if (XSTRING (x_error_message_string)->data[0])
10217 error (format, XSTRING (x_error_message_string)->data);
10218}
10219
9829ddba
RS
10220/* Nonzero if we had any X protocol errors
10221 since we did x_catch_errors on DPY. */
e99db5a1
RS
10222
10223int
10224x_had_errors_p (dpy)
10225 Display *dpy;
10226{
10227 /* Make sure to catch any errors incurred so far. */
10228 XSync (dpy, False);
10229
10230 return XSTRING (x_error_message_string)->data[0] != 0;
10231}
10232
9829ddba
RS
10233/* Forget about any errors we have had, since we did x_catch_errors on DPY. */
10234
06a2c219 10235void
9829ddba
RS
10236x_clear_errors (dpy)
10237 Display *dpy;
10238{
10239 XSTRING (x_error_message_string)->data[0] = 0;
10240}
10241
e99db5a1
RS
10242/* Stop catching X protocol errors and let them make Emacs die.
10243 DPY should be the display that was passed to x_catch_errors.
10244 COUNT should be the value that was returned by
10245 the corresponding call to x_catch_errors. */
10246
10247void
10248x_uncatch_errors (dpy, count)
10249 Display *dpy;
10250 int count;
10251{
10252 unbind_to (count, Qnil);
10253}
10254
10255#if 0
10256static unsigned int x_wire_count;
10257x_trace_wire ()
10258{
10259 fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
10260}
10261#endif /* ! 0 */
10262
10263\f
10264/* Handle SIGPIPE, which can happen when the connection to a server
10265 simply goes away. SIGPIPE is handled by x_connection_signal.
10266 Don't need to do anything, because the write which caused the
10267 SIGPIPE will fail, causing Xlib to invoke the X IO error handler,
06a2c219 10268 which will do the appropriate cleanup for us. */
e99db5a1
RS
10269
10270static SIGTYPE
10271x_connection_signal (signalnum) /* If we don't have an argument, */
06a2c219 10272 int signalnum; /* some compilers complain in signal calls. */
e99db5a1
RS
10273{
10274#ifdef USG
10275 /* USG systems forget handlers when they are used;
10276 must reestablish each time */
10277 signal (signalnum, x_connection_signal);
10278#endif /* USG */
10279}
10280\f
4746118a
JB
10281/* Handling X errors. */
10282
7a13e894 10283/* Handle the loss of connection to display DISPLAY. */
16bd92ea 10284
4746118a 10285static SIGTYPE
7a13e894
RS
10286x_connection_closed (display, error_message)
10287 Display *display;
10288 char *error_message;
4746118a 10289{
7a13e894
RS
10290 struct x_display_info *dpyinfo = x_display_info_for_display (display);
10291 Lisp_Object frame, tail;
10292
6186a4a0
RS
10293 /* Indicate that this display is dead. */
10294
f613a4c8 10295#ifdef USE_X_TOOLKIT
adabc3a9 10296 XtCloseDisplay (display);
f613a4c8 10297#endif
adabc3a9 10298
6186a4a0
RS
10299 dpyinfo->display = 0;
10300
06a2c219 10301 /* First delete frames whose mini-buffers are on frames
7a13e894
RS
10302 that are on the dead display. */
10303 FOR_EACH_FRAME (tail, frame)
10304 {
10305 Lisp_Object minibuf_frame;
10306 minibuf_frame
10307 = WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
f48f33ca
RS
10308 if (FRAME_X_P (XFRAME (frame))
10309 && FRAME_X_P (XFRAME (minibuf_frame))
10310 && ! EQ (frame, minibuf_frame)
10311 && FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
7a13e894
RS
10312 Fdelete_frame (frame, Qt);
10313 }
10314
10315 /* Now delete all remaining frames on the dead display.
06a2c219 10316 We are now sure none of these is used as the mini-buffer
7a13e894
RS
10317 for another frame that we need to delete. */
10318 FOR_EACH_FRAME (tail, frame)
f48f33ca
RS
10319 if (FRAME_X_P (XFRAME (frame))
10320 && FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
07a7096a
KH
10321 {
10322 /* Set this to t so that Fdelete_frame won't get confused
10323 trying to find a replacement. */
10324 FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
10325 Fdelete_frame (frame, Qt);
10326 }
7a13e894 10327
482a1bd2
KH
10328 if (dpyinfo)
10329 x_delete_display (dpyinfo);
7a13e894
RS
10330
10331 if (x_display_list == 0)
10332 {
f8d07b62 10333 fprintf (stderr, "%s\n", error_message);
7a13e894
RS
10334 shut_down_emacs (0, 0, Qnil);
10335 exit (70);
10336 }
12ba150f 10337
7a13e894
RS
10338 /* Ordinary stack unwind doesn't deal with these. */
10339#ifdef SIGIO
10340 sigunblock (sigmask (SIGIO));
10341#endif
10342 sigunblock (sigmask (SIGALRM));
10343 TOTALLY_UNBLOCK_INPUT;
10344
aa4d9a9e 10345 clear_waiting_for_input ();
7a13e894 10346 error ("%s", error_message);
4746118a
JB
10347}
10348
7a13e894
RS
10349/* This is the usual handler for X protocol errors.
10350 It kills all frames on the display that we got the error for.
10351 If that was the only one, it prints an error message and kills Emacs. */
10352
06a2c219 10353static void
c118dd06
JB
10354x_error_quitter (display, error)
10355 Display *display;
10356 XErrorEvent *error;
10357{
7a13e894 10358 char buf[256], buf1[356];
dc6f92b8 10359
58769bee 10360 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 10361 original error handler. */
dc6f92b8 10362
c118dd06 10363 XGetErrorText (display, error->error_code, buf, sizeof (buf));
0a0fdc70 10364 sprintf (buf1, "X protocol error: %s on protocol request %d",
c118dd06 10365 buf, error->request_code);
7a13e894 10366 x_connection_closed (display, buf1);
dc6f92b8
JB
10367}
10368
e99db5a1
RS
10369/* This is the first-level handler for X protocol errors.
10370 It calls x_error_quitter or x_error_catcher. */
7a13e894 10371
8922af5f 10372static int
e99db5a1 10373x_error_handler (display, error)
8922af5f 10374 Display *display;
e99db5a1 10375 XErrorEvent *error;
8922af5f 10376{
e99db5a1
RS
10377 if (! NILP (x_error_message_string))
10378 x_error_catcher (display, error);
10379 else
10380 x_error_quitter (display, error);
06a2c219 10381 return 0;
f9e24cb9 10382}
c118dd06 10383
e99db5a1
RS
10384/* This is the handler for X IO errors, always.
10385 It kills all frames on the display that we lost touch with.
10386 If that was the only one, it prints an error message and kills Emacs. */
7a13e894 10387
c118dd06 10388static int
e99db5a1 10389x_io_error_quitter (display)
c118dd06 10390 Display *display;
c118dd06 10391{
e99db5a1 10392 char buf[256];
dc6f92b8 10393
e99db5a1
RS
10394 sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
10395 x_connection_closed (display, buf);
06a2c219 10396 return 0;
dc6f92b8 10397}
dc6f92b8 10398\f
f451eb13
JB
10399/* Changing the font of the frame. */
10400
76bcdf39
RS
10401/* Give frame F the font named FONTNAME as its default font, and
10402 return the full name of that font. FONTNAME may be a wildcard
10403 pattern; in that case, we choose some font that fits the pattern.
10404 The return value shows which font we chose. */
10405
b5cf7a0e 10406Lisp_Object
f676886a
JB
10407x_new_font (f, fontname)
10408 struct frame *f;
dc6f92b8
JB
10409 register char *fontname;
10410{
dc43ef94
KH
10411 struct font_info *fontp
10412 = fs_load_font (f, FRAME_X_FONT_TABLE (f), CHARSET_ASCII, fontname, -1);
dc6f92b8 10413
dc43ef94
KH
10414 if (!fontp)
10415 return Qnil;
2224a5fc 10416
dc43ef94
KH
10417 f->output_data.x->font = (XFontStruct *) (fontp->font);
10418 f->output_data.x->font_baseline
10419 = (f->output_data.x->font->ascent + fontp->baseline_offset);
10420 f->output_data.x->fontset = -1;
10421
b2cad826
KH
10422 /* Compute the scroll bar width in character columns. */
10423 if (f->scroll_bar_pixel_width > 0)
10424 {
7556890b 10425 int wid = FONT_WIDTH (f->output_data.x->font);
b2cad826
KH
10426 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
10427 }
10428 else
4e61bddf
RS
10429 {
10430 int wid = FONT_WIDTH (f->output_data.x->font);
10431 f->scroll_bar_cols = (14 + wid - 1) / wid;
10432 }
b2cad826 10433
f676886a 10434 /* Now make the frame display the given font. */
c118dd06 10435 if (FRAME_X_WINDOW (f) != 0)
dc6f92b8 10436 {
7556890b
RS
10437 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
10438 f->output_data.x->font->fid);
10439 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->reverse_gc,
10440 f->output_data.x->font->fid);
10441 XSetFont (FRAME_X_DISPLAY (f), f->output_data.x->cursor_gc,
10442 f->output_data.x->font->fid);
f676886a 10443
a27f9f86 10444 frame_update_line_height (f);
0134a210 10445 x_set_window_size (f, 0, f->width, f->height);
dc6f92b8 10446 }
a27f9f86
RS
10447 else
10448 /* If we are setting a new frame's font for the first time,
10449 there are no faces yet, so this font's height is the line height. */
7556890b 10450 f->output_data.x->line_height = FONT_HEIGHT (f->output_data.x->font);
dc6f92b8 10451
dc43ef94
KH
10452 return build_string (fontp->full_name);
10453}
10454
10455/* Give frame F the fontset named FONTSETNAME as its default font, and
10456 return the full name of that fontset. FONTSETNAME may be a wildcard
b5210ea7
KH
10457 pattern; in that case, we choose some fontset that fits the pattern.
10458 The return value shows which fontset we chose. */
b5cf7a0e 10459
dc43ef94
KH
10460Lisp_Object
10461x_new_fontset (f, fontsetname)
10462 struct frame *f;
10463 char *fontsetname;
10464{
10465 int fontset = fs_query_fontset (f, fontsetname);
10466 struct fontset_info *fontsetp;
10467 Lisp_Object result;
b5cf7a0e 10468
dc43ef94
KH
10469 if (fontset < 0)
10470 return Qnil;
b5cf7a0e 10471
2da424f1
KH
10472 if (f->output_data.x->fontset == fontset)
10473 /* This fontset is already set in frame F. There's nothing more
10474 to do. */
10475 return build_string (fontsetname);
10476
dc43ef94
KH
10477 fontsetp = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
10478
10479 if (!fontsetp->fontname[CHARSET_ASCII])
10480 /* This fontset doesn't contain ASCII font. */
10481 return Qnil;
10482
10483 result = x_new_font (f, fontsetp->fontname[CHARSET_ASCII]);
10484
10485 if (!STRINGP (result))
10486 /* Can't load ASCII font. */
10487 return Qnil;
10488
10489 /* Since x_new_font doesn't update any fontset information, do it now. */
10490 f->output_data.x->fontset = fontset;
2da424f1 10491 FS_LOAD_FONT (f, FRAME_X_FONT_TABLE (f),
715a159b 10492 CHARSET_ASCII, fontsetp->fontname[CHARSET_ASCII], fontset);
dc43ef94
KH
10493
10494 return build_string (fontsetname);
dc6f92b8 10495}
dc6f92b8 10496\f
2e365682
RS
10497/* Calculate the absolute position in frame F
10498 from its current recorded position values and gravity. */
10499
dfcf069d 10500void
43bca5d5 10501x_calc_absolute_position (f)
f676886a 10502 struct frame *f;
dc6f92b8 10503{
06a2c219 10504 Window child;
6dba1858 10505 int win_x = 0, win_y = 0;
7556890b 10506 int flags = f->output_data.x->size_hint_flags;
c81412a0
KH
10507 int this_window;
10508
9829ddba
RS
10509 /* We have nothing to do if the current position
10510 is already for the top-left corner. */
10511 if (! ((flags & XNegative) || (flags & YNegative)))
10512 return;
10513
c81412a0 10514#ifdef USE_X_TOOLKIT
7556890b 10515 this_window = XtWindow (f->output_data.x->widget);
c81412a0
KH
10516#else
10517 this_window = FRAME_X_WINDOW (f);
10518#endif
6dba1858
RS
10519
10520 /* Find the position of the outside upper-left corner of
9829ddba
RS
10521 the inner window, with respect to the outer window.
10522 But do this only if we will need the results. */
7556890b 10523 if (f->output_data.x->parent_desc != FRAME_X_DISPLAY_INFO (f)->root_window)
6dba1858 10524 {
9829ddba
RS
10525 int count;
10526
6dba1858 10527 BLOCK_INPUT;
9829ddba
RS
10528 count = x_catch_errors (FRAME_X_DISPLAY (f));
10529 while (1)
10530 {
10531 x_clear_errors (FRAME_X_DISPLAY (f));
10532 XTranslateCoordinates (FRAME_X_DISPLAY (f),
10533
10534 /* From-window, to-window. */
10535 this_window,
10536 f->output_data.x->parent_desc,
10537
10538 /* From-position, to-position. */
10539 0, 0, &win_x, &win_y,
10540
10541 /* Child of win. */
10542 &child);
10543 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
10544 {
10545 Window newroot, newparent = 0xdeadbeef;
10546 Window *newchildren;
10547 int nchildren;
10548
10549 if (! XQueryTree (FRAME_X_DISPLAY (f), this_window, &newroot,
10550 &newparent, &newchildren, &nchildren))
10551 break;
58769bee 10552
7c3c78a3 10553 XFree ((char *) newchildren);
6dba1858 10554
9829ddba
RS
10555 f->output_data.x->parent_desc = newparent;
10556 }
10557 else
10558 break;
10559 }
6dba1858 10560
9829ddba 10561 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
6dba1858
RS
10562 UNBLOCK_INPUT;
10563 }
10564
10565 /* Treat negative positions as relative to the leftmost bottommost
10566 position that fits on the screen. */
20f55f9a 10567 if (flags & XNegative)
7556890b 10568 f->output_data.x->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
2e365682
RS
10569 - 2 * f->output_data.x->border_width - win_x
10570 - PIXEL_WIDTH (f)
10571 + f->output_data.x->left_pos);
dc6f92b8 10572
20f55f9a 10573 if (flags & YNegative)
06a2c219
GM
10574 {
10575 int menubar_height = 0;
10576
10577#ifdef USE_X_TOOLKIT
10578 if (f->output_data.x->menubar_widget)
10579 menubar_height
10580 = (f->output_data.x->menubar_widget->core.height
10581 + f->output_data.x->menubar_widget->core.border_width);
10582#endif
10583
10584 f->output_data.x->top_pos = (FRAME_X_DISPLAY_INFO (f)->height
10585 - 2 * f->output_data.x->border_width
10586 - win_y
10587 - PIXEL_HEIGHT (f)
10588 - menubar_height
10589 + f->output_data.x->top_pos);
10590 }
2e365682 10591
3a35ab44
RS
10592 /* The left_pos and top_pos
10593 are now relative to the top and left screen edges,
10594 so the flags should correspond. */
7556890b 10595 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
dc6f92b8
JB
10596}
10597
3a35ab44
RS
10598/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10599 to really change the position, and 0 when calling from
10600 x_make_frame_visible (in that case, XOFF and YOFF are the current
aa3ff7c9
KH
10601 position values). It is -1 when calling from x_set_frame_parameters,
10602 which means, do adjust for borders but don't change the gravity. */
3a35ab44 10603
dfcf069d 10604void
dc05a16b 10605x_set_offset (f, xoff, yoff, change_gravity)
f676886a 10606 struct frame *f;
dc6f92b8 10607 register int xoff, yoff;
dc05a16b 10608 int change_gravity;
dc6f92b8 10609{
4a4cbdd5
KH
10610 int modified_top, modified_left;
10611
aa3ff7c9 10612 if (change_gravity > 0)
3a35ab44 10613 {
7556890b
RS
10614 f->output_data.x->top_pos = yoff;
10615 f->output_data.x->left_pos = xoff;
10616 f->output_data.x->size_hint_flags &= ~ (XNegative | YNegative);
3a35ab44 10617 if (xoff < 0)
7556890b 10618 f->output_data.x->size_hint_flags |= XNegative;
3a35ab44 10619 if (yoff < 0)
7556890b
RS
10620 f->output_data.x->size_hint_flags |= YNegative;
10621 f->output_data.x->win_gravity = NorthWestGravity;
3a35ab44 10622 }
43bca5d5 10623 x_calc_absolute_position (f);
dc6f92b8
JB
10624
10625 BLOCK_INPUT;
c32cdd9a 10626 x_wm_set_size_hint (f, (long) 0, 0);
3a35ab44 10627
7556890b
RS
10628 modified_left = f->output_data.x->left_pos;
10629 modified_top = f->output_data.x->top_pos;
e73ec6fa
RS
10630#if 0 /* Running on psilocin (Debian), and displaying on the NCD X-terminal,
10631 this seems to be unnecessary and incorrect. rms, 4/17/97. */
10632 /* It is a mystery why we need to add the border_width here
10633 when the frame is already visible, but experiment says we do. */
aa3ff7c9 10634 if (change_gravity != 0)
4a4cbdd5 10635 {
7556890b
RS
10636 modified_left += f->output_data.x->border_width;
10637 modified_top += f->output_data.x->border_width;
4a4cbdd5 10638 }
e73ec6fa 10639#endif
4a4cbdd5 10640
3afe33e7 10641#ifdef USE_X_TOOLKIT
7556890b 10642 XMoveWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
4a4cbdd5 10643 modified_left, modified_top);
3afe33e7 10644#else /* not USE_X_TOOLKIT */
334208b7 10645 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
4a4cbdd5 10646 modified_left, modified_top);
3afe33e7 10647#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
10648 UNBLOCK_INPUT;
10649}
10650
bc20ebbf
FP
10651/* Call this to change the size of frame F's x-window.
10652 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10653 for this size change and subsequent size changes.
10654 Otherwise we leave the window gravity unchanged. */
dc6f92b8 10655
dfcf069d 10656void
bc20ebbf 10657x_set_window_size (f, change_gravity, cols, rows)
f676886a 10658 struct frame *f;
bc20ebbf 10659 int change_gravity;
b1c884c3 10660 int cols, rows;
dc6f92b8 10661{
06a2c219 10662#ifndef USE_X_TOOLKIT
dc6f92b8 10663 int pixelwidth, pixelheight;
06a2c219 10664#endif
dc6f92b8 10665
80fd1fe2 10666 BLOCK_INPUT;
aee9a898
RS
10667
10668#ifdef USE_X_TOOLKIT
3a20653d
RS
10669 {
10670 /* The x and y position of the widget is clobbered by the
10671 call to XtSetValues within EmacsFrameSetCharSize.
10672 This is a real kludge, but I don't understand Xt so I can't
10673 figure out a correct fix. Can anyone else tell me? -- rms. */
7556890b
RS
10674 int xpos = f->output_data.x->widget->core.x;
10675 int ypos = f->output_data.x->widget->core.y;
10676 EmacsFrameSetCharSize (f->output_data.x->edit_widget, cols, rows);
10677 f->output_data.x->widget->core.x = xpos;
10678 f->output_data.x->widget->core.y = ypos;
3a20653d 10679 }
80fd1fe2
FP
10680
10681#else /* not USE_X_TOOLKIT */
10682
b1c884c3 10683 check_frame_size (f, &rows, &cols);
7556890b 10684 f->output_data.x->vertical_scroll_bar_extra
b2cad826
KH
10685 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10686 ? 0
10687 : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
480407eb 10688 ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
7556890b 10689 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
06a2c219
GM
10690 f->output_data.x->flags_areas_extra
10691 = 2 * FRAME_FLAGS_AREA_WIDTH (f);
f451eb13
JB
10692 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10693 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
dc6f92b8 10694
7556890b 10695 f->output_data.x->win_gravity = NorthWestGravity;
c32cdd9a 10696 x_wm_set_size_hint (f, (long) 0, 0);
6ccf47d1 10697
334208b7
RS
10698 XSync (FRAME_X_DISPLAY (f), False);
10699 XResizeWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
10700 pixelwidth, pixelheight);
b1c884c3
JB
10701
10702 /* Now, strictly speaking, we can't be sure that this is accurate,
10703 but the window manager will get around to dealing with the size
10704 change request eventually, and we'll hear how it went when the
dbc4e1c1
JB
10705 ConfigureNotify event gets here.
10706
10707 We could just not bother storing any of this information here,
10708 and let the ConfigureNotify event set everything up, but that
10709 might be kind of confusing to the lisp code, since size changes
10710 wouldn't be reported in the frame parameters until some random
10711 point in the future when the ConfigureNotify event arrives. */
8922af5f 10712 change_frame_size (f, rows, cols, 0, 0);
b1c884c3
JB
10713 PIXEL_WIDTH (f) = pixelwidth;
10714 PIXEL_HEIGHT (f) = pixelheight;
10715
aee9a898
RS
10716 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10717 receive in the ConfigureNotify event; if we get what we asked
10718 for, then the event won't cause the screen to become garbaged, so
10719 we have to make sure to do it here. */
10720 SET_FRAME_GARBAGED (f);
10721
10722 XFlush (FRAME_X_DISPLAY (f));
10723
10724#endif /* not USE_X_TOOLKIT */
10725
4d73d038 10726 /* If cursor was outside the new size, mark it as off. */
06a2c219 10727 mark_window_cursors_off (XWINDOW (f->root_window));
4d73d038 10728
aee9a898
RS
10729 /* Clear out any recollection of where the mouse highlighting was,
10730 since it might be in a place that's outside the new frame size.
10731 Actually checking whether it is outside is a pain in the neck,
10732 so don't try--just let the highlighting be done afresh with new size. */
e687d06e 10733 cancel_mouse_face (f);
dbc4e1c1 10734
dc6f92b8
JB
10735 UNBLOCK_INPUT;
10736}
dc6f92b8 10737\f
d047c4eb 10738/* Mouse warping. */
dc6f92b8 10739
9b378208 10740void
f676886a
JB
10741x_set_mouse_position (f, x, y)
10742 struct frame *f;
dc6f92b8
JB
10743 int x, y;
10744{
10745 int pix_x, pix_y;
10746
7556890b
RS
10747 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.x->font) / 2;
10748 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.x->line_height / 2;
f451eb13
JB
10749
10750 if (pix_x < 0) pix_x = 0;
10751 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10752
10753 if (pix_y < 0) pix_y = 0;
10754 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
dc6f92b8
JB
10755
10756 BLOCK_INPUT;
dc6f92b8 10757
334208b7
RS
10758 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10759 0, 0, 0, 0, pix_x, pix_y);
dc6f92b8
JB
10760 UNBLOCK_INPUT;
10761}
10762
9b378208
RS
10763/* Move the mouse to position pixel PIX_X, PIX_Y relative to frame F. */
10764
10765void
10766x_set_mouse_pixel_position (f, pix_x, pix_y)
10767 struct frame *f;
10768 int pix_x, pix_y;
10769{
10770 BLOCK_INPUT;
10771
334208b7
RS
10772 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
10773 0, 0, 0, 0, pix_x, pix_y);
9b378208
RS
10774 UNBLOCK_INPUT;
10775}
d047c4eb
KH
10776\f
10777/* focus shifting, raising and lowering. */
9b378208 10778
dfcf069d 10779void
f676886a
JB
10780x_focus_on_frame (f)
10781 struct frame *f;
dc6f92b8 10782{
1fb20991 10783#if 0 /* This proves to be unpleasant. */
f676886a 10784 x_raise_frame (f);
1fb20991 10785#endif
6d4238f3
JB
10786#if 0
10787 /* I don't think that the ICCCM allows programs to do things like this
10788 without the interaction of the window manager. Whatever you end up
f676886a 10789 doing with this code, do it to x_unfocus_frame too. */
334208b7 10790 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
dc6f92b8 10791 RevertToPointerRoot, CurrentTime);
c118dd06 10792#endif /* ! 0 */
dc6f92b8
JB
10793}
10794
dfcf069d 10795void
f676886a
JB
10796x_unfocus_frame (f)
10797 struct frame *f;
dc6f92b8 10798{
6d4238f3 10799#if 0
f676886a 10800 /* Look at the remarks in x_focus_on_frame. */
0f941935 10801 if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
334208b7 10802 XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
dc6f92b8 10803 RevertToPointerRoot, CurrentTime);
c118dd06 10804#endif /* ! 0 */
dc6f92b8
JB
10805}
10806
f676886a 10807/* Raise frame F. */
dc6f92b8 10808
dfcf069d 10809void
f676886a
JB
10810x_raise_frame (f)
10811 struct frame *f;
dc6f92b8 10812{
3a88c238 10813 if (f->async_visible)
dc6f92b8
JB
10814 {
10815 BLOCK_INPUT;
3afe33e7 10816#ifdef USE_X_TOOLKIT
7556890b 10817 XRaiseWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 10818#else /* not USE_X_TOOLKIT */
334208b7 10819 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 10820#endif /* not USE_X_TOOLKIT */
334208b7 10821 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
10822 UNBLOCK_INPUT;
10823 }
10824}
10825
f676886a 10826/* Lower frame F. */
dc6f92b8 10827
dfcf069d 10828void
f676886a
JB
10829x_lower_frame (f)
10830 struct frame *f;
dc6f92b8 10831{
3a88c238 10832 if (f->async_visible)
dc6f92b8
JB
10833 {
10834 BLOCK_INPUT;
3afe33e7 10835#ifdef USE_X_TOOLKIT
7556890b 10836 XLowerWindow (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget));
3afe33e7 10837#else /* not USE_X_TOOLKIT */
334208b7 10838 XLowerWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 10839#endif /* not USE_X_TOOLKIT */
334208b7 10840 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8
JB
10841 UNBLOCK_INPUT;
10842 }
10843}
10844
dbc4e1c1 10845static void
6b0442dc 10846XTframe_raise_lower (f, raise_flag)
dbc4e1c1 10847 FRAME_PTR f;
6b0442dc 10848 int raise_flag;
dbc4e1c1 10849{
6b0442dc 10850 if (raise_flag)
dbc4e1c1
JB
10851 x_raise_frame (f);
10852 else
10853 x_lower_frame (f);
10854}
d047c4eb
KH
10855\f
10856/* Change of visibility. */
dc6f92b8 10857
9382638d
KH
10858/* This tries to wait until the frame is really visible.
10859 However, if the window manager asks the user where to position
10860 the frame, this will return before the user finishes doing that.
10861 The frame will not actually be visible at that time,
10862 but it will become visible later when the window manager
10863 finishes with it. */
10864
dfcf069d 10865void
f676886a
JB
10866x_make_frame_visible (f)
10867 struct frame *f;
dc6f92b8 10868{
990ba854 10869 Lisp_Object type;
1aa6072f 10870 int original_top, original_left;
dc6f92b8 10871
dc6f92b8 10872 BLOCK_INPUT;
dc6f92b8 10873
990ba854
RS
10874 type = x_icon_type (f);
10875 if (!NILP (type))
10876 x_bitmap_icon (f, type);
bdcd49ba 10877
f676886a 10878 if (! FRAME_VISIBLE_P (f))
90e65f07 10879 {
1aa6072f
RS
10880 /* We test FRAME_GARBAGED_P here to make sure we don't
10881 call x_set_offset a second time
10882 if we get to x_make_frame_visible a second time
10883 before the window gets really visible. */
10884 if (! FRAME_ICONIFIED_P (f)
10885 && ! f->output_data.x->asked_for_visible)
10886 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
10887
10888 f->output_data.x->asked_for_visible = 1;
10889
90e65f07 10890 if (! EQ (Vx_no_window_manager, Qt))
f676886a 10891 x_wm_set_window_state (f, NormalState);
3afe33e7 10892#ifdef USE_X_TOOLKIT
d7a38a2e 10893 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 10894 XtMapWidget (f->output_data.x->widget);
3afe33e7 10895#else /* not USE_X_TOOLKIT */
7f9c7f94 10896 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
3afe33e7 10897#endif /* not USE_X_TOOLKIT */
0134a210
RS
10898#if 0 /* This seems to bring back scroll bars in the wrong places
10899 if the window configuration has changed. They seem
10900 to come back ok without this. */
ab648270 10901 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
334208b7 10902 XMapSubwindows (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
0134a210 10903#endif
90e65f07 10904 }
dc6f92b8 10905
334208b7 10906 XFlush (FRAME_X_DISPLAY (f));
90e65f07 10907
0dacf791
RS
10908 /* Synchronize to ensure Emacs knows the frame is visible
10909 before we do anything else. We do this loop with input not blocked
10910 so that incoming events are handled. */
10911 {
10912 Lisp_Object frame;
c0a04927 10913 int count = input_signal_count;
28c01ffe
RS
10914 /* This must be before UNBLOCK_INPUT
10915 since events that arrive in response to the actions above
10916 will set it when they are handled. */
10917 int previously_visible = f->output_data.x->has_been_visible;
1aa6072f
RS
10918
10919 original_left = f->output_data.x->left_pos;
10920 original_top = f->output_data.x->top_pos;
c0a04927
RS
10921
10922 /* This must come after we set COUNT. */
10923 UNBLOCK_INPUT;
10924
2745e6c4 10925 /* We unblock here so that arriving X events are processed. */
1aa6072f 10926
dcb07ae9
RS
10927 /* Now move the window back to where it was "supposed to be".
10928 But don't do it if the gravity is negative.
10929 When the gravity is negative, this uses a position
28c01ffe
RS
10930 that is 3 pixels too low. Perhaps that's really the border width.
10931
10932 Don't do this if the window has never been visible before,
10933 because the window manager may choose the position
10934 and we don't want to override it. */
1aa6072f 10935
4d3f5d9a 10936 if (! FRAME_VISIBLE_P (f) && ! FRAME_ICONIFIED_P (f)
06c488fd 10937 && f->output_data.x->win_gravity == NorthWestGravity
28c01ffe 10938 && previously_visible)
1aa6072f 10939 {
2745e6c4
RS
10940 Drawable rootw;
10941 int x, y;
10942 unsigned int width, height, border, depth;
06a2c219 10943
1aa6072f 10944 BLOCK_INPUT;
9829ddba 10945
06a2c219
GM
10946 /* On some window managers (such as FVWM) moving an existing
10947 window, even to the same place, causes the window manager
10948 to introduce an offset. This can cause the window to move
10949 to an unexpected location. Check the geometry (a little
10950 slow here) and then verify that the window is in the right
10951 place. If the window is not in the right place, move it
10952 there, and take the potential window manager hit. */
2745e6c4
RS
10953 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10954 &rootw, &x, &y, &width, &height, &border, &depth);
10955
10956 if (original_left != x || original_top != y)
10957 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10958 original_left, original_top);
10959
1aa6072f
RS
10960 UNBLOCK_INPUT;
10961 }
9829ddba 10962
e0c1aef2 10963 XSETFRAME (frame, f);
c0a04927
RS
10964
10965 while (1)
2a6cf806 10966 {
334208b7 10967 x_sync (f);
c0a04927
RS
10968 /* Once we have handled input events,
10969 we should have received the MapNotify if one is coming.
10970 So if we have not got it yet, stop looping.
10971 Some window managers make their own decisions
10972 about visibility. */
10973 if (input_signal_count != count)
10974 break;
c12a7cbd 10975 /* Machines that do polling rather than SIGIO have been observed
23cf7c60
KH
10976 to go into a busy-wait here. So we'll fake an alarm signal
10977 to let the handler know that there's something to be read.
10978 We used to raise a real alarm, but it seems that the handler
10979 isn't always enabled here. This is probably a bug. */
8b2f8d4e 10980 if (input_polling_used ())
3b2fa4e6
RS
10981 {
10982 /* It could be confusing if a real alarm arrives while processing
10983 the fake one. Turn it off and let the handler reset it. */
10984 alarm (0);
5e8e68ce 10985 input_poll_signal (0);
3b2fa4e6 10986 }
c0a04927
RS
10987 /* Once we have handled input events,
10988 we should have received the MapNotify if one is coming.
10989 So if we have not got it yet, stop looping.
10990 Some window managers make their own decisions
10991 about visibility. */
10992 if (input_signal_count != count)
10993 break;
2a6cf806 10994 }
0dacf791
RS
10995 FRAME_SAMPLE_VISIBILITY (f);
10996 }
dc6f92b8
JB
10997}
10998
06a2c219 10999/* Change from mapped state to withdrawn state. */
dc6f92b8 11000
d047c4eb
KH
11001/* Make the frame visible (mapped and not iconified). */
11002
dfcf069d 11003void
f676886a
JB
11004x_make_frame_invisible (f)
11005 struct frame *f;
dc6f92b8 11006{
546e6d5b
RS
11007 Window window;
11008
11009#ifdef USE_X_TOOLKIT
11010 /* Use the frame's outermost window, not the one we normally draw on. */
7556890b 11011 window = XtWindow (f->output_data.x->widget);
546e6d5b
RS
11012#else /* not USE_X_TOOLKIT */
11013 window = FRAME_X_WINDOW (f);
11014#endif /* not USE_X_TOOLKIT */
dc6f92b8 11015
9319ae23 11016 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11017 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11018 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11019
5627c40e 11020#if 0/* This might add unreliability; I don't trust it -- rms. */
9319ae23 11021 if (! f->async_visible && ! f->async_iconified)
dc6f92b8 11022 return;
5627c40e 11023#endif
dc6f92b8
JB
11024
11025 BLOCK_INPUT;
c118dd06 11026
af31d76f
RS
11027 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
11028 that the current position of the window is user-specified, rather than
11029 program-specified, so that when the window is mapped again, it will be
11030 placed at the same location, without forcing the user to position it
11031 by hand again (they have already done that once for this window.) */
c32cdd9a 11032 x_wm_set_size_hint (f, (long) 0, 1);
af31d76f 11033
c118dd06
JB
11034#ifdef HAVE_X11R4
11035
334208b7
RS
11036 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11037 DefaultScreen (FRAME_X_DISPLAY (f))))
c118dd06
JB
11038 {
11039 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11040 error ("Can't notify window manager of window withdrawal");
c118dd06 11041 }
c118dd06 11042#else /* ! defined (HAVE_X11R4) */
16bd92ea 11043
c118dd06 11044 /* Tell the window manager what we're going to do. */
dc6f92b8
JB
11045 if (! EQ (Vx_no_window_manager, Qt))
11046 {
16bd92ea 11047 XEvent unmap;
dc6f92b8 11048
16bd92ea 11049 unmap.xunmap.type = UnmapNotify;
546e6d5b 11050 unmap.xunmap.window = window;
334208b7 11051 unmap.xunmap.event = DefaultRootWindow (FRAME_X_DISPLAY (f));
16bd92ea 11052 unmap.xunmap.from_configure = False;
334208b7
RS
11053 if (! XSendEvent (FRAME_X_DISPLAY (f),
11054 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea 11055 False,
06a2c219 11056 SubstructureRedirectMaskSubstructureNotifyMask,
16bd92ea
JB
11057 &unmap))
11058 {
11059 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11060 error ("Can't notify window manager of withdrawal");
16bd92ea 11061 }
dc6f92b8
JB
11062 }
11063
16bd92ea 11064 /* Unmap the window ourselves. Cheeky! */
334208b7 11065 XUnmapWindow (FRAME_X_DISPLAY (f), window);
c118dd06 11066#endif /* ! defined (HAVE_X11R4) */
dc6f92b8 11067
5627c40e
RS
11068 /* We can't distinguish this from iconification
11069 just by the event that we get from the server.
11070 So we can't win using the usual strategy of letting
11071 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
11072 and synchronize with the server to make sure we agree. */
11073 f->visible = 0;
11074 FRAME_ICONIFIED_P (f) = 0;
11075 f->async_visible = 0;
11076 f->async_iconified = 0;
11077
334208b7 11078 x_sync (f);
5627c40e 11079
dc6f92b8
JB
11080 UNBLOCK_INPUT;
11081}
11082
06a2c219 11083/* Change window state from mapped to iconified. */
dc6f92b8 11084
dfcf069d 11085void
f676886a
JB
11086x_iconify_frame (f)
11087 struct frame *f;
dc6f92b8 11088{
3afe33e7 11089 int result;
990ba854 11090 Lisp_Object type;
dc6f92b8 11091
9319ae23 11092 /* Don't keep the highlight on an invisible frame. */
0f941935
KH
11093 if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
11094 FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
9319ae23 11095
3a88c238 11096 if (f->async_iconified)
dc6f92b8
JB
11097 return;
11098
3afe33e7 11099 BLOCK_INPUT;
546e6d5b 11100
9af3143a
RS
11101 FRAME_SAMPLE_VISIBILITY (f);
11102
990ba854
RS
11103 type = x_icon_type (f);
11104 if (!NILP (type))
11105 x_bitmap_icon (f, type);
bdcd49ba
RS
11106
11107#ifdef USE_X_TOOLKIT
11108
546e6d5b
RS
11109 if (! FRAME_VISIBLE_P (f))
11110 {
11111 if (! EQ (Vx_no_window_manager, Qt))
11112 x_wm_set_window_state (f, IconicState);
11113 /* This was XtPopup, but that did nothing for an iconified frame. */
7556890b 11114 XtMapWidget (f->output_data.x->widget);
9cf30a30
RS
11115 /* The server won't give us any event to indicate
11116 that an invisible frame was changed to an icon,
11117 so we have to record it here. */
11118 f->iconified = 1;
1e6bc770 11119 f->visible = 1;
9cf30a30 11120 f->async_iconified = 1;
1e6bc770 11121 f->async_visible = 0;
546e6d5b
RS
11122 UNBLOCK_INPUT;
11123 return;
11124 }
11125
334208b7 11126 result = XIconifyWindow (FRAME_X_DISPLAY (f),
7556890b 11127 XtWindow (f->output_data.x->widget),
334208b7 11128 DefaultScreen (FRAME_X_DISPLAY (f)));
3afe33e7
RS
11129 UNBLOCK_INPUT;
11130
11131 if (!result)
546e6d5b 11132 error ("Can't notify window manager of iconification");
3afe33e7
RS
11133
11134 f->async_iconified = 1;
1e6bc770
RS
11135 f->async_visible = 0;
11136
8c002a25
KH
11137
11138 BLOCK_INPUT;
334208b7 11139 XFlush (FRAME_X_DISPLAY (f));
8c002a25 11140 UNBLOCK_INPUT;
3afe33e7
RS
11141#else /* not USE_X_TOOLKIT */
11142
fd13dbb2
RS
11143 /* Make sure the X server knows where the window should be positioned,
11144 in case the user deiconifies with the window manager. */
11145 if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
7556890b 11146 x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
fd13dbb2 11147
16bd92ea
JB
11148 /* Since we don't know which revision of X we're running, we'll use both
11149 the X11R3 and X11R4 techniques. I don't know if this is a good idea. */
11150
11151 /* X11R4: send a ClientMessage to the window manager using the
11152 WM_CHANGE_STATE type. */
11153 {
11154 XEvent message;
58769bee 11155
c118dd06 11156 message.xclient.window = FRAME_X_WINDOW (f);
16bd92ea 11157 message.xclient.type = ClientMessage;
334208b7 11158 message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
16bd92ea
JB
11159 message.xclient.format = 32;
11160 message.xclient.data.l[0] = IconicState;
11161
334208b7
RS
11162 if (! XSendEvent (FRAME_X_DISPLAY (f),
11163 DefaultRootWindow (FRAME_X_DISPLAY (f)),
16bd92ea
JB
11164 False,
11165 SubstructureRedirectMask | SubstructureNotifyMask,
11166 &message))
dc6f92b8
JB
11167 {
11168 UNBLOCK_INPUT_RESIGNAL;
546e6d5b 11169 error ("Can't notify window manager of iconification");
dc6f92b8 11170 }
16bd92ea 11171 }
dc6f92b8 11172
58769bee 11173 /* X11R3: set the initial_state field of the window manager hints to
16bd92ea
JB
11174 IconicState. */
11175 x_wm_set_window_state (f, IconicState);
dc6f92b8 11176
a9c00105
RS
11177 if (!FRAME_VISIBLE_P (f))
11178 {
11179 /* If the frame was withdrawn, before, we must map it. */
7f9c7f94 11180 XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
a9c00105
RS
11181 }
11182
3a88c238 11183 f->async_iconified = 1;
1e6bc770 11184 f->async_visible = 0;
dc6f92b8 11185
334208b7 11186 XFlush (FRAME_X_DISPLAY (f));
dc6f92b8 11187 UNBLOCK_INPUT;
8c002a25 11188#endif /* not USE_X_TOOLKIT */
dc6f92b8 11189}
d047c4eb 11190\f
c0ff3fab 11191/* Destroy the X window of frame F. */
dc6f92b8 11192
dfcf069d 11193void
c0ff3fab 11194x_destroy_window (f)
f676886a 11195 struct frame *f;
dc6f92b8 11196{
7f9c7f94
RS
11197 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11198
dc6f92b8 11199 BLOCK_INPUT;
c0ff3fab 11200
6186a4a0
RS
11201 /* If a display connection is dead, don't try sending more
11202 commands to the X server. */
11203 if (dpyinfo->display != 0)
11204 {
11205 if (f->output_data.x->icon_desc != 0)
11206 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->icon_desc);
31f41daf
RS
11207#ifdef HAVE_X_I18N
11208 if (FRAME_XIM (f))
11209 {
11210 XDestroyIC (FRAME_XIC (f));
408be661
RS
11211#if ! defined (SOLARIS2) || defined (HAVE_X11R6)
11212 /* This line causes crashes on Solaris with Openwin,
11213 due to an apparent bug in XCloseIM.
11214 X11R6 seems not to have the bug. */
31f41daf 11215 XCloseIM (FRAME_XIM (f));
a9978dd8 11216#endif
31f41daf
RS
11217 }
11218#endif
6186a4a0 11219 XDestroyWindow (FRAME_X_DISPLAY (f), f->output_data.x->window_desc);
3afe33e7 11220#ifdef USE_X_TOOLKIT
06a2c219
GM
11221 if (f->output_data.x->widget)
11222 XtDestroyWidget (f->output_data.x->widget);
6186a4a0 11223 free_frame_menubar (f);
3afe33e7
RS
11224#endif /* USE_X_TOOLKIT */
11225
6186a4a0
RS
11226 free_frame_faces (f);
11227 XFlush (FRAME_X_DISPLAY (f));
11228 }
dc6f92b8 11229
df89d8a4 11230 if (f->output_data.x->saved_menu_event)
06a2c219 11231 xfree (f->output_data.x->saved_menu_event);
0c49ce2f 11232
7556890b
RS
11233 xfree (f->output_data.x);
11234 f->output_data.x = 0;
0f941935
KH
11235 if (f == dpyinfo->x_focus_frame)
11236 dpyinfo->x_focus_frame = 0;
11237 if (f == dpyinfo->x_focus_event_frame)
11238 dpyinfo->x_focus_event_frame = 0;
11239 if (f == dpyinfo->x_highlight_frame)
11240 dpyinfo->x_highlight_frame = 0;
c0ff3fab 11241
7f9c7f94
RS
11242 dpyinfo->reference_count--;
11243
11244 if (f == dpyinfo->mouse_face_mouse_frame)
dc05a16b 11245 {
7f9c7f94
RS
11246 dpyinfo->mouse_face_beg_row
11247 = dpyinfo->mouse_face_beg_col = -1;
11248 dpyinfo->mouse_face_end_row
11249 = dpyinfo->mouse_face_end_col = -1;
11250 dpyinfo->mouse_face_window = Qnil;
21323706
RS
11251 dpyinfo->mouse_face_deferred_gc = 0;
11252 dpyinfo->mouse_face_mouse_frame = 0;
dc05a16b 11253 }
0134a210 11254
c0ff3fab 11255 UNBLOCK_INPUT;
dc6f92b8
JB
11256}
11257\f
f451eb13
JB
11258/* Setting window manager hints. */
11259
af31d76f
RS
11260/* Set the normal size hints for the window manager, for frame F.
11261 FLAGS is the flags word to use--or 0 meaning preserve the flags
11262 that the window now has.
11263 If USER_POSITION is nonzero, we set the USPosition
11264 flag (this is useful when FLAGS is 0). */
6dba1858 11265
dfcf069d 11266void
af31d76f 11267x_wm_set_size_hint (f, flags, user_position)
f676886a 11268 struct frame *f;
af31d76f
RS
11269 long flags;
11270 int user_position;
dc6f92b8
JB
11271{
11272 XSizeHints size_hints;
3afe33e7
RS
11273
11274#ifdef USE_X_TOOLKIT
7e4f2521
FP
11275 Arg al[2];
11276 int ac = 0;
11277 Dimension widget_width, widget_height;
7556890b 11278 Window window = XtWindow (f->output_data.x->widget);
3afe33e7 11279#else /* not USE_X_TOOLKIT */
c118dd06 11280 Window window = FRAME_X_WINDOW (f);
3afe33e7 11281#endif /* not USE_X_TOOLKIT */
dc6f92b8 11282
b72a58fd
RS
11283 /* Setting PMaxSize caused various problems. */
11284 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
dc6f92b8 11285
7556890b
RS
11286 size_hints.x = f->output_data.x->left_pos;
11287 size_hints.y = f->output_data.x->top_pos;
7553a6b7 11288
7e4f2521
FP
11289#ifdef USE_X_TOOLKIT
11290 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
11291 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
7556890b 11292 XtGetValues (f->output_data.x->widget, al, ac);
7e4f2521
FP
11293 size_hints.height = widget_height;
11294 size_hints.width = widget_width;
11295#else /* not USE_X_TOOLKIT */
f676886a
JB
11296 size_hints.height = PIXEL_HEIGHT (f);
11297 size_hints.width = PIXEL_WIDTH (f);
7e4f2521 11298#endif /* not USE_X_TOOLKIT */
7553a6b7 11299
7556890b
RS
11300 size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
11301 size_hints.height_inc = f->output_data.x->line_height;
334208b7
RS
11302 size_hints.max_width
11303 = FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
11304 size_hints.max_height
11305 = FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
0134a210 11306
d067ea8b
KH
11307 /* Calculate the base and minimum sizes.
11308
11309 (When we use the X toolkit, we don't do it here.
11310 Instead we copy the values that the widgets are using, below.) */
11311#ifndef USE_X_TOOLKIT
b1c884c3 11312 {
b0342f17 11313 int base_width, base_height;
0134a210 11314 int min_rows = 0, min_cols = 0;
b0342f17 11315
f451eb13
JB
11316 base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
11317 base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
b0342f17 11318
0134a210 11319 check_frame_size (f, &min_rows, &min_cols);
b0342f17 11320
0134a210
RS
11321 /* The window manager uses the base width hints to calculate the
11322 current number of rows and columns in the frame while
11323 resizing; min_width and min_height aren't useful for this
11324 purpose, since they might not give the dimensions for a
11325 zero-row, zero-column frame.
58769bee 11326
0134a210
RS
11327 We use the base_width and base_height members if we have
11328 them; otherwise, we set the min_width and min_height members
11329 to the size for a zero x zero frame. */
b0342f17
JB
11330
11331#ifdef HAVE_X11R4
0134a210
RS
11332 size_hints.flags |= PBaseSize;
11333 size_hints.base_width = base_width;
11334 size_hints.base_height = base_height;
11335 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
11336 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
b0342f17 11337#else
0134a210
RS
11338 size_hints.min_width = base_width;
11339 size_hints.min_height = base_height;
b0342f17 11340#endif
b1c884c3 11341 }
dc6f92b8 11342
d067ea8b 11343 /* If we don't need the old flags, we don't need the old hint at all. */
af31d76f 11344 if (flags)
dc6f92b8 11345 {
d067ea8b
KH
11346 size_hints.flags |= flags;
11347 goto no_read;
11348 }
11349#endif /* not USE_X_TOOLKIT */
11350
11351 {
11352 XSizeHints hints; /* Sometimes I hate X Windows... */
11353 long supplied_return;
11354 int value;
af31d76f
RS
11355
11356#ifdef HAVE_X11R4
d067ea8b
KH
11357 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
11358 &supplied_return);
af31d76f 11359#else
d067ea8b 11360 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
af31d76f 11361#endif
58769bee 11362
d067ea8b
KH
11363#ifdef USE_X_TOOLKIT
11364 size_hints.base_height = hints.base_height;
11365 size_hints.base_width = hints.base_width;
11366 size_hints.min_height = hints.min_height;
11367 size_hints.min_width = hints.min_width;
11368#endif
11369
11370 if (flags)
11371 size_hints.flags |= flags;
11372 else
11373 {
11374 if (value == 0)
11375 hints.flags = 0;
11376 if (hints.flags & PSize)
11377 size_hints.flags |= PSize;
11378 if (hints.flags & PPosition)
11379 size_hints.flags |= PPosition;
11380 if (hints.flags & USPosition)
11381 size_hints.flags |= USPosition;
11382 if (hints.flags & USSize)
11383 size_hints.flags |= USSize;
11384 }
11385 }
11386
06a2c219 11387#ifndef USE_X_TOOLKIT
d067ea8b 11388 no_read:
06a2c219 11389#endif
0134a210 11390
af31d76f 11391#ifdef PWinGravity
7556890b 11392 size_hints.win_gravity = f->output_data.x->win_gravity;
af31d76f 11393 size_hints.flags |= PWinGravity;
dc05a16b 11394
af31d76f 11395 if (user_position)
6dba1858 11396 {
af31d76f
RS
11397 size_hints.flags &= ~ PPosition;
11398 size_hints.flags |= USPosition;
6dba1858 11399 }
2554751d 11400#endif /* PWinGravity */
6dba1858 11401
b0342f17 11402#ifdef HAVE_X11R4
334208b7 11403 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 11404#else
334208b7 11405 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
b0342f17 11406#endif
dc6f92b8
JB
11407}
11408
11409/* Used for IconicState or NormalState */
06a2c219 11410
dfcf069d 11411void
f676886a
JB
11412x_wm_set_window_state (f, state)
11413 struct frame *f;
dc6f92b8
JB
11414 int state;
11415{
3afe33e7 11416#ifdef USE_X_TOOLKIT
546e6d5b
RS
11417 Arg al[1];
11418
11419 XtSetArg (al[0], XtNinitialState, state);
7556890b 11420 XtSetValues (f->output_data.x->widget, al, 1);
3afe33e7 11421#else /* not USE_X_TOOLKIT */
c118dd06 11422 Window window = FRAME_X_WINDOW (f);
dc6f92b8 11423
7556890b
RS
11424 f->output_data.x->wm_hints.flags |= StateHint;
11425 f->output_data.x->wm_hints.initial_state = state;
b1c884c3 11426
7556890b 11427 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
546e6d5b 11428#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11429}
11430
dfcf069d 11431void
7f2ae036 11432x_wm_set_icon_pixmap (f, pixmap_id)
f676886a 11433 struct frame *f;
7f2ae036 11434 int pixmap_id;
dc6f92b8 11435{
d2bd6bc4
RS
11436 Pixmap icon_pixmap;
11437
06a2c219 11438#ifndef USE_X_TOOLKIT
c118dd06 11439 Window window = FRAME_X_WINDOW (f);
75231bad 11440#endif
dc6f92b8 11441
7f2ae036 11442 if (pixmap_id > 0)
dbc4e1c1 11443 {
d2bd6bc4 11444 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
7556890b 11445 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
dbc4e1c1
JB
11446 }
11447 else
68568555
RS
11448 {
11449 /* It seems there is no way to turn off use of an icon pixmap.
11450 The following line does it, only if no icon has yet been created,
11451 for some window managers. But with mwm it crashes.
11452 Some people say it should clear the IconPixmapHint bit in this case,
11453 but that doesn't work, and the X consortium said it isn't the
11454 right thing at all. Since there is no way to win,
11455 best to explicitly give up. */
11456#if 0
11457 f->output_data.x->wm_hints.icon_pixmap = None;
11458#else
11459 return;
11460#endif
11461 }
b1c884c3 11462
d2bd6bc4
RS
11463#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
11464
11465 {
11466 Arg al[1];
11467 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
11468 XtSetValues (f->output_data.x->widget, al, 1);
11469 }
11470
11471#else /* not USE_X_TOOLKIT */
11472
7556890b
RS
11473 f->output_data.x->wm_hints.flags |= IconPixmapHint;
11474 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
d2bd6bc4
RS
11475
11476#endif /* not USE_X_TOOLKIT */
dc6f92b8
JB
11477}
11478
dfcf069d 11479void
f676886a
JB
11480x_wm_set_icon_position (f, icon_x, icon_y)
11481 struct frame *f;
dc6f92b8
JB
11482 int icon_x, icon_y;
11483{
75231bad 11484#ifdef USE_X_TOOLKIT
7556890b 11485 Window window = XtWindow (f->output_data.x->widget);
75231bad 11486#else
c118dd06 11487 Window window = FRAME_X_WINDOW (f);
75231bad 11488#endif
dc6f92b8 11489
7556890b
RS
11490 f->output_data.x->wm_hints.flags |= IconPositionHint;
11491 f->output_data.x->wm_hints.icon_x = icon_x;
11492 f->output_data.x->wm_hints.icon_y = icon_y;
b1c884c3 11493
7556890b 11494 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
dc6f92b8
JB
11495}
11496
11497\f
06a2c219
GM
11498/***********************************************************************
11499 Fonts
11500 ***********************************************************************/
dc43ef94
KH
11501
11502/* Return a pointer to struct font_info of font FONT_IDX of frame F. */
06a2c219 11503
dc43ef94
KH
11504struct font_info *
11505x_get_font_info (f, font_idx)
11506 FRAME_PTR f;
11507 int font_idx;
11508{
11509 return (FRAME_X_FONT_TABLE (f) + font_idx);
11510}
11511
11512
11513/* Return a list of names of available fonts matching PATTERN on frame
11514 F. If SIZE is not 0, it is the size (maximum bound width) of fonts
11515 to be listed. Frame F NULL means we have not yet created any
11516 frame on X, and consult the first display in x_display_list.
11517 MAXNAMES sets a limit on how many fonts to match. */
11518
11519Lisp_Object
11520x_list_fonts (f, pattern, size, maxnames)
11521 FRAME_PTR f;
11522 Lisp_Object pattern;
11523 int size;
11524 int maxnames;
11525{
06a2c219
GM
11526 Lisp_Object list = Qnil, patterns, newlist = Qnil, key = Qnil;
11527 Lisp_Object tem, second_best;
dc43ef94 11528 Display *dpy = f != NULL ? FRAME_X_DISPLAY (f) : x_display_list->display;
09c6077f 11529 int try_XLoadQueryFont = 0;
53ca4657 11530 int count;
dc43ef94 11531
6b0efe73 11532 patterns = Fassoc (pattern, Valternate_fontname_alist);
2da424f1
KH
11533 if (NILP (patterns))
11534 patterns = Fcons (pattern, Qnil);
81ba44e5 11535
09c6077f
KH
11536 if (maxnames == 1 && !size)
11537 /* We can return any single font matching PATTERN. */
11538 try_XLoadQueryFont = 1;
9a32686f 11539
2da424f1 11540 for (; CONSP (patterns); patterns = XCONS (patterns)->cdr)
dc43ef94 11541 {
dc43ef94
KH
11542 int num_fonts;
11543 char **names;
11544
2da424f1 11545 pattern = XCONS (patterns)->car;
536f4067
RS
11546 /* See if we cached the result for this particular query.
11547 The cache is an alist of the form:
11548 (((PATTERN . MAXNAMES) (FONTNAME . WIDTH) ...) ...)
11549 */
b5210ea7
KH
11550 if (f && (tem = XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr,
11551 key = Fcons (pattern, make_number (maxnames)),
11552 !NILP (list = Fassoc (key, tem))))
11553 {
11554 list = Fcdr_safe (list);
11555 /* We have a cashed list. Don't have to get the list again. */
11556 goto label_cached;
11557 }
11558
11559 /* At first, put PATTERN in the cache. */
09c6077f 11560
dc43ef94 11561 BLOCK_INPUT;
17d85edc
KH
11562 count = x_catch_errors (dpy);
11563
09c6077f
KH
11564 if (try_XLoadQueryFont)
11565 {
11566 XFontStruct *font;
11567 unsigned long value;
11568
11569 font = XLoadQueryFont (dpy, XSTRING (pattern)->data);
17d85edc
KH
11570 if (x_had_errors_p (dpy))
11571 {
11572 /* This error is perhaps due to insufficient memory on X
11573 server. Let's just ignore it. */
11574 font = NULL;
11575 x_clear_errors (dpy);
11576 }
11577
09c6077f
KH
11578 if (font
11579 && XGetFontProperty (font, XA_FONT, &value))
11580 {
11581 char *name = (char *) XGetAtomName (dpy, (Atom) value);
11582 int len = strlen (name);
01c752b5 11583 char *tmp;
09c6077f 11584
6f6512e8
KH
11585 /* If DXPC (a Differential X Protocol Compressor)
11586 Ver.3.7 is running, XGetAtomName will return null
11587 string. We must avoid such a name. */
11588 if (len == 0)
11589 try_XLoadQueryFont = 0;
11590 else
11591 {
11592 num_fonts = 1;
11593 names = (char **) alloca (sizeof (char *));
11594 /* Some systems only allow alloca assigned to a
11595 simple var. */
11596 tmp = (char *) alloca (len + 1); names[0] = tmp;
11597 bcopy (name, names[0], len + 1);
11598 XFree (name);
11599 }
09c6077f
KH
11600 }
11601 else
11602 try_XLoadQueryFont = 0;
a083fd23
RS
11603
11604 if (font)
11605 XFreeFont (dpy, font);
09c6077f
KH
11606 }
11607
11608 if (!try_XLoadQueryFont)
17d85edc
KH
11609 {
11610 /* We try at least 10 fonts because XListFonts will return
11611 auto-scaled fonts at the head. */
11612 names = XListFonts (dpy, XSTRING (pattern)->data, max (maxnames, 10),
11613 &num_fonts);
11614 if (x_had_errors_p (dpy))
11615 {
11616 /* This error is perhaps due to insufficient memory on X
11617 server. Let's just ignore it. */
11618 names = NULL;
11619 x_clear_errors (dpy);
11620 }
11621 }
11622
11623 x_uncatch_errors (dpy, count);
dc43ef94
KH
11624 UNBLOCK_INPUT;
11625
11626 if (names)
11627 {
11628 int i;
dc43ef94
KH
11629
11630 /* Make a list of all the fonts we got back.
11631 Store that in the font cache for the display. */
11632 for (i = 0; i < num_fonts; i++)
11633 {
06a2c219 11634 int width = 0;
dc43ef94 11635 char *p = names[i];
06a2c219
GM
11636 int average_width = -1, dashes = 0;
11637
dc43ef94 11638 /* Count the number of dashes in NAMES[I]. If there are
b5210ea7
KH
11639 14 dashes, and the field value following 12th dash
11640 (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
11641 is usually too ugly to be used for editing. Let's
11642 ignore it. */
dc43ef94
KH
11643 while (*p)
11644 if (*p++ == '-')
11645 {
11646 dashes++;
11647 if (dashes == 7) /* PIXEL_SIZE field */
11648 width = atoi (p);
11649 else if (dashes == 12) /* AVERAGE_WIDTH field */
11650 average_width = atoi (p);
11651 }
11652 if (dashes < 14 || average_width != 0)
11653 {
11654 tem = build_string (names[i]);
11655 if (NILP (Fassoc (tem, list)))
11656 {
11657 if (STRINGP (Vx_pixel_size_width_font_regexp)
f39db7ea
RS
11658 && ((fast_c_string_match_ignore_case
11659 (Vx_pixel_size_width_font_regexp, names[i]))
dc43ef94
KH
11660 >= 0))
11661 /* We can set the value of PIXEL_SIZE to the
b5210ea7 11662 width of this font. */
dc43ef94
KH
11663 list = Fcons (Fcons (tem, make_number (width)), list);
11664 else
11665 /* For the moment, width is not known. */
11666 list = Fcons (Fcons (tem, Qnil), list);
11667 }
11668 }
11669 }
09c6077f
KH
11670 if (!try_XLoadQueryFont)
11671 XFreeFontNames (names);
dc43ef94
KH
11672 }
11673
b5210ea7 11674 /* Now store the result in the cache. */
dc43ef94
KH
11675 if (f != NULL)
11676 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr
11677 = Fcons (Fcons (key, list),
11678 XCONS (FRAME_X_DISPLAY_INFO (f)->name_list_element)->cdr);
dc43ef94 11679
b5210ea7
KH
11680 label_cached:
11681 if (NILP (list)) continue; /* Try the remaining alternatives. */
dc43ef94 11682
b5210ea7
KH
11683 newlist = second_best = Qnil;
11684 /* Make a list of the fonts that have the right width. */
11685 for (; CONSP (list); list = XCONS (list)->cdr)
11686 {
536f4067
RS
11687 int found_size;
11688
b5210ea7 11689 tem = XCONS (list)->car;
dc43ef94 11690
b5210ea7
KH
11691 if (!CONSP (tem) || NILP (XCONS (tem)->car))
11692 continue;
11693 if (!size)
11694 {
11695 newlist = Fcons (XCONS (tem)->car, newlist);
11696 continue;
11697 }
dc43ef94 11698
dc43ef94
KH
11699 if (!INTEGERP (XCONS (tem)->cdr))
11700 {
b5210ea7
KH
11701 /* Since we have not yet known the size of this font, we
11702 must try slow function call XLoadQueryFont. */
dc43ef94
KH
11703 XFontStruct *thisinfo;
11704
11705 BLOCK_INPUT;
17d85edc 11706 count = x_catch_errors (dpy);
dc43ef94
KH
11707 thisinfo = XLoadQueryFont (dpy,
11708 XSTRING (XCONS (tem)->car)->data);
17d85edc
KH
11709 if (x_had_errors_p (dpy))
11710 {
11711 /* This error is perhaps due to insufficient memory on X
11712 server. Let's just ignore it. */
11713 thisinfo = NULL;
11714 x_clear_errors (dpy);
11715 }
11716 x_uncatch_errors (dpy, count);
dc43ef94
KH
11717 UNBLOCK_INPUT;
11718
11719 if (thisinfo)
11720 {
536f4067
RS
11721 XCONS (tem)->cdr
11722 = (thisinfo->min_bounds.width == 0
11723 ? make_number (0)
11724 : make_number (thisinfo->max_bounds.width));
dc43ef94
KH
11725 XFreeFont (dpy, thisinfo);
11726 }
11727 else
b5210ea7 11728 /* For unknown reason, the previous call of XListFont had
06a2c219 11729 returned a font which can't be opened. Record the size
b5210ea7 11730 as 0 not to try to open it again. */
dc43ef94
KH
11731 XCONS (tem)->cdr = make_number (0);
11732 }
536f4067
RS
11733
11734 found_size = XINT (XCONS (tem)->cdr);
11735 if (found_size == size)
b5210ea7 11736 newlist = Fcons (XCONS (tem)->car, newlist);
536f4067 11737 else if (found_size > 0)
b5210ea7 11738 {
536f4067 11739 if (NILP (second_best))
b5210ea7 11740 second_best = tem;
536f4067
RS
11741 else if (found_size < size)
11742 {
11743 if (XINT (XCONS (second_best)->cdr) > size
11744 || XINT (XCONS (second_best)->cdr) < found_size)
11745 second_best = tem;
11746 }
11747 else
11748 {
11749 if (XINT (XCONS (second_best)->cdr) > size
11750 && XINT (XCONS (second_best)->cdr) > found_size)
11751 second_best = tem;
11752 }
b5210ea7
KH
11753 }
11754 }
11755 if (!NILP (newlist))
11756 break;
11757 else if (!NILP (second_best))
11758 {
11759 newlist = Fcons (XCONS (second_best)->car, Qnil);
11760 break;
dc43ef94 11761 }
dc43ef94
KH
11762 }
11763
11764 return newlist;
11765}
11766
06a2c219
GM
11767
11768#if GLYPH_DEBUG
11769
11770/* Check that FONT is valid on frame F. It is if it can be found in F's
11771 font table. */
11772
11773static void
11774x_check_font (f, font)
11775 struct frame *f;
11776 XFontStruct *font;
11777{
11778 int i;
11779 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11780
11781 xassert (font != NULL);
11782
11783 for (i = 0; i < dpyinfo->n_fonts; i++)
11784 if (dpyinfo->font_table[i].name
11785 && font == dpyinfo->font_table[i].font)
11786 break;
11787
11788 xassert (i < dpyinfo->n_fonts);
11789}
11790
11791#endif /* GLYPH_DEBUG != 0 */
11792
11793/* Set *W to the minimum width, *H to the minimum font height of FONT.
11794 Note: There are (broken) X fonts out there with invalid XFontStruct
11795 min_bounds contents. For example, handa@etl.go.jp reports that
11796 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
11797 have font->min_bounds.width == 0. */
11798
11799static INLINE void
11800x_font_min_bounds (font, w, h)
11801 XFontStruct *font;
11802 int *w, *h;
11803{
11804 *h = FONT_HEIGHT (font);
11805 *w = font->min_bounds.width;
11806
11807 /* Try to handle the case where FONT->min_bounds has invalid
11808 contents. Since the only font known to have invalid min_bounds
11809 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
11810 if (*w <= 0)
11811 *w = font->max_bounds.width;
11812}
11813
11814
11815/* Compute the smallest character width and smallest font height over
11816 all fonts available on frame F. Set the members smallest_char_width
11817 and smallest_font_height in F's x_display_info structure to
11818 the values computed. Value is non-zero if smallest_font_height or
11819 smallest_char_width become smaller than they were before. */
11820
11821static int
11822x_compute_min_glyph_bounds (f)
11823 struct frame *f;
11824{
11825 int i;
11826 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11827 XFontStruct *font;
11828 int old_width = dpyinfo->smallest_char_width;
11829 int old_height = dpyinfo->smallest_font_height;
11830
11831 dpyinfo->smallest_font_height = 100000;
11832 dpyinfo->smallest_char_width = 100000;
11833
11834 for (i = 0; i < dpyinfo->n_fonts; ++i)
11835 if (dpyinfo->font_table[i].name)
11836 {
11837 struct font_info *fontp = dpyinfo->font_table + i;
11838 int w, h;
11839
11840 font = (XFontStruct *) fontp->font;
11841 xassert (font != (XFontStruct *) ~0);
11842 x_font_min_bounds (font, &w, &h);
11843
11844 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
11845 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
11846 }
11847
11848 xassert (dpyinfo->smallest_char_width > 0
11849 && dpyinfo->smallest_font_height > 0);
11850
11851 return (dpyinfo->n_fonts == 1
11852 || dpyinfo->smallest_char_width < old_width
11853 || dpyinfo->smallest_font_height < old_height);
11854}
11855
11856
dc43ef94
KH
11857/* Load font named FONTNAME of the size SIZE for frame F, and return a
11858 pointer to the structure font_info while allocating it dynamically.
11859 If SIZE is 0, load any size of font.
11860 If loading is failed, return NULL. */
11861
11862struct font_info *
11863x_load_font (f, fontname, size)
11864 struct frame *f;
11865 register char *fontname;
11866 int size;
11867{
11868 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
11869 Lisp_Object font_names;
d645aaa4 11870 int count;
dc43ef94
KH
11871
11872 /* Get a list of all the fonts that match this name. Once we
11873 have a list of matching fonts, we compare them against the fonts
11874 we already have by comparing names. */
09c6077f 11875 font_names = x_list_fonts (f, build_string (fontname), size, 1);
dc43ef94
KH
11876
11877 if (!NILP (font_names))
11878 {
11879 Lisp_Object tail;
11880 int i;
11881
11882 for (i = 0; i < dpyinfo->n_fonts; i++)
11883 for (tail = font_names; CONSP (tail); tail = XCONS (tail)->cdr)
06a2c219
GM
11884 if (dpyinfo->font_table[i].name
11885 && (!strcmp (dpyinfo->font_table[i].name,
11886 XSTRING (XCONS (tail)->car)->data)
11887 || !strcmp (dpyinfo->font_table[i].full_name,
11888 XSTRING (XCONS (tail)->car)->data)))
dc43ef94
KH
11889 return (dpyinfo->font_table + i);
11890 }
11891
11892 /* Load the font and add it to the table. */
11893 {
11894 char *full_name;
11895 XFontStruct *font;
11896 struct font_info *fontp;
11897 unsigned long value;
06a2c219 11898 int i;
dc43ef94 11899
2da424f1
KH
11900 /* If we have found fonts by x_list_font, load one of them. If
11901 not, we still try to load a font by the name given as FONTNAME
11902 because XListFonts (called in x_list_font) of some X server has
11903 a bug of not finding a font even if the font surely exists and
11904 is loadable by XLoadQueryFont. */
e1d6d5b9 11905 if (size > 0 && !NILP (font_names))
f613a4c8 11906 fontname = (char *) XSTRING (XCONS (font_names)->car)->data;
dc43ef94
KH
11907
11908 BLOCK_INPUT;
d645aaa4 11909 count = x_catch_errors (FRAME_X_DISPLAY (f));
dc43ef94 11910 font = (XFontStruct *) XLoadQueryFont (FRAME_X_DISPLAY (f), fontname);
d645aaa4
KH
11911 if (x_had_errors_p (FRAME_X_DISPLAY (f)))
11912 {
11913 /* This error is perhaps due to insufficient memory on X
11914 server. Let's just ignore it. */
11915 font = NULL;
11916 x_clear_errors (FRAME_X_DISPLAY (f));
11917 }
11918 x_uncatch_errors (FRAME_X_DISPLAY (f), count);
dc43ef94 11919 UNBLOCK_INPUT;
b5210ea7 11920 if (!font)
dc43ef94
KH
11921 return NULL;
11922
06a2c219
GM
11923 /* Find a free slot in the font table. */
11924 for (i = 0; i < dpyinfo->n_fonts; ++i)
11925 if (dpyinfo->font_table[i].name == NULL)
11926 break;
11927
11928 /* If no free slot found, maybe enlarge the font table. */
11929 if (i == dpyinfo->n_fonts
11930 && dpyinfo->n_fonts == dpyinfo->font_table_size)
dc43ef94 11931 {
06a2c219
GM
11932 int sz;
11933 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
11934 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dc43ef94 11935 dpyinfo->font_table
06a2c219 11936 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
dc43ef94
KH
11937 }
11938
06a2c219
GM
11939 fontp = dpyinfo->font_table + i;
11940 if (i == dpyinfo->n_fonts)
11941 ++dpyinfo->n_fonts;
dc43ef94
KH
11942
11943 /* Now fill in the slots of *FONTP. */
11944 BLOCK_INPUT;
11945 fontp->font = font;
06a2c219 11946 fontp->font_idx = i;
dc43ef94
KH
11947 fontp->name = (char *) xmalloc (strlen (fontname) + 1);
11948 bcopy (fontname, fontp->name, strlen (fontname) + 1);
11949
11950 /* Try to get the full name of FONT. Put it in FULL_NAME. */
11951 full_name = 0;
11952 if (XGetFontProperty (font, XA_FONT, &value))
11953 {
11954 char *name = (char *) XGetAtomName (FRAME_X_DISPLAY (f), (Atom) value);
11955 char *p = name;
11956 int dashes = 0;
11957
11958 /* Count the number of dashes in the "full name".
11959 If it is too few, this isn't really the font's full name,
11960 so don't use it.
11961 In X11R4, the fonts did not come with their canonical names
11962 stored in them. */
11963 while (*p)
11964 {
11965 if (*p == '-')
11966 dashes++;
11967 p++;
11968 }
11969
11970 if (dashes >= 13)
11971 {
11972 full_name = (char *) xmalloc (p - name + 1);
11973 bcopy (name, full_name, p - name + 1);
11974 }
11975
11976 XFree (name);
11977 }
11978
11979 if (full_name != 0)
11980 fontp->full_name = full_name;
11981 else
11982 fontp->full_name = fontp->name;
11983
11984 fontp->size = font->max_bounds.width;
d5749adb
KH
11985 fontp->height = FONT_HEIGHT (font);
11986 {
11987 /* For some font, ascent and descent in max_bounds field is
11988 larger than the above value. */
11989 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
11990 if (max_height > fontp->height)
74848a96 11991 fontp->height = max_height;
d5749adb 11992 }
dc43ef94 11993
2da424f1
KH
11994 if (NILP (font_names))
11995 {
11996 /* We come here because of a bug of XListFonts mentioned at
11997 the head of this block. Let's store this information in
11998 the cache for x_list_fonts. */
11999 Lisp_Object lispy_name = build_string (fontname);
12000 Lisp_Object lispy_full_name = build_string (fontp->full_name);
12001
12002 XCONS (dpyinfo->name_list_element)->cdr
12003 = Fcons (Fcons (Fcons (lispy_name, make_number (256)),
12004 Fcons (Fcons (lispy_full_name,
12005 make_number (fontp->size)),
12006 Qnil)),
12007 XCONS (dpyinfo->name_list_element)->cdr);
12008 if (full_name)
12009 XCONS (dpyinfo->name_list_element)->cdr
12010 = Fcons (Fcons (Fcons (lispy_full_name, make_number (256)),
12011 Fcons (Fcons (lispy_full_name,
12012 make_number (fontp->size)),
12013 Qnil)),
12014 XCONS (dpyinfo->name_list_element)->cdr);
12015 }
12016
dc43ef94
KH
12017 /* The slot `encoding' specifies how to map a character
12018 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
ce667c3e 12019 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF, 0:0x2020..0x7F7F,
8ff102bd
RS
12020 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF,
12021 0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, or
12022 2:0xA020..0xFF7F). For the moment, we don't know which charset
06a2c219 12023 uses this font. So, we set information in fontp->encoding[1]
8ff102bd
RS
12024 which is never used by any charset. If mapping can't be
12025 decided, set FONT_ENCODING_NOT_DECIDED. */
dc43ef94
KH
12026 fontp->encoding[1]
12027 = (font->max_byte1 == 0
12028 /* 1-byte font */
12029 ? (font->min_char_or_byte2 < 0x80
12030 ? (font->max_char_or_byte2 < 0x80
12031 ? 0 /* 0x20..0x7F */
8ff102bd 12032 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
dc43ef94
KH
12033 : 1) /* 0xA0..0xFF */
12034 /* 2-byte font */
12035 : (font->min_byte1 < 0x80
12036 ? (font->max_byte1 < 0x80
12037 ? (font->min_char_or_byte2 < 0x80
12038 ? (font->max_char_or_byte2 < 0x80
12039 ? 0 /* 0x2020..0x7F7F */
8ff102bd 12040 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
dc43ef94 12041 : 3) /* 0x20A0..0x7FFF */
8ff102bd 12042 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
dc43ef94
KH
12043 : (font->min_char_or_byte2 < 0x80
12044 ? (font->max_char_or_byte2 < 0x80
12045 ? 2 /* 0xA020..0xFF7F */
8ff102bd 12046 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
dc43ef94
KH
12047 : 1))); /* 0xA0A0..0xFFFF */
12048
12049 fontp->baseline_offset
12050 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
12051 ? (long) value : 0);
12052 fontp->relative_compose
12053 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
12054 ? (long) value : 0);
f78798df
KH
12055 fontp->default_ascent
12056 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
12057 ? (long) value : 0);
dc43ef94 12058
06a2c219
GM
12059 /* Set global flag fonts_changed_p to non-zero if the font loaded
12060 has a character with a smaller width than any other character
12061 before, or if the font loaded has a smalle>r height than any
12062 other font loaded before. If this happens, it will make a
12063 glyph matrix reallocation necessary. */
12064 fonts_changed_p = x_compute_min_glyph_bounds (f);
dc43ef94 12065 UNBLOCK_INPUT;
dc43ef94
KH
12066 return fontp;
12067 }
12068}
12069
06a2c219
GM
12070
12071/* Return a pointer to struct font_info of a font named FONTNAME for
12072 frame F. If no such font is loaded, return NULL. */
12073
dc43ef94
KH
12074struct font_info *
12075x_query_font (f, fontname)
12076 struct frame *f;
12077 register char *fontname;
12078{
12079 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
12080 int i;
12081
12082 for (i = 0; i < dpyinfo->n_fonts; i++)
06a2c219
GM
12083 if (dpyinfo->font_table[i].name
12084 && (!strcmp (dpyinfo->font_table[i].name, fontname)
12085 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
dc43ef94
KH
12086 return (dpyinfo->font_table + i);
12087 return NULL;
12088}
12089
06a2c219
GM
12090
12091/* Find a CCL program for a font specified by FONTP, and set the member
a6582676
KH
12092 `encoder' of the structure. */
12093
12094void
12095x_find_ccl_program (fontp)
12096 struct font_info *fontp;
12097{
a42f54e6 12098 Lisp_Object list, elt;
a6582676
KH
12099
12100 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCONS (list)->cdr)
12101 {
12102 elt = XCONS (list)->car;
12103 if (CONSP (elt)
12104 && STRINGP (XCONS (elt)->car)
12105 && (fast_c_string_match_ignore_case (XCONS (elt)->car, fontp->name)
12106 >= 0))
a42f54e6
KH
12107 break;
12108 }
12109 if (! NILP (list))
12110 {
d27f8ca7
KH
12111 struct ccl_program *ccl
12112 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
a42f54e6
KH
12113
12114 if (setup_ccl_program (ccl, XCONS (elt)->cdr) < 0)
12115 xfree (ccl);
12116 else
12117 fontp->font_encoder = ccl;
a6582676
KH
12118 }
12119}
12120
06a2c219 12121
dc43ef94 12122\f
06a2c219
GM
12123/***********************************************************************
12124 Initialization
12125 ***********************************************************************/
f451eb13 12126
3afe33e7
RS
12127#ifdef USE_X_TOOLKIT
12128static XrmOptionDescRec emacs_options[] = {
12129 {"-geometry", ".geometry", XrmoptionSepArg, NULL},
12130 {"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
12131
12132 {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
12133 XrmoptionSepArg, NULL},
12134 {"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
12135
12136 {"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12137 {"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12138 {"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
12139 {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12140 {"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
12141 {"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
12142 {"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
12143};
12144#endif /* USE_X_TOOLKIT */
12145
7a13e894
RS
12146static int x_initialized;
12147
29b38361
KH
12148#ifdef MULTI_KBOARD
12149/* Test whether two display-name strings agree up to the dot that separates
12150 the screen number from the server number. */
12151static int
12152same_x_server (name1, name2)
12153 char *name1, *name2;
12154{
12155 int seen_colon = 0;
cf591cc1
RS
12156 unsigned char *system_name = XSTRING (Vsystem_name)->data;
12157 int system_name_length = strlen (system_name);
12158 int length_until_period = 0;
12159
12160 while (system_name[length_until_period] != 0
12161 && system_name[length_until_period] != '.')
12162 length_until_period++;
12163
12164 /* Treat `unix' like an empty host name. */
12165 if (! strncmp (name1, "unix:", 5))
12166 name1 += 4;
12167 if (! strncmp (name2, "unix:", 5))
12168 name2 += 4;
12169 /* Treat this host's name like an empty host name. */
12170 if (! strncmp (name1, system_name, system_name_length)
12171 && name1[system_name_length] == ':')
12172 name1 += system_name_length;
12173 if (! strncmp (name2, system_name, system_name_length)
12174 && name2[system_name_length] == ':')
12175 name2 += system_name_length;
12176 /* Treat this host's domainless name like an empty host name. */
12177 if (! strncmp (name1, system_name, length_until_period)
12178 && name1[length_until_period] == ':')
12179 name1 += length_until_period;
12180 if (! strncmp (name2, system_name, length_until_period)
12181 && name2[length_until_period] == ':')
12182 name2 += length_until_period;
12183
29b38361
KH
12184 for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
12185 {
12186 if (*name1 == ':')
12187 seen_colon++;
12188 if (seen_colon && *name1 == '.')
12189 return 1;
12190 }
12191 return (seen_colon
12192 && (*name1 == '.' || *name1 == '\0')
12193 && (*name2 == '.' || *name2 == '\0'));
12194}
12195#endif
12196
71f8198a
PE
12197#if defined (HAVE_X_I18N) || (defined (USE_X_TOOLKIT) && defined (HAVE_X11XTR6))
12198/* Recover from setlocale (LC_ALL, ""). */
12199static void
12200fixup_locale ()
12201{
12202 /* Currently we require strerror to use the "C" locale,
12203 since we don't yet support decoding its string result. */
12204#ifdef LC_MESSAGES
12205 setlocale (LC_MESSAGES, "C");
12206#endif
12207
12208 /* The Emacs Lisp reader needs LC_NUMERIC to be "C",
12209 so that numbers are read and printed properly for Emacs Lisp. */
12210 setlocale (LC_NUMERIC, "C");
12211
12212 /* Currently we require strftime to use the "C" locale,
12213 since we don't yet support encoding its format argument,
12214 or decoding its string result. */
12215 setlocale (LC_TIME, "C");
12216}
12217#endif
12218
334208b7 12219struct x_display_info *
1f8255f2 12220x_term_init (display_name, xrm_option, resource_name)
334208b7 12221 Lisp_Object display_name;
1f8255f2
RS
12222 char *xrm_option;
12223 char *resource_name;
dc6f92b8 12224{
334208b7 12225 int connection;
7a13e894 12226 Display *dpy;
334208b7
RS
12227 struct x_display_info *dpyinfo;
12228 XrmDatabase xrdb;
12229
60439948
KH
12230 BLOCK_INPUT;
12231
7a13e894
RS
12232 if (!x_initialized)
12233 {
12234 x_initialize ();
12235 x_initialized = 1;
12236 }
dc6f92b8 12237
6c183ba5 12238#ifdef HAVE_X_I18N
6186a4a0 12239 setlocale (LC_ALL, "");
71f8198a 12240 fixup_locale ();
6c183ba5
RS
12241#endif
12242
3afe33e7 12243#ifdef USE_X_TOOLKIT
2d7fc7e8
RS
12244 /* weiner@footloose.sps.mot.com reports that this causes
12245 errors with X11R5:
12246 X protocol error: BadAtom (invalid Atom parameter)
12247 on protocol request 18skiloaf.
12248 So let's not use it until R6. */
12249#ifdef HAVE_X11XTR6
bdcd49ba
RS
12250 XtSetLanguageProc (NULL, NULL, NULL);
12251#endif
12252
7f9c7f94
RS
12253 {
12254 int argc = 0;
12255 char *argv[3];
12256
12257 argv[0] = "";
12258 argc = 1;
12259 if (xrm_option)
12260 {
12261 argv[argc++] = "-xrm";
12262 argv[argc++] = xrm_option;
12263 }
12264 dpy = XtOpenDisplay (Xt_app_con, XSTRING (display_name)->data,
12265 resource_name, EMACS_CLASS,
12266 emacs_options, XtNumber (emacs_options),
12267 &argc, argv);
39d8bb4d
KH
12268
12269#ifdef HAVE_X11XTR6
10537cb1 12270 /* I think this is to compensate for XtSetLanguageProc. */
71f8198a 12271 fixup_locale ();
39d8bb4d 12272#endif
7f9c7f94 12273 }
3afe33e7
RS
12274
12275#else /* not USE_X_TOOLKIT */
bdcd49ba
RS
12276#ifdef HAVE_X11R5
12277 XSetLocaleModifiers ("");
12278#endif
7a13e894 12279 dpy = XOpenDisplay (XSTRING (display_name)->data);
3afe33e7 12280#endif /* not USE_X_TOOLKIT */
334208b7 12281
7a13e894
RS
12282 /* Detect failure. */
12283 if (dpy == 0)
60439948
KH
12284 {
12285 UNBLOCK_INPUT;
12286 return 0;
12287 }
7a13e894
RS
12288
12289 /* We have definitely succeeded. Record the new connection. */
12290
12291 dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
12292
29b38361
KH
12293#ifdef MULTI_KBOARD
12294 {
12295 struct x_display_info *share;
12296 Lisp_Object tail;
12297
12298 for (share = x_display_list, tail = x_display_name_list; share;
12299 share = share->next, tail = XCONS (tail)->cdr)
12300 if (same_x_server (XSTRING (XCONS (XCONS (tail)->car)->car)->data,
12301 XSTRING (display_name)->data))
12302 break;
12303 if (share)
12304 dpyinfo->kboard = share->kboard;
12305 else
12306 {
12307 dpyinfo->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
12308 init_kboard (dpyinfo->kboard);
59e755be
KH
12309 if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
12310 {
12311 char *vendor = ServerVendor (dpy);
12312 dpyinfo->kboard->Vsystem_key_alist
12313 = call1 (Qvendor_specific_keysyms,
12314 build_string (vendor ? vendor : ""));
12315 }
12316
29b38361
KH
12317 dpyinfo->kboard->next_kboard = all_kboards;
12318 all_kboards = dpyinfo->kboard;
0ad5446c
KH
12319 /* Don't let the initial kboard remain current longer than necessary.
12320 That would cause problems if a file loaded on startup tries to
06a2c219 12321 prompt in the mini-buffer. */
0ad5446c
KH
12322 if (current_kboard == initial_kboard)
12323 current_kboard = dpyinfo->kboard;
29b38361
KH
12324 }
12325 dpyinfo->kboard->reference_count++;
12326 }
b9737ad3
KH
12327#endif
12328
7a13e894
RS
12329 /* Put this display on the chain. */
12330 dpyinfo->next = x_display_list;
12331 x_display_list = dpyinfo;
12332
12333 /* Put it on x_display_name_list as well, to keep them parallel. */
12334 x_display_name_list = Fcons (Fcons (display_name, Qnil),
12335 x_display_name_list);
12336 dpyinfo->name_list_element = XCONS (x_display_name_list)->car;
12337
12338 dpyinfo->display = dpy;
dc6f92b8 12339
dc6f92b8 12340#if 0
7a13e894 12341 XSetAfterFunction (x_current_display, x_trace_wire);
c118dd06 12342#endif /* ! 0 */
7a13e894
RS
12343
12344 dpyinfo->x_id_name
fc932ac6
RS
12345 = (char *) xmalloc (STRING_BYTES (XSTRING (Vinvocation_name))
12346 + STRING_BYTES (XSTRING (Vsystem_name))
7a13e894
RS
12347 + 2);
12348 sprintf (dpyinfo->x_id_name, "%s@%s",
12349 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
28430d3c
JB
12350
12351 /* Figure out which modifier bits mean what. */
334208b7 12352 x_find_modifier_meanings (dpyinfo);
f451eb13 12353
ab648270 12354 /* Get the scroll bar cursor. */
7a13e894 12355 dpyinfo->vertical_scroll_bar_cursor
334208b7 12356 = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
f451eb13 12357
334208b7
RS
12358 xrdb = x_load_resources (dpyinfo->display, xrm_option,
12359 resource_name, EMACS_CLASS);
12360#ifdef HAVE_XRMSETDATABASE
12361 XrmSetDatabase (dpyinfo->display, xrdb);
12362#else
12363 dpyinfo->display->db = xrdb;
12364#endif
547d9db8 12365 /* Put the rdb where we can find it in a way that works on
7a13e894
RS
12366 all versions. */
12367 dpyinfo->xrdb = xrdb;
334208b7
RS
12368
12369 dpyinfo->screen = ScreenOfDisplay (dpyinfo->display,
12370 DefaultScreen (dpyinfo->display));
12371 dpyinfo->visual = select_visual (dpyinfo->display, dpyinfo->screen,
12372 &dpyinfo->n_planes);
12373 dpyinfo->height = HeightOfScreen (dpyinfo->screen);
12374 dpyinfo->width = WidthOfScreen (dpyinfo->screen);
12375 dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
12376 dpyinfo->grabbed = 0;
12377 dpyinfo->reference_count = 0;
12378 dpyinfo->icon_bitmap_id = -1;
06a2c219 12379 dpyinfo->font_table = NULL;
7a13e894
RS
12380 dpyinfo->n_fonts = 0;
12381 dpyinfo->font_table_size = 0;
12382 dpyinfo->bitmaps = 0;
12383 dpyinfo->bitmaps_size = 0;
12384 dpyinfo->bitmaps_last = 0;
12385 dpyinfo->scratch_cursor_gc = 0;
12386 dpyinfo->mouse_face_mouse_frame = 0;
12387 dpyinfo->mouse_face_deferred_gc = 0;
12388 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
12389 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
06a2c219 12390 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
7a13e894
RS
12391 dpyinfo->mouse_face_window = Qnil;
12392 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
12393 dpyinfo->mouse_face_defer = 0;
0f941935
KH
12394 dpyinfo->x_focus_frame = 0;
12395 dpyinfo->x_focus_event_frame = 0;
12396 dpyinfo->x_highlight_frame = 0;
06a2c219 12397 dpyinfo->image_cache = make_image_cache ();
334208b7 12398
06a2c219
GM
12399 {
12400 int screen_number = XScreenNumberOfScreen (dpyinfo->screen);
12401 double pixels = DisplayHeight (dpyinfo->display, screen_number);
12402 double mm = DisplayHeightMM (dpyinfo->display, screen_number);
12403 dpyinfo->resy = pixels * 25.4 / mm;
12404 pixels = DisplayWidth (dpyinfo->display, screen_number);
12405 mm = DisplayWidthMM (dpyinfo->display, screen_number);
12406 dpyinfo->resx = pixels * 25.4 / mm;
12407 }
12408
334208b7
RS
12409 dpyinfo->Xatom_wm_protocols
12410 = XInternAtom (dpyinfo->display, "WM_PROTOCOLS", False);
12411 dpyinfo->Xatom_wm_take_focus
12412 = XInternAtom (dpyinfo->display, "WM_TAKE_FOCUS", False);
12413 dpyinfo->Xatom_wm_save_yourself
12414 = XInternAtom (dpyinfo->display, "WM_SAVE_YOURSELF", False);
12415 dpyinfo->Xatom_wm_delete_window
12416 = XInternAtom (dpyinfo->display, "WM_DELETE_WINDOW", False);
12417 dpyinfo->Xatom_wm_change_state
12418 = XInternAtom (dpyinfo->display, "WM_CHANGE_STATE", False);
12419 dpyinfo->Xatom_wm_configure_denied
12420 = XInternAtom (dpyinfo->display, "WM_CONFIGURE_DENIED", False);
12421 dpyinfo->Xatom_wm_window_moved
12422 = XInternAtom (dpyinfo->display, "WM_MOVED", False);
12423 dpyinfo->Xatom_editres
12424 = XInternAtom (dpyinfo->display, "Editres", False);
12425 dpyinfo->Xatom_CLIPBOARD
12426 = XInternAtom (dpyinfo->display, "CLIPBOARD", False);
12427 dpyinfo->Xatom_TIMESTAMP
12428 = XInternAtom (dpyinfo->display, "TIMESTAMP", False);
12429 dpyinfo->Xatom_TEXT
12430 = XInternAtom (dpyinfo->display, "TEXT", False);
dc43ef94
KH
12431 dpyinfo->Xatom_COMPOUND_TEXT
12432 = XInternAtom (dpyinfo->display, "COMPOUND_TEXT", False);
334208b7
RS
12433 dpyinfo->Xatom_DELETE
12434 = XInternAtom (dpyinfo->display, "DELETE", False);
12435 dpyinfo->Xatom_MULTIPLE
12436 = XInternAtom (dpyinfo->display, "MULTIPLE", False);
12437 dpyinfo->Xatom_INCR
12438 = XInternAtom (dpyinfo->display, "INCR", False);
12439 dpyinfo->Xatom_EMACS_TMP
12440 = XInternAtom (dpyinfo->display, "_EMACS_TMP_", False);
12441 dpyinfo->Xatom_TARGETS
12442 = XInternAtom (dpyinfo->display, "TARGETS", False);
12443 dpyinfo->Xatom_NULL
12444 = XInternAtom (dpyinfo->display, "NULL", False);
12445 dpyinfo->Xatom_ATOM_PAIR
12446 = XInternAtom (dpyinfo->display, "ATOM_PAIR", False);
dc43ef94
KH
12447 /* For properties of font. */
12448 dpyinfo->Xatom_PIXEL_SIZE
12449 = XInternAtom (dpyinfo->display, "PIXEL_SIZE", False);
12450 dpyinfo->Xatom_MULE_BASELINE_OFFSET
12451 = XInternAtom (dpyinfo->display, "_MULE_BASELINE_OFFSET", False);
12452 dpyinfo->Xatom_MULE_RELATIVE_COMPOSE
12453 = XInternAtom (dpyinfo->display, "_MULE_RELATIVE_COMPOSE", False);
f78798df
KH
12454 dpyinfo->Xatom_MULE_DEFAULT_ASCENT
12455 = XInternAtom (dpyinfo->display, "_MULE_DEFAULT_ASCENT", False);
334208b7 12456
06a2c219
GM
12457 /* Ghostscript support. */
12458 dpyinfo->Xatom_PAGE = XInternAtom (dpyinfo->display, "PAGE", False);
12459 dpyinfo->Xatom_DONE = XInternAtom (dpyinfo->display, "DONE", False);
12460
12461 dpyinfo->Xatom_Scrollbar = XInternAtom (dpyinfo->display, "SCROLLBAR",
12462 False);
12463
547d9db8
KH
12464 dpyinfo->cut_buffers_initialized = 0;
12465
334208b7
RS
12466 connection = ConnectionNumber (dpyinfo->display);
12467 dpyinfo->connection = connection;
12468
dc43ef94 12469 {
5d7cc324
RS
12470 char null_bits[1];
12471
12472 null_bits[0] = 0x00;
dc43ef94
KH
12473
12474 dpyinfo->null_pixel
12475 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12476 null_bits, 1, 1, (long) 0, (long) 0,
12477 1);
12478 }
12479
06a2c219
GM
12480 {
12481 extern int gray_bitmap_width, gray_bitmap_height;
12482 extern unsigned char *gray_bitmap_bits;
12483 dpyinfo->gray
12484 = XCreatePixmapFromBitmapData (dpyinfo->display, dpyinfo->root_window,
12485 gray_bitmap_bits,
12486 gray_bitmap_width, gray_bitmap_height,
12487 (unsigned long) 1, (unsigned long) 0, 1);
12488 }
12489
87485d6f
MW
12490#ifdef subprocesses
12491 /* This is only needed for distinguishing keyboard and process input. */
334208b7 12492 if (connection != 0)
7a13e894 12493 add_keyboard_wait_descriptor (connection);
87485d6f 12494#endif
6d4238f3 12495
041b69ac 12496#ifndef F_SETOWN_BUG
dc6f92b8 12497#ifdef F_SETOWN
dc6f92b8 12498#ifdef F_SETOWN_SOCK_NEG
61c3ce62 12499 /* stdin is a socket here */
334208b7 12500 fcntl (connection, F_SETOWN, -getpid ());
c118dd06 12501#else /* ! defined (F_SETOWN_SOCK_NEG) */
334208b7 12502 fcntl (connection, F_SETOWN, getpid ());
c118dd06
JB
12503#endif /* ! defined (F_SETOWN_SOCK_NEG) */
12504#endif /* ! defined (F_SETOWN) */
041b69ac 12505#endif /* F_SETOWN_BUG */
dc6f92b8
JB
12506
12507#ifdef SIGIO
eee20f6a
KH
12508 if (interrupt_input)
12509 init_sigio (connection);
c118dd06 12510#endif /* ! defined (SIGIO) */
dc6f92b8 12511
51b592fb 12512#ifdef USE_LUCID
f8c39f51 12513#ifdef HAVE_X11R5 /* It seems X11R4 lacks XtCvtStringToFont, and XPointer. */
51b592fb
RS
12514 /* Make sure that we have a valid font for dialog boxes
12515 so that Xt does not crash. */
12516 {
12517 Display *dpy = dpyinfo->display;
12518 XrmValue d, fr, to;
12519 Font font;
e99db5a1 12520 int count;
51b592fb
RS
12521
12522 d.addr = (XPointer)&dpy;
12523 d.size = sizeof (Display *);
12524 fr.addr = XtDefaultFont;
12525 fr.size = sizeof (XtDefaultFont);
12526 to.size = sizeof (Font *);
12527 to.addr = (XPointer)&font;
e99db5a1 12528 count = x_catch_errors (dpy);
51b592fb
RS
12529 if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL))
12530 abort ();
12531 if (x_had_errors_p (dpy) || !XQueryFont (dpy, font))
12532 XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15");
e99db5a1 12533 x_uncatch_errors (dpy, count);
51b592fb
RS
12534 }
12535#endif
f8c39f51 12536#endif
51b592fb 12537
60439948
KH
12538 UNBLOCK_INPUT;
12539
7a13e894
RS
12540 return dpyinfo;
12541}
12542\f
12543/* Get rid of display DPYINFO, assuming all frames are already gone,
12544 and without sending any more commands to the X server. */
dc6f92b8 12545
7a13e894
RS
12546void
12547x_delete_display (dpyinfo)
12548 struct x_display_info *dpyinfo;
12549{
12550 delete_keyboard_wait_descriptor (dpyinfo->connection);
12551
12552 /* Discard this display from x_display_name_list and x_display_list.
12553 We can't use Fdelq because that can quit. */
12554 if (! NILP (x_display_name_list)
12555 && EQ (XCONS (x_display_name_list)->car, dpyinfo->name_list_element))
12556 x_display_name_list = XCONS (x_display_name_list)->cdr;
12557 else
12558 {
12559 Lisp_Object tail;
12560
12561 tail = x_display_name_list;
12562 while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
12563 {
12564 if (EQ (XCONS (XCONS (tail)->cdr)->car,
12565 dpyinfo->name_list_element))
12566 {
12567 XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
12568 break;
12569 }
12570 tail = XCONS (tail)->cdr;
12571 }
12572 }
12573
12574 if (x_display_list == dpyinfo)
12575 x_display_list = dpyinfo->next;
7f9c7f94
RS
12576 else
12577 {
12578 struct x_display_info *tail;
7a13e894 12579
7f9c7f94
RS
12580 for (tail = x_display_list; tail; tail = tail->next)
12581 if (tail->next == dpyinfo)
12582 tail->next = tail->next->next;
12583 }
7a13e894 12584
0d777288
RS
12585#ifndef USE_X_TOOLKIT /* I'm told Xt does this itself. */
12586#ifndef AIX /* On AIX, XCloseDisplay calls this. */
7f9c7f94
RS
12587 XrmDestroyDatabase (dpyinfo->xrdb);
12588#endif
0d777288 12589#endif
29b38361
KH
12590#ifdef MULTI_KBOARD
12591 if (--dpyinfo->kboard->reference_count == 0)
39f79001 12592 delete_kboard (dpyinfo->kboard);
b9737ad3
KH
12593#endif
12594 xfree (dpyinfo->font_table);
12595 xfree (dpyinfo->x_id_name);
12596 xfree (dpyinfo);
7a13e894
RS
12597}
12598\f
12599/* Set up use of X before we make the first connection. */
12600
06a2c219
GM
12601static struct redisplay_interface x_redisplay_interface =
12602{
12603 x_produce_glyphs,
12604 x_write_glyphs,
12605 x_insert_glyphs,
12606 x_clear_end_of_line,
12607 x_scroll_run,
12608 x_after_update_window_line,
12609 x_update_window_begin,
12610 x_update_window_end,
12611 XTcursor_to,
12612 x_flush,
12613 x_get_glyph_overhangs
12614};
12615
dfcf069d 12616void
7a13e894
RS
12617x_initialize ()
12618{
06a2c219
GM
12619 rif = &x_redisplay_interface;
12620
12621 clear_frame_hook = x_clear_frame;
12622 ins_del_lines_hook = x_ins_del_lines;
12623 change_line_highlight_hook = x_change_line_highlight;
12624 delete_glyphs_hook = x_delete_glyphs;
dc6f92b8
JB
12625 ring_bell_hook = XTring_bell;
12626 reset_terminal_modes_hook = XTreset_terminal_modes;
12627 set_terminal_modes_hook = XTset_terminal_modes;
06a2c219
GM
12628 update_begin_hook = x_update_begin;
12629 update_end_hook = x_update_end;
dc6f92b8
JB
12630 set_terminal_window_hook = XTset_terminal_window;
12631 read_socket_hook = XTread_socket;
b8009dd1 12632 frame_up_to_date_hook = XTframe_up_to_date;
dc6f92b8 12633 reassert_line_highlight_hook = XTreassert_line_highlight;
90e65f07 12634 mouse_position_hook = XTmouse_position;
f451eb13 12635 frame_rehighlight_hook = XTframe_rehighlight;
dbc4e1c1 12636 frame_raise_lower_hook = XTframe_raise_lower;
ab648270
JB
12637 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
12638 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
12639 redeem_scroll_bar_hook = XTredeem_scroll_bar;
12640 judge_scroll_bars_hook = XTjudge_scroll_bars;
06a2c219 12641 estimate_mode_line_height_hook = x_estimate_mode_line_height;
58769bee 12642
f676886a 12643 scroll_region_ok = 1; /* we'll scroll partial frames */
dc6f92b8
JB
12644 char_ins_del_ok = 0; /* just as fast to write the line */
12645 line_ins_del_ok = 1; /* we'll just blt 'em */
12646 fast_clear_end_of_line = 1; /* X does this well */
58769bee 12647 memory_below_frame = 0; /* we don't remember what scrolls
dc6f92b8
JB
12648 off the bottom */
12649 baud_rate = 19200;
12650
7a13e894 12651 x_noop_count = 0;
06a2c219
GM
12652 last_toolbar_item = -1;
12653 any_help_event_p = 0;
12654
b30b24cb
RS
12655 /* Try to use interrupt input; if we can't, then start polling. */
12656 Fset_input_mode (Qt, Qnil, Qt, Qnil);
12657
7f9c7f94
RS
12658#ifdef USE_X_TOOLKIT
12659 XtToolkitInitialize ();
12660 Xt_app_con = XtCreateApplicationContext ();
665881ad 12661 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
7f9c7f94
RS
12662#endif
12663
58769bee 12664 /* Note that there is no real way portable across R3/R4 to get the
c118dd06 12665 original error handler. */
e99db5a1 12666 XSetErrorHandler (x_error_handler);
334208b7 12667 XSetIOErrorHandler (x_io_error_quitter);
dc6f92b8 12668
06a2c219 12669 /* Disable Window Change signals; they are handled by X events. */
dc6f92b8
JB
12670#ifdef SIGWINCH
12671 signal (SIGWINCH, SIG_DFL);
c118dd06 12672#endif /* ! defined (SIGWINCH) */
dc6f92b8 12673
92e2441b 12674 signal (SIGPIPE, x_connection_signal);
dc6f92b8 12675}
55123275 12676
06a2c219 12677
55123275
JB
12678void
12679syms_of_xterm ()
12680{
e99db5a1
RS
12681 staticpro (&x_error_message_string);
12682 x_error_message_string = Qnil;
12683
7a13e894
RS
12684 staticpro (&x_display_name_list);
12685 x_display_name_list = Qnil;
334208b7 12686
ab648270 12687 staticpro (&last_mouse_scroll_bar);
e53cb100 12688 last_mouse_scroll_bar = Qnil;
59e755be
KH
12689
12690 staticpro (&Qvendor_specific_keysyms);
12691 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
2237cac9
RS
12692
12693 staticpro (&last_mouse_press_frame);
12694 last_mouse_press_frame = Qnil;
06a2c219
GM
12695
12696 staticpro (&help_echo);
12697 help_echo = Qnil;
12698 staticpro (&previous_help_echo);
12699 previous_help_echo = Qnil;
12700
12701 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
12702 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
12703For example, if a block cursor is over a tab, it will be drawn as\n\
12704wide as that tab on the display.");
12705 x_stretch_cursor_p = 0;
12706
12707 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
12708 "If not nil, Emacs uses toolkit scroll bars.");
12709#if USE_TOOLKIT_SCROLL_BARS
12710 x_toolkit_scroll_bars_p = 1;
12711#else
12712 x_toolkit_scroll_bars_p = 0;
12713#endif
12714
12715 defsubr (&Sxt_process_timeouts);
12716 staticpro (&last_mouse_motion_frame);
12717 last_mouse_motion_frame = Qnil;
55123275 12718}
6cf0ae86
RS
12719
12720#endif /* not HAVE_X_WINDOWS */
06a2c219 12721