Revision: miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-41
[bpt/emacs.git] / src / xdisp.c
CommitLineData
a2889657 1/* Display generation from window structure and buffer text.
7af0e8d7 2 Copyright (C) 1985,86,87,88,93,94,95,97,98,99,2000,01,02,03,04
5f5c8ee5 3 Free Software Foundation, Inc.
a2889657
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
b1d1124b 9the Free Software Foundation; either version 2, or (at your option)
a2889657
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. */
a2889657 21
5f5c8ee5
GM
22/* New redisplay written by Gerd Moellmann <gerd@gnu.org>.
23
24 Redisplay.
25
26 Emacs separates the task of updating the display from code
27 modifying global state, e.g. buffer text. This way functions
28 operating on buffers don't also have to be concerned with updating
29 the display.
30
31 Updating the display is triggered by the Lisp interpreter when it
32 decides it's time to do it. This is done either automatically for
33 you as part of the interpreter's command loop or as the result of
34 calling Lisp functions like `sit-for'. The C function `redisplay'
35 in xdisp.c is the only entry into the inner redisplay code. (Or,
48400103 36 let's say almost---see the description of direct update
4b41cebb 37 operations, below.)
5f5c8ee5
GM
38
39 The following diagram shows how redisplay code is invoked. As you
40 can see, Lisp calls redisplay and vice versa. Under window systems
41 like X, some portions of the redisplay code are also called
42 asynchronously during mouse movement or expose events. It is very
43 important that these code parts do NOT use the C library (malloc,
44 free) because many C libraries under Unix are not reentrant. They
45 may also NOT call functions of the Lisp interpreter which could
46 change the interpreter's state. If you don't follow these rules,
47 you will encounter bugs which are very hard to explain.
48
49 (Direct functions, see below)
2311178e 50 direct_output_for_insert,
5f5c8ee5
GM
51 direct_forward_char (dispnew.c)
52 +---------------------------------+
53 | |
54 | V
82a7ab23 55 +--------------+ redisplay +----------------+
5f5c8ee5
GM
56 | Lisp machine |---------------->| Redisplay code |<--+
57 +--------------+ (xdisp.c) +----------------+ |
58 ^ | |
59 +----------------------------------+ |
60 Don't use this path when called |
61 asynchronously! |
62 |
63 expose_window (asynchronous) |
64 |
65 X expose events -----+
66
959bc044 67 What does redisplay do? Obviously, it has to figure out somehow what
5f5c8ee5
GM
68 has been changed since the last time the display has been updated,
69 and to make these changes visible. Preferably it would do that in
70 a moderately intelligent way, i.e. fast.
71
72 Changes in buffer text can be deduced from window and buffer
73 structures, and from some global variables like `beg_unchanged' and
74 `end_unchanged'. The contents of the display are additionally
75 recorded in a `glyph matrix', a two-dimensional matrix of glyph
76 structures. Each row in such a matrix corresponds to a line on the
77 display, and each glyph in a row corresponds to a column displaying
78 a character, an image, or what else. This matrix is called the
79 `current glyph matrix' or `current matrix' in redisplay
80 terminology.
81
82 For buffer parts that have been changed since the last update, a
83 second glyph matrix is constructed, the so called `desired glyph
84 matrix' or short `desired matrix'. Current and desired matrix are
85 then compared to find a cheap way to update the display, e.g. by
86 reusing part of the display by scrolling lines.
87
88
89 Direct operations.
90
48400103 91 You will find a lot of redisplay optimizations when you start
5f5c8ee5
GM
92 looking at the innards of redisplay. The overall goal of all these
93 optimizations is to make redisplay fast because it is done
94 frequently.
95
96 Two optimizations are not found in xdisp.c. These are the direct
97 operations mentioned above. As the name suggests they follow a
98 different principle than the rest of redisplay. Instead of
99 building a desired matrix and then comparing it with the current
100 display, they perform their actions directly on the display and on
101 the current matrix.
102
103 One direct operation updates the display after one character has
104 been entered. The other one moves the cursor by one position
105 forward or backward. You find these functions under the names
106 `direct_output_for_insert' and `direct_output_forward_char' in
107 dispnew.c.
108
2311178e 109
5f5c8ee5
GM
110 Desired matrices.
111
112 Desired matrices are always built per Emacs window. The function
113 `display_line' is the central function to look at if you are
114 interested. It constructs one row in a desired matrix given an
115 iterator structure containing both a buffer position and a
116 description of the environment in which the text is to be
117 displayed. But this is too early, read on.
118
119 Characters and pixmaps displayed for a range of buffer text depend
120 on various settings of buffers and windows, on overlays and text
121 properties, on display tables, on selective display. The good news
122 is that all this hairy stuff is hidden behind a small set of
959bc044 123 interface functions taking an iterator structure (struct it)
5f5c8ee5
GM
124 argument.
125
48400103 126 Iteration over things to be displayed is then simple. It is
1178ddde
GM
127 started by initializing an iterator with a call to init_iterator.
128 Calls to get_next_display_element fill the iterator structure with
129 relevant information about the next thing to display. Calls to
5f5c8ee5
GM
130 set_iterator_to_next move the iterator to the next thing.
131
132 Besides this, an iterator also contains information about the
133 display environment in which glyphs for display elements are to be
134 produced. It has fields for the width and height of the display,
135 the information whether long lines are truncated or continued, a
136 current X and Y position, and lots of other stuff you can better
137 see in dispextern.h.
138
139 Glyphs in a desired matrix are normally constructed in a loop
140 calling get_next_display_element and then produce_glyphs. The call
141 to produce_glyphs will fill the iterator structure with pixel
142 information about the element being displayed and at the same time
143 produce glyphs for it. If the display element fits on the line
144 being displayed, set_iterator_to_next is called next, otherwise the
145 glyphs produced are discarded.
146
147
148 Frame matrices.
149
150 That just couldn't be all, could it? What about terminal types not
151 supporting operations on sub-windows of the screen? To update the
152 display on such a terminal, window-based glyph matrices are not
153 well suited. To be able to reuse part of the display (scrolling
154 lines up and down), we must instead have a view of the whole
155 screen. This is what `frame matrices' are for. They are a trick.
156
157 Frames on terminals like above have a glyph pool. Windows on such
158 a frame sub-allocate their glyph memory from their frame's glyph
159 pool. The frame itself is given its own glyph matrices. By
160 coincidence---or maybe something else---rows in window glyph
161 matrices are slices of corresponding rows in frame matrices. Thus
162 writing to window matrices implicitly updates a frame matrix which
163 provides us with the view of the whole screen that we originally
164 wanted to have without having to move many bytes around. To be
165 honest, there is a little bit more done, but not much more. If you
166 plan to extend that code, take a look at dispnew.c. The function
167 build_frame_matrix is a good starting point. */
a2889657 168
18160b98 169#include <config.h>
a2889657 170#include <stdio.h>
7ee72033 171
a2889657 172#include "lisp.h"
546a4f00 173#include "keyboard.h"
44fa5b1e 174#include "frame.h"
a2889657
JB
175#include "window.h"
176#include "termchar.h"
177#include "dispextern.h"
178#include "buffer.h"
1c9241f5 179#include "charset.h"
a2889657
JB
180#include "indent.h"
181#include "commands.h"
fa3c6b4d 182#include "keymap.h"
a2889657
JB
183#include "macros.h"
184#include "disptab.h"
30c566e4 185#include "termhooks.h"
b0a0fbda 186#include "intervals.h"
1c9241f5
KH
187#include "coding.h"
188#include "process.h"
dfcf069d 189#include "region-cache.h"
0ef75e87 190#include "fontset.h"
f9b3d256 191#include "blockinput.h"
dfcf069d 192
6d55d620 193#ifdef HAVE_X_WINDOWS
dfcf069d
AS
194#include "xterm.h"
195#endif
a75dfea0
AI
196#ifdef WINDOWSNT
197#include "w32term.h"
198#endif
e0f712ba 199#ifdef MAC_OS
1a578e9b 200#include "macterm.h"
365fa1b3
AC
201
202Cursor No_Cursor;
1a578e9b 203#endif
a2889657 204
1dabd0cf
KS
205#ifndef FRAME_X_OUTPUT
206#define FRAME_X_OUTPUT(f) ((f)->output_data.x)
207#endif
208
5f5c8ee5
GM
209#define INFINITY 10000000
210
488dd4c4
JD
211#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
212 || defined (USE_GTK)
2e621225 213extern void set_frame_menubar P_ ((struct frame *f, int, int));
cd6dfed6 214extern int pending_menu_activation;
76412d64
RS
215#endif
216
a2889657
JB
217extern int interrupt_input;
218extern int command_loop_level;
219
b6436d4e 220extern int minibuffer_auto_raise;
b2b5455d 221extern Lisp_Object Vminibuffer_list;
b6436d4e 222
c4628384 223extern Lisp_Object Qface;
fec8f23e 224extern Lisp_Object Qmode_line, Qmode_line_inactive, Qheader_line;
c4628384 225
399164b4
KH
226extern Lisp_Object Voverriding_local_map;
227extern Lisp_Object Voverriding_local_map_menu_flag;
5f5c8ee5 228extern Lisp_Object Qmenu_item;
0b063c27 229extern Lisp_Object Qwhen;
fa3c6b4d 230extern Lisp_Object Qhelp_echo;
399164b4 231
d46fb96a 232Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
75c43375 233Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
e0bfbde6 234Lisp_Object Qredisplay_end_trigger_functions;
2e54982e 235Lisp_Object Qinhibit_point_motion_hooks;
0b063c27 236Lisp_Object QCeval, QCfile, QCdata, QCpropertize;
5f5c8ee5 237Lisp_Object Qfontified;
6422c1d7 238Lisp_Object Qgrow_only;
869fb12c 239Lisp_Object Qinhibit_eval_during_redisplay;
b384d6f8 240Lisp_Object Qbuffer_position, Qposition, Qobject;
5f5c8ee5 241
cfe03a41
KS
242/* Cursor shapes */
243Lisp_Object Qbar, Qhbar, Qbox, Qhollow;
244
493fdc3c
KS
245/* Pointer shapes */
246Lisp_Object Qarrow, Qhand, Qtext;
247
c53a1624
RS
248Lisp_Object Qrisky_local_variable;
249
7033d6df
RS
250/* Holds the list (error). */
251Lisp_Object list_of_error;
252
5f5c8ee5
GM
253/* Functions called to fontify regions of text. */
254
255Lisp_Object Vfontification_functions;
256Lisp_Object Qfontification_functions;
257
fa3c6b4d
KS
258/* Non-zero means automatically select any window when the mouse
259 cursor moves into it. */
260int mouse_autoselect_window;
261
e037b9ec 262/* Non-zero means draw tool bar buttons raised when the mouse moves
5f5c8ee5
GM
263 over them. */
264
e037b9ec 265int auto_raise_tool_bar_buttons_p;
5f5c8ee5 266
e037b9ec 267/* Margin around tool bar buttons in pixels. */
5f5c8ee5 268
35a41507 269Lisp_Object Vtool_bar_button_margin;
5f5c8ee5 270
e037b9ec 271/* Thickness of shadow to draw around tool bar buttons. */
5f5c8ee5 272
31ade731 273EMACS_INT tool_bar_button_relief;
5f5c8ee5 274
e037b9ec 275/* Non-zero means automatically resize tool-bars so that all tool-bar
5f5c8ee5
GM
276 items are visible, and no blank lines remain. */
277
e037b9ec 278int auto_resize_tool_bars_p;
399164b4 279
fa3c6b4d
KS
280/* Non-zero means draw block and hollow cursor as wide as the glyph
281 under it. For example, if a block cursor is over a tab, it will be
282 drawn as wide as that tab on the display. */
283
284int x_stretch_cursor_p;
285
735c094c
KH
286/* Non-nil means don't actually do any redisplay. */
287
288Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
289
30a3f61c
GM
290/* Non-zero means Lisp evaluation during redisplay is inhibited. */
291
869fb12c 292int inhibit_eval_during_redisplay;
30a3f61c 293
5f5c8ee5
GM
294/* Names of text properties relevant for redisplay. */
295
493fdc3c 296Lisp_Object Qdisplay;
4b41cebb 297extern Lisp_Object Qface, Qinvisible, Qwidth;
5f5c8ee5
GM
298
299/* Symbols used in text property values. */
300
f65536fa 301Lisp_Object Vdisplay_pixels_per_inch;
5f5c8ee5 302Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
a7e27ef7 303Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
493fdc3c 304Lisp_Object Qmargin, Qpointer;
a7e27ef7 305extern Lisp_Object Qheight;
133c764e 306extern Lisp_Object QCwidth, QCheight, QCascent;
f65536fa 307extern Lisp_Object Qscroll_bar;
5f5c8ee5 308
8f897821 309/* Non-nil means highlight trailing whitespace. */
5f5c8ee5 310
8f897821 311Lisp_Object Vshow_trailing_whitespace;
5f5c8ee5 312
7af0e8d7 313#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
314/* Non-nil means that newline may flow into the right fringe. */
315
316Lisp_Object Voverflow_newline_into_fringe;
7af0e8d7 317#endif /* HAVE_WINDOW_SYSTEM */
88e6b646
KS
318
319/* Test if overflow newline into fringe. Called with iterator IT
320 at or past right window margin, and with IT->current_x set. */
321
322#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) \
323 (!NILP (Voverflow_newline_into_fringe) \
324 && FRAME_WINDOW_P (it->f) \
325 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0 \
326 && it->current_x == it->last_visible_x)
327
f65536fa
KS
328/* Non-nil means show the text cursor in void text areas
329 i.e. in blank areas after eol and eob. This used to be
330 the default in 21.3. */
331
493fdc3c 332Lisp_Object Vvoid_text_area_pointer;
f65536fa 333
5f5c8ee5
GM
334/* Name of the face used to highlight trailing whitespace. */
335
336Lisp_Object Qtrailing_whitespace;
337
338/* The symbol `image' which is the car of the lists used to represent
339 images in Lisp. */
340
341Lisp_Object Qimage;
342
493fdc3c
KS
343/* The image map types. */
344Lisp_Object QCmap, QCpointer;
345Lisp_Object Qrect, Qcircle, Qpoly;
346
5f5c8ee5
GM
347/* Non-zero means print newline to stdout before next mini-buffer
348 message. */
a2889657
JB
349
350int noninteractive_need_newline;
351
5f5c8ee5 352/* Non-zero means print newline to message log before next message. */
f88eb0b6 353
3c6595e0 354static int message_log_need_newline;
f88eb0b6 355
b14bc55e
RS
356/* Three markers that message_dolog uses.
357 It could allocate them itself, but that causes trouble
358 in handling memory-full errors. */
359static Lisp_Object message_dolog_marker1;
360static Lisp_Object message_dolog_marker2;
361static Lisp_Object message_dolog_marker3;
5f5c8ee5
GM
362\f
363/* The buffer position of the first character appearing entirely or
364 partially on the line of the selected window which contains the
365 cursor; <= 0 if not known. Set by set_cursor_from_row, used for
366 redisplay optimization in redisplay_internal. */
a2889657 367
5f5c8ee5 368static struct text_pos this_line_start_pos;
a2889657 369
5f5c8ee5
GM
370/* Number of characters past the end of the line above, including the
371 terminating newline. */
372
373static struct text_pos this_line_end_pos;
374
375/* The vertical positions and the height of this line. */
a2889657 376
a2889657 377static int this_line_vpos;
5f5c8ee5
GM
378static int this_line_y;
379static int this_line_pixel_height;
380
381/* X position at which this display line starts. Usually zero;
382 negative if first character is partially visible. */
383
384static int this_line_start_x;
a2889657 385
5f5c8ee5 386/* Buffer that this_line_.* variables are referring to. */
a2889657 387
a2889657
JB
388static struct buffer *this_line_buffer;
389
5f5c8ee5
GM
390/* Nonzero means truncate lines in all windows less wide than the
391 frame. */
a2889657 392
a2889657
JB
393int truncate_partial_width_windows;
394
7bbe686f 395/* A flag to control how to display unibyte 8-bit character. */
5f5c8ee5 396
7bbe686f 397int unibyte_display_via_language_environment;
2311178e 398
5f5c8ee5
GM
399/* Nonzero means we have more than one non-mini-buffer-only frame.
400 Not guaranteed to be accurate except while parsing
401 frame-title-format. */
7bbe686f 402
d39b6696
KH
403int multiple_frames;
404
a2889657
JB
405Lisp_Object Vglobal_mode_string;
406
407/* Marker for where to display an arrow on top of the buffer text. */
5f5c8ee5 408
a2889657
JB
409Lisp_Object Voverlay_arrow_position;
410
5f5c8ee5
GM
411/* String to display for the arrow. Only used on terminal frames. */
412
a2889657
JB
413Lisp_Object Voverlay_arrow_string;
414
5f5c8ee5
GM
415/* Values of those variables at last redisplay. However, if
416 Voverlay_arrow_position is a marker, last_arrow_position is its
417 numerical position. */
418
d45de95b
RS
419static Lisp_Object last_arrow_position, last_arrow_string;
420
5f5c8ee5
GM
421/* Like mode-line-format, but for the title bar on a visible frame. */
422
d39b6696
KH
423Lisp_Object Vframe_title_format;
424
5f5c8ee5
GM
425/* Like mode-line-format, but for the title bar on an iconified frame. */
426
d39b6696
KH
427Lisp_Object Vicon_title_format;
428
08b610e4
RS
429/* List of functions to call when a window's size changes. These
430 functions get one arg, a frame on which one or more windows' sizes
431 have changed. */
5f5c8ee5 432
08b610e4
RS
433static Lisp_Object Vwindow_size_change_functions;
434
0bca8940 435Lisp_Object Qmenu_bar_update_hook, Vmenu_bar_update_hook;
cf074754 436
a2889657 437/* Nonzero if overlay arrow has been displayed once in this window. */
a2889657 438
5f5c8ee5 439static int overlay_arrow_seen;
ca26e1c8 440
fba9ce76 441/* Nonzero means highlight the region even in nonselected windows. */
fba9ce76 442
5f5c8ee5
GM
443int highlight_nonselected_windows;
444
445/* If cursor motion alone moves point off frame, try scrolling this
446 many lines up or down if that will bring it back. */
447
31ade731 448static EMACS_INT scroll_step;
a2889657 449
4b41cebb 450/* Nonzero means scroll just far enough to bring point back on the
5f5c8ee5
GM
451 screen, when appropriate. */
452
31ade731 453static EMACS_INT scroll_conservatively;
0789adb2 454
5f5c8ee5
GM
455/* Recenter the window whenever point gets within this many lines of
456 the top or bottom of the window. This value is translated into a
da8b7f4f
KS
457 pixel value by multiplying it with FRAME_LINE_HEIGHT, which means
458 that there is really a fixed pixel height scroll margin. */
5f5c8ee5 459
31ade731 460EMACS_INT scroll_margin;
9afd2168 461
5f5c8ee5
GM
462/* Number of windows showing the buffer of the selected window (or
463 another buffer with the same base buffer). keyboard.c refers to
464 this. */
a2889657 465
a2889657
JB
466int buffer_shared;
467
5f5c8ee5 468/* Vector containing glyphs for an ellipsis `...'. */
a2889657 469
5f5c8ee5 470static Lisp_Object default_invis_vector[3];
a2889657 471
1862a24e
MB
472/* Zero means display the mode-line/header-line/menu-bar in the default face
473 (this slightly odd definition is for compatibility with previous versions
474 of emacs), non-zero means display them using their respective faces.
475
476 This variable is deprecated. */
a2889657 477
a2889657
JB
478int mode_line_inverse_video;
479
5f5c8ee5
GM
480/* Prompt to display in front of the mini-buffer contents. */
481
8c5b6a0a 482Lisp_Object minibuf_prompt;
a2889657 483
5f5c8ee5
GM
484/* Width of current mini-buffer prompt. Only set after display_line
485 of the line that contains the prompt. */
486
a2889657 487int minibuf_prompt_width;
5f5c8ee5 488
5f5c8ee5
GM
489/* This is the window where the echo area message was displayed. It
490 is always a mini-buffer window, but it may not be the same window
491 currently active as a mini-buffer. */
492
73af359d
RS
493Lisp_Object echo_area_window;
494
c6e89d6c
GM
495/* List of pairs (MESSAGE . MULTIBYTE). The function save_message
496 pushes the current message and the value of
497 message_enable_multibyte on the stack, the function restore_message
498 pops the stack and displays MESSAGE again. */
499
500Lisp_Object Vmessage_stack;
501
a3788d53
RS
502/* Nonzero means multibyte characters were enabled when the echo area
503 message was specified. */
5f5c8ee5 504
a3788d53
RS
505int message_enable_multibyte;
506
4b41cebb 507/* Nonzero if we should redraw the mode lines on the next redisplay. */
5f5c8ee5 508
a2889657
JB
509int update_mode_lines;
510
5f5c8ee5 511/* Nonzero if window sizes or contents have changed since last
4b41cebb 512 redisplay that finished. */
5f5c8ee5 513
a2889657
JB
514int windows_or_buffers_changed;
515
5fb96e96
RS
516/* Nonzero means a frame's cursor type has been changed. */
517
518int cursor_type_changed;
519
5f5c8ee5
GM
520/* Nonzero after display_mode_line if %l was used and it displayed a
521 line number. */
522
aa6d10fa
RS
523int line_number_displayed;
524
525/* Maximum buffer size for which to display line numbers. */
5f5c8ee5 526
090703f4 527Lisp_Object Vline_number_display_limit;
5992c4f7 528
4b41cebb 529/* Line width to consider when repositioning for line number display. */
5d121aec 530
31ade731 531static EMACS_INT line_number_display_limit_width;
5d121aec 532
5f5c8ee5
GM
533/* Number of lines to keep in the message log buffer. t means
534 infinite. nil means don't log at all. */
535
5992c4f7 536Lisp_Object Vmessage_log_max;
d45de95b 537
6a94510a
GM
538/* The name of the *Messages* buffer, a string. */
539
540static Lisp_Object Vmessages_buffer_name;
541
c6e89d6c
GM
542/* Current, index 0, and last displayed echo area message. Either
543 buffers from echo_buffers, or nil to indicate no message. */
544
545Lisp_Object echo_area_buffer[2];
546
547/* The buffers referenced from echo_area_buffer. */
548
549static Lisp_Object echo_buffer[2];
550
551/* A vector saved used in with_area_buffer to reduce consing. */
552
553static Lisp_Object Vwith_echo_area_save_vector;
554
555/* Non-zero means display_echo_area should display the last echo area
556 message again. Set by redisplay_preserve_echo_area. */
557
558static int display_last_displayed_message_p;
559
560/* Nonzero if echo area is being used by print; zero if being used by
561 message. */
562
563int message_buf_print;
564
e1477f43
GM
565/* The symbol `inhibit-menubar-update' and its DEFVAR_BOOL variable. */
566
567Lisp_Object Qinhibit_menubar_update;
568int inhibit_menubar_update;
569
9142dd5b
GM
570/* Maximum height for resizing mini-windows. Either a float
571 specifying a fraction of the available height, or an integer
572 specifying a number of lines. */
c6e89d6c 573
ad4f174e
GM
574Lisp_Object Vmax_mini_window_height;
575
576/* Non-zero means messages should be displayed with truncated
577 lines instead of being continued. */
578
579int message_truncate_lines;
580Lisp_Object Qmessage_truncate_lines;
c6e89d6c 581
6e019995
GM
582/* Set to 1 in clear_message to make redisplay_internal aware
583 of an emptied echo area. */
584
585static int message_cleared_p;
586
d6d26ed3
GM
587/* Non-zero means we want a hollow cursor in windows that are not
588 selected. Zero means there's no cursor in such windows. */
589
cfe03a41 590Lisp_Object Vcursor_in_non_selected_windows;
af79bccb 591Lisp_Object Qcursor_in_non_selected_windows;
d6d26ed3 592
cfe03a41
KS
593/* How to blink the default frame cursor off. */
594Lisp_Object Vblink_cursor_alist;
595
5f5c8ee5
GM
596/* A scratch glyph row with contents used for generating truncation
597 glyphs. Also used in direct_output_for_insert. */
12adba34 598
5f5c8ee5
GM
599#define MAX_SCRATCH_GLYPHS 100
600struct glyph_row scratch_glyph_row;
601static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
1adc55de 602
5f5c8ee5
GM
603/* Ascent and height of the last line processed by move_it_to. */
604
605static int last_max_ascent, last_height;
606
21fdfb65
GM
607/* Non-zero if there's a help-echo in the echo area. */
608
609int help_echo_showing_p;
610
04612a64
GM
611/* If >= 0, computed, exact values of mode-line and header-line height
612 to use in the macros CURRENT_MODE_LINE_HEIGHT and
613 CURRENT_HEADER_LINE_HEIGHT. */
614
615int current_mode_line_height, current_header_line_height;
616
5f5c8ee5 617/* The maximum distance to look ahead for text properties. Values
2311178e 618 that are too small let us call compute_char_face and similar
5f5c8ee5
GM
619 functions too often which is expensive. Values that are too large
620 let us call compute_char_face and alike too often because we
621 might not be interested in text properties that far away. */
622
623#define TEXT_PROP_DISTANCE_LIMIT 100
624
47589c8c
GM
625#if GLYPH_DEBUG
626
76cb5e06
GM
627/* Variables to turn off display optimizations from Lisp. */
628
629int inhibit_try_window_id, inhibit_try_window_reusing;
630int inhibit_try_cursor_movement;
631
5f5c8ee5
GM
632/* Non-zero means print traces of redisplay if compiled with
633 GLYPH_DEBUG != 0. */
634
5f5c8ee5 635int trace_redisplay_p;
47589c8c 636
546a4f00 637#endif /* GLYPH_DEBUG */
47589c8c 638
546a4f00
AI
639#ifdef DEBUG_TRACE_MOVE
640/* Non-zero means trace with TRACE_MOVE to stderr. */
47589c8c
GM
641int trace_move;
642
47589c8c
GM
643#define TRACE_MOVE(x) if (trace_move) fprintf x; else (void) 0
644#else
91c3f500 645#define TRACE_MOVE(x) (void) 0
5f5c8ee5 646#endif
2311178e 647
d475bcb8
GM
648/* Non-zero means automatically scroll windows horizontally to make
649 point visible. */
650
651int automatic_hscrolling_p;
652
1df7e8f0
EZ
653/* How close to the margin can point get before the window is scrolled
654 horizontally. */
5d335845 655EMACS_INT hscroll_margin;
1df7e8f0
EZ
656
657/* How much to scroll horizontally when point is inside the above margin. */
e76d28d5 658Lisp_Object Vhscroll_step;
1df7e8f0 659
e00daaa0
GM
660/* A list of symbols, one for each supported image type. */
661
662Lisp_Object Vimage_types;
663
6422c1d7 664/* The variable `resize-mini-windows'. If nil, don't resize
67526daf 665 mini-windows. If t, always resize them to fit the text they
6422c1d7
GM
666 display. If `grow-only', let mini-windows grow only until they
667 become empty. */
668
669Lisp_Object Vresize_mini_windows;
670
82a7ab23
RS
671/* Buffer being redisplayed -- for redisplay_window_error. */
672
673struct buffer *displayed_buffer;
674
5f5c8ee5
GM
675/* Value returned from text property handlers (see below). */
676
677enum prop_handled
3c6595e0 678{
5f5c8ee5
GM
679 HANDLED_NORMALLY,
680 HANDLED_RECOMPUTE_PROPS,
681 HANDLED_OVERLAY_STRING_CONSUMED,
682 HANDLED_RETURN
683};
3c6595e0 684
5f5c8ee5
GM
685/* A description of text properties that redisplay is interested
686 in. */
3c6595e0 687
5f5c8ee5
GM
688struct props
689{
690 /* The name of the property. */
691 Lisp_Object *name;
90adcf20 692
5f5c8ee5
GM
693 /* A unique index for the property. */
694 enum prop_idx idx;
695
696 /* A handler function called to set up iterator IT from the property
697 at IT's current position. Value is used to steer handle_stop. */
698 enum prop_handled (*handler) P_ ((struct it *it));
699};
700
701static enum prop_handled handle_face_prop P_ ((struct it *));
702static enum prop_handled handle_invisible_prop P_ ((struct it *));
703static enum prop_handled handle_display_prop P_ ((struct it *));
260a86a0 704static enum prop_handled handle_composition_prop P_ ((struct it *));
5f5c8ee5
GM
705static enum prop_handled handle_overlay_change P_ ((struct it *));
706static enum prop_handled handle_fontified_prop P_ ((struct it *));
707
708/* Properties handled by iterators. */
709
710static struct props it_props[] =
5992c4f7 711{
5f5c8ee5
GM
712 {&Qfontified, FONTIFIED_PROP_IDX, handle_fontified_prop},
713 /* Handle `face' before `display' because some sub-properties of
714 `display' need to know the face. */
715 {&Qface, FACE_PROP_IDX, handle_face_prop},
716 {&Qdisplay, DISPLAY_PROP_IDX, handle_display_prop},
717 {&Qinvisible, INVISIBLE_PROP_IDX, handle_invisible_prop},
260a86a0 718 {&Qcomposition, COMPOSITION_PROP_IDX, handle_composition_prop},
5f5c8ee5
GM
719 {NULL, 0, NULL}
720};
5992c4f7 721
5f5c8ee5
GM
722/* Value is the position described by X. If X is a marker, value is
723 the marker_position of X. Otherwise, value is X. */
12adba34 724
5f5c8ee5 725#define COERCE_MARKER(X) (MARKERP ((X)) ? Fmarker_position (X) : (X))
12adba34 726
5f5c8ee5 727/* Enumeration returned by some move_it_.* functions internally. */
12adba34 728
5f5c8ee5
GM
729enum move_it_result
730{
731 /* Not used. Undefined value. */
732 MOVE_UNDEFINED,
bab29e15 733
5f5c8ee5
GM
734 /* Move ended at the requested buffer position or ZV. */
735 MOVE_POS_MATCH_OR_ZV,
bab29e15 736
5f5c8ee5
GM
737 /* Move ended at the requested X pixel position. */
738 MOVE_X_REACHED,
12adba34 739
5f5c8ee5
GM
740 /* Move within a line ended at the end of a line that must be
741 continued. */
742 MOVE_LINE_CONTINUED,
2311178e 743
5f5c8ee5
GM
744 /* Move within a line ended at the end of a line that would
745 be displayed truncated. */
746 MOVE_LINE_TRUNCATED,
ff6c30e5 747
5f5c8ee5
GM
748 /* Move within a line ended at a line end. */
749 MOVE_NEWLINE_OR_CR
750};
12adba34 751
1987b083
RS
752/* This counter is used to clear the face cache every once in a while
753 in redisplay_internal. It is incremented for each redisplay.
754 Every CLEAR_FACE_CACHE_COUNT full redisplays, the face cache is
755 cleared. */
756
757#define CLEAR_FACE_CACHE_COUNT 500
758static int clear_face_cache_count;
759
760/* Record the previous terminal frame we displayed. */
761
762static struct frame *previous_terminal_frame;
763
764/* Non-zero while redisplay_internal is in progress. */
765
766int redisplaying_p;
767
26683087
RS
768/* Non-zero means don't free realized faces. Bound while freeing
769 realized faces is dangerous because glyph matrices might still
770 reference them. */
1987b083 771
26683087
RS
772int inhibit_free_realized_faces;
773Lisp_Object Qinhibit_free_realized_faces;
ff6c30e5 774
fa3c6b4d
KS
775/* If a string, XTread_socket generates an event to display that string.
776 (The display is done in read_char.) */
777
778Lisp_Object help_echo_string;
779Lisp_Object help_echo_window;
780Lisp_Object help_echo_object;
781int help_echo_pos;
782
783/* Temporary variable for XTread_socket. */
784
785Lisp_Object previous_help_echo_string;
786
787
5f5c8ee5
GM
788\f
789/* Function prototypes. */
790
5a08cbaf 791static void setup_for_ellipsis P_ ((struct it *));
43c09969 792static void mark_window_display_accurate_1 P_ ((struct window *, int));
74bd6d65
GM
793static int single_display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
794static int display_prop_string_p P_ ((Lisp_Object, Lisp_Object));
cafafe0b 795static int cursor_row_p P_ ((struct window *, struct glyph_row *));
715e84c9 796static int redisplay_mode_lines P_ ((Lisp_Object, int));
2e621225 797static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
c0a53abb
PJ
798
799#if 0
2e621225 800static int invisible_text_between_p P_ ((struct it *, int, int));
c0a53abb
PJ
801#endif
802
2e621225
GM
803static int next_element_from_ellipsis P_ ((struct it *));
804static void pint2str P_ ((char *, int, int));
525b8b09 805static void pint2hrstr P_ ((char *, int, int));
2e621225
GM
806static struct text_pos run_window_scroll_functions P_ ((Lisp_Object,
807 struct text_pos));
808static void reconsider_clip_changes P_ ((struct window *, struct buffer *));
809static int text_outside_line_unchanged_p P_ ((struct window *, int, int));
810static void store_frame_title_char P_ ((char));
50f80c2f 811static int store_frame_title P_ ((const unsigned char *, int, int));
2e621225
GM
812static void x_consider_frame_title P_ ((Lisp_Object));
813static void handle_stop P_ ((struct it *));
814static int tool_bar_lines_needed P_ ((struct frame *));
06568bbf 815static int single_display_prop_intangible_p P_ ((Lisp_Object));
5bcfeb49 816static void ensure_echo_area_buffers P_ ((void));
c6e89d6c
GM
817static Lisp_Object unwind_with_echo_area_buffer P_ ((Lisp_Object));
818static Lisp_Object with_echo_area_buffer_unwind_data P_ ((struct window *));
23a96c77 819static int with_echo_area_buffer P_ ((struct window *, int,
23dd2d97
KR
820 int (*) (EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT),
821 EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 822static void clear_garbaged_frames P_ ((void));
23dd2d97
KR
823static int current_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
824static int truncate_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
825static int set_message_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
c6e89d6c 826static int display_echo_area P_ ((struct window *));
23dd2d97
KR
827static int display_echo_area_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
828static int resize_mini_window_1 P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
28514cd9 829static Lisp_Object unwind_redisplay P_ ((Lisp_Object));
50f80c2f 830static int string_char_and_length P_ ((const unsigned char *, int, int *));
5f5c8ee5
GM
831static struct text_pos display_prop_end P_ ((struct it *, Lisp_Object,
832 struct text_pos));
833static int compute_window_start_on_continuation_line P_ ((struct window *));
116d6f5c 834static Lisp_Object safe_eval_handler P_ ((Lisp_Object));
5f5c8ee5
GM
835static void insert_left_trunc_glyphs P_ ((struct it *));
836static struct glyph_row *get_overlay_arrow_glyph_row P_ ((struct window *));
837static void extend_face_to_end_of_line P_ ((struct it *));
80c6cb1f 838static int append_space P_ ((struct it *, int));
cb617e7c 839static int make_cursor_line_fully_visible P_ ((struct window *));
03b0a4b4 840static int try_scrolling P_ ((Lisp_Object, int, EMACS_INT, EMACS_INT, int, int));
47589c8c 841static int try_cursor_movement P_ ((Lisp_Object, struct text_pos, int *));
5f5c8ee5
GM
842static int trailing_whitespace_p P_ ((int));
843static int message_log_check_duplicate P_ ((int, int, int, int));
5f5c8ee5
GM
844static void push_it P_ ((struct it *));
845static void pop_it P_ ((struct it *));
846static void sync_frame_with_window_matrix_rows P_ ((struct window *));
dd429b03 847static void select_frame_for_redisplay P_ ((Lisp_Object));
5f5c8ee5 848static void redisplay_internal P_ ((int));
c6e89d6c 849static int echo_area_display P_ ((int));
5f5c8ee5
GM
850static void redisplay_windows P_ ((Lisp_Object));
851static void redisplay_window P_ ((Lisp_Object, int));
82a7ab23
RS
852static Lisp_Object redisplay_window_error ();
853static Lisp_Object redisplay_window_0 P_ ((Lisp_Object));
854static Lisp_Object redisplay_window_1 P_ ((Lisp_Object));
5f5c8ee5
GM
855static void update_menu_bar P_ ((struct frame *, int));
856static int try_window_reusing_current_matrix P_ ((struct window *));
857static int try_window_id P_ ((struct window *));
858static int display_line P_ ((struct it *));
715e84c9 859static int display_mode_lines P_ ((struct window *));
04612a64 860static int display_mode_line P_ ((struct window *, enum face_id, Lisp_Object));
c53a1624 861static int display_mode_element P_ ((struct it *, int, int, int, Lisp_Object, Lisp_Object, int));
fec8f23e 862static int store_mode_line_string P_ ((char *, Lisp_Object, int, int, int, Lisp_Object));
72f62cb5 863static char *decode_mode_spec P_ ((struct window *, int, int, int, int *));
5f5c8ee5
GM
864static void display_menu_bar P_ ((struct window *));
865static int display_count_lines P_ ((int, int, int, int, int *));
866static int display_string P_ ((unsigned char *, Lisp_Object, Lisp_Object,
867 int, int, struct it *, int, int, int, int));
868static void compute_line_metrics P_ ((struct it *));
869static void run_redisplay_end_trigger_hook P_ ((struct it *));
5a08cbaf 870static int get_overlay_strings P_ ((struct it *, int));
5f5c8ee5 871static void next_overlay_string P_ ((struct it *));
5f5c8ee5
GM
872static void reseat P_ ((struct it *, struct text_pos, int));
873static void reseat_1 P_ ((struct it *, struct text_pos, int));
874static void back_to_previous_visible_line_start P_ ((struct it *));
875static void reseat_at_previous_visible_line_start P_ ((struct it *));
312246d1 876static void reseat_at_next_visible_line_start P_ ((struct it *, int));
5f5c8ee5
GM
877static int next_element_from_display_vector P_ ((struct it *));
878static int next_element_from_string P_ ((struct it *));
879static int next_element_from_c_string P_ ((struct it *));
880static int next_element_from_buffer P_ ((struct it *));
260a86a0 881static int next_element_from_composition P_ ((struct it *));
5f5c8ee5
GM
882static int next_element_from_image P_ ((struct it *));
883static int next_element_from_stretch P_ ((struct it *));
5a08cbaf 884static void load_overlay_strings P_ ((struct it *, int));
47d57b22
GM
885static int init_from_display_pos P_ ((struct it *, struct window *,
886 struct display_pos *));
5f5c8ee5
GM
887static void reseat_to_string P_ ((struct it *, unsigned char *,
888 Lisp_Object, int, int, int, int));
5f5c8ee5
GM
889static enum move_it_result move_it_in_display_line_to P_ ((struct it *,
890 int, int, int));
891void move_it_vertically_backward P_ ((struct it *, int));
892static void init_to_row_start P_ ((struct it *, struct window *,
893 struct glyph_row *));
47d57b22
GM
894static int init_to_row_end P_ ((struct it *, struct window *,
895 struct glyph_row *));
5f5c8ee5 896static void back_to_previous_line_start P_ ((struct it *));
cafafe0b 897static int forward_to_next_line_start P_ ((struct it *, int *));
5f5c8ee5
GM
898static struct text_pos string_pos_nchars_ahead P_ ((struct text_pos,
899 Lisp_Object, int));
900static struct text_pos string_pos P_ ((int, Lisp_Object));
901static struct text_pos c_string_pos P_ ((int, unsigned char *, int));
902static int number_of_chars P_ ((unsigned char *, int));
903static void compute_stop_pos P_ ((struct it *));
904static void compute_string_pos P_ ((struct text_pos *, struct text_pos,
905 Lisp_Object));
906static int face_before_or_after_it_pos P_ ((struct it *, int));
907static int next_overlay_change P_ ((int));
908static int handle_single_display_prop P_ ((struct it *, Lisp_Object,
a61b7058
GM
909 Lisp_Object, struct text_pos *,
910 int));
06a12811 911static int underlying_face_id P_ ((struct it *));
4bde0ebb
GM
912static int in_ellipses_for_invisible_text_p P_ ((struct display_pos *,
913 struct window *));
5f5c8ee5
GM
914
915#define face_before_it_pos(IT) face_before_or_after_it_pos ((IT), 1)
916#define face_after_it_pos(IT) face_before_or_after_it_pos ((IT), 0)
ff6c30e5 917
5f5c8ee5 918#ifdef HAVE_WINDOW_SYSTEM
12adba34 919
e037b9ec
GM
920static void update_tool_bar P_ ((struct frame *, int));
921static void build_desired_tool_bar_string P_ ((struct frame *f));
922static int redisplay_tool_bar P_ ((struct frame *));
923static void display_tool_bar_line P_ ((struct it *));
fa3c6b4d
KS
924static void notice_overwritten_cursor P_ ((struct window *,
925 enum glyph_row_area,
926 int, int, int, int));
927
928
12adba34 929
5f5c8ee5 930#endif /* HAVE_WINDOW_SYSTEM */
12adba34 931
5f5c8ee5
GM
932\f
933/***********************************************************************
934 Window display dimensions
935 ***********************************************************************/
12adba34 936
40a301b3
RS
937/* Return the bottom boundary y-position for text lines in window W.
938 This is the first y position at which a line cannot start.
939 It is relative to the top of the window.
940
941 This is the height of W minus the height of a mode line, if any. */
5f5c8ee5
GM
942
943INLINE int
944window_text_bottom_y (w)
945 struct window *w;
946{
da8b7f4f 947 int height = WINDOW_TOTAL_HEIGHT (w);
1a578e9b 948
5f5c8ee5
GM
949 if (WINDOW_WANTS_MODELINE_P (w))
950 height -= CURRENT_MODE_LINE_HEIGHT (w);
951 return height;
f88eb0b6
KH
952}
953
5f5c8ee5 954/* Return the pixel width of display area AREA of window W. AREA < 0
b46952ae 955 means return the total width of W, not including fringes to
5f5c8ee5 956 the left and right of the window. */
ff6c30e5 957
5f5c8ee5
GM
958INLINE int
959window_box_width (w, area)
960 struct window *w;
961 int area;
962{
da8b7f4f
KS
963 int cols = XFASTINT (w->total_cols);
964 int pixels = 0;
2311178e 965
5f5c8ee5 966 if (!w->pseudo_window_p)
ff6c30e5 967 {
da8b7f4f 968 cols -= WINDOW_SCROLL_BAR_COLS (w);
2311178e 969
5f5c8ee5
GM
970 if (area == TEXT_AREA)
971 {
da8b7f4f
KS
972 if (INTEGERP (w->left_margin_cols))
973 cols -= XFASTINT (w->left_margin_cols);
974 if (INTEGERP (w->right_margin_cols))
975 cols -= XFASTINT (w->right_margin_cols);
976 pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
5f5c8ee5
GM
977 }
978 else if (area == LEFT_MARGIN_AREA)
da8b7f4f
KS
979 {
980 cols = (INTEGERP (w->left_margin_cols)
981 ? XFASTINT (w->left_margin_cols) : 0);
982 pixels = 0;
983 }
5f5c8ee5 984 else if (area == RIGHT_MARGIN_AREA)
da8b7f4f
KS
985 {
986 cols = (INTEGERP (w->right_margin_cols)
987 ? XFASTINT (w->right_margin_cols) : 0);
988 pixels = 0;
989 }
ff6c30e5 990 }
5f5c8ee5 991
da8b7f4f 992 return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
ff6c30e5 993}
1adc55de 994
1adc55de 995
5f5c8ee5 996/* Return the pixel height of the display area of window W, not
4b41cebb 997 including mode lines of W, if any. */
f88eb0b6 998
5f5c8ee5
GM
999INLINE int
1000window_box_height (w)
1001 struct window *w;
f88eb0b6 1002{
5f5c8ee5 1003 struct frame *f = XFRAME (w->frame);
da8b7f4f 1004 int height = WINDOW_TOTAL_HEIGHT (w);
7ecd4937
GM
1005
1006 xassert (height >= 0);
2311178e 1007
d9c9e99c
MB
1008 /* Note: the code below that determines the mode-line/header-line
1009 height is essentially the same as that contained in the macro
1010 CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
1011 the appropriate glyph row has its `mode_line_p' flag set,
1012 and if it doesn't, uses estimate_mode_line_height instead. */
1013
5f5c8ee5 1014 if (WINDOW_WANTS_MODELINE_P (w))
97dff879
MB
1015 {
1016 struct glyph_row *ml_row
1017 = (w->current_matrix && w->current_matrix->rows
1018 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1019 : 0);
1020 if (ml_row && ml_row->mode_line_p)
1021 height -= ml_row->height;
1022 else
96d2320f 1023 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
97dff879 1024 }
5f5c8ee5 1025
045dee35 1026 if (WINDOW_WANTS_HEADER_LINE_P (w))
97dff879
MB
1027 {
1028 struct glyph_row *hl_row
1029 = (w->current_matrix && w->current_matrix->rows
1030 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1031 : 0);
1032 if (hl_row && hl_row->mode_line_p)
1033 height -= hl_row->height;
1034 else
1035 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1036 }
5f5c8ee5 1037
7c75be36
PJ
1038 /* With a very small font and a mode-line that's taller than
1039 default, we might end up with a negative height. */
1040 return max (0, height);
5992c4f7
KH
1041}
1042
da8b7f4f
KS
1043/* Return the window-relative coordinate of the left edge of display
1044 area AREA of window W. AREA < 0 means return the left edge of the
1045 whole window, to the right of the left fringe of W. */
1046
1047INLINE int
1048window_box_left_offset (w, area)
1049 struct window *w;
1050 int area;
1051{
1052 int x;
1053
1054 if (w->pseudo_window_p)
1055 return 0;
1056
1057 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1058
1059 if (area == TEXT_AREA)
1060 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1061 + window_box_width (w, LEFT_MARGIN_AREA));
1062 else if (area == RIGHT_MARGIN_AREA)
1063 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1064 + window_box_width (w, LEFT_MARGIN_AREA)
1065 + window_box_width (w, TEXT_AREA)
1066 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1067 ? 0
1068 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1069 else if (area == LEFT_MARGIN_AREA
1070 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1071 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1072
1073 return x;
1074}
1075
1076
1077/* Return the window-relative coordinate of the right edge of display
1078 area AREA of window W. AREA < 0 means return the left edge of the
1079 whole window, to the left of the right fringe of W. */
1080
1081INLINE int
1082window_box_right_offset (w, area)
1083 struct window *w;
1084 int area;
1085{
1086 return window_box_left_offset (w, area) + window_box_width (w, area);
1087}
5992c4f7 1088
5f5c8ee5
GM
1089/* Return the frame-relative coordinate of the left edge of display
1090 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1091 whole window, to the right of the left fringe of W. */
5992c4f7 1092
5f5c8ee5
GM
1093INLINE int
1094window_box_left (w, area)
1095 struct window *w;
1096 int area;
90adcf20 1097{
5f5c8ee5 1098 struct frame *f = XFRAME (w->frame);
da8b7f4f 1099 int x;
a3788d53 1100
da8b7f4f
KS
1101 if (w->pseudo_window_p)
1102 return FRAME_INTERNAL_BORDER_WIDTH (f);
2311178e 1103
da8b7f4f
KS
1104 x = (WINDOW_LEFT_EDGE_X (w)
1105 + window_box_left_offset (w, area));
73af359d 1106
5f5c8ee5 1107 return x;
2311178e 1108}
90adcf20 1109
b6436d4e 1110
5f5c8ee5
GM
1111/* Return the frame-relative coordinate of the right edge of display
1112 area AREA of window W. AREA < 0 means return the left edge of the
b46952ae 1113 whole window, to the left of the right fringe of W. */
ded34426 1114
5f5c8ee5
GM
1115INLINE int
1116window_box_right (w, area)
1117 struct window *w;
1118 int area;
1119{
1120 return window_box_left (w, area) + window_box_width (w, area);
2311178e
TTN
1121}
1122
5f5c8ee5
GM
1123/* Get the bounding box of the display area AREA of window W, without
1124 mode lines, in frame-relative coordinates. AREA < 0 means the
b46952ae 1125 whole window, not including the left and right fringes of
5f5c8ee5
GM
1126 the window. Return in *BOX_X and *BOX_Y the frame-relative pixel
1127 coordinates of the upper-left corner of the box. Return in
1128 *BOX_WIDTH, and *BOX_HEIGHT the pixel width and height of the box. */
1129
1130INLINE void
1131window_box (w, area, box_x, box_y, box_width, box_height)
1132 struct window *w;
1133 int area;
1134 int *box_x, *box_y, *box_width, *box_height;
1135{
da8b7f4f
KS
1136 if (box_width)
1137 *box_width = window_box_width (w, area);
1138 if (box_height)
1139 *box_height = window_box_height (w);
1140 if (box_x)
1141 *box_x = window_box_left (w, area);
1142 if (box_y)
1143 {
1144 *box_y = WINDOW_TOP_EDGE_Y (w);
1145 if (WINDOW_WANTS_HEADER_LINE_P (w))
1146 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1147 }
ded34426 1148}
1adc55de 1149
1adc55de 1150
5f5c8ee5 1151/* Get the bounding box of the display area AREA of window W, without
b46952ae
KS
1152 mode lines. AREA < 0 means the whole window, not including the
1153 left and right fringe of the window. Return in *TOP_LEFT_X
5f5c8ee5
GM
1154 and TOP_LEFT_Y the frame-relative pixel coordinates of the
1155 upper-left corner of the box. Return in *BOTTOM_RIGHT_X, and
1156 *BOTTOM_RIGHT_Y the coordinates of the bottom-right corner of the
1157 box. */
ded34426 1158
5f5c8ee5
GM
1159INLINE void
1160window_box_edges (w, area, top_left_x, top_left_y,
1161 bottom_right_x, bottom_right_y)
1162 struct window *w;
1163 int area;
1164 int *top_left_x, *top_left_y, *bottom_right_x, *bottom_right_y;
48ae5f0a 1165{
5f5c8ee5
GM
1166 window_box (w, area, top_left_x, top_left_y, bottom_right_x,
1167 bottom_right_y);
1168 *bottom_right_x += *top_left_x;
1169 *bottom_right_y += *top_left_y;
48ae5f0a
KH
1170}
1171
5f5c8ee5
GM
1172
1173\f
1174/***********************************************************************
1175 Utilities
1176 ***********************************************************************/
1177
8b6ea97f
GM
1178/* Return the bottom y-position of the line the iterator IT is in.
1179 This can modify IT's settings. */
1180
1181int
1182line_bottom_y (it)
1183 struct it *it;
1184{
1185 int line_height = it->max_ascent + it->max_descent;
1186 int line_top_y = it->current_y;
2311178e 1187
8b6ea97f
GM
1188 if (line_height == 0)
1189 {
1190 if (last_height)
1191 line_height = last_height;
1192 else if (IT_CHARPOS (*it) < ZV)
1193 {
1194 move_it_by_lines (it, 1, 1);
1195 line_height = (it->max_ascent || it->max_descent
1196 ? it->max_ascent + it->max_descent
1197 : last_height);
1198 }
1199 else
1200 {
1201 struct glyph_row *row = it->glyph_row;
2311178e 1202
8b6ea97f
GM
1203 /* Use the default character height. */
1204 it->glyph_row = NULL;
1205 it->what = IT_CHARACTER;
1206 it->c = ' ';
1207 it->len = 1;
1208 PRODUCE_GLYPHS (it);
1209 line_height = it->ascent + it->descent;
1210 it->glyph_row = row;
1211 }
1212 }
1213
1214 return line_top_y + line_height;
1215}
1216
1217
0db95684
GM
1218/* Return 1 if position CHARPOS is visible in window W. Set *FULLY to
1219 1 if POS is visible and the line containing POS is fully visible.
1220 EXACT_MODE_LINE_HEIGHTS_P non-zero means compute exact mode-line
1221 and header-lines heights. */
3a641a69
GM
1222
1223int
04612a64 1224pos_visible_p (w, charpos, fully, exact_mode_line_heights_p)
3a641a69 1225 struct window *w;
04612a64 1226 int charpos, *fully, exact_mode_line_heights_p;
3a641a69
GM
1227{
1228 struct it it;
1229 struct text_pos top;
fcab1954
GM
1230 int visible_p;
1231 struct buffer *old_buffer = NULL;
1232
1233 if (XBUFFER (w->buffer) != current_buffer)
1234 {
1235 old_buffer = current_buffer;
1236 set_buffer_internal_1 (XBUFFER (w->buffer));
1237 }
3a641a69
GM
1238
1239 *fully = visible_p = 0;
1240 SET_TEXT_POS_FROM_MARKER (top, w->start);
2311178e 1241
04612a64
GM
1242 /* Compute exact mode line heights, if requested. */
1243 if (exact_mode_line_heights_p)
1244 {
1245 if (WINDOW_WANTS_MODELINE_P (w))
1246 current_mode_line_height
96d2320f 1247 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
04612a64 1248 current_buffer->mode_line_format);
2311178e 1249
04612a64
GM
1250 if (WINDOW_WANTS_HEADER_LINE_P (w))
1251 current_header_line_height
1252 = display_mode_line (w, HEADER_LINE_FACE_ID,
1253 current_buffer->header_line_format);
1254 }
3a641a69 1255
04612a64 1256 start_display (&it, w, top);
3a641a69
GM
1257 move_it_to (&it, charpos, 0, it.last_visible_y, -1,
1258 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
a13be207
GM
1259
1260 /* Note that we may overshoot because of invisible text. */
1261 if (IT_CHARPOS (it) >= charpos)
3a641a69 1262 {
8b6ea97f
GM
1263 int top_y = it.current_y;
1264 int bottom_y = line_bottom_y (&it);
da8b7f4f 1265 int window_top_y = WINDOW_HEADER_LINE_HEIGHT (w);
2311178e 1266
8b6ea97f
GM
1267 if (top_y < window_top_y)
1268 visible_p = bottom_y > window_top_y;
1269 else if (top_y < it.last_visible_y)
fcab1954
GM
1270 {
1271 visible_p = 1;
8b6ea97f 1272 *fully = bottom_y <= it.last_visible_y;
fcab1954 1273 }
3a641a69
GM
1274 }
1275 else if (it.current_y + it.max_ascent + it.max_descent > it.last_visible_y)
1276 {
1277 move_it_by_lines (&it, 1, 0);
1278 if (charpos < IT_CHARPOS (it))
1279 {
1280 visible_p = 1;
1281 *fully = 0;
1282 }
1283 }
fcab1954
GM
1284
1285 if (old_buffer)
1286 set_buffer_internal_1 (old_buffer);
04612a64
GM
1287
1288 current_header_line_height = current_mode_line_height = -1;
3a641a69
GM
1289 return visible_p;
1290}
1291
1292
4fdb80f2
GM
1293/* Return the next character from STR which is MAXLEN bytes long.
1294 Return in *LEN the length of the character. This is like
1295 STRING_CHAR_AND_LENGTH but never returns an invalid character. If
9ab8560d 1296 we find one, we return a `?', but with the length of the invalid
4fdb80f2
GM
1297 character. */
1298
1299static INLINE int
7a5b8a93 1300string_char_and_length (str, maxlen, len)
50f80c2f 1301 const unsigned char *str;
7a5b8a93 1302 int maxlen, *len;
4fdb80f2
GM
1303{
1304 int c;
1305
1306 c = STRING_CHAR_AND_LENGTH (str, maxlen, *len);
1307 if (!CHAR_VALID_P (c, 1))
1308 /* We may not change the length here because other places in Emacs
9ab8560d 1309 don't use this function, i.e. they silently accept invalid
4fdb80f2
GM
1310 characters. */
1311 c = '?';
1312
1313 return c;
1314}
1315
1316
1317
5f5c8ee5
GM
1318/* Given a position POS containing a valid character and byte position
1319 in STRING, return the position NCHARS ahead (NCHARS >= 0). */
1320
1321static struct text_pos
1322string_pos_nchars_ahead (pos, string, nchars)
1323 struct text_pos pos;
1324 Lisp_Object string;
1325 int nchars;
0b1005ef 1326{
5f5c8ee5
GM
1327 xassert (STRINGP (string) && nchars >= 0);
1328
1329 if (STRING_MULTIBYTE (string))
1330 {
2051c264 1331 int rest = SBYTES (string) - BYTEPOS (pos);
50f80c2f 1332 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
5f5c8ee5
GM
1333 int len;
1334
1335 while (nchars--)
1336 {
4fdb80f2 1337 string_char_and_length (p, rest, &len);
5f5c8ee5
GM
1338 p += len, rest -= len;
1339 xassert (rest >= 0);
1340 CHARPOS (pos) += 1;
1341 BYTEPOS (pos) += len;
1342 }
1343 }
1344 else
1345 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
1346
1347 return pos;
0a9dc68b
RS
1348}
1349
0a9dc68b 1350
5f5c8ee5
GM
1351/* Value is the text position, i.e. character and byte position,
1352 for character position CHARPOS in STRING. */
1353
1354static INLINE struct text_pos
1355string_pos (charpos, string)
1356 int charpos;
0a9dc68b 1357 Lisp_Object string;
0a9dc68b 1358{
5f5c8ee5
GM
1359 struct text_pos pos;
1360 xassert (STRINGP (string));
1361 xassert (charpos >= 0);
1362 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
1363 return pos;
1364}
1365
1366
1367/* Value is a text position, i.e. character and byte position, for
1368 character position CHARPOS in C string S. MULTIBYTE_P non-zero
1369 means recognize multibyte characters. */
1370
1371static struct text_pos
1372c_string_pos (charpos, s, multibyte_p)
1373 int charpos;
1374 unsigned char *s;
1375 int multibyte_p;
1376{
1377 struct text_pos pos;
1378
1379 xassert (s != NULL);
1380 xassert (charpos >= 0);
1381
1382 if (multibyte_p)
0a9dc68b 1383 {
5f5c8ee5
GM
1384 int rest = strlen (s), len;
1385
1386 SET_TEXT_POS (pos, 0, 0);
1387 while (charpos--)
0a9dc68b 1388 {
4fdb80f2 1389 string_char_and_length (s, rest, &len);
5f5c8ee5
GM
1390 s += len, rest -= len;
1391 xassert (rest >= 0);
1392 CHARPOS (pos) += 1;
1393 BYTEPOS (pos) += len;
0a9dc68b
RS
1394 }
1395 }
5f5c8ee5
GM
1396 else
1397 SET_TEXT_POS (pos, charpos, charpos);
0a9dc68b 1398
5f5c8ee5
GM
1399 return pos;
1400}
0a9dc68b 1401
0a9dc68b 1402
5f5c8ee5
GM
1403/* Value is the number of characters in C string S. MULTIBYTE_P
1404 non-zero means recognize multibyte characters. */
0a9dc68b 1405
5f5c8ee5
GM
1406static int
1407number_of_chars (s, multibyte_p)
1408 unsigned char *s;
1409 int multibyte_p;
1410{
1411 int nchars;
2311178e 1412
5f5c8ee5
GM
1413 if (multibyte_p)
1414 {
1415 int rest = strlen (s), len;
1416 unsigned char *p = (unsigned char *) s;
0a9dc68b 1417
5f5c8ee5
GM
1418 for (nchars = 0; rest > 0; ++nchars)
1419 {
4fdb80f2 1420 string_char_and_length (p, rest, &len);
5f5c8ee5 1421 rest -= len, p += len;
0a9dc68b
RS
1422 }
1423 }
5f5c8ee5
GM
1424 else
1425 nchars = strlen (s);
1426
1427 return nchars;
0b1005ef
KH
1428}
1429
2311178e 1430
5f5c8ee5
GM
1431/* Compute byte position NEWPOS->bytepos corresponding to
1432 NEWPOS->charpos. POS is a known position in string STRING.
1433 NEWPOS->charpos must be >= POS.charpos. */
76412d64 1434
5f5c8ee5
GM
1435static void
1436compute_string_pos (newpos, pos, string)
1437 struct text_pos *newpos, pos;
1438 Lisp_Object string;
76412d64 1439{
5f5c8ee5
GM
1440 xassert (STRINGP (string));
1441 xassert (CHARPOS (*newpos) >= CHARPOS (pos));
2311178e 1442
5f5c8ee5 1443 if (STRING_MULTIBYTE (string))
6fc556fd
KR
1444 *newpos = string_pos_nchars_ahead (pos, string,
1445 CHARPOS (*newpos) - CHARPOS (pos));
5f5c8ee5
GM
1446 else
1447 BYTEPOS (*newpos) = CHARPOS (*newpos);
76412d64
RS
1448}
1449
fa3c6b4d
KS
1450/* EXPORT:
1451 Return an estimation of the pixel height of mode or top lines on
1452 frame F. FACE_ID specifies what line's height to estimate. */
1453
1454int
1455estimate_mode_line_height (f, face_id)
1456 struct frame *f;
1457 enum face_id face_id;
1458{
1459#ifdef HAVE_WINDOW_SYSTEM
1460 if (FRAME_WINDOW_P (f))
1461 {
1462 int height = FONT_HEIGHT (FRAME_FONT (f));
1463
1464 /* This function is called so early when Emacs starts that the face
1465 cache and mode line face are not yet initialized. */
1466 if (FRAME_FACE_CACHE (f))
1467 {
1468 struct face *face = FACE_FROM_ID (f, face_id);
1469 if (face)
1470 {
1471 if (face->font)
1472 height = FONT_HEIGHT (face->font);
1473 if (face->box_line_width > 0)
1474 height += 2 * face->box_line_width;
1475 }
1476 }
1477
1478 return height;
1479 }
1480#endif
1481
1482 return 1;
1483}
1484
e080d3eb
KS
1485/* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
1486 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
1487 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
1488 not force the value into range. */
1489
1490void
1491pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
1492 FRAME_PTR f;
1493 register int pix_x, pix_y;
1494 int *x, *y;
1495 NativeRectangle *bounds;
1496 int noclip;
1497{
1498
1499#ifdef HAVE_WINDOW_SYSTEM
1500 if (FRAME_WINDOW_P (f))
1501 {
da8b7f4f 1502 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to round down
e080d3eb
KS
1503 even for negative values. */
1504 if (pix_x < 0)
da8b7f4f 1505 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
e080d3eb 1506 if (pix_y < 0)
da8b7f4f 1507 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
e080d3eb 1508
da8b7f4f
KS
1509 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
1510 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
e080d3eb
KS
1511
1512 if (bounds)
1513 STORE_NATIVE_RECT (*bounds,
da8b7f4f
KS
1514 FRAME_COL_TO_PIXEL_X (f, pix_x),
1515 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
1516 FRAME_COLUMN_WIDTH (f) - 1,
1517 FRAME_LINE_HEIGHT (f) - 1);
e080d3eb
KS
1518
1519 if (!noclip)
1520 {
1521 if (pix_x < 0)
1522 pix_x = 0;
da8b7f4f
KS
1523 else if (pix_x > FRAME_TOTAL_COLS (f))
1524 pix_x = FRAME_TOTAL_COLS (f);
e080d3eb
KS
1525
1526 if (pix_y < 0)
1527 pix_y = 0;
da8b7f4f
KS
1528 else if (pix_y > FRAME_LINES (f))
1529 pix_y = FRAME_LINES (f);
e080d3eb
KS
1530 }
1531 }
1532#endif
1533
1534 *x = pix_x;
1535 *y = pix_y;
1536}
1537
1538
1539/* Given HPOS/VPOS in the current matrix of W, return corresponding
1540 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
1541 can't tell the positions because W's display is not up to date,
1542 return 0. */
1543
1544int
1545glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
1546 struct window *w;
1547 int hpos, vpos;
1548 int *frame_x, *frame_y;
1549{
1550#ifdef HAVE_WINDOW_SYSTEM
1551 if (FRAME_WINDOW_P (XFRAME (WINDOW_FRAME (w))))
1552 {
1553 int success_p;
1554
1555 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
1556 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
1557
1558 if (display_completed)
1559 {
1560 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
1561 struct glyph *glyph = row->glyphs[TEXT_AREA];
1562 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
1563
1564 hpos = row->x;
1565 vpos = row->y;
1566 while (glyph < end)
1567 {
1568 hpos += glyph->pixel_width;
1569 ++glyph;
1570 }
1571
f65536fa
KS
1572 /* If first glyph is partially visible, its first visible position is still 0. */
1573 if (hpos < 0)
1574 hpos = 0;
1575
e080d3eb
KS
1576 success_p = 1;
1577 }
1578 else
1579 {
1580 hpos = vpos = 0;
1581 success_p = 0;
1582 }
1583
1584 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, hpos);
1585 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, vpos);
1586 return success_p;
1587 }
1588#endif
1589
1590 *frame_x = hpos;
1591 *frame_y = vpos;
1592 return 1;
1593}
1594
1595
fa3c6b4d
KS
1596#ifdef HAVE_WINDOW_SYSTEM
1597
1598/* Find the glyph under window-relative coordinates X/Y in window W.
1599 Consider only glyphs from buffer text, i.e. no glyphs from overlay
1600 strings. Return in *HPOS and *VPOS the row and column number of
1601 the glyph found. Return in *AREA the glyph area containing X.
1602 Value is a pointer to the glyph found or null if X/Y is not on
1603 text, or we can't tell because W's current matrix is not up to
1604 date. */
1605
1606static struct glyph *
493fdc3c 1607x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area)
fa3c6b4d
KS
1608 struct window *w;
1609 int x, y;
493fdc3c 1610 int *hpos, *vpos, *dx, *dy, *area;
fa3c6b4d
KS
1611{
1612 struct glyph *glyph, *end;
1613 struct glyph_row *row = NULL;
da8b7f4f 1614 int x0, i;
fa3c6b4d
KS
1615
1616 /* Find row containing Y. Give up if some row is not enabled. */
1617 for (i = 0; i < w->current_matrix->nrows; ++i)
1618 {
1619 row = MATRIX_ROW (w->current_matrix, i);
1620 if (!row->enabled_p)
1621 return NULL;
1622 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
1623 break;
1624 }
1625
1626 *vpos = i;
1627 *hpos = 0;
1628
1629 /* Give up if Y is not in the window. */
1630 if (i == w->current_matrix->nrows)
1631 return NULL;
1632
1633 /* Get the glyph area containing X. */
1634 if (w->pseudo_window_p)
1635 {
1636 *area = TEXT_AREA;
1637 x0 = 0;
1638 }
1639 else
1640 {
da8b7f4f 1641 if (x < window_box_left_offset (w, TEXT_AREA))
fa3c6b4d
KS
1642 {
1643 *area = LEFT_MARGIN_AREA;
da8b7f4f 1644 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
fa3c6b4d 1645 }
da8b7f4f 1646 else if (x < window_box_right_offset (w, TEXT_AREA))
fa3c6b4d
KS
1647 {
1648 *area = TEXT_AREA;
f65536fa 1649 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
fa3c6b4d
KS
1650 }
1651 else
1652 {
1653 *area = RIGHT_MARGIN_AREA;
da8b7f4f 1654 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
fa3c6b4d
KS
1655 }
1656 }
1657
1658 /* Find glyph containing X. */
1659 glyph = row->glyphs[*area];
1660 end = glyph + row->used[*area];
493fdc3c
KS
1661 x -= x0;
1662 while (glyph < end && x >= glyph->pixel_width)
fa3c6b4d 1663 {
493fdc3c 1664 x -= glyph->pixel_width;
fa3c6b4d
KS
1665 ++glyph;
1666 }
1667
1668 if (glyph == end)
1669 return NULL;
1670
493fdc3c
KS
1671 if (dx)
1672 {
1673 *dx = x;
1674 *dy = y - (row->y + row->ascent - glyph->ascent);
1675 }
1676
fa3c6b4d
KS
1677 *hpos = glyph - row->glyphs[*area];
1678 return glyph;
1679}
1680
1681
1682/* EXPORT:
1683 Convert frame-relative x/y to coordinates relative to window W.
1684 Takes pseudo-windows into account. */
1685
1686void
1687frame_to_window_pixel_xy (w, x, y)
1688 struct window *w;
1689 int *x, *y;
1690{
1691 if (w->pseudo_window_p)
1692 {
1693 /* A pseudo-window is always full-width, and starts at the
1694 left edge of the frame, plus a frame border. */
1695 struct frame *f = XFRAME (w->frame);
da8b7f4f 1696 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
fa3c6b4d
KS
1697 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1698 }
1699 else
1700 {
da8b7f4f 1701 *x -= WINDOW_LEFT_EDGE_X (w);
fa3c6b4d
KS
1702 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
1703 }
1704}
1705
1706/* EXPORT:
1707 Return in *R the clipping rectangle for glyph string S. */
1708
1709void
1710get_glyph_string_clip_rect (s, nr)
1711 struct glyph_string *s;
1712 NativeRectangle *nr;
1713{
1714 XRectangle r;
1715
1716 if (s->row->full_width_p)
1717 {
da8b7f4f
KS
1718 /* Draw full-width. X coordinates are relative to S->w->left_col. */
1719 r.x = WINDOW_LEFT_EDGE_X (s->w);
1720 r.width = WINDOW_TOTAL_WIDTH (s->w);
fa3c6b4d
KS
1721
1722 /* Unless displaying a mode or menu bar line, which are always
1723 fully visible, clip to the visible part of the row. */
1724 if (s->w->pseudo_window_p)
1725 r.height = s->row->visible_height;
1726 else
1727 r.height = s->height;
1728 }
1729 else
1730 {
1731 /* This is a text line that may be partially visible. */
da8b7f4f 1732 r.x = window_box_left (s->w, s->area);
fa3c6b4d
KS
1733 r.width = window_box_width (s->w, s->area);
1734 r.height = s->row->visible_height;
1735 }
1736
1737 /* If S draws overlapping rows, it's sufficient to use the top and
1738 bottom of the window for clipping because this glyph string
1739 intentionally draws over other lines. */
1740 if (s->for_overlaps_p)
1741 {
da8b7f4f 1742 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1743 r.height = window_text_bottom_y (s->w) - r.y;
1744 }
1745 else
1746 {
1747 /* Don't use S->y for clipping because it doesn't take partially
1748 visible lines into account. For example, it can be negative for
1749 partially visible lines at the top of a window. */
1750 if (!s->row->full_width_p
1751 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
da8b7f4f 1752 r.y = WINDOW_HEADER_LINE_HEIGHT (s->w);
fa3c6b4d
KS
1753 else
1754 r.y = max (0, s->row->y);
1755
1756 /* If drawing a tool-bar window, draw it over the internal border
1757 at the top of the window. */
1758 if (s->w == XWINDOW (s->f->tool_bar_window))
b4ebbb12 1759 r.y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
fa3c6b4d
KS
1760 }
1761
1762 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
1763
fa3c6b4d
KS
1764 /* If drawing the cursor, don't let glyph draw outside its
1765 advertised boundaries. Cleartype does this under some circumstances. */
1766 if (s->hl == DRAW_CURSOR)
1767 {
493fdc3c
KS
1768 struct glyph *glyph = s->first_glyph;
1769 int height;
1770
fa3c6b4d
KS
1771 if (s->x > r.x)
1772 {
1773 r.width -= s->x - r.x;
1774 r.x = s->x;
1775 }
493fdc3c
KS
1776 r.width = min (r.width, glyph->pixel_width);
1777
1778 /* Don't draw cursor glyph taller than our actual glyph. */
1779 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
1780 if (height < r.height)
1781 {
1782 r.y = s->ybase + glyph->descent - height;
1783 r.height = height;
1784 }
fa3c6b4d 1785 }
fa3c6b4d
KS
1786
1787#ifdef CONVERT_FROM_XRECT
1788 CONVERT_FROM_XRECT (r, *nr);
1789#else
1790 *nr = r;
fd4c9408 1791#endif
fa3c6b4d
KS
1792}
1793
1794#endif /* HAVE_WINDOW_SYSTEM */
9c74a0dd 1795
5f5c8ee5
GM
1796\f
1797/***********************************************************************
1798 Lisp form evaluation
1799 ***********************************************************************/
1800
116d6f5c 1801/* Error handler for safe_eval and safe_call. */
5f5c8ee5
GM
1802
1803static Lisp_Object
116d6f5c 1804safe_eval_handler (arg)
5f5c8ee5
GM
1805 Lisp_Object arg;
1806{
0dbf9fd2 1807 add_to_log ("Error during redisplay: %s", arg, Qnil);
5f5c8ee5
GM
1808 return Qnil;
1809}
1810
1811
1812/* Evaluate SEXPR and return the result, or nil if something went
2913a9c0 1813 wrong. Prevent redisplay during the evaluation. */
5f5c8ee5 1814
71e5b1b8 1815Lisp_Object
116d6f5c 1816safe_eval (sexpr)
5f5c8ee5
GM
1817 Lisp_Object sexpr;
1818{
5f5c8ee5 1819 Lisp_Object val;
2311178e 1820
30a3f61c
GM
1821 if (inhibit_eval_during_redisplay)
1822 val = Qnil;
1823 else
1824 {
331379bf 1825 int count = SPECPDL_INDEX ();
30a3f61c 1826 struct gcpro gcpro1;
0d8b31c0 1827
30a3f61c
GM
1828 GCPRO1 (sexpr);
1829 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1830 /* Use Qt to ensure debugger does not run,
1831 so there is no possibility of wanting to redisplay. */
1832 val = internal_condition_case_1 (Feval, sexpr, Qt,
30a3f61c
GM
1833 safe_eval_handler);
1834 UNGCPRO;
1835 val = unbind_to (count, val);
1836 }
2311178e 1837
30a3f61c 1838 return val;
0d8b31c0
GM
1839}
1840
1841
1842/* Call function ARGS[0] with arguments ARGS[1] to ARGS[NARGS - 1].
2913a9c0
GM
1843 Return the result, or nil if something went wrong. Prevent
1844 redisplay during the evaluation. */
0d8b31c0
GM
1845
1846Lisp_Object
116d6f5c 1847safe_call (nargs, args)
0d8b31c0
GM
1848 int nargs;
1849 Lisp_Object *args;
1850{
0d8b31c0 1851 Lisp_Object val;
2311178e 1852
30a3f61c
GM
1853 if (inhibit_eval_during_redisplay)
1854 val = Qnil;
1855 else
1856 {
331379bf 1857 int count = SPECPDL_INDEX ();
30a3f61c 1858 struct gcpro gcpro1;
0d8b31c0 1859
30a3f61c
GM
1860 GCPRO1 (args[0]);
1861 gcpro1.nvars = nargs;
1862 specbind (Qinhibit_redisplay, Qt);
7033d6df
RS
1863 /* Use Qt to ensure debugger does not run,
1864 so there is no possibility of wanting to redisplay. */
1865 val = internal_condition_case_2 (Ffuncall, nargs, args, Qt,
30a3f61c
GM
1866 safe_eval_handler);
1867 UNGCPRO;
1868 val = unbind_to (count, val);
1869 }
1870
1871 return val;
5f5c8ee5
GM
1872}
1873
1874
116d6f5c
GM
1875/* Call function FN with one argument ARG.
1876 Return the result, or nil if something went wrong. */
1877
1878Lisp_Object
1879safe_call1 (fn, arg)
1880 Lisp_Object fn, arg;
1881{
1882 Lisp_Object args[2];
1883 args[0] = fn;
1884 args[1] = arg;
1885 return safe_call (2, args);
1886}
1887
1888
5f5c8ee5
GM
1889\f
1890/***********************************************************************
1891 Debugging
1892 ***********************************************************************/
1893
1894#if 0
1895
1896/* Define CHECK_IT to perform sanity checks on iterators.
1897 This is for debugging. It is too slow to do unconditionally. */
1898
1899static void
1900check_it (it)
1901 struct it *it;
1902{
1903 if (it->method == next_element_from_string)
a2889657 1904 {
5f5c8ee5
GM
1905 xassert (STRINGP (it->string));
1906 xassert (IT_STRING_CHARPOS (*it) >= 0);
1907 }
1908 else if (it->method == next_element_from_buffer)
1909 {
1910 /* Check that character and byte positions agree. */
1911 xassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
1912 }
73af359d 1913
5f5c8ee5
GM
1914 if (it->dpvec)
1915 xassert (it->current.dpvec_index >= 0);
1916 else
1917 xassert (it->current.dpvec_index < 0);
1918}
1f40cad2 1919
5f5c8ee5
GM
1920#define CHECK_IT(IT) check_it ((IT))
1921
1922#else /* not 0 */
1923
1924#define CHECK_IT(IT) (void) 0
1925
1926#endif /* not 0 */
1927
1928
1929#if GLYPH_DEBUG
1930
1931/* Check that the window end of window W is what we expect it
1932 to be---the last row in the current matrix displaying text. */
1933
1934static void
1935check_window_end (w)
1936 struct window *w;
1937{
1938 if (!MINI_WINDOW_P (w)
1939 && !NILP (w->window_end_valid))
1940 {
1941 struct glyph_row *row;
1942 xassert ((row = MATRIX_ROW (w->current_matrix,
1943 XFASTINT (w->window_end_vpos)),
1944 !row->enabled_p
1945 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
1946 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
1947 }
1948}
1949
1950#define CHECK_WINDOW_END(W) check_window_end ((W))
1951
1952#else /* not GLYPH_DEBUG */
1953
1954#define CHECK_WINDOW_END(W) (void) 0
1955
1956#endif /* not GLYPH_DEBUG */
1957
1958
1959\f
1960/***********************************************************************
1961 Iterator initialization
1962 ***********************************************************************/
1963
1964/* Initialize IT for displaying current_buffer in window W, starting
1965 at character position CHARPOS. CHARPOS < 0 means that no buffer
1966 position is specified which is useful when the iterator is assigned
1967 a position later. BYTEPOS is the byte position corresponding to
3ebf0ea9 1968 CHARPOS. BYTEPOS < 0 means compute it from CHARPOS.
5f5c8ee5
GM
1969
1970 If ROW is not null, calls to produce_glyphs with IT as parameter
1971 will produce glyphs in that row.
1972
1973 BASE_FACE_ID is the id of a base face to use. It must be one of
96d2320f
KS
1974 DEFAULT_FACE_ID for normal text, MODE_LINE_FACE_ID,
1975 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID for displaying
1976 mode lines, or TOOL_BAR_FACE_ID for displaying the tool-bar.
2311178e 1977
96d2320f
KS
1978 If ROW is null and BASE_FACE_ID is equal to MODE_LINE_FACE_ID,
1979 MODE_LINE_INACTIVE_FACE_ID, or HEADER_LINE_FACE_ID, the iterator
1980 will be initialized to use the corresponding mode line glyph row of
1981 the desired matrix of W. */
5f5c8ee5
GM
1982
1983void
1984init_iterator (it, w, charpos, bytepos, row, base_face_id)
1985 struct it *it;
1986 struct window *w;
1987 int charpos, bytepos;
1988 struct glyph_row *row;
1989 enum face_id base_face_id;
1990{
1991 int highlight_region_p;
5f5c8ee5
GM
1992
1993 /* Some precondition checks. */
1994 xassert (w != NULL && it != NULL);
3b6b6db7
SM
1995 xassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
1996 && charpos <= ZV));
5f5c8ee5
GM
1997
1998 /* If face attributes have been changed since the last redisplay,
1999 free realized faces now because they depend on face definitions
7d0393cf 2000 that might have changed. Don't free faces while there might be
1987b083 2001 desired matrices pending which reference these faces. */
26683087 2002 if (face_change_count && !inhibit_free_realized_faces)
5f5c8ee5
GM
2003 {
2004 face_change_count = 0;
2005 free_all_realized_faces (Qnil);
2006 }
2007
2008 /* Use one of the mode line rows of W's desired matrix if
2009 appropriate. */
2010 if (row == NULL)
2011 {
96d2320f
KS
2012 if (base_face_id == MODE_LINE_FACE_ID
2013 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
5f5c8ee5 2014 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
045dee35
GM
2015 else if (base_face_id == HEADER_LINE_FACE_ID)
2016 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
5f5c8ee5 2017 }
2311178e 2018
5f5c8ee5
GM
2019 /* Clear IT. */
2020 bzero (it, sizeof *it);
2021 it->current.overlay_string_index = -1;
2022 it->current.dpvec_index = -1;
5f5c8ee5
GM
2023 it->base_face_id = base_face_id;
2024
2025 /* The window in which we iterate over current_buffer: */
2026 XSETWINDOW (it->window, w);
2027 it->w = w;
2028 it->f = XFRAME (w->frame);
2029
d475bcb8
GM
2030 /* Extra space between lines (on window systems only). */
2031 if (base_face_id == DEFAULT_FACE_ID
2032 && FRAME_WINDOW_P (it->f))
2033 {
2034 if (NATNUMP (current_buffer->extra_line_spacing))
2035 it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
2036 else if (it->f->extra_line_spacing > 0)
2037 it->extra_line_spacing = it->f->extra_line_spacing;
2038 }
2039
5f5c8ee5 2040 /* If realized faces have been removed, e.g. because of face
62be9979
GM
2041 attribute changes of named faces, recompute them. When running
2042 in batch mode, the face cache of Vterminal_frame is null. If
2043 we happen to get called, make a dummy face cache. */
a24d4cb2 2044 if (noninteractive && FRAME_FACE_CACHE (it->f) == NULL)
62be9979 2045 init_frame_faces (it->f);
5f5c8ee5
GM
2046 if (FRAME_FACE_CACHE (it->f)->used == 0)
2047 recompute_basic_faces (it->f);
2048
5f5c8ee5
GM
2049 /* Current value of the `space-width', and 'height' properties. */
2050 it->space_width = Qnil;
2051 it->font_height = Qnil;
2311178e 2052
5f5c8ee5
GM
2053 /* Are control characters displayed as `^C'? */
2054 it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
2055
2056 /* -1 means everything between a CR and the following line end
2057 is invisible. >0 means lines indented more than this value are
2058 invisible. */
2059 it->selective = (INTEGERP (current_buffer->selective_display)
2060 ? XFASTINT (current_buffer->selective_display)
2311178e 2061 : (!NILP (current_buffer->selective_display)
5f5c8ee5
GM
2062 ? -1 : 0));
2063 it->selective_display_ellipsis_p
2064 = !NILP (current_buffer->selective_display_ellipses);
2065
2066 /* Display table to use. */
2067 it->dp = window_display_table (w);
2068
2069 /* Are multibyte characters enabled in current_buffer? */
2070 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
2071
2072 /* Non-zero if we should highlight the region. */
2073 highlight_region_p
3ebf0ea9 2074 = (!NILP (Vtransient_mark_mode)
5f5c8ee5
GM
2075 && !NILP (current_buffer->mark_active)
2076 && XMARKER (current_buffer->mark)->buffer != 0);
2077
2078 /* Set IT->region_beg_charpos and IT->region_end_charpos to the
2079 start and end of a visible region in window IT->w. Set both to
2080 -1 to indicate no region. */
2081 if (highlight_region_p
2082 /* Maybe highlight only in selected window. */
2311178e 2083 && (/* Either show region everywhere. */
5f5c8ee5
GM
2084 highlight_nonselected_windows
2085 /* Or show region in the selected window. */
2086 || w == XWINDOW (selected_window)
2087 /* Or show the region if we are in the mini-buffer and W is
2088 the window the mini-buffer refers to. */
2089 || (MINI_WINDOW_P (XWINDOW (selected_window))
5705966b
KS
2090 && WINDOWP (minibuf_selected_window)
2091 && w == XWINDOW (minibuf_selected_window))))
5f5c8ee5
GM
2092 {
2093 int charpos = marker_position (current_buffer->mark);
2094 it->region_beg_charpos = min (PT, charpos);
2095 it->region_end_charpos = max (PT, charpos);
2096 }
2097 else
2098 it->region_beg_charpos = it->region_end_charpos = -1;
2099
2100 /* Get the position at which the redisplay_end_trigger hook should
2101 be run, if it is to be run at all. */
2102 if (MARKERP (w->redisplay_end_trigger)
2103 && XMARKER (w->redisplay_end_trigger)->buffer != 0)
2104 it->redisplay_end_trigger_charpos
2105 = marker_position (w->redisplay_end_trigger);
2106 else if (INTEGERP (w->redisplay_end_trigger))
2107 it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
2108
2109 /* Correct bogus values of tab_width. */
2110 it->tab_width = XINT (current_buffer->tab_width);
2111 if (it->tab_width <= 0 || it->tab_width > 1000)
2112 it->tab_width = 8;
2113
2114 /* Are lines in the display truncated? */
2115 it->truncate_lines_p
2116 = (base_face_id != DEFAULT_FACE_ID
2117 || XINT (it->w->hscroll)
2118 || (truncate_partial_width_windows
2119 && !WINDOW_FULL_WIDTH_P (it->w))
2120 || !NILP (current_buffer->truncate_lines));
2121
2122 /* Get dimensions of truncation and continuation glyphs. These are
b46952ae 2123 displayed as fringe bitmaps under X, so we don't need them for such
5f5c8ee5
GM
2124 frames. */
2125 if (!FRAME_WINDOW_P (it->f))
2126 {
2127 if (it->truncate_lines_p)
2128 {
2129 /* We will need the truncation glyph. */
2130 xassert (it->glyph_row == NULL);
2131 produce_special_glyphs (it, IT_TRUNCATION);
2132 it->truncation_pixel_width = it->pixel_width;
2133 }
2134 else
2135 {
2136 /* We will need the continuation glyph. */
2137 xassert (it->glyph_row == NULL);
2138 produce_special_glyphs (it, IT_CONTINUATION);
2139 it->continuation_pixel_width = it->pixel_width;
2140 }
2141
153c2160 2142 /* Reset these values to zero because the produce_special_glyphs
5f5c8ee5
GM
2143 above has changed them. */
2144 it->pixel_width = it->ascent = it->descent = 0;
312246d1 2145 it->phys_ascent = it->phys_descent = 0;
5f5c8ee5
GM
2146 }
2147
2148 /* Set this after getting the dimensions of truncation and
2149 continuation glyphs, so that we don't produce glyphs when calling
2150 produce_special_glyphs, above. */
2151 it->glyph_row = row;
2152 it->area = TEXT_AREA;
2153
2154 /* Get the dimensions of the display area. The display area
2155 consists of the visible window area plus a horizontally scrolled
2156 part to the left of the window. All x-values are relative to the
2157 start of this total display area. */
2158 if (base_face_id != DEFAULT_FACE_ID)
2159 {
2160 /* Mode lines, menu bar in terminal frames. */
2161 it->first_visible_x = 0;
da8b7f4f 2162 it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
5f5c8ee5
GM
2163 }
2164 else
2165 {
2166 it->first_visible_x
da8b7f4f 2167 = XFASTINT (it->w->hscroll) * FRAME_COLUMN_WIDTH (it->f);
5f5c8ee5
GM
2168 it->last_visible_x = (it->first_visible_x
2169 + window_box_width (w, TEXT_AREA));
2170
2171 /* If we truncate lines, leave room for the truncator glyph(s) at
2172 the right margin. Otherwise, leave room for the continuation
2173 glyph(s). Truncation and continuation glyphs are not inserted
2174 for window-based redisplay. */
2175 if (!FRAME_WINDOW_P (it->f))
2176 {
2177 if (it->truncate_lines_p)
2178 it->last_visible_x -= it->truncation_pixel_width;
2179 else
2180 it->last_visible_x -= it->continuation_pixel_width;
2181 }
2182
045dee35 2183 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
da8b7f4f 2184 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
5f5c8ee5
GM
2185 }
2186
2187 /* Leave room for a border glyph. */
2188 if (!FRAME_WINDOW_P (it->f)
2189 && !WINDOW_RIGHTMOST_P (it->w))
2190 it->last_visible_x -= 1;
2191
2192 it->last_visible_y = window_text_bottom_y (w);
2193
2194 /* For mode lines and alike, arrange for the first glyph having a
2195 left box line if the face specifies a box. */
2196 if (base_face_id != DEFAULT_FACE_ID)
2197 {
2198 struct face *face;
2311178e 2199
5f5c8ee5
GM
2200 it->face_id = base_face_id;
2201
2202 /* If we have a boxed mode line, make the first character appear
2203 with a left box line. */
2204 face = FACE_FROM_ID (it->f, base_face_id);
2205 if (face->box != FACE_NO_BOX)
2206 it->start_of_box_run_p = 1;
2207 }
2208
2209 /* If a buffer position was specified, set the iterator there,
2210 getting overlays and face properties from that position. */
3ebf0ea9 2211 if (charpos >= BUF_BEG (current_buffer))
5f5c8ee5
GM
2212 {
2213 it->end_charpos = ZV;
2214 it->face_id = -1;
2215 IT_CHARPOS (*it) = charpos;
2311178e 2216
5f5c8ee5 2217 /* Compute byte position if not specified. */
3ebf0ea9 2218 if (bytepos < charpos)
5f5c8ee5
GM
2219 IT_BYTEPOS (*it) = CHAR_TO_BYTE (charpos);
2220 else
2221 IT_BYTEPOS (*it) = bytepos;
2222
29b3ea63
KS
2223 it->start = it->current;
2224
5f5c8ee5
GM
2225 /* Compute faces etc. */
2226 reseat (it, it->current.pos, 1);
2227 }
2311178e 2228
5f5c8ee5
GM
2229 CHECK_IT (it);
2230}
2231
2232
2233/* Initialize IT for the display of window W with window start POS. */
2234
2235void
2236start_display (it, w, pos)
2237 struct it *it;
2238 struct window *w;
2239 struct text_pos pos;
2240{
5f5c8ee5 2241 struct glyph_row *row;
045dee35 2242 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
5f5c8ee5
GM
2243
2244 row = w->desired_matrix->rows + first_vpos;
2245 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3ccb8bcf 2246 it->first_vpos = first_vpos;
17fdcfc8
GM
2247
2248 if (!it->truncate_lines_p)
5f5c8ee5 2249 {
17fdcfc8
GM
2250 int start_at_line_beg_p;
2251 int first_y = it->current_y;
2311178e 2252
17fdcfc8
GM
2253 /* If window start is not at a line start, skip forward to POS to
2254 get the correct continuation lines width. */
2255 start_at_line_beg_p = (CHARPOS (pos) == BEGV
2256 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
2257 if (!start_at_line_beg_p)
5f5c8ee5 2258 {
0e47bbf7
RS
2259 int new_x;
2260
17fdcfc8
GM
2261 reseat_at_previous_visible_line_start (it);
2262 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
2263
0e47bbf7
RS
2264 new_x = it->current_x + it->pixel_width;
2265
17fdcfc8
GM
2266 /* If lines are continued, this line may end in the middle
2267 of a multi-glyph character (e.g. a control character
2268 displayed as \003, or in the middle of an overlay
2269 string). In this case move_it_to above will not have
2270 taken us to the start of the continuation line but to the
2271 end of the continued line. */
0e47bbf7
RS
2272 if (it->current_x > 0
2273 && !it->truncate_lines_p /* Lines are continued. */
2274 && (/* And glyph doesn't fit on the line. */
2275 new_x > it->last_visible_x
2276 /* Or it fits exactly and we're on a window
2277 system frame. */
2278 || (new_x == it->last_visible_x
2279 && FRAME_WINDOW_P (it->f))))
5f5c8ee5 2280 {
b28cb6ed
GM
2281 if (it->current.dpvec_index >= 0
2282 || it->current.overlay_string_index >= 0)
2283 {
cafafe0b 2284 set_iterator_to_next (it, 1);
b28cb6ed
GM
2285 move_it_in_display_line_to (it, -1, -1, 0);
2286 }
2311178e 2287
b28cb6ed 2288 it->continuation_lines_width += it->current_x;
5f5c8ee5 2289 }
b28cb6ed
GM
2290
2291 /* We're starting a new display line, not affected by the
2292 height of the continued line, so clear the appropriate
2293 fields in the iterator structure. */
2294 it->max_ascent = it->max_descent = 0;
2295 it->max_phys_ascent = it->max_phys_descent = 0;
2311178e 2296
17fdcfc8
GM
2297 it->current_y = first_y;
2298 it->vpos = 0;
2299 it->current_x = it->hpos = 0;
2300 }
5f5c8ee5
GM
2301 }
2302
2303#if 0 /* Don't assert the following because start_display is sometimes
2304 called intentionally with a window start that is not at a
2305 line start. Please leave this code in as a comment. */
2311178e 2306
5f5c8ee5
GM
2307 /* Window start should be on a line start, now. */
2308 xassert (it->continuation_lines_width
2309 || IT_CHARPOS (it) == BEGV
2310 || FETCH_BYTE (IT_BYTEPOS (it) - 1) == '\n');
2311#endif /* 0 */
2312}
2313
2314
4bde0ebb
GM
2315/* Return 1 if POS is a position in ellipses displayed for invisible
2316 text. W is the window we display, for text property lookup. */
5f5c8ee5 2317
4bde0ebb
GM
2318static int
2319in_ellipses_for_invisible_text_p (pos, w)
5f5c8ee5 2320 struct display_pos *pos;
4bde0ebb 2321 struct window *w;
5f5c8ee5 2322{
ac90c44f 2323 Lisp_Object prop, window;
4bde0ebb
GM
2324 int ellipses_p = 0;
2325 int charpos = CHARPOS (pos->pos);
2311178e 2326
ac90c44f
GM
2327 /* If POS specifies a position in a display vector, this might
2328 be for an ellipsis displayed for invisible text. We won't
2329 get the iterator set up for delivering that ellipsis unless
2330 we make sure that it gets aware of the invisible text. */
2331 if (pos->dpvec_index >= 0
2332 && pos->overlay_string_index < 0
2333 && CHARPOS (pos->string_pos) < 0
2334 && charpos > BEGV
2335 && (XSETWINDOW (window, w),
2336 prop = Fget_char_property (make_number (charpos),
2337 Qinvisible, window),
20fbd925 2338 !TEXT_PROP_MEANS_INVISIBLE (prop)))
ac90c44f
GM
2339 {
2340 prop = Fget_char_property (make_number (charpos - 1), Qinvisible,
2341 window);
8580a4e3 2342 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
4bde0ebb
GM
2343 }
2344
2345 return ellipses_p;
2346}
2347
2348
2349/* Initialize IT for stepping through current_buffer in window W,
2350 starting at position POS that includes overlay string and display
47d57b22
GM
2351 vector/ control character translation position information. Value
2352 is zero if there are overlay strings with newlines at POS. */
4bde0ebb 2353
47d57b22 2354static int
4bde0ebb
GM
2355init_from_display_pos (it, w, pos)
2356 struct it *it;
2357 struct window *w;
2358 struct display_pos *pos;
2359{
2360 int charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
47d57b22 2361 int i, overlay_strings_with_newlines = 0;
2311178e 2362
4bde0ebb
GM
2363 /* If POS specifies a position in a display vector, this might
2364 be for an ellipsis displayed for invisible text. We won't
2365 get the iterator set up for delivering that ellipsis unless
2366 we make sure that it gets aware of the invisible text. */
2367 if (in_ellipses_for_invisible_text_p (pos, w))
2368 {
2369 --charpos;
2370 bytepos = 0;
ac90c44f 2371 }
2311178e 2372
5f5c8ee5
GM
2373 /* Keep in mind: the call to reseat in init_iterator skips invisible
2374 text, so we might end up at a position different from POS. This
2375 is only a problem when POS is a row start after a newline and an
2376 overlay starts there with an after-string, and the overlay has an
2377 invisible property. Since we don't skip invisible text in
2378 display_line and elsewhere immediately after consuming the
2379 newline before the row start, such a POS will not be in a string,
2380 but the call to init_iterator below will move us to the
2381 after-string. */
ac90c44f 2382 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
5f5c8ee5 2383
47d57b22 2384 for (i = 0; i < it->n_overlay_strings; ++i)
1e1e5daf 2385 {
50f80c2f
KR
2386 const char *s = SDATA (it->overlay_strings[i]);
2387 const char *e = s + SBYTES (it->overlay_strings[i]);
2311178e 2388
1e1e5daf
GM
2389 while (s < e && *s != '\n')
2390 ++s;
2391
2392 if (s < e)
2393 {
2394 overlay_strings_with_newlines = 1;
2395 break;
2396 }
2397 }
47d57b22 2398
75c5350a
GM
2399 /* If position is within an overlay string, set up IT to the right
2400 overlay string. */
5f5c8ee5
GM
2401 if (pos->overlay_string_index >= 0)
2402 {
2403 int relative_index;
75c5350a
GM
2404
2405 /* If the first overlay string happens to have a `display'
2406 property for an image, the iterator will be set up for that
2407 image, and we have to undo that setup first before we can
2408 correct the overlay string index. */
2409 if (it->method == next_element_from_image)
2410 pop_it (it);
2311178e 2411
5f5c8ee5
GM
2412 /* We already have the first chunk of overlay strings in
2413 IT->overlay_strings. Load more until the one for
2414 pos->overlay_string_index is in IT->overlay_strings. */
2415 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
2416 {
2417 int n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
2418 it->current.overlay_string_index = 0;
2419 while (n--)
2420 {
5a08cbaf 2421 load_overlay_strings (it, 0);
5f5c8ee5
GM
2422 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
2423 }
2424 }
2311178e 2425
5f5c8ee5
GM
2426 it->current.overlay_string_index = pos->overlay_string_index;
2427 relative_index = (it->current.overlay_string_index
2428 % OVERLAY_STRING_CHUNK_SIZE);
2429 it->string = it->overlay_strings[relative_index];
cafafe0b 2430 xassert (STRINGP (it->string));
5f5c8ee5
GM
2431 it->current.string_pos = pos->string_pos;
2432 it->method = next_element_from_string;
2433 }
2311178e 2434
1e1e5daf
GM
2435#if 0 /* This is bogus because POS not having an overlay string
2436 position does not mean it's after the string. Example: A
2437 line starting with a before-string and initialization of IT
2438 to the previous row's end position. */
2be8f184
GM
2439 else if (it->current.overlay_string_index >= 0)
2440 {
2441 /* If POS says we're already after an overlay string ending at
2442 POS, make sure to pop the iterator because it will be in
2443 front of that overlay string. When POS is ZV, we've thereby
2444 also ``processed'' overlay strings at ZV. */
aeb2b8fc
GM
2445 while (it->sp)
2446 pop_it (it);
2be8f184
GM
2447 it->current.overlay_string_index = -1;
2448 it->method = next_element_from_buffer;
2449 if (CHARPOS (pos->pos) == ZV)
2450 it->overlay_strings_at_end_processed_p = 1;
2451 }
1e1e5daf 2452#endif /* 0 */
2311178e 2453
2be8f184 2454 if (CHARPOS (pos->string_pos) >= 0)
5f5c8ee5
GM
2455 {
2456 /* Recorded position is not in an overlay string, but in another
2457 string. This can only be a string from a `display' property.
2458 IT should already be filled with that string. */
2459 it->current.string_pos = pos->string_pos;
2460 xassert (STRINGP (it->string));
2461 }
2462
ac90c44f
GM
2463 /* Restore position in display vector translations, control
2464 character translations or ellipses. */
5f5c8ee5
GM
2465 if (pos->dpvec_index >= 0)
2466 {
ac90c44f
GM
2467 if (it->dpvec == NULL)
2468 get_next_display_element (it);
5f5c8ee5
GM
2469 xassert (it->dpvec && it->current.dpvec_index == 0);
2470 it->current.dpvec_index = pos->dpvec_index;
2471 }
2311178e 2472
5f5c8ee5 2473 CHECK_IT (it);
47d57b22 2474 return !overlay_strings_with_newlines;
5f5c8ee5
GM
2475}
2476
2477
2478/* Initialize IT for stepping through current_buffer in window W
2479 starting at ROW->start. */
2480
2481static void
2482init_to_row_start (it, w, row)
2483 struct it *it;
2484 struct window *w;
2485 struct glyph_row *row;
2486{
2487 init_from_display_pos (it, w, &row->start);
29b3ea63 2488 it->start = row->start;
5f5c8ee5
GM
2489 it->continuation_lines_width = row->continuation_lines_width;
2490 CHECK_IT (it);
2491}
2492
2311178e 2493
5f5c8ee5 2494/* Initialize IT for stepping through current_buffer in window W
47d57b22
GM
2495 starting in the line following ROW, i.e. starting at ROW->end.
2496 Value is zero if there are overlay strings with newlines at ROW's
2497 end position. */
5f5c8ee5 2498
47d57b22 2499static int
5f5c8ee5
GM
2500init_to_row_end (it, w, row)
2501 struct it *it;
2502 struct window *w;
2503 struct glyph_row *row;
2504{
47d57b22 2505 int success = 0;
2311178e 2506
47d57b22
GM
2507 if (init_from_display_pos (it, w, &row->end))
2508 {
2509 if (row->continued_p)
2510 it->continuation_lines_width
2511 = row->continuation_lines_width + row->pixel_width;
2512 CHECK_IT (it);
2513 success = 1;
2514 }
2311178e 2515
47d57b22 2516 return success;
5f5c8ee5
GM
2517}
2518
2519
2520
2521\f
2522/***********************************************************************
2523 Text properties
2524 ***********************************************************************/
2525
2526/* Called when IT reaches IT->stop_charpos. Handle text property and
2527 overlay changes. Set IT->stop_charpos to the next position where
2528 to stop. */
2529
2530static void
2531handle_stop (it)
2532 struct it *it;
2533{
2534 enum prop_handled handled;
2535 int handle_overlay_change_p = 1;
2536 struct props *p;
2537
2538 it->dpvec = NULL;
2539 it->current.dpvec_index = -1;
2540
2541 do
2542 {
2543 handled = HANDLED_NORMALLY;
2311178e 2544
5f5c8ee5
GM
2545 /* Call text property handlers. */
2546 for (p = it_props; p->handler; ++p)
2547 {
2548 handled = p->handler (it);
2970b9be 2549
5f5c8ee5
GM
2550 if (handled == HANDLED_RECOMPUTE_PROPS)
2551 break;
2552 else if (handled == HANDLED_RETURN)
2553 return;
2554 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
2555 handle_overlay_change_p = 0;
2556 }
2557
2558 if (handled != HANDLED_RECOMPUTE_PROPS)
2559 {
2560 /* Don't check for overlay strings below when set to deliver
2561 characters from a display vector. */
2562 if (it->method == next_element_from_display_vector)
2563 handle_overlay_change_p = 0;
2564
2565 /* Handle overlay changes. */
2566 if (handle_overlay_change_p)
2567 handled = handle_overlay_change (it);
2311178e 2568
5f5c8ee5
GM
2569 /* Determine where to stop next. */
2570 if (handled == HANDLED_NORMALLY)
2571 compute_stop_pos (it);
2572 }
2573 }
2574 while (handled == HANDLED_RECOMPUTE_PROPS);
2575}
2576
2577
2578/* Compute IT->stop_charpos from text property and overlay change
2579 information for IT's current position. */
2580
2581static void
2582compute_stop_pos (it)
2583 struct it *it;
2584{
2585 register INTERVAL iv, next_iv;
2586 Lisp_Object object, limit, position;
2587
2588 /* If nowhere else, stop at the end. */
2589 it->stop_charpos = it->end_charpos;
2311178e 2590
5f5c8ee5
GM
2591 if (STRINGP (it->string))
2592 {
2593 /* Strings are usually short, so don't limit the search for
2594 properties. */
2595 object = it->string;
2596 limit = Qnil;
ac90c44f 2597 position = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
2598 }
2599 else
2600 {
2601 int charpos;
2602
2603 /* If next overlay change is in front of the current stop pos
2604 (which is IT->end_charpos), stop there. Note: value of
2605 next_overlay_change is point-max if no overlay change
2606 follows. */
2607 charpos = next_overlay_change (IT_CHARPOS (*it));
2608 if (charpos < it->stop_charpos)
2609 it->stop_charpos = charpos;
2610
2611 /* If showing the region, we have to stop at the region
2612 start or end because the face might change there. */
2613 if (it->region_beg_charpos > 0)
2614 {
2615 if (IT_CHARPOS (*it) < it->region_beg_charpos)
2616 it->stop_charpos = min (it->stop_charpos, it->region_beg_charpos);
2617 else if (IT_CHARPOS (*it) < it->region_end_charpos)
2618 it->stop_charpos = min (it->stop_charpos, it->region_end_charpos);
2619 }
2311178e 2620
5f5c8ee5
GM
2621 /* Set up variables for computing the stop position from text
2622 property changes. */
2623 XSETBUFFER (object, current_buffer);
ac90c44f
GM
2624 limit = make_number (IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT);
2625 position = make_number (IT_CHARPOS (*it));
5f5c8ee5
GM
2626
2627 }
2628
2629 /* Get the interval containing IT's position. Value is a null
2630 interval if there isn't such an interval. */
2631 iv = validate_interval_range (object, &position, &position, 0);
2632 if (!NULL_INTERVAL_P (iv))
2633 {
2634 Lisp_Object values_here[LAST_PROP_IDX];
2635 struct props *p;
2636
2637 /* Get properties here. */
2638 for (p = it_props; p->handler; ++p)
2639 values_here[p->idx] = textget (iv->plist, *p->name);
2640
2641 /* Look for an interval following iv that has different
2642 properties. */
2643 for (next_iv = next_interval (iv);
2644 (!NULL_INTERVAL_P (next_iv)
2645 && (NILP (limit)
2646 || XFASTINT (limit) > next_iv->position));
2647 next_iv = next_interval (next_iv))
2648 {
2649 for (p = it_props; p->handler; ++p)
2650 {
2651 Lisp_Object new_value;
2652
2653 new_value = textget (next_iv->plist, *p->name);
2654 if (!EQ (values_here[p->idx], new_value))
2655 break;
2656 }
2311178e 2657
5f5c8ee5
GM
2658 if (p->handler)
2659 break;
2660 }
2661
2662 if (!NULL_INTERVAL_P (next_iv))
2663 {
2664 if (INTEGERP (limit)
2665 && next_iv->position >= XFASTINT (limit))
2666 /* No text property change up to limit. */
2667 it->stop_charpos = min (XFASTINT (limit), it->stop_charpos);
2668 else
2669 /* Text properties change in next_iv. */
2670 it->stop_charpos = min (it->stop_charpos, next_iv->position);
2671 }
2672 }
2673
2674 xassert (STRINGP (it->string)
2675 || (it->stop_charpos >= BEGV
2676 && it->stop_charpos >= IT_CHARPOS (*it)));
2677}
2678
2679
2680/* Return the position of the next overlay change after POS in
2681 current_buffer. Value is point-max if no overlay change
2682 follows. This is like `next-overlay-change' but doesn't use
2683 xmalloc. */
2684
2685static int
2686next_overlay_change (pos)
2687 int pos;
2688{
2689 int noverlays;
2690 int endpos;
2691 Lisp_Object *overlays;
2692 int len;
2693 int i;
2694
2695 /* Get all overlays at the given position. */
2696 len = 10;
2697 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2698 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2699 if (noverlays > len)
2700 {
2701 len = noverlays;
2702 overlays = (Lisp_Object *) alloca (len * sizeof *overlays);
a0315a63 2703 noverlays = overlays_at (pos, 0, &overlays, &len, &endpos, NULL, 1);
5f5c8ee5
GM
2704 }
2705
2706 /* If any of these overlays ends before endpos,
2707 use its ending point instead. */
2708 for (i = 0; i < noverlays; ++i)
2709 {
2710 Lisp_Object oend;
2711 int oendpos;
2712
2713 oend = OVERLAY_END (overlays[i]);
2714 oendpos = OVERLAY_POSITION (oend);
2715 endpos = min (endpos, oendpos);
2716 }
2717
2718 return endpos;
2719}
2720
2721
2722\f
2723/***********************************************************************
2724 Fontification
2725 ***********************************************************************/
2726
2727/* Handle changes in the `fontified' property of the current buffer by
2728 calling hook functions from Qfontification_functions to fontify
2729 regions of text. */
2730
2731static enum prop_handled
2732handle_fontified_prop (it)
2733 struct it *it;
2734{
2735 Lisp_Object prop, pos;
2736 enum prop_handled handled = HANDLED_NORMALLY;
2737
2738 /* Get the value of the `fontified' property at IT's current buffer
2739 position. (The `fontified' property doesn't have a special
2740 meaning in strings.) If the value is nil, call functions from
2741 Qfontification_functions. */
2742 if (!STRINGP (it->string)
2743 && it->s == NULL
2744 && !NILP (Vfontification_functions)
085536c2 2745 && !NILP (Vrun_hooks)
5f5c8ee5
GM
2746 && (pos = make_number (IT_CHARPOS (*it)),
2747 prop = Fget_char_property (pos, Qfontified, Qnil),
2748 NILP (prop)))
2749 {
331379bf 2750 int count = SPECPDL_INDEX ();
085536c2
GM
2751 Lisp_Object val;
2752
2753 val = Vfontification_functions;
2754 specbind (Qfontification_functions, Qnil);
2311178e 2755
085536c2 2756 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
116d6f5c 2757 safe_call1 (val, pos);
085536c2
GM
2758 else
2759 {
2760 Lisp_Object globals, fn;
2761 struct gcpro gcpro1, gcpro2;
5f5c8ee5 2762
085536c2
GM
2763 globals = Qnil;
2764 GCPRO2 (val, globals);
2311178e 2765
085536c2
GM
2766 for (; CONSP (val); val = XCDR (val))
2767 {
2768 fn = XCAR (val);
2311178e 2769
085536c2
GM
2770 if (EQ (fn, Qt))
2771 {
2772 /* A value of t indicates this hook has a local
2773 binding; it means to run the global binding too.
2774 In a global value, t should not occur. If it
2775 does, we must ignore it to avoid an endless
2776 loop. */
2777 for (globals = Fdefault_value (Qfontification_functions);
2778 CONSP (globals);
2779 globals = XCDR (globals))
2780 {
2781 fn = XCAR (globals);
2782 if (!EQ (fn, Qt))
116d6f5c 2783 safe_call1 (fn, pos);
085536c2
GM
2784 }
2785 }
2786 else
116d6f5c 2787 safe_call1 (fn, pos);
085536c2
GM
2788 }
2789
2790 UNGCPRO;
2791 }
2792
2793 unbind_to (count, Qnil);
5f5c8ee5
GM
2794
2795 /* Return HANDLED_RECOMPUTE_PROPS only if function fontified
2796 something. This avoids an endless loop if they failed to
2797 fontify the text for which reason ever. */
2798 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
2799 handled = HANDLED_RECOMPUTE_PROPS;
2800 }
2801
2802 return handled;
2803}
2804
2805
2806\f
2807/***********************************************************************
2808 Faces
2809 ***********************************************************************/
2810
2811/* Set up iterator IT from face properties at its current position.
2812 Called from handle_stop. */
2813
2814static enum prop_handled
2815handle_face_prop (it)
2816 struct it *it;
2817{
2818 int new_face_id, next_stop;
2311178e 2819
5f5c8ee5
GM
2820 if (!STRINGP (it->string))
2821 {
2822 new_face_id
2823 = face_at_buffer_position (it->w,
2824 IT_CHARPOS (*it),
2825 it->region_beg_charpos,
2826 it->region_end_charpos,
2827 &next_stop,
2828 (IT_CHARPOS (*it)
2829 + TEXT_PROP_DISTANCE_LIMIT),
2830 0);
2311178e 2831
5f5c8ee5
GM
2832 /* Is this a start of a run of characters with box face?
2833 Caveat: this can be called for a freshly initialized
4b41cebb 2834 iterator; face_id is -1 in this case. We know that the new
5f5c8ee5
GM
2835 face will not change until limit, i.e. if the new face has a
2836 box, all characters up to limit will have one. But, as
2837 usual, we don't know whether limit is really the end. */
2838 if (new_face_id != it->face_id)
2839 {
2840 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2311178e 2841
5f5c8ee5
GM
2842 /* If new face has a box but old face has not, this is
2843 the start of a run of characters with box, i.e. it has
2844 a shadow on the left side. The value of face_id of the
2845 iterator will be -1 if this is the initial call that gets
2846 the face. In this case, we have to look in front of IT's
2847 position and see whether there is a face != new_face_id. */
2848 it->start_of_box_run_p
2849 = (new_face->box != FACE_NO_BOX
2850 && (it->face_id >= 0
2851 || IT_CHARPOS (*it) == BEG
2852 || new_face_id != face_before_it_pos (it)));
2853 it->face_box_p = new_face->box != FACE_NO_BOX;
2854 }
2855 }
2856 else
2857 {
06a12811
GM
2858 int base_face_id, bufpos;
2859
2860 if (it->current.overlay_string_index >= 0)
2861 bufpos = IT_CHARPOS (*it);
2862 else
2863 bufpos = 0;
2311178e 2864
06a12811
GM
2865 /* For strings from a buffer, i.e. overlay strings or strings
2866 from a `display' property, use the face at IT's current
2867 buffer position as the base face to merge with, so that
2868 overlay strings appear in the same face as surrounding
2869 text, unless they specify their own faces. */
2870 base_face_id = underlying_face_id (it);
2311178e 2871
06a12811
GM
2872 new_face_id = face_at_string_position (it->w,
2873 it->string,
2874 IT_STRING_CHARPOS (*it),
2875 bufpos,
2876 it->region_beg_charpos,
2877 it->region_end_charpos,
2878 &next_stop,
5de7c6f2 2879 base_face_id, 0);
2311178e 2880
5f5c8ee5
GM
2881#if 0 /* This shouldn't be neccessary. Let's check it. */
2882 /* If IT is used to display a mode line we would really like to
2883 use the mode line face instead of the frame's default face. */
2884 if (it->glyph_row == MATRIX_MODE_LINE_ROW (it->w->desired_matrix)
2885 && new_face_id == DEFAULT_FACE_ID)
96d2320f 2886 new_face_id = CURRENT_MODE_LINE_FACE_ID (it->w);
5f5c8ee5 2887#endif
2311178e 2888
5f5c8ee5
GM
2889 /* Is this a start of a run of characters with box? Caveat:
2890 this can be called for a freshly allocated iterator; face_id
2891 is -1 is this case. We know that the new face will not
2892 change until the next check pos, i.e. if the new face has a
2893 box, all characters up to that position will have a
2894 box. But, as usual, we don't know whether that position
2895 is really the end. */
2896 if (new_face_id != it->face_id)
2897 {
2898 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
2899 struct face *old_face = FACE_FROM_ID (it->f, it->face_id);
2311178e 2900
5f5c8ee5
GM
2901 /* If new face has a box but old face hasn't, this is the
2902 start of a run of characters with box, i.e. it has a
2903 shadow on the left side. */
2904 it->start_of_box_run_p
2905 = new_face->box && (old_face == NULL || !old_face->box);
2906 it->face_box_p = new_face->box != FACE_NO_BOX;
2907 }
2908 }
2311178e 2909
5f5c8ee5 2910 it->face_id = new_face_id;
5f5c8ee5
GM
2911 return HANDLED_NORMALLY;
2912}
2913
2914
06a12811
GM
2915/* Return the ID of the face ``underlying'' IT's current position,
2916 which is in a string. If the iterator is associated with a
2917 buffer, return the face at IT's current buffer position.
2918 Otherwise, use the iterator's base_face_id. */
2919
2920static int
2921underlying_face_id (it)
2922 struct it *it;
2923{
2924 int face_id = it->base_face_id, i;
2925
2926 xassert (STRINGP (it->string));
2927
2928 for (i = it->sp - 1; i >= 0; --i)
2929 if (NILP (it->stack[i].string))
2930 face_id = it->stack[i].face_id;
2931
2932 return face_id;
2933}
2934
2935
5f5c8ee5
GM
2936/* Compute the face one character before or after the current position
2937 of IT. BEFORE_P non-zero means get the face in front of IT's
2938 position. Value is the id of the face. */
2939
2940static int
2941face_before_or_after_it_pos (it, before_p)
2942 struct it *it;
2943 int before_p;
2944{
2945 int face_id, limit;
2946 int next_check_charpos;
2947 struct text_pos pos;
2948
2949 xassert (it->s == NULL);
2311178e 2950
5f5c8ee5
GM
2951 if (STRINGP (it->string))
2952 {
06a12811 2953 int bufpos, base_face_id;
2311178e 2954
5f5c8ee5
GM
2955 /* No face change past the end of the string (for the case
2956 we are padding with spaces). No face change before the
2957 string start. */
2051c264 2958 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
5f5c8ee5
GM
2959 || (IT_STRING_CHARPOS (*it) == 0 && before_p))
2960 return it->face_id;
2961
2962 /* Set pos to the position before or after IT's current position. */
2963 if (before_p)
2964 pos = string_pos (IT_STRING_CHARPOS (*it) - 1, it->string);
2965 else
260a86a0
KH
2966 /* For composition, we must check the character after the
2967 composition. */
2968 pos = (it->what == IT_COMPOSITION
2969 ? string_pos (IT_STRING_CHARPOS (*it) + it->cmp_len, it->string)
2970 : string_pos (IT_STRING_CHARPOS (*it) + 1, it->string));
5f5c8ee5 2971
06a12811
GM
2972 if (it->current.overlay_string_index >= 0)
2973 bufpos = IT_CHARPOS (*it);
2974 else
2975 bufpos = 0;
2976
2977 base_face_id = underlying_face_id (it);
2978
5f5c8ee5 2979 /* Get the face for ASCII, or unibyte. */
06a12811
GM
2980 face_id = face_at_string_position (it->w,
2981 it->string,
2982 CHARPOS (pos),
2983 bufpos,
2984 it->region_beg_charpos,
2985 it->region_end_charpos,
2986 &next_check_charpos,
5de7c6f2 2987 base_face_id, 0);
5f5c8ee5
GM
2988
2989 /* Correct the face for charsets different from ASCII. Do it
2990 for the multibyte case only. The face returned above is
2991 suitable for unibyte text if IT->string is unibyte. */
2992 if (STRING_MULTIBYTE (it->string))
2993 {
50f80c2f 2994 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos);
2051c264 2995 int rest = SBYTES (it->string) - BYTEPOS (pos);
980806b6
KH
2996 int c, len;
2997 struct face *face = FACE_FROM_ID (it->f, face_id);
2311178e 2998
4fdb80f2 2999 c = string_char_and_length (p, rest, &len);
980806b6 3000 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
3001 }
3002 }
3003 else
3004 {
70851746
GM
3005 if ((IT_CHARPOS (*it) >= ZV && !before_p)
3006 || (IT_CHARPOS (*it) <= BEGV && before_p))
3007 return it->face_id;
2311178e 3008
5f5c8ee5
GM
3009 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
3010 pos = it->current.pos;
2311178e 3011
5f5c8ee5 3012 if (before_p)
c1005d06 3013 DEC_TEXT_POS (pos, it->multibyte_p);
5f5c8ee5 3014 else
260a86a0
KH
3015 {
3016 if (it->what == IT_COMPOSITION)
3017 /* For composition, we must check the position after the
3018 composition. */
3019 pos.charpos += it->cmp_len, pos.bytepos += it->len;
3020 else
c1005d06 3021 INC_TEXT_POS (pos, it->multibyte_p);
260a86a0 3022 }
2311178e 3023
5f5c8ee5
GM
3024 /* Determine face for CHARSET_ASCII, or unibyte. */
3025 face_id = face_at_buffer_position (it->w,
3026 CHARPOS (pos),
3027 it->region_beg_charpos,
3028 it->region_end_charpos,
3029 &next_check_charpos,
3030 limit, 0);
3031
3032 /* Correct the face for charsets different from ASCII. Do it
3033 for the multibyte case only. The face returned above is
3034 suitable for unibyte text if current_buffer is unibyte. */
3035 if (it->multibyte_p)
3036 {
1d1b6e6a 3037 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
980806b6
KH
3038 struct face *face = FACE_FROM_ID (it->f, face_id);
3039 face_id = FACE_FOR_CHAR (it->f, face, c);
5f5c8ee5
GM
3040 }
3041 }
2311178e 3042
5f5c8ee5
GM
3043 return face_id;
3044}
3045
3046
3047\f
3048/***********************************************************************
3049 Invisible text
3050 ***********************************************************************/
3051
3052/* Set up iterator IT from invisible properties at its current
3053 position. Called from handle_stop. */
3054
3055static enum prop_handled
3056handle_invisible_prop (it)
3057 struct it *it;
3058{
3059 enum prop_handled handled = HANDLED_NORMALLY;
3060
3061 if (STRINGP (it->string))
3062 {
3063 extern Lisp_Object Qinvisible;
3064 Lisp_Object prop, end_charpos, limit, charpos;
3065
3066 /* Get the value of the invisible text property at the
3067 current position. Value will be nil if there is no such
3068 property. */
ac90c44f 3069 charpos = make_number (IT_STRING_CHARPOS (*it));
5f5c8ee5
GM
3070 prop = Fget_text_property (charpos, Qinvisible, it->string);
3071
eadc0bf8
GM
3072 if (!NILP (prop)
3073 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3074 {
3075 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3076
5f5c8ee5
GM
3077 /* Get the position at which the next change of the
3078 invisible text property can be found in IT->string.
3079 Value will be nil if the property value is the same for
3080 all the rest of IT->string. */
2051c264 3081 XSETINT (limit, SCHARS (it->string));
5f5c8ee5 3082 end_charpos = Fnext_single_property_change (charpos, Qinvisible,
2051c264 3083 it->string, limit);
2311178e 3084
5f5c8ee5
GM
3085 /* Text at current position is invisible. The next
3086 change in the property is at position end_charpos.
3087 Move IT's current position to that position. */
3088 if (INTEGERP (end_charpos)
3089 && XFASTINT (end_charpos) < XFASTINT (limit))
3090 {
3091 struct text_pos old;
3092 old = it->current.string_pos;
3093 IT_STRING_CHARPOS (*it) = XFASTINT (end_charpos);
3094 compute_string_pos (&it->current.string_pos, old, it->string);
3095 }
3096 else
3097 {
3098 /* The rest of the string is invisible. If this is an
3099 overlay string, proceed with the next overlay string
3100 or whatever comes and return a character from there. */
3101 if (it->current.overlay_string_index >= 0)
3102 {
3103 next_overlay_string (it);
3104 /* Don't check for overlay strings when we just
3105 finished processing them. */
3106 handled = HANDLED_OVERLAY_STRING_CONSUMED;
3107 }
3108 else
3109 {
2051c264
GM
3110 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
3111 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5f5c8ee5
GM
3112 }
3113 }
3114 }
3115 }
3116 else
3117 {
8580a4e3 3118 int invis_p, newpos, next_stop, start_charpos;
5a08cbaf 3119 Lisp_Object pos, prop, overlay;
5f5c8ee5
GM
3120
3121 /* First of all, is there invisible text at this position? */
5a08cbaf 3122 start_charpos = IT_CHARPOS (*it);
ac90c44f 3123 pos = make_number (IT_CHARPOS (*it));
5a08cbaf
GM
3124 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
3125 &overlay);
8580a4e3
SM
3126 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
3127
5f5c8ee5 3128 /* If we are on invisible text, skip over it. */
8580a4e3 3129 if (invis_p && IT_CHARPOS (*it) < it->end_charpos)
5f5c8ee5
GM
3130 {
3131 /* Record whether we have to display an ellipsis for the
3132 invisible text. */
8580a4e3 3133 int display_ellipsis_p = invis_p == 2;
5f5c8ee5
GM
3134
3135 handled = HANDLED_RECOMPUTE_PROPS;
2311178e 3136
5f5c8ee5
GM
3137 /* Loop skipping over invisible text. The loop is left at
3138 ZV or with IT on the first char being visible again. */
3139 do
3140 {
3141 /* Try to skip some invisible text. Return value is the
3142 position reached which can be equal to IT's position
3143 if there is nothing invisible here. This skips both
3144 over invisible text properties and overlays with
3145 invisible property. */
3146 newpos = skip_invisible (IT_CHARPOS (*it),
3147 &next_stop, ZV, it->window);
3148
3149 /* If we skipped nothing at all we weren't at invisible
3150 text in the first place. If everything to the end of
3151 the buffer was skipped, end the loop. */
3152 if (newpos == IT_CHARPOS (*it) || newpos >= ZV)
8580a4e3 3153 invis_p = 0;
5f5c8ee5
GM
3154 else
3155 {
3156 /* We skipped some characters but not necessarily
3157 all there are. Check if we ended up on visible
3158 text. Fget_char_property returns the property of
3159 the char before the given position, i.e. if we
8580a4e3 3160 get invis_p = 0, this means that the char at
5f5c8ee5 3161 newpos is visible. */
ac90c44f 3162 pos = make_number (newpos);
5f5c8ee5 3163 prop = Fget_char_property (pos, Qinvisible, it->window);
8580a4e3 3164 invis_p = TEXT_PROP_MEANS_INVISIBLE (prop);
5f5c8ee5 3165 }
2311178e 3166
5f5c8ee5
GM
3167 /* If we ended up on invisible text, proceed to
3168 skip starting with next_stop. */
8580a4e3 3169 if (invis_p)
5f5c8ee5
GM
3170 IT_CHARPOS (*it) = next_stop;
3171 }
8580a4e3 3172 while (invis_p);
5a08cbaf 3173
5f5c8ee5
GM
3174 /* The position newpos is now either ZV or on visible text. */
3175 IT_CHARPOS (*it) = newpos;
3176 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
2311178e 3177
5a08cbaf
GM
3178 /* If there are before-strings at the start of invisible
3179 text, and the text is invisible because of a text
3180 property, arrange to show before-strings because 20.x did
3181 it that way. (If the text is invisible because of an
3182 overlay property instead of a text property, this is
3183 already handled in the overlay code.) */
3184 if (NILP (overlay)
3185 && get_overlay_strings (it, start_charpos))
5f5c8ee5 3186 {
5a08cbaf
GM
3187 handled = HANDLED_RECOMPUTE_PROPS;
3188 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5f5c8ee5 3189 }
5a08cbaf
GM
3190 else if (display_ellipsis_p)
3191 setup_for_ellipsis (it);
5f5c8ee5
GM
3192 }
3193 }
3194
3195 return handled;
3196}
3197
3198
5a08cbaf
GM
3199/* Make iterator IT return `...' next. */
3200
3201static void
3202setup_for_ellipsis (it)
3203 struct it *it;
3204{
2311178e 3205 if (it->dp
5a08cbaf
GM
3206 && VECTORP (DISP_INVIS_VECTOR (it->dp)))
3207 {
3208 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
3209 it->dpvec = v->contents;
3210 it->dpend = v->contents + v->size;
3211 }
2311178e 3212 else
5a08cbaf
GM
3213 {
3214 /* Default `...'. */
3215 it->dpvec = default_invis_vector;
3216 it->dpend = default_invis_vector + 3;
3217 }
2311178e 3218
5a08cbaf
GM
3219 /* The ellipsis display does not replace the display of the
3220 character at the new position. Indicate this by setting
3221 IT->dpvec_char_len to zero. */
3222 it->dpvec_char_len = 0;
2311178e 3223
5a08cbaf
GM
3224 it->current.dpvec_index = 0;
3225 it->method = next_element_from_display_vector;
3226}
3227
3228
5f5c8ee5
GM
3229\f
3230/***********************************************************************
3231 'display' property
3232 ***********************************************************************/
3233
3234/* Set up iterator IT from `display' property at its current position.
3235 Called from handle_stop. */
3236
3237static enum prop_handled
3238handle_display_prop (it)
3239 struct it *it;
3240{
3241 Lisp_Object prop, object;
3242 struct text_pos *position;
a61b7058 3243 int display_replaced_p = 0;
5f5c8ee5
GM
3244
3245 if (STRINGP (it->string))
3246 {
3247 object = it->string;
3248 position = &it->current.string_pos;
3249 }
3250 else
3251 {
221dd3e7 3252 object = it->w->buffer;
5f5c8ee5
GM
3253 position = &it->current.pos;
3254 }
3255
3256 /* Reset those iterator values set from display property values. */
3257 it->font_height = Qnil;
3258 it->space_width = Qnil;
3259 it->voffset = 0;
3260
3261 /* We don't support recursive `display' properties, i.e. string
3262 values that have a string `display' property, that have a string
3263 `display' property etc. */
3264 if (!it->string_from_display_prop_p)
3265 it->area = TEXT_AREA;
3266
3267 prop = Fget_char_property (make_number (position->charpos),
3268 Qdisplay, object);
3269 if (NILP (prop))
3270 return HANDLED_NORMALLY;
3271
f3751a65 3272 if (CONSP (prop)
12700f40
GM
3273 /* Simple properties. */
3274 && !EQ (XCAR (prop), Qimage)
3275 && !EQ (XCAR (prop), Qspace)
3276 && !EQ (XCAR (prop), Qwhen)
3277 && !EQ (XCAR (prop), Qspace_width)
3278 && !EQ (XCAR (prop), Qheight)
3279 && !EQ (XCAR (prop), Qraise)
3280 /* Marginal area specifications. */
3281 && !(CONSP (XCAR (prop)) && EQ (XCAR (XCAR (prop)), Qmargin))
3282 && !NILP (XCAR (prop)))
5f5c8ee5 3283 {
a61b7058 3284 for (; CONSP (prop); prop = XCDR (prop))
5f5c8ee5 3285 {
a61b7058
GM
3286 if (handle_single_display_prop (it, XCAR (prop), object,
3287 position, display_replaced_p))
3288 display_replaced_p = 1;
5f5c8ee5
GM
3289 }
3290 }
3291 else if (VECTORP (prop))
3292 {
3293 int i;
a61b7058
GM
3294 for (i = 0; i < ASIZE (prop); ++i)
3295 if (handle_single_display_prop (it, AREF (prop, i), object,
3296 position, display_replaced_p))
3297 display_replaced_p = 1;
5f5c8ee5
GM
3298 }
3299 else
3300 {
a61b7058
GM
3301 if (handle_single_display_prop (it, prop, object, position, 0))
3302 display_replaced_p = 1;
5f5c8ee5
GM
3303 }
3304
a61b7058 3305 return display_replaced_p ? HANDLED_RETURN : HANDLED_NORMALLY;
5f5c8ee5
GM
3306}
3307
3308
6c577098 3309/* Value is the position of the end of the `display' property starting
5f5c8ee5
GM
3310 at START_POS in OBJECT. */
3311
3312static struct text_pos
3313display_prop_end (it, object, start_pos)
3314 struct it *it;
3315 Lisp_Object object;
3316 struct text_pos start_pos;
3317{
3318 Lisp_Object end;
3319 struct text_pos end_pos;
5f5c8ee5 3320
016b5642
MB
3321 end = Fnext_single_char_property_change (make_number (CHARPOS (start_pos)),
3322 Qdisplay, object, Qnil);
6c577098
GM
3323 CHARPOS (end_pos) = XFASTINT (end);
3324 if (STRINGP (object))
5f5c8ee5
GM
3325 compute_string_pos (&end_pos, start_pos, it->string);
3326 else
6c577098 3327 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFASTINT (end));
5f5c8ee5
GM
3328
3329 return end_pos;
3330}
3331
3332
3333/* Set up IT from a single `display' sub-property value PROP. OBJECT
3334 is the object in which the `display' property was found. *POSITION
a61b7058
GM
3335 is the position at which it was found. DISPLAY_REPLACED_P non-zero
3336 means that we previously saw a display sub-property which already
3337 replaced text display with something else, for example an image;
3338 ignore such properties after the first one has been processed.
5f5c8ee5
GM
3339
3340 If PROP is a `space' or `image' sub-property, set *POSITION to the
3341 end position of the `display' property.
3342
4b41cebb 3343 Value is non-zero if something was found which replaces the display
a61b7058 3344 of buffer or string text. */
5f5c8ee5
GM
3345
3346static int
a61b7058
GM
3347handle_single_display_prop (it, prop, object, position,
3348 display_replaced_before_p)
5f5c8ee5
GM
3349 struct it *it;
3350 Lisp_Object prop;
3351 Lisp_Object object;
3352 struct text_pos *position;
a61b7058 3353 int display_replaced_before_p;
5f5c8ee5
GM
3354{
3355 Lisp_Object value;
a61b7058 3356 int replaces_text_display_p = 0;
5f5c8ee5
GM
3357 Lisp_Object form;
3358
d3acf96b 3359 /* If PROP is a list of the form `(when FORM . VALUE)', FORM is
4b41cebb 3360 evaluated. If the result is nil, VALUE is ignored. */
5f5c8ee5 3361 form = Qt;
d3acf96b 3362 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
5f5c8ee5
GM
3363 {
3364 prop = XCDR (prop);
3365 if (!CONSP (prop))
3366 return 0;
3367 form = XCAR (prop);
3368 prop = XCDR (prop);
5f5c8ee5
GM
3369 }
3370
3371 if (!NILP (form) && !EQ (form, Qt))
3372 {
331379bf 3373 int count = SPECPDL_INDEX ();
5f5c8ee5 3374 struct gcpro gcpro1;
5f5c8ee5 3375
b384d6f8
GM
3376 /* Bind `object' to the object having the `display' property, a
3377 buffer or string. Bind `position' to the position in the
3378 object where the property was found, and `buffer-position'
3379 to the current position in the buffer. */
3380 specbind (Qobject, object);
31ac723b
SM
3381 specbind (Qposition, make_number (CHARPOS (*position)));
3382 specbind (Qbuffer_position,
3383 make_number (STRINGP (object)
3384 ? IT_CHARPOS (*it) : CHARPOS (*position)));
b384d6f8 3385 GCPRO1 (form);
116d6f5c 3386 form = safe_eval (form);
b384d6f8
GM
3387 UNGCPRO;
3388 unbind_to (count, Qnil);
5f5c8ee5 3389 }
2311178e 3390
5f5c8ee5
GM
3391 if (NILP (form))
3392 return 0;
3393
3394 if (CONSP (prop)
3395 && EQ (XCAR (prop), Qheight)
3396 && CONSP (XCDR (prop)))
3397 {
e4093f38 3398 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
5f5c8ee5 3399 return 0;
2311178e 3400
5f5c8ee5
GM
3401 /* `(height HEIGHT)'. */
3402 it->font_height = XCAR (XCDR (prop));
3403 if (!NILP (it->font_height))
3404 {
3405 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3406 int new_height = -1;
3407
3408 if (CONSP (it->font_height)
3409 && (EQ (XCAR (it->font_height), Qplus)
3410 || EQ (XCAR (it->font_height), Qminus))
3411 && CONSP (XCDR (it->font_height))
3412 && INTEGERP (XCAR (XCDR (it->font_height))))
3413 {
3414 /* `(+ N)' or `(- N)' where N is an integer. */
3415 int steps = XINT (XCAR (XCDR (it->font_height)));
3416 if (EQ (XCAR (it->font_height), Qplus))
3417 steps = - steps;
3418 it->face_id = smaller_face (it->f, it->face_id, steps);
3419 }
0d8b31c0 3420 else if (FUNCTIONP (it->font_height))
5f5c8ee5
GM
3421 {
3422 /* Call function with current height as argument.
3423 Value is the new height. */
116d6f5c
GM
3424 Lisp_Object height;
3425 height = safe_call1 (it->font_height,
3426 face->lface[LFACE_HEIGHT_INDEX]);
5f5c8ee5
GM
3427 if (NUMBERP (height))
3428 new_height = XFLOATINT (height);
5f5c8ee5
GM
3429 }
3430 else if (NUMBERP (it->font_height))
3431 {
3432 /* Value is a multiple of the canonical char height. */
3433 struct face *face;
2311178e 3434
5f5c8ee5
GM
3435 face = FACE_FROM_ID (it->f, DEFAULT_FACE_ID);
3436 new_height = (XFLOATINT (it->font_height)
3437 * XINT (face->lface[LFACE_HEIGHT_INDEX]));
3438 }
3439 else
3440 {
3441 /* Evaluate IT->font_height with `height' bound to the
3442 current specified height to get the new height. */
3443 Lisp_Object value;
331379bf 3444 int count = SPECPDL_INDEX ();
2311178e 3445
5f5c8ee5 3446 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
116d6f5c 3447 value = safe_eval (it->font_height);
5f5c8ee5 3448 unbind_to (count, Qnil);
2311178e 3449
5f5c8ee5
GM
3450 if (NUMBERP (value))
3451 new_height = XFLOATINT (value);
3452 }
2311178e 3453
5f5c8ee5
GM
3454 if (new_height > 0)
3455 it->face_id = face_with_height (it->f, it->face_id, new_height);
3456 }
3457 }
3458 else if (CONSP (prop)
3459 && EQ (XCAR (prop), Qspace_width)
3460 && CONSP (XCDR (prop)))
3461 {
3462 /* `(space_width WIDTH)'. */
e4093f38 3463 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3464 return 0;
2311178e 3465
5f5c8ee5
GM
3466 value = XCAR (XCDR (prop));
3467 if (NUMBERP (value) && XFLOATINT (value) > 0)
3468 it->space_width = value;
3469 }
3470 else if (CONSP (prop)
3471 && EQ (XCAR (prop), Qraise)
3472 && CONSP (XCDR (prop)))
3473 {
5f5c8ee5 3474 /* `(raise FACTOR)'. */
e4093f38 3475 if (FRAME_TERMCAP_P (it->f) || FRAME_MSDOS_P (it->f))
bafb434c 3476 return 0;
2311178e 3477
fb3842a8 3478#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
3479 value = XCAR (XCDR (prop));
3480 if (NUMBERP (value))
3481 {
3482 struct face *face = FACE_FROM_ID (it->f, it->face_id);
3483 it->voffset = - (XFLOATINT (value)
1ab3e082 3484 * (FONT_HEIGHT (face->font)));
5f5c8ee5
GM
3485 }
3486#endif /* HAVE_WINDOW_SYSTEM */
3487 }
3488 else if (!it->string_from_display_prop_p)
3489 {
f3751a65 3490 /* `((margin left-margin) VALUE)' or `((margin right-margin)
4b41cebb 3491 VALUE) or `((margin nil) VALUE)' or VALUE. */
5f5c8ee5
GM
3492 Lisp_Object location, value;
3493 struct text_pos start_pos;
3494 int valid_p;
3495
3496 /* Characters having this form of property are not displayed, so
3497 we have to find the end of the property. */
5f5c8ee5
GM
3498 start_pos = *position;
3499 *position = display_prop_end (it, object, start_pos);
15e26c76 3500 value = Qnil;
5f5c8ee5
GM
3501
3502 /* Let's stop at the new position and assume that all
3503 text properties change there. */
3504 it->stop_charpos = position->charpos;
3505
f3751a65
GM
3506 location = Qunbound;
3507 if (CONSP (prop) && CONSP (XCAR (prop)))
5f5c8ee5 3508 {
f3751a65 3509 Lisp_Object tem;
2311178e 3510
5f5c8ee5 3511 value = XCDR (prop);
f3751a65
GM
3512 if (CONSP (value))
3513 value = XCAR (value);
3514
3515 tem = XCAR (prop);
3516 if (EQ (XCAR (tem), Qmargin)
3517 && (tem = XCDR (tem),
3518 tem = CONSP (tem) ? XCAR (tem) : Qnil,
3519 (NILP (tem)
3520 || EQ (tem, Qleft_margin)
3521 || EQ (tem, Qright_margin))))
3522 location = tem;
5f5c8ee5 3523 }
f3751a65
GM
3524
3525 if (EQ (location, Qunbound))
5f5c8ee5
GM
3526 {
3527 location = Qnil;
3528 value = prop;
3529 }
3530
3531#ifdef HAVE_WINDOW_SYSTEM
fb3842a8 3532 if (FRAME_TERMCAP_P (it->f))
5f5c8ee5
GM
3533 valid_p = STRINGP (value);
3534 else
3535 valid_p = (STRINGP (value)
3536 || (CONSP (value) && EQ (XCAR (value), Qspace))
3537 || valid_image_p (value));
3538#else /* not HAVE_WINDOW_SYSTEM */
3539 valid_p = STRINGP (value);
3540#endif /* not HAVE_WINDOW_SYSTEM */
2311178e 3541
5f5c8ee5
GM
3542 if ((EQ (location, Qleft_margin)
3543 || EQ (location, Qright_margin)
3544 || NILP (location))
a61b7058
GM
3545 && valid_p
3546 && !display_replaced_before_p)
5f5c8ee5 3547 {
a61b7058 3548 replaces_text_display_p = 1;
2311178e 3549
5f5c8ee5
GM
3550 /* Save current settings of IT so that we can restore them
3551 when we are finished with the glyph property value. */
3552 push_it (it);
2311178e 3553
5f5c8ee5
GM
3554 if (NILP (location))
3555 it->area = TEXT_AREA;
3556 else if (EQ (location, Qleft_margin))
3557 it->area = LEFT_MARGIN_AREA;
3558 else
3559 it->area = RIGHT_MARGIN_AREA;
2311178e 3560
5f5c8ee5
GM
3561 if (STRINGP (value))
3562 {
3563 it->string = value;
3564 it->multibyte_p = STRING_MULTIBYTE (it->string);
3565 it->current.overlay_string_index = -1;
3566 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
2051c264 3567 it->end_charpos = it->string_nchars = SCHARS (it->string);
5f5c8ee5
GM
3568 it->method = next_element_from_string;
3569 it->stop_charpos = 0;
3570 it->string_from_display_prop_p = 1;
e187cf71
GM
3571 /* Say that we haven't consumed the characters with
3572 `display' property yet. The call to pop_it in
3573 set_iterator_to_next will clean this up. */
3574 *position = start_pos;
5f5c8ee5
GM
3575 }
3576 else if (CONSP (value) && EQ (XCAR (value), Qspace))
3577 {
3578 it->method = next_element_from_stretch;
3579 it->object = value;
3580 it->current.pos = it->position = start_pos;
3581 }
3582#ifdef HAVE_WINDOW_SYSTEM
3583 else
3584 {
3585 it->what = IT_IMAGE;
3586 it->image_id = lookup_image (it->f, value);
3587 it->position = start_pos;
3588 it->object = NILP (object) ? it->w->buffer : object;
3589 it->method = next_element_from_image;
2311178e 3590
02513cdd 3591 /* Say that we haven't consumed the characters with
5f5c8ee5
GM
3592 `display' property yet. The call to pop_it in
3593 set_iterator_to_next will clean this up. */
3594 *position = start_pos;
3595 }
3596#endif /* HAVE_WINDOW_SYSTEM */
3597 }
a21a3943
GM
3598 else
3599 /* Invalid property or property not supported. Restore
3600 the position to what it was before. */
3601 *position = start_pos;
5f5c8ee5
GM
3602 }
3603
a61b7058 3604 return replaces_text_display_p;
5f5c8ee5
GM
3605}
3606
3607
06568bbf
GM
3608/* Check if PROP is a display sub-property value whose text should be
3609 treated as intangible. */
3610
3611static int
3612single_display_prop_intangible_p (prop)
3613 Lisp_Object prop;
3614{
3615 /* Skip over `when FORM'. */
3616 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3617 {
3618 prop = XCDR (prop);
3619 if (!CONSP (prop))
3620 return 0;
3621 prop = XCDR (prop);
3622 }
3623
959bc044
SM
3624 if (STRINGP (prop))
3625 return 1;
3626
06568bbf
GM
3627 if (!CONSP (prop))
3628 return 0;
3629
3630 /* Skip over `margin LOCATION'. If LOCATION is in the margins,
3631 we don't need to treat text as intangible. */
3632 if (EQ (XCAR (prop), Qmargin))
3633 {
3634 prop = XCDR (prop);
3635 if (!CONSP (prop))
3636 return 0;
3637
3638 prop = XCDR (prop);
3639 if (!CONSP (prop)
3640 || EQ (XCAR (prop), Qleft_margin)
3641 || EQ (XCAR (prop), Qright_margin))
3642 return 0;
3643 }
2311178e 3644
6cd83a9a
SM
3645 return (CONSP (prop)
3646 && (EQ (XCAR (prop), Qimage)
3647 || EQ (XCAR (prop), Qspace)));
06568bbf
GM
3648}
3649
3650
3651/* Check if PROP is a display property value whose text should be
3652 treated as intangible. */
3653
3654int
3655display_prop_intangible_p (prop)
3656 Lisp_Object prop;
3657{
3658 if (CONSP (prop)
3659 && CONSP (XCAR (prop))
3660 && !EQ (Qmargin, XCAR (XCAR (prop))))
3661 {
3662 /* A list of sub-properties. */
3663 while (CONSP (prop))
3664 {
3665 if (single_display_prop_intangible_p (XCAR (prop)))
3666 return 1;
3667 prop = XCDR (prop);
3668 }
3669 }
3670 else if (VECTORP (prop))
3671 {
3672 /* A vector of sub-properties. */
3673 int i;
a61b7058
GM
3674 for (i = 0; i < ASIZE (prop); ++i)
3675 if (single_display_prop_intangible_p (AREF (prop, i)))
06568bbf
GM
3676 return 1;
3677 }
3678 else
3679 return single_display_prop_intangible_p (prop);
3680
3681 return 0;
3682}
3683
74bd6d65
GM
3684
3685/* Return 1 if PROP is a display sub-property value containing STRING. */
3686
3687static int
3688single_display_prop_string_p (prop, string)
3689 Lisp_Object prop, string;
3690{
74bd6d65
GM
3691 if (EQ (string, prop))
3692 return 1;
2311178e 3693
74bd6d65
GM
3694 /* Skip over `when FORM'. */
3695 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
3696 {
3697 prop = XCDR (prop);
3698 if (!CONSP (prop))
3699 return 0;
3700 prop = XCDR (prop);
3701 }
3702
3703 if (CONSP (prop))
3704 /* Skip over `margin LOCATION'. */
3705 if (EQ (XCAR (prop), Qmargin))
3706 {
3707 prop = XCDR (prop);
3708 if (!CONSP (prop))
3709 return 0;
3710
3711 prop = XCDR (prop);
3712 if (!CONSP (prop))
3713 return 0;
3714 }
2311178e 3715
74bd6d65
GM
3716 return CONSP (prop) && EQ (XCAR (prop), string);
3717}
3718
3719
3720/* Return 1 if STRING appears in the `display' property PROP. */
3721
3722static int
3723display_prop_string_p (prop, string)
3724 Lisp_Object prop, string;
3725{
74bd6d65
GM
3726 if (CONSP (prop)
3727 && CONSP (XCAR (prop))
3728 && !EQ (Qmargin, XCAR (XCAR (prop))))
3729 {
3730 /* A list of sub-properties. */
3731 while (CONSP (prop))
3732 {
3733 if (single_display_prop_string_p (XCAR (prop), string))
3734 return 1;
3735 prop = XCDR (prop);
3736 }
3737 }
3738 else if (VECTORP (prop))
3739 {
3740 /* A vector of sub-properties. */
3741 int i;
3742 for (i = 0; i < ASIZE (prop); ++i)
3743 if (single_display_prop_string_p (AREF (prop, i), string))
3744 return 1;
3745 }
3746 else
3747 return single_display_prop_string_p (prop, string);
3748
3749 return 0;
3750}
3751
3752
3753/* Determine from which buffer position in W's buffer STRING comes
3754 from. AROUND_CHARPOS is an approximate position where it could
3755 be from. Value is the buffer position or 0 if it couldn't be
3756 determined.
3757
3758 W's buffer must be current.
3759
3760 This function is necessary because we don't record buffer positions
3761 in glyphs generated from strings (to keep struct glyph small).
3762 This function may only use code that doesn't eval because it is
3763 called asynchronously from note_mouse_highlight. */
3764
3765int
3766string_buffer_position (w, string, around_charpos)
3767 struct window *w;
3768 Lisp_Object string;
3769 int around_charpos;
3770{
74bd6d65
GM
3771 Lisp_Object limit, prop, pos;
3772 const int MAX_DISTANCE = 1000;
3773 int found = 0;
3774
d8731202 3775 pos = make_number (around_charpos);
74bd6d65
GM
3776 limit = make_number (min (XINT (pos) + MAX_DISTANCE, ZV));
3777 while (!found && !EQ (pos, limit))
3778 {
3779 prop = Fget_char_property (pos, Qdisplay, Qnil);
3780 if (!NILP (prop) && display_prop_string_p (prop, string))
3781 found = 1;
3782 else
134d9283 3783 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil, limit);
74bd6d65
GM
3784 }
3785
3786 if (!found)
3787 {
d8731202 3788 pos = make_number (around_charpos);
74bd6d65
GM
3789 limit = make_number (max (XINT (pos) - MAX_DISTANCE, BEGV));
3790 while (!found && !EQ (pos, limit))
3791 {
3792 prop = Fget_char_property (pos, Qdisplay, Qnil);
3793 if (!NILP (prop) && display_prop_string_p (prop, string))
3794 found = 1;
3795 else
134d9283
GM
3796 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
3797 limit);
74bd6d65
GM
3798 }
3799 }
3800
3801 return found ? XINT (pos) : 0;
3802}
3803
3804
5f5c8ee5 3805\f
260a86a0
KH
3806/***********************************************************************
3807 `composition' property
3808 ***********************************************************************/
3809
3810/* Set up iterator IT from `composition' property at its current
3811 position. Called from handle_stop. */
3812
3813static enum prop_handled
3814handle_composition_prop (it)
3815 struct it *it;
3816{
3817 Lisp_Object prop, string;
3818 int pos, pos_byte, end;
3819 enum prop_handled handled = HANDLED_NORMALLY;
3820
3821 if (STRINGP (it->string))
3822 {
3823 pos = IT_STRING_CHARPOS (*it);
3824 pos_byte = IT_STRING_BYTEPOS (*it);
3825 string = it->string;
3826 }
3827 else
3828 {
3829 pos = IT_CHARPOS (*it);
3830 pos_byte = IT_BYTEPOS (*it);
3831 string = Qnil;
3832 }
3833
3834 /* If there's a valid composition and point is not inside of the
3835 composition (in the case that the composition is from the current
3836 buffer), draw a glyph composed from the composition components. */
3837 if (find_composition (pos, -1, &pos, &end, &prop, string)
3838 && COMPOSITION_VALID_P (pos, end, prop)
3839 && (STRINGP (it->string) || (PT <= pos || PT >= end)))
3840 {
3841 int id = get_composition_id (pos, pos_byte, end - pos, prop, string);
3842
3843 if (id >= 0)
3844 {
3845 it->method = next_element_from_composition;
3846 it->cmp_id = id;
3847 it->cmp_len = COMPOSITION_LENGTH (prop);
3848 /* For a terminal, draw only the first character of the
3849 components. */
3850 it->c = COMPOSITION_GLYPH (composition_table[id], 0);
3851 it->len = (STRINGP (it->string)
3852 ? string_char_to_byte (it->string, end)
3853 : CHAR_TO_BYTE (end)) - pos_byte;
3854 it->stop_charpos = end;
3855 handled = HANDLED_RETURN;
3856 }
3857 }
3858
3859 return handled;
3860}
3861
3862
3863\f
5f5c8ee5
GM
3864/***********************************************************************
3865 Overlay strings
3866 ***********************************************************************/
3867
3868/* The following structure is used to record overlay strings for
3869 later sorting in load_overlay_strings. */
3870
3871struct overlay_entry
3872{
2970b9be 3873 Lisp_Object overlay;
5f5c8ee5
GM
3874 Lisp_Object string;
3875 int priority;
3876 int after_string_p;
3877};
3878
3879
3880/* Set up iterator IT from overlay strings at its current position.
3881 Called from handle_stop. */
3882
3883static enum prop_handled
3884handle_overlay_change (it)
3885 struct it *it;
3886{
5a08cbaf 3887 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
2970b9be 3888 return HANDLED_RECOMPUTE_PROPS;
5f5c8ee5 3889 else
2970b9be 3890 return HANDLED_NORMALLY;
5f5c8ee5
GM
3891}
3892
3893
3894/* Set up the next overlay string for delivery by IT, if there is an
3895 overlay string to deliver. Called by set_iterator_to_next when the
3896 end of the current overlay string is reached. If there are more
3897 overlay strings to display, IT->string and
3898 IT->current.overlay_string_index are set appropriately here.
3899 Otherwise IT->string is set to nil. */
2311178e 3900
5f5c8ee5
GM
3901static void
3902next_overlay_string (it)
3903 struct it *it;
3904{
3905 ++it->current.overlay_string_index;
3906 if (it->current.overlay_string_index == it->n_overlay_strings)
3907 {
3908 /* No more overlay strings. Restore IT's settings to what
3909 they were before overlay strings were processed, and
3910 continue to deliver from current_buffer. */
5a08cbaf 3911 int display_ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
2311178e 3912
5f5c8ee5
GM
3913 pop_it (it);
3914 xassert (it->stop_charpos >= BEGV
3915 && it->stop_charpos <= it->end_charpos);
3916 it->string = Qnil;
3917 it->current.overlay_string_index = -1;
3918 SET_TEXT_POS (it->current.string_pos, -1, -1);
3919 it->n_overlay_strings = 0;
3920 it->method = next_element_from_buffer;
2970b9be
GM
3921
3922 /* If we're at the end of the buffer, record that we have
3923 processed the overlay strings there already, so that
3924 next_element_from_buffer doesn't try it again. */
3925 if (IT_CHARPOS (*it) >= it->end_charpos)
3926 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf
GM
3927
3928 /* If we have to display `...' for invisible text, set
3929 the iterator up for that. */
3930 if (display_ellipsis_p)
3931 setup_for_ellipsis (it);
5f5c8ee5
GM
3932 }
3933 else
3934 {
3935 /* There are more overlay strings to process. If
3936 IT->current.overlay_string_index has advanced to a position
3937 where we must load IT->overlay_strings with more strings, do
3938 it. */
3939 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
2311178e 3940
5f5c8ee5 3941 if (it->current.overlay_string_index && i == 0)
5a08cbaf 3942 load_overlay_strings (it, 0);
5f5c8ee5
GM
3943
3944 /* Initialize IT to deliver display elements from the overlay
3945 string. */
3946 it->string = it->overlay_strings[i];
3947 it->multibyte_p = STRING_MULTIBYTE (it->string);
3948 SET_TEXT_POS (it->current.string_pos, 0, 0);
3949 it->method = next_element_from_string;
3950 it->stop_charpos = 0;
3951 }
2311178e 3952
5f5c8ee5
GM
3953 CHECK_IT (it);
3954}
3955
3956
3957/* Compare two overlay_entry structures E1 and E2. Used as a
3958 comparison function for qsort in load_overlay_strings. Overlay
3959 strings for the same position are sorted so that
3960
2970b9be
GM
3961 1. All after-strings come in front of before-strings, except
3962 when they come from the same overlay.
2311178e 3963
5f5c8ee5
GM
3964 2. Within after-strings, strings are sorted so that overlay strings
3965 from overlays with higher priorities come first.
3966
3967 2. Within before-strings, strings are sorted so that overlay
3968 strings from overlays with higher priorities come last.
3969
3970 Value is analogous to strcmp. */
3971
2311178e 3972
5f5c8ee5
GM
3973static int
3974compare_overlay_entries (e1, e2)
3975 void *e1, *e2;
3976{
3977 struct overlay_entry *entry1 = (struct overlay_entry *) e1;
3978 struct overlay_entry *entry2 = (struct overlay_entry *) e2;
3979 int result;
3980
3981 if (entry1->after_string_p != entry2->after_string_p)
2970b9be
GM
3982 {
3983 /* Let after-strings appear in front of before-strings if
3984 they come from different overlays. */
3985 if (EQ (entry1->overlay, entry2->overlay))
3986 result = entry1->after_string_p ? 1 : -1;
3987 else
3988 result = entry1->after_string_p ? -1 : 1;
3989 }
5f5c8ee5
GM
3990 else if (entry1->after_string_p)
3991 /* After-strings sorted in order of decreasing priority. */
3992 result = entry2->priority - entry1->priority;
3993 else
3994 /* Before-strings sorted in order of increasing priority. */
3995 result = entry1->priority - entry2->priority;
3996
3997 return result;
3998}
3999
4000
4001/* Load the vector IT->overlay_strings with overlay strings from IT's
5a08cbaf
GM
4002 current buffer position, or from CHARPOS if that is > 0. Set
4003 IT->n_overlays to the total number of overlay strings found.
5f5c8ee5
GM
4004
4005 Overlay strings are processed OVERLAY_STRING_CHUNK_SIZE strings at
4006 a time. On entry into load_overlay_strings,
4007 IT->current.overlay_string_index gives the number of overlay
4008 strings that have already been loaded by previous calls to this
4009 function.
4010
2970b9be
GM
4011 IT->add_overlay_start contains an additional overlay start
4012 position to consider for taking overlay strings from, if non-zero.
4013 This position comes into play when the overlay has an `invisible'
4014 property, and both before and after-strings. When we've skipped to
4015 the end of the overlay, because of its `invisible' property, we
4016 nevertheless want its before-string to appear.
4017 IT->add_overlay_start will contain the overlay start position
4018 in this case.
4019
5f5c8ee5
GM
4020 Overlay strings are sorted so that after-string strings come in
4021 front of before-string strings. Within before and after-strings,
4022 strings are sorted by overlay priority. See also function
4023 compare_overlay_entries. */
2311178e 4024
5f5c8ee5 4025static void
5a08cbaf 4026load_overlay_strings (it, charpos)
5f5c8ee5 4027 struct it *it;
5a08cbaf 4028 int charpos;
5f5c8ee5
GM
4029{
4030 extern Lisp_Object Qafter_string, Qbefore_string, Qwindow, Qpriority;
b7253a3e
SM
4031 Lisp_Object overlay, window, str, invisible;
4032 struct Lisp_Overlay *ov;
5f5c8ee5
GM
4033 int start, end;
4034 int size = 20;
cafafe0b 4035 int n = 0, i, j, invis_p;
5f5c8ee5
GM
4036 struct overlay_entry *entries
4037 = (struct overlay_entry *) alloca (size * sizeof *entries);
5a08cbaf
GM
4038
4039 if (charpos <= 0)
4040 charpos = IT_CHARPOS (*it);
5f5c8ee5
GM
4041
4042 /* Append the overlay string STRING of overlay OVERLAY to vector
4043 `entries' which has size `size' and currently contains `n'
4044 elements. AFTER_P non-zero means STRING is an after-string of
4045 OVERLAY. */
4046#define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
4047 do \
4048 { \
4049 Lisp_Object priority; \
4050 \
4051 if (n == size) \
4052 { \
4053 int new_size = 2 * size; \
4054 struct overlay_entry *old = entries; \
4055 entries = \
4056 (struct overlay_entry *) alloca (new_size \
4057 * sizeof *entries); \
4058 bcopy (old, entries, size * sizeof *entries); \
4059 size = new_size; \
4060 } \
4061 \
4062 entries[n].string = (STRING); \
2970b9be 4063 entries[n].overlay = (OVERLAY); \
5f5c8ee5 4064 priority = Foverlay_get ((OVERLAY), Qpriority); \
2970b9be 4065 entries[n].priority = INTEGERP (priority) ? XINT (priority) : 0; \
5f5c8ee5
GM
4066 entries[n].after_string_p = (AFTER_P); \
4067 ++n; \
4068 } \
4069 while (0)
4070
4071 /* Process overlay before the overlay center. */
b7253a3e 4072 for (ov = current_buffer->overlays_before; ov; ov = ov->next)
5f5c8ee5 4073 {
b7253a3e 4074 XSETMISC (overlay, ov);
5f5c8ee5
GM
4075 xassert (OVERLAYP (overlay));
4076 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4077 end = OVERLAY_POSITION (OVERLAY_END (overlay));
2311178e 4078
cafafe0b 4079 if (end < charpos)
5f5c8ee5
GM
4080 break;
4081
4082 /* Skip this overlay if it doesn't start or end at IT's current
4083 position. */
cafafe0b 4084 if (end != charpos && start != charpos)
5f5c8ee5 4085 continue;
2311178e 4086
5f5c8ee5
GM
4087 /* Skip this overlay if it doesn't apply to IT->w. */
4088 window = Foverlay_get (overlay, Qwindow);
4089 if (WINDOWP (window) && XWINDOW (window) != it->w)
4090 continue;
4091
cafafe0b
GM
4092 /* If the text ``under'' the overlay is invisible, both before-
4093 and after-strings from this overlay are visible; start and
4094 end position are indistinguishable. */
4095 invisible = Foverlay_get (overlay, Qinvisible);
4096 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4097
5f5c8ee5 4098 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4099 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4100 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4101 && SCHARS (str))
5f5c8ee5 4102 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4103
5f5c8ee5 4104 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4105 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4106 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4107 && SCHARS (str))
5f5c8ee5
GM
4108 RECORD_OVERLAY_STRING (overlay, str, 1);
4109 }
2311178e 4110
5f5c8ee5 4111 /* Process overlays after the overlay center. */
b7253a3e 4112 for (ov = current_buffer->overlays_after; ov; ov = ov->next)
5f5c8ee5 4113 {
b7253a3e 4114 XSETMISC (overlay, ov);
5f5c8ee5
GM
4115 xassert (OVERLAYP (overlay));
4116 start = OVERLAY_POSITION (OVERLAY_START (overlay));
4117 end = OVERLAY_POSITION (OVERLAY_END (overlay));
4118
cafafe0b 4119 if (start > charpos)
5f5c8ee5 4120 break;
2311178e 4121
5f5c8ee5
GM
4122 /* Skip this overlay if it doesn't start or end at IT's current
4123 position. */
cafafe0b 4124 if (end != charpos && start != charpos)
5f5c8ee5
GM
4125 continue;
4126
4127 /* Skip this overlay if it doesn't apply to IT->w. */
4128 window = Foverlay_get (overlay, Qwindow);
4129 if (WINDOWP (window) && XWINDOW (window) != it->w)
4130 continue;
2311178e 4131
cafafe0b
GM
4132 /* If the text ``under'' the overlay is invisible, it has a zero
4133 dimension, and both before- and after-strings apply. */
4134 invisible = Foverlay_get (overlay, Qinvisible);
4135 invis_p = TEXT_PROP_MEANS_INVISIBLE (invisible);
4136
5f5c8ee5 4137 /* If overlay has a non-empty before-string, record it. */
cafafe0b 4138 if ((start == charpos || (end == charpos && invis_p))
5f5c8ee5 4139 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
2051c264 4140 && SCHARS (str))
5f5c8ee5 4141 RECORD_OVERLAY_STRING (overlay, str, 0);
2311178e 4142
5f5c8ee5 4143 /* If overlay has a non-empty after-string, record it. */
cafafe0b 4144 if ((end == charpos || (start == charpos && invis_p))
5f5c8ee5 4145 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
2051c264 4146 && SCHARS (str))
5f5c8ee5
GM
4147 RECORD_OVERLAY_STRING (overlay, str, 1);
4148 }
4149
4150#undef RECORD_OVERLAY_STRING
2311178e 4151
5f5c8ee5 4152 /* Sort entries. */
cafafe0b 4153 if (n > 1)
2970b9be 4154 qsort (entries, n, sizeof *entries, compare_overlay_entries);
5f5c8ee5
GM
4155
4156 /* Record the total number of strings to process. */
4157 it->n_overlay_strings = n;
4158
4159 /* IT->current.overlay_string_index is the number of overlay strings
4160 that have already been consumed by IT. Copy some of the
4161 remaining overlay strings to IT->overlay_strings. */
4162 i = 0;
4163 j = it->current.overlay_string_index;
4164 while (i < OVERLAY_STRING_CHUNK_SIZE && j < n)
4165 it->overlay_strings[i++] = entries[j++].string;
2970b9be 4166
5f5c8ee5
GM
4167 CHECK_IT (it);
4168}
4169
4170
4171/* Get the first chunk of overlay strings at IT's current buffer
5a08cbaf
GM
4172 position, or at CHARPOS if that is > 0. Value is non-zero if at
4173 least one overlay string was found. */
5f5c8ee5
GM
4174
4175static int
5a08cbaf 4176get_overlay_strings (it, charpos)
5f5c8ee5 4177 struct it *it;
5a08cbaf 4178 int charpos;
5f5c8ee5
GM
4179{
4180 /* Get the first OVERLAY_STRING_CHUNK_SIZE overlay strings to
4181 process. This fills IT->overlay_strings with strings, and sets
4182 IT->n_overlay_strings to the total number of strings to process.
4183 IT->pos.overlay_string_index has to be set temporarily to zero
4184 because load_overlay_strings needs this; it must be set to -1
4185 when no overlay strings are found because a zero value would
4186 indicate a position in the first overlay string. */
4187 it->current.overlay_string_index = 0;
5a08cbaf 4188 load_overlay_strings (it, charpos);
5f5c8ee5
GM
4189
4190 /* If we found overlay strings, set up IT to deliver display
4191 elements from the first one. Otherwise set up IT to deliver
4192 from current_buffer. */
4193 if (it->n_overlay_strings)
4194 {
4195 /* Make sure we know settings in current_buffer, so that we can
4196 restore meaningful values when we're done with the overlay
4197 strings. */
4198 compute_stop_pos (it);
4199 xassert (it->face_id >= 0);
2311178e 4200
5f5c8ee5
GM
4201 /* Save IT's settings. They are restored after all overlay
4202 strings have been processed. */
4203 xassert (it->sp == 0);
4204 push_it (it);
4205
4206 /* Set up IT to deliver display elements from the first overlay
4207 string. */
4208 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
5f5c8ee5 4209 it->string = it->overlay_strings[0];
b2046df8 4210 it->stop_charpos = 0;
5f5c8ee5 4211 xassert (STRINGP (it->string));
2051c264 4212 it->end_charpos = SCHARS (it->string);
d5db4077 4213 it->multibyte_p = STRING_MULTIBYTE (it->string);
5f5c8ee5
GM
4214 it->method = next_element_from_string;
4215 }
4216 else
4217 {
4218 it->string = Qnil;
4219 it->current.overlay_string_index = -1;
4220 it->method = next_element_from_buffer;
4221 }
4222
4223 CHECK_IT (it);
4224
4225 /* Value is non-zero if we found at least one overlay string. */
4226 return STRINGP (it->string);
4227}
4228
4229
4230\f
4231/***********************************************************************
4232 Saving and restoring state
4233 ***********************************************************************/
4234
4235/* Save current settings of IT on IT->stack. Called, for example,
4236 before setting up IT for an overlay string, to be able to restore
4237 IT's settings to what they were after the overlay string has been
4238 processed. */
4239
4240static void
4241push_it (it)
4242 struct it *it;
4243{
4244 struct iterator_stack_entry *p;
2311178e 4245
5f5c8ee5
GM
4246 xassert (it->sp < 2);
4247 p = it->stack + it->sp;
4248
4249 p->stop_charpos = it->stop_charpos;
4250 xassert (it->face_id >= 0);
4251 p->face_id = it->face_id;
4252 p->string = it->string;
4253 p->pos = it->current;
4254 p->end_charpos = it->end_charpos;
4255 p->string_nchars = it->string_nchars;
4256 p->area = it->area;
4257 p->multibyte_p = it->multibyte_p;
4258 p->space_width = it->space_width;
4259 p->font_height = it->font_height;
4260 p->voffset = it->voffset;
4261 p->string_from_display_prop_p = it->string_from_display_prop_p;
5a08cbaf 4262 p->display_ellipsis_p = 0;
5f5c8ee5
GM
4263 ++it->sp;
4264}
4265
4266
4267/* Restore IT's settings from IT->stack. Called, for example, when no
4268 more overlay strings must be processed, and we return to delivering
4269 display elements from a buffer, or when the end of a string from a
4270 `display' property is reached and we return to delivering display
4271 elements from an overlay string, or from a buffer. */
4272
4273static void
4274pop_it (it)
4275 struct it *it;
4276{
4277 struct iterator_stack_entry *p;
2311178e 4278
5f5c8ee5
GM
4279 xassert (it->sp > 0);
4280 --it->sp;
4281 p = it->stack + it->sp;
4282 it->stop_charpos = p->stop_charpos;
4283 it->face_id = p->face_id;
4284 it->string = p->string;
4285 it->current = p->pos;
4286 it->end_charpos = p->end_charpos;
4287 it->string_nchars = p->string_nchars;
4288 it->area = p->area;
4289 it->multibyte_p = p->multibyte_p;
4290 it->space_width = p->space_width;
4291 it->font_height = p->font_height;
4292 it->voffset = p->voffset;
4293 it->string_from_display_prop_p = p->string_from_display_prop_p;
4294}
4295
4296
4297\f
4298/***********************************************************************
4299 Moving over lines
4300 ***********************************************************************/
4301
4302/* Set IT's current position to the previous line start. */
4303
4304static void
4305back_to_previous_line_start (it)
4306 struct it *it;
4307{
4308 IT_CHARPOS (*it) = find_next_newline_no_quit (IT_CHARPOS (*it) - 1, -1);
4309 IT_BYTEPOS (*it) = CHAR_TO_BYTE (IT_CHARPOS (*it));
4310}
4311
4312
cafafe0b 4313/* Move IT to the next line start.
2311178e 4314
cafafe0b
GM
4315 Value is non-zero if a newline was found. Set *SKIPPED_P to 1 if
4316 we skipped over part of the text (as opposed to moving the iterator
4317 continuously over the text). Otherwise, don't change the value
4318 of *SKIPPED_P.
2311178e 4319
cafafe0b
GM
4320 Newlines may come from buffer text, overlay strings, or strings
4321 displayed via the `display' property. That's the reason we can't
0fd37545
GM
4322 simply use find_next_newline_no_quit.
4323
4324 Note that this function may not skip over invisible text that is so
4325 because of text properties and immediately follows a newline. If
4326 it would, function reseat_at_next_visible_line_start, when called
4327 from set_iterator_to_next, would effectively make invisible
4328 characters following a newline part of the wrong glyph row, which
4329 leads to wrong cursor motion. */
5f5c8ee5 4330
cafafe0b
GM
4331static int
4332forward_to_next_line_start (it, skipped_p)
5f5c8ee5 4333 struct it *it;
cafafe0b 4334 int *skipped_p;
5f5c8ee5 4335{
54918e2b 4336 int old_selective, newline_found_p, n;
cafafe0b
GM
4337 const int MAX_NEWLINE_DISTANCE = 500;
4338
0fd37545
GM
4339 /* If already on a newline, just consume it to avoid unintended
4340 skipping over invisible text below. */
51695746
GM
4341 if (it->what == IT_CHARACTER
4342 && it->c == '\n'
4343 && CHARPOS (it->position) == IT_CHARPOS (*it))
0fd37545
GM
4344 {
4345 set_iterator_to_next (it, 0);
a77dc1ec 4346 it->c = 0;
0fd37545
GM
4347 return 1;
4348 }
4349
54918e2b 4350 /* Don't handle selective display in the following. It's (a)
0fd37545
GM
4351 unnecessary because it's done by the caller, and (b) leads to an
4352 infinite recursion because next_element_from_ellipsis indirectly
4353 calls this function. */
54918e2b
GM
4354 old_selective = it->selective;
4355 it->selective = 0;
4356
cafafe0b
GM
4357 /* Scan for a newline within MAX_NEWLINE_DISTANCE display elements
4358 from buffer text. */
3aec8722
GM
4359 for (n = newline_found_p = 0;
4360 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
4361 n += STRINGP (it->string) ? 0 : 1)
cafafe0b 4362 {
8692ca92 4363 if (!get_next_display_element (it))
d43be70c 4364 return 0;
d02f1cb8 4365 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
cafafe0b 4366 set_iterator_to_next (it, 0);
cafafe0b
GM
4367 }
4368
4369 /* If we didn't find a newline near enough, see if we can use a
4370 short-cut. */
db0bb807 4371 if (!newline_found_p)
cafafe0b
GM
4372 {
4373 int start = IT_CHARPOS (*it);
4374 int limit = find_next_newline_no_quit (start, 1);
4375 Lisp_Object pos;
4376
4377 xassert (!STRINGP (it->string));
4378
4379 /* If there isn't any `display' property in sight, and no
4380 overlays, we can just use the position of the newline in
4381 buffer text. */
4382 if (it->stop_charpos >= limit
4383 || ((pos = Fnext_single_property_change (make_number (start),
4384 Qdisplay,
4385 Qnil, make_number (limit)),
4386 NILP (pos))
4387 && next_overlay_change (start) == ZV))
4388 {
4389 IT_CHARPOS (*it) = limit;
4390 IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
4391 *skipped_p = newline_found_p = 1;
4392 }
4393 else
4394 {
4395 while (get_next_display_element (it)
4396 && !newline_found_p)
4397 {
4398 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
4399 set_iterator_to_next (it, 0);
4400 }
4401 }
4402 }
4403
54918e2b 4404 it->selective = old_selective;
cafafe0b 4405 return newline_found_p;
5f5c8ee5
GM
4406}
4407
4408
4409/* Set IT's current position to the previous visible line start. Skip
4410 invisible text that is so either due to text properties or due to
4411 selective display. Caution: this does not change IT->current_x and
4412 IT->hpos. */
4413
4414static void
4415back_to_previous_visible_line_start (it)
4416 struct it *it;
4417{
4418 int visible_p = 0;
4419
4420 /* Go back one newline if not on BEGV already. */
4421 if (IT_CHARPOS (*it) > BEGV)
4422 back_to_previous_line_start (it);
4423
4424 /* Move over lines that are invisible because of selective display
4425 or text properties. */
4426 while (IT_CHARPOS (*it) > BEGV
4427 && !visible_p)
4428 {
4429 visible_p = 1;
4430
4431 /* If selective > 0, then lines indented more than that values
4432 are invisible. */
4433 if (it->selective > 0
4434 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4435 (double) it->selective)) /* iftc */
5f5c8ee5 4436 visible_p = 0;
2311178e 4437 else
5f5c8ee5
GM
4438 {
4439 Lisp_Object prop;
4440
6fc556fd
KR
4441 prop = Fget_char_property (make_number (IT_CHARPOS (*it)),
4442 Qinvisible, it->window);
5f5c8ee5
GM
4443 if (TEXT_PROP_MEANS_INVISIBLE (prop))
4444 visible_p = 0;
4445 }
5f5c8ee5
GM
4446
4447 /* Back one more newline if the current one is invisible. */
4448 if (!visible_p)
4449 back_to_previous_line_start (it);
4450 }
4451
4452 xassert (IT_CHARPOS (*it) >= BEGV);
4453 xassert (IT_CHARPOS (*it) == BEGV
4454 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4455 CHECK_IT (it);
4456}
4457
4458
4459/* Reseat iterator IT at the previous visible line start. Skip
4460 invisible text that is so either due to text properties or due to
4461 selective display. At the end, update IT's overlay information,
4462 face information etc. */
4463
4464static void
4465reseat_at_previous_visible_line_start (it)
4466 struct it *it;
4467{
4468 back_to_previous_visible_line_start (it);
4469 reseat (it, it->current.pos, 1);
4470 CHECK_IT (it);
4471}
4472
4473
4474/* Reseat iterator IT on the next visible line start in the current
312246d1
GM
4475 buffer. ON_NEWLINE_P non-zero means position IT on the newline
4476 preceding the line start. Skip over invisible text that is so
4477 because of selective display. Compute faces, overlays etc at the
4478 new position. Note that this function does not skip over text that
4479 is invisible because of text properties. */
5f5c8ee5
GM
4480
4481static void
312246d1 4482reseat_at_next_visible_line_start (it, on_newline_p)
5f5c8ee5 4483 struct it *it;
312246d1 4484 int on_newline_p;
5f5c8ee5 4485{
cafafe0b
GM
4486 int newline_found_p, skipped_p = 0;
4487
4488 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4489
4490 /* Skip over lines that are invisible because they are indented
4491 more than the value of IT->selective. */
4492 if (it->selective > 0)
4493 while (IT_CHARPOS (*it) < ZV
a77dc1ec 4494 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
a67e162b 4495 (double) it->selective)) /* iftc */
a77dc1ec
GM
4496 {
4497 xassert (FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
4498 newline_found_p = forward_to_next_line_start (it, &skipped_p);
4499 }
cafafe0b
GM
4500
4501 /* Position on the newline if that's what's requested. */
4502 if (on_newline_p && newline_found_p)
5f5c8ee5 4503 {
cafafe0b 4504 if (STRINGP (it->string))
5f5c8ee5 4505 {
cafafe0b
GM
4506 if (IT_STRING_CHARPOS (*it) > 0)
4507 {
4508 --IT_STRING_CHARPOS (*it);
4509 --IT_STRING_BYTEPOS (*it);
4510 }
5f5c8ee5 4511 }
cafafe0b 4512 else if (IT_CHARPOS (*it) > BEGV)
312246d1
GM
4513 {
4514 --IT_CHARPOS (*it);
cafafe0b
GM
4515 --IT_BYTEPOS (*it);
4516 reseat (it, it->current.pos, 0);
312246d1 4517 }
5f5c8ee5 4518 }
cafafe0b
GM
4519 else if (skipped_p)
4520 reseat (it, it->current.pos, 0);
2311178e 4521
5f5c8ee5
GM
4522 CHECK_IT (it);
4523}
4524
4525
4526\f
4527/***********************************************************************
4528 Changing an iterator's position
4529***********************************************************************/
4530
4531/* Change IT's current position to POS in current_buffer. If FORCE_P
4532 is non-zero, always check for text properties at the new position.
4533 Otherwise, text properties are only looked up if POS >=
4534 IT->check_charpos of a property. */
4535
4536static void
4537reseat (it, pos, force_p)
4538 struct it *it;
4539 struct text_pos pos;
4540 int force_p;
4541{
4542 int original_pos = IT_CHARPOS (*it);
4543
4544 reseat_1 (it, pos, 0);
4545
4546 /* Determine where to check text properties. Avoid doing it
4547 where possible because text property lookup is very expensive. */
4548 if (force_p
4549 || CHARPOS (pos) > it->stop_charpos
4550 || CHARPOS (pos) < original_pos)
4551 handle_stop (it);
4552
4553 CHECK_IT (it);
4554}
4555
4556
4557/* Change IT's buffer position to POS. SET_STOP_P non-zero means set
4558 IT->stop_pos to POS, also. */
4559
4560static void
4561reseat_1 (it, pos, set_stop_p)
4562 struct it *it;
4563 struct text_pos pos;
4564 int set_stop_p;
4565{
4566 /* Don't call this function when scanning a C string. */
4567 xassert (it->s == NULL);
4568
4569 /* POS must be a reasonable value. */
4570 xassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
4571
4572 it->current.pos = it->position = pos;
4573 XSETBUFFER (it->object, current_buffer);
78c663d8 4574 it->end_charpos = ZV;
5f5c8ee5
GM
4575 it->dpvec = NULL;
4576 it->current.dpvec_index = -1;
4577 it->current.overlay_string_index = -1;
4578 IT_STRING_CHARPOS (*it) = -1;
4579 IT_STRING_BYTEPOS (*it) = -1;
4580 it->string = Qnil;
4581 it->method = next_element_from_buffer;
5905025c
RS
4582 /* RMS: I added this to fix a bug in move_it_vertically_backward
4583 where it->area continued to relate to the starting point
4584 for the backward motion. Bug report from
4585 Nick Roberts <nick@nick.uklinux.net> on 19 May 2003.
4586 However, I am not sure whether reseat still does the right thing
4587 in general after this change. */
4588 it->area = TEXT_AREA;
06fd3792 4589 it->multibyte_p = !NILP (current_buffer->enable_multibyte_characters);
5f5c8ee5 4590 it->sp = 0;
4aad61f8 4591 it->face_before_selective_p = 0;
5f5c8ee5
GM
4592
4593 if (set_stop_p)
4594 it->stop_charpos = CHARPOS (pos);
4595}
4596
4597
4598/* Set up IT for displaying a string, starting at CHARPOS in window W.
4599 If S is non-null, it is a C string to iterate over. Otherwise,
4600 STRING gives a Lisp string to iterate over.
2311178e 4601
5f5c8ee5
GM
4602 If PRECISION > 0, don't return more then PRECISION number of
4603 characters from the string.
4604
4605 If FIELD_WIDTH > 0, return padding spaces until FIELD_WIDTH
4606 characters have been returned. FIELD_WIDTH < 0 means an infinite
4607 field width.
4608
4609 MULTIBYTE = 0 means disable processing of multibyte characters,
4610 MULTIBYTE > 0 means enable it,
4611 MULTIBYTE < 0 means use IT->multibyte_p.
4612
4613 IT must be initialized via a prior call to init_iterator before
4614 calling this function. */
4615
4616static void
4617reseat_to_string (it, s, string, charpos, precision, field_width, multibyte)
4618 struct it *it;
4619 unsigned char *s;
4620 Lisp_Object string;
4621 int charpos;
4622 int precision, field_width, multibyte;
4623{
4624 /* No region in strings. */
4625 it->region_beg_charpos = it->region_end_charpos = -1;
4626
4627 /* No text property checks performed by default, but see below. */
4628 it->stop_charpos = -1;
4629
4630 /* Set iterator position and end position. */
4631 bzero (&it->current, sizeof it->current);
4632 it->current.overlay_string_index = -1;
4633 it->current.dpvec_index = -1;
5f5c8ee5 4634 xassert (charpos >= 0);
2311178e 4635
e719f5ae
GM
4636 /* If STRING is specified, use its multibyteness, otherwise use the
4637 setting of MULTIBYTE, if specified. */
cabf45da 4638 if (multibyte >= 0)
5f5c8ee5 4639 it->multibyte_p = multibyte > 0;
2311178e 4640
5f5c8ee5
GM
4641 if (s == NULL)
4642 {
4643 xassert (STRINGP (string));
4644 it->string = string;
4645 it->s = NULL;
2051c264 4646 it->end_charpos = it->string_nchars = SCHARS (string);
5f5c8ee5
GM
4647 it->method = next_element_from_string;
4648 it->current.string_pos = string_pos (charpos, string);
4649 }
4650 else
4651 {
4652 it->s = s;
4653 it->string = Qnil;
4654
4655 /* Note that we use IT->current.pos, not it->current.string_pos,
4656 for displaying C strings. */
4657 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
4658 if (it->multibyte_p)
4659 {
4660 it->current.pos = c_string_pos (charpos, s, 1);
4661 it->end_charpos = it->string_nchars = number_of_chars (s, 1);
4662 }
4663 else
4664 {
4665 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
4666 it->end_charpos = it->string_nchars = strlen (s);
4667 }
2311178e 4668
5f5c8ee5
GM
4669 it->method = next_element_from_c_string;
4670 }
4671
4672 /* PRECISION > 0 means don't return more than PRECISION characters
4673 from the string. */
4674 if (precision > 0 && it->end_charpos - charpos > precision)
4675 it->end_charpos = it->string_nchars = charpos + precision;
4676
4677 /* FIELD_WIDTH > 0 means pad with spaces until FIELD_WIDTH
4678 characters have been returned. FIELD_WIDTH == 0 means don't pad,
4679 FIELD_WIDTH < 0 means infinite field width. This is useful for
4680 padding with `-' at the end of a mode line. */
4681 if (field_width < 0)
4682 field_width = INFINITY;
4683 if (field_width > it->end_charpos - charpos)
4684 it->end_charpos = charpos + field_width;
4685
4686 /* Use the standard display table for displaying strings. */
4687 if (DISP_TABLE_P (Vstandard_display_table))
4688 it->dp = XCHAR_TABLE (Vstandard_display_table);
4689
4690 it->stop_charpos = charpos;
4691 CHECK_IT (it);
4692}
4693
4694
4695\f
4696/***********************************************************************
4697 Iteration
4698 ***********************************************************************/
4699
4700/* Load IT's display element fields with information about the next
4701 display element from the current position of IT. Value is zero if
4702 end of buffer (or C string) is reached. */
4703
4704int
4705get_next_display_element (it)
4706 struct it *it;
4707{
7d0393cf 4708 /* Non-zero means that we found a display element. Zero means that
5f5c8ee5
GM
4709 we hit the end of what we iterate over. Performance note: the
4710 function pointer `method' used here turns out to be faster than
4711 using a sequence of if-statements. */
4712 int success_p = (*it->method) (it);
5f5c8ee5
GM
4713
4714 if (it->what == IT_CHARACTER)
4715 {
4716 /* Map via display table or translate control characters.
4717 IT->c, IT->len etc. have been set to the next character by
4718 the function call above. If we have a display table, and it
4719 contains an entry for IT->c, translate it. Don't do this if
4720 IT->c itself comes from a display table, otherwise we could
4721 end up in an infinite recursion. (An alternative could be to
4722 count the recursion depth of this function and signal an
4723 error when a certain maximum depth is reached.) Is it worth
4724 it? */
4725 if (success_p && it->dpvec == NULL)
4726 {
4727 Lisp_Object dv;
4728
4729 if (it->dp
4730 && (dv = DISP_CHAR_VECTOR (it->dp, it->c),
4731 VECTORP (dv)))
4732 {
4733 struct Lisp_Vector *v = XVECTOR (dv);
4734
4735 /* Return the first character from the display table
4736 entry, if not empty. If empty, don't display the
4737 current character. */
4738 if (v->size)
4739 {
4740 it->dpvec_char_len = it->len;
4741 it->dpvec = v->contents;
4742 it->dpend = v->contents + v->size;
4743 it->current.dpvec_index = 0;
4744 it->method = next_element_from_display_vector;
7eee47cc
GM
4745 success_p = get_next_display_element (it);
4746 }
4747 else
4748 {
4749 set_iterator_to_next (it, 0);
4750 success_p = get_next_display_element (it);
5f5c8ee5 4751 }
5f5c8ee5
GM
4752 }
4753
4754 /* Translate control characters into `\003' or `^C' form.
4755 Control characters coming from a display table entry are
4756 currently not translated because we use IT->dpvec to hold
4757 the translation. This could easily be changed but I
197516c2
KH
4758 don't believe that it is worth doing.
4759
fa831cf8
KH
4760 If it->multibyte_p is nonzero, eight-bit characters and
4761 non-printable multibyte characters are also translated to
4762 octal form.
4763
4764 If it->multibyte_p is zero, eight-bit characters that
4765 don't have corresponding multibyte char code are also
4766 translated to octal form. */
ba197fe6 4767 else if ((it->c < ' '
5f5c8ee5 4768 && (it->area != TEXT_AREA
c6e89d6c 4769 || (it->c != '\n' && it->c != '\t')))
fa831cf8
KH
4770 || (it->multibyte_p
4771 ? ((it->c >= 127
4772 && it->len == 1)
4773 || !CHAR_PRINTABLE_P (it->c))
ba197fe6 4774 : (it->c >= 127
fa831cf8 4775 && it->c == unibyte_char_to_multibyte (it->c))))
5f5c8ee5
GM
4776 {
4777 /* IT->c is a control character which must be displayed
4778 either as '\003' or as `^C' where the '\\' and '^'
4779 can be defined in the display table. Fill
4780 IT->ctl_chars with glyphs for what we have to
4781 display. Then, set IT->dpvec to these glyphs. */
4782 GLYPH g;
4783
54c85a23 4784 if (it->c < 128 && it->ctl_arrow_p)
5f5c8ee5
GM
4785 {
4786 /* Set IT->ctl_chars[0] to the glyph for `^'. */
4787 if (it->dp
4788 && INTEGERP (DISP_CTRL_GLYPH (it->dp))
4789 && GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (it->dp))))
4790 g = XINT (DISP_CTRL_GLYPH (it->dp));
4791 else
4792 g = FAST_MAKE_GLYPH ('^', 0);
4793 XSETINT (it->ctl_chars[0], g);
4794
4795 g = FAST_MAKE_GLYPH (it->c ^ 0100, 0);
4796 XSETINT (it->ctl_chars[1], g);
4797
4798 /* Set up IT->dpvec and return first character from it. */
4799 it->dpvec_char_len = it->len;
4800 it->dpvec = it->ctl_chars;
4801 it->dpend = it->dpvec + 2;
4802 it->current.dpvec_index = 0;
4803 it->method = next_element_from_display_vector;
4804 get_next_display_element (it);
4805 }
4806 else
4807 {
260a86a0 4808 unsigned char str[MAX_MULTIBYTE_LENGTH];
c5924f47 4809 int len;
197516c2
KH
4810 int i;
4811 GLYPH escape_glyph;
4812
5f5c8ee5
GM
4813 /* Set IT->ctl_chars[0] to the glyph for `\\'. */
4814 if (it->dp
4815 && INTEGERP (DISP_ESCAPE_GLYPH (it->dp))
4816 && GLYPH_CHAR_VALID_P (XFASTINT (DISP_ESCAPE_GLYPH (it->dp))))
197516c2 4817 escape_glyph = XFASTINT (DISP_ESCAPE_GLYPH (it->dp));
5f5c8ee5 4818 else
197516c2
KH
4819 escape_glyph = FAST_MAKE_GLYPH ('\\', 0);
4820
c5924f47
KH
4821 if (SINGLE_BYTE_CHAR_P (it->c))
4822 str[0] = it->c, len = 1;
4823 else
ea9dd091
GM
4824 {
4825 len = CHAR_STRING_NO_SIGNAL (it->c, str);
4826 if (len < 0)
4827 {
4828 /* It's an invalid character, which
4829 shouldn't happen actually, but due to
4830 bugs it may happen. Let's print the char
4831 as is, there's not much meaningful we can
4832 do with it. */
4833 str[0] = it->c;
4834 str[1] = it->c >> 8;
4835 str[2] = it->c >> 16;
4836 str[3] = it->c >> 24;
4837 len = 4;
4838 }
4839 }
c5924f47 4840
197516c2
KH
4841 for (i = 0; i < len; i++)
4842 {
4843 XSETINT (it->ctl_chars[i * 4], escape_glyph);
4844 /* Insert three more glyphs into IT->ctl_chars for
4845 the octal display of the character. */
2311178e 4846 g = FAST_MAKE_GLYPH (((str[i] >> 6) & 7) + '0', 0);
197516c2 4847 XSETINT (it->ctl_chars[i * 4 + 1], g);
2311178e 4848 g = FAST_MAKE_GLYPH (((str[i] >> 3) & 7) + '0', 0);
197516c2 4849 XSETINT (it->ctl_chars[i * 4 + 2], g);
2311178e 4850 g = FAST_MAKE_GLYPH ((str[i] & 7) + '0', 0);
197516c2
KH
4851 XSETINT (it->ctl_chars[i * 4 + 3], g);
4852 }
5f5c8ee5
GM
4853
4854 /* Set up IT->dpvec and return the first character
4855 from it. */
4856 it->dpvec_char_len = it->len;
4857 it->dpvec = it->ctl_chars;
197516c2 4858 it->dpend = it->dpvec + len * 4;
5f5c8ee5
GM
4859 it->current.dpvec_index = 0;
4860 it->method = next_element_from_display_vector;
4861 get_next_display_element (it);
4862 }
4863 }
4864 }
4865
980806b6
KH
4866 /* Adjust face id for a multibyte character. There are no
4867 multibyte character in unibyte text. */
5f5c8ee5
GM
4868 if (it->multibyte_p
4869 && success_p
980806b6 4870 && FRAME_WINDOW_P (it->f))
5f5c8ee5 4871 {
980806b6
KH
4872 struct face *face = FACE_FROM_ID (it->f, it->face_id);
4873 it->face_id = FACE_FOR_CHAR (it->f, face, it->c);
5f5c8ee5
GM
4874 }
4875 }
4876
4877 /* Is this character the last one of a run of characters with
4878 box? If yes, set IT->end_of_box_run_p to 1. */
4879 if (it->face_box_p
4880 && it->s == NULL)
4881 {
4882 int face_id;
4883 struct face *face;
4884
4885 it->end_of_box_run_p
4886 = ((face_id = face_after_it_pos (it),
4887 face_id != it->face_id)
4888 && (face = FACE_FROM_ID (it->f, face_id),
4889 face->box == FACE_NO_BOX));
4890 }
4891
4892 /* Value is 0 if end of buffer or string reached. */
4893 return success_p;
4894}
4895
4896
4897/* Move IT to the next display element.
4898
cafafe0b
GM
4899 RESEAT_P non-zero means if called on a newline in buffer text,
4900 skip to the next visible line start.
4901
5f5c8ee5
GM
4902 Functions get_next_display_element and set_iterator_to_next are
4903 separate because I find this arrangement easier to handle than a
4904 get_next_display_element function that also increments IT's
4905 position. The way it is we can first look at an iterator's current
4906 display element, decide whether it fits on a line, and if it does,
4907 increment the iterator position. The other way around we probably
4908 would either need a flag indicating whether the iterator has to be
4909 incremented the next time, or we would have to implement a
4910 decrement position function which would not be easy to write. */
4911
4912void
cafafe0b 4913set_iterator_to_next (it, reseat_p)
5f5c8ee5 4914 struct it *it;
cafafe0b 4915 int reseat_p;
5f5c8ee5 4916{
483de32b
GM
4917 /* Reset flags indicating start and end of a sequence of characters
4918 with box. Reset them at the start of this function because
4919 moving the iterator to a new position might set them. */
4920 it->start_of_box_run_p = it->end_of_box_run_p = 0;
2311178e 4921
5f5c8ee5
GM
4922 if (it->method == next_element_from_buffer)
4923 {
4924 /* The current display element of IT is a character from
4925 current_buffer. Advance in the buffer, and maybe skip over
4926 invisible lines that are so because of selective display. */
cafafe0b 4927 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
312246d1 4928 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
4929 else
4930 {
4931 xassert (it->len != 0);
4932 IT_BYTEPOS (*it) += it->len;
4933 IT_CHARPOS (*it) += 1;
4934 xassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
4935 }
4936 }
260a86a0
KH
4937 else if (it->method == next_element_from_composition)
4938 {
4939 xassert (it->cmp_id >= 0 && it ->cmp_id < n_compositions);
4940 if (STRINGP (it->string))
4941 {
4942 IT_STRING_BYTEPOS (*it) += it->len;
4943 IT_STRING_CHARPOS (*it) += it->cmp_len;
4944 it->method = next_element_from_string;
4945 goto consider_string_end;
4946 }
4947 else
4948 {
4949 IT_BYTEPOS (*it) += it->len;
4950 IT_CHARPOS (*it) += it->cmp_len;
4951 it->method = next_element_from_buffer;
4952 }
4953 }
5f5c8ee5
GM
4954 else if (it->method == next_element_from_c_string)
4955 {
4956 /* Current display element of IT is from a C string. */
4957 IT_BYTEPOS (*it) += it->len;
4958 IT_CHARPOS (*it) += 1;
4959 }
4960 else if (it->method == next_element_from_display_vector)
4961 {
4962 /* Current display element of IT is from a display table entry.
4963 Advance in the display table definition. Reset it to null if
4964 end reached, and continue with characters from buffers/
4965 strings. */
4966 ++it->current.dpvec_index;
286bcbc9 4967
980806b6
KH
4968 /* Restore face of the iterator to what they were before the
4969 display vector entry (these entries may contain faces). */
5f5c8ee5 4970 it->face_id = it->saved_face_id;
2311178e 4971
5f5c8ee5
GM
4972 if (it->dpvec + it->current.dpvec_index == it->dpend)
4973 {
4974 if (it->s)
4975 it->method = next_element_from_c_string;
4976 else if (STRINGP (it->string))
4977 it->method = next_element_from_string;
4978 else
4979 it->method = next_element_from_buffer;
4980
4981 it->dpvec = NULL;
4982 it->current.dpvec_index = -1;
4983
312246d1
GM
4984 /* Skip over characters which were displayed via IT->dpvec. */
4985 if (it->dpvec_char_len < 0)
4986 reseat_at_next_visible_line_start (it, 1);
4987 else if (it->dpvec_char_len > 0)
5f5c8ee5
GM
4988 {
4989 it->len = it->dpvec_char_len;
cafafe0b 4990 set_iterator_to_next (it, reseat_p);
5f5c8ee5
GM
4991 }
4992 }
4993 }
4994 else if (it->method == next_element_from_string)
4995 {
4996 /* Current display element is a character from a Lisp string. */
4997 xassert (it->s == NULL && STRINGP (it->string));
4998 IT_STRING_BYTEPOS (*it) += it->len;
4999 IT_STRING_CHARPOS (*it) += 1;
2311178e 5000
5f5c8ee5
GM
5001 consider_string_end:
5002
5003 if (it->current.overlay_string_index >= 0)
5004 {
5005 /* IT->string is an overlay string. Advance to the
5006 next, if there is one. */
2051c264 5007 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
5008 next_overlay_string (it);
5009 }
5010 else
5011 {
5012 /* IT->string is not an overlay string. If we reached
5013 its end, and there is something on IT->stack, proceed
5014 with what is on the stack. This can be either another
5015 string, this time an overlay string, or a buffer. */
2051c264 5016 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
5f5c8ee5
GM
5017 && it->sp > 0)
5018 {
5019 pop_it (it);
5020 if (!STRINGP (it->string))
5021 it->method = next_element_from_buffer;
b2046df8
GM
5022 else
5023 goto consider_string_end;
5f5c8ee5
GM
5024 }
5025 }
5026 }
5027 else if (it->method == next_element_from_image
5028 || it->method == next_element_from_stretch)
5029 {
5030 /* The position etc with which we have to proceed are on
5031 the stack. The position may be at the end of a string,
5032 if the `display' property takes up the whole string. */
5033 pop_it (it);
5034 it->image_id = 0;
5035 if (STRINGP (it->string))
5036 {
5037 it->method = next_element_from_string;
5038 goto consider_string_end;
5039 }
5040 else
5041 it->method = next_element_from_buffer;
5042 }
5043 else
5044 /* There are no other methods defined, so this should be a bug. */
5045 abort ();
5046
5f5c8ee5
GM
5047 xassert (it->method != next_element_from_string
5048 || (STRINGP (it->string)
5049 && IT_STRING_CHARPOS (*it) >= 0));
5050}
5051
5052
5053/* Load IT's display element fields with information about the next
5054 display element which comes from a display table entry or from the
5055 result of translating a control character to one of the forms `^C'
5056 or `\003'. IT->dpvec holds the glyphs to return as characters. */
5057
5058static int
5059next_element_from_display_vector (it)
5060 struct it *it;
5061{
5062 /* Precondition. */
5063 xassert (it->dpvec && it->current.dpvec_index >= 0);
5064
5065 /* Remember the current face id in case glyphs specify faces.
5066 IT's face is restored in set_iterator_to_next. */
5067 it->saved_face_id = it->face_id;
2311178e 5068
5f5c8ee5
GM
5069 if (INTEGERP (*it->dpvec)
5070 && GLYPH_CHAR_VALID_P (XFASTINT (*it->dpvec)))
5071 {
5072 int lface_id;
5073 GLYPH g;
5074
5075 g = XFASTINT (it->dpvec[it->current.dpvec_index]);
5076 it->c = FAST_GLYPH_CHAR (g);
c5924f47 5077 it->len = CHAR_BYTES (it->c);
5f5c8ee5
GM
5078
5079 /* The entry may contain a face id to use. Such a face id is
5080 the id of a Lisp face, not a realized face. A face id of
969065c3 5081 zero means no face is specified. */
5f5c8ee5
GM
5082 lface_id = FAST_GLYPH_FACE (g);
5083 if (lface_id)
5084 {
969065c3 5085 /* The function returns -1 if lface_id is invalid. */
5f5c8ee5
GM
5086 int face_id = ascii_face_of_lisp_face (it->f, lface_id);
5087 if (face_id >= 0)
969065c3 5088 it->face_id = face_id;
5f5c8ee5
GM
5089 }
5090 }
5091 else
5092 /* Display table entry is invalid. Return a space. */
5093 it->c = ' ', it->len = 1;
5094
5095 /* Don't change position and object of the iterator here. They are
5096 still the values of the character that had this display table
5097 entry or was translated, and that's what we want. */
5098 it->what = IT_CHARACTER;
5099 return 1;
5100}
5101
5102
5103/* Load IT with the next display element from Lisp string IT->string.
5104 IT->current.string_pos is the current position within the string.
5105 If IT->current.overlay_string_index >= 0, the Lisp string is an
5106 overlay string. */
5107
5108static int
5109next_element_from_string (it)
5110 struct it *it;
5111{
5112 struct text_pos position;
5113
5114 xassert (STRINGP (it->string));
5115 xassert (IT_STRING_CHARPOS (*it) >= 0);
5116 position = it->current.string_pos;
5117
5118 /* Time to check for invisible text? */
5119 if (IT_STRING_CHARPOS (*it) < it->end_charpos
5120 && IT_STRING_CHARPOS (*it) == it->stop_charpos)
5121 {
5122 handle_stop (it);
5123
5124 /* Since a handler may have changed IT->method, we must
5125 recurse here. */
5126 return get_next_display_element (it);
5127 }
5128
5129 if (it->current.overlay_string_index >= 0)
5130 {
5131 /* Get the next character from an overlay string. In overlay
5132 strings, There is no field width or padding with spaces to
5133 do. */
2051c264 5134 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
5f5c8ee5
GM
5135 {
5136 it->what = IT_EOB;
5137 return 0;
5138 }
5139 else if (STRING_MULTIBYTE (it->string))
5140 {
2051c264 5141 int remaining = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5142 const unsigned char *s = (SDATA (it->string)
5143 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5144 it->c = string_char_and_length (s, remaining, &it->len);
5f5c8ee5
GM
5145 }
5146 else
5147 {
2051c264 5148 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5149 it->len = 1;
5150 }
5151 }
5152 else
5153 {
5154 /* Get the next character from a Lisp string that is not an
5155 overlay string. Such strings come from the mode line, for
5156 example. We may have to pad with spaces, or truncate the
5157 string. See also next_element_from_c_string. */
5158 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
5159 {
5160 it->what = IT_EOB;
5161 return 0;
5162 }
5163 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
5164 {
5165 /* Pad with spaces. */
5166 it->c = ' ', it->len = 1;
5167 CHARPOS (position) = BYTEPOS (position) = -1;
5168 }
5169 else if (STRING_MULTIBYTE (it->string))
5170 {
2051c264 5171 int maxlen = SBYTES (it->string) - IT_STRING_BYTEPOS (*it);
50f80c2f
KR
5172 const unsigned char *s = (SDATA (it->string)
5173 + IT_STRING_BYTEPOS (*it));
4fdb80f2 5174 it->c = string_char_and_length (s, maxlen, &it->len);
5f5c8ee5
GM
5175 }
5176 else
5177 {
2051c264 5178 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
5f5c8ee5
GM
5179 it->len = 1;
5180 }
5181 }
5182
5183 /* Record what we have and where it came from. Note that we store a
5184 buffer position in IT->position although it could arguably be a
5185 string position. */
5186 it->what = IT_CHARACTER;
5187 it->object = it->string;
5188 it->position = position;
5189 return 1;
5190}
5191
5192
5193/* Load IT with next display element from C string IT->s.
5194 IT->string_nchars is the maximum number of characters to return
5195 from the string. IT->end_charpos may be greater than
5196 IT->string_nchars when this function is called, in which case we
5197 may have to return padding spaces. Value is zero if end of string
5198 reached, including padding spaces. */
5199
5200static int
5201next_element_from_c_string (it)
5202 struct it *it;
5203{
5204 int success_p = 1;
2311178e 5205
5f5c8ee5
GM
5206 xassert (it->s);
5207 it->what = IT_CHARACTER;
5208 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
5209 it->object = Qnil;
2311178e 5210
5f5c8ee5
GM
5211 /* IT's position can be greater IT->string_nchars in case a field
5212 width or precision has been specified when the iterator was
5213 initialized. */
5214 if (IT_CHARPOS (*it) >= it->end_charpos)
5215 {
5216 /* End of the game. */
5217 it->what = IT_EOB;
5218 success_p = 0;
5219 }
5220 else if (IT_CHARPOS (*it) >= it->string_nchars)
5221 {
5222 /* Pad with spaces. */
5223 it->c = ' ', it->len = 1;
5224 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
5225 }
5226 else if (it->multibyte_p)
5227 {
5228 /* Implementation note: The calls to strlen apparently aren't a
5229 performance problem because there is no noticeable performance
5230 difference between Emacs running in unibyte or multibyte mode. */
5231 int maxlen = strlen (it->s) - IT_BYTEPOS (*it);
4fdb80f2
GM
5232 it->c = string_char_and_length (it->s + IT_BYTEPOS (*it),
5233 maxlen, &it->len);
5f5c8ee5
GM
5234 }
5235 else
5236 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
2311178e 5237
5f5c8ee5
GM
5238 return success_p;
5239}
5240
5241
5242/* Set up IT to return characters from an ellipsis, if appropriate.
5243 The definition of the ellipsis glyphs may come from a display table
5244 entry. This function Fills IT with the first glyph from the
5245 ellipsis if an ellipsis is to be displayed. */
5246
13f19968 5247static int
5f5c8ee5
GM
5248next_element_from_ellipsis (it)
5249 struct it *it;
5250{
13f19968 5251 if (it->selective_display_ellipsis_p)
5f5c8ee5 5252 {
13f19968
GM
5253 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5254 {
5255 /* Use the display table definition for `...'. Invalid glyphs
5256 will be handled by the method returning elements from dpvec. */
5257 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5258 it->dpvec_char_len = it->len;
5259 it->dpvec = v->contents;
5260 it->dpend = v->contents + v->size;
5261 it->current.dpvec_index = 0;
5262 it->method = next_element_from_display_vector;
5263 }
5264 else
5265 {
5266 /* Use default `...' which is stored in default_invis_vector. */
5267 it->dpvec_char_len = it->len;
5268 it->dpvec = default_invis_vector;
5269 it->dpend = default_invis_vector + 3;
5270 it->current.dpvec_index = 0;
5271 it->method = next_element_from_display_vector;
5272 }
5f5c8ee5 5273 }
13f19968 5274 else
54918e2b 5275 {
4aad61f8
GM
5276 /* The face at the current position may be different from the
5277 face we find after the invisible text. Remember what it
5278 was in IT->saved_face_id, and signal that it's there by
5279 setting face_before_selective_p. */
5280 it->saved_face_id = it->face_id;
54918e2b
GM
5281 it->method = next_element_from_buffer;
5282 reseat_at_next_visible_line_start (it, 1);
4aad61f8 5283 it->face_before_selective_p = 1;
54918e2b 5284 }
2311178e 5285
13f19968 5286 return get_next_display_element (it);
5f5c8ee5
GM
5287}
5288
5289
5290/* Deliver an image display element. The iterator IT is already
5291 filled with image information (done in handle_display_prop). Value
5292 is always 1. */
2311178e 5293
5f5c8ee5
GM
5294
5295static int
5296next_element_from_image (it)
5297 struct it *it;
5298{
5299 it->what = IT_IMAGE;
5300 return 1;
5301}
5302
5303
5304/* Fill iterator IT with next display element from a stretch glyph
5305 property. IT->object is the value of the text property. Value is
5306 always 1. */
5307
5308static int
5309next_element_from_stretch (it)
5310 struct it *it;
5311{
5312 it->what = IT_STRETCH;
5313 return 1;
5314}
5315
5316
5317/* Load IT with the next display element from current_buffer. Value
5318 is zero if end of buffer reached. IT->stop_charpos is the next
5319 position at which to stop and check for text properties or buffer
5320 end. */
5321
5322static int
5323next_element_from_buffer (it)
5324 struct it *it;
5325{
5326 int success_p = 1;
5327
5328 /* Check this assumption, otherwise, we would never enter the
5329 if-statement, below. */
5330 xassert (IT_CHARPOS (*it) >= BEGV
5331 && IT_CHARPOS (*it) <= it->stop_charpos);
5332
5333 if (IT_CHARPOS (*it) >= it->stop_charpos)
5334 {
5335 if (IT_CHARPOS (*it) >= it->end_charpos)
5336 {
5337 int overlay_strings_follow_p;
2311178e 5338
5f5c8ee5
GM
5339 /* End of the game, except when overlay strings follow that
5340 haven't been returned yet. */
5341 if (it->overlay_strings_at_end_processed_p)
5342 overlay_strings_follow_p = 0;
5343 else
5344 {
5345 it->overlay_strings_at_end_processed_p = 1;
5a08cbaf 5346 overlay_strings_follow_p = get_overlay_strings (it, 0);
5f5c8ee5
GM
5347 }
5348
5349 if (overlay_strings_follow_p)
5350 success_p = get_next_display_element (it);
5351 else
5352 {
5353 it->what = IT_EOB;
5354 it->position = it->current.pos;
5355 success_p = 0;
5356 }
5357 }
5358 else
5359 {
5360 handle_stop (it);
5361 return get_next_display_element (it);
5362 }
5363 }
5364 else
5365 {
5366 /* No face changes, overlays etc. in sight, so just return a
5367 character from current_buffer. */
5368 unsigned char *p;
5369
5370 /* Maybe run the redisplay end trigger hook. Performance note:
5371 This doesn't seem to cost measurable time. */
5372 if (it->redisplay_end_trigger_charpos
5373 && it->glyph_row
5374 && IT_CHARPOS (*it) >= it->redisplay_end_trigger_charpos)
5375 run_redisplay_end_trigger_hook (it);
5376
5377 /* Get the next character, maybe multibyte. */
5378 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
260a86a0 5379 if (it->multibyte_p && !ASCII_BYTE_P (*p))
5f5c8ee5
GM
5380 {
5381 int maxlen = ((IT_BYTEPOS (*it) >= GPT_BYTE ? ZV_BYTE : GPT_BYTE)
5382 - IT_BYTEPOS (*it));
4fdb80f2 5383 it->c = string_char_and_length (p, maxlen, &it->len);
5f5c8ee5
GM
5384 }
5385 else
5386 it->c = *p, it->len = 1;
5387
5388 /* Record what we have and where it came from. */
5389 it->what = IT_CHARACTER;;
5390 it->object = it->w->buffer;
5391 it->position = it->current.pos;
5392
5393 /* Normally we return the character found above, except when we
5394 really want to return an ellipsis for selective display. */
5395 if (it->selective)
5396 {
5397 if (it->c == '\n')
5398 {
5399 /* A value of selective > 0 means hide lines indented more
5400 than that number of columns. */
5401 if (it->selective > 0
5402 && IT_CHARPOS (*it) + 1 < ZV
5403 && indented_beyond_p (IT_CHARPOS (*it) + 1,
5404 IT_BYTEPOS (*it) + 1,
a67e162b 5405 (double) it->selective)) /* iftc */
312246d1 5406 {
13f19968 5407 success_p = next_element_from_ellipsis (it);
312246d1
GM
5408 it->dpvec_char_len = -1;
5409 }
5f5c8ee5
GM
5410 }
5411 else if (it->c == '\r' && it->selective == -1)
5412 {
5413 /* A value of selective == -1 means that everything from the
5414 CR to the end of the line is invisible, with maybe an
5415 ellipsis displayed for it. */
13f19968 5416 success_p = next_element_from_ellipsis (it);
312246d1 5417 it->dpvec_char_len = -1;
5f5c8ee5
GM
5418 }
5419 }
5420 }
5421
5422 /* Value is zero if end of buffer reached. */
c880678e 5423 xassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
5f5c8ee5
GM
5424 return success_p;
5425}
5426
2311178e 5427
5f5c8ee5
GM
5428/* Run the redisplay end trigger hook for IT. */
5429
5430static void
5431run_redisplay_end_trigger_hook (it)
5432 struct it *it;
5433{
5434 Lisp_Object args[3];
5435
5436 /* IT->glyph_row should be non-null, i.e. we should be actually
5437 displaying something, or otherwise we should not run the hook. */
5438 xassert (it->glyph_row);
5439
5440 /* Set up hook arguments. */
5441 args[0] = Qredisplay_end_trigger_functions;
5442 args[1] = it->window;
5443 XSETINT (args[2], it->redisplay_end_trigger_charpos);
5444 it->redisplay_end_trigger_charpos = 0;
5445
5446 /* Since we are *trying* to run these functions, don't try to run
5447 them again, even if they get an error. */
5448 it->w->redisplay_end_trigger = Qnil;
5449 Frun_hook_with_args (3, args);
2311178e 5450
5f5c8ee5
GM
5451 /* Notice if it changed the face of the character we are on. */
5452 handle_face_prop (it);
5453}
5454
5455
260a86a0
KH
5456/* Deliver a composition display element. The iterator IT is already
5457 filled with composition information (done in
5458 handle_composition_prop). Value is always 1. */
5459
5460static int
5461next_element_from_composition (it)
5462 struct it *it;
5463{
5464 it->what = IT_COMPOSITION;
5465 it->position = (STRINGP (it->string)
5466 ? it->current.string_pos
5467 : it->current.pos);
5468 return 1;
5469}
5470
5471
5f5c8ee5
GM
5472\f
5473/***********************************************************************
5474 Moving an iterator without producing glyphs
5475 ***********************************************************************/
5476
5477/* Move iterator IT to a specified buffer or X position within one
5478 line on the display without producing glyphs.
5479
c53a1624
RS
5480 OP should be a bit mask including some or all of these bits:
5481 MOVE_TO_X: Stop on reaching x-position TO_X.
5482 MOVE_TO_POS: Stop on reaching buffer or string position TO_CHARPOS.
5483 Regardless of OP's value, stop in reaching the end of the display line.
5f5c8ee5 5484
c53a1624
RS
5485 TO_X is normally a value 0 <= TO_X <= IT->last_visible_x.
5486 This means, in particular, that TO_X includes window's horizontal
5487 scroll amount.
5f5c8ee5 5488
c53a1624
RS
5489 The return value has several possible values that
5490 say what condition caused the scan to stop:
5f5c8ee5
GM
5491
5492 MOVE_POS_MATCH_OR_ZV
5493 - when TO_POS or ZV was reached.
2311178e 5494
5f5c8ee5
GM
5495 MOVE_X_REACHED
5496 -when TO_X was reached before TO_POS or ZV were reached.
2311178e 5497
5f5c8ee5
GM
5498 MOVE_LINE_CONTINUED
5499 - when we reached the end of the display area and the line must
5500 be continued.
2311178e 5501
5f5c8ee5
GM
5502 MOVE_LINE_TRUNCATED
5503 - when we reached the end of the display area and the line is
5504 truncated.
5505
5506 MOVE_NEWLINE_OR_CR
5507 - when we stopped at a line end, i.e. a newline or a CR and selective
5508 display is on. */
5509
701552dd 5510static enum move_it_result
5f5c8ee5
GM
5511move_it_in_display_line_to (it, to_charpos, to_x, op)
5512 struct it *it;
5513 int to_charpos, to_x, op;
5514{
5515 enum move_it_result result = MOVE_UNDEFINED;
5516 struct glyph_row *saved_glyph_row;
5517
5518 /* Don't produce glyphs in produce_glyphs. */
5519 saved_glyph_row = it->glyph_row;
5520 it->glyph_row = NULL;
5521
5f5c8ee5
GM
5522 while (1)
5523 {
ae26e27d 5524 int x, i, ascent = 0, descent = 0;
2311178e 5525
5f5c8ee5
GM
5526 /* Stop when ZV or TO_CHARPOS reached. */
5527 if (!get_next_display_element (it)
5528 || ((op & MOVE_TO_POS) != 0
5529 && BUFFERP (it->object)
5530 && IT_CHARPOS (*it) >= to_charpos))
5531 {
5532 result = MOVE_POS_MATCH_OR_ZV;
5533 break;
5534 }
2311178e 5535
5f5c8ee5
GM
5536 /* The call to produce_glyphs will get the metrics of the
5537 display element IT is loaded with. We record in x the
5538 x-position before this display element in case it does not
5539 fit on the line. */
5540 x = it->current_x;
2311178e 5541
47589c8c
GM
5542 /* Remember the line height so far in case the next element doesn't
5543 fit on the line. */
5544 if (!it->truncate_lines_p)
5545 {
5546 ascent = it->max_ascent;
5547 descent = it->max_descent;
5548 }
2311178e 5549
5f5c8ee5
GM
5550 PRODUCE_GLYPHS (it);
5551
5552 if (it->area != TEXT_AREA)
5553 {
cafafe0b 5554 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5555 continue;
5556 }
5557
5558 /* The number of glyphs we get back in IT->nglyphs will normally
5559 be 1 except when IT->c is (i) a TAB, or (ii) a multi-glyph
5560 character on a terminal frame, or (iii) a line end. For the
5561 second case, IT->nglyphs - 1 padding glyphs will be present
5562 (on X frames, there is only one glyph produced for a
5563 composite character.
5564
5565 The behavior implemented below means, for continuation lines,
5566 that as many spaces of a TAB as fit on the current line are
5567 displayed there. For terminal frames, as many glyphs of a
5568 multi-glyph character are displayed in the current line, too.
5569 This is what the old redisplay code did, and we keep it that
5570 way. Under X, the whole shape of a complex character must
5571 fit on the line or it will be completely displayed in the
5572 next line.
5573
5574 Note that both for tabs and padding glyphs, all glyphs have
5575 the same width. */
5576 if (it->nglyphs)
5577 {
5578 /* More than one glyph or glyph doesn't fit on line. All
5579 glyphs have the same width. */
5580 int single_glyph_width = it->pixel_width / it->nglyphs;
5581 int new_x;
2311178e 5582
5f5c8ee5
GM
5583 for (i = 0; i < it->nglyphs; ++i, x = new_x)
5584 {
5585 new_x = x + single_glyph_width;
5586
5587 /* We want to leave anything reaching TO_X to the caller. */
5588 if ((op & MOVE_TO_X) && new_x > to_x)
5589 {
5590 it->current_x = x;
5591 result = MOVE_X_REACHED;
5592 break;
5593 }
5594 else if (/* Lines are continued. */
5595 !it->truncate_lines_p
5596 && (/* And glyph doesn't fit on the line. */
5597 new_x > it->last_visible_x
5598 /* Or it fits exactly and we're on a window
5599 system frame. */
5600 || (new_x == it->last_visible_x
5601 && FRAME_WINDOW_P (it->f))))
5602 {
5603 if (/* IT->hpos == 0 means the very first glyph
5604 doesn't fit on the line, e.g. a wide image. */
5605 it->hpos == 0
5606 || (new_x == it->last_visible_x
5607 && FRAME_WINDOW_P (it->f)))
5608 {
5609 ++it->hpos;
5610 it->current_x = new_x;
5611 if (i == it->nglyphs - 1)
88e6b646
KS
5612 {
5613 set_iterator_to_next (it, 1);
7af0e8d7 5614#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
5615 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
5616 {
5617 get_next_display_element (it);
5618 if (ITERATOR_AT_END_OF_LINE_P (it))
5619 {
5620 result = MOVE_NEWLINE_OR_CR;
5621 break;
5622 }
5623 }
7af0e8d7 5624#endif /* HAVE_WINDOW_SYSTEM */
88e6b646 5625 }
5f5c8ee5
GM
5626 }
5627 else
47589c8c
GM
5628 {
5629 it->current_x = x;
5630 it->max_ascent = ascent;
5631 it->max_descent = descent;
5632 }
2311178e 5633
47589c8c
GM
5634 TRACE_MOVE ((stderr, "move_it_in: continued at %d\n",
5635 IT_CHARPOS (*it)));
5f5c8ee5
GM
5636 result = MOVE_LINE_CONTINUED;
5637 break;
5638 }
5639 else if (new_x > it->first_visible_x)
5640 {
5641 /* Glyph is visible. Increment number of glyphs that
5642 would be displayed. */
5643 ++it->hpos;
5644 }
5645 else
5646 {
2311178e 5647 /* Glyph is completely off the left margin of the display
5f5c8ee5
GM
5648 area. Nothing to do. */
5649 }
5650 }
5651
5652 if (result != MOVE_UNDEFINED)
5653 break;
5654 }
5655 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
5656 {
5657 /* Stop when TO_X specified and reached. This check is
5658 necessary here because of lines consisting of a line end,
5659 only. The line end will not produce any glyphs and we
5660 would never get MOVE_X_REACHED. */
5661 xassert (it->nglyphs == 0);
5662 result = MOVE_X_REACHED;
5663 break;
5664 }
2311178e 5665
5f5c8ee5
GM
5666 /* Is this a line end? If yes, we're done. */
5667 if (ITERATOR_AT_END_OF_LINE_P (it))
5668 {
5669 result = MOVE_NEWLINE_OR_CR;
5670 break;
5671 }
2311178e 5672
5f5c8ee5
GM
5673 /* The current display element has been consumed. Advance
5674 to the next. */
cafafe0b 5675 set_iterator_to_next (it, 1);
2311178e 5676
5f5c8ee5
GM
5677 /* Stop if lines are truncated and IT's current x-position is
5678 past the right edge of the window now. */
5679 if (it->truncate_lines_p
5680 && it->current_x >= it->last_visible_x)
5681 {
7af0e8d7 5682#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
5683 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
5684 {
5685 get_next_display_element (it);
5686 if (ITERATOR_AT_END_OF_LINE_P (it))
5687 {
5688 result = MOVE_NEWLINE_OR_CR;
5689 break;
5690 }
5691 }
7af0e8d7 5692#endif /* HAVE_WINDOW_SYSTEM */
5f5c8ee5
GM
5693 result = MOVE_LINE_TRUNCATED;
5694 break;
5695 }
5696 }
5697
5698 /* Restore the iterator settings altered at the beginning of this
5699 function. */
5700 it->glyph_row = saved_glyph_row;
5701 return result;
5702}
5703
5704
9b2bba76
RS
5705/* Move IT forward until it satisfies one or more of the criteria in
5706 TO_CHARPOS, TO_X, TO_Y, and TO_VPOS.
5707
5708 OP is a bit-mask that specifies where to stop, and in particular,
5709 which of those four position arguments makes a difference. See the
5710 description of enum move_operation_enum.
2311178e 5711
5f5c8ee5
GM
5712 If TO_CHARPOS is in invisible text, e.g. a truncated part of a
5713 screen line, this function will set IT to the next position >
5714 TO_CHARPOS. */
5715
5716void
5717move_it_to (it, to_charpos, to_x, to_y, to_vpos, op)
5718 struct it *it;
5719 int to_charpos, to_x, to_y, to_vpos;
5720 int op;
5721{
5722 enum move_it_result skip, skip2 = MOVE_X_REACHED;
5723 int line_height;
47589c8c 5724 int reached = 0;
5f5c8ee5 5725
47589c8c 5726 for (;;)
5f5c8ee5
GM
5727 {
5728 if (op & MOVE_TO_VPOS)
5729 {
5730 /* If no TO_CHARPOS and no TO_X specified, stop at the
5731 start of the line TO_VPOS. */
5732 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
5733 {
5734 if (it->vpos == to_vpos)
47589c8c
GM
5735 {
5736 reached = 1;
5737 break;
5738 }
5739 else
5740 skip = move_it_in_display_line_to (it, -1, -1, 0);
5f5c8ee5
GM
5741 }
5742 else
5743 {
5744 /* TO_VPOS >= 0 means stop at TO_X in the line at
5745 TO_VPOS, or at TO_POS, whichever comes first. */
47589c8c
GM
5746 if (it->vpos == to_vpos)
5747 {
5748 reached = 2;
5749 break;
5750 }
2311178e 5751
5f5c8ee5
GM
5752 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
5753
5754 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
47589c8c
GM
5755 {
5756 reached = 3;
5757 break;
5758 }
5f5c8ee5
GM
5759 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
5760 {
5761 /* We have reached TO_X but not in the line we want. */
5762 skip = move_it_in_display_line_to (it, to_charpos,
5763 -1, MOVE_TO_POS);
5764 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5765 {
5766 reached = 4;
5767 break;
5768 }
5f5c8ee5
GM
5769 }
5770 }
5771 }
5772 else if (op & MOVE_TO_Y)
5773 {
5774 struct it it_backup;
2311178e 5775
5f5c8ee5
GM
5776 /* TO_Y specified means stop at TO_X in the line containing
5777 TO_Y---or at TO_CHARPOS if this is reached first. The
5778 problem is that we can't really tell whether the line
5779 contains TO_Y before we have completely scanned it, and
5780 this may skip past TO_X. What we do is to first scan to
5781 TO_X.
5782
5783 If TO_X is not specified, use a TO_X of zero. The reason
5784 is to make the outcome of this function more predictable.
5785 If we didn't use TO_X == 0, we would stop at the end of
5786 the line which is probably not what a caller would expect
5787 to happen. */
5788 skip = move_it_in_display_line_to (it, to_charpos,
5789 ((op & MOVE_TO_X)
5790 ? to_x : 0),
5791 (MOVE_TO_X
5792 | (op & MOVE_TO_POS)));
5793
5794 /* If TO_CHARPOS is reached or ZV, we don't have to do more. */
5795 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c
GM
5796 {
5797 reached = 5;
5798 break;
5799 }
2311178e 5800
5f5c8ee5
GM
5801 /* If TO_X was reached, we would like to know whether TO_Y
5802 is in the line. This can only be said if we know the
5803 total line height which requires us to scan the rest of
5804 the line. */
5f5c8ee5
GM
5805 if (skip == MOVE_X_REACHED)
5806 {
5807 it_backup = *it;
47589c8c 5808 TRACE_MOVE ((stderr, "move_it: from %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5809 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
5810 op & MOVE_TO_POS);
47589c8c 5811 TRACE_MOVE ((stderr, "move_it: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
5812 }
5813
5814 /* Now, decide whether TO_Y is in this line. */
5815 line_height = it->max_ascent + it->max_descent;
47589c8c 5816 TRACE_MOVE ((stderr, "move_it: line_height = %d\n", line_height));
2311178e 5817
5f5c8ee5
GM
5818 if (to_y >= it->current_y
5819 && to_y < it->current_y + line_height)
5820 {
5821 if (skip == MOVE_X_REACHED)
5822 /* If TO_Y is in this line and TO_X was reached above,
5823 we scanned too far. We have to restore IT's settings
5824 to the ones before skipping. */
5825 *it = it_backup;
47589c8c 5826 reached = 6;
5f5c8ee5
GM
5827 }
5828 else if (skip == MOVE_X_REACHED)
5829 {
5830 skip = skip2;
5831 if (skip == MOVE_POS_MATCH_OR_ZV)
47589c8c 5832 reached = 7;
5f5c8ee5
GM
5833 }
5834
47589c8c 5835 if (reached)
5f5c8ee5
GM
5836 break;
5837 }
5838 else
5839 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
5840
5841 switch (skip)
5842 {
5843 case MOVE_POS_MATCH_OR_ZV:
47589c8c
GM
5844 reached = 8;
5845 goto out;
5f5c8ee5
GM
5846
5847 case MOVE_NEWLINE_OR_CR:
cafafe0b 5848 set_iterator_to_next (it, 1);
5f5c8ee5
GM
5849 it->continuation_lines_width = 0;
5850 break;
5851
5852 case MOVE_LINE_TRUNCATED:
5853 it->continuation_lines_width = 0;
312246d1 5854 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
5855 if ((op & MOVE_TO_POS) != 0
5856 && IT_CHARPOS (*it) > to_charpos)
47589c8c
GM
5857 {
5858 reached = 9;
5859 goto out;
5860 }
5f5c8ee5
GM
5861 break;
5862
5863 case MOVE_LINE_CONTINUED:
5864 it->continuation_lines_width += it->current_x;
5865 break;
5866
5867 default:
5868 abort ();
5869 }
5870
5871 /* Reset/increment for the next run. */
5872 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
5873 it->current_x = it->hpos = 0;
5874 it->current_y += it->max_ascent + it->max_descent;
5875 ++it->vpos;
5876 last_height = it->max_ascent + it->max_descent;
5877 last_max_ascent = it->max_ascent;
5878 it->max_ascent = it->max_descent = 0;
5879 }
2311178e 5880
47589c8c
GM
5881 out:
5882
5883 TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
5f5c8ee5
GM
5884}
5885
5886
5887/* Move iterator IT backward by a specified y-distance DY, DY >= 0.
5888
5889 If DY > 0, move IT backward at least that many pixels. DY = 0
5890 means move IT backward to the preceding line start or BEGV. This
5891 function may move over more than DY pixels if IT->current_y - DY
5892 ends up in the middle of a line; in this case IT->current_y will be
5893 set to the top of the line moved to. */
5894
5895void
5896move_it_vertically_backward (it, dy)
5897 struct it *it;
5898 int dy;
5899{
79ddf6f7
GM
5900 int nlines, h;
5901 struct it it2, it3;
5f5c8ee5 5902 int start_pos = IT_CHARPOS (*it);
2311178e 5903
5f5c8ee5
GM
5904 xassert (dy >= 0);
5905
5906 /* Estimate how many newlines we must move back. */
da8b7f4f 5907 nlines = max (1, dy / FRAME_LINE_HEIGHT (it->f));
5f5c8ee5
GM
5908
5909 /* Set the iterator's position that many lines back. */
5910 while (nlines-- && IT_CHARPOS (*it) > BEGV)
5911 back_to_previous_visible_line_start (it);
5912
5913 /* Reseat the iterator here. When moving backward, we don't want
5914 reseat to skip forward over invisible text, set up the iterator
5915 to deliver from overlay strings at the new position etc. So,
5916 use reseat_1 here. */
5917 reseat_1 (it, it->current.pos, 1);
5918
5919 /* We are now surely at a line start. */
5920 it->current_x = it->hpos = 0;
0e47bbf7 5921 it->continuation_lines_width = 0;
5f5c8ee5
GM
5922
5923 /* Move forward and see what y-distance we moved. First move to the
5924 start of the next line so that we get its height. We need this
5925 height to be able to tell whether we reached the specified
5926 y-distance. */
5927 it2 = *it;
5928 it2.max_ascent = it2.max_descent = 0;
5929 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
5930 MOVE_TO_POS | MOVE_TO_VPOS);
5931 xassert (IT_CHARPOS (*it) >= BEGV);
79ddf6f7 5932 it3 = it2;
2311178e 5933
5f5c8ee5
GM
5934 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
5935 xassert (IT_CHARPOS (*it) >= BEGV);
ccbb9ed2
RS
5936 /* H is the actual vertical distance from the position in *IT
5937 and the starting position. */
5f5c8ee5 5938 h = it2.current_y - it->current_y;
ccbb9ed2 5939 /* NLINES is the distance in number of lines. */
5f5c8ee5
GM
5940 nlines = it2.vpos - it->vpos;
5941
ccbb9ed2
RS
5942 /* Correct IT's y and vpos position
5943 so that they are relative to the starting point. */
5f5c8ee5
GM
5944 it->vpos -= nlines;
5945 it->current_y -= h;
2311178e 5946
5f5c8ee5
GM
5947 if (dy == 0)
5948 {
5949 /* DY == 0 means move to the start of the screen line. The
5950 value of nlines is > 0 if continuation lines were involved. */
5951 if (nlines > 0)
5952 move_it_by_lines (it, nlines, 1);
5953 xassert (IT_CHARPOS (*it) <= start_pos);
5954 }
ccbb9ed2 5955 else
5f5c8ee5 5956 {
ccbb9ed2
RS
5957 /* The y-position we try to reach, relative to *IT.
5958 Note that H has been subtracted in front of the if-statement. */
5f5c8ee5 5959 int target_y = it->current_y + h - dy;
79ddf6f7
GM
5960 int y0 = it3.current_y;
5961 int y1 = line_bottom_y (&it3);
5962 int line_height = y1 - y0;
f7ccfc8c 5963
5f5c8ee5
GM
5964 /* If we did not reach target_y, try to move further backward if
5965 we can. If we moved too far backward, try to move forward. */
5966 if (target_y < it->current_y
79ddf6f7
GM
5967 /* This is heuristic. In a window that's 3 lines high, with
5968 a line height of 13 pixels each, recentering with point
5969 on the bottom line will try to move -39/2 = 19 pixels
5970 backward. Try to avoid moving into the first line. */
798dbe1f 5971 && it->current_y - target_y > line_height / 3 * 2
5f5c8ee5
GM
5972 && IT_CHARPOS (*it) > BEGV)
5973 {
f7ccfc8c
GM
5974 TRACE_MOVE ((stderr, " not far enough -> move_vert %d\n",
5975 target_y - it->current_y));
5f5c8ee5
GM
5976 move_it_vertically (it, target_y - it->current_y);
5977 xassert (IT_CHARPOS (*it) >= BEGV);
5978 }
5979 else if (target_y >= it->current_y + line_height
5980 && IT_CHARPOS (*it) < ZV)
5981 {
55591976 5982 /* Should move forward by at least one line, maybe more.
2311178e 5983
55591976
GM
5984 Note: Calling move_it_by_lines can be expensive on
5985 terminal frames, where compute_motion is used (via
5986 vmotion) to do the job, when there are very long lines
5987 and truncate-lines is nil. That's the reason for
5988 treating terminal frames specially here. */
2311178e 5989
55591976
GM
5990 if (!FRAME_WINDOW_P (it->f))
5991 move_it_vertically (it, target_y - (it->current_y + line_height));
5992 else
f7ccfc8c 5993 {
55591976
GM
5994 do
5995 {
5996 move_it_by_lines (it, 1, 1);
5997 }
5998 while (target_y >= line_bottom_y (it) && IT_CHARPOS (*it) < ZV);
f7ccfc8c 5999 }
f7ccfc8c 6000
5f5c8ee5
GM
6001 xassert (IT_CHARPOS (*it) >= BEGV);
6002 }
6003 }
6004}
6005
6006
6007/* Move IT by a specified amount of pixel lines DY. DY negative means
6008 move backwards. DY = 0 means move to start of screen line. At the
6009 end, IT will be on the start of a screen line. */
6010
2311178e 6011void
5f5c8ee5
GM
6012move_it_vertically (it, dy)
6013 struct it *it;
6014 int dy;
6015{
6016 if (dy <= 0)
6017 move_it_vertically_backward (it, -dy);
6018 else if (dy > 0)
6019 {
47589c8c 6020 TRACE_MOVE ((stderr, "move_it_v: from %d, %d\n", IT_CHARPOS (*it), dy));
5f5c8ee5
GM
6021 move_it_to (it, ZV, -1, it->current_y + dy, -1,
6022 MOVE_TO_POS | MOVE_TO_Y);
47589c8c 6023 TRACE_MOVE ((stderr, "move_it_v: to %d\n", IT_CHARPOS (*it)));
5f5c8ee5
GM
6024
6025 /* If buffer ends in ZV without a newline, move to the start of
6026 the line to satisfy the post-condition. */
6027 if (IT_CHARPOS (*it) == ZV
6028 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
6029 move_it_by_lines (it, 0, 0);
6030 }
6031}
6032
6033
47fc2c10
GM
6034/* Move iterator IT past the end of the text line it is in. */
6035
6036void
6037move_it_past_eol (it)
6038 struct it *it;
6039{
6040 enum move_it_result rc;
2311178e 6041
47fc2c10
GM
6042 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
6043 if (rc == MOVE_NEWLINE_OR_CR)
6044 set_iterator_to_next (it, 0);
6045}
6046
6047
2c79b732
GM
6048#if 0 /* Currently not used. */
6049
5f5c8ee5
GM
6050/* Return non-zero if some text between buffer positions START_CHARPOS
6051 and END_CHARPOS is invisible. IT->window is the window for text
6052 property lookup. */
6053
6054static int
6055invisible_text_between_p (it, start_charpos, end_charpos)
6056 struct it *it;
6057 int start_charpos, end_charpos;
6058{
5f5c8ee5
GM
6059 Lisp_Object prop, limit;
6060 int invisible_found_p;
2311178e 6061
5f5c8ee5
GM
6062 xassert (it != NULL && start_charpos <= end_charpos);
6063
6064 /* Is text at START invisible? */
6065 prop = Fget_char_property (make_number (start_charpos), Qinvisible,
6066 it->window);
6067 if (TEXT_PROP_MEANS_INVISIBLE (prop))
6068 invisible_found_p = 1;
6069 else
6070 {
016b5642
MB
6071 limit = Fnext_single_char_property_change (make_number (start_charpos),
6072 Qinvisible, Qnil,
6073 make_number (end_charpos));
5f5c8ee5
GM
6074 invisible_found_p = XFASTINT (limit) < end_charpos;
6075 }
6076
6077 return invisible_found_p;
5f5c8ee5
GM
6078}
6079
2c79b732
GM
6080#endif /* 0 */
6081
5f5c8ee5
GM
6082
6083/* Move IT by a specified number DVPOS of screen lines down. DVPOS
6084 negative means move up. DVPOS == 0 means move to the start of the
6085 screen line. NEED_Y_P non-zero means calculate IT->current_y. If
6086 NEED_Y_P is zero, IT->current_y will be left unchanged.
6087
6088 Further optimization ideas: If we would know that IT->f doesn't use
6089 a face with proportional font, we could be faster for
6090 truncate-lines nil. */
6091
6092void
6093move_it_by_lines (it, dvpos, need_y_p)
6094 struct it *it;
6095 int dvpos, need_y_p;
6096{
6097 struct position pos;
2311178e 6098
5f5c8ee5
GM
6099 if (!FRAME_WINDOW_P (it->f))
6100 {
6101 struct text_pos textpos;
2311178e 6102
5f5c8ee5
GM
6103 /* We can use vmotion on frames without proportional fonts. */
6104 pos = *vmotion (IT_CHARPOS (*it), dvpos, it->w);
6105 SET_TEXT_POS (textpos, pos.bufpos, pos.bytepos);
6106 reseat (it, textpos, 1);
6107 it->vpos += pos.vpos;
6108 it->current_y += pos.vpos;
6109 }
6110 else if (dvpos == 0)
6111 {
6112 /* DVPOS == 0 means move to the start of the screen line. */
6113 move_it_vertically_backward (it, 0);
6114 xassert (it->current_x == 0 && it->hpos == 0);
6115 }
6116 else if (dvpos > 0)
2c79b732 6117 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
5f5c8ee5
GM
6118 else
6119 {
6120 struct it it2;
6121 int start_charpos, i;
2311178e 6122
e8660d73
GM
6123 /* Start at the beginning of the screen line containing IT's
6124 position. */
6125 move_it_vertically_backward (it, 0);
2311178e 6126
5f5c8ee5
GM
6127 /* Go back -DVPOS visible lines and reseat the iterator there. */
6128 start_charpos = IT_CHARPOS (*it);
6129 for (i = -dvpos; i && IT_CHARPOS (*it) > BEGV; --i)
6130 back_to_previous_visible_line_start (it);
6131 reseat (it, it->current.pos, 1);
6132 it->current_x = it->hpos = 0;
6133
6134 /* Above call may have moved too far if continuation lines
6135 are involved. Scan forward and see if it did. */
6136 it2 = *it;
6137 it2.vpos = it2.current_y = 0;
6138 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
6139 it->vpos -= it2.vpos;
6140 it->current_y -= it2.current_y;
6141 it->current_x = it->hpos = 0;
6142
6143 /* If we moved too far, move IT some lines forward. */
6144 if (it2.vpos > -dvpos)
6145 {
6146 int delta = it2.vpos + dvpos;
6147 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
6148 }
6149 }
6150}
6151
3824b1a6
AS
6152/* Return 1 if IT points into the middle of a display vector. */
6153
6154int
6155in_display_vector_p (it)
6156 struct it *it;
6157{
6158 return (it->method == next_element_from_display_vector
6159 && it->current.dpvec_index > 0
6160 && it->dpvec + it->current.dpvec_index != it->dpend);
6161}
5f5c8ee5
GM
6162
6163\f
6164/***********************************************************************
6165 Messages
6166 ***********************************************************************/
6167
6168
937248bc
GM
6169/* Add a message with format string FORMAT and arguments ARG1 and ARG2
6170 to *Messages*. */
6171
6172void
6173add_to_log (format, arg1, arg2)
6174 char *format;
6175 Lisp_Object arg1, arg2;
6176{
6177 Lisp_Object args[3];
6178 Lisp_Object msg, fmt;
6179 char *buffer;
6180 int len;
6181 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
6182
ae794295
GM
6183 /* Do nothing if called asynchronously. Inserting text into
6184 a buffer may call after-change-functions and alike and
6185 that would means running Lisp asynchronously. */
6186 if (handling_signal)
6187 return;
6188
937248bc
GM
6189 fmt = msg = Qnil;
6190 GCPRO4 (fmt, msg, arg1, arg2);
2311178e 6191
937248bc
GM
6192 args[0] = fmt = build_string (format);
6193 args[1] = arg1;
6194 args[2] = arg2;
6fc556fd 6195 msg = Fformat (3, args);
937248bc 6196
2051c264 6197 len = SBYTES (msg) + 1;
937248bc 6198 buffer = (char *) alloca (len);
2051c264 6199 bcopy (SDATA (msg), buffer, len);
2311178e 6200
796184bc 6201 message_dolog (buffer, len - 1, 1, 0);
937248bc
GM
6202 UNGCPRO;
6203}
6204
6205
5f5c8ee5
GM
6206/* Output a newline in the *Messages* buffer if "needs" one. */
6207
6208void
6209message_log_maybe_newline ()
6210{
6211 if (message_log_need_newline)
6212 message_dolog ("", 0, 1, 0);
6213}
6214
6215
1e313f28 6216/* Add a string M of length NBYTES to the message log, optionally
5f5c8ee5
GM
6217 terminated with a newline when NLFLAG is non-zero. MULTIBYTE, if
6218 nonzero, means interpret the contents of M as multibyte. This
6219 function calls low-level routines in order to bypass text property
6220 hooks, etc. which might not be safe to run. */
6221
6222void
1e313f28 6223message_dolog (m, nbytes, nlflag, multibyte)
50f80c2f 6224 const char *m;
1e313f28 6225 int nbytes, nlflag, multibyte;
5f5c8ee5 6226{
a67e162b
RS
6227 if (!NILP (Vmemory_full))
6228 return;
6229
5f5c8ee5
GM
6230 if (!NILP (Vmessage_log_max))
6231 {
6232 struct buffer *oldbuf;
6233 Lisp_Object oldpoint, oldbegv, oldzv;
6234 int old_windows_or_buffers_changed = windows_or_buffers_changed;
6235 int point_at_end = 0;
6236 int zv_at_end = 0;
6237 Lisp_Object old_deactivate_mark, tem;
6052529b 6238 struct gcpro gcpro1;
5f5c8ee5
GM
6239
6240 old_deactivate_mark = Vdeactivate_mark;
6241 oldbuf = current_buffer;
6a94510a 6242 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name));
5f5c8ee5
GM
6243 current_buffer->undo_list = Qt;
6244
b14bc55e
RS
6245 oldpoint = message_dolog_marker1;
6246 set_marker_restricted (oldpoint, make_number (PT), Qnil);
6247 oldbegv = message_dolog_marker2;
6248 set_marker_restricted (oldbegv, make_number (BEGV), Qnil);
6249 oldzv = message_dolog_marker3;
6250 set_marker_restricted (oldzv, make_number (ZV), Qnil);
6251 GCPRO1 (old_deactivate_mark);
5f5c8ee5
GM
6252
6253 if (PT == Z)
6254 point_at_end = 1;
6255 if (ZV == Z)
6256 zv_at_end = 1;
6257
6258 BEGV = BEG;
6259 BEGV_BYTE = BEG_BYTE;
6260 ZV = Z;
6261 ZV_BYTE = Z_BYTE;
6262 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6263
6264 /* Insert the string--maybe converting multibyte to single byte
6265 or vice versa, so that all the text fits the buffer. */
6266 if (multibyte
6267 && NILP (current_buffer->enable_multibyte_characters))
6268 {
1e313f28 6269 int i, c, char_bytes;
5f5c8ee5 6270 unsigned char work[1];
2311178e 6271
5f5c8ee5
GM
6272 /* Convert a multibyte string to single-byte
6273 for the *Message* buffer. */
6e57ec5e 6274 for (i = 0; i < nbytes; i += char_bytes)
5f5c8ee5 6275 {
1e313f28 6276 c = string_char_and_length (m + i, nbytes - i, &char_bytes);
5f5c8ee5
GM
6277 work[0] = (SINGLE_BYTE_CHAR_P (c)
6278 ? c
6279 : multibyte_char_to_unibyte (c, Qnil));
6280 insert_1_both (work, 1, 1, 1, 0, 0);
6281 }
6282 }
6283 else if (! multibyte
6284 && ! NILP (current_buffer->enable_multibyte_characters))
6285 {
1e313f28 6286 int i, c, char_bytes;
5f5c8ee5 6287 unsigned char *msg = (unsigned char *) m;
260a86a0 6288 unsigned char str[MAX_MULTIBYTE_LENGTH];
5f5c8ee5
GM
6289 /* Convert a single-byte string to multibyte
6290 for the *Message* buffer. */
1e313f28 6291 for (i = 0; i < nbytes; i++)
5f5c8ee5
GM
6292 {
6293 c = unibyte_char_to_multibyte (msg[i]);
1e313f28
GM
6294 char_bytes = CHAR_STRING (c, str);
6295 insert_1_both (str, 1, char_bytes, 1, 0, 0);
5f5c8ee5
GM
6296 }
6297 }
1e313f28
GM
6298 else if (nbytes)
6299 insert_1 (m, nbytes, 1, 0, 0);
5f5c8ee5
GM
6300
6301 if (nlflag)
6302 {
6303 int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
6304 insert_1 ("\n", 1, 1, 0, 0);
6305
6306 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
6307 this_bol = PT;
6308 this_bol_byte = PT_BYTE;
6309
b14bc55e
RS
6310 /* See if this line duplicates the previous one.
6311 If so, combine duplicates. */
5f5c8ee5
GM
6312 if (this_bol > BEG)
6313 {
6314 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
6315 prev_bol = PT;
6316 prev_bol_byte = PT_BYTE;
6317
6318 dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
6319 this_bol, this_bol_byte);
6320 if (dup)
6321 {
6322 del_range_both (prev_bol, prev_bol_byte,
6323 this_bol, this_bol_byte, 0);
6324 if (dup > 1)
6325 {
6326 char dupstr[40];
6327 int duplen;
6328
6329 /* If you change this format, don't forget to also
6330 change message_log_check_duplicate. */
6331 sprintf (dupstr, " [%d times]", dup);
6332 duplen = strlen (dupstr);
6333 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
6334 insert_1 (dupstr, duplen, 1, 0, 1);
6335 }
6336 }
6337 }
6338
b14bc55e
RS
6339 /* If we have more than the desired maximum number of lines
6340 in the *Messages* buffer now, delete the oldest ones.
6341 This is safe because we don't have undo in this buffer. */
6342
5f5c8ee5
GM
6343 if (NATNUMP (Vmessage_log_max))
6344 {
6345 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
6346 -XFASTINT (Vmessage_log_max) - 1, 0);
6347 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
6348 }
6349 }
6350 BEGV = XMARKER (oldbegv)->charpos;
6351 BEGV_BYTE = marker_byte_position (oldbegv);
6352
6353 if (zv_at_end)
6354 {
6355 ZV = Z;
6356 ZV_BYTE = Z_BYTE;
6357 }
6358 else
6359 {
6360 ZV = XMARKER (oldzv)->charpos;
6361 ZV_BYTE = marker_byte_position (oldzv);
6362 }
6363
6364 if (point_at_end)
6365 TEMP_SET_PT_BOTH (Z, Z_BYTE);
6366 else
6367 /* We can't do Fgoto_char (oldpoint) because it will run some
6368 Lisp code. */
6369 TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
6370 XMARKER (oldpoint)->bytepos);
6371
6372 UNGCPRO;
cfea0546
SM
6373 unchain_marker (XMARKER (oldpoint));
6374 unchain_marker (XMARKER (oldbegv));
6375 unchain_marker (XMARKER (oldzv));
5f5c8ee5
GM
6376
6377 tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
6378 set_buffer_internal (oldbuf);
6379 if (NILP (tem))
6380 windows_or_buffers_changed = old_windows_or_buffers_changed;
6381 message_log_need_newline = !nlflag;
6382 Vdeactivate_mark = old_deactivate_mark;
6383 }
6384}
6385
6386
6387/* We are at the end of the buffer after just having inserted a newline.
6388 (Note: We depend on the fact we won't be crossing the gap.)
6389 Check to see if the most recent message looks a lot like the previous one.
6390 Return 0 if different, 1 if the new one should just replace it, or a
6391 value N > 1 if we should also append " [N times]". */
6392
6393static int
6394message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
6395 int prev_bol, this_bol;
6396 int prev_bol_byte, this_bol_byte;
6397{
6398 int i;
6399 int len = Z_BYTE - 1 - this_bol_byte;
6400 int seen_dots = 0;
6401 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
6402 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
6403
6404 for (i = 0; i < len; i++)
6405 {
509633e3 6406 if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.')
5f5c8ee5
GM
6407 seen_dots = 1;
6408 if (p1[i] != p2[i])
6409 return seen_dots;
6410 }
6411 p1 += len;
6412 if (*p1 == '\n')
6413 return 2;
6414 if (*p1++ == ' ' && *p1++ == '[')
6415 {
6416 int n = 0;
6417 while (*p1 >= '0' && *p1 <= '9')
6418 n = n * 10 + *p1++ - '0';
6419 if (strncmp (p1, " times]\n", 8) == 0)
6420 return n+1;
6421 }
6422 return 0;
6423}
6424
6425
1e313f28
GM
6426/* Display an echo area message M with a specified length of NBYTES
6427 bytes. The string may include null characters. If M is 0, clear
6428 out any existing message, and let the mini-buffer text show
6429 through.
5f5c8ee5
GM
6430
6431 The buffer M must continue to exist until after the echo area gets
6432 cleared or some other message gets displayed there. This means do
6433 not pass text that is stored in a Lisp string; do not pass text in
6434 a buffer that was alloca'd. */
6435
6436void
1e313f28 6437message2 (m, nbytes, multibyte)
50f80c2f 6438 const char *m;
1e313f28 6439 int nbytes;
5f5c8ee5
GM
6440 int multibyte;
6441{
6442 /* First flush out any partial line written with print. */
6443 message_log_maybe_newline ();
6444 if (m)
1e313f28
GM
6445 message_dolog (m, nbytes, 1, multibyte);
6446 message2_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6447}
6448
6449
6450/* The non-logging counterpart of message2. */
6451
6452void
1e313f28 6453message2_nolog (m, nbytes, multibyte)
50f80c2f 6454 const char *m;
e3383b6f 6455 int nbytes, multibyte;
5f5c8ee5 6456{
886bd6f2 6457 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6458 message_enable_multibyte = multibyte;
6459
6460 if (noninteractive)
6461 {
6462 if (noninteractive_need_newline)
6463 putc ('\n', stderr);
6464 noninteractive_need_newline = 0;
6465 if (m)
1e313f28 6466 fwrite (m, nbytes, 1, stderr);
5f5c8ee5
GM
6467 if (cursor_in_echo_area == 0)
6468 fprintf (stderr, "\n");
6469 fflush (stderr);
6470 }
6471 /* A null message buffer means that the frame hasn't really been
6472 initialized yet. Error messages get reported properly by
6473 cmd_error, so this must be just an informative message; toss it. */
2311178e 6474 else if (INTERACTIVE
886bd6f2
GM
6475 && sf->glyphs_initialized_p
6476 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6477 {
6478 Lisp_Object mini_window;
6479 struct frame *f;
6480
6481 /* Get the frame containing the mini-buffer
6482 that the selected frame is using. */
886bd6f2 6483 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6484 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6485
6486 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6487 if (FRAME_VISIBLE_P (sf)
5f5c8ee5
GM
6488 && ! FRAME_VISIBLE_P (f))
6489 Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
6490
6491 if (m)
6492 {
1e313f28 6493 set_message (m, Qnil, nbytes, multibyte);
5f5c8ee5
GM
6494 if (minibuffer_auto_raise)
6495 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
6496 }
6497 else
c6e89d6c 6498 clear_message (1, 1);
5f5c8ee5 6499
c6e89d6c 6500 do_pending_window_change (0);
5f5c8ee5 6501 echo_area_display (1);
c6e89d6c 6502 do_pending_window_change (0);
5f5c8ee5
GM
6503 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6504 (*frame_up_to_date_hook) (f);
6505 }
6506}
6507
6508
c6e89d6c
GM
6509/* Display an echo area message M with a specified length of NBYTES
6510 bytes. The string may include null characters. If M is not a
5f5c8ee5
GM
6511 string, clear out any existing message, and let the mini-buffer
6512 text show through. */
6513
6514void
c6e89d6c 6515message3 (m, nbytes, multibyte)
5f5c8ee5 6516 Lisp_Object m;
c6e89d6c 6517 int nbytes;
5f5c8ee5
GM
6518 int multibyte;
6519{
6520 struct gcpro gcpro1;
6521
6522 GCPRO1 (m);
2311178e 6523
5f5c8ee5
GM
6524 /* First flush out any partial line written with print. */
6525 message_log_maybe_newline ();
6526 if (STRINGP (m))
2051c264 6527 message_dolog (SDATA (m), nbytes, 1, multibyte);
c6e89d6c 6528 message3_nolog (m, nbytes, multibyte);
5f5c8ee5
GM
6529
6530 UNGCPRO;
6531}
6532
6533
6534/* The non-logging version of message3. */
6535
6536void
c6e89d6c 6537message3_nolog (m, nbytes, multibyte)
5f5c8ee5 6538 Lisp_Object m;
c6e89d6c 6539 int nbytes, multibyte;
5f5c8ee5 6540{
886bd6f2 6541 struct frame *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6542 message_enable_multibyte = multibyte;
6543
6544 if (noninteractive)
6545 {
6546 if (noninteractive_need_newline)
6547 putc ('\n', stderr);
6548 noninteractive_need_newline = 0;
6549 if (STRINGP (m))
2051c264 6550 fwrite (SDATA (m), nbytes, 1, stderr);
5f5c8ee5
GM
6551 if (cursor_in_echo_area == 0)
6552 fprintf (stderr, "\n");
6553 fflush (stderr);
6554 }
6555 /* A null message buffer means that the frame hasn't really been
6556 initialized yet. Error messages get reported properly by
6557 cmd_error, so this must be just an informative message; toss it. */
2311178e 6558 else if (INTERACTIVE
886bd6f2
GM
6559 && sf->glyphs_initialized_p
6560 && FRAME_MESSAGE_BUF (sf))
5f5c8ee5
GM
6561 {
6562 Lisp_Object mini_window;
c6e89d6c 6563 Lisp_Object frame;
5f5c8ee5
GM
6564 struct frame *f;
6565
6566 /* Get the frame containing the mini-buffer
6567 that the selected frame is using. */
886bd6f2 6568 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
6569 frame = XWINDOW (mini_window)->frame;
6570 f = XFRAME (frame);
5f5c8ee5
GM
6571
6572 FRAME_SAMPLE_VISIBILITY (f);
886bd6f2 6573 if (FRAME_VISIBLE_P (sf)
c6e89d6c
GM
6574 && !FRAME_VISIBLE_P (f))
6575 Fmake_frame_visible (frame);
5f5c8ee5 6576
2051c264 6577 if (STRINGP (m) && SCHARS (m) > 0)
5f5c8ee5 6578 {
c6e89d6c 6579 set_message (NULL, m, nbytes, multibyte);
468155d7
GM
6580 if (minibuffer_auto_raise)
6581 Fraise_frame (frame);
5f5c8ee5
GM
6582 }
6583 else
c6e89d6c 6584 clear_message (1, 1);
5f5c8ee5 6585
c6e89d6c 6586 do_pending_window_change (0);
5f5c8ee5 6587 echo_area_display (1);
c6e89d6c 6588 do_pending_window_change (0);
5f5c8ee5
GM
6589 if (frame_up_to_date_hook != 0 && ! gc_in_progress)
6590 (*frame_up_to_date_hook) (f);
6591 }
6592}
6593
6594
6595/* Display a null-terminated echo area message M. If M is 0, clear
6596 out any existing message, and let the mini-buffer text show through.
6597
6598 The buffer M must continue to exist until after the echo area gets
6599 cleared or some other message gets displayed there. Do not pass
6600 text that is stored in a Lisp string. Do not pass text in a buffer
6601 that was alloca'd. */
6602
6603void
6604message1 (m)
6605 char *m;
6606{
6607 message2 (m, (m ? strlen (m) : 0), 0);
6608}
6609
6610
6611/* The non-logging counterpart of message1. */
6612
6613void
6614message1_nolog (m)
6615 char *m;
6616{
6617 message2_nolog (m, (m ? strlen (m) : 0), 0);
6618}
6619
6620/* Display a message M which contains a single %s
6621 which gets replaced with STRING. */
6622
6623void
6624message_with_string (m, string, log)
6625 char *m;
6626 Lisp_Object string;
6627 int log;
6628{
5b6d51b6
RS
6629 CHECK_STRING (string);
6630
5f5c8ee5
GM
6631 if (noninteractive)
6632 {
6633 if (m)
6634 {
6635 if (noninteractive_need_newline)
6636 putc ('\n', stderr);
6637 noninteractive_need_newline = 0;
2051c264 6638 fprintf (stderr, m, SDATA (string));
5f5c8ee5
GM
6639 if (cursor_in_echo_area == 0)
6640 fprintf (stderr, "\n");
6641 fflush (stderr);
6642 }
6643 }
6644 else if (INTERACTIVE)
6645 {
6646 /* The frame whose minibuffer we're going to display the message on.
6647 It may be larger than the selected frame, so we need
6648 to use its buffer, not the selected frame's buffer. */
6649 Lisp_Object mini_window;
886bd6f2 6650 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6651
6652 /* Get the frame containing the minibuffer
6653 that the selected frame is using. */
886bd6f2 6654 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6655 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6656
6657 /* A null message buffer means that the frame hasn't really been
6658 initialized yet. Error messages get reported properly by
6659 cmd_error, so this must be just an informative message; toss it. */
6660 if (FRAME_MESSAGE_BUF (f))
6661 {
eb484132
GM
6662 Lisp_Object args[2], message;
6663 struct gcpro gcpro1, gcpro2;
5f5c8ee5 6664
eb484132
GM
6665 args[0] = build_string (m);
6666 args[1] = message = string;
78e17433 6667 GCPRO2 (args[0], message);
eb484132 6668 gcpro1.nvars = 2;
2311178e 6669
eb484132 6670 message = Fformat (2, args);
5f5c8ee5
GM
6671
6672 if (log)
d5db4077 6673 message3 (message, SBYTES (message), STRING_MULTIBYTE (message));
5f5c8ee5 6674 else
d5db4077 6675 message3_nolog (message, SBYTES (message), STRING_MULTIBYTE (message));
eb484132
GM
6676
6677 UNGCPRO;
5f5c8ee5
GM
6678
6679 /* Print should start at the beginning of the message
6680 buffer next time. */
6681 message_buf_print = 0;
6682 }
6683 }
6684}
6685
6686
5f5c8ee5
GM
6687/* Dump an informative message to the minibuf. If M is 0, clear out
6688 any existing message, and let the mini-buffer text show through. */
6689
6690/* VARARGS 1 */
6691void
6692message (m, a1, a2, a3)
6693 char *m;
6694 EMACS_INT a1, a2, a3;
6695{
6696 if (noninteractive)
6697 {
6698 if (m)
6699 {
6700 if (noninteractive_need_newline)
6701 putc ('\n', stderr);
6702 noninteractive_need_newline = 0;
6703 fprintf (stderr, m, a1, a2, a3);
6704 if (cursor_in_echo_area == 0)
6705 fprintf (stderr, "\n");
6706 fflush (stderr);
6707 }
6708 }
6709 else if (INTERACTIVE)
6710 {
6711 /* The frame whose mini-buffer we're going to display the message
6712 on. It may be larger than the selected frame, so we need to
6713 use its buffer, not the selected frame's buffer. */
6714 Lisp_Object mini_window;
886bd6f2 6715 struct frame *f, *sf = SELECTED_FRAME ();
5f5c8ee5
GM
6716
6717 /* Get the frame containing the mini-buffer
6718 that the selected frame is using. */
886bd6f2 6719 mini_window = FRAME_MINIBUF_WINDOW (sf);
5f5c8ee5
GM
6720 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
6721
6722 /* A null message buffer means that the frame hasn't really been
6723 initialized yet. Error messages get reported properly by
6724 cmd_error, so this must be just an informative message; toss
6725 it. */
6726 if (FRAME_MESSAGE_BUF (f))
6727 {
6728 if (m)
6729 {
6730 int len;
6731#ifdef NO_ARG_ARRAY
6732 char *a[3];
6733 a[0] = (char *) a1;
6734 a[1] = (char *) a2;
6735 a[2] = (char *) a3;
6736
6737 len = doprnt (FRAME_MESSAGE_BUF (f),
6738 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
6739#else
6740 len = doprnt (FRAME_MESSAGE_BUF (f),
6741 FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
6742 (char **) &a1);
6743#endif /* NO_ARG_ARRAY */
6744
6745 message2 (FRAME_MESSAGE_BUF (f), len, 0);
6746 }
6747 else
6748 message1 (0);
6749
6750 /* Print should start at the beginning of the message
6751 buffer next time. */
6752 message_buf_print = 0;
6753 }
6754 }
6755}
6756
6757
6758/* The non-logging version of message. */
6759
6760void
6761message_nolog (m, a1, a2, a3)
6762 char *m;
6763 EMACS_INT a1, a2, a3;
6764{
6765 Lisp_Object old_log_max;
6766 old_log_max = Vmessage_log_max;
6767 Vmessage_log_max = Qnil;
6768 message (m, a1, a2, a3);
6769 Vmessage_log_max = old_log_max;
6770}
6771
6772
c6e89d6c
GM
6773/* Display the current message in the current mini-buffer. This is
6774 only called from error handlers in process.c, and is not time
6775 critical. */
5f5c8ee5
GM
6776
6777void
6778update_echo_area ()
6779{
c6e89d6c
GM
6780 if (!NILP (echo_area_buffer[0]))
6781 {
6782 Lisp_Object string;
6783 string = Fcurrent_message ();
2311178e 6784 message3 (string, SBYTES (string),
c6e89d6c
GM
6785 !NILP (current_buffer->enable_multibyte_characters));
6786 }
6787}
6788
6789
a67e162b
RS
6790/* Make sure echo area buffers in `echo_buffers' are live.
6791 If they aren't, make new ones. */
5bcfeb49
GM
6792
6793static void
6794ensure_echo_area_buffers ()
6795{
6796 int i;
6797
6798 for (i = 0; i < 2; ++i)
6799 if (!BUFFERP (echo_buffer[i])
6800 || NILP (XBUFFER (echo_buffer[i])->name))
6801 {
6802 char name[30];
ff3d9573
GM
6803 Lisp_Object old_buffer;
6804 int j;
6805
6806 old_buffer = echo_buffer[i];
5bcfeb49
GM
6807 sprintf (name, " *Echo Area %d*", i);
6808 echo_buffer[i] = Fget_buffer_create (build_string (name));
ad4f174e 6809 XBUFFER (echo_buffer[i])->truncate_lines = Qnil;
ff3d9573
GM
6810
6811 for (j = 0; j < 2; ++j)
6812 if (EQ (old_buffer, echo_area_buffer[j]))
6813 echo_area_buffer[j] = echo_buffer[i];
5bcfeb49
GM
6814 }
6815}
6816
6817
23a96c77 6818/* Call FN with args A1..A4 with either the current or last displayed
c6e89d6c
GM
6819 echo_area_buffer as current buffer.
6820
6821 WHICH zero means use the current message buffer
6822 echo_area_buffer[0]. If that is nil, choose a suitable buffer
6823 from echo_buffer[] and clear it.
6824
6825 WHICH > 0 means use echo_area_buffer[1]. If that is nil, choose a
6826 suitable buffer from echo_buffer[] and clear it.
6827
6828 If WHICH < 0, set echo_area_buffer[1] to echo_area_buffer[0], so
6829 that the current message becomes the last displayed one, make
6830 choose a suitable buffer for echo_area_buffer[0], and clear it.
6831
4b41cebb 6832 Value is what FN returns. */
c6e89d6c
GM
6833
6834static int
23a96c77 6835with_echo_area_buffer (w, which, fn, a1, a2, a3, a4)
c6e89d6c
GM
6836 struct window *w;
6837 int which;
23dd2d97
KR
6838 int (*fn) P_ ((EMACS_INT, Lisp_Object, EMACS_INT, EMACS_INT));
6839 EMACS_INT a1;
6840 Lisp_Object a2;
6841 EMACS_INT a3, a4;
c6e89d6c
GM
6842{
6843 Lisp_Object buffer;
15e26c76 6844 int this_one, the_other, clear_buffer_p, rc;
331379bf 6845 int count = SPECPDL_INDEX ();
c6e89d6c 6846
9583b2bb 6847 /* If buffers aren't live, make new ones. */
5bcfeb49 6848 ensure_echo_area_buffers ();
c6e89d6c
GM
6849
6850 clear_buffer_p = 0;
2311178e 6851
c6e89d6c
GM
6852 if (which == 0)
6853 this_one = 0, the_other = 1;
6854 else if (which > 0)
6855 this_one = 1, the_other = 0;
5f5c8ee5 6856 else
c6e89d6c
GM
6857 {
6858 this_one = 0, the_other = 1;
6859 clear_buffer_p = 1;
2311178e 6860
c6e89d6c
GM
6861 /* We need a fresh one in case the current echo buffer equals
6862 the one containing the last displayed echo area message. */
6863 if (!NILP (echo_area_buffer[this_one])
6864 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
6865 echo_area_buffer[this_one] = Qnil;
c6e89d6c
GM
6866 }
6867
6868 /* Choose a suitable buffer from echo_buffer[] is we don't
6869 have one. */
6870 if (NILP (echo_area_buffer[this_one]))
6871 {
6872 echo_area_buffer[this_one]
6873 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
6874 ? echo_buffer[the_other]
6875 : echo_buffer[this_one]);
6876 clear_buffer_p = 1;
6877 }
6878
6879 buffer = echo_area_buffer[this_one];
6880
1013f4e3
GM
6881 /* Don't get confused by reusing the buffer used for echoing
6882 for a different purpose. */
032906b1 6883 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
1013f4e3
GM
6884 cancel_echoing ();
6885
c6e89d6c
GM
6886 record_unwind_protect (unwind_with_echo_area_buffer,
6887 with_echo_area_buffer_unwind_data (w));
6888
6889 /* Make the echo area buffer current. Note that for display
6890 purposes, it is not necessary that the displayed window's buffer
6891 == current_buffer, except for text property lookup. So, let's
6892 only set that buffer temporarily here without doing a full
6893 Fset_window_buffer. We must also change w->pointm, though,
6894 because otherwise an assertions in unshow_buffer fails, and Emacs
6895 aborts. */
9142dd5b 6896 set_buffer_internal_1 (XBUFFER (buffer));
c6e89d6c
GM
6897 if (w)
6898 {
6899 w->buffer = buffer;
6900 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
6901 }
ad4f174e 6902
c6e89d6c
GM
6903 current_buffer->undo_list = Qt;
6904 current_buffer->read_only = Qnil;
bbbf6d06 6905 specbind (Qinhibit_read_only, Qt);
0b04fa5f 6906 specbind (Qinhibit_modification_hooks, Qt);
c6e89d6c
GM
6907
6908 if (clear_buffer_p && Z > BEG)
6909 del_range (BEG, Z);
6910
6911 xassert (BEGV >= BEG);
6912 xassert (ZV <= Z && ZV >= BEGV);
6913
23a96c77 6914 rc = fn (a1, a2, a3, a4);
c6e89d6c
GM
6915
6916 xassert (BEGV >= BEG);
6917 xassert (ZV <= Z && ZV >= BEGV);
6918
6919 unbind_to (count, Qnil);
6920 return rc;
5f5c8ee5
GM
6921}
6922
6923
c6e89d6c
GM
6924/* Save state that should be preserved around the call to the function
6925 FN called in with_echo_area_buffer. */
5f5c8ee5 6926
c6e89d6c
GM
6927static Lisp_Object
6928with_echo_area_buffer_unwind_data (w)
6929 struct window *w;
5f5c8ee5 6930{
c6e89d6c
GM
6931 int i = 0;
6932 Lisp_Object vector;
5f5c8ee5 6933
c6e89d6c
GM
6934 /* Reduce consing by keeping one vector in
6935 Vwith_echo_area_save_vector. */
6936 vector = Vwith_echo_area_save_vector;
6937 Vwith_echo_area_save_vector = Qnil;
2311178e 6938
c6e89d6c 6939 if (NILP (vector))
9142dd5b 6940 vector = Fmake_vector (make_number (7), Qnil);
2311178e 6941
a61b7058
GM
6942 XSETBUFFER (AREF (vector, i), current_buffer); ++i;
6943 AREF (vector, i) = Vdeactivate_mark, ++i;
6944 AREF (vector, i) = make_number (windows_or_buffers_changed), ++i;
2311178e 6945
c6e89d6c
GM
6946 if (w)
6947 {
a61b7058
GM
6948 XSETWINDOW (AREF (vector, i), w); ++i;
6949 AREF (vector, i) = w->buffer; ++i;
6950 AREF (vector, i) = make_number (XMARKER (w->pointm)->charpos); ++i;
6951 AREF (vector, i) = make_number (XMARKER (w->pointm)->bytepos); ++i;
c6e89d6c
GM
6952 }
6953 else
6954 {
6955 int end = i + 4;
a61b7058
GM
6956 for (; i < end; ++i)
6957 AREF (vector, i) = Qnil;
c6e89d6c 6958 }
5f5c8ee5 6959
a61b7058 6960 xassert (i == ASIZE (vector));
c6e89d6c
GM
6961 return vector;
6962}
5f5c8ee5 6963
5f5c8ee5 6964
c6e89d6c
GM
6965/* Restore global state from VECTOR which was created by
6966 with_echo_area_buffer_unwind_data. */
6967
6968static Lisp_Object
6969unwind_with_echo_area_buffer (vector)
6970 Lisp_Object vector;
6971{
bbbf6d06
GM
6972 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
6973 Vdeactivate_mark = AREF (vector, 1);
6974 windows_or_buffers_changed = XFASTINT (AREF (vector, 2));
c6e89d6c 6975
bbbf6d06 6976 if (WINDOWP (AREF (vector, 3)))
c6e89d6c
GM
6977 {
6978 struct window *w;
6979 Lisp_Object buffer, charpos, bytepos;
2311178e 6980
bbbf6d06
GM
6981 w = XWINDOW (AREF (vector, 3));
6982 buffer = AREF (vector, 4);
6983 charpos = AREF (vector, 5);
6984 bytepos = AREF (vector, 6);
2311178e 6985
c6e89d6c
GM
6986 w->buffer = buffer;
6987 set_marker_both (w->pointm, buffer,
6988 XFASTINT (charpos), XFASTINT (bytepos));
6989 }
6990
6991 Vwith_echo_area_save_vector = vector;
6992 return Qnil;
6993}
6994
6995
6996/* Set up the echo area for use by print functions. MULTIBYTE_P
6997 non-zero means we will print multibyte. */
6998
6999void
7000setup_echo_area_for_printing (multibyte_p)
7001 int multibyte_p;
7002{
03b0a4b4
RS
7003 /* If we can't find an echo area any more, exit. */
7004 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
7005 Fkill_emacs (Qnil);
7006
5bcfeb49
GM
7007 ensure_echo_area_buffers ();
7008
c6e89d6c
GM
7009 if (!message_buf_print)
7010 {
7011 /* A message has been output since the last time we printed.
7012 Choose a fresh echo area buffer. */
7013 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 7014 echo_area_buffer[0] = echo_buffer[1];
c6e89d6c
GM
7015 else
7016 echo_area_buffer[0] = echo_buffer[0];
7017
7018 /* Switch to that buffer and clear it. */
7019 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
ab2c5f0a 7020 current_buffer->truncate_lines = Qnil;
2311178e 7021
c6e89d6c 7022 if (Z > BEG)
bbbf6d06 7023 {
331379bf 7024 int count = SPECPDL_INDEX ();
bbbf6d06 7025 specbind (Qinhibit_read_only, Qt);
a67e162b 7026 /* Note that undo recording is always disabled. */
bbbf6d06
GM
7027 del_range (BEG, Z);
7028 unbind_to (count, Qnil);
7029 }
c6e89d6c
GM
7030 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
7031
7032 /* Set up the buffer for the multibyteness we need. */
7033 if (multibyte_p
7034 != !NILP (current_buffer->enable_multibyte_characters))
7035 Fset_buffer_multibyte (multibyte_p ? Qt : Qnil);
7036
7037 /* Raise the frame containing the echo area. */
7038 if (minibuffer_auto_raise)
7039 {
886bd6f2 7040 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7041 Lisp_Object mini_window;
886bd6f2 7042 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7043 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
7044 }
7045
8a4e3c0c 7046 message_log_maybe_newline ();
c6e89d6c
GM
7047 message_buf_print = 1;
7048 }
fa77249f
GM
7049 else
7050 {
7051 if (NILP (echo_area_buffer[0]))
7052 {
7053 if (EQ (echo_area_buffer[1], echo_buffer[0]))
2311178e 7054 echo_area_buffer[0] = echo_buffer[1];
fa77249f
GM
7055 else
7056 echo_area_buffer[0] = echo_buffer[0];
7057 }
2311178e 7058
fa77249f 7059 if (current_buffer != XBUFFER (echo_area_buffer[0]))
ab2c5f0a
GM
7060 {
7061 /* Someone switched buffers between print requests. */
7062 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
7063 current_buffer->truncate_lines = Qnil;
7064 }
fa77249f 7065 }
c6e89d6c
GM
7066}
7067
7068
dd2eb166
GM
7069/* Display an echo area message in window W. Value is non-zero if W's
7070 height is changed. If display_last_displayed_message_p is
7071 non-zero, display the message that was last displayed, otherwise
7072 display the current message. */
c6e89d6c
GM
7073
7074static int
7075display_echo_area (w)
7076 struct window *w;
7077{
25edb08f
GM
7078 int i, no_message_p, window_height_changed_p, count;
7079
7080 /* Temporarily disable garbage collections while displaying the echo
7081 area. This is done because a GC can print a message itself.
7082 That message would modify the echo area buffer's contents while a
7083 redisplay of the buffer is going on, and seriously confuse
7084 redisplay. */
7085 count = inhibit_garbage_collection ();
dd2eb166
GM
7086
7087 /* If there is no message, we must call display_echo_area_1
7088 nevertheless because it resizes the window. But we will have to
7089 reset the echo_area_buffer in question to nil at the end because
7090 with_echo_area_buffer will sets it to an empty buffer. */
7091 i = display_last_displayed_message_p ? 1 : 0;
7092 no_message_p = NILP (echo_area_buffer[i]);
2311178e 7093
dd2eb166
GM
7094 window_height_changed_p
7095 = with_echo_area_buffer (w, display_last_displayed_message_p,
23a96c77 7096 display_echo_area_1,
23dd2d97 7097 (EMACS_INT) w, Qnil, 0, 0);
dd2eb166
GM
7098
7099 if (no_message_p)
7100 echo_area_buffer[i] = Qnil;
25edb08f
GM
7101
7102 unbind_to (count, Qnil);
dd2eb166 7103 return window_height_changed_p;
c6e89d6c
GM
7104}
7105
7106
7107/* Helper for display_echo_area. Display the current buffer which
23a96c77
GM
7108 contains the current echo area message in window W, a mini-window,
7109 a pointer to which is passed in A1. A2..A4 are currently not used.
c6e89d6c
GM
7110 Change the height of W so that all of the message is displayed.
7111 Value is non-zero if height of W was changed. */
7112
7113static int
23a96c77 7114display_echo_area_1 (a1, a2, a3, a4)
23dd2d97
KR
7115 EMACS_INT a1;
7116 Lisp_Object a2;
7117 EMACS_INT a3, a4;
c6e89d6c 7118{
23a96c77 7119 struct window *w = (struct window *) a1;
c6e89d6c 7120 Lisp_Object window;
c6e89d6c
GM
7121 struct text_pos start;
7122 int window_height_changed_p = 0;
7123
7124 /* Do this before displaying, so that we have a large enough glyph
7125 matrix for the display. */
92a90e89 7126 window_height_changed_p = resize_mini_window (w, 0);
c6e89d6c
GM
7127
7128 /* Display. */
7129 clear_glyph_matrix (w->desired_matrix);
7130 XSETWINDOW (window, w);
7131 SET_TEXT_POS (start, BEG, BEG_BYTE);
7132 try_window (window, start);
7133
c6e89d6c
GM
7134 return window_height_changed_p;
7135}
7136
7137
92a90e89 7138/* Resize the echo area window to exactly the size needed for the
6d004fea
GM
7139 currently displayed message, if there is one. If a mini-buffer
7140 is active, don't shrink it. */
92a90e89
GM
7141
7142void
308a74d8 7143resize_echo_area_exactly ()
92a90e89
GM
7144{
7145 if (BUFFERP (echo_area_buffer[0])
7146 && WINDOWP (echo_area_window))
7147 {
7148 struct window *w = XWINDOW (echo_area_window);
7149 int resized_p;
6d004fea
GM
7150 Lisp_Object resize_exactly;
7151
7152 if (minibuf_level == 0)
7153 resize_exactly = Qt;
7154 else
7155 resize_exactly = Qnil;
2311178e 7156
23a96c77 7157 resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
6d004fea 7158 (EMACS_INT) w, resize_exactly, 0, 0);
92a90e89
GM
7159 if (resized_p)
7160 {
7161 ++windows_or_buffers_changed;
7162 ++update_mode_lines;
7163 redisplay_internal (0);
7164 }
7165 }
7166}
7167
7168
23a96c77 7169/* Callback function for with_echo_area_buffer, when used from
308a74d8 7170 resize_echo_area_exactly. A1 contains a pointer to the window to
6d004fea
GM
7171 resize, EXACTLY non-nil means resize the mini-window exactly to the
7172 size of the text displayed. A3 and A4 are not used. Value is what
7173 resize_mini_window returns. */
23a96c77
GM
7174
7175static int
6d004fea 7176resize_mini_window_1 (a1, exactly, a3, a4)
23dd2d97 7177 EMACS_INT a1;
6d004fea 7178 Lisp_Object exactly;
23dd2d97 7179 EMACS_INT a3, a4;
23a96c77 7180{
6d004fea 7181 return resize_mini_window ((struct window *) a1, !NILP (exactly));
23a96c77
GM
7182}
7183
7184
92a90e89
GM
7185/* Resize mini-window W to fit the size of its contents. EXACT:P
7186 means size the window exactly to the size needed. Otherwise, it's
7187 only enlarged until W's buffer is empty. Value is non-zero if
4b41cebb 7188 the window height has been changed. */
c6e89d6c 7189
9472f927 7190int
92a90e89 7191resize_mini_window (w, exact_p)
c6e89d6c 7192 struct window *w;
92a90e89 7193 int exact_p;
c6e89d6c
GM
7194{
7195 struct frame *f = XFRAME (w->frame);
7196 int window_height_changed_p = 0;
7197
7198 xassert (MINI_WINDOW_P (w));
97cafc0f 7199
2913a9c0
GM
7200 /* Don't resize windows while redisplaying a window; it would
7201 confuse redisplay functions when the size of the window they are
7202 displaying changes from under them. Such a resizing can happen,
7203 for instance, when which-func prints a long message while
7204 we are running fontification-functions. We're running these
7205 functions with safe_call which binds inhibit-redisplay to t. */
7206 if (!NILP (Vinhibit_redisplay))
64c5be50 7207 return 0;
2311178e 7208
97cafc0f 7209 /* Nil means don't try to resize. */
6422c1d7 7210 if (NILP (Vresize_mini_windows)
fa3c6b4d 7211 || (FRAME_X_P (f) && FRAME_X_OUTPUT (f) == NULL))
97cafc0f 7212 return 0;
2311178e 7213
c6e89d6c
GM
7214 if (!FRAME_MINIBUF_ONLY_P (f))
7215 {
7216 struct it it;
dd2eb166 7217 struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
da8b7f4f 7218 int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
dd2eb166 7219 int height, max_height;
da8b7f4f 7220 int unit = FRAME_LINE_HEIGHT (f);
dd2eb166 7221 struct text_pos start;
1bfdbe43
GM
7222 struct buffer *old_current_buffer = NULL;
7223
7224 if (current_buffer != XBUFFER (w->buffer))
7225 {
7226 old_current_buffer = current_buffer;
7227 set_buffer_internal (XBUFFER (w->buffer));
7228 }
9142dd5b 7229
c6e89d6c 7230 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
c6e89d6c 7231
dd2eb166
GM
7232 /* Compute the max. number of lines specified by the user. */
7233 if (FLOATP (Vmax_mini_window_height))
da8b7f4f 7234 max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
dd2eb166
GM
7235 else if (INTEGERP (Vmax_mini_window_height))
7236 max_height = XINT (Vmax_mini_window_height);
97cafc0f
GM
7237 else
7238 max_height = total_height / 4;
2311178e 7239
4b41cebb 7240 /* Correct that max. height if it's bogus. */
dd2eb166
GM
7241 max_height = max (1, max_height);
7242 max_height = min (total_height, max_height);
2311178e 7243
dd2eb166 7244 /* Find out the height of the text in the window. */
ad4f174e
GM
7245 if (it.truncate_lines_p)
7246 height = 1;
55b064bd 7247 else
ad4f174e
GM
7248 {
7249 last_height = 0;
7250 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
7251 if (it.max_ascent == 0 && it.max_descent == 0)
7252 height = it.current_y + last_height;
7253 else
7254 height = it.current_y + it.max_ascent + it.max_descent;
3c4b7685 7255 height -= it.extra_line_spacing;
ad4f174e
GM
7256 height = (height + unit - 1) / unit;
7257 }
2311178e 7258
dd2eb166
GM
7259 /* Compute a suitable window start. */
7260 if (height > max_height)
7261 {
7262 height = max_height;
7263 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
7264 move_it_vertically_backward (&it, (height - 1) * unit);
7265 start = it.current.pos;
7266 }
7267 else
7268 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
7269 SET_MARKER_FROM_TEXT_POS (w->start, start);
c59c668a 7270
6422c1d7 7271 if (EQ (Vresize_mini_windows, Qgrow_only))
dd2eb166 7272 {
6422c1d7
GM
7273 /* Let it grow only, until we display an empty message, in which
7274 case the window shrinks again. */
da8b7f4f 7275 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7276 {
da8b7f4f 7277 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7278 freeze_window_starts (f, 1);
da8b7f4f
KS
7279 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7280 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7281 }
da8b7f4f 7282 else if (height < WINDOW_TOTAL_LINES (w)
6422c1d7
GM
7283 && (exact_p || BEGV == ZV))
7284 {
da8b7f4f 7285 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7286 freeze_window_starts (f, 0);
7287 shrink_mini_window (w);
da8b7f4f 7288 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7289 }
da448723 7290 }
2311178e 7291 else
da448723 7292 {
6422c1d7 7293 /* Always resize to exact size needed. */
da8b7f4f 7294 if (height > WINDOW_TOTAL_LINES (w))
6422c1d7 7295 {
da8b7f4f 7296 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7 7297 freeze_window_starts (f, 1);
da8b7f4f
KS
7298 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
7299 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7300 }
da8b7f4f 7301 else if (height < WINDOW_TOTAL_LINES (w))
6422c1d7 7302 {
da8b7f4f 7303 int old_height = WINDOW_TOTAL_LINES (w);
6422c1d7
GM
7304 freeze_window_starts (f, 0);
7305 shrink_mini_window (w);
7306
7307 if (height)
7308 {
7309 freeze_window_starts (f, 1);
da8b7f4f 7310 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
6422c1d7 7311 }
2311178e 7312
da8b7f4f 7313 window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
6422c1d7 7314 }
9142dd5b 7315 }
1bfdbe43
GM
7316
7317 if (old_current_buffer)
7318 set_buffer_internal (old_current_buffer);
c6e89d6c
GM
7319 }
7320
7321 return window_height_changed_p;
7322}
7323
7324
7325/* Value is the current message, a string, or nil if there is no
7326 current message. */
7327
7328Lisp_Object
7329current_message ()
7330{
7331 Lisp_Object msg;
7332
7333 if (NILP (echo_area_buffer[0]))
7334 msg = Qnil;
7335 else
7336 {
23a96c77 7337 with_echo_area_buffer (0, 0, current_message_1,
23dd2d97 7338 (EMACS_INT) &msg, Qnil, 0, 0);
c6e89d6c
GM
7339 if (NILP (msg))
7340 echo_area_buffer[0] = Qnil;
7341 }
2311178e 7342
c6e89d6c
GM
7343 return msg;
7344}
7345
7346
7347static int
23a96c77 7348current_message_1 (a1, a2, a3, a4)
23dd2d97
KR
7349 EMACS_INT a1;
7350 Lisp_Object a2;
7351 EMACS_INT a3, a4;
c6e89d6c 7352{
23a96c77 7353 Lisp_Object *msg = (Lisp_Object *) a1;
2311178e 7354
c6e89d6c
GM
7355 if (Z > BEG)
7356 *msg = make_buffer_string (BEG, Z, 1);
7357 else
7358 *msg = Qnil;
7359 return 0;
7360}
7361
7362
7363/* Push the current message on Vmessage_stack for later restauration
7364 by restore_message. Value is non-zero if the current message isn't
7365 empty. This is a relatively infrequent operation, so it's not
7366 worth optimizing. */
7367
7368int
7369push_message ()
7370{
7371 Lisp_Object msg;
7372 msg = current_message ();
7373 Vmessage_stack = Fcons (msg, Vmessage_stack);
7374 return STRINGP (msg);
7375}
7376
7377
7378/* Restore message display from the top of Vmessage_stack. */
7379
7380void
7381restore_message ()
7382{
7383 Lisp_Object msg;
2311178e 7384
c6e89d6c
GM
7385 xassert (CONSP (Vmessage_stack));
7386 msg = XCAR (Vmessage_stack);
7387 if (STRINGP (msg))
d5db4077 7388 message3_nolog (msg, SBYTES (msg), STRING_MULTIBYTE (msg));
c6e89d6c
GM
7389 else
7390 message3_nolog (msg, 0, 0);
7391}
7392
7393
37d66095
RS
7394/* Handler for record_unwind_protect calling pop_message. */
7395
7396Lisp_Object
7397pop_message_unwind (dummy)
7398 Lisp_Object dummy;
7399{
7400 pop_message ();
7401 return Qnil;
7402}
7403
c6e89d6c
GM
7404/* Pop the top-most entry off Vmessage_stack. */
7405
7406void
7407pop_message ()
7408{
7409 xassert (CONSP (Vmessage_stack));
7410 Vmessage_stack = XCDR (Vmessage_stack);
7411}
7412
7413
7414/* Check that Vmessage_stack is nil. Called from emacs.c when Emacs
7415 exits. If the stack is not empty, we have a missing pop_message
7416 somewhere. */
7417
7418void
7419check_message_stack ()
7420{
7421 if (!NILP (Vmessage_stack))
7422 abort ();
7423}
7424
7425
7426/* Truncate to NCHARS what will be displayed in the echo area the next
7427 time we display it---but don't redisplay it now. */
7428
7429void
7430truncate_echo_area (nchars)
7431 int nchars;
7432{
7433 if (nchars == 0)
7434 echo_area_buffer[0] = Qnil;
7435 /* A null message buffer means that the frame hasn't really been
7436 initialized yet. Error messages get reported properly by
7437 cmd_error, so this must be just an informative message; toss it. */
7438 else if (!noninteractive
7439 && INTERACTIVE
c6e89d6c 7440 && !NILP (echo_area_buffer[0]))
886bd6f2
GM
7441 {
7442 struct frame *sf = SELECTED_FRAME ();
7443 if (FRAME_MESSAGE_BUF (sf))
23dd2d97 7444 with_echo_area_buffer (0, 0, truncate_message_1, nchars, Qnil, 0, 0);
886bd6f2 7445 }
c6e89d6c
GM
7446}
7447
7448
7449/* Helper function for truncate_echo_area. Truncate the current
7450 message to at most NCHARS characters. */
7451
7452static int
23a96c77 7453truncate_message_1 (nchars, a2, a3, a4)
23dd2d97
KR
7454 EMACS_INT nchars;
7455 Lisp_Object a2;
7456 EMACS_INT a3, a4;
c6e89d6c
GM
7457{
7458 if (BEG + nchars < Z)
7459 del_range (BEG + nchars, Z);
7460 if (Z == BEG)
7461 echo_area_buffer[0] = Qnil;
7462 return 0;
7463}
7464
7465
7466/* Set the current message to a substring of S or STRING.
7467
7468 If STRING is a Lisp string, set the message to the first NBYTES
7469 bytes from STRING. NBYTES zero means use the whole string. If
7470 STRING is multibyte, the message will be displayed multibyte.
7471
7472 If S is not null, set the message to the first LEN bytes of S. LEN
7473 zero means use the whole string. MULTIBYTE_P non-zero means S is
7474 multibyte. Display the message multibyte in that case. */
7475
7476void
7477set_message (s, string, nbytes, multibyte_p)
50f80c2f 7478 const char *s;
c6e89d6c 7479 Lisp_Object string;
e3383b6f 7480 int nbytes, multibyte_p;
c6e89d6c
GM
7481{
7482 message_enable_multibyte
7483 = ((s && multibyte_p)
7484 || (STRINGP (string) && STRING_MULTIBYTE (string)));
2311178e 7485
23a96c77
GM
7486 with_echo_area_buffer (0, -1, set_message_1,
7487 (EMACS_INT) s, string, nbytes, multibyte_p);
c6e89d6c 7488 message_buf_print = 0;
21fdfb65 7489 help_echo_showing_p = 0;
c6e89d6c
GM
7490}
7491
7492
7493/* Helper function for set_message. Arguments have the same meaning
23a96c77
GM
7494 as there, with A1 corresponding to S and A2 corresponding to STRING
7495 This function is called with the echo area buffer being
c6e89d6c
GM
7496 current. */
7497
7498static int
23a96c77 7499set_message_1 (a1, a2, nbytes, multibyte_p)
23dd2d97
KR
7500 EMACS_INT a1;
7501 Lisp_Object a2;
7502 EMACS_INT nbytes, multibyte_p;
c6e89d6c 7503{
50f80c2f 7504 const char *s = (const char *) a1;
23dd2d97 7505 Lisp_Object string = a2;
2311178e 7506
c6e89d6c 7507 xassert (BEG == Z);
2311178e 7508
c6e89d6c
GM
7509 /* Change multibyteness of the echo buffer appropriately. */
7510 if (message_enable_multibyte
7511 != !NILP (current_buffer->enable_multibyte_characters))
7512 Fset_buffer_multibyte (message_enable_multibyte ? Qt : Qnil);
7513
ad4f174e 7514 current_buffer->truncate_lines = message_truncate_lines ? Qt : Qnil;
2311178e 7515
c6e89d6c
GM
7516 /* Insert new message at BEG. */
7517 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
7518
7519 if (STRINGP (string))
7520 {
7521 int nchars;
2311178e 7522
c6e89d6c 7523 if (nbytes == 0)
2051c264 7524 nbytes = SBYTES (string);
c6e89d6c 7525 nchars = string_byte_to_char (string, nbytes);
2311178e 7526
c6e89d6c
GM
7527 /* This function takes care of single/multibyte conversion. We
7528 just have to ensure that the echo area buffer has the right
7529 setting of enable_multibyte_characters. */
7530 insert_from_string (string, 0, 0, nchars, nbytes, 1);
7531 }
7532 else if (s)
7533 {
7534 if (nbytes == 0)
7535 nbytes = strlen (s);
2311178e 7536
c6e89d6c
GM
7537 if (multibyte_p && NILP (current_buffer->enable_multibyte_characters))
7538 {
7539 /* Convert from multi-byte to single-byte. */
7540 int i, c, n;
7541 unsigned char work[1];
2311178e 7542
c6e89d6c
GM
7543 /* Convert a multibyte string to single-byte. */
7544 for (i = 0; i < nbytes; i += n)
7545 {
7546 c = string_char_and_length (s + i, nbytes - i, &n);
7547 work[0] = (SINGLE_BYTE_CHAR_P (c)
7548 ? c
7549 : multibyte_char_to_unibyte (c, Qnil));
7550 insert_1_both (work, 1, 1, 1, 0, 0);
7551 }
7552 }
7553 else if (!multibyte_p
7554 && !NILP (current_buffer->enable_multibyte_characters))
7555 {
7556 /* Convert from single-byte to multi-byte. */
7557 int i, c, n;
50f80c2f 7558 const unsigned char *msg = (const unsigned char *) s;
260a86a0 7559 unsigned char str[MAX_MULTIBYTE_LENGTH];
2311178e 7560
c6e89d6c
GM
7561 /* Convert a single-byte string to multibyte. */
7562 for (i = 0; i < nbytes; i++)
7563 {
7564 c = unibyte_char_to_multibyte (msg[i]);
260a86a0
KH
7565 n = CHAR_STRING (c, str);
7566 insert_1_both (str, 1, n, 1, 0, 0);
c6e89d6c
GM
7567 }
7568 }
7569 else
7570 insert_1 (s, nbytes, 1, 0, 0);
7571 }
7572
7573 return 0;
7574}
7575
7576
7577/* Clear messages. CURRENT_P non-zero means clear the current
7578 message. LAST_DISPLAYED_P non-zero means clear the message
7579 last displayed. */
7580
7581void
7582clear_message (current_p, last_displayed_p)
7583 int current_p, last_displayed_p;
7584{
7585 if (current_p)
6e019995
GM
7586 {
7587 echo_area_buffer[0] = Qnil;
7588 message_cleared_p = 1;
7589 }
2311178e 7590
c6e89d6c
GM
7591 if (last_displayed_p)
7592 echo_area_buffer[1] = Qnil;
2311178e 7593
c6e89d6c
GM
7594 message_buf_print = 0;
7595}
7596
7597/* Clear garbaged frames.
7598
7599 This function is used where the old redisplay called
7600 redraw_garbaged_frames which in turn called redraw_frame which in
7601 turn called clear_frame. The call to clear_frame was a source of
7602 flickering. I believe a clear_frame is not necessary. It should
7603 suffice in the new redisplay to invalidate all current matrices,
7604 and ensure a complete redisplay of all windows. */
7605
7606static void
7607clear_garbaged_frames ()
7608{
5f5c8ee5
GM
7609 if (frame_garbaged)
7610 {
5f5c8ee5 7611 Lisp_Object tail, frame;
5fb96e96 7612 int changed_count = 0;
2311178e 7613
5f5c8ee5
GM
7614 FOR_EACH_FRAME (tail, frame)
7615 {
7616 struct frame *f = XFRAME (frame);
2311178e 7617
5f5c8ee5
GM
7618 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
7619 {
6bb95882 7620 if (f->resized_p)
573e57f1 7621 Fredraw_frame (frame);
5f5c8ee5 7622 clear_current_matrices (f);
5fb96e96 7623 changed_count++;
5f5c8ee5 7624 f->garbaged = 0;
6bb95882 7625 f->resized_p = 0;
5f5c8ee5
GM
7626 }
7627 }
7628
7629 frame_garbaged = 0;
5fb96e96
RS
7630 if (changed_count)
7631 ++windows_or_buffers_changed;
5f5c8ee5 7632 }
c6e89d6c 7633}
5f5c8ee5 7634
5f5c8ee5 7635
886bd6f2
GM
7636/* Redisplay the echo area of the selected frame. If UPDATE_FRAME_P
7637 is non-zero update selected_frame. Value is non-zero if the
c6e89d6c 7638 mini-windows height has been changed. */
5f5c8ee5 7639
c6e89d6c
GM
7640static int
7641echo_area_display (update_frame_p)
7642 int update_frame_p;
7643{
7644 Lisp_Object mini_window;
7645 struct window *w;
7646 struct frame *f;
7647 int window_height_changed_p = 0;
886bd6f2 7648 struct frame *sf = SELECTED_FRAME ();
c6e89d6c 7649
886bd6f2 7650 mini_window = FRAME_MINIBUF_WINDOW (sf);
c6e89d6c
GM
7651 w = XWINDOW (mini_window);
7652 f = XFRAME (WINDOW_FRAME (w));
7653
7654 /* Don't display if frame is invisible or not yet initialized. */
7655 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
7656 return 0;
5f5c8ee5 7657
1a578e9b 7658/* The terminal frame is used as the first Emacs frame on the Mac OS. */
e0f712ba 7659#ifndef MAC_OS8
1ab3e082 7660#ifdef HAVE_WINDOW_SYSTEM
c6e89d6c
GM
7661 /* When Emacs starts, selected_frame may be a visible terminal
7662 frame, even if we run under a window system. If we let this
7663 through, a message would be displayed on the terminal. */
2311178e 7664 if (EQ (selected_frame, Vterminal_frame)
622e3754 7665 && !NILP (Vwindow_system))
c6e89d6c 7666 return 0;
1ab3e082 7667#endif /* HAVE_WINDOW_SYSTEM */
1a578e9b 7668#endif
c6e89d6c
GM
7669
7670 /* Redraw garbaged frames. */
7671 if (frame_garbaged)
7672 clear_garbaged_frames ();
7673
7674 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
7675 {
7676 echo_area_window = mini_window;
7677 window_height_changed_p = display_echo_area (w);
5f5c8ee5 7678 w->must_be_updated_p = 1;
c59c668a 7679
d4358b37
GM
7680 /* Update the display, unless called from redisplay_internal.
7681 Also don't update the screen during redisplay itself. The
7682 update will happen at the end of redisplay, and an update
7683 here could cause confusion. */
7684 if (update_frame_p && !redisplaying_p)
5f5c8ee5 7685 {
715e84c9 7686 int n = 0;
edc68111 7687
715e84c9
GM
7688 /* If the display update has been interrupted by pending
7689 input, update mode lines in the frame. Due to the
7690 pending input, it might have been that redisplay hasn't
7691 been called, so that mode lines above the echo area are
7692 garbaged. This looks odd, so we prevent it here. */
7693 if (!display_completed)
7694 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), 0);
2311178e 7695
8af1308e
GM
7696 if (window_height_changed_p
7697 /* Don't do this if Emacs is shutting down. Redisplay
7698 needs to run hooks. */
7699 && !NILP (Vrun_hooks))
c59c668a 7700 {
c06017fb
GM
7701 /* Must update other windows. Likewise as in other
7702 cases, don't let this update be interrupted by
7703 pending input. */
331379bf 7704 int count = SPECPDL_INDEX ();
c06017fb 7705 specbind (Qredisplay_dont_pause, Qt);
edc68111 7706 windows_or_buffers_changed = 1;
c59c668a 7707 redisplay_internal (0);
c06017fb 7708 unbind_to (count, Qnil);
c59c668a 7709 }
715e84c9 7710 else if (FRAME_WINDOW_P (f) && n == 0)
5f5c8ee5 7711 {
edc68111 7712 /* Window configuration is the same as before.
715e84c9
GM
7713 Can do with a display update of the echo area,
7714 unless we displayed some mode lines. */
5f5c8ee5
GM
7715 update_single_window (w, 1);
7716 rif->flush_display (f);
7717 }
7718 else
7719 update_frame (f, 1, 1);
31b6671b
GM
7720
7721 /* If cursor is in the echo area, make sure that the next
7722 redisplay displays the minibuffer, so that the cursor will
7723 be replaced with what the minibuffer wants. */
7724 if (cursor_in_echo_area)
7725 ++windows_or_buffers_changed;
5f5c8ee5
GM
7726 }
7727 }
7728 else if (!EQ (mini_window, selected_window))
7729 windows_or_buffers_changed++;
c59c668a
GM
7730
7731 /* Last displayed message is now the current message. */
dd2eb166 7732 echo_area_buffer[1] = echo_area_buffer[0];
2311178e 7733
5f5c8ee5
GM
7734 /* Prevent redisplay optimization in redisplay_internal by resetting
7735 this_line_start_pos. This is done because the mini-buffer now
7736 displays the message instead of its buffer text. */
7737 if (EQ (mini_window, selected_window))
7738 CHARPOS (this_line_start_pos) = 0;
c6e89d6c
GM
7739
7740 return window_height_changed_p;
5f5c8ee5
GM
7741}
7742
7743
7744\f
7745/***********************************************************************
7746 Frame Titles
7747 ***********************************************************************/
7748
7749
8143e6ab
KS
7750/* The frame title buffering code is also used by Fformat_mode_line.
7751 So it is not conditioned by HAVE_WINDOW_SYSTEM. */
5f5c8ee5
GM
7752
7753/* A buffer for constructing frame titles in it; allocated from the
7754 heap in init_xdisp and resized as needed in store_frame_title_char. */
7755
7756static char *frame_title_buf;
7757
7758/* The buffer's end, and a current output position in it. */
7759
7760static char *frame_title_buf_end;
7761static char *frame_title_ptr;
7762
7763
7764/* Store a single character C for the frame title in frame_title_buf.
7765 Re-allocate frame_title_buf if necessary. */
7766
7767static void
5d15cc8f
DL
7768#ifdef PROTOTYPES
7769store_frame_title_char (char c)
7770#else
5f5c8ee5
GM
7771store_frame_title_char (c)
7772 char c;
5d15cc8f 7773#endif
5f5c8ee5
GM
7774{
7775 /* If output position has reached the end of the allocated buffer,
7776 double the buffer's size. */
7777 if (frame_title_ptr == frame_title_buf_end)
7778 {
7779 int len = frame_title_ptr - frame_title_buf;
7780 int new_size = 2 * len * sizeof *frame_title_buf;
7781 frame_title_buf = (char *) xrealloc (frame_title_buf, new_size);
7782 frame_title_buf_end = frame_title_buf + new_size;
7783 frame_title_ptr = frame_title_buf + len;
7784 }
7785
7786 *frame_title_ptr++ = c;
7787}
7788
7789
7790/* Store part of a frame title in frame_title_buf, beginning at
d26b89b8
KH
7791 frame_title_ptr. STR is the string to store. Do not copy
7792 characters that yield more columns than PRECISION; PRECISION <= 0
7793 means copy the whole string. Pad with spaces until FIELD_WIDTH
7794 number of characters have been copied; FIELD_WIDTH <= 0 means don't
7795 pad. Called from display_mode_element when it is used to build a
7796 frame title. */
5f5c8ee5
GM
7797
7798static int
7799store_frame_title (str, field_width, precision)
50f80c2f 7800 const unsigned char *str;
5f5c8ee5
GM
7801 int field_width, precision;
7802{
7803 int n = 0;
3b552d56 7804 int dummy, nbytes;
5f5c8ee5
GM
7805
7806 /* Copy at most PRECISION chars from STR. */
d26b89b8
KH
7807 nbytes = strlen (str);
7808 n+= c_string_width (str, nbytes, precision, &dummy, &nbytes);
7809 while (nbytes--)
7810 store_frame_title_char (*str++);
5f5c8ee5
GM
7811
7812 /* Fill up with spaces until FIELD_WIDTH reached. */
7813 while (field_width > 0
7814 && n < field_width)
7815 {
7816 store_frame_title_char (' ');
7817 ++n;
7818 }
7819
7820 return n;
7821}
7822
8143e6ab 7823#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7824
7825/* Set the title of FRAME, if it has changed. The title format is
7826 Vicon_title_format if FRAME is iconified, otherwise it is
7827 frame_title_format. */
7828
7829static void
7830x_consider_frame_title (frame)
7831 Lisp_Object frame;
7832{
7833 struct frame *f = XFRAME (frame);
7834
7835 if (FRAME_WINDOW_P (f)
7836 || FRAME_MINIBUF_ONLY_P (f)
7837 || f->explicit_name)
7838 {
7839 /* Do we have more than one visible frame on this X display? */
7840 Lisp_Object tail;
7841 Lisp_Object fmt;
7842 struct buffer *obuf;
7843 int len;
7844 struct it it;
7845
9472f927 7846 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
5f5c8ee5 7847 {
74779f52
JR
7848 Lisp_Object other_frame = XCAR (tail);
7849 struct frame *tf = XFRAME (other_frame);
5f5c8ee5 7850
2311178e 7851 if (tf != f
5f5c8ee5
GM
7852 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
7853 && !FRAME_MINIBUF_ONLY_P (tf)
74779f52 7854 && !EQ (other_frame, tip_frame)
5f5c8ee5
GM
7855 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
7856 break;
7857 }
7858
7859 /* Set global variable indicating that multiple frames exist. */
7860 multiple_frames = CONSP (tail);
7861
7862 /* Switch to the buffer of selected window of the frame. Set up
7863 frame_title_ptr so that display_mode_element will output into it;
7864 then display the title. */
7865 obuf = current_buffer;
bb336f8d 7866 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->buffer));
5f5c8ee5
GM
7867 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;
7868 frame_title_ptr = frame_title_buf;
7869 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
7870 NULL, DEFAULT_FACE_ID);
c53a1624 7871 display_mode_element (&it, 0, -1, -1, fmt, Qnil, 0);
d26b89b8 7872 len = frame_title_ptr - frame_title_buf;
5f5c8ee5 7873 frame_title_ptr = NULL;
bb336f8d 7874 set_buffer_internal_1 (obuf);
5f5c8ee5
GM
7875
7876 /* Set the title only if it's changed. This avoids consing in
7877 the common case where it hasn't. (If it turns out that we've
7878 already wasted too much time by walking through the list with
7879 display_mode_element, then we might need to optimize at a
7880 higher level than this.) */
2311178e 7881 if (! STRINGP (f->name)
2051c264
GM
7882 || SBYTES (f->name) != len
7883 || bcmp (frame_title_buf, SDATA (f->name), len) != 0)
5f5c8ee5
GM
7884 x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
7885 }
7886}
7887
5f5c8ee5
GM
7888#endif /* not HAVE_WINDOW_SYSTEM */
7889
7890
7891
7892\f
7893/***********************************************************************
7894 Menu Bars
7895 ***********************************************************************/
7896
7897
7898/* Prepare for redisplay by updating menu-bar item lists when
7899 appropriate. This can call eval. */
7900
7901void
7902prepare_menu_bars ()
7903{
7904 int all_windows;
7905 struct gcpro gcpro1, gcpro2;
7906 struct frame *f;
6b5c4794 7907 Lisp_Object tooltip_frame;
5f5c8ee5 7908
86ffe5cd 7909#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
7910 tooltip_frame = tip_frame;
7911#else
6b5c4794 7912 tooltip_frame = Qnil;
5f5c8ee5
GM
7913#endif
7914
7915 /* Update all frame titles based on their buffer names, etc. We do
7916 this before the menu bars so that the buffer-menu will show the
7917 up-to-date frame titles. */
7918#ifdef HAVE_WINDOW_SYSTEM
7919 if (windows_or_buffers_changed || update_mode_lines)
7920 {
7921 Lisp_Object tail, frame;
7922
7923 FOR_EACH_FRAME (tail, frame)
7924 {
7925 f = XFRAME (frame);
6b5c4794 7926 if (!EQ (frame, tooltip_frame)
5f5c8ee5
GM
7927 && (FRAME_VISIBLE_P (f) || FRAME_ICONIFIED_P (f)))
7928 x_consider_frame_title (frame);
7929 }
7930 }
7931#endif /* HAVE_WINDOW_SYSTEM */
7932
7933 /* Update the menu bar item lists, if appropriate. This has to be
7934 done before any actual redisplay or generation of display lines. */
2311178e 7935 all_windows = (update_mode_lines
5f5c8ee5
GM
7936 || buffer_shared > 1
7937 || windows_or_buffers_changed);
7938 if (all_windows)
7939 {
7940 Lisp_Object tail, frame;
331379bf 7941 int count = SPECPDL_INDEX ();
5f5c8ee5
GM
7942
7943 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
7944
7945 FOR_EACH_FRAME (tail, frame)
7946 {
7947 f = XFRAME (frame);
7948
7949 /* Ignore tooltip frame. */
6b5c4794 7950 if (EQ (frame, tooltip_frame))
5f5c8ee5 7951 continue;
2311178e 7952
5f5c8ee5
GM
7953 /* If a window on this frame changed size, report that to
7954 the user and clear the size-change flag. */
7955 if (FRAME_WINDOW_SIZES_CHANGED (f))
7956 {
7957 Lisp_Object functions;
2311178e 7958
5f5c8ee5
GM
7959 /* Clear flag first in case we get an error below. */
7960 FRAME_WINDOW_SIZES_CHANGED (f) = 0;
7961 functions = Vwindow_size_change_functions;
7962 GCPRO2 (tail, functions);
2311178e 7963
5f5c8ee5
GM
7964 while (CONSP (functions))
7965 {
7966 call1 (XCAR (functions), frame);
7967 functions = XCDR (functions);
7968 }
7969 UNGCPRO;
7970 }
2311178e 7971
5f5c8ee5
GM
7972 GCPRO1 (tail);
7973 update_menu_bar (f, 0);
7974#ifdef HAVE_WINDOW_SYSTEM
e037b9ec 7975 update_tool_bar (f, 0);
5f5c8ee5
GM
7976#endif
7977 UNGCPRO;
7978 }
7979
7980 unbind_to (count, Qnil);
7981 }
7982 else
7983 {
886bd6f2
GM
7984 struct frame *sf = SELECTED_FRAME ();
7985 update_menu_bar (sf, 1);
5f5c8ee5 7986#ifdef HAVE_WINDOW_SYSTEM
886bd6f2 7987 update_tool_bar (sf, 1);
5f5c8ee5
GM
7988#endif
7989 }
7990
7991 /* Motif needs this. See comment in xmenu.c. Turn it off when
7992 pending_menu_activation is not defined. */
7993#ifdef USE_X_TOOLKIT
7994 pending_menu_activation = 0;
7995#endif
7996}
7997
7998
7999/* Update the menu bar item list for frame F. This has to be done
8000 before we start to fill in any display lines, because it can call
8001 eval.
8002
8003 If SAVE_MATCH_DATA is non-zero, we must save and restore it here. */
8004
8005static void
8006update_menu_bar (f, save_match_data)
8007 struct frame *f;
8008 int save_match_data;
8009{
8010 Lisp_Object window;
8011 register struct window *w;
8012
e1477f43
GM
8013 /* If called recursively during a menu update, do nothing. This can
8014 happen when, for instance, an activate-menubar-hook causes a
8015 redisplay. */
8016 if (inhibit_menubar_update)
8017 return;
8018
5f5c8ee5
GM
8019 window = FRAME_SELECTED_WINDOW (f);
8020 w = XWINDOW (window);
2311178e 8021
84f2e615 8022#if 0 /* The if statement below this if statement used to include the
a5f08374
RS
8023 condition !NILP (w->update_mode_line), rather than using
8024 update_mode_lines directly, and this if statement may have
8025 been added to make that condition work. Now the if
2311178e 8026 statement below matches its comment, this isn't needed. */
5f5c8ee5
GM
8027 if (update_mode_lines)
8028 w->update_mode_line = Qt;
a5f08374 8029#endif
5f5c8ee5
GM
8030
8031 if (FRAME_WINDOW_P (f)
8032 ?
488dd4c4
JD
8033#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
8034 || defined (USE_GTK)
2311178e 8035 FRAME_EXTERNAL_MENU_BAR (f)
5f5c8ee5
GM
8036#else
8037 FRAME_MENU_BAR_LINES (f) > 0
8038#endif
8039 : FRAME_MENU_BAR_LINES (f) > 0)
8040 {
8041 /* If the user has switched buffers or windows, we need to
8042 recompute to reflect the new bindings. But we'll
8043 recompute when update_mode_lines is set too; that means
8044 that people can use force-mode-line-update to request
8045 that the menu bar be recomputed. The adverse effect on
8046 the rest of the redisplay algorithm is about the same as
8047 windows_or_buffers_changed anyway. */
8048 if (windows_or_buffers_changed
a5f08374
RS
8049 /* This used to test w->update_mode_line, but we believe
8050 there is no need to recompute the menu in that case. */
8051 || update_mode_lines
5f5c8ee5
GM
8052 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8053 < BUF_MODIFF (XBUFFER (w->buffer)))
8054 != !NILP (w->last_had_star))
8055 || ((!NILP (Vtransient_mark_mode)
8056 && !NILP (XBUFFER (w->buffer)->mark_active))
8057 != !NILP (w->region_showing)))
8058 {
8059 struct buffer *prev = current_buffer;
331379bf 8060 int count = SPECPDL_INDEX ();
5f5c8ee5 8061
e1477f43
GM
8062 specbind (Qinhibit_menubar_update, Qt);
8063
5f5c8ee5
GM
8064 set_buffer_internal_1 (XBUFFER (w->buffer));
8065 if (save_match_data)
8066 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8067 if (NILP (Voverriding_local_map_menu_flag))
8068 {
8069 specbind (Qoverriding_terminal_local_map, Qnil);
8070 specbind (Qoverriding_local_map, Qnil);
8071 }
8072
8073 /* Run the Lucid hook. */
65048e97 8074 safe_run_hooks (Qactivate_menubar_hook);
2311178e 8075
5f5c8ee5
GM
8076 /* If it has changed current-menubar from previous value,
8077 really recompute the menu-bar from the value. */
8078 if (! NILP (Vlucid_menu_bar_dirty_flag))
8079 call0 (Qrecompute_lucid_menubar);
2311178e 8080
5f5c8ee5
GM
8081 safe_run_hooks (Qmenu_bar_update_hook);
8082 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
2311178e 8083
5f5c8ee5 8084 /* Redisplay the menu bar in case we changed it. */
488dd4c4
JD
8085#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
8086 || defined (USE_GTK)
1a578e9b 8087 if (FRAME_WINDOW_P (f)
e0f712ba 8088#if defined (MAC_OS)
1a578e9b
AC
8089 /* All frames on Mac OS share the same menubar. So only the
8090 selected frame should be allowed to set it. */
8091 && f == SELECTED_FRAME ()
8092#endif
8093 )
5f5c8ee5
GM
8094 set_frame_menubar (f, 0, 0);
8095 else
8096 /* On a terminal screen, the menu bar is an ordinary screen
8097 line, and this makes it get updated. */
8098 w->update_mode_line = Qt;
488dd4c4 8099#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8100 /* In the non-toolkit version, the menu bar is an ordinary screen
8101 line, and this makes it get updated. */
8102 w->update_mode_line = Qt;
488dd4c4 8103#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */
5f5c8ee5
GM
8104
8105 unbind_to (count, Qnil);
8106 set_buffer_internal_1 (prev);
8107 }
8108 }
8109}
8110
8111
8112\f
fa3c6b4d
KS
8113/***********************************************************************
8114 Output Cursor
8115 ***********************************************************************/
8116
1dabd0cf
KS
8117#ifdef HAVE_WINDOW_SYSTEM
8118
fa3c6b4d
KS
8119/* EXPORT:
8120 Nominal cursor position -- where to draw output.
8121 HPOS and VPOS are window relative glyph matrix coordinates.
8122 X and Y are window relative pixel coordinates. */
8123
8124struct cursor_pos output_cursor;
8125
8126
8127/* EXPORT:
8128 Set the global variable output_cursor to CURSOR. All cursor
8129 positions are relative to updated_window. */
8130
8131void
8132set_output_cursor (cursor)
8133 struct cursor_pos *cursor;
8134{
8135 output_cursor.hpos = cursor->hpos;
8136 output_cursor.vpos = cursor->vpos;
8137 output_cursor.x = cursor->x;
8138 output_cursor.y = cursor->y;
8139}
8140
8141
8142/* EXPORT for RIF:
8143 Set a nominal cursor position.
8144
8145 HPOS and VPOS are column/row positions in a window glyph matrix. X
8146 and Y are window text area relative pixel positions.
8147
8148 If this is done during an update, updated_window will contain the
8149 window that is being updated and the position is the future output
8150 cursor position for that window. If updated_window is null, use
8151 selected_window and display the cursor at the given position. */
8152
8153void
8154x_cursor_to (vpos, hpos, y, x)
8155 int vpos, hpos, y, x;
8156{
8157 struct window *w;
8158
8159 /* If updated_window is not set, work on selected_window. */
8160 if (updated_window)
8161 w = updated_window;
8162 else
8163 w = XWINDOW (selected_window);
8164
8165 /* Set the output cursor. */
8166 output_cursor.hpos = hpos;
8167 output_cursor.vpos = vpos;
8168 output_cursor.x = x;
8169 output_cursor.y = y;
8170
8171 /* If not called as part of an update, really display the cursor.
8172 This will also set the cursor position of W. */
8173 if (updated_window == NULL)
8174 {
8175 BLOCK_INPUT;
8176 display_and_set_cursor (w, 1, hpos, vpos, x, y);
8177 if (rif->flush_display_optional)
8178 rif->flush_display_optional (SELECTED_FRAME ());
8179 UNBLOCK_INPUT;
8180 }
8181}
8182
1dabd0cf 8183#endif /* HAVE_WINDOW_SYSTEM */
fa3c6b4d
KS
8184
8185\f
5f5c8ee5 8186/***********************************************************************
e037b9ec 8187 Tool-bars
5f5c8ee5
GM
8188 ***********************************************************************/
8189
8190#ifdef HAVE_WINDOW_SYSTEM
8191
fa3c6b4d
KS
8192/* Where the mouse was last time we reported a mouse event. */
8193
8194FRAME_PTR last_mouse_frame;
8195
8196/* Tool-bar item index of the item on which a mouse button was pressed
8197 or -1. */
8198
8199int last_tool_bar_item;
8200
8201
e037b9ec 8202/* Update the tool-bar item list for frame F. This has to be done
5f5c8ee5
GM
8203 before we start to fill in any display lines. Called from
8204 prepare_menu_bars. If SAVE_MATCH_DATA is non-zero, we must save
8205 and restore it here. */
8206
8207static void
e037b9ec 8208update_tool_bar (f, save_match_data)
5f5c8ee5
GM
8209 struct frame *f;
8210 int save_match_data;
8211{
488dd4c4 8212#ifdef USE_GTK
810f2256 8213 int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
488dd4c4
JD
8214#else
8215 int do_update = WINDOWP (f->tool_bar_window)
da8b7f4f 8216 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
488dd4c4
JD
8217#endif
8218
8219 if (do_update)
5f5c8ee5
GM
8220 {
8221 Lisp_Object window;
8222 struct window *w;
8223
8224 window = FRAME_SELECTED_WINDOW (f);
8225 w = XWINDOW (window);
2311178e 8226
5f5c8ee5
GM
8227 /* If the user has switched buffers or windows, we need to
8228 recompute to reflect the new bindings. But we'll
8229 recompute when update_mode_lines is set too; that means
8230 that people can use force-mode-line-update to request
8231 that the menu bar be recomputed. The adverse effect on
8232 the rest of the redisplay algorithm is about the same as
8233 windows_or_buffers_changed anyway. */
8234 if (windows_or_buffers_changed
8235 || !NILP (w->update_mode_line)
84f2e615 8236 || update_mode_lines
5f5c8ee5
GM
8237 || ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
8238 < BUF_MODIFF (XBUFFER (w->buffer)))
8239 != !NILP (w->last_had_star))
8240 || ((!NILP (Vtransient_mark_mode)
8241 && !NILP (XBUFFER (w->buffer)->mark_active))
8242 != !NILP (w->region_showing)))
8243 {
8244 struct buffer *prev = current_buffer;
331379bf 8245 int count = SPECPDL_INDEX ();
84f2e615
RS
8246 Lisp_Object old_tool_bar;
8247 struct gcpro gcpro1;
a2889657 8248
5f5c8ee5
GM
8249 /* Set current_buffer to the buffer of the selected
8250 window of the frame, so that we get the right local
8251 keymaps. */
8252 set_buffer_internal_1 (XBUFFER (w->buffer));
1f40cad2 8253
5f5c8ee5
GM
8254 /* Save match data, if we must. */
8255 if (save_match_data)
8256 record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
8257
8258 /* Make sure that we don't accidentally use bogus keymaps. */
8259 if (NILP (Voverriding_local_map_menu_flag))
8260 {
8261 specbind (Qoverriding_terminal_local_map, Qnil);
8262 specbind (Qoverriding_local_map, Qnil);
1f40cad2 8263 }
1f40cad2 8264
84f2e615
RS
8265 old_tool_bar = f->tool_bar_items;
8266 GCPRO1 (old_tool_bar);
8267
e037b9ec 8268 /* Build desired tool-bar items from keymaps. */
e3b2c21f 8269 BLOCK_INPUT;
7464726e
GM
8270 f->tool_bar_items
8271 = tool_bar_items (f->tool_bar_items, &f->n_tool_bar_items);
e3b2c21f 8272 UNBLOCK_INPUT;
2311178e 8273
84f2e615
RS
8274 /* Redisplay the tool-bar if we changed it. */
8275 if (! NILP (Fequal (old_tool_bar, f->tool_bar_items)))
8276 w->update_mode_line = Qt;
1e802fb5
SM
8277
8278 UNGCPRO;
5f5c8ee5
GM
8279
8280 unbind_to (count, Qnil);
8281 set_buffer_internal_1 (prev);
81d478f3 8282 }
a2889657
JB
8283 }
8284}
8285
6c4429a5 8286
e037b9ec 8287/* Set F->desired_tool_bar_string to a Lisp string representing frame
7464726e 8288 F's desired tool-bar contents. F->tool_bar_items must have
5f5c8ee5
GM
8289 been set up previously by calling prepare_menu_bars. */
8290
a2889657 8291static void
e037b9ec 8292build_desired_tool_bar_string (f)
5f5c8ee5 8293 struct frame *f;
a2889657 8294{
a23887b9 8295 int i, size, size_needed;
5f5c8ee5
GM
8296 struct gcpro gcpro1, gcpro2, gcpro3;
8297 Lisp_Object image, plist, props;
a2889657 8298
5f5c8ee5
GM
8299 image = plist = props = Qnil;
8300 GCPRO3 (image, plist, props);
a2889657 8301
e037b9ec 8302 /* Prepare F->desired_tool_bar_string. If we can reuse it, do so.
5f5c8ee5 8303 Otherwise, make a new string. */
2311178e 8304
5f5c8ee5 8305 /* The size of the string we might be able to reuse. */
e037b9ec 8306 size = (STRINGP (f->desired_tool_bar_string)
2051c264 8307 ? SCHARS (f->desired_tool_bar_string)
5f5c8ee5
GM
8308 : 0);
8309
b94c0d9c 8310 /* We need one space in the string for each image. */
a23887b9 8311 size_needed = f->n_tool_bar_items;
2311178e 8312
b94c0d9c 8313 /* Reuse f->desired_tool_bar_string, if possible. */
cb2ddc53 8314 if (size < size_needed || NILP (f->desired_tool_bar_string))
6fc556fd
KR
8315 f->desired_tool_bar_string = Fmake_string (make_number (size_needed),
8316 make_number (' '));
5f5c8ee5
GM
8317 else
8318 {
8319 props = list4 (Qdisplay, Qnil, Qmenu_item, Qnil);
8320 Fremove_text_properties (make_number (0), make_number (size),
e037b9ec 8321 props, f->desired_tool_bar_string);
5f5c8ee5 8322 }
a2889657 8323
5f5c8ee5 8324 /* Put a `display' property on the string for the images to display,
e037b9ec
GM
8325 put a `menu_item' property on tool-bar items with a value that
8326 is the index of the item in F's tool-bar item vector. */
a23887b9 8327 for (i = 0; i < f->n_tool_bar_items; ++i)
a2889657 8328 {
7464726e 8329#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
5f5c8ee5 8330
e037b9ec
GM
8331 int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
8332 int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
35a41507 8333 int hmargin, vmargin, relief, idx, end;
493fdc3c 8334 extern Lisp_Object QCrelief, QCmargin, QCconversion;
5f5c8ee5
GM
8335
8336 /* If image is a vector, choose the image according to the
8337 button state. */
e037b9ec 8338 image = PROP (TOOL_BAR_ITEM_IMAGES);
5f5c8ee5
GM
8339 if (VECTORP (image))
8340 {
5f5c8ee5
GM
8341 if (enabled_p)
8342 idx = (selected_p
e037b9ec
GM
8343 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
8344 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
5f5c8ee5
GM
8345 else
8346 idx = (selected_p
e037b9ec
GM
8347 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
8348 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
2311178e 8349
37e4e482
GM
8350 xassert (ASIZE (image) >= idx);
8351 image = AREF (image, idx);
5f5c8ee5 8352 }
37e4e482
GM
8353 else
8354 idx = -1;
5f5c8ee5
GM
8355
8356 /* Ignore invalid image specifications. */
8357 if (!valid_image_p (image))
8358 continue;
8359
e037b9ec 8360 /* Display the tool-bar button pressed, or depressed. */
5f5c8ee5
GM
8361 plist = Fcopy_sequence (XCDR (image));
8362
8363 /* Compute margin and relief to draw. */
9f864bf9 8364 relief = (tool_bar_button_relief >= 0
c3d76173
GM
8365 ? tool_bar_button_relief
8366 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
35a41507
GM
8367 hmargin = vmargin = relief;
8368
8369 if (INTEGERP (Vtool_bar_button_margin)
8370 && XINT (Vtool_bar_button_margin) > 0)
8371 {
8372 hmargin += XFASTINT (Vtool_bar_button_margin);
8373 vmargin += XFASTINT (Vtool_bar_button_margin);
8374 }
8375 else if (CONSP (Vtool_bar_button_margin))
8376 {
8377 if (INTEGERP (XCAR (Vtool_bar_button_margin))
8378 && XINT (XCAR (Vtool_bar_button_margin)) > 0)
8379 hmargin += XFASTINT (XCAR (Vtool_bar_button_margin));
2311178e 8380
35a41507
GM
8381 if (INTEGERP (XCDR (Vtool_bar_button_margin))
8382 && XINT (XCDR (Vtool_bar_button_margin)) > 0)
8383 vmargin += XFASTINT (XCDR (Vtool_bar_button_margin));
8384 }
2311178e 8385
e037b9ec 8386 if (auto_raise_tool_bar_buttons_p)
5f5c8ee5
GM
8387 {
8388 /* Add a `:relief' property to the image spec if the item is
8389 selected. */
8390 if (selected_p)
8391 {
8392 plist = Fplist_put (plist, QCrelief, make_number (-relief));
35a41507
GM
8393 hmargin -= relief;
8394 vmargin -= relief;
5f5c8ee5
GM
8395 }
8396 }
8397 else
8398 {
8399 /* If image is selected, display it pressed, i.e. with a
8400 negative relief. If it's not selected, display it with a
8401 raised relief. */
8402 plist = Fplist_put (plist, QCrelief,
8403 (selected_p
8404 ? make_number (-relief)
8405 : make_number (relief)));
35a41507
GM
8406 hmargin -= relief;
8407 vmargin -= relief;
5f5c8ee5
GM
8408 }
8409
8410 /* Put a margin around the image. */
35a41507
GM
8411 if (hmargin || vmargin)
8412 {
8413 if (hmargin == vmargin)
8414 plist = Fplist_put (plist, QCmargin, make_number (hmargin));
8415 else
8416 plist = Fplist_put (plist, QCmargin,
8417 Fcons (make_number (hmargin),
8418 make_number (vmargin)));
8419 }
2311178e 8420
37e4e482
GM
8421 /* If button is not enabled, and we don't have special images
8422 for the disabled state, make the image appear disabled by
5f5c8ee5 8423 applying an appropriate algorithm to it. */
37e4e482 8424 if (!enabled_p && idx < 0)
ecd01a0e 8425 plist = Fplist_put (plist, QCconversion, Qdisabled);
2311178e 8426
5f5c8ee5
GM
8427 /* Put a `display' text property on the string for the image to
8428 display. Put a `menu-item' property on the string that gives
e037b9ec 8429 the start of this item's properties in the tool-bar items
5f5c8ee5
GM
8430 vector. */
8431 image = Fcons (Qimage, plist);
8432 props = list4 (Qdisplay, image,
a23887b9
GM
8433 Qmenu_item, make_number (i * TOOL_BAR_ITEM_NSLOTS));
8434
8435 /* Let the last image hide all remaining spaces in the tool bar
8436 string. The string can be longer than needed when we reuse a
8437 previous string. */
8438 if (i + 1 == f->n_tool_bar_items)
2051c264 8439 end = SCHARS (f->desired_tool_bar_string);
a23887b9
GM
8440 else
8441 end = i + 1;
8442 Fadd_text_properties (make_number (i), make_number (end),
e037b9ec 8443 props, f->desired_tool_bar_string);
5f5c8ee5 8444#undef PROP
a2889657
JB
8445 }
8446
5f5c8ee5
GM
8447 UNGCPRO;
8448}
8449
8450
e037b9ec 8451/* Display one line of the tool-bar of frame IT->f. */
5f5c8ee5
GM
8452
8453static void
e037b9ec 8454display_tool_bar_line (it)
5f5c8ee5
GM
8455 struct it *it;
8456{
8457 struct glyph_row *row = it->glyph_row;
8458 int max_x = it->last_visible_x;
8459 struct glyph *last;
2311178e 8460
5f5c8ee5
GM
8461 prepare_desired_row (row);
8462 row->y = it->current_y;
90aa2856
GM
8463
8464 /* Note that this isn't made use of if the face hasn't a box,
8465 so there's no need to check the face here. */
8466 it->start_of_box_run_p = 1;
2311178e 8467
5f5c8ee5 8468 while (it->current_x < max_x)
a2889657 8469 {
5f5c8ee5 8470 int x_before, x, n_glyphs_before, i, nglyphs;
a2f016e3 8471
5f5c8ee5
GM
8472 /* Get the next display element. */
8473 if (!get_next_display_element (it))
8474 break;
73af359d 8475
5f5c8ee5
GM
8476 /* Produce glyphs. */
8477 x_before = it->current_x;
8478 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
8479 PRODUCE_GLYPHS (it);
daa37602 8480
5f5c8ee5
GM
8481 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
8482 i = 0;
8483 x = x_before;
8484 while (i < nglyphs)
8485 {
8486 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 8487
5f5c8ee5
GM
8488 if (x + glyph->pixel_width > max_x)
8489 {
8490 /* Glyph doesn't fit on line. */
8491 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
8492 it->current_x = x;
8493 goto out;
8494 }
daa37602 8495
5f5c8ee5
GM
8496 ++it->hpos;
8497 x += glyph->pixel_width;
8498 ++i;
8499 }
8500
8501 /* Stop at line ends. */
8502 if (ITERATOR_AT_END_OF_LINE_P (it))
8503 break;
8504
cafafe0b 8505 set_iterator_to_next (it, 1);
a2889657 8506 }
a2889657 8507
5f5c8ee5 8508 out:;
a2889657 8509
5f5c8ee5
GM
8510 row->displays_text_p = row->used[TEXT_AREA] != 0;
8511 extend_face_to_end_of_line (it);
8512 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
8513 last->right_box_line_p = 1;
90aa2856
GM
8514 if (last == row->glyphs[TEXT_AREA])
8515 last->left_box_line_p = 1;
5f5c8ee5 8516 compute_line_metrics (it);
2311178e 8517
e037b9ec 8518 /* If line is empty, make it occupy the rest of the tool-bar. */
5f5c8ee5
GM
8519 if (!row->displays_text_p)
8520 {
312246d1
GM
8521 row->height = row->phys_height = it->last_visible_y - row->y;
8522 row->ascent = row->phys_ascent = 0;
5f5c8ee5 8523 }
2311178e 8524
5f5c8ee5
GM
8525 row->full_width_p = 1;
8526 row->continued_p = 0;
8527 row->truncated_on_left_p = 0;
8528 row->truncated_on_right_p = 0;
8529
8530 it->current_x = it->hpos = 0;
8531 it->current_y += row->height;
8532 ++it->vpos;
8533 ++it->glyph_row;
a2889657 8534}
96a410bc 8535
5f5c8ee5 8536
e037b9ec 8537/* Value is the number of screen lines needed to make all tool-bar
5f5c8ee5 8538 items of frame F visible. */
96a410bc 8539
d39b6696 8540static int
e037b9ec 8541tool_bar_lines_needed (f)
5f5c8ee5 8542 struct frame *f;
d39b6696 8543{
e037b9ec 8544 struct window *w = XWINDOW (f->tool_bar_window);
5f5c8ee5 8545 struct it it;
2311178e 8546
e037b9ec
GM
8547 /* Initialize an iterator for iteration over
8548 F->desired_tool_bar_string in the tool-bar window of frame F. */
8549 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8550 it.first_visible_x = 0;
da8b7f4f 8551 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
e037b9ec 8552 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
5f5c8ee5
GM
8553
8554 while (!ITERATOR_AT_END_P (&it))
8555 {
8556 it.glyph_row = w->desired_matrix->rows;
8557 clear_glyph_row (it.glyph_row);
e037b9ec 8558 display_tool_bar_line (&it);
5f5c8ee5
GM
8559 }
8560
da8b7f4f 8561 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
d39b6696 8562}
96a410bc 8563
5f5c8ee5 8564
57c28064
GM
8565DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
8566 0, 1, 0,
7ee72033
MB
8567 doc: /* Return the number of lines occupied by the tool bar of FRAME. */)
8568 (frame)
57c28064
GM
8569 Lisp_Object frame;
8570{
8571 struct frame *f;
8572 struct window *w;
8573 int nlines = 0;
8574
8575 if (NILP (frame))
8576 frame = selected_frame;
8577 else
b7826503 8578 CHECK_FRAME (frame);
57c28064 8579 f = XFRAME (frame);
2311178e 8580
57c28064
GM
8581 if (WINDOWP (f->tool_bar_window)
8582 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8583 WINDOW_TOTAL_LINES (w) > 0))
57c28064
GM
8584 {
8585 update_tool_bar (f, 1);
8586 if (f->n_tool_bar_items)
8587 {
8588 build_desired_tool_bar_string (f);
8589 nlines = tool_bar_lines_needed (f);
8590 }
8591 }
8592
8593 return make_number (nlines);
8594}
8595
8596
e037b9ec 8597/* Display the tool-bar of frame F. Value is non-zero if tool-bar's
5f5c8ee5
GM
8598 height should be changed. */
8599
8600static int
e037b9ec 8601redisplay_tool_bar (f)
5f5c8ee5 8602 struct frame *f;
96a410bc 8603{
5f5c8ee5
GM
8604 struct window *w;
8605 struct it it;
8606 struct glyph_row *row;
8607 int change_height_p = 0;
177c0ea7 8608
488dd4c4 8609#ifdef USE_GTK
810f2256 8610 if (FRAME_EXTERNAL_TOOL_BAR (f))
488dd4c4
JD
8611 update_frame_tool_bar (f);
8612 return 0;
8613#endif
2311178e 8614
e037b9ec
GM
8615 /* If frame hasn't a tool-bar window or if it is zero-height, don't
8616 do anything. This means you must start with tool-bar-lines
5f5c8ee5 8617 non-zero to get the auto-sizing effect. Or in other words, you
e037b9ec
GM
8618 can turn off tool-bars by specifying tool-bar-lines zero. */
8619 if (!WINDOWP (f->tool_bar_window)
8620 || (w = XWINDOW (f->tool_bar_window),
da8b7f4f 8621 WINDOW_TOTAL_LINES (w) == 0))
5f5c8ee5 8622 return 0;
96a410bc 8623
e037b9ec
GM
8624 /* Set up an iterator for the tool-bar window. */
8625 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
5f5c8ee5 8626 it.first_visible_x = 0;
da8b7f4f 8627 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5 8628 row = it.glyph_row;
3450d04c 8629
e037b9ec
GM
8630 /* Build a string that represents the contents of the tool-bar. */
8631 build_desired_tool_bar_string (f);
8632 reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
3450d04c 8633
e037b9ec 8634 /* Display as many lines as needed to display all tool-bar items. */
5f5c8ee5 8635 while (it.current_y < it.last_visible_y)
e037b9ec 8636 display_tool_bar_line (&it);
3450d04c 8637
e037b9ec 8638 /* It doesn't make much sense to try scrolling in the tool-bar
5f5c8ee5
GM
8639 window, so don't do it. */
8640 w->desired_matrix->no_scrolling_p = 1;
8641 w->must_be_updated_p = 1;
3450d04c 8642
e037b9ec 8643 if (auto_resize_tool_bars_p)
5f5c8ee5
GM
8644 {
8645 int nlines;
6e33e6f0
GM
8646
8647 /* If we couldn't display everything, change the tool-bar's
8648 height. */
8649 if (IT_STRING_CHARPOS (it) < it.end_charpos)
8650 change_height_p = 1;
2311178e 8651
5f5c8ee5
GM
8652 /* If there are blank lines at the end, except for a partially
8653 visible blank line at the end that is smaller than
da8b7f4f 8654 FRAME_LINE_HEIGHT, change the tool-bar's height. */
5f5c8ee5
GM
8655 row = it.glyph_row - 1;
8656 if (!row->displays_text_p
da8b7f4f 8657 && row->height >= FRAME_LINE_HEIGHT (f))
5f5c8ee5
GM
8658 change_height_p = 1;
8659
e037b9ec
GM
8660 /* If row displays tool-bar items, but is partially visible,
8661 change the tool-bar's height. */
5f5c8ee5
GM
8662 if (row->displays_text_p
8663 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
8664 change_height_p = 1;
8665
e037b9ec 8666 /* Resize windows as needed by changing the `tool-bar-lines'
5f5c8ee5
GM
8667 frame parameter. */
8668 if (change_height_p
e037b9ec 8669 && (nlines = tool_bar_lines_needed (f),
da8b7f4f 8670 nlines != WINDOW_TOTAL_LINES (w)))
5f5c8ee5 8671 {
e037b9ec 8672 extern Lisp_Object Qtool_bar_lines;
5f5c8ee5 8673 Lisp_Object frame;
da8b7f4f 8674 int old_height = WINDOW_TOTAL_LINES (w);
2311178e 8675
5f5c8ee5
GM
8676 XSETFRAME (frame, f);
8677 clear_glyph_matrix (w->desired_matrix);
8678 Fmodify_frame_parameters (frame,
e037b9ec 8679 Fcons (Fcons (Qtool_bar_lines,
5f5c8ee5
GM
8680 make_number (nlines)),
8681 Qnil));
da8b7f4f 8682 if (WINDOW_TOTAL_LINES (w) != old_height)
e85ee976 8683 fonts_changed_p = 1;
5f5c8ee5
GM
8684 }
8685 }
3450d04c 8686
5f5c8ee5 8687 return change_height_p;
96a410bc 8688}
90adcf20 8689
5f5c8ee5 8690
e037b9ec
GM
8691/* Get information about the tool-bar item which is displayed in GLYPH
8692 on frame F. Return in *PROP_IDX the index where tool-bar item
7464726e 8693 properties start in F->tool_bar_items. Value is zero if
e037b9ec 8694 GLYPH doesn't display a tool-bar item. */
5f5c8ee5 8695
fa3c6b4d 8696static int
e037b9ec 8697tool_bar_item_info (f, glyph, prop_idx)
5f5c8ee5
GM
8698 struct frame *f;
8699 struct glyph *glyph;
8700 int *prop_idx;
90adcf20 8701{
5f5c8ee5
GM
8702 Lisp_Object prop;
8703 int success_p;
be676094
GM
8704 int charpos;
8705
8706 /* This function can be called asynchronously, which means we must
8707 exclude any possibility that Fget_text_property signals an
8708 error. */
2051c264 8709 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
be676094 8710 charpos = max (0, charpos);
2311178e 8711
5f5c8ee5
GM
8712 /* Get the text property `menu-item' at pos. The value of that
8713 property is the start index of this item's properties in
7464726e 8714 F->tool_bar_items. */
be676094 8715 prop = Fget_text_property (make_number (charpos),
e037b9ec 8716 Qmenu_item, f->current_tool_bar_string);
5f5c8ee5
GM
8717 if (INTEGERP (prop))
8718 {
8719 *prop_idx = XINT (prop);
8720 success_p = 1;
8721 }
8722 else
8723 success_p = 0;
90adcf20 8724
5f5c8ee5
GM
8725 return success_p;
8726}
2311178e 8727
fa3c6b4d
KS
8728\f
8729/* Get information about the tool-bar item at position X/Y on frame F.
8730 Return in *GLYPH a pointer to the glyph of the tool-bar item in
8731 the current matrix of the tool-bar window of F, or NULL if not
8732 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
8733 item in F->tool_bar_items. Value is
8734
8735 -1 if X/Y is not on a tool-bar item
8736 0 if X/Y is on the same item that was highlighted before.
8737 1 otherwise. */
8738
8739static int
8740get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
8741 struct frame *f;
8742 int x, y;
8743 struct glyph **glyph;
8744 int *hpos, *vpos, *prop_idx;
8745{
8746 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8747 struct window *w = XWINDOW (f->tool_bar_window);
8748 int area;
8749
8750 /* Find the glyph under X/Y. */
493fdc3c 8751 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
fa3c6b4d
KS
8752 if (*glyph == NULL)
8753 return -1;
8754
8755 /* Get the start of this tool-bar item's properties in
8756 f->tool_bar_items. */
8757 if (!tool_bar_item_info (f, *glyph, prop_idx))
8758 return -1;
8759
8760 /* Is mouse on the highlighted item? */
8761 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
8762 && *vpos >= dpyinfo->mouse_face_beg_row
8763 && *vpos <= dpyinfo->mouse_face_end_row
8764 && (*vpos > dpyinfo->mouse_face_beg_row
8765 || *hpos >= dpyinfo->mouse_face_beg_col)
8766 && (*vpos < dpyinfo->mouse_face_end_row
8767 || *hpos < dpyinfo->mouse_face_end_col
8768 || dpyinfo->mouse_face_past_end))
8769 return 0;
8770
8771 return 1;
8772}
8773
8774
8775/* EXPORT:
8776 Handle mouse button event on the tool-bar of frame F, at
8777 frame-relative coordinates X/Y. DOWN_P is 1 for a button press,
8778 0 for button release. MODIFIERS is event modifiers for button
8779 release. */
8780
8781void
8782handle_tool_bar_click (f, x, y, down_p, modifiers)
8783 struct frame *f;
8784 int x, y, down_p;
8785 unsigned int modifiers;
8786{
8787 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8788 struct window *w = XWINDOW (f->tool_bar_window);
8789 int hpos, vpos, prop_idx;
8790 struct glyph *glyph;
8791 Lisp_Object enabled_p;
8792
8793 /* If not on the highlighted tool-bar item, return. */
8794 frame_to_window_pixel_xy (w, &x, &y);
8795 if (get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
8796 return;
8797
8798 /* If item is disabled, do nothing. */
8799 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8800 if (NILP (enabled_p))
8801 return;
8802
8803 if (down_p)
8804 {
8805 /* Show item in pressed state. */
8806 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
8807 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
8808 last_tool_bar_item = prop_idx;
8809 }
8810 else
8811 {
8812 Lisp_Object key, frame;
8813 struct input_event event;
d86705ec 8814 EVENT_INIT (event);
fa3c6b4d
KS
8815
8816 /* Show item in released state. */
8817 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
8818 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
8819
8820 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
8821
8822 XSETFRAME (frame, f);
8823 event.kind = TOOL_BAR_EVENT;
8824 event.frame_or_window = frame;
8825 event.arg = frame;
8826 kbd_buffer_store_event (&event);
8827
8828 event.kind = TOOL_BAR_EVENT;
8829 event.frame_or_window = frame;
8830 event.arg = key;
8831 event.modifiers = modifiers;
8832 kbd_buffer_store_event (&event);
8833 last_tool_bar_item = -1;
8834 }
8835}
8836
8837
8838/* Possibly highlight a tool-bar item on frame F when mouse moves to
8839 tool-bar window-relative coordinates X/Y. Called from
8840 note_mouse_highlight. */
8841
8842static void
8843note_tool_bar_highlight (f, x, y)
8844 struct frame *f;
8845 int x, y;
8846{
8847 Lisp_Object window = f->tool_bar_window;
8848 struct window *w = XWINDOW (window);
8849 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
8850 int hpos, vpos;
8851 struct glyph *glyph;
8852 struct glyph_row *row;
8853 int i;
8854 Lisp_Object enabled_p;
8855 int prop_idx;
8856 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
8857 int mouse_down_p, rc;
8858
8859 /* Function note_mouse_highlight is called with negative x(y
8860 values when mouse moves outside of the frame. */
8861 if (x <= 0 || y <= 0)
8862 {
8863 clear_mouse_face (dpyinfo);
8864 return;
8865 }
8866
8867 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
8868 if (rc < 0)
8869 {
8870 /* Not on tool-bar item. */
8871 clear_mouse_face (dpyinfo);
8872 return;
8873 }
8874 else if (rc == 0)
8875 /* On same tool-bar item as before. */
8876 goto set_help_echo;
8877
8878 clear_mouse_face (dpyinfo);
8879
8880 /* Mouse is down, but on different tool-bar item? */
8881 mouse_down_p = (dpyinfo->grabbed
8882 && f == last_mouse_frame
8883 && FRAME_LIVE_P (f));
8884 if (mouse_down_p
8885 && last_tool_bar_item != prop_idx)
8886 return;
8887
8888 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
8889 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
8890
8891 /* If tool-bar item is not enabled, don't highlight it. */
8892 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
8893 if (!NILP (enabled_p))
8894 {
8895 /* Compute the x-position of the glyph. In front and past the
da8b7f4f 8896 image is a space. We include this in the highlighted area. */
fa3c6b4d
KS
8897 row = MATRIX_ROW (w->current_matrix, vpos);
8898 for (i = x = 0; i < hpos; ++i)
8899 x += row->glyphs[TEXT_AREA][i].pixel_width;
8900
8901 /* Record this as the current active region. */
8902 dpyinfo->mouse_face_beg_col = hpos;
8903 dpyinfo->mouse_face_beg_row = vpos;
8904 dpyinfo->mouse_face_beg_x = x;
8905 dpyinfo->mouse_face_beg_y = row->y;
8906 dpyinfo->mouse_face_past_end = 0;
8907
8908 dpyinfo->mouse_face_end_col = hpos + 1;
8909 dpyinfo->mouse_face_end_row = vpos;
8910 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
8911 dpyinfo->mouse_face_end_y = row->y;
8912 dpyinfo->mouse_face_window = window;
8913 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
8914
8915 /* Display it as active. */
8916 show_mouse_face (dpyinfo, draw);
8917 dpyinfo->mouse_face_image_state = draw;
8918 }
8919
8920 set_help_echo:
8921
8922 /* Set help_echo_string to a help string to display for this tool-bar item.
8923 XTread_socket does the rest. */
8924 help_echo_object = help_echo_window = Qnil;
8925 help_echo_pos = -1;
8926 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
8927 if (NILP (help_echo_string))
8928 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
8929}
8930
5f5c8ee5 8931#endif /* HAVE_WINDOW_SYSTEM */
ffbbc941
KS
8932
8933
8934\f
8935/***********************************************************************
8936 Fringes
8937 ***********************************************************************/
8938
8939#ifdef HAVE_WINDOW_SYSTEM
8940
88e6b646
KS
8941/* Notice that all bitmaps bits are "mirrored". */
8942
ffbbc941 8943/* An arrow like this: `<-'. */
88e6b646
KS
8944/*
8945 ...xx...
8946 ....xx..
8947 .....xx.
8948 ..xxxxxx
8949 ..xxxxxx
8950 .....xx.
8951 ....xx..
8952 ...xx...
8953*/
ffbbc941
KS
8954static unsigned char left_bits[] = {
8955 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
8956
88e6b646 8957
ffbbc941 8958/* Right truncation arrow bitmap `->'. */
88e6b646
KS
8959/*
8960 ...xx...
8961 ..xx....
8962 .xx.....
8963 xxxxxx..
8964 xxxxxx..
8965 .xx.....
8966 ..xx....
8967 ...xx...
8968*/
ffbbc941
KS
8969static unsigned char right_bits[] = {
8970 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
8971
88e6b646
KS
8972
8973/* Up arrow bitmap. */
8974/*
8975 ...xx...
8976 ..xxxx..
8977 .xxxxxx.
8978 xxxxxxxx
8979 ...xx...
8980 ...xx...
8981 ...xx...
8982 ...xx...
8983*/
8984static unsigned char up_arrow_bits[] = {
8985 0x18, 0x3c, 0x7e, 0xff, 0x18, 0x18, 0x18, 0x18};
8986
8987
8988/* Down arrow bitmap. */
8989/*
8990 ...xx...
8991 ...xx...
8992 ...xx...
8993 ...xx...
8994 xxxxxxxx
8995 .xxxxxx.
8996 ..xxxx..
8997 ...xx...
8998*/
8999static unsigned char down_arrow_bits[] = {
9000 0x18, 0x18, 0x18, 0x18, 0xff, 0x7e, 0x3c, 0x18};
9001
ffbbc941 9002/* Marker for continued lines. */
88e6b646
KS
9003/*
9004 ..xxxx..
9005 .xxxxx..
9006 xx......
9007 xxx..x..
9008 xxxxxx..
9009 .xxxxx..
9010 ..xxxx..
9011 .xxxxx..
9012*/
ffbbc941
KS
9013static unsigned char continued_bits[] = {
9014 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
9015
9016/* Marker for continuation lines. */
88e6b646
KS
9017/*
9018 ..xxxx..
9019 ..xxxxx.
9020 ......xx
9021 ..x..xxx
9022 ..xxxxxx
9023 ..xxxxx.
9024 ..xxxx..
9025 ..xxxxx.
9026*/
ffbbc941
KS
9027static unsigned char continuation_bits[] = {
9028 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
9029
9030/* Overlay arrow bitmap. A triangular arrow. */
88e6b646
KS
9031/*
9032 ......xx
9033 ....xxxx
9034 ...xxxxx
9035 ..xxxxxx
9036 ..xxxxxx
9037 ...xxxxx
9038 ....xxxx
9039 ......xx
9040*/
ffbbc941
KS
9041static unsigned char ov_bits[] = {
9042 0x03, 0x0f, 0x1f, 0x3f, 0x3f, 0x1f, 0x0f, 0x03};
9043
88e6b646
KS
9044
9045/* First line bitmap. An left-up angle. */
9046/*
9047 ..xxxxxx
9048 ..xxxxxx
9049 ......xx
9050 ......xx
9051 ......xx
9052 ......xx
9053 ......xx
9054 ........
9055*/
9056static unsigned char first_line_bits[] = {
9057 0x3f, 0x3f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00};
9058
9059
9060/* Last line bitmap. An left-down angle. */
9061/*
9062 ........
9063 xx......
9064 xx......
9065 xx......
9066 xx......
9067 xx......
9068 xxxxxx..
9069 xxxxxx..
9070*/
9071static unsigned char last_line_bits[] = {
9072 0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfc, 0xfc};
9073
9074/* Filled box cursor bitmap. A filled box; max 13 pixels high. */
9075/*
9076 .xxxxxxx
9077 .xxxxxxx
9078 .xxxxxxx
9079 .xxxxxxx
9080 .xxxxxxx
9081 .xxxxxxx
9082 .xxxxxxx
9083 .xxxxxxx
9084 .xxxxxxx
9085 .xxxxxxx
9086 .xxxxxxx
9087 .xxxxxxx
9088 .xxxxxxx
9089*/
9090static unsigned char filled_box_cursor_bits[] = {
9091 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f};
9092
9093/* Hollow box cursor bitmap. A hollow box; max 13 pixels high. */
9094/*
9095 .xxxxxxx
9096 .x.....x
9097 .x.....x
9098 .x.....x
9099 .x.....x
9100 .x.....x
9101 .x.....x
9102 .x.....x
9103 .x.....x
9104 .x.....x
9105 .x.....x
9106 .x.....x
9107 .xxxxxxx
9108*/
9109static unsigned char hollow_box_cursor_bits[] = {
9110 0x7f, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x7f};
9111
9112/* Bar cursor bitmap. A vertical bar; max 13 pixels high. */
9113/*
9114 ......xx
9115 ......xx
9116 ......xx
9117 ......xx
9118 ......xx
9119 ......xx
9120 ......xx
9121 ......xx
9122 ......xx
9123 ......xx
9124 ......xx
9125 ......xx
9126 ......xx
9127*/
9128static unsigned char bar_cursor_bits[] = {
9129 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
9130
9131/* HBar cursor bitmap. A horisontal bar; 2 pixels high. */
9132/*
9133 .xxxxxxx
9134 .xxxxxxx
9135*/
9136static unsigned char hbar_cursor_bits[] = {
9137 0x7f, 0x7f};
9138
9139
ffbbc941
KS
9140/* Bitmap drawn to indicate lines not displaying text if
9141 `indicate-empty-lines' is non-nil. */
9142static unsigned char zv_bits[] = {
9143 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9144 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9145 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9146 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9147 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9148 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9149 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
9150 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
9151
88e6b646
KS
9152/* Hollow square bitmap. */
9153/*
9154 .xxxxxx.
9155 .x....x.
9156 .x....x.
9157 .x....x.
9158 .x....x.
9159 .xxxxxx.
9160*/
9161static unsigned char hollow_square_bits[] = {
9162 0x7e, 0x42, 0x42, 0x42, 0x42, 0x7e};
9163
9164
ffbbc941
KS
9165struct fringe_bitmap fringe_bitmaps[MAX_FRINGE_BITMAPS] =
9166{
9167 { 0, 0, 0, NULL /* NO_FRINGE_BITMAP */ },
9168 { 8, sizeof (left_bits), 0, left_bits },
9169 { 8, sizeof (right_bits), 0, right_bits },
88e6b646
KS
9170 { 8, sizeof (up_arrow_bits), -1, up_arrow_bits },
9171 { 8, sizeof (down_arrow_bits), -2, down_arrow_bits },
ffbbc941
KS
9172 { 8, sizeof (continued_bits), 0, continued_bits },
9173 { 8, sizeof (continuation_bits), 0, continuation_bits },
9174 { 8, sizeof (ov_bits), 0, ov_bits },
88e6b646
KS
9175 { 8, sizeof (first_line_bits), -1, first_line_bits },
9176 { 8, sizeof (last_line_bits), -2, last_line_bits },
9177 { 8, sizeof (filled_box_cursor_bits), 0, filled_box_cursor_bits },
9178 { 8, sizeof (hollow_box_cursor_bits), 0, hollow_box_cursor_bits },
9179 { 8, sizeof (bar_cursor_bits), 0, bar_cursor_bits },
9180 { 8, sizeof (hbar_cursor_bits), -2, hbar_cursor_bits },
9181 { 8, sizeof (zv_bits), 3, zv_bits },
9182 { 8, sizeof (hollow_square_bits), 0, hollow_square_bits },
ffbbc941
KS
9183};
9184
9185
9186/* Draw the bitmap WHICH in one of the left or right fringes of
9187 window W. ROW is the glyph row for which to display the bitmap; it
9188 determines the vertical position at which the bitmap has to be
88e6b646
KS
9189 drawn.
9190 LEFT_P is 1 for left fringe, 0 for right fringe.
9191*/
ffbbc941 9192
88e6b646
KS
9193void
9194draw_fringe_bitmap (w, row, left_p)
ffbbc941
KS
9195 struct window *w;
9196 struct glyph_row *row;
ffbbc941
KS
9197 int left_p;
9198{
9199 struct frame *f = XFRAME (WINDOW_FRAME (w));
9200 struct draw_fringe_bitmap_params p;
88e6b646
KS
9201 enum fringe_bitmap_type which;
9202 int period;
9203
9204 if (left_p)
9205 which = row->left_fringe_bitmap;
9206 else if (!row->cursor_in_fringe_p)
9207 which = row->right_fringe_bitmap;
9208 else
9209 switch (w->phys_cursor_type)
9210 {
9211 case HOLLOW_BOX_CURSOR:
9212 if (row->visible_height >= sizeof(hollow_box_cursor_bits))
9213 which = HOLLOW_BOX_CURSOR_BITMAP;
9214 else
9215 which = HOLLOW_SQUARE_BITMAP;
9216 break;
9217 case FILLED_BOX_CURSOR:
9218 which = FILLED_BOX_CURSOR_BITMAP;
9219 break;
9220 case BAR_CURSOR:
9221 which = BAR_CURSOR_BITMAP;
9222 break;
9223 case HBAR_CURSOR:
9224 which = HBAR_CURSOR_BITMAP;
9225 break;
9226 case NO_CURSOR:
9227 default:
9228 w->phys_cursor_on_p = 0;
9229 row->cursor_in_fringe_p = 0;
9230 which = row->right_fringe_bitmap;
9231 break;
9232 }
9233
9234 period = fringe_bitmaps[which].period;
ffbbc941
KS
9235
9236 /* Convert row to frame coordinates. */
9237 p.y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9238
9239 p.which = which;
9240 p.wd = fringe_bitmaps[which].width;
9241
9242 p.h = fringe_bitmaps[which].height;
88e6b646 9243 p.dh = (period > 0 ? (p.y % period) : 0);
ffbbc941
KS
9244 p.h -= p.dh;
9245 /* Clip bitmap if too high. */
9246 if (p.h > row->height)
9247 p.h = row->height;
9248
9249 p.face = FACE_FROM_ID (f, FRINGE_FACE_ID);
9250 PREPARE_FACE_FOR_DISPLAY (f, p.face);
9251
9252 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
9253 the fringe. */
9254 p.bx = -1;
9255 if (left_p)
9256 {
da8b7f4f
KS
9257 int wd = WINDOW_LEFT_FRINGE_WIDTH (w);
9258 int x = window_box_left (w, (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
9259 ? LEFT_MARGIN_AREA
9260 : TEXT_AREA));
9261 if (p.wd > wd)
9262 p.wd = wd;
9263 p.x = x - p.wd - (wd - p.wd) / 2;
9264
9265 if (p.wd < wd || row->height > p.h)
ffbbc941
KS
9266 {
9267 /* If W has a vertical border to its left, don't draw over it. */
da8b7f4f
KS
9268 wd -= ((!WINDOW_LEFTMOST_P (w)
9269 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
9270 ? 1 : 0);
9271 p.bx = x - wd;
9272 p.nx = wd;
ffbbc941
KS
9273 }
9274 }
9275 else
9276 {
da8b7f4f
KS
9277 int x = window_box_right (w,
9278 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
9279 ? RIGHT_MARGIN_AREA
9280 : TEXT_AREA));
9281 int wd = WINDOW_RIGHT_FRINGE_WIDTH (w);
9282 if (p.wd > wd)
9283 p.wd = wd;
9284 p.x = x + (wd - p.wd) / 2;
ffbbc941
KS
9285 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
9286 the fringe. */
da8b7f4f 9287 if (p.wd < wd || row->height > p.h)
ffbbc941 9288 {
da8b7f4f
KS
9289 p.bx = x;
9290 p.nx = wd;
ffbbc941
KS
9291 }
9292 }
9293
9294 if (p.bx >= 0)
9295 {
da8b7f4f 9296 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
ffbbc941
KS
9297
9298 p.by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, row->y));
9299 p.ny = row->visible_height;
9300 }
9301
9302 /* Adjust y to the offset in the row to start drawing the bitmap. */
88e6b646
KS
9303 if (period == 0)
9304 p.y += (row->height - p.h) / 2;
9305 else if (period == -2)
9306 {
9307 p.h = fringe_bitmaps[which].height;
9308 p.y += (row->visible_height - p.h);
9309 }
ffbbc941
KS
9310
9311 rif->draw_fringe_bitmap (w, row, &p);
9312}
9313
9314/* Draw fringe bitmaps for glyph row ROW on window W. Call this
9315 function with input blocked. */
9316
9317void
9318draw_row_fringe_bitmaps (w, row)
9319 struct window *w;
9320 struct glyph_row *row;
9321{
ffbbc941
KS
9322 xassert (interrupt_input_blocked);
9323
9324 /* If row is completely invisible, because of vscrolling, we
9325 don't have to draw anything. */
9326 if (row->visible_height <= 0)
9327 return;
9328
da8b7f4f 9329 if (WINDOW_LEFT_FRINGE_WIDTH (w) != 0)
88e6b646 9330 draw_fringe_bitmap (w, row, 1);
ffbbc941 9331
da8b7f4f 9332 if (WINDOW_RIGHT_FRINGE_WIDTH (w) != 0)
88e6b646
KS
9333 draw_fringe_bitmap (w, row, 0);
9334}
9335
9336/* Draw the fringes of window W. Only fringes for rows marked for
9337 update in redraw_fringe_bitmaps_p are drawn. */
ffbbc941 9338
88e6b646
KS
9339void
9340draw_window_fringes (w)
9341 struct window *w;
9342{
9343 struct glyph_row *row;
9344 int yb = window_text_bottom_y (w);
9345 int nrows = w->current_matrix->nrows;
9346 int y = 0, rn;
9347
9348 if (w->pseudo_window_p)
9349 return;
9350
9351 for (y = 0, rn = 0, row = w->current_matrix->rows;
9352 y < yb && rn < nrows;
9353 y += row->height, ++row, ++rn)
9354 {
9355 if (!row->redraw_fringe_bitmaps_p)
9356 continue;
9357 draw_row_fringe_bitmaps (w, row);
9358 row->redraw_fringe_bitmaps_p = 0;
ffbbc941
KS
9359 }
9360}
9361
9362
564946b6
KS
9363/* Compute actual fringe widths for frame F.
9364
9365 If REDRAW is 1, redraw F if the fringe settings was actually
9366 modified and F is visible.
9367
9368 Since the combined left and right fringe must occupy an integral
9369 number of columns, we may need to add some pixels to each fringe.
9370 Typically, we add an equal amount (+/- 1 pixel) to each fringe,
9371 but a negative width value is taken literally (after negating it).
9372
9373 We never make the fringes narrower than specified. It is planned
9374 to make fringe bitmaps customizable and expandable, and at that
9375 time, the user will typically specify the minimum number of pixels
9376 needed for his bitmaps, so we shouldn't select anything less than
9377 what is specified.
9378*/
ffbbc941
KS
9379
9380void
9381compute_fringe_widths (f, redraw)
9382 struct frame *f;
9383 int redraw;
9384{
da8b7f4f
KS
9385 int o_left = FRAME_LEFT_FRINGE_WIDTH (f);
9386 int o_right = FRAME_RIGHT_FRINGE_WIDTH (f);
9387 int o_cols = FRAME_FRINGE_COLS (f);
ffbbc941
KS
9388
9389 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9390 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9391 int left_fringe_width, right_fringe_width;
9392
9393 if (!NILP (left_fringe))
9394 left_fringe = Fcdr (left_fringe);
9395 if (!NILP (right_fringe))
9396 right_fringe = Fcdr (right_fringe);
9397
9398 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9399 XINT (left_fringe));
9400 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9401 XINT (right_fringe));
9402
9403 if (left_fringe_width || right_fringe_width)
9404 {
9405 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9406 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9407 int conf_wid = left_wid + right_wid;
da8b7f4f 9408 int font_wid = FRAME_COLUMN_WIDTH (f);
ffbbc941
KS
9409 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
9410 int real_wid = cols * font_wid;
9411 if (left_wid && right_wid)
9412 {
9413 if (left_fringe_width < 0)
9414 {
9415 /* Left fringe width is fixed, adjust right fringe if necessary */
da8b7f4f
KS
9416 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid;
9417 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid - left_wid;
ffbbc941
KS
9418 }
9419 else if (right_fringe_width < 0)
9420 {
9421 /* Right fringe width is fixed, adjust left fringe if necessary */
da8b7f4f
KS
9422 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid - right_wid;
9423 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid;
ffbbc941
KS
9424 }
9425 else
9426 {
9427 /* Adjust both fringes with an equal amount.
9428 Note that we are doing integer arithmetic here, so don't
9429 lose a pixel if the total width is an odd number. */
9430 int fill = real_wid - conf_wid;
da8b7f4f
KS
9431 FRAME_LEFT_FRINGE_WIDTH (f) = left_wid + fill/2;
9432 FRAME_RIGHT_FRINGE_WIDTH (f) = right_wid + fill - fill/2;
ffbbc941
KS
9433 }
9434 }
9435 else if (left_fringe_width)
9436 {
da8b7f4f
KS
9437 FRAME_LEFT_FRINGE_WIDTH (f) = real_wid;
9438 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
ffbbc941
KS
9439 }
9440 else
9441 {
da8b7f4f
KS
9442 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
9443 FRAME_RIGHT_FRINGE_WIDTH (f) = real_wid;
ffbbc941 9444 }
da8b7f4f 9445 FRAME_FRINGE_COLS (f) = cols;
ffbbc941
KS
9446 }
9447 else
9448 {
da8b7f4f
KS
9449 FRAME_LEFT_FRINGE_WIDTH (f) = 0;
9450 FRAME_RIGHT_FRINGE_WIDTH (f) = 0;
9451 FRAME_FRINGE_COLS (f) = 0;
ffbbc941
KS
9452 }
9453
9454 if (redraw && FRAME_VISIBLE_P (f))
da8b7f4f
KS
9455 if (o_left != FRAME_LEFT_FRINGE_WIDTH (f) ||
9456 o_right != FRAME_RIGHT_FRINGE_WIDTH (f) ||
9457 o_cols != FRAME_FRINGE_COLS (f))
ffbbc941
KS
9458 redraw_frame (f);
9459}
9460
9461#endif /* HAVE_WINDOW_SYSTEM */
90adcf20 9462
feb0c42f 9463
5f5c8ee5
GM
9464\f
9465/************************************************************************
9466 Horizontal scrolling
9467 ************************************************************************/
feb0c42f 9468
5f5c8ee5
GM
9469static int hscroll_window_tree P_ ((Lisp_Object));
9470static int hscroll_windows P_ ((Lisp_Object));
feb0c42f 9471
5f5c8ee5
GM
9472/* For all leaf windows in the window tree rooted at WINDOW, set their
9473 hscroll value so that PT is (i) visible in the window, and (ii) so
9474 that it is not within a certain margin at the window's left and
9475 right border. Value is non-zero if any window's hscroll has been
9476 changed. */
9477
9478static int
9479hscroll_window_tree (window)
9480 Lisp_Object window;
9481{
9482 int hscrolled_p = 0;
e76d28d5 9483 int hscroll_relative_p = FLOATP (Vhscroll_step);
1df7e8f0
EZ
9484 int hscroll_step_abs = 0;
9485 double hscroll_step_rel = 0;
9486
9487 if (hscroll_relative_p)
9488 {
e76d28d5 9489 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
1df7e8f0
EZ
9490 if (hscroll_step_rel < 0)
9491 {
9492 hscroll_relative_p = 0;
9493 hscroll_step_abs = 0;
9494 }
9495 }
e76d28d5 9496 else if (INTEGERP (Vhscroll_step))
1df7e8f0 9497 {
e76d28d5 9498 hscroll_step_abs = XINT (Vhscroll_step);
1df7e8f0
EZ
9499 if (hscroll_step_abs < 0)
9500 hscroll_step_abs = 0;
9501 }
9502 else
9503 hscroll_step_abs = 0;
9504
5f5c8ee5 9505 while (WINDOWP (window))
90adcf20 9506 {
5f5c8ee5 9507 struct window *w = XWINDOW (window);
1df7e8f0 9508
5f5c8ee5
GM
9509 if (WINDOWP (w->hchild))
9510 hscrolled_p |= hscroll_window_tree (w->hchild);
9511 else if (WINDOWP (w->vchild))
9512 hscrolled_p |= hscroll_window_tree (w->vchild);
9513 else if (w->cursor.vpos >= 0)
9514 {
da8b7f4f
KS
9515 int h_margin;
9516 int text_area_width;
92a90e89
GM
9517 struct glyph_row *current_cursor_row
9518 = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
9519 struct glyph_row *desired_cursor_row
9520 = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
9521 struct glyph_row *cursor_row
9522 = (desired_cursor_row->enabled_p
9523 ? desired_cursor_row
9524 : current_cursor_row);
a2725ab2 9525
da8b7f4f 9526 text_area_width = window_box_width (w, TEXT_AREA);
90adcf20 9527
5f5c8ee5 9528 /* Scroll when cursor is inside this scroll margin. */
da8b7f4f 9529 h_margin = hscroll_margin * WINDOW_FRAME_COLUMN_WIDTH (w);
1df7e8f0 9530
5f5c8ee5 9531 if ((XFASTINT (w->hscroll)
e76d28d5 9532 && w->cursor.x <= h_margin)
92a90e89
GM
9533 || (cursor_row->enabled_p
9534 && cursor_row->truncated_on_right_p
e76d28d5 9535 && (w->cursor.x >= text_area_width - h_margin)))
08b610e4 9536 {
5f5c8ee5
GM
9537 struct it it;
9538 int hscroll;
9539 struct buffer *saved_current_buffer;
9540 int pt;
1df7e8f0 9541 int wanted_x;
5f5c8ee5
GM
9542
9543 /* Find point in a display of infinite width. */
9544 saved_current_buffer = current_buffer;
9545 current_buffer = XBUFFER (w->buffer);
1df7e8f0 9546
5f5c8ee5
GM
9547 if (w == XWINDOW (selected_window))
9548 pt = BUF_PT (current_buffer);
9549 else
08b610e4 9550 {
5f5c8ee5
GM
9551 pt = marker_position (w->pointm);
9552 pt = max (BEGV, pt);
9553 pt = min (ZV, pt);
9554 }
9555
9556 /* Move iterator to pt starting at cursor_row->start in
9557 a line with infinite width. */
9558 init_to_row_start (&it, w, cursor_row);
9559 it.last_visible_x = INFINITY;
9560 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
9561 current_buffer = saved_current_buffer;
9562
1df7e8f0
EZ
9563 /* Position cursor in window. */
9564 if (!hscroll_relative_p && hscroll_step_abs == 0)
9565 hscroll = max (0, it.current_x - text_area_width / 2)
da8b7f4f 9566 / FRAME_COLUMN_WIDTH (it.f);
e76d28d5 9567 else if (w->cursor.x >= text_area_width - h_margin)
1df7e8f0
EZ
9568 {
9569 if (hscroll_relative_p)
9570 wanted_x = text_area_width * (1 - hscroll_step_rel)
e76d28d5 9571 - h_margin;
1df7e8f0
EZ
9572 else
9573 wanted_x = text_area_width
da8b7f4f 9574 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9575 - h_margin;
1df7e8f0 9576 hscroll
da8b7f4f 9577 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0
EZ
9578 }
9579 else
9580 {
9581 if (hscroll_relative_p)
9582 wanted_x = text_area_width * hscroll_step_rel
e76d28d5 9583 + h_margin;
1df7e8f0 9584 else
da8b7f4f 9585 wanted_x = hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
e76d28d5 9586 + h_margin;
1df7e8f0 9587 hscroll
da8b7f4f 9588 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
1df7e8f0 9589 }
3172f70b 9590 hscroll = max (hscroll, XFASTINT (w->min_hscroll));
5f5c8ee5
GM
9591
9592 /* Don't call Fset_window_hscroll if value hasn't
9593 changed because it will prevent redisplay
9594 optimizations. */
9595 if (XFASTINT (w->hscroll) != hscroll)
9596 {
3172f70b
GM
9597 XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
9598 w->hscroll = make_number (hscroll);
5f5c8ee5 9599 hscrolled_p = 1;
08b610e4 9600 }
08b610e4 9601 }
08b610e4 9602 }
a2725ab2 9603
5f5c8ee5 9604 window = w->next;
90adcf20 9605 }
cd6dfed6 9606
5f5c8ee5
GM
9607 /* Value is non-zero if hscroll of any leaf window has been changed. */
9608 return hscrolled_p;
9609}
9610
9611
9612/* Set hscroll so that cursor is visible and not inside horizontal
9613 scroll margins for all windows in the tree rooted at WINDOW. See
9614 also hscroll_window_tree above. Value is non-zero if any window's
9615 hscroll has been changed. If it has, desired matrices on the frame
9616 of WINDOW are cleared. */
9617
9618static int
9619hscroll_windows (window)
9620 Lisp_Object window;
9621{
d475bcb8 9622 int hscrolled_p;
2311178e 9623
d475bcb8
GM
9624 if (automatic_hscrolling_p)
9625 {
9626 hscrolled_p = hscroll_window_tree (window);
9627 if (hscrolled_p)
9628 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
9629 }
9630 else
9631 hscrolled_p = 0;
5f5c8ee5 9632 return hscrolled_p;
90adcf20 9633}
5f5c8ee5
GM
9634
9635
90adcf20 9636\f
5f5c8ee5
GM
9637/************************************************************************
9638 Redisplay
9639 ************************************************************************/
9640
9641/* Variables holding some state of redisplay if GLYPH_DEBUG is defined
9642 to a non-zero value. This is sometimes handy to have in a debugger
9643 session. */
9644
9645#if GLYPH_DEBUG
a2889657 9646
5f5c8ee5
GM
9647/* First and last unchanged row for try_window_id. */
9648
9649int debug_first_unchanged_at_end_vpos;
9650int debug_last_unchanged_at_beg_vpos;
9651
9652/* Delta vpos and y. */
9653
9654int debug_dvpos, debug_dy;
9655
9656/* Delta in characters and bytes for try_window_id. */
9657
9658int debug_delta, debug_delta_bytes;
9659
9660/* Values of window_end_pos and window_end_vpos at the end of
9661 try_window_id. */
9662
31ade731 9663EMACS_INT debug_end_pos, debug_end_vpos;
5f5c8ee5
GM
9664
9665/* Append a string to W->desired_matrix->method. FMT is a printf
9666 format string. A1...A9 are a supplement for a variable-length
9667 argument list. If trace_redisplay_p is non-zero also printf the
9668 resulting string to stderr. */
9669
9670static void
9671debug_method_add (w, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
9672 struct window *w;
9673 char *fmt;
9674 int a1, a2, a3, a4, a5, a6, a7, a8, a9;
9675{
9676 char buffer[512];
9677 char *method = w->desired_matrix->method;
9678 int len = strlen (method);
9679 int size = sizeof w->desired_matrix->method;
9680 int remaining = size - len - 1;
9681
9682 sprintf (buffer, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
9683 if (len && remaining)
9684 {
9685 method[len] = '|';
9686 --remaining, ++len;
9687 }
2311178e 9688
5f5c8ee5
GM
9689 strncpy (method + len, buffer, remaining);
9690
9691 if (trace_redisplay_p)
9692 fprintf (stderr, "%p (%s): %s\n",
9693 w,
9694 ((BUFFERP (w->buffer)
9695 && STRINGP (XBUFFER (w->buffer)->name))
2051c264 9696 ? (char *) SDATA (XBUFFER (w->buffer)->name)
5f5c8ee5
GM
9697 : "no buffer"),
9698 buffer);
9699}
a2889657 9700
5f5c8ee5 9701#endif /* GLYPH_DEBUG */
90adcf20 9702
a2889657 9703
5f5c8ee5
GM
9704/* Value is non-zero if all changes in window W, which displays
9705 current_buffer, are in the text between START and END. START is a
9706 buffer position, END is given as a distance from Z. Used in
9707 redisplay_internal for display optimization. */
9708
9709static INLINE int
9710text_outside_line_unchanged_p (w, start, end)
9711 struct window *w;
9712 int start, end;
9713{
9714 int unchanged_p = 1;
2311178e 9715
5f5c8ee5
GM
9716 /* If text or overlays have changed, see where. */
9717 if (XFASTINT (w->last_modified) < MODIFF
9718 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
9719 {
9720 /* Gap in the line? */
9721 if (GPT < start || Z - GPT < end)
9722 unchanged_p = 0;
9723
9724 /* Changes start in front of the line, or end after it? */
9725 if (unchanged_p
9142dd5b
GM
9726 && (BEG_UNCHANGED < start - 1
9727 || END_UNCHANGED < end))
5f5c8ee5 9728 unchanged_p = 0;
2311178e 9729
5f5c8ee5
GM
9730 /* If selective display, can't optimize if changes start at the
9731 beginning of the line. */
9732 if (unchanged_p
9733 && INTEGERP (current_buffer->selective_display)
9734 && XINT (current_buffer->selective_display) > 0
9142dd5b 9735 && (BEG_UNCHANGED < start || GPT <= start))
5f5c8ee5 9736 unchanged_p = 0;
47d57b22
GM
9737
9738 /* If there are overlays at the start or end of the line, these
9739 may have overlay strings with newlines in them. A change at
9740 START, for instance, may actually concern the display of such
9741 overlay strings as well, and they are displayed on different
9742 lines. So, quickly rule out this case. (For the future, it
9743 might be desirable to implement something more telling than
9744 just BEG/END_UNCHANGED.) */
9745 if (unchanged_p)
9746 {
9747 if (BEG + BEG_UNCHANGED == start
9748 && overlay_touches_p (start))
9749 unchanged_p = 0;
9750 if (END_UNCHANGED == end
9751 && overlay_touches_p (Z - end))
9752 unchanged_p = 0;
9753 }
5f5c8ee5
GM
9754 }
9755
9756 return unchanged_p;
9757}
9758
9759
9760/* Do a frame update, taking possible shortcuts into account. This is
9761 the main external entry point for redisplay.
9762
9763 If the last redisplay displayed an echo area message and that message
9764 is no longer requested, we clear the echo area or bring back the
9765 mini-buffer if that is in use. */
20de20dc 9766
a2889657
JB
9767void
9768redisplay ()
e9874cee
RS
9769{
9770 redisplay_internal (0);
9771}
9772
47d57b22 9773
260a86a0
KH
9774/* Return 1 if point moved out of or into a composition. Otherwise
9775 return 0. PREV_BUF and PREV_PT are the last point buffer and
9776 position. BUF and PT are the current point buffer and position. */
9777
9778int
9779check_point_in_composition (prev_buf, prev_pt, buf, pt)
9780 struct buffer *prev_buf, *buf;
9781 int prev_pt, pt;
9782{
9783 int start, end;
9784 Lisp_Object prop;
9785 Lisp_Object buffer;
9786
9787 XSETBUFFER (buffer, buf);
9788 /* Check a composition at the last point if point moved within the
9789 same buffer. */
9790 if (prev_buf == buf)
9791 {
9792 if (prev_pt == pt)
9793 /* Point didn't move. */
9794 return 0;
2311178e 9795
260a86a0
KH
9796 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
9797 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
9798 && COMPOSITION_VALID_P (start, end, prop)
9799 && start < prev_pt && end > prev_pt)
9800 /* The last point was within the composition. Return 1 iff
9801 point moved out of the composition. */
9802 return (pt <= start || pt >= end);
9803 }
9804
9805 /* Check a composition at the current point. */
9806 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
9807 && find_composition (pt, -1, &start, &end, &prop, buffer)
9808 && COMPOSITION_VALID_P (start, end, prop)
9809 && start < pt && end > pt);
9810}
5f5c8ee5 9811
47d57b22 9812
9142dd5b
GM
9813/* Reconsider the setting of B->clip_changed which is displayed
9814 in window W. */
9815
9816static INLINE void
9817reconsider_clip_changes (w, b)
9818 struct window *w;
9819 struct buffer *b;
9820{
c62c1bb5 9821 if (b->clip_changed
9142dd5b
GM
9822 && !NILP (w->window_end_valid)
9823 && w->current_matrix->buffer == b
9824 && w->current_matrix->zv == BUF_ZV (b)
9825 && w->current_matrix->begv == BUF_BEGV (b))
9826 b->clip_changed = 0;
260a86a0
KH
9827
9828 /* If display wasn't paused, and W is not a tool bar window, see if
9829 point has been moved into or out of a composition. In that case,
9830 we set b->clip_changed to 1 to force updating the screen. If
9831 b->clip_changed has already been set to 1, we can skip this
9832 check. */
9833 if (!b->clip_changed
9834 && BUFFERP (w->buffer) && !NILP (w->window_end_valid))
9835 {
9836 int pt;
9837
9838 if (w == XWINDOW (selected_window))
9839 pt = BUF_PT (current_buffer);
9840 else
9841 pt = marker_position (w->pointm);
9842
9843 if ((w->current_matrix->buffer != XBUFFER (w->buffer)
6fc556fd 9844 || pt != XINT (w->last_point))
260a86a0 9845 && check_point_in_composition (w->current_matrix->buffer,
6fc556fd 9846 XINT (w->last_point),
260a86a0
KH
9847 XBUFFER (w->buffer), pt))
9848 b->clip_changed = 1;
9849 }
9142dd5b 9850}
aac2d8b2 9851\f
dd429b03
KH
9852
9853/* Select FRAME to forward the values of frame-local variables into C
9854 variables so that the redisplay routines can access those values
9855 directly. */
9856
9857static void
9858select_frame_for_redisplay (frame)
9859 Lisp_Object frame;
9860{
9861 Lisp_Object tail, sym, val;
9862 Lisp_Object old = selected_frame;
9863
9864 selected_frame = frame;
9865
9866 for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
9867 if (CONSP (XCAR (tail))
9868 && (sym = XCAR (XCAR (tail)),
9869 SYMBOLP (sym))
9870 && (sym = indirect_variable (sym),
9871 val = SYMBOL_VALUE (sym),
9872 (BUFFER_LOCAL_VALUEP (val)
9873 || SOME_BUFFER_LOCAL_VALUEP (val)))
9874 && XBUFFER_LOCAL_VALUE (val)->check_frame)
9875 Fsymbol_value (sym);
9876
9877 for (tail = XFRAME (old)->param_alist; CONSP (tail); tail = XCDR (tail))
9878 if (CONSP (XCAR (tail))
9879 && (sym = XCAR (XCAR (tail)),
9880 SYMBOLP (sym))
9881 && (sym = indirect_variable (sym),
9882 val = SYMBOL_VALUE (sym),
9883 (BUFFER_LOCAL_VALUEP (val)
9884 || SOME_BUFFER_LOCAL_VALUEP (val)))
9885 && XBUFFER_LOCAL_VALUE (val)->check_frame)
9886 Fsymbol_value (sym);
9887}
9888
9889
aac2d8b2
RS
9890#define STOP_POLLING \
9891do { if (! polling_stopped_here) stop_polling (); \
9892 polling_stopped_here = 1; } while (0)
9893
9894#define RESUME_POLLING \
9895do { if (polling_stopped_here) start_polling (); \
9896 polling_stopped_here = 0; } while (0)
9142dd5b
GM
9897
9898
5f5c8ee5
GM
9899/* If PRESERVE_ECHO_AREA is nonzero, it means this redisplay is not in
9900 response to any user action; therefore, we should preserve the echo
9901 area. (Actually, our caller does that job.) Perhaps in the future
9902 avoid recentering windows if it is not necessary; currently that
9903 causes some problems. */
e9874cee
RS
9904
9905static void
9906redisplay_internal (preserve_echo_area)
9907 int preserve_echo_area;
a2889657 9908{
5f5c8ee5
GM
9909 struct window *w = XWINDOW (selected_window);
9910 struct frame *f = XFRAME (w->frame);
9911 int pause;
a2889657 9912 int must_finish = 0;
5f5c8ee5 9913 struct text_pos tlbufpos, tlendpos;
89819bdd 9914 int number_of_visible_frames;
28514cd9 9915 int count;
886bd6f2 9916 struct frame *sf = SELECTED_FRAME ();
aac2d8b2 9917 int polling_stopped_here = 0;
a2889657 9918
5f5c8ee5
GM
9919 /* Non-zero means redisplay has to consider all windows on all
9920 frames. Zero means, only selected_window is considered. */
9921 int consider_all_windows_p;
2311178e 9922
5f5c8ee5
GM
9923 TRACE ((stderr, "redisplay_internal %d\n", redisplaying_p));
9924
9925 /* No redisplay if running in batch mode or frame is not yet fully
9926 initialized, or redisplay is explicitly turned off by setting
9927 Vinhibit_redisplay. */
9928 if (noninteractive
9929 || !NILP (Vinhibit_redisplay)
9930 || !f->glyphs_initialized_p)
a2889657
JB
9931 return;
9932
5f5c8ee5
GM
9933 /* The flag redisplay_performed_directly_p is set by
9934 direct_output_for_insert when it already did the whole screen
9935 update necessary. */
9936 if (redisplay_performed_directly_p)
9937 {
9938 redisplay_performed_directly_p = 0;
9939 if (!hscroll_windows (selected_window))
9940 return;
9941 }
9942
488dd4c4 9943#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
15f0cf78
RS
9944 if (popup_activated ())
9945 return;
9946#endif
9947
28514cd9 9948 /* I don't think this happens but let's be paranoid. */
5f5c8ee5 9949 if (redisplaying_p)
735c094c
KH
9950 return;
9951
28514cd9
GM
9952 /* Record a function that resets redisplaying_p to its old value
9953 when we leave this function. */
331379bf 9954 count = SPECPDL_INDEX ();
dd429b03
KH
9955 record_unwind_protect (unwind_redisplay,
9956 Fcons (make_number (redisplaying_p), selected_frame));
28514cd9 9957 ++redisplaying_p;
26683087 9958 specbind (Qinhibit_free_realized_faces, Qnil);
2311178e 9959
8b32d885 9960 retry:
bd9d0f3f 9961 pause = 0;
9142dd5b
GM
9962 reconsider_clip_changes (w, current_buffer);
9963
5f5c8ee5
GM
9964 /* If new fonts have been loaded that make a glyph matrix adjustment
9965 necessary, do it. */
9966 if (fonts_changed_p)
9967 {
9968 adjust_glyphs (NULL);
9969 ++windows_or_buffers_changed;
9970 fonts_changed_p = 0;
9971 }
9972
6961e0c1
GM
9973 /* If face_change_count is non-zero, init_iterator will free all
9974 realized faces, which includes the faces referenced from current
9975 matrices. So, we can't reuse current matrices in this case. */
9976 if (face_change_count)
9977 ++windows_or_buffers_changed;
9978
886bd6f2
GM
9979 if (! FRAME_WINDOW_P (sf)
9980 && previous_terminal_frame != sf)
20de20dc 9981 {
5f5c8ee5
GM
9982 /* Since frames on an ASCII terminal share the same display
9983 area, displaying a different frame means redisplay the whole
9984 thing. */
20de20dc 9985 windows_or_buffers_changed++;
886bd6f2
GM
9986 SET_FRAME_GARBAGED (sf);
9987 XSETFRAME (Vterminal_frame, sf);
20de20dc 9988 }
886bd6f2 9989 previous_terminal_frame = sf;
20de20dc 9990
5f5c8ee5
GM
9991 /* Set the visible flags for all frames. Do this before checking
9992 for resized or garbaged frames; they want to know if their frames
9993 are visible. See the comment in frame.h for
9994 FRAME_SAMPLE_VISIBILITY. */
d724d989 9995 {
35f56f96 9996 Lisp_Object tail, frame;
d724d989 9997
89819bdd
RS
9998 number_of_visible_frames = 0;
9999
35f56f96 10000 FOR_EACH_FRAME (tail, frame)
f82aff7c 10001 {
5f5c8ee5 10002 struct frame *f = XFRAME (frame);
2311178e 10003
5f5c8ee5
GM
10004 FRAME_SAMPLE_VISIBILITY (f);
10005 if (FRAME_VISIBLE_P (f))
10006 ++number_of_visible_frames;
10007 clear_desired_matrices (f);
f82aff7c 10008 }
d724d989
JB
10009 }
10010
44fa5b1e 10011 /* Notice any pending interrupt request to change frame size. */
c6e89d6c 10012 do_pending_window_change (1);
a2889657 10013
5f5c8ee5 10014 /* Clear frames marked as garbaged. */
44fa5b1e 10015 if (frame_garbaged)
c6e89d6c 10016 clear_garbaged_frames ();
a2889657 10017
e037b9ec 10018 /* Build menubar and tool-bar items. */
f82aff7c
RS
10019 prepare_menu_bars ();
10020
28995e67 10021 if (windows_or_buffers_changed)
a2889657
JB
10022 update_mode_lines++;
10023
538f13d4
RS
10024 /* Detect case that we need to write or remove a star in the mode line. */
10025 if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
a2889657
JB
10026 {
10027 w->update_mode_line = Qt;
10028 if (buffer_shared > 1)
10029 update_mode_lines++;
10030 }
10031
5f5c8ee5 10032 /* If %c is in the mode line, update it if needed. */
28995e67
RS
10033 if (!NILP (w->column_number_displayed)
10034 /* This alternative quickly identifies a common case
10035 where no change is needed. */
10036 && !(PT == XFASTINT (w->last_point)
8850a573
RS
10037 && XFASTINT (w->last_modified) >= MODIFF
10038 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
10039 && (XFASTINT (w->column_number_displayed)
10040 != (int) current_column ())) /* iftc */
10041 w->update_mode_line = Qt;
28995e67 10042
44fa5b1e 10043 FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
a2889657 10044
5f5c8ee5
GM
10045 /* The variable buffer_shared is set in redisplay_window and
10046 indicates that we redisplay a buffer in different windows. See
10047 there. */
5fb96e96
RS
10048 consider_all_windows_p = (update_mode_lines || buffer_shared > 1
10049 || cursor_type_changed);
a2889657
JB
10050
10051 /* If specs for an arrow have changed, do thorough redisplay
10052 to ensure we remove any arrow that should no longer exist. */
d45de95b 10053 if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
ded34426 10054 || ! EQ (Voverlay_arrow_string, last_arrow_string))
5f5c8ee5 10055 consider_all_windows_p = windows_or_buffers_changed = 1;
a2889657 10056
90adcf20
RS
10057 /* Normally the message* functions will have already displayed and
10058 updated the echo area, but the frame may have been trashed, or
10059 the update may have been preempted, so display the echo area
6e019995 10060 again here. Checking message_cleared_p captures the case that
c6e89d6c 10061 the echo area should be cleared. */
96d5e9a0
GM
10062 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
10063 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
3fa69ee7
GM
10064 || (message_cleared_p
10065 && minibuf_level == 0
10066 /* If the mini-window is currently selected, this means the
10067 echo-area doesn't show through. */
10068 && !MINI_WINDOW_P (XWINDOW (selected_window))))
90adcf20 10069 {
c6e89d6c 10070 int window_height_changed_p = echo_area_display (0);
90adcf20 10071 must_finish = 1;
6e019995
GM
10072
10073 /* If we don't display the current message, don't clear the
10074 message_cleared_p flag, because, if we did, we wouldn't clear
10075 the echo area in the next redisplay which doesn't preserve
10076 the echo area. */
10077 if (!display_last_displayed_message_p)
10078 message_cleared_p = 0;
2311178e 10079
c6e89d6c
GM
10080 if (fonts_changed_p)
10081 goto retry;
10082 else if (window_height_changed_p)
10083 {
10084 consider_all_windows_p = 1;
10085 ++update_mode_lines;
10086 ++windows_or_buffers_changed;
2311178e 10087
9142dd5b
GM
10088 /* If window configuration was changed, frames may have been
10089 marked garbaged. Clear them or we will experience
10090 surprises wrt scrolling. */
10091 if (frame_garbaged)
10092 clear_garbaged_frames ();
c6e89d6c 10093 }
90adcf20 10094 }
97a36635 10095 else if (EQ (selected_window, minibuf_window)
dd2eb166
GM
10096 && (current_buffer->clip_changed
10097 || XFASTINT (w->last_modified) < MODIFF
10098 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF)
92a90e89 10099 && resize_mini_window (w, 0))
c6e89d6c
GM
10100 {
10101 /* Resized active mini-window to fit the size of what it is
dd2eb166
GM
10102 showing if its contents might have changed. */
10103 must_finish = 1;
10104 consider_all_windows_p = 1;
c6e89d6c 10105 ++windows_or_buffers_changed;
dd2eb166 10106 ++update_mode_lines;
2311178e 10107
9142dd5b
GM
10108 /* If window configuration was changed, frames may have been
10109 marked garbaged. Clear them or we will experience
10110 surprises wrt scrolling. */
10111 if (frame_garbaged)
10112 clear_garbaged_frames ();
c6e89d6c 10113 }
2311178e 10114
90adcf20 10115
5f5c8ee5
GM
10116 /* If showing the region, and mark has changed, we must redisplay
10117 the whole window. The assignment to this_line_start_pos prevents
10118 the optimization directly below this if-statement. */
bd66d1ba
RS
10119 if (((!NILP (Vtransient_mark_mode)
10120 && !NILP (XBUFFER (w->buffer)->mark_active))
10121 != !NILP (w->region_showing))
82d04750
JB
10122 || (!NILP (w->region_showing)
10123 && !EQ (w->region_showing,
10124 Fmarker_position (XBUFFER (w->buffer)->mark))))
5f5c8ee5
GM
10125 CHARPOS (this_line_start_pos) = 0;
10126
10127 /* Optimize the case that only the line containing the cursor in the
10128 selected window has changed. Variables starting with this_ are
10129 set in display_line and record information about the line
10130 containing the cursor. */
10131 tlbufpos = this_line_start_pos;
10132 tlendpos = this_line_end_pos;
10133 if (!consider_all_windows_p
10134 && CHARPOS (tlbufpos) > 0
10135 && NILP (w->update_mode_line)
73af359d 10136 && !current_buffer->clip_changed
c62c1bb5 10137 && !current_buffer->prevent_redisplay_optimizations_p
44fa5b1e 10138 && FRAME_VISIBLE_P (XFRAME (w->frame))
f21ef775 10139 && !FRAME_OBSCURED_P (XFRAME (w->frame))
5f5c8ee5 10140 /* Make sure recorded data applies to current buffer, etc. */
a2889657
JB
10141 && this_line_buffer == current_buffer
10142 && current_buffer == XBUFFER (w->buffer)
265a9e55 10143 && NILP (w->force_start)
acda20e1 10144 && NILP (w->optional_new_start)
5f5c8ee5
GM
10145 /* Point must be on the line that we have info recorded about. */
10146 && PT >= CHARPOS (tlbufpos)
10147 && PT <= Z - CHARPOS (tlendpos)
a2889657
JB
10148 /* All text outside that line, including its final newline,
10149 must be unchanged */
5f5c8ee5
GM
10150 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
10151 CHARPOS (tlendpos)))
10152 {
10153 if (CHARPOS (tlbufpos) > BEGV
10154 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
10155 && (CHARPOS (tlbufpos) == ZV
10156 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
a2889657
JB
10157 /* Former continuation line has disappeared by becoming empty */
10158 goto cancel;
10159 else if (XFASTINT (w->last_modified) < MODIFF
8850a573 10160 || XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
a2889657
JB
10161 || MINI_WINDOW_P (w))
10162 {
1c9241f5
KH
10163 /* We have to handle the case of continuation around a
10164 wide-column character (See the comment in indent.c around
10165 line 885).
10166
10167 For instance, in the following case:
10168
10169 -------- Insert --------
10170 K_A_N_\\ `a' K_A_N_a\ `X_' are wide-column chars.
10171 J_I_ ==> J_I_ `^^' are cursors.
10172 ^^ ^^
10173 -------- --------
10174
10175 As we have to redraw the line above, we should goto cancel. */
10176
5f5c8ee5
GM
10177 struct it it;
10178 int line_height_before = this_line_pixel_height;
10179
10180 /* Note that start_display will handle the case that the
10181 line starting at tlbufpos is a continuation lines. */
10182 start_display (&it, w, tlbufpos);
10183
10184 /* Implementation note: It this still necessary? */
10185 if (it.current_x != this_line_start_x)
1c9241f5
KH
10186 goto cancel;
10187
5f5c8ee5
GM
10188 TRACE ((stderr, "trying display optimization 1\n"));
10189 w->cursor.vpos = -1;
a2889657 10190 overlay_arrow_seen = 0;
5f5c8ee5
GM
10191 it.vpos = this_line_vpos;
10192 it.current_y = this_line_y;
10193 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
10194 display_line (&it);
10195
a2889657 10196 /* If line contains point, is not continued,
5f5c8ee5 10197 and ends at same distance from eob as before, we win */
2311178e 10198 if (w->cursor.vpos >= 0
5f5c8ee5
GM
10199 /* Line is not continued, otherwise this_line_start_pos
10200 would have been set to 0 in display_line. */
10201 && CHARPOS (this_line_start_pos)
10202 /* Line ends as before. */
10203 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
10204 /* Line has same height as before. Otherwise other lines
10205 would have to be shifted up or down. */
10206 && this_line_pixel_height == line_height_before)
a2889657 10207 {
5f5c8ee5
GM
10208 /* If this is not the window's last line, we must adjust
10209 the charstarts of the lines below. */
10210 if (it.current_y < it.last_visible_y)
10211 {
10212 struct glyph_row *row
10213 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
10214 int delta, delta_bytes;
2311178e 10215
5f5c8ee5
GM
10216 if (Z - CHARPOS (tlendpos) == ZV)
10217 {
10218 /* This line ends at end of (accessible part of)
10219 buffer. There is no newline to count. */
10220 delta = (Z
10221 - CHARPOS (tlendpos)
10222 - MATRIX_ROW_START_CHARPOS (row));
10223 delta_bytes = (Z_BYTE
10224 - BYTEPOS (tlendpos)
10225 - MATRIX_ROW_START_BYTEPOS (row));
10226 }
10227 else
10228 {
10229 /* This line ends in a newline. Must take
10230 account of the newline and the rest of the
10231 text that follows. */
10232 delta = (Z
10233 - CHARPOS (tlendpos)
10234 - MATRIX_ROW_START_CHARPOS (row));
10235 delta_bytes = (Z_BYTE
10236 - BYTEPOS (tlendpos)
10237 - MATRIX_ROW_START_BYTEPOS (row));
10238 }
2311178e 10239
f2d86d7a
GM
10240 increment_matrix_positions (w->current_matrix,
10241 this_line_vpos + 1,
10242 w->current_matrix->nrows,
10243 delta, delta_bytes);
85bcef6c 10244 }
46db8486 10245
5f5c8ee5
GM
10246 /* If this row displays text now but previously didn't,
10247 or vice versa, w->window_end_vpos may have to be
10248 adjusted. */
10249 if ((it.glyph_row - 1)->displays_text_p)
10250 {
10251 if (XFASTINT (w->window_end_vpos) < this_line_vpos)
10252 XSETINT (w->window_end_vpos, this_line_vpos);
10253 }
10254 else if (XFASTINT (w->window_end_vpos) == this_line_vpos
10255 && this_line_vpos > 0)
10256 XSETINT (w->window_end_vpos, this_line_vpos - 1);
10257 w->window_end_valid = Qnil;
2311178e 10258
5f5c8ee5
GM
10259 /* Update hint: No need to try to scroll in update_window. */
10260 w->desired_matrix->no_scrolling_p = 1;
10261
10262#if GLYPH_DEBUG
10263 *w->desired_matrix->method = 0;
10264 debug_method_add (w, "optimization 1");
10265#endif
7af0e8d7 10266#ifdef HAVE_WINDOW_SYSTEM
88e6b646 10267 update_window_fringes (w, 0);
7af0e8d7 10268#endif
a2889657
JB
10269 goto update;
10270 }
10271 else
10272 goto cancel;
10273 }
5f5c8ee5
GM
10274 else if (/* Cursor position hasn't changed. */
10275 PT == XFASTINT (w->last_point)
b6f0fe04
RS
10276 /* Make sure the cursor was last displayed
10277 in this window. Otherwise we have to reposition it. */
5f5c8ee5 10278 && 0 <= w->cursor.vpos
da8b7f4f 10279 && WINDOW_TOTAL_LINES (w) > w->cursor.vpos)
a2889657
JB
10280 {
10281 if (!must_finish)
10282 {
c6e89d6c 10283 do_pending_window_change (1);
5f5c8ee5 10284
2311178e 10285 /* We used to always goto end_of_redisplay here, but this
5f5c8ee5
GM
10286 isn't enough if we have a blinking cursor. */
10287 if (w->cursor_off_p == w->last_cursor_off_p)
10288 goto end_of_redisplay;
a2889657
JB
10289 }
10290 goto update;
10291 }
8b51f1e3
KH
10292 /* If highlighting the region, or if the cursor is in the echo area,
10293 then we can't just move the cursor. */
bd66d1ba
RS
10294 else if (! (!NILP (Vtransient_mark_mode)
10295 && !NILP (current_buffer->mark_active))
97a36635 10296 && (EQ (selected_window, current_buffer->last_selected_window)
293a54ce 10297 || highlight_nonselected_windows)
8b51f1e3 10298 && NILP (w->region_showing)
8f897821 10299 && NILP (Vshow_trailing_whitespace)
8b51f1e3 10300 && !cursor_in_echo_area)
a2889657 10301 {
5f5c8ee5
GM
10302 struct it it;
10303 struct glyph_row *row;
10304
10305 /* Skip from tlbufpos to PT and see where it is. Note that
10306 PT may be in invisible text. If so, we will end at the
10307 next visible position. */
10308 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
10309 NULL, DEFAULT_FACE_ID);
10310 it.current_x = this_line_start_x;
10311 it.current_y = this_line_y;
10312 it.vpos = this_line_vpos;
2311178e 10313
5f5c8ee5
GM
10314 /* The call to move_it_to stops in front of PT, but
10315 moves over before-strings. */
10316 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
10317
10318 if (it.vpos == this_line_vpos
10319 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
10320 row->enabled_p))
a2889657 10321 {
5f5c8ee5
GM
10322 xassert (this_line_vpos == it.vpos);
10323 xassert (this_line_y == it.current_y);
10324 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
ade0bee1
GM
10325#if GLYPH_DEBUG
10326 *w->desired_matrix->method = 0;
10327 debug_method_add (w, "optimization 3");
10328#endif
a2889657
JB
10329 goto update;
10330 }
10331 else
10332 goto cancel;
10333 }
5f5c8ee5 10334
a2889657 10335 cancel:
5f5c8ee5
GM
10336 /* Text changed drastically or point moved off of line. */
10337 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, 0);
a2889657
JB
10338 }
10339
5f5c8ee5
GM
10340 CHARPOS (this_line_start_pos) = 0;
10341 consider_all_windows_p |= buffer_shared > 1;
10342 ++clear_face_cache_count;
a2889657 10343
2311178e 10344
bd9d0f3f
GM
10345 /* Build desired matrices, and update the display. If
10346 consider_all_windows_p is non-zero, do it for all windows on all
10347 frames. Otherwise do it for selected_window, only. */
463f6b91 10348
5f5c8ee5 10349 if (consider_all_windows_p)
a2889657 10350 {
35f56f96 10351 Lisp_Object tail, frame;
0528abe1
GM
10352 int i, n = 0, size = 50;
10353 struct frame **updated
10354 = (struct frame **) alloca (size * sizeof *updated);
a2889657 10355
5f5c8ee5
GM
10356 /* Clear the face cache eventually. */
10357 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
463f6b91 10358 {
5f5c8ee5 10359 clear_face_cache (0);
463f6b91
RS
10360 clear_face_cache_count = 0;
10361 }
31b24551 10362
5f5c8ee5
GM
10363 /* Recompute # windows showing selected buffer. This will be
10364 incremented each time such a window is displayed. */
a2889657
JB
10365 buffer_shared = 0;
10366
35f56f96 10367 FOR_EACH_FRAME (tail, frame)
30c566e4 10368 {
5f5c8ee5 10369 struct frame *f = XFRAME (frame);
2311178e 10370
886bd6f2 10371 if (FRAME_WINDOW_P (f) || f == sf)
9769686d 10372 {
dd429b03
KH
10373 if (! EQ (frame, selected_frame))
10374 /* Select the frame, for the sake of frame-local
10375 variables. */
10376 select_frame_for_redisplay (frame);
10377
ae02e06a 10378#ifdef HAVE_WINDOW_SYSTEM
bb336f8d
RS
10379 if (clear_face_cache_count % 50 == 0
10380 && FRAME_WINDOW_P (f))
10381 clear_image_cache (f, 0);
ae02e06a 10382#endif /* HAVE_WINDOW_SYSTEM */
bb336f8d 10383
5f5c8ee5
GM
10384 /* Mark all the scroll bars to be removed; we'll redeem
10385 the ones we want when we redisplay their windows. */
9769686d 10386 if (condemn_scroll_bars_hook)
504454e8 10387 condemn_scroll_bars_hook (f);
30c566e4 10388
f21ef775 10389 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
5f5c8ee5 10390 redisplay_windows (FRAME_ROOT_WINDOW (f));
30c566e4 10391
5f5c8ee5
GM
10392 /* Any scroll bars which redisplay_windows should have
10393 nuked should now go away. */
9769686d 10394 if (judge_scroll_bars_hook)
504454e8 10395 judge_scroll_bars_hook (f);
bd9d0f3f
GM
10396
10397 /* If fonts changed, display again. */
b60c9653
RS
10398 /* ??? rms: I suspect it is a mistake to jump all the way
10399 back to retry here. It should just retry this frame. */
bd9d0f3f
GM
10400 if (fonts_changed_p)
10401 goto retry;
2311178e 10402
bd9d0f3f
GM
10403 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
10404 {
10405 /* See if we have to hscroll. */
10406 if (hscroll_windows (f->root_window))
10407 goto retry;
10408
10409 /* Prevent various kinds of signals during display
10410 update. stdio is not robust about handling
10411 signals, which can cause an apparent I/O
10412 error. */
10413 if (interrupt_input)
10414 unrequest_sigio ();
aac2d8b2 10415 STOP_POLLING;
bd9d0f3f
GM
10416
10417 /* Update the display. */
10418 set_window_update_flags (XWINDOW (f->root_window), 1);
10419 pause |= update_frame (f, 0, 0);
ccbb9ed2 10420#if 0 /* Exiting the loop can leave the wrong value for buffer_shared. */
bd9d0f3f
GM
10421 if (pause)
10422 break;
ccbb9ed2 10423#endif
bd9d0f3f 10424
0528abe1
GM
10425 if (n == size)
10426 {
10427 int nbytes = size * sizeof *updated;
10428 struct frame **p = (struct frame **) alloca (2 * nbytes);
10429 bcopy (updated, p, nbytes);
10430 size *= 2;
10431 }
2311178e 10432
0528abe1 10433 updated[n++] = f;
bd9d0f3f 10434 }
9769686d 10435 }
30c566e4 10436 }
0528abe1 10437
6f68b035
GM
10438 if (!pause)
10439 {
10440 /* Do the mark_window_display_accurate after all windows have
10441 been redisplayed because this call resets flags in buffers
10442 which are needed for proper redisplay. */
10443 for (i = 0; i < n; ++i)
10444 {
10445 struct frame *f = updated[i];
10446 mark_window_display_accurate (f->root_window, 1);
10447 if (frame_up_to_date_hook)
10448 frame_up_to_date_hook (f);
10449 }
0528abe1 10450 }
a2889657 10451 }
bd9d0f3f
GM
10452 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
10453 {
10454 Lisp_Object mini_window;
10455 struct frame *mini_frame;
5f5c8ee5 10456
82a7ab23 10457 displayed_buffer = XBUFFER (XWINDOW (selected_window)->buffer);
7033d6df
RS
10458 /* Use list_of_error, not Qerror, so that
10459 we catch only errors and don't run the debugger. */
10460 internal_condition_case_1 (redisplay_window_1, selected_window,
10461 list_of_error,
82a7ab23 10462 redisplay_window_error);
2311178e 10463
bd9d0f3f 10464 /* Compare desired and current matrices, perform output. */
7d0393cf 10465
26683087 10466 update:
bd9d0f3f
GM
10467 /* If fonts changed, display again. */
10468 if (fonts_changed_p)
92a90e89 10469 goto retry;
a2889657 10470
bd9d0f3f
GM
10471 /* Prevent various kinds of signals during display update.
10472 stdio is not robust about handling signals,
10473 which can cause an apparent I/O error. */
10474 if (interrupt_input)
10475 unrequest_sigio ();
aac2d8b2 10476 STOP_POLLING;
1af9f229 10477
bd9d0f3f 10478 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
5f5c8ee5 10479 {
92a90e89
GM
10480 if (hscroll_windows (selected_window))
10481 goto retry;
2311178e 10482
5f5c8ee5 10483 XWINDOW (selected_window)->must_be_updated_p = 1;
886bd6f2 10484 pause = update_frame (sf, 0, 0);
5f5c8ee5 10485 }
d724d989 10486
8de2d90b 10487 /* We may have called echo_area_display at the top of this
44fa5b1e
JB
10488 function. If the echo area is on another frame, that may
10489 have put text on a frame other than the selected one, so the
10490 above call to update_frame would not have caught it. Catch
8de2d90b 10491 it here. */
bd9d0f3f
GM
10492 mini_window = FRAME_MINIBUF_WINDOW (sf);
10493 mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
2311178e 10494
bd9d0f3f
GM
10495 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
10496 {
10497 XWINDOW (mini_window)->must_be_updated_p = 1;
10498 pause |= update_frame (mini_frame, 0, 0);
10499 if (!pause && hscroll_windows (mini_window))
10500 goto retry;
10501 }
6e8290aa 10502 }
a2889657 10503
5f5c8ee5
GM
10504 /* If display was paused because of pending input, make sure we do a
10505 thorough update the next time. */
a2889657
JB
10506 if (pause)
10507 {
5f5c8ee5
GM
10508 /* Prevent the optimization at the beginning of
10509 redisplay_internal that tries a single-line update of the
10510 line containing the cursor in the selected window. */
10511 CHARPOS (this_line_start_pos) = 0;
10512
10513 /* Let the overlay arrow be updated the next time. */
265a9e55 10514 if (!NILP (last_arrow_position))
a2889657
JB
10515 {
10516 last_arrow_position = Qt;
10517 last_arrow_string = Qt;
10518 }
2311178e 10519
5f5c8ee5
GM
10520 /* If we pause after scrolling, some rows in the current
10521 matrices of some windows are not valid. */
10522 if (!WINDOW_FULL_WIDTH_P (w)
10523 && !FRAME_WINDOW_P (XFRAME (w->frame)))
a2889657
JB
10524 update_mode_lines = 1;
10525 }
43c09969 10526 else
a2889657 10527 {
43c09969 10528 if (!consider_all_windows_p)
a2889657 10529 {
43c09969
GM
10530 /* This has already been done above if
10531 consider_all_windows_p is set. */
10532 mark_window_display_accurate_1 (w, 1);
2311178e 10533
927c5b3b
GM
10534 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
10535 last_arrow_string = Voverlay_arrow_string;
2311178e 10536
efc63ef0 10537 if (frame_up_to_date_hook != 0)
43c09969 10538 frame_up_to_date_hook (sf);
a2889657 10539 }
15e26c76 10540
a2889657
JB
10541 update_mode_lines = 0;
10542 windows_or_buffers_changed = 0;
5fb96e96 10543 cursor_type_changed = 0;
a2889657
JB
10544 }
10545
5f5c8ee5
GM
10546 /* Start SIGIO interrupts coming again. Having them off during the
10547 code above makes it less likely one will discard output, but not
10548 impossible, since there might be stuff in the system buffer here.
a2889657 10549 But it is much hairier to try to do anything about that. */
a2889657
JB
10550 if (interrupt_input)
10551 request_sigio ();
aac2d8b2 10552 RESUME_POLLING;
a2889657 10553
5f5c8ee5
GM
10554 /* If a frame has become visible which was not before, redisplay
10555 again, so that we display it. Expose events for such a frame
10556 (which it gets when becoming visible) don't call the parts of
10557 redisplay constructing glyphs, so simply exposing a frame won't
10558 display anything in this case. So, we have to display these
10559 frames here explicitly. */
11c52c4f
RS
10560 if (!pause)
10561 {
10562 Lisp_Object tail, frame;
10563 int new_count = 0;
10564
10565 FOR_EACH_FRAME (tail, frame)
10566 {
10567 int this_is_visible = 0;
8e83f802
RS
10568
10569 if (XFRAME (frame)->visible)
10570 this_is_visible = 1;
10571 FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
10572 if (XFRAME (frame)->visible)
10573 this_is_visible = 1;
11c52c4f
RS
10574
10575 if (this_is_visible)
10576 new_count++;
10577 }
10578
89819bdd 10579 if (new_count != number_of_visible_frames)
11c52c4f
RS
10580 windows_or_buffers_changed++;
10581 }
10582
44fa5b1e 10583 /* Change frame size now if a change is pending. */
c6e89d6c 10584 do_pending_window_change (1);
d8e242fd 10585
8b32d885
RS
10586 /* If we just did a pending size change, or have additional
10587 visible frames, redisplay again. */
3c8c72e0 10588 if (windows_or_buffers_changed && !pause)
8b32d885 10589 goto retry;
5f5c8ee5 10590
1987b083 10591 end_of_redisplay:
28514cd9 10592 unbind_to (count, Qnil);
aac2d8b2 10593 RESUME_POLLING;
a2889657
JB
10594}
10595
5f5c8ee5
GM
10596
10597/* Redisplay, but leave alone any recent echo area message unless
10598 another message has been requested in its place.
a2889657
JB
10599
10600 This is useful in situations where you need to redisplay but no
10601 user action has occurred, making it inappropriate for the message
10602 area to be cleared. See tracking_off and
9bf76936
GM
10603 wait_reading_process_input for examples of these situations.
10604
10605 FROM_WHERE is an integer saying from where this function was
10606 called. This is useful for debugging. */
a2889657 10607
8991bb31 10608void
9bf76936
GM
10609redisplay_preserve_echo_area (from_where)
10610 int from_where;
a2889657 10611{
9bf76936
GM
10612 TRACE ((stderr, "redisplay_preserve_echo_area (%d)\n", from_where));
10613
c6e89d6c 10614 if (!NILP (echo_area_buffer[1]))
a2889657 10615 {
c6e89d6c
GM
10616 /* We have a previously displayed message, but no current
10617 message. Redisplay the previous message. */
10618 display_last_displayed_message_p = 1;
e9874cee 10619 redisplay_internal (1);
c6e89d6c 10620 display_last_displayed_message_p = 0;
a2889657
JB
10621 }
10622 else
e9874cee 10623 redisplay_internal (1);
a2889657
JB
10624}
10625
5f5c8ee5 10626
28514cd9 10627/* Function registered with record_unwind_protect in
acfca545
RS
10628 redisplay_internal. Reset redisplaying_p to the value it had
10629 before redisplay_internal was called, and clear
dd429b03
KH
10630 prevent_freeing_realized_faces_p. It also selects the previously
10631 selected frame. */
28514cd9
GM
10632
10633static Lisp_Object
dd429b03
KH
10634unwind_redisplay (val)
10635 Lisp_Object val;
28514cd9 10636{
dd429b03
KH
10637 Lisp_Object old_redisplaying_p, old_frame;
10638
10639 old_redisplaying_p = XCAR (val);
28514cd9 10640 redisplaying_p = XFASTINT (old_redisplaying_p);
dd429b03
KH
10641 old_frame = XCDR (val);
10642 if (! EQ (old_frame, selected_frame))
10643 select_frame_for_redisplay (old_frame);
c6e89d6c 10644 return Qnil;
28514cd9
GM
10645}
10646
10647
43c09969
GM
10648/* Mark the display of window W as accurate or inaccurate. If
10649 ACCURATE_P is non-zero mark display of W as accurate. If
10650 ACCURATE_P is zero, arrange for W to be redisplayed the next time
10651 redisplay_internal is called. */
5f5c8ee5 10652
43c09969
GM
10653static void
10654mark_window_display_accurate_1 (w, accurate_p)
10655 struct window *w;
5f5c8ee5 10656 int accurate_p;
a2889657 10657{
43c09969 10658 if (BUFFERP (w->buffer))
a2889657 10659 {
43c09969 10660 struct buffer *b = XBUFFER (w->buffer);
2311178e 10661
43c09969
GM
10662 w->last_modified
10663 = make_number (accurate_p ? BUF_MODIFF (b) : 0);
10664 w->last_overlay_modified
10665 = make_number (accurate_p ? BUF_OVERLAY_MODIFF (b) : 0);
10666 w->last_had_star
10667 = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b) ? Qt : Qnil;
a2889657 10668
43c09969 10669 if (accurate_p)
bd66d1ba 10670 {
43c09969
GM
10671 b->clip_changed = 0;
10672 b->prevent_redisplay_optimizations_p = 0;
10673
10674 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
10675 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
10676 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
10677 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
2311178e 10678
43c09969
GM
10679 w->current_matrix->buffer = b;
10680 w->current_matrix->begv = BUF_BEGV (b);
10681 w->current_matrix->zv = BUF_ZV (b);
2311178e 10682
43c09969
GM
10683 w->last_cursor = w->cursor;
10684 w->last_cursor_off_p = w->cursor_off_p;
2311178e 10685
43c09969
GM
10686 if (w == XWINDOW (selected_window))
10687 w->last_point = make_number (BUF_PT (b));
10688 else
10689 w->last_point = make_number (XMARKER (w->pointm)->charpos);
bd66d1ba 10690 }
43c09969 10691 }
bd66d1ba 10692
43c09969
GM
10693 if (accurate_p)
10694 {
d2f84654 10695 w->window_end_valid = w->buffer;
99332eb6 10696#if 0 /* This is incorrect with variable-height lines. */
2913a9c0 10697 xassert (XINT (w->window_end_vpos)
da8b7f4f 10698 < (WINDOW_TOTAL_LINES (w)
2913a9c0 10699 - (WINDOW_WANTS_MODELINE_P (w) ? 1 : 0)));
99332eb6 10700#endif
a2889657 10701 w->update_mode_line = Qnil;
43c09969
GM
10702 }
10703}
10704
10705
10706/* Mark the display of windows in the window tree rooted at WINDOW as
10707 accurate or inaccurate. If ACCURATE_P is non-zero mark display of
10708 windows as accurate. If ACCURATE_P is zero, arrange for windows to
10709 be redisplayed the next time redisplay_internal is called. */
10710
10711void
10712mark_window_display_accurate (window, accurate_p)
10713 Lisp_Object window;
10714 int accurate_p;
10715{
10716 struct window *w;
2311178e 10717
43c09969
GM
10718 for (; !NILP (window); window = w->next)
10719 {
10720 w = XWINDOW (window);
10721 mark_window_display_accurate_1 (w, accurate_p);
a2889657 10722
265a9e55 10723 if (!NILP (w->vchild))
5f5c8ee5 10724 mark_window_display_accurate (w->vchild, accurate_p);
265a9e55 10725 if (!NILP (w->hchild))
5f5c8ee5 10726 mark_window_display_accurate (w->hchild, accurate_p);
a2889657
JB
10727 }
10728
5f5c8ee5 10729 if (accurate_p)
a2889657 10730 {
d45de95b 10731 last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
a2889657
JB
10732 last_arrow_string = Voverlay_arrow_string;
10733 }
10734 else
10735 {
5f5c8ee5
GM
10736 /* Force a thorough redisplay the next time by setting
10737 last_arrow_position and last_arrow_string to t, which is
4b41cebb 10738 unequal to any useful value of Voverlay_arrow_... */
a2889657
JB
10739 last_arrow_position = Qt;
10740 last_arrow_string = Qt;
10741 }
10742}
5f5c8ee5
GM
10743
10744
10745/* Return value in display table DP (Lisp_Char_Table *) for character
10746 C. Since a display table doesn't have any parent, we don't have to
10747 follow parent. Do not call this function directly but use the
10748 macro DISP_CHAR_VECTOR. */
10749
10750Lisp_Object
10751disp_char_vector (dp, c)
10752 struct Lisp_Char_Table *dp;
10753 int c;
10754{
10755 int code[4], i;
10756 Lisp_Object val;
10757
10758 if (SINGLE_BYTE_CHAR_P (c))
10759 return (dp->contents[c]);
2311178e 10760
c5924f47 10761 SPLIT_CHAR (c, code[0], code[1], code[2]);
260a86a0
KH
10762 if (code[1] < 32)
10763 code[1] = -1;
10764 else if (code[2] < 32)
10765 code[2] = -1;
2311178e 10766
5f5c8ee5
GM
10767 /* Here, the possible range of code[0] (== charset ID) is
10768 128..max_charset. Since the top level char table contains data
10769 for multibyte characters after 256th element, we must increment
10770 code[0] by 128 to get a correct index. */
10771 code[0] += 128;
10772 code[3] = -1; /* anchor */
10773
10774 for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
10775 {
10776 val = dp->contents[code[i]];
10777 if (!SUB_CHAR_TABLE_P (val))
10778 return (NILP (val) ? dp->defalt : val);
10779 }
2311178e 10780
5f5c8ee5
GM
10781 /* Here, val is a sub char table. We return the default value of
10782 it. */
10783 return (dp->defalt);
10784}
10785
10786
a2889657 10787\f
5f5c8ee5
GM
10788/***********************************************************************
10789 Window Redisplay
10790 ***********************************************************************/
a2725ab2 10791
5f5c8ee5 10792/* Redisplay all leaf windows in the window tree rooted at WINDOW. */
90adcf20
RS
10793
10794static void
5f5c8ee5
GM
10795redisplay_windows (window)
10796 Lisp_Object window;
90adcf20 10797{
5f5c8ee5
GM
10798 while (!NILP (window))
10799 {
10800 struct window *w = XWINDOW (window);
2311178e 10801
5f5c8ee5
GM
10802 if (!NILP (w->hchild))
10803 redisplay_windows (w->hchild);
10804 else if (!NILP (w->vchild))
10805 redisplay_windows (w->vchild);
10806 else
82a7ab23
RS
10807 {
10808 displayed_buffer = XBUFFER (w->buffer);
7033d6df
RS
10809 /* Use list_of_error, not Qerror, so that
10810 we catch only errors and don't run the debugger. */
2311178e 10811 internal_condition_case_1 (redisplay_window_0, window,
7033d6df 10812 list_of_error,
82a7ab23
RS
10813 redisplay_window_error);
10814 }
a2725ab2 10815
5f5c8ee5
GM
10816 window = w->next;
10817 }
10818}
10819
82a7ab23
RS
10820static Lisp_Object
10821redisplay_window_error ()
10822{
10823 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
10824 return Qnil;
10825}
10826
10827static Lisp_Object
10828redisplay_window_0 (window)
10829 Lisp_Object window;
10830{
10831 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10832 redisplay_window (window, 0);
10833 return Qnil;
10834}
5f5c8ee5 10835
82a7ab23
RS
10836static Lisp_Object
10837redisplay_window_1 (window)
10838 Lisp_Object window;
10839{
10840 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
10841 redisplay_window (window, 1);
10842 return Qnil;
10843}
10844\f
bc6371a6
KH
10845
10846/* Increment GLYPH until it reaches END or CONDITION fails while
10847 adding (GLYPH)->pixel_width to X. */
10848
10849#define SKIP_GLYPHS(glyph, end, x, condition) \
10850 do \
10851 { \
10852 (x) += (glyph)->pixel_width; \
10853 ++(glyph); \
10854 } \
10855 while ((glyph) < (end) && (condition))
10856
10857
5f5c8ee5
GM
10858/* Set cursor position of W. PT is assumed to be displayed in ROW.
10859 DELTA is the number of bytes by which positions recorded in ROW
10860 differ from current buffer positions. */
10861
10862void
10863set_cursor_from_row (w, row, matrix, delta, delta_bytes, dy, dvpos)
10864 struct window *w;
10865 struct glyph_row *row;
10866 struct glyph_matrix *matrix;
10867 int delta, delta_bytes, dy, dvpos;
10868{
10869 struct glyph *glyph = row->glyphs[TEXT_AREA];
10870 struct glyph *end = glyph + row->used[TEXT_AREA];
ae73dc1c
KH
10871 /* The first glyph that starts a sequence of glyphs from string. */
10872 struct glyph *string_start;
10873 /* The X coordinate of string_start. */
10874 int string_start_x;
10875 /* The last known character position. */
10876 int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
10877 /* The last known character position before string_start. */
10878 int string_before_pos;
5f5c8ee5
GM
10879 int x = row->x;
10880 int pt_old = PT - delta;
10881
10882 /* Skip over glyphs not having an object at the start of the row.
10883 These are special glyphs like truncation marks on terminal
10884 frames. */
10885 if (row->displays_text_p)
10886 while (glyph < end
6fc556fd 10887 && INTEGERP (glyph->object)
5f5c8ee5
GM
10888 && glyph->charpos < 0)
10889 {
10890 x += glyph->pixel_width;
10891 ++glyph;
10892 }
10893
ae73dc1c 10894 string_start = NULL;
5f5c8ee5 10895 while (glyph < end
6fc556fd 10896 && !INTEGERP (glyph->object)
5f5c8ee5 10897 && (!BUFFERP (glyph->object)
ae73dc1c 10898 || (last_pos = glyph->charpos) < pt_old))
5f5c8ee5 10899 {
ae73dc1c
KH
10900 if (! STRINGP (glyph->object))
10901 {
10902 string_start = NULL;
10903 x += glyph->pixel_width;
10904 ++glyph;
10905 }
10906 else
10907 {
10908 string_before_pos = last_pos;
10909 string_start = glyph;
10910 string_start_x = x;
10911 /* Skip all glyphs from string. */
bc6371a6 10912 SKIP_GLYPHS (glyph, end, x, STRINGP (glyph->object));
ae73dc1c
KH
10913 }
10914 }
10915
10916 if (string_start
10917 && (glyph == end || !BUFFERP (glyph->object) || last_pos > pt_old))
10918 {
10919 /* We may have skipped over point because the previous glyphs
10920 are from string. As there's no easy way to know the
10921 character position of the current glyph, find the correct
10922 glyph on point by scanning from string_start again. */
bc6371a6
KH
10923 Lisp_Object limit;
10924 Lisp_Object string;
10925 int pos;
ae73dc1c 10926
bc6371a6
KH
10927 limit = make_number (pt_old + 1);
10928 end = glyph;
ae73dc1c
KH
10929 glyph = string_start;
10930 x = string_start_x;
bc6371a6
KH
10931 string = glyph->object;
10932 pos = string_buffer_position (w, string, string_before_pos);
10933 /* If STRING is from overlay, LAST_POS == 0. We skip such glyphs
10934 because we always put cursor after overlay strings. */
10935 while (pos == 0 && glyph < end)
ae73dc1c 10936 {
bc6371a6
KH
10937 string = glyph->object;
10938 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10939 if (glyph < end)
10940 pos = string_buffer_position (w, glyph->object, string_before_pos);
10941 }
10942
10943 while (glyph < end)
10944 {
10945 pos = XINT (Fnext_single_char_property_change
10946 (make_number (pos), Qdisplay, Qnil, limit));
10947 if (pos > pt_old)
10948 break;
ae73dc1c 10949 /* Skip glyphs from the same string. */
bc6371a6
KH
10950 string = glyph->object;
10951 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
10952 /* Skip glyphs from an overlay. */
10953 while (glyph < end
10954 && ! string_buffer_position (w, glyph->object, pos))
ae73dc1c 10955 {
bc6371a6
KH
10956 string = glyph->object;
10957 SKIP_GLYPHS (glyph, end, x, EQ (glyph->object, string));
ae73dc1c 10958 }
ae73dc1c 10959 }
5f5c8ee5
GM
10960 }
10961
10962 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
10963 w->cursor.x = x;
10964 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
10965 w->cursor.y = row->y + dy;
10966
10967 if (w == XWINDOW (selected_window))
10968 {
10969 if (!row->continued_p
10970 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
10971 && row->x == 0)
10972 {
10973 this_line_buffer = XBUFFER (w->buffer);
2311178e 10974
5f5c8ee5
GM
10975 CHARPOS (this_line_start_pos)
10976 = MATRIX_ROW_START_CHARPOS (row) + delta;
10977 BYTEPOS (this_line_start_pos)
10978 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
2311178e 10979
5f5c8ee5
GM
10980 CHARPOS (this_line_end_pos)
10981 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
10982 BYTEPOS (this_line_end_pos)
10983 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
2311178e 10984
5f5c8ee5
GM
10985 this_line_y = w->cursor.y;
10986 this_line_pixel_height = row->height;
10987 this_line_vpos = w->cursor.vpos;
10988 this_line_start_x = row->x;
10989 }
10990 else
10991 CHARPOS (this_line_start_pos) = 0;
10992 }
10993}
10994
10995
10996/* Run window scroll functions, if any, for WINDOW with new window
756a3cb6
RS
10997 start STARTP. Sets the window start of WINDOW to that position.
10998
10999 We assume that the window's buffer is really current. */
5f5c8ee5
GM
11000
11001static INLINE struct text_pos
11002run_window_scroll_functions (window, startp)
11003 Lisp_Object window;
11004 struct text_pos startp;
11005{
11006 struct window *w = XWINDOW (window);
11007 SET_MARKER_FROM_TEXT_POS (w->start, startp);
756a3cb6
RS
11008
11009 if (current_buffer != XBUFFER (w->buffer))
11010 abort ();
11011
5f5c8ee5
GM
11012 if (!NILP (Vwindow_scroll_functions))
11013 {
2311178e 11014 run_hook_with_args_2 (Qwindow_scroll_functions, window,
5f5c8ee5
GM
11015 make_number (CHARPOS (startp)));
11016 SET_TEXT_POS_FROM_MARKER (startp, w->start);
756a3cb6
RS
11017 /* In case the hook functions switch buffers. */
11018 if (current_buffer != XBUFFER (w->buffer))
11019 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5 11020 }
90adcf20 11021
5f5c8ee5
GM
11022 return startp;
11023}
11024
11025
ddf6b9a3
RS
11026/* Make sure the line containing the cursor is fully visible.
11027 A value of 1 means there is nothing to be done.
11028 (Either the line is fully visible, or it cannot be made so,
11029 or we cannot tell.)
11030 A value of 0 means the caller should do scrolling
11031 as if point had gone off the screen. */
5f5c8ee5 11032
cb617e7c 11033static int
5f5c8ee5
GM
11034make_cursor_line_fully_visible (w)
11035 struct window *w;
11036{
11037 struct glyph_matrix *matrix;
11038 struct glyph_row *row;
478d746b 11039 int window_height;
2311178e 11040
5f5c8ee5
GM
11041 /* It's not always possible to find the cursor, e.g, when a window
11042 is full of overlay strings. Don't do anything in that case. */
11043 if (w->cursor.vpos < 0)
cb617e7c 11044 return 1;
2311178e 11045
5f5c8ee5
GM
11046 matrix = w->desired_matrix;
11047 row = MATRIX_ROW (matrix, w->cursor.vpos);
11048
acda20e1 11049 /* If the cursor row is not partially visible, there's nothing to do. */
b28cb6ed 11050 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
cb617e7c 11051 return 1;
b28cb6ed
GM
11052
11053 /* If the row the cursor is in is taller than the window's height,
11054 it's not clear what to do, so do nothing. */
11055 window_height = window_box_height (w);
11056 if (row->height >= window_height)
cb617e7c 11057 return 1;
b28cb6ed 11058
ddf6b9a3
RS
11059 return 0;
11060
11061#if 0
11062 /* This code used to try to scroll the window just enough to make
11063 the line visible. It returned 0 to say that the caller should
11064 allocate larger glyph matrices. */
11065
b28cb6ed 11066 if (MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (w, row))
5f5c8ee5
GM
11067 {
11068 int dy = row->height - row->visible_height;
11069 w->vscroll = 0;
11070 w->cursor.y += dy;
11071 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
11072 }
b28cb6ed 11073 else /* MATRIX_ROW_PARTIALLY_VISIBLE_AT_BOTTOM_P (w, row)) */
5f5c8ee5
GM
11074 {
11075 int dy = - (row->height - row->visible_height);
11076 w->vscroll = dy;
11077 w->cursor.y += dy;
11078 shift_glyph_matrix (w, matrix, 0, matrix->nrows, dy);
11079 }
2311178e 11080
5f5c8ee5
GM
11081 /* When we change the cursor y-position of the selected window,
11082 change this_line_y as well so that the display optimization for
11083 the cursor line of the selected window in redisplay_internal uses
11084 the correct y-position. */
11085 if (w == XWINDOW (selected_window))
11086 this_line_y = w->cursor.y;
cb617e7c
GM
11087
11088 /* If vscrolling requires a larger glyph matrix, arrange for a fresh
11089 redisplay with larger matrices. */
11090 if (matrix->nrows < required_matrix_height (w))
11091 {
11092 fonts_changed_p = 1;
11093 return 0;
11094 }
11095
11096 return 1;
ddf6b9a3 11097#endif /* 0 */
5f5c8ee5
GM
11098}
11099
11100
11101/* Try scrolling PT into view in window WINDOW. JUST_THIS_ONE_P
11102 non-zero means only WINDOW is redisplayed in redisplay_internal.
11103 TEMP_SCROLL_STEP has the same meaning as scroll_step, and is used
11104 in redisplay_window to bring a partially visible line into view in
11105 the case that only the cursor has moved.
11106
03b0a4b4
RS
11107 LAST_LINE_MISFIT should be nonzero if we're scrolling because the
11108 last screen line's vertical height extends past the end of the screen.
11109
5f5c8ee5
GM
11110 Value is
11111
11112 1 if scrolling succeeded
2311178e 11113
5f5c8ee5 11114 0 if scrolling didn't find point.
2311178e 11115
5f5c8ee5
GM
11116 -1 if new fonts have been loaded so that we must interrupt
11117 redisplay, adjust glyph matrices, and try again. */
11118
cb617e7c
GM
11119enum
11120{
11121 SCROLLING_SUCCESS,
11122 SCROLLING_FAILED,
11123 SCROLLING_NEED_LARGER_MATRICES
11124};
11125
5f5c8ee5
GM
11126static int
11127try_scrolling (window, just_this_one_p, scroll_conservatively,
03b0a4b4 11128 scroll_step, temp_scroll_step, last_line_misfit)
5f5c8ee5
GM
11129 Lisp_Object window;
11130 int just_this_one_p;
31ade731 11131 EMACS_INT scroll_conservatively, scroll_step;
5f5c8ee5 11132 int temp_scroll_step;
03b0a4b4 11133 int last_line_misfit;
5f5c8ee5
GM
11134{
11135 struct window *w = XWINDOW (window);
11136 struct frame *f = XFRAME (w->frame);
11137 struct text_pos scroll_margin_pos;
11138 struct text_pos pos;
11139 struct text_pos startp;
11140 struct it it;
11141 Lisp_Object window_end;
11142 int this_scroll_margin;
11143 int dy = 0;
11144 int scroll_max;
b8a63ccb 11145 int rc;
5f5c8ee5
GM
11146 int amount_to_scroll = 0;
11147 Lisp_Object aggressive;
11148 int height;
03b0a4b4 11149 int end_scroll_margin;
5f5c8ee5
GM
11150
11151#if GLYPH_DEBUG
11152 debug_method_add (w, "try_scrolling");
78614721 11153#endif
5f5c8ee5
GM
11154
11155 SET_TEXT_POS_FROM_MARKER (startp, w->start);
2311178e 11156
5f5c8ee5
GM
11157 /* Compute scroll margin height in pixels. We scroll when point is
11158 within this distance from the top or bottom of the window. */
11159 if (scroll_margin > 0)
90adcf20 11160 {
da8b7f4f
KS
11161 this_scroll_margin = min (scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
11162 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
11163 }
11164 else
11165 this_scroll_margin = 0;
11166
11167 /* Compute how much we should try to scroll maximally to bring point
11168 into view. */
0894e696
SM
11169 if (scroll_step || scroll_conservatively || temp_scroll_step)
11170 scroll_max = max (scroll_step,
11171 max (scroll_conservatively, temp_scroll_step));
5f5c8ee5
GM
11172 else if (NUMBERP (current_buffer->scroll_down_aggressively)
11173 || NUMBERP (current_buffer->scroll_up_aggressively))
11174 /* We're trying to scroll because of aggressive scrolling
11175 but no scroll_step is set. Choose an arbitrary one. Maybe
11176 there should be a variable for this. */
11177 scroll_max = 10;
11178 else
11179 scroll_max = 0;
da8b7f4f 11180 scroll_max *= FRAME_LINE_HEIGHT (f);
5f5c8ee5
GM
11181
11182 /* Decide whether we have to scroll down. Start at the window end
11183 and move this_scroll_margin up to find the position of the scroll
11184 margin. */
11185 window_end = Fwindow_end (window, Qt);
03b0a4b4
RS
11186
11187 too_near_end:
11188
5f5c8ee5
GM
11189 CHARPOS (scroll_margin_pos) = XINT (window_end);
11190 BYTEPOS (scroll_margin_pos) = CHAR_TO_BYTE (CHARPOS (scroll_margin_pos));
03b0a4b4
RS
11191
11192 end_scroll_margin = this_scroll_margin + !!last_line_misfit;
11193 if (end_scroll_margin)
5f5c8ee5
GM
11194 {
11195 start_display (&it, w, scroll_margin_pos);
03b0a4b4 11196 move_it_vertically (&it, - end_scroll_margin);
5f5c8ee5
GM
11197 scroll_margin_pos = it.current.pos;
11198 }
11199
11200 if (PT >= CHARPOS (scroll_margin_pos))
11201 {
11202 int y0;
2311178e 11203
5f5c8ee5
GM
11204 /* Point is in the scroll margin at the bottom of the window, or
11205 below. Compute a new window start that makes point visible. */
47589c8c 11206
5f5c8ee5
GM
11207 /* Compute the distance from the scroll margin to PT.
11208 Give up if the distance is greater than scroll_max. */
11209 start_display (&it, w, scroll_margin_pos);
11210 y0 = it.current_y;
11211 move_it_to (&it, PT, 0, it.last_visible_y, -1,
11212 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
539e92ad
GM
11213
11214 /* To make point visible, we have to move the window start
11215 down so that the line the cursor is in is visible, which
11216 means we have to add in the height of the cursor line. */
11217 dy = line_bottom_y (&it) - y0;
2311178e 11218
5f5c8ee5 11219 if (dy > scroll_max)
cb617e7c 11220 return SCROLLING_FAILED;
2311178e 11221
5f5c8ee5
GM
11222 /* Move the window start down. If scrolling conservatively,
11223 move it just enough down to make point visible. If
11224 scroll_step is set, move it down by scroll_step. */
11225 start_display (&it, w, startp);
11226
11227 if (scroll_conservatively)
03b0a4b4
RS
11228 /* Set AMOUNT_TO_SCROLL to at least one line,
11229 and at most scroll_conservatively lines. */
e89aaabd 11230 amount_to_scroll
da8b7f4f
KS
11231 = min (max (dy, FRAME_LINE_HEIGHT (f)),
11232 FRAME_LINE_HEIGHT (f) * scroll_conservatively);
5f5c8ee5
GM
11233 else if (scroll_step || temp_scroll_step)
11234 amount_to_scroll = scroll_max;
11235 else
90adcf20 11236 {
46226c1d 11237 aggressive = current_buffer->scroll_up_aggressively;
da8b7f4f 11238 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
11239 if (NUMBERP (aggressive))
11240 amount_to_scroll = XFLOATINT (aggressive) * height;
11241 }
a2725ab2 11242
5f5c8ee5 11243 if (amount_to_scroll <= 0)
cb617e7c 11244 return SCROLLING_FAILED;
a2725ab2 11245
03b0a4b4
RS
11246 /* If moving by amount_to_scroll leaves STARTP unchanged,
11247 move it down one screen line. */
11248
5f5c8ee5 11249 move_it_vertically (&it, amount_to_scroll);
03b0a4b4
RS
11250 if (CHARPOS (it.current.pos) == CHARPOS (startp))
11251 move_it_by_lines (&it, 1, 1);
5f5c8ee5
GM
11252 startp = it.current.pos;
11253 }
11254 else
11255 {
11256 /* See if point is inside the scroll margin at the top of the
11257 window. */
11258 scroll_margin_pos = startp;
11259 if (this_scroll_margin)
11260 {
11261 start_display (&it, w, startp);
11262 move_it_vertically (&it, this_scroll_margin);
11263 scroll_margin_pos = it.current.pos;
11264 }
11265
11266 if (PT < CHARPOS (scroll_margin_pos))
11267 {
11268 /* Point is in the scroll margin at the top of the window or
11269 above what is displayed in the window. */
11270 int y0;
2311178e 11271
5f5c8ee5
GM
11272 /* Compute the vertical distance from PT to the scroll
11273 margin position. Give up if distance is greater than
11274 scroll_max. */
11275 SET_TEXT_POS (pos, PT, PT_BYTE);
11276 start_display (&it, w, pos);
11277 y0 = it.current_y;
11278 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
11279 it.last_visible_y, -1,
11280 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
11281 dy = it.current_y - y0;
11282 if (dy > scroll_max)
cb617e7c 11283 return SCROLLING_FAILED;
2311178e 11284
5f5c8ee5
GM
11285 /* Compute new window start. */
11286 start_display (&it, w, startp);
2311178e 11287
5f5c8ee5 11288 if (scroll_conservatively)
0894e696 11289 amount_to_scroll =
da8b7f4f 11290 max (dy, FRAME_LINE_HEIGHT (f) * max (scroll_step, temp_scroll_step));
5f5c8ee5
GM
11291 else if (scroll_step || temp_scroll_step)
11292 amount_to_scroll = scroll_max;
538f13d4 11293 else
5f5c8ee5 11294 {
46226c1d 11295 aggressive = current_buffer->scroll_down_aggressively;
da8b7f4f 11296 height = WINDOW_BOX_TEXT_HEIGHT (w);
5f5c8ee5
GM
11297 if (NUMBERP (aggressive))
11298 amount_to_scroll = XFLOATINT (aggressive) * height;
11299 }
a2725ab2 11300
5f5c8ee5 11301 if (amount_to_scroll <= 0)
cb617e7c 11302 return SCROLLING_FAILED;
2311178e 11303
5f5c8ee5
GM
11304 move_it_vertically (&it, - amount_to_scroll);
11305 startp = it.current.pos;
90adcf20
RS
11306 }
11307 }
a2889657 11308
5f5c8ee5
GM
11309 /* Run window scroll functions. */
11310 startp = run_window_scroll_functions (window, startp);
90adcf20 11311
5f5c8ee5
GM
11312 /* Display the window. Give up if new fonts are loaded, or if point
11313 doesn't appear. */
11314 if (!try_window (window, startp))
cb617e7c 11315 rc = SCROLLING_NEED_LARGER_MATRICES;
5f5c8ee5
GM
11316 else if (w->cursor.vpos < 0)
11317 {
11318 clear_glyph_matrix (w->desired_matrix);
cb617e7c 11319 rc = SCROLLING_FAILED;
5f5c8ee5
GM
11320 }
11321 else
11322 {
11323 /* Maybe forget recorded base line for line number display. */
2311178e 11324 if (!just_this_one_p
5f5c8ee5 11325 || current_buffer->clip_changed
9142dd5b 11326 || BEG_UNCHANGED < CHARPOS (startp))
5f5c8ee5 11327 w->base_line_number = Qnil;
2311178e 11328
ddf6b9a3
RS
11329 /* If cursor ends up on a partially visible line,
11330 treat that as being off the bottom of the screen. */
11331 if (! make_cursor_line_fully_visible (w))
ef3c2c73
RS
11332 {
11333 clear_glyph_matrix (w->desired_matrix);
03b0a4b4 11334 last_line_misfit = 1;
ef3c2c73
RS
11335 goto too_near_end;
11336 }
ddf6b9a3 11337 rc = SCROLLING_SUCCESS;
5f5c8ee5
GM
11338 }
11339
11340 return rc;
a2889657
JB
11341}
11342
5f5c8ee5
GM
11343
11344/* Compute a suitable window start for window W if display of W starts
11345 on a continuation line. Value is non-zero if a new window start
11346 was computed.
11347
11348 The new window start will be computed, based on W's width, starting
11349 from the start of the continued line. It is the start of the
11350 screen line with the minimum distance from the old start W->start. */
11351
11352static int
11353compute_window_start_on_continuation_line (w)
11354 struct window *w;
1f1ff51d 11355{
5f5c8ee5
GM
11356 struct text_pos pos, start_pos;
11357 int window_start_changed_p = 0;
1f1ff51d 11358
5f5c8ee5 11359 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
1f1ff51d 11360
5f5c8ee5 11361 /* If window start is on a continuation line... Window start may be
2311178e 11362 < BEGV in case there's invisible text at the start of the
5f5c8ee5
GM
11363 buffer (M-x rmail, for example). */
11364 if (CHARPOS (start_pos) > BEGV
11365 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
1f1ff51d 11366 {
5f5c8ee5
GM
11367 struct it it;
11368 struct glyph_row *row;
f3751a65
GM
11369
11370 /* Handle the case that the window start is out of range. */
11371 if (CHARPOS (start_pos) < BEGV)
11372 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
11373 else if (CHARPOS (start_pos) > ZV)
11374 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
2311178e 11375
5f5c8ee5
GM
11376 /* Find the start of the continued line. This should be fast
11377 because scan_buffer is fast (newline cache). */
045dee35 11378 row = w->desired_matrix->rows + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0);
5f5c8ee5
GM
11379 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
11380 row, DEFAULT_FACE_ID);
11381 reseat_at_previous_visible_line_start (&it);
11382
11383 /* If the line start is "too far" away from the window start,
11384 say it takes too much time to compute a new window start. */
11385 if (CHARPOS (start_pos) - IT_CHARPOS (it)
da8b7f4f 11386 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
5f5c8ee5
GM
11387 {
11388 int min_distance, distance;
2311178e 11389
5f5c8ee5
GM
11390 /* Move forward by display lines to find the new window
11391 start. If window width was enlarged, the new start can
11392 be expected to be > the old start. If window width was
11393 decreased, the new window start will be < the old start.
11394 So, we're looking for the display line start with the
11395 minimum distance from the old window start. */
11396 pos = it.current.pos;
11397 min_distance = INFINITY;
11398 while ((distance = abs (CHARPOS (start_pos) - IT_CHARPOS (it))),
11399 distance < min_distance)
11400 {
11401 min_distance = distance;
11402 pos = it.current.pos;
11403 move_it_by_lines (&it, 1, 0);
11404 }
2311178e 11405
5f5c8ee5
GM
11406 /* Set the window start there. */
11407 SET_MARKER_FROM_TEXT_POS (w->start, pos);
11408 window_start_changed_p = 1;
11409 }
1f1ff51d 11410 }
2311178e 11411
5f5c8ee5 11412 return window_start_changed_p;
1f1ff51d
KH
11413}
11414
5f5c8ee5 11415
1dd5768b 11416/* Try cursor movement in case text has not changed in window WINDOW,
47589c8c
GM
11417 with window start STARTP. Value is
11418
cb617e7c 11419 CURSOR_MOVEMENT_SUCCESS if successful
2311178e 11420
cb617e7c
GM
11421 CURSOR_MOVEMENT_CANNOT_BE_USED if this method cannot be used
11422
11423 CURSOR_MOVEMENT_MUST_SCROLL if we know we have to scroll the
11424 display. *SCROLL_STEP is set to 1, under certain circumstances, if
11425 we want to scroll as if scroll-step were set to 1. See the code.
11426
11427 CURSOR_MOVEMENT_NEED_LARGER_MATRICES if we need larger matrices, in
11428 which case we have to abort this redisplay, and adjust matrices
11429 first. */
11430
2311178e 11431enum
cb617e7c
GM
11432{
11433 CURSOR_MOVEMENT_SUCCESS,
11434 CURSOR_MOVEMENT_CANNOT_BE_USED,
11435 CURSOR_MOVEMENT_MUST_SCROLL,
11436 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
11437};
47589c8c
GM
11438
11439static int
11440try_cursor_movement (window, startp, scroll_step)
11441 Lisp_Object window;
11442 struct text_pos startp;
11443 int *scroll_step;
11444{
11445 struct window *w = XWINDOW (window);
11446 struct frame *f = XFRAME (w->frame);
cb617e7c 11447 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
2311178e 11448
69d1f7c9 11449#if GLYPH_DEBUG
76cb5e06
GM
11450 if (inhibit_try_cursor_movement)
11451 return rc;
11452#endif
11453
47589c8c
GM
11454 /* Handle case where text has not changed, only point, and it has
11455 not moved off the frame. */
11456 if (/* Point may be in this window. */
11457 PT >= CHARPOS (startp)
47589c8c
GM
11458 /* Selective display hasn't changed. */
11459 && !current_buffer->clip_changed
4db87380
GM
11460 /* Function force-mode-line-update is used to force a thorough
11461 redisplay. It sets either windows_or_buffers_changed or
11462 update_mode_lines. So don't take a shortcut here for these
11463 cases. */
11464 && !update_mode_lines
11465 && !windows_or_buffers_changed
5fb96e96 11466 && !cursor_type_changed
2311178e 11467 /* Can't use this case if highlighting a region. When a
47589c8c
GM
11468 region exists, cursor movement has to do more than just
11469 set the cursor. */
11470 && !(!NILP (Vtransient_mark_mode)
11471 && !NILP (current_buffer->mark_active))
11472 && NILP (w->region_showing)
11473 && NILP (Vshow_trailing_whitespace)
11474 /* Right after splitting windows, last_point may be nil. */
11475 && INTEGERP (w->last_point)
11476 /* This code is not used for mini-buffer for the sake of the case
11477 of redisplaying to replace an echo area message; since in
11478 that case the mini-buffer contents per se are usually
11479 unchanged. This code is of no real use in the mini-buffer
11480 since the handling of this_line_start_pos, etc., in redisplay
11481 handles the same cases. */
11482 && !EQ (window, minibuf_window)
11483 /* When splitting windows or for new windows, it happens that
11484 redisplay is called with a nil window_end_vpos or one being
11485 larger than the window. This should really be fixed in
11486 window.c. I don't have this on my list, now, so we do
11487 approximately the same as the old redisplay code. --gerd. */
11488 && INTEGERP (w->window_end_vpos)
11489 && XFASTINT (w->window_end_vpos) < w->current_matrix->nrows
11490 && (FRAME_WINDOW_P (f)
11491 || !MARKERP (Voverlay_arrow_position)
11492 || current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
11493 {
11494 int this_scroll_margin;
8ee5b6a3 11495 struct glyph_row *row = NULL;
47589c8c
GM
11496
11497#if GLYPH_DEBUG
11498 debug_method_add (w, "cursor movement");
11499#endif
11500
11501 /* Scroll if point within this distance from the top or bottom
11502 of the window. This is a pixel value. */
11503 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
11504 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
11505 this_scroll_margin *= FRAME_LINE_HEIGHT (f);
47589c8c
GM
11506
11507 /* Start with the row the cursor was displayed during the last
11508 not paused redisplay. Give up if that row is not valid. */
bd9d0f3f
GM
11509 if (w->last_cursor.vpos < 0
11510 || w->last_cursor.vpos >= w->current_matrix->nrows)
cb617e7c 11511 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11512 else
11513 {
11514 row = MATRIX_ROW (w->current_matrix, w->last_cursor.vpos);
11515 if (row->mode_line_p)
11516 ++row;
11517 if (!row->enabled_p)
cb617e7c 11518 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11519 }
11520
cb617e7c 11521 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
47589c8c
GM
11522 {
11523 int scroll_p = 0;
68c5d1db 11524 int last_y = window_text_bottom_y (w) - this_scroll_margin;
2311178e 11525
47589c8c
GM
11526 if (PT > XFASTINT (w->last_point))
11527 {
11528 /* Point has moved forward. */
47589c8c
GM
11529 while (MATRIX_ROW_END_CHARPOS (row) < PT
11530 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
11531 {
11532 xassert (row->enabled_p);
11533 ++row;
11534 }
11535
11536 /* The end position of a row equals the start position
11537 of the next row. If PT is there, we would rather
cafafe0b
GM
11538 display it in the next line. */
11539 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11540 && MATRIX_ROW_END_CHARPOS (row) == PT
11541 && !cursor_row_p (w, row))
11542 ++row;
47589c8c
GM
11543
11544 /* If within the scroll margin, scroll. Note that
11545 MATRIX_ROW_BOTTOM_Y gives the pixel position at which
11546 the next line would be drawn, and that
11547 this_scroll_margin can be zero. */
11548 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
11549 || PT > MATRIX_ROW_END_CHARPOS (row)
11550 /* Line is completely visible last line in window
11551 and PT is to be set in the next line. */
11552 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
11553 && PT == MATRIX_ROW_END_CHARPOS (row)
11554 && !row->ends_at_zv_p
11555 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
11556 scroll_p = 1;
11557 }
11558 else if (PT < XFASTINT (w->last_point))
11559 {
11560 /* Cursor has to be moved backward. Note that PT >=
11561 CHARPOS (startp) because of the outer
11562 if-statement. */
11563 while (!row->mode_line_p
11564 && (MATRIX_ROW_START_CHARPOS (row) > PT
11565 || (MATRIX_ROW_START_CHARPOS (row) == PT
11566 && MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)))
11567 && (row->y > this_scroll_margin
11568 || CHARPOS (startp) == BEGV))
11569 {
11570 xassert (row->enabled_p);
11571 --row;
11572 }
11573
11574 /* Consider the following case: Window starts at BEGV,
11575 there is invisible, intangible text at BEGV, so that
11576 display starts at some point START > BEGV. It can
11577 happen that we are called with PT somewhere between
11578 BEGV and START. Try to handle that case. */
11579 if (row < w->current_matrix->rows
11580 || row->mode_line_p)
11581 {
11582 row = w->current_matrix->rows;
11583 if (row->mode_line_p)
11584 ++row;
11585 }
11586
11587 /* Due to newlines in overlay strings, we may have to
11588 skip forward over overlay strings. */
68c5d1db
GM
11589 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
11590 && MATRIX_ROW_END_CHARPOS (row) == PT
11591 && !cursor_row_p (w, row))
47589c8c 11592 ++row;
2311178e 11593
47589c8c
GM
11594 /* If within the scroll margin, scroll. */
11595 if (row->y < this_scroll_margin
11596 && CHARPOS (startp) != BEGV)
11597 scroll_p = 1;
11598 }
11599
11600 if (PT < MATRIX_ROW_START_CHARPOS (row)
11601 || PT > MATRIX_ROW_END_CHARPOS (row))
11602 {
11603 /* if PT is not in the glyph row, give up. */
cb617e7c 11604 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c 11605 }
440fc135 11606 else if (MATRIX_ROW_PARTIALLY_VISIBLE_P (row))
47589c8c 11607 {
8de4aaf8
GM
11608 if (PT == MATRIX_ROW_END_CHARPOS (row)
11609 && !row->ends_at_zv_p
11610 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
cb617e7c 11611 rc = CURSOR_MOVEMENT_MUST_SCROLL;
3f7e3031 11612 else if (row->height > window_box_height (w))
440fc135 11613 {
8de4aaf8
GM
11614 /* If we end up in a partially visible line, let's
11615 make it fully visible, except when it's taller
11616 than the window, in which case we can't do much
11617 about it. */
440fc135 11618 *scroll_step = 1;
cb617e7c 11619 rc = CURSOR_MOVEMENT_MUST_SCROLL;
440fc135
GM
11620 }
11621 else
11622 {
11623 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 11624 if (!make_cursor_line_fully_visible (w))
ddf6b9a3 11625 rc = CURSOR_MOVEMENT_MUST_SCROLL;
cb617e7c
GM
11626 else
11627 rc = CURSOR_MOVEMENT_SUCCESS;
440fc135 11628 }
47589c8c
GM
11629 }
11630 else if (scroll_p)
cb617e7c 11631 rc = CURSOR_MOVEMENT_MUST_SCROLL;
47589c8c
GM
11632 else
11633 {
11634 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
cb617e7c 11635 rc = CURSOR_MOVEMENT_SUCCESS;
47589c8c
GM
11636 }
11637 }
11638 }
11639
11640 return rc;
11641}
11642
9a08d928
SM
11643void
11644set_vertical_scroll_bar (w)
11645 struct window *w;
11646{
11647 int start, end, whole;
11648
11649 /* Calculate the start and end positions for the current window.
11650 At some point, it would be nice to choose between scrollbars
11651 which reflect the whole buffer size, with special markers
11652 indicating narrowing, and scrollbars which reflect only the
11653 visible region.
11654
11655 Note that mini-buffers sometimes aren't displaying any text. */
11656 if (!MINI_WINDOW_P (w)
11657 || (w == XWINDOW (minibuf_window)
11658 && NILP (echo_area_buffer[0])))
11659 {
11660 struct buffer *buf = XBUFFER (w->buffer);
11661 whole = BUF_ZV (buf) - BUF_BEGV (buf);
11662 start = marker_position (w->start) - BUF_BEGV (buf);
11663 /* I don't think this is guaranteed to be right. For the
11664 moment, we'll pretend it is. */
11665 end = BUF_Z (buf) - XFASTINT (w->window_end_pos) - BUF_BEGV (buf);
11666
11667 if (end < start)
11668 end = start;
11669 if (whole < (end - start))
11670 whole = end - start;
11671 }
11672 else
11673 start = end = whole = 0;
11674
11675 /* Indicate what this scroll bar ought to be displaying now. */
11676 set_vertical_scroll_bar_hook (w, end - start, whole, start);
11677}
47589c8c 11678
7af0e8d7 11679#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
11680
11681/* Recalculate the bitmaps to show in the fringes of window W.
11682 If FORCE_P is 0, only mark rows with modified bitmaps for update in
11683 redraw_fringe_bitmaps_p; else mark all rows for update. */
11684
11685int
11686update_window_fringes (w, force_p)
11687 struct window *w;
11688 int force_p;
11689{
11690 struct glyph_row *row, *cur = 0;
11691 int yb = window_text_bottom_y (w);
11692 int rn, nrows = w->current_matrix->nrows;
11693 int y;
11694 int redraw_p = 0;
11695 Lisp_Object ind;
11696
11697 if (w->pseudo_window_p)
11698 return 0;
11699
11700 if (!MINI_WINDOW_P (w)
11701 && (ind = XBUFFER (w->buffer)->indicate_buffer_boundaries, !NILP (ind)))
11702 {
11703 int do_eob = 1, do_bob = 1;
11704
11705 for (y = 0, rn = 0;
11706 y < yb && rn < nrows;
11707 y += row->height, ++rn)
11708 {
11709 unsigned indicate_bob_p, indicate_top_line_p;
11710 unsigned indicate_eob_p, indicate_bottom_line_p;
11711
11712 row = w->desired_matrix->rows + rn;
11713 if (!row->enabled_p)
11714 row = w->current_matrix->rows + rn;
11715
11716 indicate_bob_p = row->indicate_bob_p;
11717 indicate_top_line_p = row->indicate_top_line_p;
11718 indicate_eob_p = row->indicate_eob_p;
11719 indicate_bottom_line_p = row->indicate_bottom_line_p;
11720
11721 row->indicate_bob_p = row->indicate_top_line_p = 0;
11722 row->indicate_eob_p = row->indicate_bottom_line_p = 0;
11723
11724 if (MATRIX_ROW_START_CHARPOS (row) <= BUF_BEGV (XBUFFER (w->buffer)))
11725 row->indicate_bob_p = do_bob, do_bob = 0;
11726 else if (EQ (ind, Qt)
11727 && (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0) == rn)
11728 row->indicate_top_line_p = 1;
11729
11730 if (MATRIX_ROW_END_CHARPOS (row) >= BUF_ZV (XBUFFER (w->buffer)))
11731 row->indicate_eob_p = do_eob, do_eob = 0;
11732 else if (EQ (ind, Qt)
11733 && y + row->height >= yb)
11734 row->indicate_bottom_line_p = 1;
11735
11736 if (indicate_bob_p != row->indicate_bob_p
11737 || indicate_top_line_p != row->indicate_top_line_p
11738 || indicate_eob_p != row->indicate_eob_p
11739 || indicate_bottom_line_p != row->indicate_bottom_line_p)
11740 row->redraw_fringe_bitmaps_p = 1;
11741 }
11742 }
11743
11744 for (y = 0, rn = 0;
11745 y < yb && rn < nrows;
11746 y += row->height, rn++)
11747 {
11748 enum fringe_bitmap_type left, right;
11749
11750 row = w->desired_matrix->rows + rn;
11751 cur = w->current_matrix->rows + rn;
11752 if (!row->enabled_p)
11753 row = cur;
11754
11755 /* Decide which bitmap to draw in the left fringe. */
11756 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
11757 left = NO_FRINGE_BITMAP;
11758 else if (row->overlay_arrow_p)
11759 left = OVERLAY_ARROW_BITMAP;
11760 else if (row->truncated_on_left_p)
11761 left = LEFT_TRUNCATION_BITMAP;
11762 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
11763 left = CONTINUATION_LINE_BITMAP;
11764 else if (row->indicate_empty_line_p)
11765 left = ZV_LINE_BITMAP;
11766 else if (row->indicate_bob_p)
11767 left = FIRST_LINE_BITMAP;
11768 else
11769 left = NO_FRINGE_BITMAP;
11770
11771 /* Decide which bitmap to draw in the right fringe. */
11772 if (WINDOW_RIGHT_FRINGE_WIDTH (w) == 0)
11773 right = NO_FRINGE_BITMAP;
11774 else if (row->truncated_on_right_p)
11775 right = RIGHT_TRUNCATION_BITMAP;
11776 else if (row->continued_p)
11777 right = CONTINUED_LINE_BITMAP;
11778 else if (row->indicate_eob_p)
11779 right = LAST_LINE_BITMAP;
11780 else if (row->indicate_top_line_p)
11781 right = UP_ARROW_BITMAP;
11782 else if (row->indicate_bottom_line_p)
11783 right = DOWN_ARROW_BITMAP;
11784 else if (row->indicate_empty_line_p && WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
11785 right = ZV_LINE_BITMAP;
11786 else
11787 right = NO_FRINGE_BITMAP;
11788
11789 if (force_p
11790 || row->y != cur->y
11791 || row->visible_height != cur->visible_height
11792 || left != cur->left_fringe_bitmap
11793 || right != cur->right_fringe_bitmap
11794 || cur->redraw_fringe_bitmaps_p)
11795 {
11796 redraw_p = row->redraw_fringe_bitmaps_p = cur->redraw_fringe_bitmaps_p = 1;
11797 cur->left_fringe_bitmap = left;
11798 cur->right_fringe_bitmap = right;
11799 }
11800
11801 row->left_fringe_bitmap = left;
11802 row->right_fringe_bitmap = right;
11803 }
11804
11805 return redraw_p;
11806}
11807
7af0e8d7 11808#endif /* HAVE_WINDOW_SYSTEM */
88e6b646 11809
5f5c8ee5 11810/* Redisplay leaf window WINDOW. JUST_THIS_ONE_P non-zero means only
b60c9653
RS
11811 selected_window is redisplayed.
11812
11813 We can return without actually redisplaying the window if
11814 fonts_changed_p is nonzero. In that case, redisplay_internal will
11815 retry. */
90adcf20 11816
a2889657 11817static void
5f5c8ee5 11818redisplay_window (window, just_this_one_p)
a2889657 11819 Lisp_Object window;
5f5c8ee5 11820 int just_this_one_p;
a2889657 11821{
5f5c8ee5
GM
11822 struct window *w = XWINDOW (window);
11823 struct frame *f = XFRAME (w->frame);
11824 struct buffer *buffer = XBUFFER (w->buffer);
a2889657 11825 struct buffer *old = current_buffer;
5f5c8ee5 11826 struct text_pos lpoint, opoint, startp;
e481f960 11827 int update_mode_line;
5f5c8ee5
GM
11828 int tem;
11829 struct it it;
11830 /* Record it now because it's overwritten. */
11831 int current_matrix_up_to_date_p = 0;
88e6b646 11832 int used_current_matrix_p = 0;
c62c1bb5
RS
11833 /* This is less strict than current_matrix_up_to_date_p.
11834 It indictes that the buffer contents and narrowing are unchanged. */
11835 int buffer_unchanged_p = 0;
5f5c8ee5 11836 int temp_scroll_step = 0;
331379bf 11837 int count = SPECPDL_INDEX ();
47589c8c 11838 int rc;
ddf6b9a3 11839 int centering_position;
03b0a4b4 11840 int last_line_misfit = 0;
a2889657 11841
5f5c8ee5
GM
11842 SET_TEXT_POS (lpoint, PT, PT_BYTE);
11843 opoint = lpoint;
a2889657 11844
5f5c8ee5
GM
11845 /* W must be a leaf window here. */
11846 xassert (!NILP (w->buffer));
11847#if GLYPH_DEBUG
11848 *w->desired_matrix->method = 0;
11849#endif
2e54982e
RS
11850
11851 specbind (Qinhibit_point_motion_hooks, Qt);
9142dd5b
GM
11852
11853 reconsider_clip_changes (w, buffer);
2311178e
TTN
11854
11855 /* Has the mode line to be updated? */
5f5c8ee5
GM
11856 update_mode_line = (!NILP (w->update_mode_line)
11857 || update_mode_lines
c62c1bb5
RS
11858 || buffer->clip_changed
11859 || buffer->prevent_redisplay_optimizations_p);
8de2d90b
JB
11860
11861 if (MINI_WINDOW_P (w))
11862 {
5f5c8ee5 11863 if (w == XWINDOW (echo_area_window)
c6e89d6c 11864 && !NILP (echo_area_buffer[0]))
5f5c8ee5
GM
11865 {
11866 if (update_mode_line)
11867 /* We may have to update a tty frame's menu bar or a
e037b9ec 11868 tool-bar. Example `M-x C-h C-h C-g'. */
5f5c8ee5
GM
11869 goto finish_menu_bars;
11870 else
11871 /* We've already displayed the echo area glyphs in this window. */
11872 goto finish_scroll_bars;
11873 }
b2b5455d
RS
11874 else if ((w != XWINDOW (minibuf_window)
11875 || minibuf_level == 0)
c0bcce6f
JPW
11876 /* When buffer is nonempty, redisplay window normally. */
11877 && BUF_Z (XBUFFER (w->buffer)) == BUF_BEG (XBUFFER (w->buffer))
3354fdcf
RS
11878 /* Quail displays non-mini buffers in minibuffer window.
11879 In that case, redisplay the window normally. */
b2b5455d 11880 && !NILP (Fmemq (w->buffer, Vminibuffer_list)))
8de2d90b 11881 {
3354fdcf
RS
11882 /* W is a mini-buffer window, but it's not active, so clear
11883 it. */
5f5c8ee5
GM
11884 int yb = window_text_bottom_y (w);
11885 struct glyph_row *row;
11886 int y;
11887
11888 for (y = 0, row = w->desired_matrix->rows;
11889 y < yb;
11890 y += row->height, ++row)
11891 blank_row (w, row, y);
88f22aff 11892 goto finish_scroll_bars;
8de2d90b 11893 }
c095a1dd
GM
11894
11895 clear_glyph_matrix (w->desired_matrix);
8de2d90b 11896 }
a2889657 11897
5f5c8ee5
GM
11898 /* Otherwise set up data on this window; select its buffer and point
11899 value. */
6a93695f
GM
11900 /* Really select the buffer, for the sake of buffer-local
11901 variables. */
11902 set_buffer_internal_1 (XBUFFER (w->buffer));
5f5c8ee5
GM
11903 SET_TEXT_POS (opoint, PT, PT_BYTE);
11904
11905 current_matrix_up_to_date_p
11906 = (!NILP (w->window_end_valid)
11907 && !current_buffer->clip_changed
c62c1bb5 11908 && !current_buffer->prevent_redisplay_optimizations_p
5f5c8ee5
GM
11909 && XFASTINT (w->last_modified) >= MODIFF
11910 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
e481f960 11911
c62c1bb5
RS
11912 buffer_unchanged_p
11913 = (!NILP (w->window_end_valid)
11914 && !current_buffer->clip_changed
3f1258d0 11915 && XFASTINT (w->last_modified) >= MODIFF
c62c1bb5
RS
11916 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF);
11917
5f5c8ee5
GM
11918 /* When windows_or_buffers_changed is non-zero, we can't rely on
11919 the window end being valid, so set it to nil there. */
11920 if (windows_or_buffers_changed)
11921 {
11922 /* If window starts on a continuation line, maybe adjust the
11923 window start in case the window's width changed. */
11924 if (XMARKER (w->start)->buffer == current_buffer)
11925 compute_window_start_on_continuation_line (w);
2311178e 11926
5f5c8ee5
GM
11927 w->window_end_valid = Qnil;
11928 }
12adba34 11929
5f5c8ee5
GM
11930 /* Some sanity checks. */
11931 CHECK_WINDOW_END (w);
11932 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
12adba34 11933 abort ();
5f5c8ee5 11934 if (BYTEPOS (opoint) < CHARPOS (opoint))
12adba34 11935 abort ();
a2889657 11936
28995e67
RS
11937 /* If %c is in mode line, update it if needed. */
11938 if (!NILP (w->column_number_displayed)
11939 /* This alternative quickly identifies a common case
11940 where no change is needed. */
11941 && !(PT == XFASTINT (w->last_point)
8850a573
RS
11942 && XFASTINT (w->last_modified) >= MODIFF
11943 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
2311178e
TTN
11944 && (XFASTINT (w->column_number_displayed)
11945 != (int) current_column ())) /* iftc */
11946 update_mode_line = 1;
28995e67 11947
5f5c8ee5
GM
11948 /* Count number of windows showing the selected buffer. An indirect
11949 buffer counts as its base buffer. */
11950 if (!just_this_one_p)
42640f83
RS
11951 {
11952 struct buffer *current_base, *window_base;
11953 current_base = current_buffer;
11954 window_base = XBUFFER (XWINDOW (selected_window)->buffer);
11955 if (current_base->base_buffer)
11956 current_base = current_base->base_buffer;
11957 if (window_base->base_buffer)
11958 window_base = window_base->base_buffer;
11959 if (current_base == window_base)
11960 buffer_shared++;
11961 }
a2889657 11962
5f5c8ee5
GM
11963 /* Point refers normally to the selected window. For any other
11964 window, set up appropriate value. */
a2889657
JB
11965 if (!EQ (window, selected_window))
11966 {
12adba34
RS
11967 int new_pt = XMARKER (w->pointm)->charpos;
11968 int new_pt_byte = marker_byte_position (w->pointm);
f67a0f51 11969 if (new_pt < BEGV)
a2889657 11970 {
f67a0f51 11971 new_pt = BEGV;
12adba34
RS
11972 new_pt_byte = BEGV_BYTE;
11973 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
a2889657 11974 }
f67a0f51 11975 else if (new_pt > (ZV - 1))
a2889657 11976 {
f67a0f51 11977 new_pt = ZV;
12adba34
RS
11978 new_pt_byte = ZV_BYTE;
11979 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
a2889657 11980 }
2311178e 11981
f67a0f51 11982 /* We don't use SET_PT so that the point-motion hooks don't run. */
12adba34 11983 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
a2889657
JB
11984 }
11985
f4faa47c 11986 /* If any of the character widths specified in the display table
5f5c8ee5
GM
11987 have changed, invalidate the width run cache. It's true that
11988 this may be a bit late to catch such changes, but the rest of
f4faa47c
JB
11989 redisplay goes (non-fatally) haywire when the display table is
11990 changed, so why should we worry about doing any better? */
11991 if (current_buffer->width_run_cache)
11992 {
f908610f 11993 struct Lisp_Char_Table *disptab = buffer_display_table ();
f4faa47c
JB
11994
11995 if (! disptab_matches_widthtab (disptab,
11996 XVECTOR (current_buffer->width_table)))
11997 {
11998 invalidate_region_cache (current_buffer,
11999 current_buffer->width_run_cache,
12000 BEG, Z);
12001 recompute_width_table (current_buffer, disptab);
12002 }
12003 }
12004
a2889657 12005 /* If window-start is screwed up, choose a new one. */
a2889657
JB
12006 if (XMARKER (w->start)->buffer != current_buffer)
12007 goto recenter;
12008
5f5c8ee5 12009 SET_TEXT_POS_FROM_MARKER (startp, w->start);
a2889657 12010
cf0df6ab
RS
12011 /* If someone specified a new starting point but did not insist,
12012 check whether it can be used. */
cfad01b4
GM
12013 if (!NILP (w->optional_new_start)
12014 && CHARPOS (startp) >= BEGV
12015 && CHARPOS (startp) <= ZV)
cf0df6ab
RS
12016 {
12017 w->optional_new_start = Qnil;
5f5c8ee5
GM
12018 start_display (&it, w, startp);
12019 move_it_to (&it, PT, 0, it.last_visible_y, -1,
12020 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
12021 if (IT_CHARPOS (it) == PT)
cf0df6ab 12022 w->force_start = Qt;
29b3ea63
KS
12023 /* IT may overshoot PT if text at PT is invisible. */
12024 else if (IT_CHARPOS (it) > PT && CHARPOS (startp) <= PT)
12025 w->force_start = Qt;
12026
12027
cf0df6ab
RS
12028 }
12029
8de2d90b 12030 /* Handle case where place to start displaying has been specified,
aa6d10fa 12031 unless the specified location is outside the accessible range. */
9472f927
GM
12032 if (!NILP (w->force_start)
12033 || w->frozen_window_start_p)
a2889657 12034 {
b60c9653
RS
12035 /* We set this later on if we have to adjust point. */
12036 int new_vpos = -1;
12037
e63574d7 12038 w->force_start = Qnil;
5f5c8ee5 12039 w->vscroll = 0;
b5174a51 12040 w->window_end_valid = Qnil;
5f5c8ee5
GM
12041
12042 /* Forget any recorded base line for line number display. */
c62c1bb5 12043 if (!buffer_unchanged_p)
5f5c8ee5
GM
12044 w->base_line_number = Qnil;
12045
75c43375
RS
12046 /* Redisplay the mode line. Select the buffer properly for that.
12047 Also, run the hook window-scroll-functions
12048 because we have scrolled. */
e63574d7
RS
12049 /* Note, we do this after clearing force_start because
12050 if there's an error, it is better to forget about force_start
12051 than to get into an infinite loop calling the hook functions
12052 and having them get more errors. */
75c43375
RS
12053 if (!update_mode_line
12054 || ! NILP (Vwindow_scroll_functions))
e481f960 12055 {
e481f960
RS
12056 update_mode_line = 1;
12057 w->update_mode_line = Qt;
5f5c8ee5 12058 startp = run_window_scroll_functions (window, startp);
e481f960 12059 }
2311178e 12060
ac90c44f
GM
12061 w->last_modified = make_number (0);
12062 w->last_overlay_modified = make_number (0);
5f5c8ee5
GM
12063 if (CHARPOS (startp) < BEGV)
12064 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
12065 else if (CHARPOS (startp) > ZV)
12066 SET_TEXT_POS (startp, ZV, ZV_BYTE);
2311178e
TTN
12067
12068 /* Redisplay, then check if cursor has been set during the
5f5c8ee5
GM
12069 redisplay. Give up if new fonts were loaded. */
12070 if (!try_window (window, startp))
12071 {
12072 w->force_start = Qt;
12073 clear_glyph_matrix (w->desired_matrix);
b60c9653 12074 goto need_larger_matrices;
5f5c8ee5
GM
12075 }
12076
9472f927 12077 if (w->cursor.vpos < 0 && !w->frozen_window_start_p)
5f5c8ee5 12078 {
b28cb6ed
GM
12079 /* If point does not appear, try to move point so it does
12080 appear. The desired matrix has been built above, so we
12081 can use it here. */
b60c9653
RS
12082 new_vpos = window_box_height (w) / 2;
12083 }
12084
12085 if (!make_cursor_line_fully_visible (w))
12086 {
12087 /* Point does appear, but on a line partly visible at end of window.
12088 Move it back to a fully-visible line. */
12089 new_vpos = window_box_height (w);
12090 }
12091
12092 /* If we need to move point for either of the above reasons,
12093 now actually do it. */
12094 if (new_vpos >= 0)
12095 {
b28cb6ed
GM
12096 struct glyph_row *row;
12097
b28cb6ed 12098 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
b60c9653 12099 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos)
5f5c8ee5
GM
12100 ++row;
12101
12102 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
12103 MATRIX_ROW_START_BYTEPOS (row));
12104
90adcf20 12105 if (w != XWINDOW (selected_window))
12adba34 12106 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
5f5c8ee5
GM
12107 else if (current_buffer == old)
12108 SET_TEXT_POS (lpoint, PT, PT_BYTE);
12109
12110 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
2311178e 12111
5f5c8ee5
GM
12112 /* If we are highlighting the region, then we just changed
12113 the region, so redisplay to show it. */
df0b5ea1
RS
12114 if (!NILP (Vtransient_mark_mode)
12115 && !NILP (current_buffer->mark_active))
6f27fa9b 12116 {
5f5c8ee5
GM
12117 clear_glyph_matrix (w->desired_matrix);
12118 if (!try_window (window, startp))
cb617e7c 12119 goto need_larger_matrices;
6f27fa9b 12120 }
a2889657 12121 }
5f5c8ee5 12122
5f5c8ee5
GM
12123#if GLYPH_DEBUG
12124 debug_method_add (w, "forced window start");
12125#endif
a2889657
JB
12126 goto done;
12127 }
12128
5f5c8ee5 12129 /* Handle case where text has not changed, only point, and it has
3f029ea0
RS
12130 not moved off the frame, and we are not retrying after hscroll.
12131 (current_matrix_up_to_date_p is nonzero when retrying.) */
12132 if (current_matrix_up_to_date_p
47589c8c 12133 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
cb617e7c 12134 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
a2889657 12135 {
cb617e7c
GM
12136 switch (rc)
12137 {
12138 case CURSOR_MOVEMENT_SUCCESS:
88e6b646 12139 used_current_matrix_p = 1;
cb617e7c 12140 goto done;
2311178e 12141
b60c9653 12142#if 0 /* try_cursor_movement never returns this value. */
cb617e7c
GM
12143 case CURSOR_MOVEMENT_NEED_LARGER_MATRICES:
12144 goto need_larger_matrices;
b60c9653 12145#endif
2311178e 12146
cb617e7c
GM
12147 case CURSOR_MOVEMENT_MUST_SCROLL:
12148 goto try_to_scroll;
2311178e 12149
cb617e7c
GM
12150 default:
12151 abort ();
12152 }
a2889657
JB
12153 }
12154 /* If current starting point was originally the beginning of a line
12155 but no longer is, find a new starting point. */
265a9e55 12156 else if (!NILP (w->start_at_line_beg)
5f5c8ee5
GM
12157 && !(CHARPOS (startp) <= BEGV
12158 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n'))
a2889657 12159 {
5f5c8ee5
GM
12160#if GLYPH_DEBUG
12161 debug_method_add (w, "recenter 1");
12162#endif
a2889657
JB
12163 goto recenter;
12164 }
2311178e 12165
27d16f05
GM
12166 /* Try scrolling with try_window_id. Value is > 0 if update has
12167 been done, it is -1 if we know that the same window start will
12168 not work. It is 0 if unsuccessful for some other reason. */
12169 else if ((tem = try_window_id (w)) != 0)
a2889657 12170 {
5f5c8ee5 12171#if GLYPH_DEBUG
ef121659 12172 debug_method_add (w, "try_window_id %d", tem);
5f5c8ee5
GM
12173#endif
12174
12175 if (fonts_changed_p)
cb617e7c 12176 goto need_larger_matrices;
a2889657
JB
12177 if (tem > 0)
12178 goto done;
ef121659 12179
5f5c8ee5
GM
12180 /* Otherwise try_window_id has returned -1 which means that we
12181 don't want the alternative below this comment to execute. */
a2889657 12182 }
5f5c8ee5
GM
12183 else if (CHARPOS (startp) >= BEGV
12184 && CHARPOS (startp) <= ZV
12185 && PT >= CHARPOS (startp)
12186 && (CHARPOS (startp) < ZV
e9874cee 12187 /* Avoid starting at end of buffer. */
5f5c8ee5 12188 || CHARPOS (startp) == BEGV
8850a573
RS
12189 || (XFASTINT (w->last_modified) >= MODIFF
12190 && XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
a2889657 12191 {
5f5c8ee5
GM
12192#if GLYPH_DEBUG
12193 debug_method_add (w, "same window start");
12194#endif
2311178e 12195
5f5c8ee5
GM
12196 /* Try to redisplay starting at same place as before.
12197 If point has not moved off frame, accept the results. */
12198 if (!current_matrix_up_to_date_p
12199 /* Don't use try_window_reusing_current_matrix in this case
15e26c76
GM
12200 because a window scroll function can have changed the
12201 buffer. */
5f5c8ee5
GM
12202 || !NILP (Vwindow_scroll_functions)
12203 || MINI_WINDOW_P (w)
88e6b646
KS
12204 || !(used_current_matrix_p =
12205 try_window_reusing_current_matrix (w)))
5f5c8ee5
GM
12206 {
12207 IF_DEBUG (debug_method_add (w, "1"));
12208 try_window (window, startp);
12209 }
12210
12211 if (fonts_changed_p)
cb617e7c 12212 goto need_larger_matrices;
2311178e 12213
5f5c8ee5 12214 if (w->cursor.vpos >= 0)
aa6d10fa 12215 {
2311178e 12216 if (!just_this_one_p
5f5c8ee5 12217 || current_buffer->clip_changed
9142dd5b 12218 || BEG_UNCHANGED < CHARPOS (startp))
aa6d10fa
RS
12219 /* Forget any recorded base line for line number display. */
12220 w->base_line_number = Qnil;
2311178e 12221
cb617e7c 12222 if (!make_cursor_line_fully_visible (w))
03b0a4b4
RS
12223 {
12224 clear_glyph_matrix (w->desired_matrix);
12225 last_line_misfit = 1;
12226 }
ddf6b9a3 12227 /* Drop through and scroll. */
ef3c2c73
RS
12228 else
12229 goto done;
aa6d10fa 12230 }
a2889657 12231 else
5f5c8ee5 12232 clear_glyph_matrix (w->desired_matrix);
a2889657
JB
12233 }
12234
5f5c8ee5
GM
12235 try_to_scroll:
12236
ac90c44f
GM
12237 w->last_modified = make_number (0);
12238 w->last_overlay_modified = make_number (0);
5f5c8ee5 12239
e481f960
RS
12240 /* Redisplay the mode line. Select the buffer properly for that. */
12241 if (!update_mode_line)
12242 {
e481f960
RS
12243 update_mode_line = 1;
12244 w->update_mode_line = Qt;
12245 }
a2889657 12246
5f5c8ee5
GM
12247 /* Try to scroll by specified few lines. */
12248 if ((scroll_conservatively
12249 || scroll_step
12250 || temp_scroll_step
12251 || NUMBERP (current_buffer->scroll_up_aggressively)
12252 || NUMBERP (current_buffer->scroll_down_aggressively))
09cacf9c 12253 && !current_buffer->clip_changed
2311178e 12254 && CHARPOS (startp) >= BEGV
5f5c8ee5 12255 && CHARPOS (startp) <= ZV)
0789adb2 12256 {
5f5c8ee5
GM
12257 /* The function returns -1 if new fonts were loaded, 1 if
12258 successful, 0 if not successful. */
12259 int rc = try_scrolling (window, just_this_one_p,
12260 scroll_conservatively,
12261 scroll_step,
03b0a4b4 12262 temp_scroll_step, last_line_misfit);
cb617e7c
GM
12263 switch (rc)
12264 {
12265 case SCROLLING_SUCCESS:
12266 goto done;
2311178e 12267
cb617e7c
GM
12268 case SCROLLING_NEED_LARGER_MATRICES:
12269 goto need_larger_matrices;
2311178e 12270
cb617e7c
GM
12271 case SCROLLING_FAILED:
12272 break;
2311178e 12273
cb617e7c
GM
12274 default:
12275 abort ();
12276 }
5f5c8ee5 12277 }
f9c8af06 12278
5f5c8ee5 12279 /* Finally, just choose place to start which centers point */
5936754e 12280
5f5c8ee5 12281 recenter:
ddf6b9a3
RS
12282 centering_position = window_box_height (w) / 2;
12283
12284 point_at_top:
12285 /* Jump here with centering_position already set to 0. */
44173109 12286
5f5c8ee5
GM
12287#if GLYPH_DEBUG
12288 debug_method_add (w, "recenter");
12289#endif
0789adb2 12290
5f5c8ee5 12291 /* w->vscroll = 0; */
0789adb2 12292
5f5c8ee5 12293 /* Forget any previously recorded base line for line number display. */
c62c1bb5 12294 if (!buffer_unchanged_p)
5f5c8ee5
GM
12295 w->base_line_number = Qnil;
12296
12297 /* Move backward half the height of the window. */
12298 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
12299 it.current_y = it.last_visible_y;
ddf6b9a3 12300 move_it_vertically_backward (&it, centering_position);
5f5c8ee5
GM
12301 xassert (IT_CHARPOS (it) >= BEGV);
12302
12303 /* The function move_it_vertically_backward may move over more
12304 than the specified y-distance. If it->w is small, e.g. a
12305 mini-buffer window, we may end up in front of the window's
12306 display area. Start displaying at the start of the line
12307 containing PT in this case. */
12308 if (it.current_y <= 0)
12309 {
12310 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
12311 move_it_vertically (&it, 0);
12312 xassert (IT_CHARPOS (it) <= PT);
12313 it.current_y = 0;
0789adb2
RS
12314 }
12315
5f5c8ee5 12316 it.current_x = it.hpos = 0;
2311178e 12317
5f5c8ee5
GM
12318 /* Set startp here explicitly in case that helps avoid an infinite loop
12319 in case the window-scroll-functions functions get errors. */
12320 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
12321
12322 /* Run scroll hooks. */
12323 startp = run_window_scroll_functions (window, it.current.pos);
12324
12325 /* Redisplay the window. */
12326 if (!current_matrix_up_to_date_p
12327 || windows_or_buffers_changed
5fb96e96 12328 || cursor_type_changed
5f5c8ee5
GM
12329 /* Don't use try_window_reusing_current_matrix in this case
12330 because it can have changed the buffer. */
12331 || !NILP (Vwindow_scroll_functions)
12332 || !just_this_one_p
12333 || MINI_WINDOW_P (w)
88e6b646
KS
12334 || !(used_current_matrix_p =
12335 try_window_reusing_current_matrix (w)))
5f5c8ee5
GM
12336 try_window (window, startp);
12337
12338 /* If new fonts have been loaded (due to fontsets), give up. We
12339 have to start a new redisplay since we need to re-adjust glyph
12340 matrices. */
12341 if (fonts_changed_p)
cb617e7c 12342 goto need_larger_matrices;
5f5c8ee5
GM
12343
12344 /* If cursor did not appear assume that the middle of the window is
12345 in the first line of the window. Do it again with the next line.
12346 (Imagine a window of height 100, displaying two lines of height
12347 60. Moving back 50 from it->last_visible_y will end in the first
12348 line.) */
12349 if (w->cursor.vpos < 0)
a2889657 12350 {
5f5c8ee5
GM
12351 if (!NILP (w->window_end_valid)
12352 && PT >= Z - XFASTINT (w->window_end_pos))
a2889657 12353 {
5f5c8ee5
GM
12354 clear_glyph_matrix (w->desired_matrix);
12355 move_it_by_lines (&it, 1, 0);
12356 try_window (window, it.current.pos);
a2889657 12357 }
5f5c8ee5 12358 else if (PT < IT_CHARPOS (it))
a2889657 12359 {
5f5c8ee5
GM
12360 clear_glyph_matrix (w->desired_matrix);
12361 move_it_by_lines (&it, -1, 0);
12362 try_window (window, it.current.pos);
12363 }
12364 else
12365 {
12366 /* Not much we can do about it. */
a2889657 12367 }
a2889657 12368 }
010494d0 12369
5f5c8ee5
GM
12370 /* Consider the following case: Window starts at BEGV, there is
12371 invisible, intangible text at BEGV, so that display starts at
12372 some point START > BEGV. It can happen that we are called with
12373 PT somewhere between BEGV and START. Try to handle that case. */
12374 if (w->cursor.vpos < 0)
835766b6 12375 {
5f5c8ee5
GM
12376 struct glyph_row *row = w->current_matrix->rows;
12377 if (row->mode_line_p)
12378 ++row;
12379 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
835766b6 12380 }
2311178e 12381
cb617e7c 12382 if (!make_cursor_line_fully_visible (w))
ddf6b9a3 12383 {
932357b4
KS
12384 /* If vscroll is enabled, disable it and try again. */
12385 if (w->vscroll)
12386 {
12387 w->vscroll = 0;
12388 clear_glyph_matrix (w->desired_matrix);
12389 goto recenter;
12390 }
2a6d0874 12391
ddf6b9a3
RS
12392 /* If centering point failed to make the whole line visible,
12393 put point at the top instead. That has to make the whole line
12394 visible, if it can be done. */
12395 centering_position = 0;
12396 goto point_at_top;
12397 }
b5174a51 12398
74d481ac
GM
12399 done:
12400
5f5c8ee5
GM
12401 SET_TEXT_POS_FROM_MARKER (startp, w->start);
12402 w->start_at_line_beg = ((CHARPOS (startp) == BEGV
12403 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n')
12404 ? Qt : Qnil);
a2889657 12405
5f5c8ee5 12406 /* Display the mode line, if we must. */
e481f960 12407 if ((update_mode_line
aa6d10fa 12408 /* If window not full width, must redo its mode line
2311178e 12409 if (a) the window to its side is being redone and
5f5c8ee5
GM
12410 (b) we do a frame-based redisplay. This is a consequence
12411 of how inverted lines are drawn in frame-based redisplay. */
2311178e 12412 || (!just_this_one_p
5f5c8ee5
GM
12413 && !FRAME_WINDOW_P (f)
12414 && !WINDOW_FULL_WIDTH_P (w))
12415 /* Line number to display. */
155ef550 12416 || INTEGERP (w->base_line_pos)
5f5c8ee5 12417 /* Column number is displayed and different from the one displayed. */
155ef550 12418 || (!NILP (w->column_number_displayed)
2311178e
TTN
12419 && (XFASTINT (w->column_number_displayed)
12420 != (int) current_column ()))) /* iftc */
5f5c8ee5
GM
12421 /* This means that the window has a mode line. */
12422 && (WINDOW_WANTS_MODELINE_P (w)
045dee35 12423 || WINDOW_WANTS_HEADER_LINE_P (w)))
5ba50c51 12424 {
5f5c8ee5
GM
12425 display_mode_lines (w);
12426
12427 /* If mode line height has changed, arrange for a thorough
12428 immediate redisplay using the correct mode line height. */
12429 if (WINDOW_WANTS_MODELINE_P (w)
12430 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
5ba50c51 12431 {
5f5c8ee5
GM
12432 fonts_changed_p = 1;
12433 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
12434 = DESIRED_MODE_LINE_HEIGHT (w);
5ba50c51 12435 }
2311178e 12436
5f5c8ee5
GM
12437 /* If top line height has changed, arrange for a thorough
12438 immediate redisplay using the correct mode line height. */
045dee35
GM
12439 if (WINDOW_WANTS_HEADER_LINE_P (w)
12440 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
5f5c8ee5
GM
12441 {
12442 fonts_changed_p = 1;
045dee35
GM
12443 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
12444 = DESIRED_HEADER_LINE_HEIGHT (w);
5f5c8ee5
GM
12445 }
12446
12447 if (fonts_changed_p)
cb617e7c 12448 goto need_larger_matrices;
5ba50c51 12449 }
5f5c8ee5
GM
12450
12451 if (!line_number_displayed
12452 && !BUFFERP (w->base_line_pos))
aa6d10fa
RS
12453 {
12454 w->base_line_pos = Qnil;
12455 w->base_line_number = Qnil;
12456 }
a2889657 12457
5f5c8ee5 12458 finish_menu_bars:
2311178e 12459
7ce2c095 12460 /* When we reach a frame's selected window, redo the frame's menu bar. */
e481f960 12461 if (update_mode_line
5f5c8ee5
GM
12462 && EQ (FRAME_SELECTED_WINDOW (f), window))
12463 {
12464 int redisplay_menu_p = 0;
488dd4c4 12465 int redisplay_tool_bar_p = 0;
5f5c8ee5
GM
12466
12467 if (FRAME_WINDOW_P (f))
12468 {
488dd4c4
JD
12469#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
12470 || defined (USE_GTK)
5f5c8ee5 12471 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
76412d64 12472#else
5f5c8ee5 12473 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
76412d64 12474#endif
5f5c8ee5
GM
12475 }
12476 else
12477 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
12478
12479 if (redisplay_menu_p)
12480 display_menu_bar (w);
12481
12482#ifdef HAVE_WINDOW_SYSTEM
488dd4c4
JD
12483#ifdef USE_GTK
12484 redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
12485#else
12486 redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
12487 && (FRAME_TOOL_BAR_LINES (f) > 0
12488 || auto_resize_tool_bars_p);
177c0ea7 12489
488dd4c4
JD
12490#endif
12491
12492 if (redisplay_tool_bar_p)
12493 redisplay_tool_bar (f);
5f5c8ee5
GM
12494#endif
12495 }
7ce2c095 12496
7af0e8d7 12497#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
12498 if (update_window_fringes (w, 0)
12499 && (used_current_matrix_p || overlay_arrow_seen)
12500 && !w->pseudo_window_p)
12501 {
12502 update_begin (f);
12503 BLOCK_INPUT;
12504 draw_window_fringes (w);
12505 UNBLOCK_INPUT;
12506 update_end (f);
12507 }
7af0e8d7 12508#endif /* HAVE_WINDOW_SYSTEM */
88e6b646 12509
b60c9653
RS
12510 /* We go to this label, with fonts_changed_p nonzero,
12511 if it is necessary to try again using larger glyph matrices.
12512 We have to redeem the scroll bar even in this case,
12513 because the loop in redisplay_internal expects that. */
cb617e7c
GM
12514 need_larger_matrices:
12515 ;
88f22aff 12516 finish_scroll_bars:
5f5c8ee5 12517
da8b7f4f 12518 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
30c566e4 12519 {
9a08d928
SM
12520 /* Set the thumb's position and size. */
12521 set_vertical_scroll_bar (w);
30c566e4 12522
5f5c8ee5
GM
12523 /* Note that we actually used the scroll bar attached to this
12524 window, so it shouldn't be deleted at the end of redisplay. */
504454e8 12525 redeem_scroll_bar_hook (w);
30c566e4 12526 }
b1d1124b 12527
5f5c8ee5
GM
12528 /* Restore current_buffer and value of point in it. */
12529 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
6a93695f 12530 set_buffer_internal_1 (old);
5f5c8ee5 12531 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
2e54982e
RS
12532
12533 unbind_to (count, Qnil);
a2889657 12534}
a2889657 12535
5f5c8ee5
GM
12536
12537/* Build the complete desired matrix of WINDOW with a window start
12538 buffer position POS. Value is non-zero if successful. It is zero
12539 if fonts were loaded during redisplay which makes re-adjusting
12540 glyph matrices necessary. */
12541
12542int
a2889657
JB
12543try_window (window, pos)
12544 Lisp_Object window;
5f5c8ee5
GM
12545 struct text_pos pos;
12546{
12547 struct window *w = XWINDOW (window);
12548 struct it it;
12549 struct glyph_row *last_text_row = NULL;
9cbab4ff 12550
5f5c8ee5
GM
12551 /* Make POS the new window start. */
12552 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
12adba34 12553
5f5c8ee5
GM
12554 /* Mark cursor position as unknown. No overlay arrow seen. */
12555 w->cursor.vpos = -1;
a2889657 12556 overlay_arrow_seen = 0;
642eefc6 12557
5f5c8ee5
GM
12558 /* Initialize iterator and info to start at POS. */
12559 start_display (&it, w, pos);
a2889657 12560
5f5c8ee5
GM
12561 /* Display all lines of W. */
12562 while (it.current_y < it.last_visible_y)
12563 {
12564 if (display_line (&it))
12565 last_text_row = it.glyph_row - 1;
12566 if (fonts_changed_p)
12567 return 0;
12568 }
a2889657 12569
5f5c8ee5
GM
12570 /* If bottom moved off end of frame, change mode line percentage. */
12571 if (XFASTINT (w->window_end_pos) <= 0
12572 && Z != IT_CHARPOS (it))
a2889657
JB
12573 w->update_mode_line = Qt;
12574
5f5c8ee5
GM
12575 /* Set window_end_pos to the offset of the last character displayed
12576 on the window from the end of current_buffer. Set
12577 window_end_vpos to its row number. */
12578 if (last_text_row)
12579 {
12580 xassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
12581 w->window_end_bytepos
12582 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12583 w->window_end_pos
12584 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12585 w->window_end_vpos
12586 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12587 xassert (MATRIX_ROW (w->desired_matrix, XFASTINT (w->window_end_vpos))
12588 ->displays_text_p);
12589 }
12590 else
12591 {
86bf3faa
RS
12592 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12593 w->window_end_pos = make_number (Z - ZV);
12594 w->window_end_vpos = make_number (0);
5f5c8ee5 12595 }
2311178e 12596
a2889657
JB
12597 /* But that is not valid info until redisplay finishes. */
12598 w->window_end_valid = Qnil;
5f5c8ee5 12599 return 1;
a2889657 12600}
5f5c8ee5
GM
12601
12602
a2889657 12603\f
5f5c8ee5
GM
12604/************************************************************************
12605 Window redisplay reusing current matrix when buffer has not changed
12606 ************************************************************************/
12607
12608/* Try redisplay of window W showing an unchanged buffer with a
12609 different window start than the last time it was displayed by
12610 reusing its current matrix. Value is non-zero if successful.
12611 W->start is the new window start. */
a2889657
JB
12612
12613static int
5f5c8ee5
GM
12614try_window_reusing_current_matrix (w)
12615 struct window *w;
a2889657 12616{
5f5c8ee5
GM
12617 struct frame *f = XFRAME (w->frame);
12618 struct glyph_row *row, *bottom_row;
12619 struct it it;
12620 struct run run;
12621 struct text_pos start, new_start;
12622 int nrows_scrolled, i;
12623 struct glyph_row *last_text_row;
12624 struct glyph_row *last_reused_text_row;
12625 struct glyph_row *start_row;
12626 int start_vpos, min_y, max_y;
75c5350a 12627
69d1f7c9 12628#if GLYPH_DEBUG
76cb5e06
GM
12629 if (inhibit_try_window_reusing)
12630 return 0;
12631#endif
12632
d18354b6
GM
12633 if (/* This function doesn't handle terminal frames. */
12634 !FRAME_WINDOW_P (f)
12635 /* Don't try to reuse the display if windows have been split
12636 or such. */
5fb96e96
RS
12637 || windows_or_buffers_changed
12638 || cursor_type_changed)
5f5c8ee5 12639 return 0;
a2889657 12640
5f5c8ee5
GM
12641 /* Can't do this if region may have changed. */
12642 if ((!NILP (Vtransient_mark_mode)
12643 && !NILP (current_buffer->mark_active))
8f897821
GM
12644 || !NILP (w->region_showing)
12645 || !NILP (Vshow_trailing_whitespace))
5f5c8ee5 12646 return 0;
a2889657 12647
5f5c8ee5 12648 /* If top-line visibility has changed, give up. */
045dee35
GM
12649 if (WINDOW_WANTS_HEADER_LINE_P (w)
12650 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
5f5c8ee5
GM
12651 return 0;
12652
12653 /* Give up if old or new display is scrolled vertically. We could
12654 make this function handle this, but right now it doesn't. */
12655 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
12656 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (start_row))
12657 return 0;
12658
12659 /* The variable new_start now holds the new window start. The old
12660 start `start' can be determined from the current matrix. */
12661 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
12662 start = start_row->start.pos;
12663 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
a2889657 12664
5f5c8ee5
GM
12665 /* Clear the desired matrix for the display below. */
12666 clear_glyph_matrix (w->desired_matrix);
2311178e 12667
5f5c8ee5
GM
12668 if (CHARPOS (new_start) <= CHARPOS (start))
12669 {
12670 int first_row_y;
2311178e 12671
607ec83c
GM
12672 /* Don't use this method if the display starts with an ellipsis
12673 displayed for invisible text. It's not easy to handle that case
12674 below, and it's certainly not worth the effort since this is
12675 not a frequent case. */
12676 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
12677 return 0;
12678
5f5c8ee5 12679 IF_DEBUG (debug_method_add (w, "twu1"));
2311178e 12680
5f5c8ee5
GM
12681 /* Display up to a row that can be reused. The variable
12682 last_text_row is set to the last row displayed that displays
b48f74cb
GM
12683 text. Note that it.vpos == 0 if or if not there is a
12684 header-line; it's not the same as the MATRIX_ROW_VPOS! */
5f5c8ee5
GM
12685 start_display (&it, w, new_start);
12686 first_row_y = it.current_y;
12687 w->cursor.vpos = -1;
12688 last_text_row = last_reused_text_row = NULL;
2311178e 12689
5f5c8ee5
GM
12690 while (it.current_y < it.last_visible_y
12691 && IT_CHARPOS (it) < CHARPOS (start)
12692 && !fonts_changed_p)
12693 if (display_line (&it))
12694 last_text_row = it.glyph_row - 1;
12695
12696 /* A value of current_y < last_visible_y means that we stopped
12697 at the previous window start, which in turn means that we
12698 have at least one reusable row. */
12699 if (it.current_y < it.last_visible_y)
a2889657 12700 {
b48f74cb 12701 /* IT.vpos always starts from 0; it counts text lines. */
5f5c8ee5 12702 nrows_scrolled = it.vpos;
2311178e 12703
5f5c8ee5
GM
12704 /* Find PT if not already found in the lines displayed. */
12705 if (w->cursor.vpos < 0)
a2889657 12706 {
5f5c8ee5 12707 int dy = it.current_y - first_row_y;
2311178e 12708
5f5c8ee5 12709 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
0df56f4d
GM
12710 row = row_containing_pos (w, PT, row, NULL, dy);
12711 if (row)
12712 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
12713 dy, nrows_scrolled);
12714 else
5f5c8ee5
GM
12715 {
12716 clear_glyph_matrix (w->desired_matrix);
12717 return 0;
12718 }
a2889657 12719 }
5f5c8ee5
GM
12720
12721 /* Scroll the display. Do it before the current matrix is
12722 changed. The problem here is that update has not yet
12723 run, i.e. part of the current matrix is not up to date.
12724 scroll_run_hook will clear the cursor, and use the
12725 current matrix to get the height of the row the cursor is
12726 in. */
12727 run.current_y = first_row_y;
12728 run.desired_y = it.current_y;
12729 run.height = it.last_visible_y - it.current_y;
b48f74cb
GM
12730
12731 if (run.height > 0 && run.current_y != run.desired_y)
a2889657 12732 {
5f5c8ee5
GM
12733 update_begin (f);
12734 rif->update_window_begin_hook (w);
fa3c6b4d 12735 rif->clear_window_mouse_face (w);
5f5c8ee5 12736 rif->scroll_run_hook (w, &run);
64d1e7d3 12737 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5 12738 update_end (f);
a2889657 12739 }
5f5c8ee5
GM
12740
12741 /* Shift current matrix down by nrows_scrolled lines. */
12742 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
12743 rotate_matrix (w->current_matrix,
12744 start_vpos,
12745 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12746 nrows_scrolled);
2311178e 12747
9c8b8382 12748 /* Disable lines that must be updated. */
5f5c8ee5 12749 for (i = 0; i < it.vpos; ++i)
b48f74cb 12750 (start_row + i)->enabled_p = 0;
9c8b8382 12751
5f5c8ee5 12752 /* Re-compute Y positions. */
da8b7f4f 12753 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12754 max_y = it.last_visible_y;
b48f74cb
GM
12755 for (row = start_row + nrows_scrolled;
12756 row < bottom_row;
12757 ++row)
d2f84654 12758 {
5f5c8ee5 12759 row->y = it.current_y;
75c5350a 12760 row->visible_height = row->height;
5f5c8ee5
GM
12761
12762 if (row->y < min_y)
75c5350a
GM
12763 row->visible_height -= min_y - row->y;
12764 if (row->y + row->height > max_y)
12765 row->visible_height -= row->y + row->height - max_y;
88e6b646 12766 row->redraw_fringe_bitmaps_p = 1;
2311178e 12767
5f5c8ee5 12768 it.current_y += row->height;
5f5c8ee5
GM
12769
12770 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
12771 last_reused_text_row = row;
12772 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
12773 break;
d2f84654 12774 }
2311178e 12775
9c8b8382
GM
12776 /* Disable lines in the current matrix which are now
12777 below the window. */
bafb434c 12778 for (++row; row < bottom_row; ++row)
9c8b8382 12779 row->enabled_p = 0;
a2889657 12780 }
5f5c8ee5
GM
12781
12782 /* Update window_end_pos etc.; last_reused_text_row is the last
12783 reused row from the current matrix containing text, if any.
12784 The value of last_text_row is the last displayed line
12785 containing text. */
12786 if (last_reused_text_row)
a2889657 12787 {
5f5c8ee5
GM
12788 w->window_end_bytepos
12789 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_reused_text_row);
ac90c44f
GM
12790 w->window_end_pos
12791 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_reused_text_row));
12792 w->window_end_vpos
12793 = make_number (MATRIX_ROW_VPOS (last_reused_text_row,
12794 w->current_matrix));
a2889657 12795 }
5f5c8ee5
GM
12796 else if (last_text_row)
12797 {
12798 w->window_end_bytepos
12799 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12800 w->window_end_pos
12801 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12802 w->window_end_vpos
12803 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12804 }
12805 else
12806 {
12807 /* This window must be completely empty. */
86bf3faa
RS
12808 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
12809 w->window_end_pos = make_number (Z - ZV);
12810 w->window_end_vpos = make_number (0);
5f5c8ee5
GM
12811 }
12812 w->window_end_valid = Qnil;
a2889657 12813
5f5c8ee5
GM
12814 /* Update hint: don't try scrolling again in update_window. */
12815 w->desired_matrix->no_scrolling_p = 1;
2311178e 12816
5f5c8ee5
GM
12817#if GLYPH_DEBUG
12818 debug_method_add (w, "try_window_reusing_current_matrix 1");
12819#endif
12820 return 1;
a2889657 12821 }
5f5c8ee5
GM
12822 else if (CHARPOS (new_start) > CHARPOS (start))
12823 {
12824 struct glyph_row *pt_row, *row;
12825 struct glyph_row *first_reusable_row;
12826 struct glyph_row *first_row_to_display;
12827 int dy;
12828 int yb = window_text_bottom_y (w);
12829
5f5c8ee5
GM
12830 /* Find the row starting at new_start, if there is one. Don't
12831 reuse a partially visible line at the end. */
b48f74cb 12832 first_reusable_row = start_row;
5f5c8ee5
GM
12833 while (first_reusable_row->enabled_p
12834 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
12835 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12836 < CHARPOS (new_start)))
12837 ++first_reusable_row;
12838
12839 /* Give up if there is no row to reuse. */
12840 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
28514cd9
GM
12841 || !first_reusable_row->enabled_p
12842 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
12843 != CHARPOS (new_start)))
5f5c8ee5
GM
12844 return 0;
12845
5f5c8ee5
GM
12846 /* We can reuse fully visible rows beginning with
12847 first_reusable_row to the end of the window. Set
12848 first_row_to_display to the first row that cannot be reused.
12849 Set pt_row to the row containing point, if there is any. */
5f5c8ee5 12850 pt_row = NULL;
ac90c44f
GM
12851 for (first_row_to_display = first_reusable_row;
12852 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
12853 ++first_row_to_display)
5f5c8ee5 12854 {
4bde0ebb
GM
12855 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
12856 && PT < MATRIX_ROW_END_CHARPOS (first_row_to_display))
5f5c8ee5 12857 pt_row = first_row_to_display;
5f5c8ee5 12858 }
a2889657 12859
5f5c8ee5
GM
12860 /* Start displaying at the start of first_row_to_display. */
12861 xassert (first_row_to_display->y < yb);
12862 init_to_row_start (&it, w, first_row_to_display);
607ec83c 12863
b48f74cb
GM
12864 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
12865 - start_vpos);
5f5c8ee5
GM
12866 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
12867 - nrows_scrolled);
b48f74cb 12868 it.current_y = (first_row_to_display->y - first_reusable_row->y
da8b7f4f 12869 + WINDOW_HEADER_LINE_HEIGHT (w));
5f5c8ee5
GM
12870
12871 /* Display lines beginning with first_row_to_display in the
12872 desired matrix. Set last_text_row to the last row displayed
12873 that displays text. */
12874 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
12875 if (pt_row == NULL)
12876 w->cursor.vpos = -1;
12877 last_text_row = NULL;
12878 while (it.current_y < it.last_visible_y && !fonts_changed_p)
12879 if (display_line (&it))
12880 last_text_row = it.glyph_row - 1;
12881
12882 /* Give up If point isn't in a row displayed or reused. */
12883 if (w->cursor.vpos < 0)
12884 {
12885 clear_glyph_matrix (w->desired_matrix);
12886 return 0;
12887 }
12adba34 12888
5f5c8ee5
GM
12889 /* If point is in a reused row, adjust y and vpos of the cursor
12890 position. */
12891 if (pt_row)
12892 {
12893 w->cursor.vpos -= MATRIX_ROW_VPOS (first_reusable_row,
12894 w->current_matrix);
12895 w->cursor.y -= first_reusable_row->y;
a2889657
JB
12896 }
12897
5f5c8ee5
GM
12898 /* Scroll the display. */
12899 run.current_y = first_reusable_row->y;
da8b7f4f 12900 run.desired_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12901 run.height = it.last_visible_y - run.current_y;
4da61803 12902 dy = run.current_y - run.desired_y;
2311178e 12903
5f5c8ee5
GM
12904 if (run.height)
12905 {
5f5c8ee5
GM
12906 update_begin (f);
12907 rif->update_window_begin_hook (w);
fa3c6b4d 12908 rif->clear_window_mouse_face (w);
5f5c8ee5 12909 rif->scroll_run_hook (w, &run);
64d1e7d3 12910 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
12911 update_end (f);
12912 }
a2889657 12913
5f5c8ee5
GM
12914 /* Adjust Y positions of reused rows. */
12915 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
da8b7f4f 12916 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
5f5c8ee5 12917 max_y = it.last_visible_y;
b48f74cb 12918 for (row = first_reusable_row; row < first_row_to_display; ++row)
5f5c8ee5
GM
12919 {
12920 row->y -= dy;
75c5350a 12921 row->visible_height = row->height;
5f5c8ee5 12922 if (row->y < min_y)
75c5350a
GM
12923 row->visible_height -= min_y - row->y;
12924 if (row->y + row->height > max_y)
12925 row->visible_height -= row->y + row->height - max_y;
88e6b646 12926 row->redraw_fringe_bitmaps_p = 1;
5f5c8ee5 12927 }
a2889657 12928
5f5c8ee5
GM
12929 /* Scroll the current matrix. */
12930 xassert (nrows_scrolled > 0);
12931 rotate_matrix (w->current_matrix,
12932 start_vpos,
12933 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
12934 -nrows_scrolled);
12935
ac90c44f
GM
12936 /* Disable rows not reused. */
12937 for (row -= nrows_scrolled; row < bottom_row; ++row)
12938 row->enabled_p = 0;
12939
5f5c8ee5
GM
12940 /* Adjust window end. A null value of last_text_row means that
12941 the window end is in reused rows which in turn means that
12942 only its vpos can have changed. */
12943 if (last_text_row)
12944 {
12945 w->window_end_bytepos
12946 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
12947 w->window_end_pos
12948 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
12949 w->window_end_vpos
12950 = make_number (MATRIX_ROW_VPOS (last_text_row, w->desired_matrix));
5f5c8ee5
GM
12951 }
12952 else
a2889657 12953 {
ac90c44f
GM
12954 w->window_end_vpos
12955 = make_number (XFASTINT (w->window_end_vpos) - nrows_scrolled);
a2889657 12956 }
2311178e 12957
5f5c8ee5
GM
12958 w->window_end_valid = Qnil;
12959 w->desired_matrix->no_scrolling_p = 1;
12960
12961#if GLYPH_DEBUG
12962 debug_method_add (w, "try_window_reusing_current_matrix 2");
12963#endif
12964 return 1;
a2889657 12965 }
2311178e 12966
5f5c8ee5
GM
12967 return 0;
12968}
a2889657 12969
a2889657 12970
5f5c8ee5
GM
12971\f
12972/************************************************************************
12973 Window redisplay reusing current matrix when buffer has changed
12974 ************************************************************************/
12975
1ec185cb
GM
12976static struct glyph_row *find_last_unchanged_at_beg_row P_ ((struct window *));
12977static struct glyph_row *find_first_unchanged_at_end_row P_ ((struct window *,
5f5c8ee5
GM
12978 int *, int *));
12979static struct glyph_row *
12980find_last_row_displaying_text P_ ((struct glyph_matrix *, struct it *,
12981 struct glyph_row *));
12982
12983
12984/* Return the last row in MATRIX displaying text. If row START is
12985 non-null, start searching with that row. IT gives the dimensions
12986 of the display. Value is null if matrix is empty; otherwise it is
12987 a pointer to the row found. */
12988
12989static struct glyph_row *
12990find_last_row_displaying_text (matrix, it, start)
12991 struct glyph_matrix *matrix;
12992 struct it *it;
12993 struct glyph_row *start;
12994{
12995 struct glyph_row *row, *row_found;
12996
12997 /* Set row_found to the last row in IT->w's current matrix
12998 displaying text. The loop looks funny but think of partially
12999 visible lines. */
13000 row_found = NULL;
13001 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
13002 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
13003 {
13004 xassert (row->enabled_p);
13005 row_found = row;
13006 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
13007 break;
13008 ++row;
a2889657 13009 }
2311178e 13010
5f5c8ee5
GM
13011 return row_found;
13012}
13013
a2889657 13014
5f5c8ee5 13015/* Return the last row in the current matrix of W that is not affected
d43fbe9d
GM
13016 by changes at the start of current_buffer that occurred since W's
13017 current matrix was built. Value is null if no such row exists.
a2889657 13018
d43fbe9d
GM
13019 BEG_UNCHANGED us the number of characters unchanged at the start of
13020 current_buffer. BEG + BEG_UNCHANGED is the buffer position of the
13021 first changed character in current_buffer. Characters at positions <
13022 BEG + BEG_UNCHANGED are at the same buffer positions as they were
13023 when the current matrix was built. */
5f5c8ee5
GM
13024
13025static struct glyph_row *
1ec185cb 13026find_last_unchanged_at_beg_row (w)
5f5c8ee5
GM
13027 struct window *w;
13028{
9142dd5b 13029 int first_changed_pos = BEG + BEG_UNCHANGED;
5f5c8ee5
GM
13030 struct glyph_row *row;
13031 struct glyph_row *row_found = NULL;
13032 int yb = window_text_bottom_y (w);
13033
13034 /* Find the last row displaying unchanged text. */
13035 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
13036 while (MATRIX_ROW_DISPLAYS_TEXT_P (row)
13037 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos)
a2889657 13038 {
5f5c8ee5
GM
13039 if (/* If row ends before first_changed_pos, it is unchanged,
13040 except in some case. */
13041 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
13042 /* When row ends in ZV and we write at ZV it is not
13043 unchanged. */
13044 && !row->ends_at_zv_p
13045 /* When first_changed_pos is the end of a continued line,
13046 row is not unchanged because it may be no longer
13047 continued. */
13048 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
88e6b646
KS
13049 && (row->continued_p
13050 || row->exact_window_width_line_p)))
5f5c8ee5
GM
13051 row_found = row;
13052
13053 /* Stop if last visible row. */
13054 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
13055 break;
2311178e 13056
5f5c8ee5 13057 ++row;
a2889657
JB
13058 }
13059
5f5c8ee5 13060 return row_found;
a2889657 13061}
5f5c8ee5
GM
13062
13063
13064/* Find the first glyph row in the current matrix of W that is not
2311178e 13065 affected by changes at the end of current_buffer since the
d43fbe9d
GM
13066 time W's current matrix was built.
13067
13068 Return in *DELTA the number of chars by which buffer positions in
13069 unchanged text at the end of current_buffer must be adjusted.
2311178e 13070
d43fbe9d
GM
13071 Return in *DELTA_BYTES the corresponding number of bytes.
13072
13073 Value is null if no such row exists, i.e. all rows are affected by
13074 changes. */
2311178e 13075
5f5c8ee5 13076static struct glyph_row *
1ec185cb 13077find_first_unchanged_at_end_row (w, delta, delta_bytes)
5f5c8ee5
GM
13078 struct window *w;
13079 int *delta, *delta_bytes;
a2889657 13080{
5f5c8ee5
GM
13081 struct glyph_row *row;
13082 struct glyph_row *row_found = NULL;
c581d710 13083
5f5c8ee5 13084 *delta = *delta_bytes = 0;
b2a76982 13085
1ec185cb
GM
13086 /* Display must not have been paused, otherwise the current matrix
13087 is not up to date. */
13088 if (NILP (w->window_end_valid))
13089 abort ();
2311178e 13090
1ec185cb 13091 /* A value of window_end_pos >= END_UNCHANGED means that the window
5f5c8ee5
GM
13092 end is in the range of changed text. If so, there is no
13093 unchanged row at the end of W's current matrix. */
9142dd5b 13094 if (XFASTINT (w->window_end_pos) >= END_UNCHANGED)
5f5c8ee5
GM
13095 return NULL;
13096
13097 /* Set row to the last row in W's current matrix displaying text. */
13098 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
2311178e
TTN
13099
13100 /* If matrix is entirely empty, no unchanged row exists. */
5f5c8ee5
GM
13101 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
13102 {
13103 /* The value of row is the last glyph row in the matrix having a
13104 meaningful buffer position in it. The end position of row
13105 corresponds to window_end_pos. This allows us to translate
13106 buffer positions in the current matrix to current buffer
13107 positions for characters not in changed text. */
13108 int Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
13109 int Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
13110 int last_unchanged_pos, last_unchanged_pos_old;
13111 struct glyph_row *first_text_row
13112 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
13113
13114 *delta = Z - Z_old;
13115 *delta_bytes = Z_BYTE - Z_BYTE_old;
13116
13117 /* Set last_unchanged_pos to the buffer position of the last
13118 character in the buffer that has not been changed. Z is the
d43fbe9d
GM
13119 index + 1 of the last character in current_buffer, i.e. by
13120 subtracting END_UNCHANGED we get the index of the last
5f5c8ee5
GM
13121 unchanged character, and we have to add BEG to get its buffer
13122 position. */
9142dd5b 13123 last_unchanged_pos = Z - END_UNCHANGED + BEG;
5f5c8ee5 13124 last_unchanged_pos_old = last_unchanged_pos - *delta;
2311178e 13125
5f5c8ee5
GM
13126 /* Search backward from ROW for a row displaying a line that
13127 starts at a minimum position >= last_unchanged_pos_old. */
1ec185cb 13128 for (; row > first_text_row; --row)
5f5c8ee5 13129 {
1ec185cb
GM
13130 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
13131 abort ();
2311178e 13132
5f5c8ee5
GM
13133 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
13134 row_found = row;
5f5c8ee5
GM
13135 }
13136 }
13137
1ec185cb
GM
13138 if (row_found && !MATRIX_ROW_DISPLAYS_TEXT_P (row_found))
13139 abort ();
2311178e 13140
5f5c8ee5 13141 return row_found;
c581d710
RS
13142}
13143
c581d710 13144
5f5c8ee5
GM
13145/* Make sure that glyph rows in the current matrix of window W
13146 reference the same glyph memory as corresponding rows in the
13147 frame's frame matrix. This function is called after scrolling W's
13148 current matrix on a terminal frame in try_window_id and
13149 try_window_reusing_current_matrix. */
13150
13151static void
13152sync_frame_with_window_matrix_rows (w)
13153 struct window *w;
c581d710 13154{
5f5c8ee5
GM
13155 struct frame *f = XFRAME (w->frame);
13156 struct glyph_row *window_row, *window_row_end, *frame_row;
13157
13158 /* Preconditions: W must be a leaf window and full-width. Its frame
13159 must have a frame matrix. */
13160 xassert (NILP (w->hchild) && NILP (w->vchild));
13161 xassert (WINDOW_FULL_WIDTH_P (w));
13162 xassert (!FRAME_WINDOW_P (f));
13163
13164 /* If W is a full-width window, glyph pointers in W's current matrix
13165 have, by definition, to be the same as glyph pointers in the
7d4cc828
GM
13166 corresponding frame matrix. Note that frame matrices have no
13167 marginal areas (see build_frame_matrix). */
5f5c8ee5
GM
13168 window_row = w->current_matrix->rows;
13169 window_row_end = window_row + w->current_matrix->nrows;
da8b7f4f 13170 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
5f5c8ee5 13171 while (window_row < window_row_end)
659a218f 13172 {
7d4cc828
GM
13173 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
13174 struct glyph *end = window_row->glyphs[LAST_AREA];
13175
13176 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
13177 frame_row->glyphs[TEXT_AREA] = start;
13178 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
13179 frame_row->glyphs[LAST_AREA] = end;
f002db93
GM
13180
13181 /* Disable frame rows whose corresponding window rows have
13182 been disabled in try_window_id. */
13183 if (!window_row->enabled_p)
13184 frame_row->enabled_p = 0;
2311178e 13185
5f5c8ee5 13186 ++window_row, ++frame_row;
659a218f 13187 }
a2889657 13188}
5f5c8ee5
GM
13189
13190
e037b9ec
GM
13191/* Find the glyph row in window W containing CHARPOS. Consider all
13192 rows between START and END (not inclusive). END null means search
13193 all rows to the end of the display area of W. Value is the row
13194 containing CHARPOS or null. */
13195
0bef35bc 13196struct glyph_row *
0df56f4d 13197row_containing_pos (w, charpos, start, end, dy)
e037b9ec
GM
13198 struct window *w;
13199 int charpos;
13200 struct glyph_row *start, *end;
0df56f4d 13201 int dy;
e037b9ec
GM
13202{
13203 struct glyph_row *row = start;
13204 int last_y;
13205
13206 /* If we happen to start on a header-line, skip that. */
13207 if (row->mode_line_p)
13208 ++row;
2311178e 13209
e037b9ec
GM
13210 if ((end && row >= end) || !row->enabled_p)
13211 return NULL;
2311178e 13212
0df56f4d 13213 last_y = window_text_bottom_y (w) - dy;
2311178e 13214
5cce13dd
RS
13215 while (1)
13216 {
13217 /* Give up if we have gone too far. */
13218 if (end && row >= end)
13219 return NULL;
40a301b3
RS
13220 /* This formerly returned if they were equal.
13221 I think that both quantities are of a "last plus one" type;
13222 if so, when they are equal, the row is within the screen. -- rms. */
13223 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
5cce13dd
RS
13224 return NULL;
13225
13226 /* If it is in this row, return this row. */
13227 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
e037b9ec 13228 || (MATRIX_ROW_END_CHARPOS (row) == charpos
0df56f4d
GM
13229 /* The end position of a row equals the start
13230 position of the next row. If CHARPOS is there, we
13231 would rather display it in the next line, except
13232 when this line ends in ZV. */
13233 && !row->ends_at_zv_p
5cce13dd
RS
13234 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
13235 && charpos >= MATRIX_ROW_START_CHARPOS (row))
13236 return row;
13237 ++row;
13238 }
e037b9ec
GM
13239}
13240
13241
5f5c8ee5
GM
13242/* Try to redisplay window W by reusing its existing display. W's
13243 current matrix must be up to date when this function is called,
13244 i.e. window_end_valid must not be nil.
13245
13246 Value is
13247
13248 1 if display has been updated
13249 0 if otherwise unsuccessful
13250 -1 if redisplay with same window start is known not to succeed
13251
13252 The following steps are performed:
13253
13254 1. Find the last row in the current matrix of W that is not
13255 affected by changes at the start of current_buffer. If no such row
13256 is found, give up.
13257
13258 2. Find the first row in W's current matrix that is not affected by
13259 changes at the end of current_buffer. Maybe there is no such row.
13260
13261 3. Display lines beginning with the row + 1 found in step 1 to the
13262 row found in step 2 or, if step 2 didn't find a row, to the end of
13263 the window.
13264
13265 4. If cursor is not known to appear on the window, give up.
13266
13267 5. If display stopped at the row found in step 2, scroll the
13268 display and current matrix as needed.
13269
13270 6. Maybe display some lines at the end of W, if we must. This can
13271 happen under various circumstances, like a partially visible line
13272 becoming fully visible, or because newly displayed lines are displayed
13273 in smaller font sizes.
13274
13275 7. Update W's window end information. */
13276
12adba34 13277static int
5f5c8ee5 13278try_window_id (w)
12adba34 13279 struct window *w;
12adba34 13280{
5f5c8ee5
GM
13281 struct frame *f = XFRAME (w->frame);
13282 struct glyph_matrix *current_matrix = w->current_matrix;
13283 struct glyph_matrix *desired_matrix = w->desired_matrix;
13284 struct glyph_row *last_unchanged_at_beg_row;
13285 struct glyph_row *first_unchanged_at_end_row;
13286 struct glyph_row *row;
13287 struct glyph_row *bottom_row;
13288 int bottom_vpos;
13289 struct it it;
13290 int delta = 0, delta_bytes = 0, stop_pos, dvpos, dy;
13291 struct text_pos start_pos;
13292 struct run run;
13293 int first_unchanged_at_end_vpos = 0;
13294 struct glyph_row *last_text_row, *last_text_row_at_end;
13295 struct text_pos start;
27d16f05 13296 int first_changed_charpos, last_changed_charpos;
5f5c8ee5 13297
69d1f7c9 13298#if GLYPH_DEBUG
76cb5e06
GM
13299 if (inhibit_try_window_id)
13300 return 0;
13301#endif
13302
27d16f05
GM
13303 /* This is handy for debugging. */
13304#if 0
13305#define GIVE_UP(X) \
13306 do { \
13307 fprintf (stderr, "try_window_id give up %d\n", (X)); \
13308 return 0; \
13309 } while (0)
13310#else
62397849 13311#define GIVE_UP(X) return 0
27d16f05 13312#endif
2311178e 13313
5f5c8ee5
GM
13314 SET_TEXT_POS_FROM_MARKER (start, w->start);
13315
27d16f05
GM
13316 /* Don't use this for mini-windows because these can show
13317 messages and mini-buffers, and we don't handle that here. */
13318 if (MINI_WINDOW_P (w))
13319 GIVE_UP (1);
2311178e 13320
27d16f05 13321 /* This flag is used to prevent redisplay optimizations. */
5fb96e96 13322 if (windows_or_buffers_changed || cursor_type_changed)
27d16f05 13323 GIVE_UP (2);
2311178e 13324
c62c1bb5
RS
13325 /* Verify that narrowing has not changed.
13326 Also verify that we were not told to prevent redisplay optimizations.
13327 It would be nice to further
27d16f05 13328 reduce the number of cases where this prevents try_window_id. */
c62c1bb5
RS
13329 if (current_buffer->clip_changed
13330 || current_buffer->prevent_redisplay_optimizations_p)
27d16f05
GM
13331 GIVE_UP (3);
13332
13333 /* Window must either use window-based redisplay or be full width. */
13334 if (!FRAME_WINDOW_P (f)
13335 && (!line_ins_del_ok
13336 || !WINDOW_FULL_WIDTH_P (w)))
13337 GIVE_UP (4);
5f5c8ee5 13338
f5376658 13339 /* Give up if point is not known NOT to appear in W. */
27d16f05
GM
13340 if (PT < CHARPOS (start))
13341 GIVE_UP (5);
13342
13343 /* Another way to prevent redisplay optimizations. */
13344 if (XFASTINT (w->last_modified) == 0)
13345 GIVE_UP (6);
2311178e 13346
f5376658 13347 /* Verify that window is not hscrolled. */
27d16f05
GM
13348 if (XFASTINT (w->hscroll) != 0)
13349 GIVE_UP (7);
2311178e 13350
f5376658 13351 /* Verify that display wasn't paused. */
27d16f05
GM
13352 if (NILP (w->window_end_valid))
13353 GIVE_UP (8);
2311178e 13354
27d16f05
GM
13355 /* Can't use this if highlighting a region because a cursor movement
13356 will do more than just set the cursor. */
13357 if (!NILP (Vtransient_mark_mode)
13358 && !NILP (current_buffer->mark_active))
13359 GIVE_UP (9);
13360
13361 /* Likewise if highlighting trailing whitespace. */
13362 if (!NILP (Vshow_trailing_whitespace))
13363 GIVE_UP (11);
2311178e 13364
27d16f05
GM
13365 /* Likewise if showing a region. */
13366 if (!NILP (w->region_showing))
13367 GIVE_UP (10);
2311178e 13368
27d16f05
GM
13369 /* Can use this if overlay arrow position and or string have changed. */
13370 if (!EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
13371 || !EQ (last_arrow_string, Voverlay_arrow_string))
13372 GIVE_UP (12);
13373
2311178e 13374
5f5c8ee5
GM
13375 /* Make sure beg_unchanged and end_unchanged are up to date. Do it
13376 only if buffer has really changed. The reason is that the gap is
13377 initially at Z for freshly visited files. The code below would
13378 set end_unchanged to 0 in that case. */
28ee91c0
GM
13379 if (MODIFF > SAVE_MODIFF
13380 /* This seems to happen sometimes after saving a buffer. */
13381 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
5f5c8ee5 13382 {
9142dd5b
GM
13383 if (GPT - BEG < BEG_UNCHANGED)
13384 BEG_UNCHANGED = GPT - BEG;
13385 if (Z - GPT < END_UNCHANGED)
13386 END_UNCHANGED = Z - GPT;
5f5c8ee5 13387 }
bf9249e3 13388
27d16f05
GM
13389 /* The position of the first and last character that has been changed. */
13390 first_changed_charpos = BEG + BEG_UNCHANGED;
13391 last_changed_charpos = Z - END_UNCHANGED;
13392
5f5c8ee5
GM
13393 /* If window starts after a line end, and the last change is in
13394 front of that newline, then changes don't affect the display.
f2d86d7a
GM
13395 This case happens with stealth-fontification. Note that although
13396 the display is unchanged, glyph positions in the matrix have to
13397 be adjusted, of course. */
5f5c8ee5 13398 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
27d16f05 13399 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
e60f4527 13400 && ((last_changed_charpos < CHARPOS (start)
27d16f05 13401 && CHARPOS (start) == BEGV)
e60f4527 13402 || (last_changed_charpos < CHARPOS (start) - 1
27d16f05
GM
13403 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
13404 {
13405 int Z_old, delta, Z_BYTE_old, delta_bytes;
13406 struct glyph_row *r0;
13407
13408 /* Compute how many chars/bytes have been added to or removed
13409 from the buffer. */
13410 Z_old = MATRIX_ROW_END_CHARPOS (row) + XFASTINT (w->window_end_pos);
13411 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
13412 delta = Z - Z_old;
13413 delta_bytes = Z_BYTE - Z_BYTE_old;
2311178e 13414
27d16f05
GM
13415 /* Give up if PT is not in the window. Note that it already has
13416 been checked at the start of try_window_id that PT is not in
13417 front of the window start. */
13418 if (PT >= MATRIX_ROW_END_CHARPOS (row) + delta)
13419 GIVE_UP (13);
13420
13421 /* If window start is unchanged, we can reuse the whole matrix
13422 as is, after adjusting glyph positions. No need to compute
13423 the window end again, since its offset from Z hasn't changed. */
13424 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
13425 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + delta
2d031b89
AS
13426 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + delta_bytes
13427 /* PT must not be in a partially visible line. */
13428 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + delta
13429 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
13430 {
13431 /* Adjust positions in the glyph matrix. */
13432 if (delta || delta_bytes)
13433 {
13434 struct glyph_row *r1
13435 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
13436 increment_matrix_positions (w->current_matrix,
13437 MATRIX_ROW_VPOS (r0, current_matrix),
13438 MATRIX_ROW_VPOS (r1, current_matrix),
13439 delta, delta_bytes);
13440 }
2311178e 13441
27d16f05 13442 /* Set the cursor. */
0df56f4d 13443 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
13444 if (row)
13445 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
13446 else
13447 abort ();
27d16f05
GM
13448 return 1;
13449 }
5f5c8ee5
GM
13450 }
13451
27d16f05 13452 /* Handle the case that changes are all below what is displayed in
33ea6c4d 13453 the window, and that PT is in the window. This shortcut cannot
2b9c25e0
GM
13454 be taken if ZV is visible in the window, and text has been added
13455 there that is visible in the window. */
13456 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
33ea6c4d
GM
13457 /* ZV is not visible in the window, or there are no
13458 changes at ZV, actually. */
13459 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
13460 || first_changed_charpos == last_changed_charpos))
5f5c8ee5 13461 {
27d16f05 13462 struct glyph_row *r0;
ef121659 13463
27d16f05
GM
13464 /* Give up if PT is not in the window. Note that it already has
13465 been checked at the start of try_window_id that PT is not in
13466 front of the window start. */
13467 if (PT >= MATRIX_ROW_END_CHARPOS (row))
13468 GIVE_UP (14);
13469
13470 /* If window start is unchanged, we can reuse the whole matrix
13471 as is, without changing glyph positions since no text has
13472 been added/removed in front of the window end. */
13473 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
2d031b89
AS
13474 if (TEXT_POS_EQUAL_P (start, r0->start.pos)
13475 /* PT must not be in a partially visible line. */
13476 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
13477 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
27d16f05
GM
13478 {
13479 /* We have to compute the window end anew since text
13480 can have been added/removed after it. */
13481 w->window_end_pos
13482 = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
13483 w->window_end_bytepos
13484 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
13485
13486 /* Set the cursor. */
0df56f4d 13487 row = row_containing_pos (w, PT, r0, NULL, 0);
59adf8e8
KS
13488 if (row)
13489 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
40a301b3
RS
13490 else
13491 abort ();
27d16f05
GM
13492 return 2;
13493 }
5f5c8ee5
GM
13494 }
13495
2b9c25e0 13496 /* Give up if window start is in the changed area.
2311178e 13497
2b9c25e0
GM
13498 The condition used to read
13499
13500 (BEG_UNCHANGED + END_UNCHANGED != Z - BEG && ...)
13501
13502 but why that was tested escapes me at the moment. */
13503 if (CHARPOS (start) >= first_changed_charpos
27d16f05
GM
13504 && CHARPOS (start) <= last_changed_charpos)
13505 GIVE_UP (15);
2311178e 13506
f5376658
RS
13507 /* Check that window start agrees with the start of the first glyph
13508 row in its current matrix. Check this after we know the window
13509 start is not in changed text, otherwise positions would not be
13510 comparable. */
27d16f05 13511 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
5f5c8ee5 13512 if (!TEXT_POS_EQUAL_P (start, row->start.pos))
27d16f05 13513 GIVE_UP (16);
5f5c8ee5 13514
23e8bd86
GM
13515 /* Give up if the window ends in strings. Overlay strings
13516 at the end are difficult to handle, so don't try. */
13517 row = MATRIX_ROW (current_matrix, XFASTINT (w->window_end_vpos));
13518 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
13519 GIVE_UP (20);
13520
5f5c8ee5
GM
13521 /* Compute the position at which we have to start displaying new
13522 lines. Some of the lines at the top of the window might be
13523 reusable because they are not displaying changed text. Find the
13524 last row in W's current matrix not affected by changes at the
13525 start of current_buffer. Value is null if changes start in the
13526 first line of window. */
1ec185cb 13527 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
5f5c8ee5
GM
13528 if (last_unchanged_at_beg_row)
13529 {
67f1cf4c
GM
13530 /* Avoid starting to display in the moddle of a character, a TAB
13531 for instance. This is easier than to set up the iterator
13532 exactly, and it's not a frequent case, so the additional
13533 effort wouldn't really pay off. */
e74fb0f7
GM
13534 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
13535 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
67f1cf4c
GM
13536 && last_unchanged_at_beg_row > w->current_matrix->rows)
13537 --last_unchanged_at_beg_row;
13538
13539 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
27d16f05 13540 GIVE_UP (17);
47d57b22
GM
13541
13542 if (init_to_row_end (&it, w, last_unchanged_at_beg_row) == 0)
13543 GIVE_UP (18);
5f5c8ee5 13544 start_pos = it.current.pos;
2311178e 13545
5f5c8ee5
GM
13546 /* Start displaying new lines in the desired matrix at the same
13547 vpos we would use in the current matrix, i.e. below
13548 last_unchanged_at_beg_row. */
13549 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
13550 current_matrix);
13551 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13552 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
13553
13554 xassert (it.hpos == 0 && it.current_x == 0);
13555 }
13556 else
13557 {
13558 /* There are no reusable lines at the start of the window.
3ccb8bcf 13559 Start displaying in the first text line. */
5f5c8ee5 13560 start_display (&it, w, start);
3ccb8bcf 13561 it.vpos = it.first_vpos;
5f5c8ee5
GM
13562 start_pos = it.current.pos;
13563 }
13564
5f5c8ee5
GM
13565 /* Find the first row that is not affected by changes at the end of
13566 the buffer. Value will be null if there is no unchanged row, in
13567 which case we must redisplay to the end of the window. delta
13568 will be set to the value by which buffer positions beginning with
13569 first_unchanged_at_end_row have to be adjusted due to text
13570 changes. */
13571 first_unchanged_at_end_row
1ec185cb 13572 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
5f5c8ee5
GM
13573 IF_DEBUG (debug_delta = delta);
13574 IF_DEBUG (debug_delta_bytes = delta_bytes);
2311178e 13575
5f5c8ee5
GM
13576 /* Set stop_pos to the buffer position up to which we will have to
13577 display new lines. If first_unchanged_at_end_row != NULL, this
13578 is the buffer position of the start of the line displayed in that
13579 row. For first_unchanged_at_end_row == NULL, use 0 to indicate
13580 that we don't stop at a buffer position. */
13581 stop_pos = 0;
13582 if (first_unchanged_at_end_row)
13583 {
13584 xassert (last_unchanged_at_beg_row == NULL
13585 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
2311178e 13586
5f5c8ee5
GM
13587 /* If this is a continuation line, move forward to the next one
13588 that isn't. Changes in lines above affect this line.
13589 Caution: this may move first_unchanged_at_end_row to a row
13590 not displaying text. */
13591 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
13592 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13593 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13594 < it.last_visible_y))
13595 ++first_unchanged_at_end_row;
13596
13597 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
13598 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
13599 >= it.last_visible_y))
13600 first_unchanged_at_end_row = NULL;
13601 else
13602 {
13603 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
13604 + delta);
13605 first_unchanged_at_end_vpos
13606 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
9142dd5b 13607 xassert (stop_pos >= Z - END_UNCHANGED);
5f5c8ee5
GM
13608 }
13609 }
13610 else if (last_unchanged_at_beg_row == NULL)
23e8bd86 13611 GIVE_UP (19);
5f5c8ee5
GM
13612
13613
13614#if GLYPH_DEBUG
2311178e 13615
5f5c8ee5
GM
13616 /* Either there is no unchanged row at the end, or the one we have
13617 now displays text. This is a necessary condition for the window
13618 end pos calculation at the end of this function. */
13619 xassert (first_unchanged_at_end_row == NULL
13620 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
2311178e 13621
5f5c8ee5
GM
13622 debug_last_unchanged_at_beg_vpos
13623 = (last_unchanged_at_beg_row
13624 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
13625 : -1);
13626 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
2311178e 13627
5f5c8ee5
GM
13628#endif /* GLYPH_DEBUG != 0 */
13629
2311178e 13630
5f5c8ee5
GM
13631 /* Display new lines. Set last_text_row to the last new line
13632 displayed which has text on it, i.e. might end up as being the
13633 line where the window_end_vpos is. */
13634 w->cursor.vpos = -1;
13635 last_text_row = NULL;
13636 overlay_arrow_seen = 0;
13637 while (it.current_y < it.last_visible_y
13638 && !fonts_changed_p
13639 && (first_unchanged_at_end_row == NULL
13640 || IT_CHARPOS (it) < stop_pos))
13641 {
13642 if (display_line (&it))
13643 last_text_row = it.glyph_row - 1;
13644 }
13645
13646 if (fonts_changed_p)
13647 return -1;
13648
13649
13650 /* Compute differences in buffer positions, y-positions etc. for
13651 lines reused at the bottom of the window. Compute what we can
13652 scroll. */
ca42b2e8
GM
13653 if (first_unchanged_at_end_row
13654 /* No lines reused because we displayed everything up to the
13655 bottom of the window. */
13656 && it.current_y < it.last_visible_y)
5f5c8ee5
GM
13657 {
13658 dvpos = (it.vpos
13659 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
13660 current_matrix));
13661 dy = it.current_y - first_unchanged_at_end_row->y;
13662 run.current_y = first_unchanged_at_end_row->y;
13663 run.desired_y = run.current_y + dy;
13664 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
13665 }
13666 else
ca42b2e8
GM
13667 {
13668 delta = dvpos = dy = run.current_y = run.desired_y = run.height = 0;
13669 first_unchanged_at_end_row = NULL;
13670 }
5f5c8ee5
GM
13671 IF_DEBUG (debug_dvpos = dvpos; debug_dy = dy);
13672
8f8ba186 13673
5f5c8ee5
GM
13674 /* Find the cursor if not already found. We have to decide whether
13675 PT will appear on this window (it sometimes doesn't, but this is
13676 not a very frequent case.) This decision has to be made before
13677 the current matrix is altered. A value of cursor.vpos < 0 means
13678 that PT is either in one of the lines beginning at
13679 first_unchanged_at_end_row or below the window. Don't care for
13680 lines that might be displayed later at the window end; as
13681 mentioned, this is not a frequent case. */
13682 if (w->cursor.vpos < 0)
13683 {
5f5c8ee5
GM
13684 /* Cursor in unchanged rows at the top? */
13685 if (PT < CHARPOS (start_pos)
13686 && last_unchanged_at_beg_row)
13687 {
e037b9ec
GM
13688 row = row_containing_pos (w, PT,
13689 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
0df56f4d 13690 last_unchanged_at_beg_row + 1, 0);
bfe0ee88
GM
13691 if (row)
13692 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
13693 }
13694
13695 /* Start from first_unchanged_at_end_row looking for PT. */
13696 else if (first_unchanged_at_end_row)
13697 {
e037b9ec 13698 row = row_containing_pos (w, PT - delta,
0df56f4d 13699 first_unchanged_at_end_row, NULL, 0);
e037b9ec 13700 if (row)
468155d7
GM
13701 set_cursor_from_row (w, row, w->current_matrix, delta,
13702 delta_bytes, dy, dvpos);
5f5c8ee5
GM
13703 }
13704
13705 /* Give up if cursor was not found. */
13706 if (w->cursor.vpos < 0)
13707 {
13708 clear_glyph_matrix (w->desired_matrix);
13709 return -1;
13710 }
13711 }
2311178e 13712
5f5c8ee5
GM
13713 /* Don't let the cursor end in the scroll margins. */
13714 {
13715 int this_scroll_margin, cursor_height;
2311178e 13716
5f5c8ee5 13717 this_scroll_margin = max (0, scroll_margin);
da8b7f4f
KS
13718 this_scroll_margin = min (this_scroll_margin, WINDOW_TOTAL_LINES (w) / 4);
13719 this_scroll_margin *= FRAME_LINE_HEIGHT (it.f);
5f5c8ee5 13720 cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
2311178e 13721
5f5c8ee5
GM
13722 if ((w->cursor.y < this_scroll_margin
13723 && CHARPOS (start) > BEGV)
13724 /* Don't take scroll margin into account at the bottom because
13725 old redisplay didn't do it either. */
13726 || w->cursor.y + cursor_height > it.last_visible_y)
13727 {
13728 w->cursor.vpos = -1;
13729 clear_glyph_matrix (w->desired_matrix);
13730 return -1;
13731 }
13732 }
13733
13734 /* Scroll the display. Do it before changing the current matrix so
13735 that xterm.c doesn't get confused about where the cursor glyph is
13736 found. */
fa77249f 13737 if (dy && run.height)
5f5c8ee5
GM
13738 {
13739 update_begin (f);
2311178e 13740
5f5c8ee5
GM
13741 if (FRAME_WINDOW_P (f))
13742 {
13743 rif->update_window_begin_hook (w);
fa3c6b4d 13744 rif->clear_window_mouse_face (w);
5f5c8ee5 13745 rif->scroll_run_hook (w, &run);
64d1e7d3 13746 rif->update_window_end_hook (w, 0, 0);
5f5c8ee5
GM
13747 }
13748 else
13749 {
13750 /* Terminal frame. In this case, dvpos gives the number of
13751 lines to scroll by; dvpos < 0 means scroll up. */
13752 int first_unchanged_at_end_vpos
13753 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
da8b7f4f
KS
13754 int from = WINDOW_TOP_EDGE_LINE (w) + first_unchanged_at_end_vpos;
13755 int end = (WINDOW_TOP_EDGE_LINE (w)
522ed7fb
GM
13756 + (WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0)
13757 + window_internal_height (w));
2311178e 13758
5f5c8ee5
GM
13759 /* Perform the operation on the screen. */
13760 if (dvpos > 0)
13761 {
13762 /* Scroll last_unchanged_at_beg_row to the end of the
13763 window down dvpos lines. */
13764 set_terminal_window (end);
13765
13766 /* On dumb terminals delete dvpos lines at the end
13767 before inserting dvpos empty lines. */
13768 if (!scroll_region_ok)
13769 ins_del_lines (end - dvpos, -dvpos);
13770
13771 /* Insert dvpos empty lines in front of
13772 last_unchanged_at_beg_row. */
13773 ins_del_lines (from, dvpos);
13774 }
13775 else if (dvpos < 0)
13776 {
13777 /* Scroll up last_unchanged_at_beg_vpos to the end of
13778 the window to last_unchanged_at_beg_vpos - |dvpos|. */
13779 set_terminal_window (end);
13780
13781 /* Delete dvpos lines in front of
13782 last_unchanged_at_beg_vpos. ins_del_lines will set
13783 the cursor to the given vpos and emit |dvpos| delete
13784 line sequences. */
13785 ins_del_lines (from + dvpos, dvpos);
13786
13787 /* On a dumb terminal insert dvpos empty lines at the
13788 end. */
13789 if (!scroll_region_ok)
13790 ins_del_lines (end + dvpos, -dvpos);
13791 }
2311178e 13792
5f5c8ee5
GM
13793 set_terminal_window (0);
13794 }
2311178e 13795
5f5c8ee5
GM
13796 update_end (f);
13797 }
13798
ca42b2e8
GM
13799 /* Shift reused rows of the current matrix to the right position.
13800 BOTTOM_ROW is the last + 1 row in the current matrix reserved for
13801 text. */
13802 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
13803 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
5f5c8ee5
GM
13804 if (dvpos < 0)
13805 {
13806 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
13807 bottom_vpos, dvpos);
13808 enable_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
13809 bottom_vpos, 0);
13810 }
13811 else if (dvpos > 0)
13812 {
13813 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
13814 bottom_vpos, dvpos);
13815 enable_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
13816 first_unchanged_at_end_vpos + dvpos, 0);
13817 }
13818
13819 /* For frame-based redisplay, make sure that current frame and window
13820 matrix are in sync with respect to glyph memory. */
13821 if (!FRAME_WINDOW_P (f))
13822 sync_frame_with_window_matrix_rows (w);
13823
13824 /* Adjust buffer positions in reused rows. */
13825 if (delta)
f2d86d7a
GM
13826 increment_matrix_positions (current_matrix,
13827 first_unchanged_at_end_vpos + dvpos,
13828 bottom_vpos, delta, delta_bytes);
5f5c8ee5
GM
13829
13830 /* Adjust Y positions. */
13831 if (dy)
13832 shift_glyph_matrix (w, current_matrix,
13833 first_unchanged_at_end_vpos + dvpos,
13834 bottom_vpos, dy);
13835
13836 if (first_unchanged_at_end_row)
13837 first_unchanged_at_end_row += dvpos;
13838
13839 /* If scrolling up, there may be some lines to display at the end of
13840 the window. */
13841 last_text_row_at_end = NULL;
13842 if (dy < 0)
13843 {
9c6ba6d1
GM
13844 /* Scrolling up can leave for example a partially visible line
13845 at the end of the window to be redisplayed. */
5f5c8ee5
GM
13846 /* Set last_row to the glyph row in the current matrix where the
13847 window end line is found. It has been moved up or down in
13848 the matrix by dvpos. */
13849 int last_vpos = XFASTINT (w->window_end_vpos) + dvpos;
13850 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
13851
13852 /* If last_row is the window end line, it should display text. */
13853 xassert (last_row->displays_text_p);
13854
13855 /* If window end line was partially visible before, begin
13856 displaying at that line. Otherwise begin displaying with the
13857 line following it. */
13858 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
13859 {
13860 init_to_row_start (&it, w, last_row);
13861 it.vpos = last_vpos;
13862 it.current_y = last_row->y;
13863 }
13864 else
13865 {
13866 init_to_row_end (&it, w, last_row);
13867 it.vpos = 1 + last_vpos;
13868 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
13869 ++last_row;
13870 }
12adba34 13871
23e8bd86
GM
13872 /* We may start in a continuation line. If so, we have to
13873 get the right continuation_lines_width and current_x. */
13874 it.continuation_lines_width = last_row->continuation_lines_width;
13875 it.hpos = it.current_x = 0;
2311178e 13876
23e8bd86
GM
13877 /* Display the rest of the lines at the window end. */
13878 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
13879 while (it.current_y < it.last_visible_y
13880 && !fonts_changed_p)
5f5c8ee5 13881 {
23e8bd86
GM
13882 /* Is it always sure that the display agrees with lines in
13883 the current matrix? I don't think so, so we mark rows
13884 displayed invalid in the current matrix by setting their
13885 enabled_p flag to zero. */
13886 MATRIX_ROW (w->current_matrix, it.vpos)->enabled_p = 0;
13887 if (display_line (&it))
13888 last_text_row_at_end = it.glyph_row - 1;
5f5c8ee5
GM
13889 }
13890 }
12adba34 13891
5f5c8ee5
GM
13892 /* Update window_end_pos and window_end_vpos. */
13893 if (first_unchanged_at_end_row
13894 && first_unchanged_at_end_row->y < it.last_visible_y
13895 && !last_text_row_at_end)
13896 {
13897 /* Window end line if one of the preserved rows from the current
13898 matrix. Set row to the last row displaying text in current
13899 matrix starting at first_unchanged_at_end_row, after
13900 scrolling. */
13901 xassert (first_unchanged_at_end_row->displays_text_p);
13902 row = find_last_row_displaying_text (w->current_matrix, &it,
13903 first_unchanged_at_end_row);
13904 xassert (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
2311178e 13905
ac90c44f 13906 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
5f5c8ee5 13907 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
ac90c44f
GM
13908 w->window_end_vpos
13909 = make_number (MATRIX_ROW_VPOS (row, w->current_matrix));
23fca891 13910 xassert (w->window_end_bytepos >= 0);
0416532f 13911 IF_DEBUG (debug_method_add (w, "A"));
5f5c8ee5
GM
13912 }
13913 else if (last_text_row_at_end)
13914 {
ac90c44f
GM
13915 w->window_end_pos
13916 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row_at_end));
5f5c8ee5
GM
13917 w->window_end_bytepos
13918 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row_at_end);
ac90c44f
GM
13919 w->window_end_vpos
13920 = make_number (MATRIX_ROW_VPOS (last_text_row_at_end, desired_matrix));
23fca891 13921 xassert (w->window_end_bytepos >= 0);
0416532f 13922 IF_DEBUG (debug_method_add (w, "B"));
5f5c8ee5
GM
13923 }
13924 else if (last_text_row)
13925 {
13926 /* We have displayed either to the end of the window or at the
13927 end of the window, i.e. the last row with text is to be found
13928 in the desired matrix. */
ac90c44f
GM
13929 w->window_end_pos
13930 = make_number (Z - MATRIX_ROW_END_CHARPOS (last_text_row));
5f5c8ee5
GM
13931 w->window_end_bytepos
13932 = Z_BYTE - MATRIX_ROW_END_BYTEPOS (last_text_row);
ac90c44f
GM
13933 w->window_end_vpos
13934 = make_number (MATRIX_ROW_VPOS (last_text_row, desired_matrix));
23fca891 13935 xassert (w->window_end_bytepos >= 0);
5f5c8ee5
GM
13936 }
13937 else if (first_unchanged_at_end_row == NULL
13938 && last_text_row == NULL
13939 && last_text_row_at_end == NULL)
13940 {
13941 /* Displayed to end of window, but no line containing text was
13942 displayed. Lines were deleted at the end of the window. */
0416532f
GM
13943 int first_vpos = WINDOW_WANTS_HEADER_LINE_P (w) ? 1 : 0;
13944 int vpos = XFASTINT (w->window_end_vpos);
13945 struct glyph_row *current_row = current_matrix->rows + vpos;
13946 struct glyph_row *desired_row = desired_matrix->rows + vpos;
13947
13948 for (row = NULL;
13949 row == NULL && vpos >= first_vpos;
13950 --vpos, --current_row, --desired_row)
13951 {
13952 if (desired_row->enabled_p)
13953 {
13954 if (desired_row->displays_text_p)
13955 row = desired_row;
13956 }
13957 else if (current_row->displays_text_p)
13958 row = current_row;
13959 }
12adba34 13960
0416532f 13961 xassert (row != NULL);
d88a79d4 13962 w->window_end_vpos = make_number (vpos + 1);
8c56a983
GM
13963 w->window_end_pos = make_number (Z - MATRIX_ROW_END_CHARPOS (row));
13964 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
23fca891 13965 xassert (w->window_end_bytepos >= 0);
0416532f 13966 IF_DEBUG (debug_method_add (w, "C"));
5f5c8ee5
GM
13967 }
13968 else
13969 abort ();
ac90c44f 13970
8cdb267e
GM
13971#if 0 /* This leads to problems, for instance when the cursor is
13972 at ZV, and the cursor line displays no text. */
ac90c44f
GM
13973 /* Disable rows below what's displayed in the window. This makes
13974 debugging easier. */
13975 enable_glyph_matrix_rows (current_matrix,
13976 XFASTINT (w->window_end_vpos) + 1,
13977 bottom_vpos, 0);
8cdb267e 13978#endif
23e8bd86 13979
5f5c8ee5
GM
13980 IF_DEBUG (debug_end_pos = XFASTINT (w->window_end_pos);
13981 debug_end_vpos = XFASTINT (w->window_end_vpos));
12adba34 13982
5f5c8ee5
GM
13983 /* Record that display has not been completed. */
13984 w->window_end_valid = Qnil;
13985 w->desired_matrix->no_scrolling_p = 1;
ef121659 13986 return 3;
27d16f05
GM
13987
13988#undef GIVE_UP
12adba34 13989}
0f9c0ff0 13990
a2889657 13991
5f5c8ee5
GM
13992\f
13993/***********************************************************************
13994 More debugging support
13995 ***********************************************************************/
a2889657 13996
5f5c8ee5 13997#if GLYPH_DEBUG
a2889657 13998
eaaa65b0 13999void dump_glyph_row P_ ((struct glyph_row *, int, int));
9ab436b9 14000void dump_glyph_matrix P_ ((struct glyph_matrix *, int));
e187cf71 14001void dump_glyph P_ ((struct glyph_row *, struct glyph *, int));
1c9241f5 14002
31b24551 14003
9ab436b9 14004/* Dump the contents of glyph matrix MATRIX on stderr.
ca26e1c8 14005
9ab436b9
GM
14006 GLYPHS 0 means don't show glyph contents.
14007 GLYPHS 1 means show glyphs in short form
14008 GLYPHS > 1 means show glyphs in long form. */
14009
14010void
14011dump_glyph_matrix (matrix, glyphs)
5f5c8ee5 14012 struct glyph_matrix *matrix;
9ab436b9 14013 int glyphs;
5f5c8ee5 14014{
efc63ef0 14015 int i;
5f5c8ee5 14016 for (i = 0; i < matrix->nrows; ++i)
eaaa65b0 14017 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
5f5c8ee5 14018}
31b24551 14019
68a37fa8 14020
e187cf71
GM
14021/* Dump contents of glyph GLYPH to stderr. ROW and AREA are
14022 the glyph row and area where the glyph comes from. */
14023
14024void
14025dump_glyph (row, glyph, area)
14026 struct glyph_row *row;
14027 struct glyph *glyph;
14028 int area;
14029{
14030 if (glyph->type == CHAR_GLYPH)
14031 {
14032 fprintf (stderr,
14033 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
14034 glyph - row->glyphs[TEXT_AREA],
14035 'C',
14036 glyph->charpos,
14037 (BUFFERP (glyph->object)
14038 ? 'B'
14039 : (STRINGP (glyph->object)
14040 ? 'S'
14041 : '-')),
14042 glyph->pixel_width,
14043 glyph->u.ch,
14044 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
14045 ? glyph->u.ch
14046 : '.'),
14047 glyph->face_id,
14048 glyph->left_box_line_p,
14049 glyph->right_box_line_p);
14050 }
14051 else if (glyph->type == STRETCH_GLYPH)
14052 {
14053 fprintf (stderr,
14054 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
14055 glyph - row->glyphs[TEXT_AREA],
14056 'S',
14057 glyph->charpos,
14058 (BUFFERP (glyph->object)
14059 ? 'B'
14060 : (STRINGP (glyph->object)
14061 ? 'S'
14062 : '-')),
14063 glyph->pixel_width,
14064 0,
14065 '.',
14066 glyph->face_id,
14067 glyph->left_box_line_p,
14068 glyph->right_box_line_p);
14069 }
14070 else if (glyph->type == IMAGE_GLYPH)
14071 {
14072 fprintf (stderr,
14073 " %5d %4c %6d %c %3d 0x%05x %c %4d %1.1d%1.1d\n",
14074 glyph - row->glyphs[TEXT_AREA],
14075 'I',
14076 glyph->charpos,
14077 (BUFFERP (glyph->object)
14078 ? 'B'
14079 : (STRINGP (glyph->object)
14080 ? 'S'
14081 : '-')),
14082 glyph->pixel_width,
14083 glyph->u.img_id,
14084 '.',
14085 glyph->face_id,
14086 glyph->left_box_line_p,
14087 glyph->right_box_line_p);
14088 }
14089}
14090
14091
5f5c8ee5 14092/* Dump the contents of glyph row at VPOS in MATRIX to stderr.
9ab436b9
GM
14093 GLYPHS 0 means don't show glyph contents.
14094 GLYPHS 1 means show glyphs in short form
14095 GLYPHS > 1 means show glyphs in long form. */
a2889657 14096
5f5c8ee5 14097void
eaaa65b0
GM
14098dump_glyph_row (row, vpos, glyphs)
14099 struct glyph_row *row;
9ab436b9 14100 int vpos, glyphs;
5f5c8ee5 14101{
9ab436b9
GM
14102 if (glyphs != 1)
14103 {
b94c0d9c 14104 fprintf (stderr, "Row Start End Used oEI><O\\CTZFesm X Y W H V A P\n");
9ab436b9 14105 fprintf (stderr, "=======================================================================\n");
2311178e 14106
0ad38729 14107 fprintf (stderr, "%3d %5d %5d %4d %1.1d%1.1d%1.1d%1.1d%1.1d\
33ea6c4d 14108%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
eaaa65b0 14109 vpos,
9ab436b9
GM
14110 MATRIX_ROW_START_CHARPOS (row),
14111 MATRIX_ROW_END_CHARPOS (row),
14112 row->used[TEXT_AREA],
14113 row->contains_overlapping_glyphs_p,
14114 row->enabled_p,
9ab436b9
GM
14115 row->truncated_on_left_p,
14116 row->truncated_on_right_p,
14117 row->overlay_arrow_p,
14118 row->continued_p,
14119 MATRIX_ROW_CONTINUATION_LINE_P (row),
14120 row->displays_text_p,
14121 row->ends_at_zv_p,
14122 row->fill_line_p,
14123 row->ends_in_middle_of_char_p,
14124 row->starts_in_middle_of_char_p,
b94c0d9c 14125 row->mouse_face_p,
9ab436b9
GM
14126 row->x,
14127 row->y,
14128 row->pixel_width,
14129 row->height,
14130 row->visible_height,
14131 row->ascent,
14132 row->phys_ascent);
33ea6c4d
GM
14133 fprintf (stderr, "%9d %5d\t%5d\n", row->start.overlay_string_index,
14134 row->end.overlay_string_index,
14135 row->continuation_lines_width);
9ab436b9
GM
14136 fprintf (stderr, "%9d %5d\n",
14137 CHARPOS (row->start.string_pos),
14138 CHARPOS (row->end.string_pos));
14139 fprintf (stderr, "%9d %5d\n", row->start.dpvec_index,
14140 row->end.dpvec_index);
14141 }
2311178e 14142
9ab436b9 14143 if (glyphs > 1)
bd66d1ba 14144 {
e187cf71
GM
14145 int area;
14146
14147 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
14148 {
091f8878
GM
14149 struct glyph *glyph = row->glyphs[area];
14150 struct glyph *glyph_end = glyph + row->used[area];
2311178e 14151
e187cf71 14152 /* Glyph for a line end in text. */
091f8878 14153 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
e187cf71 14154 ++glyph_end;
2311178e 14155
e187cf71
GM
14156 if (glyph < glyph_end)
14157 fprintf (stderr, " Glyph Type Pos O W Code C Face LR\n");
2311178e 14158
e187cf71
GM
14159 for (; glyph < glyph_end; ++glyph)
14160 dump_glyph (row, glyph, area);
f7b4b63a 14161 }
f4faa47c 14162 }
9ab436b9
GM
14163 else if (glyphs == 1)
14164 {
e187cf71 14165 int area;
9ab436b9 14166
e187cf71 14167 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
9ab436b9 14168 {
e187cf71
GM
14169 char *s = (char *) alloca (row->used[area] + 1);
14170 int i;
14171
14172 for (i = 0; i < row->used[area]; ++i)
14173 {
14174 struct glyph *glyph = row->glyphs[area] + i;
14175 if (glyph->type == CHAR_GLYPH
14176 && glyph->u.ch < 0x80
14177 && glyph->u.ch >= ' ')
14178 s[i] = glyph->u.ch;
14179 else
14180 s[i] = '.';
14181 }
2311178e 14182
e187cf71
GM
14183 s[i] = '\0';
14184 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
14185 }
9ab436b9 14186 }
5f5c8ee5 14187}
f4faa47c 14188
a2889657 14189
5f5c8ee5
GM
14190DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
14191 Sdump_glyph_matrix, 0, 1, "p",
7ee72033 14192 doc: /* Dump the current matrix of the selected window to stderr.
228299fa
GM
14193Shows contents of glyph row structures. With non-nil
14194parameter GLYPHS, dump glyphs as well. If GLYPHS is 1 show
7ee72033
MB
14195glyphs in short form, otherwise show glyphs in long form. */)
14196 (glyphs)
9ab436b9 14197 Lisp_Object glyphs;
5f5c8ee5
GM
14198{
14199 struct window *w = XWINDOW (selected_window);
14200 struct buffer *buffer = XBUFFER (w->buffer);
14201
14202 fprintf (stderr, "PT = %d, BEGV = %d. ZV = %d\n",
14203 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
14204 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
14205 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
14206 fprintf (stderr, "=============================================\n");
9ab436b9
GM
14207 dump_glyph_matrix (w->current_matrix,
14208 NILP (glyphs) ? 0 : XINT (glyphs));
5f5c8ee5
GM
14209 return Qnil;
14210}
1c2250c2 14211
1fca3fae 14212
7d4cc828
GM
14213DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
14214 Sdump_frame_glyph_matrix, 0, 0, "", doc: /* */)
14215 ()
14216{
14217 struct frame *f = XFRAME (selected_frame);
14218 dump_glyph_matrix (f->current_matrix, 1);
14219 return Qnil;
14220}
14221
14222
e9abc296 14223DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "",
7ee72033 14224 doc: /* Dump glyph row ROW to stderr.
228299fa
GM
14225GLYPH 0 means don't dump glyphs.
14226GLYPH 1 means dump glyphs in short form.
7ee72033
MB
14227GLYPH > 1 or omitted means dump glyphs in long form. */)
14228 (row, glyphs)
e9abc296 14229 Lisp_Object row, glyphs;
5f5c8ee5 14230{
eaaa65b0
GM
14231 struct glyph_matrix *matrix;
14232 int vpos;
2311178e 14233
b7826503 14234 CHECK_NUMBER (row);
eaaa65b0
GM
14235 matrix = XWINDOW (selected_window)->current_matrix;
14236 vpos = XINT (row);
14237 if (vpos >= 0 && vpos < matrix->nrows)
14238 dump_glyph_row (MATRIX_ROW (matrix, vpos),
14239 vpos,
14240 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
14241 return Qnil;
14242}
1fca3fae 14243
67481ae5 14244
b94c0d9c 14245DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "",
c2552f79 14246 doc: /* Dump glyph row ROW of the tool-bar of the current frame to stderr.
228299fa
GM
14247GLYPH 0 means don't dump glyphs.
14248GLYPH 1 means dump glyphs in short form.
7ee72033
MB
14249GLYPH > 1 or omitted means dump glyphs in long form. */)
14250 (row, glyphs)
b94c0d9c 14251 Lisp_Object row, glyphs;
5f5c8ee5 14252{
886bd6f2 14253 struct frame *sf = SELECTED_FRAME ();
eaaa65b0
GM
14254 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
14255 int vpos;
2311178e 14256
b7826503 14257 CHECK_NUMBER (row);
eaaa65b0
GM
14258 vpos = XINT (row);
14259 if (vpos >= 0 && vpos < m->nrows)
14260 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
14261 INTEGERP (glyphs) ? XINT (glyphs) : 2);
5f5c8ee5
GM
14262 return Qnil;
14263}
ca26e1c8 14264
0f9c0ff0 14265
62397849 14266DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
7ee72033
MB
14267 doc: /* Toggle tracing of redisplay.
14268With ARG, turn tracing on if and only if ARG is positive. */)
14269 (arg)
62397849 14270 Lisp_Object arg;
5f5c8ee5 14271{
62397849
GM
14272 if (NILP (arg))
14273 trace_redisplay_p = !trace_redisplay_p;
14274 else
14275 {
14276 arg = Fprefix_numeric_value (arg);
14277 trace_redisplay_p = XINT (arg) > 0;
14278 }
2311178e 14279
5f5c8ee5
GM
14280 return Qnil;
14281}
bf9249e3
GM
14282
14283
f4a374a1 14284DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
e9757d41
SM
14285 doc: /* Like `format', but print result to stderr.
14286usage: (trace-to-stderr STRING &rest OBJECTS) */)
7ee72033 14287 (nargs, args)
f4a374a1
GM
14288 int nargs;
14289 Lisp_Object *args;
bf9249e3 14290{
f4a374a1 14291 Lisp_Object s = Fformat (nargs, args);
2051c264 14292 fprintf (stderr, "%s", SDATA (s));
bf9249e3
GM
14293 return Qnil;
14294}
2311178e 14295
5f5c8ee5 14296#endif /* GLYPH_DEBUG */
ca26e1c8 14297
ca26e1c8 14298
5f5c8ee5
GM
14299\f
14300/***********************************************************************
14301 Building Desired Matrix Rows
14302 ***********************************************************************/
a2889657 14303
5f5c8ee5
GM
14304/* Return a temporary glyph row holding the glyphs of an overlay
14305 arrow. Only used for non-window-redisplay windows. */
ca26e1c8 14306
5f5c8ee5
GM
14307static struct glyph_row *
14308get_overlay_arrow_glyph_row (w)
14309 struct window *w;
14310{
14311 struct frame *f = XFRAME (WINDOW_FRAME (w));
14312 struct buffer *buffer = XBUFFER (w->buffer);
14313 struct buffer *old = current_buffer;
50f80c2f 14314 const unsigned char *arrow_string = SDATA (Voverlay_arrow_string);
2051c264 14315 int arrow_len = SCHARS (Voverlay_arrow_string);
50f80c2f
KR
14316 const unsigned char *arrow_end = arrow_string + arrow_len;
14317 const unsigned char *p;
5f5c8ee5
GM
14318 struct it it;
14319 int multibyte_p;
14320 int n_glyphs_before;
14321
14322 set_buffer_temp (buffer);
14323 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
14324 it.glyph_row->used[TEXT_AREA] = 0;
14325 SET_TEXT_POS (it.position, 0, 0);
14326
14327 multibyte_p = !NILP (buffer->enable_multibyte_characters);
14328 p = arrow_string;
14329 while (p < arrow_end)
14330 {
14331 Lisp_Object face, ilisp;
2311178e 14332
5f5c8ee5
GM
14333 /* Get the next character. */
14334 if (multibyte_p)
4fdb80f2 14335 it.c = string_char_and_length (p, arrow_len, &it.len);
5f5c8ee5
GM
14336 else
14337 it.c = *p, it.len = 1;
14338 p += it.len;
2311178e 14339
5f5c8ee5 14340 /* Get its face. */
ac90c44f 14341 ilisp = make_number (p - arrow_string);
5f5c8ee5
GM
14342 face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
14343 it.face_id = compute_char_face (f, it.c, face);
14344
14345 /* Compute its width, get its glyphs. */
14346 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
337042a9 14347 SET_TEXT_POS (it.position, -1, -1);
5f5c8ee5
GM
14348 PRODUCE_GLYPHS (&it);
14349
14350 /* If this character doesn't fit any more in the line, we have
14351 to remove some glyphs. */
14352 if (it.current_x > it.last_visible_x)
14353 {
14354 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
14355 break;
14356 }
14357 }
2311178e 14358
5f5c8ee5
GM
14359 set_buffer_temp (old);
14360 return it.glyph_row;
14361}
ca26e1c8 14362
b0a0fbda 14363
5f5c8ee5
GM
14364/* Insert truncation glyphs at the start of IT->glyph_row. Truncation
14365 glyphs are only inserted for terminal frames since we can't really
14366 win with truncation glyphs when partially visible glyphs are
14367 involved. Which glyphs to insert is determined by
14368 produce_special_glyphs. */
67481ae5 14369
5f5c8ee5
GM
14370static void
14371insert_left_trunc_glyphs (it)
14372 struct it *it;
14373{
14374 struct it truncate_it;
14375 struct glyph *from, *end, *to, *toend;
14376
14377 xassert (!FRAME_WINDOW_P (it->f));
14378
14379 /* Get the truncation glyphs. */
14380 truncate_it = *it;
5f5c8ee5
GM
14381 truncate_it.current_x = 0;
14382 truncate_it.face_id = DEFAULT_FACE_ID;
14383 truncate_it.glyph_row = &scratch_glyph_row;
14384 truncate_it.glyph_row->used[TEXT_AREA] = 0;
14385 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
6fc556fd 14386 truncate_it.object = make_number (0);
5f5c8ee5 14387 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
2311178e 14388
5f5c8ee5
GM
14389 /* Overwrite glyphs from IT with truncation glyphs. */
14390 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
14391 end = from + truncate_it.glyph_row->used[TEXT_AREA];
14392 to = it->glyph_row->glyphs[TEXT_AREA];
14393 toend = to + it->glyph_row->used[TEXT_AREA];
14394
14395 while (from < end)
14396 *to++ = *from++;
14397
37be86f2
KH
14398 /* There may be padding glyphs left over. Overwrite them too. */
14399 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
14400 {
14401 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
14402 while (from < end)
14403 *to++ = *from++;
14404 }
5f5c8ee5 14405
37be86f2
KH
14406 if (to > toend)
14407 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
5f5c8ee5 14408}
e0bfbde6 14409
e0bfbde6 14410
5f5c8ee5 14411/* Compute the pixel height and width of IT->glyph_row.
9c49d3d7 14412
5f5c8ee5
GM
14413 Most of the time, ascent and height of a display line will be equal
14414 to the max_ascent and max_height values of the display iterator
14415 structure. This is not the case if
67481ae5 14416
5f5c8ee5
GM
14417 1. We hit ZV without displaying anything. In this case, max_ascent
14418 and max_height will be zero.
1c9241f5 14419
5f5c8ee5
GM
14420 2. We have some glyphs that don't contribute to the line height.
14421 (The glyph row flag contributes_to_line_height_p is for future
14422 pixmap extensions).
f6fd109b 14423
5f5c8ee5
GM
14424 The first case is easily covered by using default values because in
14425 these cases, the line height does not really matter, except that it
14426 must not be zero. */
67481ae5 14427
5f5c8ee5
GM
14428static void
14429compute_line_metrics (it)
14430 struct it *it;
14431{
14432 struct glyph_row *row = it->glyph_row;
14433 int area, i;
1c2250c2 14434
5f5c8ee5
GM
14435 if (FRAME_WINDOW_P (it->f))
14436 {
75c5350a 14437 int i, min_y, max_y;
1c2250c2 14438
5f5c8ee5
GM
14439 /* The line may consist of one space only, that was added to
14440 place the cursor on it. If so, the row's height hasn't been
14441 computed yet. */
14442 if (row->height == 0)
14443 {
14444 if (it->max_ascent + it->max_descent == 0)
da8b7f4f 14445 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
5f5c8ee5
GM
14446 row->ascent = it->max_ascent;
14447 row->height = it->max_ascent + it->max_descent;
312246d1
GM
14448 row->phys_ascent = it->max_phys_ascent;
14449 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5 14450 }
2311178e 14451
5f5c8ee5
GM
14452 /* Compute the width of this line. */
14453 row->pixel_width = row->x;
14454 for (i = 0; i < row->used[TEXT_AREA]; ++i)
14455 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
14456
14457 xassert (row->pixel_width >= 0);
14458 xassert (row->ascent >= 0 && row->height > 0);
14459
312246d1
GM
14460 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
14461 || MATRIX_ROW_OVERLAPS_PRED_P (row));
14462
14463 /* If first line's physical ascent is larger than its logical
14464 ascent, use the physical ascent, and make the row taller.
14465 This makes accented characters fully visible. */
b28cb6ed 14466 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
312246d1
GM
14467 && row->phys_ascent > row->ascent)
14468 {
14469 row->height += row->phys_ascent - row->ascent;
14470 row->ascent = row->phys_ascent;
14471 }
14472
5f5c8ee5
GM
14473 /* Compute how much of the line is visible. */
14474 row->visible_height = row->height;
2311178e 14475
da8b7f4f
KS
14476 min_y = WINDOW_HEADER_LINE_HEIGHT (it->w);
14477 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
75c5350a
GM
14478
14479 if (row->y < min_y)
14480 row->visible_height -= min_y - row->y;
14481 if (row->y + row->height > max_y)
14482 row->visible_height -= row->y + row->height - max_y;
5f5c8ee5
GM
14483 }
14484 else
14485 {
14486 row->pixel_width = row->used[TEXT_AREA];
33ea6c4d
GM
14487 if (row->continued_p)
14488 row->pixel_width -= it->continuation_pixel_width;
14489 else if (row->truncated_on_right_p)
14490 row->pixel_width -= it->truncation_pixel_width;
312246d1
GM
14491 row->ascent = row->phys_ascent = 0;
14492 row->height = row->phys_height = row->visible_height = 1;
5f5c8ee5 14493 }
67481ae5 14494
5f5c8ee5
GM
14495 /* Compute a hash code for this row. */
14496 row->hash = 0;
14497 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
14498 for (i = 0; i < row->used[area]; ++i)
14499 row->hash = ((((row->hash << 4) + (row->hash >> 24)) & 0x0fffffff)
14500 + row->glyphs[area][i].u.val
43d120d8
KH
14501 + row->glyphs[area][i].face_id
14502 + row->glyphs[area][i].padding_p
5f5c8ee5 14503 + (row->glyphs[area][i].type << 2));
a2889657 14504
5f5c8ee5 14505 it->max_ascent = it->max_descent = 0;
312246d1 14506 it->max_phys_ascent = it->max_phys_descent = 0;
5f5c8ee5 14507}
12adba34 14508
ca26e1c8 14509
5f5c8ee5
GM
14510/* Append one space to the glyph row of iterator IT if doing a
14511 window-based redisplay. DEFAULT_FACE_P non-zero means let the
14512 space have the default face, otherwise let it have the same face as
80c6cb1f 14513 IT->face_id. Value is non-zero if a space was added.
c6e89d6c
GM
14514
14515 This function is called to make sure that there is always one glyph
14516 at the end of a glyph row that the cursor can be set on under
14517 window-systems. (If there weren't such a glyph we would not know
14518 how wide and tall a box cursor should be displayed).
14519
14520 At the same time this space let's a nicely handle clearing to the
14521 end of the line if the row ends in italic text. */
ca26e1c8 14522
80c6cb1f 14523static int
5f5c8ee5
GM
14524append_space (it, default_face_p)
14525 struct it *it;
14526 int default_face_p;
14527{
14528 if (FRAME_WINDOW_P (it->f))
14529 {
14530 int n = it->glyph_row->used[TEXT_AREA];
ca26e1c8 14531
5f5c8ee5
GM
14532 if (it->glyph_row->glyphs[TEXT_AREA] + n
14533 < it->glyph_row->glyphs[1 + TEXT_AREA])
a2889657 14534 {
cafafe0b
GM
14535 /* Save some values that must not be changed.
14536 Must save IT->c and IT->len because otherwise
14537 ITERATOR_AT_END_P wouldn't work anymore after
14538 append_space has been called. */
478d746b 14539 enum display_element_type saved_what = it->what;
cafafe0b
GM
14540 int saved_c = it->c, saved_len = it->len;
14541 int saved_x = it->current_x;
5f5c8ee5 14542 int saved_face_id = it->face_id;
cafafe0b 14543 struct text_pos saved_pos;
5f5c8ee5 14544 Lisp_Object saved_object;
980806b6 14545 struct face *face;
5f5c8ee5
GM
14546
14547 saved_object = it->object;
14548 saved_pos = it->position;
2311178e 14549
5f5c8ee5
GM
14550 it->what = IT_CHARACTER;
14551 bzero (&it->position, sizeof it->position);
6fc556fd 14552 it->object = make_number (0);
5f5c8ee5
GM
14553 it->c = ' ';
14554 it->len = 1;
5f5c8ee5
GM
14555
14556 if (default_face_p)
14557 it->face_id = DEFAULT_FACE_ID;
4aad61f8
GM
14558 else if (it->face_before_selective_p)
14559 it->face_id = it->saved_face_id;
980806b6
KH
14560 face = FACE_FROM_ID (it->f, it->face_id);
14561 it->face_id = FACE_FOR_CHAR (it->f, face, 0);
1842fc1a 14562
5f5c8ee5 14563 PRODUCE_GLYPHS (it);
2311178e 14564
5f5c8ee5
GM
14565 it->current_x = saved_x;
14566 it->object = saved_object;
14567 it->position = saved_pos;
14568 it->what = saved_what;
14569 it->face_id = saved_face_id;
cafafe0b
GM
14570 it->len = saved_len;
14571 it->c = saved_c;
80c6cb1f 14572 return 1;
5f5c8ee5
GM
14573 }
14574 }
80c6cb1f
GM
14575
14576 return 0;
5f5c8ee5 14577}
12adba34 14578
1842fc1a 14579
5f5c8ee5
GM
14580/* Extend the face of the last glyph in the text area of IT->glyph_row
14581 to the end of the display line. Called from display_line.
14582 If the glyph row is empty, add a space glyph to it so that we
14583 know the face to draw. Set the glyph row flag fill_line_p. */
2311178e 14584
5f5c8ee5
GM
14585static void
14586extend_face_to_end_of_line (it)
14587 struct it *it;
14588{
14589 struct face *face;
14590 struct frame *f = it->f;
1842fc1a 14591
5f5c8ee5
GM
14592 /* If line is already filled, do nothing. */
14593 if (it->current_x >= it->last_visible_x)
14594 return;
2311178e 14595
5f5c8ee5
GM
14596 /* Face extension extends the background and box of IT->face_id
14597 to the end of the line. If the background equals the background
4aad61f8
GM
14598 of the frame, we don't have to do anything. */
14599 if (it->face_before_selective_p)
14600 face = FACE_FROM_ID (it->f, it->saved_face_id);
14601 else
14602 face = FACE_FROM_ID (f, it->face_id);
2311178e 14603
5f5c8ee5
GM
14604 if (FRAME_WINDOW_P (f)
14605 && face->box == FACE_NO_BOX
14606 && face->background == FRAME_BACKGROUND_PIXEL (f)
14607 && !face->stipple)
14608 return;
1842fc1a 14609
5f5c8ee5
GM
14610 /* Set the glyph row flag indicating that the face of the last glyph
14611 in the text area has to be drawn to the end of the text area. */
14612 it->glyph_row->fill_line_p = 1;
545e04f6 14613
980806b6
KH
14614 /* If current character of IT is not ASCII, make sure we have the
14615 ASCII face. This will be automatically undone the next time
14616 get_next_display_element returns a multibyte character. Note
14617 that the character will always be single byte in unibyte text. */
14618 if (!SINGLE_BYTE_CHAR_P (it->c))
5f5c8ee5 14619 {
980806b6 14620 it->face_id = FACE_FOR_CHAR (f, face, 0);
5f5c8ee5 14621 }
545e04f6 14622
5f5c8ee5
GM
14623 if (FRAME_WINDOW_P (f))
14624 {
14625 /* If the row is empty, add a space with the current face of IT,
14626 so that we know which face to draw. */
14627 if (it->glyph_row->used[TEXT_AREA] == 0)
a2889657 14628 {
5f5c8ee5 14629 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
43d120d8 14630 it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
5f5c8ee5 14631 it->glyph_row->used[TEXT_AREA] = 1;
a2889657 14632 }
5f5c8ee5
GM
14633 }
14634 else
14635 {
14636 /* Save some values that must not be changed. */
14637 int saved_x = it->current_x;
14638 struct text_pos saved_pos;
14639 Lisp_Object saved_object;
478d746b 14640 enum display_element_type saved_what = it->what;
4aad61f8 14641 int saved_face_id = it->face_id;
5f5c8ee5
GM
14642
14643 saved_object = it->object;
14644 saved_pos = it->position;
2311178e 14645
5f5c8ee5
GM
14646 it->what = IT_CHARACTER;
14647 bzero (&it->position, sizeof it->position);
6fc556fd 14648 it->object = make_number (0);
5f5c8ee5
GM
14649 it->c = ' ';
14650 it->len = 1;
4aad61f8 14651 it->face_id = face->id;
2311178e 14652
5f5c8ee5 14653 PRODUCE_GLYPHS (it);
2311178e 14654
5f5c8ee5
GM
14655 while (it->current_x <= it->last_visible_x)
14656 PRODUCE_GLYPHS (it);
2311178e 14657
5f5c8ee5
GM
14658 /* Don't count these blanks really. It would let us insert a left
14659 truncation glyph below and make us set the cursor on them, maybe. */
14660 it->current_x = saved_x;
14661 it->object = saved_object;
14662 it->position = saved_pos;
14663 it->what = saved_what;
4aad61f8 14664 it->face_id = saved_face_id;
5f5c8ee5
GM
14665 }
14666}
12adba34 14667
545e04f6 14668
5f5c8ee5
GM
14669/* Value is non-zero if text starting at CHARPOS in current_buffer is
14670 trailing whitespace. */
1c9241f5 14671
5f5c8ee5
GM
14672static int
14673trailing_whitespace_p (charpos)
14674 int charpos;
14675{
14676 int bytepos = CHAR_TO_BYTE (charpos);
14677 int c = 0;
7bbe686f 14678
5f5c8ee5
GM
14679 while (bytepos < ZV_BYTE
14680 && (c = FETCH_CHAR (bytepos),
14681 c == ' ' || c == '\t'))
14682 ++bytepos;
0d09d1e6 14683
8f897821
GM
14684 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
14685 {
14686 if (bytepos != PT_BYTE)
14687 return 1;
14688 }
14689 return 0;
5f5c8ee5 14690}
31b24551 14691
545e04f6 14692
5f5c8ee5 14693/* Highlight trailing whitespace, if any, in ROW. */
545e04f6 14694
5f5c8ee5
GM
14695void
14696highlight_trailing_whitespace (f, row)
14697 struct frame *f;
14698 struct glyph_row *row;
14699{
14700 int used = row->used[TEXT_AREA];
2311178e 14701
5f5c8ee5
GM
14702 if (used)
14703 {
14704 struct glyph *start = row->glyphs[TEXT_AREA];
14705 struct glyph *glyph = start + used - 1;
14706
ade0bee1
GM
14707 /* Skip over glyphs inserted to display the cursor at the
14708 end of a line, for extending the face of the last glyph
14709 to the end of the line on terminals, and for truncation
14710 and continuation glyphs. */
65008712
GM
14711 while (glyph >= start
14712 && glyph->type == CHAR_GLYPH
65008712 14713 && INTEGERP (glyph->object))
5f5c8ee5
GM
14714 --glyph;
14715
14716 /* If last glyph is a space or stretch, and it's trailing
14717 whitespace, set the face of all trailing whitespace glyphs in
14718 IT->glyph_row to `trailing-whitespace'. */
14719 if (glyph >= start
14720 && BUFFERP (glyph->object)
14721 && (glyph->type == STRETCH_GLYPH
14722 || (glyph->type == CHAR_GLYPH
43d120d8 14723 && glyph->u.ch == ' '))
5f5c8ee5 14724 && trailing_whitespace_p (glyph->charpos))
545e04f6 14725 {
980806b6 14726 int face_id = lookup_named_face (f, Qtrailing_whitespace, 0);
2311178e 14727
5f5c8ee5
GM
14728 while (glyph >= start
14729 && BUFFERP (glyph->object)
14730 && (glyph->type == STRETCH_GLYPH
14731 || (glyph->type == CHAR_GLYPH
43d120d8
KH
14732 && glyph->u.ch == ' ')))
14733 (glyph--)->face_id = face_id;
545e04f6 14734 }
a2889657 14735 }
5f5c8ee5 14736}
a2889657 14737
5fcbb24d 14738
cafafe0b 14739/* Value is non-zero if glyph row ROW in window W should be
0fd37545 14740 used to hold the cursor. */
cafafe0b
GM
14741
14742static int
14743cursor_row_p (w, row)
14744 struct window *w;
14745 struct glyph_row *row;
14746{
9a038881 14747 int cursor_row_p = 1;
2311178e 14748
cafafe0b
GM
14749 if (PT == MATRIX_ROW_END_CHARPOS (row))
14750 {
9a038881
GM
14751 /* If the row ends with a newline from a string, we don't want
14752 the cursor there (if the row is continued it doesn't end in a
14753 newline). */
14754 if (CHARPOS (row->end.string_pos) >= 0
14755 || MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
14756 cursor_row_p = row->continued_p;
14757
14758 /* If the row ends at ZV, display the cursor at the end of that
14759 row instead of at the start of the row below. */
14760 else if (row->ends_at_zv_p)
14761 cursor_row_p = 1;
14762 else
14763 cursor_row_p = 0;
cafafe0b
GM
14764 }
14765
9a038881 14766 return cursor_row_p;
cafafe0b
GM
14767}
14768
14769
5f5c8ee5
GM
14770/* Construct the glyph row IT->glyph_row in the desired matrix of
14771 IT->w from text at the current position of IT. See dispextern.h
14772 for an overview of struct it. Value is non-zero if
14773 IT->glyph_row displays text, as opposed to a line displaying ZV
14774 only. */
2311178e 14775
5f5c8ee5
GM
14776static int
14777display_line (it)
14778 struct it *it;
14779{
14780 struct glyph_row *row = it->glyph_row;
14781
14782 /* We always start displaying at hpos zero even if hscrolled. */
14783 xassert (it->hpos == 0 && it->current_x == 0);
a2889657 14784
5f5c8ee5
GM
14785 /* We must not display in a row that's not a text row. */
14786 xassert (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
14787 < it->w->desired_matrix->nrows);
12adba34 14788
5f5c8ee5
GM
14789 /* Is IT->w showing the region? */
14790 it->w->region_showing = it->region_beg_charpos > 0 ? Qt : Qnil;
12adba34 14791
5f5c8ee5
GM
14792 /* Clear the result glyph row and enable it. */
14793 prepare_desired_row (row);
12adba34 14794
5f5c8ee5 14795 row->y = it->current_y;
29b3ea63 14796 row->start = it->start;
5f5c8ee5
GM
14797 row->continuation_lines_width = it->continuation_lines_width;
14798 row->displays_text_p = 1;
91004049
GM
14799 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
14800 it->starts_in_middle_of_char_p = 0;
5f5c8ee5
GM
14801
14802 /* Arrange the overlays nicely for our purposes. Usually, we call
14803 display_line on only one line at a time, in which case this
14804 can't really hurt too much, or we call it on lines which appear
14805 one after another in the buffer, in which case all calls to
14806 recenter_overlay_lists but the first will be pretty cheap. */
14807 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
14808
5f5c8ee5
GM
14809 /* Move over display elements that are not visible because we are
14810 hscrolled. This may stop at an x-position < IT->first_visible_x
14811 if the first glyph is partially visible or if we hit a line end. */
14812 if (it->current_x < it->first_visible_x)
14813 move_it_in_display_line_to (it, ZV, it->first_visible_x,
14814 MOVE_TO_POS | MOVE_TO_X);
14815
14816 /* Get the initial row height. This is either the height of the
14817 text hscrolled, if there is any, or zero. */
14818 row->ascent = it->max_ascent;
14819 row->height = it->max_ascent + it->max_descent;
312246d1
GM
14820 row->phys_ascent = it->max_phys_ascent;
14821 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
5f5c8ee5
GM
14822
14823 /* Loop generating characters. The loop is left with IT on the next
14824 character to display. */
14825 while (1)
14826 {
14827 int n_glyphs_before, hpos_before, x_before;
14828 int x, i, nglyphs;
ae26e27d 14829 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
b28cb6ed 14830
5f5c8ee5
GM
14831 /* Retrieve the next thing to display. Value is zero if end of
14832 buffer reached. */
14833 if (!get_next_display_element (it))
14834 {
14835 /* Maybe add a space at the end of this line that is used to
1b335865
GM
14836 display the cursor there under X. Set the charpos of the
14837 first glyph of blank lines not corresponding to any text
14838 to -1. */
14839 if ((append_space (it, 1) && row->used[TEXT_AREA] == 1)
14840 || row->used[TEXT_AREA] == 0)
a2889657 14841 {
5f5c8ee5
GM
14842 row->glyphs[TEXT_AREA]->charpos = -1;
14843 row->displays_text_p = 0;
14844
2ad551af 14845 if (!NILP (XBUFFER (it->w->buffer)->indicate_empty_lines)
e6b70fd8
GM
14846 && (!MINI_WINDOW_P (it->w)
14847 || (minibuf_level && EQ (it->window, minibuf_window))))
5f5c8ee5 14848 row->indicate_empty_line_p = 1;
a2889657 14849 }
2311178e 14850
5f5c8ee5
GM
14851 it->continuation_lines_width = 0;
14852 row->ends_at_zv_p = 1;
14853 break;
a2889657 14854 }
a2889657 14855
5f5c8ee5
GM
14856 /* Now, get the metrics of what we want to display. This also
14857 generates glyphs in `row' (which is IT->glyph_row). */
14858 n_glyphs_before = row->used[TEXT_AREA];
14859 x = it->current_x;
e6819faf
GM
14860
14861 /* Remember the line height so far in case the next element doesn't
14862 fit on the line. */
14863 if (!it->truncate_lines_p)
14864 {
14865 ascent = it->max_ascent;
14866 descent = it->max_descent;
14867 phys_ascent = it->max_phys_ascent;
14868 phys_descent = it->max_phys_descent;
14869 }
2311178e 14870
5f5c8ee5 14871 PRODUCE_GLYPHS (it);
a2889657 14872
5f5c8ee5
GM
14873 /* If this display element was in marginal areas, continue with
14874 the next one. */
14875 if (it->area != TEXT_AREA)
a2889657 14876 {
5f5c8ee5
GM
14877 row->ascent = max (row->ascent, it->max_ascent);
14878 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14879 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14880 row->phys_height = max (row->phys_height,
14881 it->max_phys_ascent + it->max_phys_descent);
cafafe0b 14882 set_iterator_to_next (it, 1);
5f5c8ee5
GM
14883 continue;
14884 }
5936754e 14885
5f5c8ee5
GM
14886 /* Does the display element fit on the line? If we truncate
14887 lines, we should draw past the right edge of the window. If
14888 we don't truncate, we want to stop so that we can display the
14889 continuation glyph before the right margin. If lines are
14890 continued, there are two possible strategies for characters
14891 resulting in more than 1 glyph (e.g. tabs): Display as many
14892 glyphs as possible in this line and leave the rest for the
14893 continuation line, or display the whole element in the next
14894 line. Original redisplay did the former, so we do it also. */
14895 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14896 hpos_before = it->hpos;
14897 x_before = x;
4dcd74e6 14898
4b41cebb 14899 if (/* Not a newline. */
4dcd74e6 14900 nglyphs > 0
202c1b5b 14901 /* Glyphs produced fit entirely in the line. */
4dcd74e6
GM
14902 && it->current_x < it->last_visible_x)
14903 {
37be86f2 14904 it->hpos += nglyphs;
5f5c8ee5
GM
14905 row->ascent = max (row->ascent, it->max_ascent);
14906 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
14907 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
14908 row->phys_height = max (row->phys_height,
14909 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
14910 if (it->current_x - it->pixel_width < it->first_visible_x)
14911 row->x = x - it->first_visible_x;
14912 }
14913 else
14914 {
14915 int new_x;
14916 struct glyph *glyph;
2311178e 14917
5f5c8ee5 14918 for (i = 0; i < nglyphs; ++i, x = new_x)
b5bbc9a5 14919 {
5f5c8ee5
GM
14920 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14921 new_x = x + glyph->pixel_width;
14922
14923 if (/* Lines are continued. */
14924 !it->truncate_lines_p
14925 && (/* Glyph doesn't fit on the line. */
14926 new_x > it->last_visible_x
14927 /* Or it fits exactly on a window system frame. */
14928 || (new_x == it->last_visible_x
14929 && FRAME_WINDOW_P (it->f))))
a2889657 14930 {
5f5c8ee5 14931 /* End of a continued line. */
2311178e 14932
5f5c8ee5
GM
14933 if (it->hpos == 0
14934 || (new_x == it->last_visible_x
14935 && FRAME_WINDOW_P (it->f)))
14936 {
e6819faf
GM
14937 /* Current glyph is the only one on the line or
14938 fits exactly on the line. We must continue
14939 the line because we can't draw the cursor
14940 after the glyph. */
5f5c8ee5
GM
14941 row->continued_p = 1;
14942 it->current_x = new_x;
14943 it->continuation_lines_width += new_x;
14944 ++it->hpos;
14945 if (i == nglyphs - 1)
88e6b646
KS
14946 {
14947 set_iterator_to_next (it, 1);
7af0e8d7 14948#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
14949 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
14950 {
14951 get_next_display_element (it);
14952 if (ITERATOR_AT_END_OF_LINE_P (it))
14953 {
14954 row->continued_p = 0;
14955 row->exact_window_width_line_p = 1;
14956 }
14957 }
7af0e8d7 14958#endif /* HAVE_WINDOW_SYSTEM */
88e6b646 14959 }
5f5c8ee5 14960 }
3b3c4bf0
GM
14961 else if (CHAR_GLYPH_PADDING_P (*glyph)
14962 && !FRAME_WINDOW_P (it->f))
14963 {
14964 /* A padding glyph that doesn't fit on this line.
14965 This means the whole character doesn't fit
14966 on the line. */
14967 row->used[TEXT_AREA] = n_glyphs_before;
2311178e 14968
3b3c4bf0
GM
14969 /* Fill the rest of the row with continuation
14970 glyphs like in 20.x. */
14971 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
14972 < row->glyphs[1 + TEXT_AREA])
14973 produce_special_glyphs (it, IT_CONTINUATION);
2311178e 14974
3b3c4bf0
GM
14975 row->continued_p = 1;
14976 it->current_x = x_before;
14977 it->continuation_lines_width += x_before;
2311178e 14978
3b3c4bf0
GM
14979 /* Restore the height to what it was before the
14980 element not fitting on the line. */
14981 it->max_ascent = ascent;
14982 it->max_descent = descent;
14983 it->max_phys_ascent = phys_ascent;
14984 it->max_phys_descent = phys_descent;
14985 }
0df56f4d
GM
14986 else if (it->c == '\t' && FRAME_WINDOW_P (it->f))
14987 {
14988 /* A TAB that extends past the right edge of the
14989 window. This produces a single glyph on
14990 window system frames. We leave the glyph in
14991 this row and let it fill the row, but don't
14992 consume the TAB. */
14993 it->continuation_lines_width += it->last_visible_x;
14994 row->ends_in_middle_of_char_p = 1;
14995 row->continued_p = 1;
14996 glyph->pixel_width = it->last_visible_x - x;
14997 it->starts_in_middle_of_char_p = 1;
14998 }
5f5c8ee5 14999 else
5936754e 15000 {
0df56f4d
GM
15001 /* Something other than a TAB that draws past
15002 the right edge of the window. Restore
15003 positions to values before the element. */
5f5c8ee5 15004 row->used[TEXT_AREA] = n_glyphs_before + i;
2311178e 15005
5f5c8ee5
GM
15006 /* Display continuation glyphs. */
15007 if (!FRAME_WINDOW_P (it->f))
15008 produce_special_glyphs (it, IT_CONTINUATION);
15009 row->continued_p = 1;
653c329b 15010
0df56f4d 15011 it->continuation_lines_width += x;
2311178e 15012
91004049
GM
15013 if (nglyphs > 1 && i > 0)
15014 {
15015 row->ends_in_middle_of_char_p = 1;
15016 it->starts_in_middle_of_char_p = 1;
15017 }
2311178e 15018
e6819faf
GM
15019 /* Restore the height to what it was before the
15020 element not fitting on the line. */
15021 it->max_ascent = ascent;
15022 it->max_descent = descent;
15023 it->max_phys_ascent = phys_ascent;
15024 it->max_phys_descent = phys_descent;
5936754e 15025 }
e6819faf 15026
5f5c8ee5
GM
15027 break;
15028 }
15029 else if (new_x > it->first_visible_x)
15030 {
15031 /* Increment number of glyphs actually displayed. */
15032 ++it->hpos;
2311178e 15033
5f5c8ee5
GM
15034 if (x < it->first_visible_x)
15035 /* Glyph is partially visible, i.e. row starts at
15036 negative X position. */
15037 row->x = x - it->first_visible_x;
15038 }
15039 else
15040 {
15041 /* Glyph is completely off the left margin of the
15042 window. This should not happen because of the
72b8c434
RS
15043 move_it_in_display_line at the start of this
15044 function, unless the text display area of the
15045 window is empty. */
15046 xassert (it->first_visible_x <= it->last_visible_x);
a2889657 15047 }
a2889657 15048 }
2311178e 15049
5f5c8ee5
GM
15050 row->ascent = max (row->ascent, it->max_ascent);
15051 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
15052 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
15053 row->phys_height = max (row->phys_height,
15054 it->max_phys_ascent + it->max_phys_descent);
2311178e 15055
5f5c8ee5
GM
15056 /* End of this display line if row is continued. */
15057 if (row->continued_p)
15058 break;
a2889657 15059 }
a2889657 15060
88e6b646 15061 at_end_of_line:
5f5c8ee5
GM
15062 /* Is this a line end? If yes, we're also done, after making
15063 sure that a non-default face is extended up to the right
15064 margin of the window. */
15065 if (ITERATOR_AT_END_OF_LINE_P (it))
1c9241f5 15066 {
5f5c8ee5
GM
15067 int used_before = row->used[TEXT_AREA];
15068
e74fb0f7
GM
15069 row->ends_in_newline_from_string_p = STRINGP (it->object);
15070
7af0e8d7 15071#ifdef HAVE_WINDOW_SYSTEM
5f5c8ee5
GM
15072 /* Add a space at the end of the line that is used to
15073 display the cursor there. */
88e6b646
KS
15074 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
15075 append_space (it, 0);
7af0e8d7 15076#endif /* HAVE_WINDOW_SYSTEM */
2311178e 15077
5f5c8ee5
GM
15078 /* Extend the face to the end of the line. */
15079 extend_face_to_end_of_line (it);
15080
15081 /* Make sure we have the position. */
15082 if (used_before == 0)
15083 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
2311178e 15084
5f5c8ee5 15085 /* Consume the line end. This skips over invisible lines. */
cafafe0b 15086 set_iterator_to_next (it, 1);
5f5c8ee5
GM
15087 it->continuation_lines_width = 0;
15088 break;
1c9241f5 15089 }
a2889657 15090
2311178e 15091 /* Proceed with next display element. Note that this skips
5f5c8ee5 15092 over lines invisible because of selective display. */
cafafe0b 15093 set_iterator_to_next (it, 1);
b1d1124b 15094
5f5c8ee5
GM
15095 /* If we truncate lines, we are done when the last displayed
15096 glyphs reach past the right margin of the window. */
15097 if (it->truncate_lines_p
15098 && (FRAME_WINDOW_P (it->f)
15099 ? (it->current_x >= it->last_visible_x)
15100 : (it->current_x > it->last_visible_x)))
75d13c64 15101 {
5f5c8ee5
GM
15102 /* Maybe add truncation glyphs. */
15103 if (!FRAME_WINDOW_P (it->f))
15104 {
a98b5ed9 15105 int i, n;
2311178e 15106
a98b5ed9
GM
15107 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
15108 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
15109 break;
15110
15111 for (n = row->used[TEXT_AREA]; i < n; ++i)
15112 {
15113 row->used[TEXT_AREA] = i;
15114 produce_special_glyphs (it, IT_TRUNCATION);
15115 }
5f5c8ee5 15116 }
7af0e8d7 15117#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
15118 else
15119 {
15120 /* Don't truncate if we can overflow newline into fringe. */
15121 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
15122 {
15123 get_next_display_element (it);
15124 if (ITERATOR_AT_END_OF_LINE_P (it))
15125 {
15126 row->exact_window_width_line_p = 1;
15127 goto at_end_of_line;
15128 }
15129 }
15130 }
7af0e8d7 15131#endif /* HAVE_WINDOW_SYSTEM */
2311178e 15132
5f5c8ee5
GM
15133 row->truncated_on_right_p = 1;
15134 it->continuation_lines_width = 0;
312246d1 15135 reseat_at_next_visible_line_start (it, 0);
5f5c8ee5
GM
15136 row->ends_at_zv_p = FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n';
15137 it->hpos = hpos_before;
15138 it->current_x = x_before;
15139 break;
75d13c64 15140 }
a2889657 15141 }
a2889657 15142
5f5c8ee5
GM
15143 /* If line is not empty and hscrolled, maybe insert truncation glyphs
15144 at the left window margin. */
15145 if (it->first_visible_x
15146 && IT_CHARPOS (*it) != MATRIX_ROW_START_CHARPOS (row))
15147 {
15148 if (!FRAME_WINDOW_P (it->f))
15149 insert_left_trunc_glyphs (it);
15150 row->truncated_on_left_p = 1;
15151 }
a2889657 15152
5f5c8ee5
GM
15153 /* If the start of this line is the overlay arrow-position, then
15154 mark this glyph row as the one containing the overlay arrow.
15155 This is clearly a mess with variable size fonts. It would be
15156 better to let it be displayed like cursors under X. */
e24c997d 15157 if (MARKERP (Voverlay_arrow_position)
a2889657 15158 && current_buffer == XMARKER (Voverlay_arrow_position)->buffer
5f5c8ee5
GM
15159 && (MATRIX_ROW_START_CHARPOS (row)
15160 == marker_position (Voverlay_arrow_position))
e24c997d 15161 && STRINGP (Voverlay_arrow_string)
a2889657
JB
15162 && ! overlay_arrow_seen)
15163 {
b46952ae 15164 /* Overlay arrow in window redisplay is a fringe bitmap. */
5f5c8ee5 15165 if (!FRAME_WINDOW_P (it->f))
c4628384 15166 {
5f5c8ee5
GM
15167 struct glyph_row *arrow_row = get_overlay_arrow_glyph_row (it->w);
15168 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
15169 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
15170 struct glyph *p = row->glyphs[TEXT_AREA];
15171 struct glyph *p2, *end;
15172
15173 /* Copy the arrow glyphs. */
15174 while (glyph < arrow_end)
15175 *p++ = *glyph++;
15176
15177 /* Throw away padding glyphs. */
15178 p2 = p;
15179 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
15180 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
15181 ++p2;
15182 if (p2 > p)
212e4f87 15183 {
5f5c8ee5
GM
15184 while (p2 < end)
15185 *p++ = *p2++;
15186 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
c4628384 15187 }
c4628384 15188 }
2311178e 15189
a2889657 15190 overlay_arrow_seen = 1;
5f5c8ee5 15191 row->overlay_arrow_p = 1;
a2889657
JB
15192 }
15193
5f5c8ee5
GM
15194 /* Compute pixel dimensions of this line. */
15195 compute_line_metrics (it);
15196
15197 /* Remember the position at which this line ends. */
15198 row->end = it->current;
15199
173cbca8 15200 /* Maybe set the cursor. */
5f5c8ee5
GM
15201 if (it->w->cursor.vpos < 0
15202 && PT >= MATRIX_ROW_START_CHARPOS (row)
cafafe0b
GM
15203 && PT <= MATRIX_ROW_END_CHARPOS (row)
15204 && cursor_row_p (it->w, row))
15205 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
5f5c8ee5
GM
15206
15207 /* Highlight trailing whitespace. */
8f897821 15208 if (!NILP (Vshow_trailing_whitespace))
5f5c8ee5
GM
15209 highlight_trailing_whitespace (it->f, it->glyph_row);
15210
15211 /* Prepare for the next line. This line starts horizontally at (X
15212 HPOS) = (0 0). Vertical positions are incremented. As a
15213 convenience for the caller, IT->glyph_row is set to the next
15214 row to be used. */
15215 it->current_x = it->hpos = 0;
15216 it->current_y += row->height;
15217 ++it->vpos;
15218 ++it->glyph_row;
29b3ea63 15219 it->start = it->current;
5f5c8ee5 15220 return row->displays_text_p;
a2889657 15221}
5f5c8ee5
GM
15222
15223
a2889657 15224\f
5f5c8ee5
GM
15225/***********************************************************************
15226 Menu Bar
15227 ***********************************************************************/
15228
15229/* Redisplay the menu bar in the frame for window W.
15230
15231 The menu bar of X frames that don't have X toolkit support is
15232 displayed in a special window W->frame->menu_bar_window.
2311178e 15233
5f5c8ee5
GM
15234 The menu bar of terminal frames is treated specially as far as
15235 glyph matrices are concerned. Menu bar lines are not part of
15236 windows, so the update is done directly on the frame matrix rows
15237 for the menu bar. */
7ce2c095
RS
15238
15239static void
15240display_menu_bar (w)
15241 struct window *w;
15242{
5f5c8ee5
GM
15243 struct frame *f = XFRAME (WINDOW_FRAME (w));
15244 struct it it;
15245 Lisp_Object items;
8351baf2 15246 int i;
7ce2c095 15247
5f5c8ee5 15248 /* Don't do all this for graphical frames. */
dc937613 15249#ifdef HAVE_NTGUI
d129c4c2
KH
15250 if (!NILP (Vwindow_system))
15251 return;
dc937613 15252#endif
488dd4c4 15253#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
d3413a53 15254 if (FRAME_X_P (f))
7ce2c095 15255 return;
5f5c8ee5 15256#endif
e0f712ba 15257#ifdef MAC_OS
1a578e9b
AC
15258 if (FRAME_MAC_P (f))
15259 return;
15260#endif
5f5c8ee5
GM
15261
15262#ifdef USE_X_TOOLKIT
15263 xassert (!FRAME_WINDOW_P (f));
52377a47 15264 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
5f5c8ee5 15265 it.first_visible_x = 0;
da8b7f4f 15266 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
15267#else /* not USE_X_TOOLKIT */
15268 if (FRAME_WINDOW_P (f))
15269 {
15270 /* Menu bar lines are displayed in the desired matrix of the
15271 dummy window menu_bar_window. */
15272 struct window *menu_w;
15273 xassert (WINDOWP (f->menu_bar_window));
15274 menu_w = XWINDOW (f->menu_bar_window);
15275 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
52377a47 15276 MENU_FACE_ID);
5f5c8ee5 15277 it.first_visible_x = 0;
da8b7f4f 15278 it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
5f5c8ee5
GM
15279 }
15280 else
15281 {
15282 /* This is a TTY frame, i.e. character hpos/vpos are used as
15283 pixel x/y. */
15284 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
52377a47 15285 MENU_FACE_ID);
5f5c8ee5 15286 it.first_visible_x = 0;
da8b7f4f 15287 it.last_visible_x = FRAME_COLS (f);
5f5c8ee5
GM
15288 }
15289#endif /* not USE_X_TOOLKIT */
15290
1862a24e
MB
15291 if (! mode_line_inverse_video)
15292 /* Force the menu-bar to be displayed in the default face. */
15293 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
15294
5f5c8ee5
GM
15295 /* Clear all rows of the menu bar. */
15296 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
15297 {
15298 struct glyph_row *row = it.glyph_row + i;
15299 clear_glyph_row (row);
15300 row->enabled_p = 1;
15301 row->full_width_p = 1;
15302 }
7ce2c095 15303
5f5c8ee5
GM
15304 /* Display all items of the menu bar. */
15305 items = FRAME_MENU_BAR_ITEMS (it.f);
469937ac 15306 for (i = 0; i < XVECTOR (items)->size; i += 4)
7ce2c095 15307 {
5f5c8ee5
GM
15308 Lisp_Object string;
15309
15310 /* Stop at nil string. */
a61b7058 15311 string = AREF (items, i + 1);
8351baf2
RS
15312 if (NILP (string))
15313 break;
2d66ad19 15314
5f5c8ee5 15315 /* Remember where item was displayed. */
a61b7058 15316 AREF (items, i + 3) = make_number (it.hpos);
7ce2c095 15317
5f5c8ee5
GM
15318 /* Display the item, pad with one space. */
15319 if (it.current_x < it.last_visible_x)
15320 display_string (NULL, string, Qnil, 0, 0, &it,
2051c264 15321 SCHARS (string) + 1, 0, 0, -1);
7ce2c095
RS
15322 }
15323
2d66ad19 15324 /* Fill out the line with spaces. */
5f5c8ee5
GM
15325 if (it.current_x < it.last_visible_x)
15326 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
db6f348c 15327
5f5c8ee5
GM
15328 /* Compute the total height of the lines. */
15329 compute_line_metrics (&it);
7ce2c095 15330}
5f5c8ee5
GM
15331
15332
7ce2c095 15333\f
5f5c8ee5
GM
15334/***********************************************************************
15335 Mode Line
15336 ***********************************************************************/
15337
715e84c9
GM
15338/* Redisplay mode lines in the window tree whose root is WINDOW. If
15339 FORCE is non-zero, redisplay mode lines unconditionally.
15340 Otherwise, redisplay only mode lines that are garbaged. Value is
15341 the number of windows whose mode lines were redisplayed. */
a2889657 15342
715e84c9
GM
15343static int
15344redisplay_mode_lines (window, force)
15345 Lisp_Object window;
15346 int force;
15347{
15348 int nwindows = 0;
2311178e 15349
715e84c9
GM
15350 while (!NILP (window))
15351 {
15352 struct window *w = XWINDOW (window);
2311178e 15353
715e84c9
GM
15354 if (WINDOWP (w->hchild))
15355 nwindows += redisplay_mode_lines (w->hchild, force);
15356 else if (WINDOWP (w->vchild))
15357 nwindows += redisplay_mode_lines (w->vchild, force);
15358 else if (force
15359 || FRAME_GARBAGED_P (XFRAME (w->frame))
15360 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
15361 {
715e84c9
GM
15362 struct text_pos lpoint;
15363 struct buffer *old = current_buffer;
15364
15365 /* Set the window's buffer for the mode line display. */
15366 SET_TEXT_POS (lpoint, PT, PT_BYTE);
15367 set_buffer_internal_1 (XBUFFER (w->buffer));
2311178e 15368
715e84c9
GM
15369 /* Point refers normally to the selected window. For any
15370 other window, set up appropriate value. */
15371 if (!EQ (window, selected_window))
15372 {
15373 struct text_pos pt;
2311178e 15374
715e84c9
GM
15375 SET_TEXT_POS_FROM_MARKER (pt, w->pointm);
15376 if (CHARPOS (pt) < BEGV)
15377 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
15378 else if (CHARPOS (pt) > (ZV - 1))
15379 TEMP_SET_PT_BOTH (ZV, ZV_BYTE);
15380 else
15381 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
15382 }
15383
715e84c9
GM
15384 /* Display mode lines. */
15385 clear_glyph_matrix (w->desired_matrix);
15386 if (display_mode_lines (w))
15387 {
15388 ++nwindows;
15389 w->must_be_updated_p = 1;
15390 }
15391
15392 /* Restore old settings. */
715e84c9
GM
15393 set_buffer_internal_1 (old);
15394 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
15395 }
15396
15397 window = w->next;
15398 }
15399
15400 return nwindows;
15401}
15402
15403
15404/* Display the mode and/or top line of window W. Value is the number
15405 of mode lines displayed. */
15406
15407static int
5f5c8ee5 15408display_mode_lines (w)
a2889657
JB
15409 struct window *w;
15410{
edd1e654 15411 Lisp_Object old_selected_window, old_selected_frame;
715e84c9 15412 int n = 0;
edd1e654
GM
15413
15414 old_selected_frame = selected_frame;
15415 selected_frame = w->frame;
15416 old_selected_window = selected_window;
15417 XSETWINDOW (selected_window, w);
2311178e 15418
5f5c8ee5 15419 /* These will be set while the mode line specs are processed. */
aa6d10fa 15420 line_number_displayed = 0;
155ef550 15421 w->column_number_displayed = Qnil;
aa6d10fa 15422
5f5c8ee5 15423 if (WINDOW_WANTS_MODELINE_P (w))
715e84c9 15424 {
c96e83bf 15425 struct window *sel_w = XWINDOW (old_selected_window);
f87c0a98 15426
96d2320f 15427 /* Select mode line face based on the real selected window. */
c96e83bf 15428 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
715e84c9
GM
15429 current_buffer->mode_line_format);
15430 ++n;
15431 }
2311178e 15432
045dee35 15433 if (WINDOW_WANTS_HEADER_LINE_P (w))
715e84c9
GM
15434 {
15435 display_mode_line (w, HEADER_LINE_FACE_ID,
15436 current_buffer->header_line_format);
15437 ++n;
15438 }
15439
edd1e654
GM
15440 selected_frame = old_selected_frame;
15441 selected_window = old_selected_window;
715e84c9 15442 return n;
5f5c8ee5 15443}
03b294dc 15444
03b294dc 15445
5f5c8ee5 15446/* Display mode or top line of window W. FACE_ID specifies which line
045dee35 15447 to display; it is either MODE_LINE_FACE_ID or HEADER_LINE_FACE_ID.
04612a64
GM
15448 FORMAT is the mode line format to display. Value is the pixel
15449 height of the mode line displayed. */
03b294dc 15450
04612a64 15451static int
5f5c8ee5
GM
15452display_mode_line (w, face_id, format)
15453 struct window *w;
15454 enum face_id face_id;
15455 Lisp_Object format;
15456{
15457 struct it it;
15458 struct face *face;
03b294dc 15459
5f5c8ee5
GM
15460 init_iterator (&it, w, -1, -1, NULL, face_id);
15461 prepare_desired_row (it.glyph_row);
15462
1862a24e
MB
15463 if (! mode_line_inverse_video)
15464 /* Force the mode-line to be displayed in the default face. */
15465 it.base_face_id = it.face_id = DEFAULT_FACE_ID;
15466
5f5c8ee5
GM
15467 /* Temporarily make frame's keyboard the current kboard so that
15468 kboard-local variables in the mode_line_format will get the right
15469 values. */
15470 push_frame_kboard (it.f);
c53a1624 15471 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
5f5c8ee5 15472 pop_frame_kboard ();
a2889657 15473
5f5c8ee5
GM
15474 /* Fill up with spaces. */
15475 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
2311178e 15476
5f5c8ee5
GM
15477 compute_line_metrics (&it);
15478 it.glyph_row->full_width_p = 1;
15479 it.glyph_row->mode_line_p = 1;
5f5c8ee5
GM
15480 it.glyph_row->continued_p = 0;
15481 it.glyph_row->truncated_on_left_p = 0;
15482 it.glyph_row->truncated_on_right_p = 0;
15483
15484 /* Make a 3D mode-line have a shadow at its right end. */
15485 face = FACE_FROM_ID (it.f, face_id);
15486 extend_face_to_end_of_line (&it);
15487 if (face->box != FACE_NO_BOX)
d7eb09a0 15488 {
5f5c8ee5
GM
15489 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
15490 + it.glyph_row->used[TEXT_AREA] - 1);
15491 last->right_box_line_p = 1;
d7eb09a0 15492 }
04612a64
GM
15493
15494 return it.glyph_row->height;
a2889657
JB
15495}
15496
0fcf414f
RS
15497/* Alist that caches the results of :propertize.
15498 Each element is (PROPERTIZED-STRING . PROPERTY-LIST). */
15499Lisp_Object mode_line_proptrans_alist;
a2889657 15500
fec8f23e
KS
15501/* List of strings making up the mode-line. */
15502Lisp_Object mode_line_string_list;
15503
15504/* Base face property when building propertized mode line string. */
15505static Lisp_Object mode_line_string_face;
15506static Lisp_Object mode_line_string_face_prop;
15507
15508
5f5c8ee5
GM
15509/* Contribute ELT to the mode line for window IT->w. How it
15510 translates into text depends on its data type.
a2889657 15511
5f5c8ee5 15512 IT describes the display environment in which we display, as usual.
a2889657
JB
15513
15514 DEPTH is the depth in recursion. It is used to prevent
15515 infinite recursion here.
15516
5f5c8ee5
GM
15517 FIELD_WIDTH is the number of characters the display of ELT should
15518 occupy in the mode line, and PRECISION is the maximum number of
15519 characters to display from ELT's representation. See
b8523839 15520 display_string for details.
a2889657 15521
c53a1624
RS
15522 Returns the hpos of the end of the text generated by ELT.
15523
15524 PROPS is a property list to add to any string we encounter.
15525
7d0393cf 15526 If RISKY is nonzero, remove (disregard) any properties in any string
93da8435
SM
15527 we encounter, and ignore :eval and :propertize.
15528
15529 If the global variable `frame_title_ptr' is non-NULL, then the output
15530 is passed to `store_frame_title' instead of `display_string'. */
a2889657
JB
15531
15532static int
c53a1624 15533display_mode_element (it, depth, field_width, precision, elt, props, risky)
5f5c8ee5 15534 struct it *it;
a2889657 15535 int depth;
5f5c8ee5 15536 int field_width, precision;
0fcf414f 15537 Lisp_Object elt, props;
c53a1624 15538 int risky;
a2889657 15539{
5f5c8ee5 15540 int n = 0, field, prec;
0fcf414f 15541 int literal = 0;
5f5c8ee5 15542
a2889657 15543 tail_recurse:
1a89be1e
SM
15544 if (depth > 100)
15545 elt = build_string ("*too-deep*");
a2889657
JB
15546
15547 depth++;
15548
0220c518 15549 switch (SWITCH_ENUM_CAST (XTYPE (elt)))
a2889657
JB
15550 {
15551 case Lisp_String:
15552 {
15553 /* A string: output it and check for %-constructs within it. */
5f5c8ee5 15554 unsigned char c;
50f80c2f 15555 const unsigned char *this, *lisp_string;
5f5c8ee5 15556
c53a1624 15557 if (!NILP (props) || risky)
0fcf414f
RS
15558 {
15559 Lisp_Object oprops, aelt;
15560 oprops = Ftext_properties_at (make_number (0), elt);
c53a1624
RS
15561
15562 if (NILP (Fequal (props, oprops)) || risky)
0fcf414f 15563 {
ae02e06a
RS
15564 /* If the starting string has properties,
15565 merge the specified ones onto the existing ones. */
c53a1624 15566 if (! NILP (oprops) && !risky)
ae02e06a
RS
15567 {
15568 Lisp_Object tem;
15569
15570 oprops = Fcopy_sequence (oprops);
15571 tem = props;
15572 while (CONSP (tem))
15573 {
15574 oprops = Fplist_put (oprops, XCAR (tem),
15575 XCAR (XCDR (tem)));
15576 tem = XCDR (XCDR (tem));
15577 }
15578 props = oprops;
15579 }
15580
0fcf414f
RS
15581 aelt = Fassoc (elt, mode_line_proptrans_alist);
15582 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
adb63af1
RS
15583 {
15584 mode_line_proptrans_alist
15585 = Fcons (aelt, Fdelq (aelt, mode_line_proptrans_alist));
15586 elt = XCAR (aelt);
15587 }
0fcf414f
RS
15588 else
15589 {
adb63af1
RS
15590 Lisp_Object tem;
15591
0fcf414f 15592 elt = Fcopy_sequence (elt);
dc3b2c8b
SM
15593 Fset_text_properties (make_number (0), Flength (elt),
15594 props, elt);
adb63af1 15595 /* Add this item to mode_line_proptrans_alist. */
0fcf414f
RS
15596 mode_line_proptrans_alist
15597 = Fcons (Fcons (elt, props),
15598 mode_line_proptrans_alist);
adb63af1
RS
15599 /* Truncate mode_line_proptrans_alist
15600 to at most 50 elements. */
15601 tem = Fnthcdr (make_number (50),
15602 mode_line_proptrans_alist);
15603 if (! NILP (tem))
15604 XSETCDR (tem, Qnil);
0fcf414f
RS
15605 }
15606 }
15607 }
15608
2051c264 15609 this = SDATA (elt);
ae02e06a
RS
15610 lisp_string = this;
15611
0fcf414f
RS
15612 if (literal)
15613 {
15614 prec = precision - n;
15615 if (frame_title_ptr)
2051c264 15616 n += store_frame_title (SDATA (elt), -1, prec);
fec8f23e
KS
15617 else if (!NILP (mode_line_string_list))
15618 n += store_mode_line_string (NULL, elt, 1, 0, prec, Qnil);
0fcf414f
RS
15619 else
15620 n += display_string (NULL, elt, Qnil, 0, 0, it,
15621 0, prec, 0, STRING_MULTIBYTE (elt));
15622
15623 break;
15624 }
15625
5f5c8ee5
GM
15626 while ((precision <= 0 || n < precision)
15627 && *this
15628 && (frame_title_ptr
fec8f23e 15629 || !NILP (mode_line_string_list)
5f5c8ee5 15630 || it->current_x < it->last_visible_x))
a2889657 15631 {
50f80c2f 15632 const unsigned char *last = this;
5f5c8ee5
GM
15633
15634 /* Advance to end of string or next format specifier. */
a2889657
JB
15635 while ((c = *this++) != '\0' && c != '%')
15636 ;
2311178e 15637
a2889657
JB
15638 if (this - 1 != last)
15639 {
5f5c8ee5
GM
15640 /* Output to end of string or up to '%'. Field width
15641 is length of string. Don't output more than
15642 PRECISION allows us. */
d26b89b8 15643 --this;
eaaa65b0
GM
15644
15645 prec = chars_in_text (last, this - last);
5f5c8ee5
GM
15646 if (precision > 0 && prec > precision - n)
15647 prec = precision - n;
2311178e 15648
d39b6696 15649 if (frame_title_ptr)
d26b89b8 15650 n += store_frame_title (last, 0, prec);
fec8f23e
KS
15651 else if (!NILP (mode_line_string_list))
15652 {
15653 int bytepos = last - lisp_string;
15654 int charpos = string_byte_to_char (elt, bytepos);
15655 n += store_mode_line_string (NULL,
15656 Fsubstring (elt, make_number (charpos),
15657 make_number (charpos + prec)),
15658 0, 0, 0, Qnil);
15659 }
d39b6696 15660 else
eaaa65b0
GM
15661 {
15662 int bytepos = last - lisp_string;
15663 int charpos = string_byte_to_char (elt, bytepos);
15664 n += display_string (NULL, elt, Qnil, 0, charpos,
ca77144d
GM
15665 it, 0, prec, 0,
15666 STRING_MULTIBYTE (elt));
eaaa65b0 15667 }
a2889657
JB
15668 }
15669 else /* c == '%' */
15670 {
50f80c2f 15671 const unsigned char *percent_position = this;
2311178e 15672
5f5c8ee5
GM
15673 /* Get the specified minimum width. Zero means
15674 don't pad. */
15675 field = 0;
a2889657 15676 while ((c = *this++) >= '0' && c <= '9')
5f5c8ee5 15677 field = field * 10 + c - '0';
a2889657 15678
5f5c8ee5
GM
15679 /* Don't pad beyond the total padding allowed. */
15680 if (field_width - n > 0 && field > field_width - n)
15681 field = field_width - n;
a2889657 15682
5f5c8ee5
GM
15683 /* Note that either PRECISION <= 0 or N < PRECISION. */
15684 prec = precision - n;
2311178e 15685
a2889657 15686 if (c == 'M')
5f5c8ee5 15687 n += display_mode_element (it, depth, field, prec,
c53a1624
RS
15688 Vglobal_mode_string, props,
15689 risky);
a2889657 15690 else if (c != 0)
d39b6696 15691 {
72f62cb5 15692 int multibyte;
ae02e06a
RS
15693 int bytepos, charpos;
15694 unsigned char *spec;
2311178e 15695
ae02e06a
RS
15696 bytepos = percent_position - lisp_string;
15697 charpos = (STRING_MULTIBYTE (elt)
15698 ? string_byte_to_char (elt, bytepos)
15699 : bytepos);
15700
15701 spec
72f62cb5
GM
15702 = decode_mode_spec (it->w, c, field, prec, &multibyte);
15703
d39b6696 15704 if (frame_title_ptr)
5f5c8ee5 15705 n += store_frame_title (spec, field, prec);
fec8f23e
KS
15706 else if (!NILP (mode_line_string_list))
15707 {
15708 int len = strlen (spec);
15709 Lisp_Object tem = make_string (spec, len);
15710 props = Ftext_properties_at (make_number (charpos), elt);
15711 /* Should only keep face property in props */
15712 n += store_mode_line_string (NULL, tem, 0, field, prec, props);
15713 }
d39b6696 15714 else
5f5c8ee5 15715 {
ae02e06a 15716 int nglyphs_before, nwritten;
2311178e 15717
72f62cb5 15718 nglyphs_before = it->glyph_row->used[TEXT_AREA];
72f62cb5
GM
15719 nwritten = display_string (spec, Qnil, elt,
15720 charpos, 0, it,
15721 field, prec, 0,
15722 multibyte);
5f5c8ee5
GM
15723
15724 /* Assign to the glyphs written above the
15725 string where the `%x' came from, position
15726 of the `%'. */
15727 if (nwritten > 0)
15728 {
15729 struct glyph *glyph
15730 = (it->glyph_row->glyphs[TEXT_AREA]
15731 + nglyphs_before);
15732 int i;
15733
15734 for (i = 0; i < nwritten; ++i)
15735 {
15736 glyph[i].object = elt;
15737 glyph[i].charpos = charpos;
15738 }
2311178e 15739
5f5c8ee5
GM
15740 n += nwritten;
15741 }
15742 }
d39b6696 15743 }
b8523839
AS
15744 else /* c == 0 */
15745 break;
a2889657
JB
15746 }
15747 }
15748 }
15749 break;
15750
15751 case Lisp_Symbol:
15752 /* A symbol: process the value of the symbol recursively
15753 as if it appeared here directly. Avoid error if symbol void.
15754 Special case: if value of symbol is a string, output the string
15755 literally. */
15756 {
15757 register Lisp_Object tem;
c53a1624
RS
15758
15759 /* If the variable is not marked as risky to set
15760 then its contents are risky to use. */
15761 if (NILP (Fget (elt, Qrisky_local_variable)))
15762 risky = 1;
15763
a2889657 15764 tem = Fboundp (elt);
265a9e55 15765 if (!NILP (tem))
a2889657
JB
15766 {
15767 tem = Fsymbol_value (elt);
15768 /* If value is a string, output that string literally:
15769 don't check for % within it. */
e24c997d 15770 if (STRINGP (tem))
0fcf414f
RS
15771 literal = 1;
15772
15773 if (!EQ (tem, elt))
5f5c8ee5
GM
15774 {
15775 /* Give up right away for nil or t. */
15776 elt = tem;
15777 goto tail_recurse;
15778 }
a2889657
JB
15779 }
15780 }
15781 break;
15782
15783 case Lisp_Cons:
15784 {
15785 register Lisp_Object car, tem;
15786
0fcf414f
RS
15787 /* A cons cell: five distinct cases.
15788 If first element is :eval or :propertize, do something special.
a2889657
JB
15789 If first element is a string or a cons, process all the elements
15790 and effectively concatenate them.
15791 If first element is a negative number, truncate displaying cdr to
15792 at most that many characters. If positive, pad (with spaces)
15793 to at least that many characters.
15794 If first element is a symbol, process the cadr or caddr recursively
15795 according to whether the symbol's value is non-nil or nil. */
9472f927 15796 car = XCAR (elt);
0fcf414f 15797 if (EQ (car, QCeval))
5f5c8ee5
GM
15798 {
15799 /* An element of the form (:eval FORM) means evaluate FORM
15800 and use the result as mode line elements. */
0fcf414f 15801
c53a1624
RS
15802 if (risky)
15803 break;
15804
0fcf414f
RS
15805 if (CONSP (XCDR (elt)))
15806 {
15807 Lisp_Object spec;
15808 spec = safe_eval (XCAR (XCDR (elt)));
15809 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15810 precision - n, spec, props,
15811 risky);
0fcf414f
RS
15812 }
15813 }
15814 else if (EQ (car, QCpropertize))
15815 {
c53a1624
RS
15816 /* An element of the form (:propertize ELT PROPS...)
15817 means display ELT but applying properties PROPS. */
15818
15819 if (risky)
15820 break;
15821
0fcf414f 15822 if (CONSP (XCDR (elt)))
c53a1624
RS
15823 n += display_mode_element (it, depth, field_width - n,
15824 precision - n, XCAR (XCDR (elt)),
15825 XCDR (XCDR (elt)), risky);
5f5c8ee5
GM
15826 }
15827 else if (SYMBOLP (car))
a2889657
JB
15828 {
15829 tem = Fboundp (car);
9472f927 15830 elt = XCDR (elt);
e24c997d 15831 if (!CONSP (elt))
a2889657
JB
15832 goto invalid;
15833 /* elt is now the cdr, and we know it is a cons cell.
15834 Use its car if CAR has a non-nil value. */
265a9e55 15835 if (!NILP (tem))
a2889657
JB
15836 {
15837 tem = Fsymbol_value (car);
265a9e55 15838 if (!NILP (tem))
9472f927
GM
15839 {
15840 elt = XCAR (elt);
15841 goto tail_recurse;
15842 }
a2889657
JB
15843 }
15844 /* Symbol's value is nil (or symbol is unbound)
15845 Get the cddr of the original list
15846 and if possible find the caddr and use that. */
9472f927 15847 elt = XCDR (elt);
265a9e55 15848 if (NILP (elt))
a2889657 15849 break;
e24c997d 15850 else if (!CONSP (elt))
a2889657 15851 goto invalid;
9472f927 15852 elt = XCAR (elt);
a2889657
JB
15853 goto tail_recurse;
15854 }
e24c997d 15855 else if (INTEGERP (car))
a2889657
JB
15856 {
15857 register int lim = XINT (car);
9472f927 15858 elt = XCDR (elt);
a2889657 15859 if (lim < 0)
5f5c8ee5
GM
15860 {
15861 /* Negative int means reduce maximum width. */
15862 if (precision <= 0)
15863 precision = -lim;
15864 else
15865 precision = min (precision, -lim);
15866 }
a2889657
JB
15867 else if (lim > 0)
15868 {
15869 /* Padding specified. Don't let it be more than
15870 current maximum. */
5f5c8ee5
GM
15871 if (precision > 0)
15872 lim = min (precision, lim);
15873
a2889657
JB
15874 /* If that's more padding than already wanted, queue it.
15875 But don't reduce padding already specified even if
15876 that is beyond the current truncation point. */
5f5c8ee5 15877 field_width = max (lim, field_width);
a2889657
JB
15878 }
15879 goto tail_recurse;
15880 }
e24c997d 15881 else if (STRINGP (car) || CONSP (car))
a2889657
JB
15882 {
15883 register int limit = 50;
5f5c8ee5
GM
15884 /* Limit is to protect against circular lists. */
15885 while (CONSP (elt)
15886 && --limit > 0
15887 && (precision <= 0 || n < precision))
a2889657 15888 {
5f5c8ee5 15889 n += display_mode_element (it, depth, field_width - n,
c53a1624
RS
15890 precision - n, XCAR (elt),
15891 props, risky);
9472f927 15892 elt = XCDR (elt);
a2889657
JB
15893 }
15894 }
15895 }
15896 break;
15897
15898 default:
15899 invalid:
1a89be1e
SM
15900 elt = build_string ("*invalid*");
15901 goto tail_recurse;
a2889657
JB
15902 }
15903
5f5c8ee5
GM
15904 /* Pad to FIELD_WIDTH. */
15905 if (field_width > 0 && n < field_width)
15906 {
15907 if (frame_title_ptr)
15908 n += store_frame_title ("", field_width - n, 0);
fec8f23e
KS
15909 else if (!NILP (mode_line_string_list))
15910 n += store_mode_line_string ("", Qnil, 0, field_width - n, 0, Qnil);
5f5c8ee5
GM
15911 else
15912 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
15913 0, 0, 0);
15914 }
2311178e 15915
5f5c8ee5 15916 return n;
a2889657 15917}
5f5c8ee5 15918
fec8f23e
KS
15919/* Store a mode-line string element in mode_line_string_list.
15920
15921 If STRING is non-null, display that C string. Otherwise, the Lisp
15922 string LISP_STRING is displayed.
15923
15924 FIELD_WIDTH is the minimum number of output glyphs to produce.
15925 If STRING has fewer characters than FIELD_WIDTH, pad to the right
15926 with spaces. FIELD_WIDTH <= 0 means don't pad.
15927
15928 PRECISION is the maximum number of characters to output from
15929 STRING. PRECISION <= 0 means don't truncate the string.
15930
15931 If COPY_STRING is non-zero, make a copy of LISP_STRING before adding
15932 properties to the string.
15933
7d0393cf 15934 PROPS are the properties to add to the string.
fec8f23e
KS
15935 The mode_line_string_face face property is always added to the string.
15936 */
15937
15938static int store_mode_line_string (string, lisp_string, copy_string, field_width, precision, props)
15939 char *string;
15940 Lisp_Object lisp_string;
15941 int copy_string;
15942 int field_width;
15943 int precision;
15944 Lisp_Object props;
15945{
15946 int len;
15947 int n = 0;
15948
15949 if (string != NULL)
15950 {
15951 len = strlen (string);
15952 if (precision > 0 && len > precision)
15953 len = precision;
15954 lisp_string = make_string (string, len);
15955 if (NILP (props))
15956 props = mode_line_string_face_prop;
15957 else if (!NILP (mode_line_string_face))
15958 {
15959 Lisp_Object face = Fplist_get (props, Qface);
15960 props = Fcopy_sequence (props);
15961 if (NILP (face))
15962 face = mode_line_string_face;
15963 else
15964 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15965 props = Fplist_put (props, Qface, face);
15966 }
15967 Fadd_text_properties (make_number (0), make_number (len),
15968 props, lisp_string);
15969 }
7d0393cf 15970 else
fec8f23e 15971 {
c8224325 15972 len = XFASTINT (Flength (lisp_string));
fec8f23e
KS
15973 if (precision > 0 && len > precision)
15974 {
15975 len = precision;
15976 lisp_string = Fsubstring (lisp_string, make_number (0), make_number (len));
15977 precision = -1;
15978 }
15979 if (!NILP (mode_line_string_face))
15980 {
15981 Lisp_Object face;
15982 if (NILP (props))
15983 props = Ftext_properties_at (make_number (0), lisp_string);
15984 face = Fplist_get (props, Qface);
15985 if (NILP (face))
15986 face = mode_line_string_face;
15987 else
15988 face = Fcons (face, Fcons (mode_line_string_face, Qnil));
15989 props = Fcons (Qface, Fcons (face, Qnil));
15990 if (copy_string)
15991 lisp_string = Fcopy_sequence (lisp_string);
15992 }
15993 if (!NILP (props))
15994 Fadd_text_properties (make_number (0), make_number (len),
15995 props, lisp_string);
15996 }
15997
15998 if (len > 0)
15999 {
16000 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 16001 n += len;
fec8f23e
KS
16002 }
16003
16004 if (field_width > len)
16005 {
16006 field_width -= len;
16007 lisp_string = Fmake_string (make_number (field_width), make_number (' '));
16008 if (!NILP (props))
16009 Fadd_text_properties (make_number (0), make_number (field_width),
16010 props, lisp_string);
16011 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
7d0393cf 16012 n += field_width;
fec8f23e
KS
16013 }
16014
16015 return n;
16016}
16017
5f5c8ee5 16018
8143e6ab 16019DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
fec8f23e 16020 0, 3, 0,
8143e6ab
KS
16021 doc: /* Return the mode-line of selected window as a string.
16022First optional arg FORMAT specifies a different format string (see
8b22c65a 16023`mode-line-format' for details) to use. If FORMAT is t, return
8143e6ab 16024the buffer's header-line. Second optional arg WINDOW specifies a
fec8f23e
KS
16025different window to use as the context for the formatting.
16026If third optional arg NO-PROPS is non-nil, string is not propertized. */)
16027 (format, window, no_props)
16028 Lisp_Object format, window, no_props;
8143e6ab
KS
16029{
16030 struct it it;
8143e6ab
KS
16031 int len;
16032 struct window *w;
16033 struct buffer *old_buffer = NULL;
fec8f23e 16034 enum face_id face_id = DEFAULT_FACE_ID;
8143e6ab
KS
16035
16036 if (NILP (window))
16037 window = selected_window;
16038 CHECK_WINDOW (window);
16039 w = XWINDOW (window);
16040 CHECK_BUFFER (w->buffer);
16041
16042 if (XBUFFER (w->buffer) != current_buffer)
16043 {
16044 old_buffer = current_buffer;
16045 set_buffer_internal_1 (XBUFFER (w->buffer));
16046 }
16047
16048 if (NILP (format) || EQ (format, Qt))
fec8f23e
KS
16049 {
16050 face_id = NILP (format)
16051 ? CURRENT_MODE_LINE_FACE_ID (w) :
16052 HEADER_LINE_FACE_ID;
16053 format = NILP (format)
16054 ? current_buffer->mode_line_format
16055 : current_buffer->header_line_format;
16056 }
16057
16058 init_iterator (&it, w, -1, -1, NULL, face_id);
8143e6ab 16059
fec8f23e
KS
16060 if (NILP (no_props))
16061 {
16062 mode_line_string_face =
16063 (face_id == MODE_LINE_FACE_ID ? Qmode_line :
16064 face_id == MODE_LINE_INACTIVE_FACE_ID ? Qmode_line_inactive :
16065 face_id == HEADER_LINE_FACE_ID ? Qheader_line : Qnil);
8143e6ab 16066
fec8f23e
KS
16067 mode_line_string_face_prop =
16068 NILP (mode_line_string_face) ? Qnil :
16069 Fcons (Qface, Fcons (mode_line_string_face, Qnil));
16070
16071 /* We need a dummy last element in mode_line_string_list to
16072 indicate we are building the propertized mode-line string.
16073 Using mode_line_string_face_prop here GC protects it. */
7d0393cf 16074 mode_line_string_list =
fec8f23e
KS
16075 Fcons (mode_line_string_face_prop, Qnil);
16076 frame_title_ptr = NULL;
16077 }
16078 else
16079 {
16080 mode_line_string_face_prop = Qnil;
16081 mode_line_string_list = Qnil;
16082 frame_title_ptr = frame_title_buf;
16083 }
8143e6ab
KS
16084
16085 push_frame_kboard (it.f);
16086 display_mode_element (&it, 0, 0, 0, format, Qnil, 0);
16087 pop_frame_kboard ();
16088
16089 if (old_buffer)
16090 set_buffer_internal_1 (old_buffer);
16091
fec8f23e
KS
16092 if (NILP (no_props))
16093 {
16094 Lisp_Object str;
16095 mode_line_string_list = Fnreverse (mode_line_string_list);
16096 str = Fmapconcat (intern ("identity"), XCDR (mode_line_string_list),
16097 make_string ("", 0));
16098 mode_line_string_face_prop = Qnil;
16099 mode_line_string_list = Qnil;
16100 return str;
16101 }
16102
8143e6ab
KS
16103 len = frame_title_ptr - frame_title_buf;
16104 if (len > 0 && frame_title_ptr[-1] == '-')
16105 {
16106 /* Mode lines typically ends with numerous dashes; reduce to two dashes. */
16107 while (frame_title_ptr > frame_title_buf && *--frame_title_ptr == '-')
16108 ;
16109 frame_title_ptr += 3; /* restore last non-dash + two dashes */
16110 if (len > frame_title_ptr - frame_title_buf)
16111 len = frame_title_ptr - frame_title_buf;
16112 }
16113
16114 frame_title_ptr = NULL;
16115 return make_string (frame_title_buf, len);
16116}
16117
766525bc
RS
16118/* Write a null-terminated, right justified decimal representation of
16119 the positive integer D to BUF using a minimal field width WIDTH. */
16120
16121static void
16122pint2str (buf, width, d)
16123 register char *buf;
16124 register int width;
16125 register int d;
16126{
16127 register char *p = buf;
2311178e 16128
766525bc 16129 if (d <= 0)
5f5c8ee5 16130 *p++ = '0';
766525bc 16131 else
5f5c8ee5 16132 {
766525bc 16133 while (d > 0)
5f5c8ee5 16134 {
766525bc
RS
16135 *p++ = d % 10 + '0';
16136 d /= 10;
5f5c8ee5
GM
16137 }
16138 }
2311178e 16139
5f5c8ee5
GM
16140 for (width -= (int) (p - buf); width > 0; --width)
16141 *p++ = ' ';
766525bc
RS
16142 *p-- = '\0';
16143 while (p > buf)
5f5c8ee5 16144 {
766525bc
RS
16145 d = *buf;
16146 *buf++ = *p;
16147 *p-- = d;
5f5c8ee5 16148 }
766525bc
RS
16149}
16150
525b8b09
LK
16151/* Write a null-terminated, right justified decimal and "human
16152 readable" representation of the nonnegative integer D to BUF using
16153 a minimal field width WIDTH. D should be smaller than 999.5e24. */
16154
16155static const char power_letter[] =
16156 {
16157 0, /* not used */
16158 'k', /* kilo */
16159 'M', /* mega */
16160 'G', /* giga */
16161 'T', /* tera */
16162 'P', /* peta */
16163 'E', /* exa */
16164 'Z', /* zetta */
16165 'Y' /* yotta */
16166 };
16167
16168static void
16169pint2hrstr (buf, width, d)
16170 char *buf;
16171 int width;
16172 int d;
16173{
16174 /* We aim to represent the nonnegative integer D as
16175 QUOTIENT.TENTHS * 10 ^ (3 * EXPONENT). */
16176 int quotient = d;
16177 int remainder = 0;
16178 /* -1 means: do not use TENTHS. */
16179 int tenths = -1;
16180 int exponent = 0;
16181
16182 /* Length of QUOTIENT.TENTHS as a string. */
16183 int length;
16184
16185 char * psuffix;
16186 char * p;
16187
16188 if (1000 <= quotient)
16189 {
16190 /* Scale to the appropriate EXPONENT. */
16191 do
16192 {
16193 remainder = quotient % 1000;
16194 quotient /= 1000;
16195 exponent++;
16196 }
16197 while (1000 <= quotient);
16198
16199 /* Round to nearest and decide whether to use TENTHS or not. */
16200 if (quotient <= 9)
16201 {
16202 tenths = remainder / 100;
16203 if (50 <= remainder % 100)
16204 if (tenths < 9)
16205 tenths++;
16206 else
16207 {
16208 quotient++;
16209 if (quotient == 10)
16210 tenths = -1;
16211 else
16212 tenths = 0;
16213 }
16214 }
16215 else
16216 if (500 <= remainder)
16217 if (quotient < 999)
16218 quotient++;
16219 else
16220 {
16221 quotient = 1;
16222 exponent++;
16223 tenths = 0;
16224 }
16225 }
16226
16227 /* Calculate the LENGTH of QUOTIENT.TENTHS as a string. */
16228 if (tenths == -1 && quotient <= 99)
16229 if (quotient <= 9)
16230 length = 1;
16231 else
16232 length = 2;
16233 else
16234 length = 3;
16235 p = psuffix = buf + max (width, length);
16236
16237 /* Print EXPONENT. */
16238 if (exponent)
16239 *psuffix++ = power_letter[exponent];
16240 *psuffix = '\0';
16241
16242 /* Print TENTHS. */
16243 if (tenths >= 0)
16244 {
16245 *--p = '0' + tenths;
16246 *--p = '.';
16247 }
16248
16249 /* Print QUOTIENT. */
16250 do
16251 {
16252 int digit = quotient % 10;
16253 *--p = '0' + digit;
16254 }
16255 while ((quotient /= 10) != 0);
16256
16257 /* Print leading spaces. */
16258 while (buf < p)
16259 *--p = ' ';
16260}
16261
5f5c8ee5 16262/* Set a mnemonic character for coding_system (Lisp symbol) in BUF.
1c9241f5
KH
16263 If EOL_FLAG is 1, set also a mnemonic character for end-of-line
16264 type of CODING_SYSTEM. Return updated pointer into BUF. */
16265
6693a99a 16266static unsigned char invalid_eol_type[] = "(*invalid*)";
d24715e8 16267
1c9241f5
KH
16268static char *
16269decode_mode_spec_coding (coding_system, buf, eol_flag)
16270 Lisp_Object coding_system;
16271 register char *buf;
16272 int eol_flag;
16273{
1e1078d6 16274 Lisp_Object val;
916848d8 16275 int multibyte = !NILP (current_buffer->enable_multibyte_characters);
50f80c2f 16276 const unsigned char *eol_str;
302f2b38
EZ
16277 int eol_str_len;
16278 /* The EOL conversion we are using. */
16279 Lisp_Object eoltype;
1e1078d6 16280
4a09dee0 16281 val = Fget (coding_system, Qcoding_system);
085536c2 16282 eoltype = Qnil;
1c9241f5 16283
4a09dee0 16284 if (!VECTORP (val)) /* Not yet decided. */
1c9241f5 16285 {
916848d8
RS
16286 if (multibyte)
16287 *buf++ = '-';
21e989e3 16288 if (eol_flag)
302f2b38 16289 eoltype = eol_mnemonic_undecided;
1e1078d6 16290 /* Don't mention EOL conversion if it isn't decided. */
1c9241f5
KH
16291 }
16292 else
16293 {
1e1078d6
RS
16294 Lisp_Object eolvalue;
16295
16296 eolvalue = Fget (coding_system, Qeol_type);
16297
916848d8 16298 if (multibyte)
a61b7058 16299 *buf++ = XFASTINT (AREF (val, 1));
916848d8 16300
1c9241f5
KH
16301 if (eol_flag)
16302 {
1e1078d6
RS
16303 /* The EOL conversion that is normal on this system. */
16304
16305 if (NILP (eolvalue)) /* Not yet decided. */
16306 eoltype = eol_mnemonic_undecided;
16307 else if (VECTORP (eolvalue)) /* Not yet decided. */
16308 eoltype = eol_mnemonic_undecided;
16309 else /* INTEGERP (eolvalue) -- 0:LF, 1:CRLF, 2:CR */
16310 eoltype = (XFASTINT (eolvalue) == 0
16311 ? eol_mnemonic_unix
16312 : (XFASTINT (eolvalue) == 1
16313 ? eol_mnemonic_dos : eol_mnemonic_mac));
302f2b38
EZ
16314 }
16315 }
2311178e 16316
302f2b38
EZ
16317 if (eol_flag)
16318 {
16319 /* Mention the EOL conversion if it is not the usual one. */
16320 if (STRINGP (eoltype))
16321 {
2051c264
GM
16322 eol_str = SDATA (eoltype);
16323 eol_str_len = SBYTES (eoltype);
302f2b38 16324 }
f30b3499
KH
16325 else if (INTEGERP (eoltype)
16326 && CHAR_VALID_P (XINT (eoltype), 0))
16327 {
50f80c2f
KR
16328 unsigned char *tmp = (unsigned char *) alloca (MAX_MULTIBYTE_LENGTH);
16329 eol_str_len = CHAR_STRING (XINT (eoltype), tmp);
16330 eol_str = tmp;
f30b3499 16331 }
302f2b38
EZ
16332 else
16333 {
16334 eol_str = invalid_eol_type;
16335 eol_str_len = sizeof (invalid_eol_type) - 1;
1c9241f5 16336 }
f30b3499 16337 bcopy (eol_str, buf, eol_str_len);
302f2b38 16338 buf += eol_str_len;
1c9241f5 16339 }
302f2b38 16340
1c9241f5
KH
16341 return buf;
16342}
16343
a2889657 16344/* Return a string for the output of a mode line %-spec for window W,
5f5c8ee5
GM
16345 generated by character C. PRECISION >= 0 means don't return a
16346 string longer than that value. FIELD_WIDTH > 0 means pad the
72f62cb5
GM
16347 string returned with spaces to that value. Return 1 in *MULTIBYTE
16348 if the result is multibyte text. */
a2889657 16349
11e82b76
JB
16350static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
16351
a2889657 16352static char *
72f62cb5 16353decode_mode_spec (w, c, field_width, precision, multibyte)
a2889657 16354 struct window *w;
68c45bf0 16355 register int c;
5f5c8ee5 16356 int field_width, precision;
72f62cb5 16357 int *multibyte;
a2889657 16358{
0b67772d 16359 Lisp_Object obj;
5f5c8ee5
GM
16360 struct frame *f = XFRAME (WINDOW_FRAME (w));
16361 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
d39b6696 16362 struct buffer *b = XBUFFER (w->buffer);
a2889657 16363
0b67772d 16364 obj = Qnil;
72f62cb5 16365 *multibyte = 0;
a2889657
JB
16366
16367 switch (c)
16368 {
1af9f229
RS
16369 case '*':
16370 if (!NILP (b->read_only))
16371 return "%";
16372 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16373 return "*";
16374 return "-";
16375
16376 case '+':
16377 /* This differs from %* only for a modified read-only buffer. */
16378 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16379 return "*";
16380 if (!NILP (b->read_only))
16381 return "%";
16382 return "-";
16383
16384 case '&':
16385 /* This differs from %* in ignoring read-only-ness. */
16386 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
16387 return "*";
16388 return "-";
16389
16390 case '%':
16391 return "%";
16392
2311178e 16393 case '[':
1af9f229
RS
16394 {
16395 int i;
16396 char *p;
16397
16398 if (command_loop_level > 5)
16399 return "[[[... ";
16400 p = decode_mode_spec_buf;
16401 for (i = 0; i < command_loop_level; i++)
16402 *p++ = '[';
16403 *p = 0;
16404 return decode_mode_spec_buf;
16405 }
16406
2311178e 16407 case ']':
1af9f229
RS
16408 {
16409 int i;
16410 char *p;
16411
16412 if (command_loop_level > 5)
16413 return " ...]]]";
16414 p = decode_mode_spec_buf;
16415 for (i = 0; i < command_loop_level; i++)
16416 *p++ = ']';
16417 *p = 0;
16418 return decode_mode_spec_buf;
16419 }
16420
16421 case '-':
16422 {
1af9f229 16423 register int i;
5f5c8ee5
GM
16424
16425 /* Let lots_of_dashes be a string of infinite length. */
fec8f23e
KS
16426 if (!NILP (mode_line_string_list))
16427 return "--";
5f5c8ee5
GM
16428 if (field_width <= 0
16429 || field_width > sizeof (lots_of_dashes))
1af9f229 16430 {
5f5c8ee5
GM
16431 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
16432 decode_mode_spec_buf[i] = '-';
16433 decode_mode_spec_buf[i] = '\0';
16434 return decode_mode_spec_buf;
1af9f229 16435 }
5f5c8ee5
GM
16436 else
16437 return lots_of_dashes;
1af9f229
RS
16438 }
16439
2311178e 16440 case 'b':
d39b6696 16441 obj = b->name;
a2889657
JB
16442 break;
16443
1af9f229
RS
16444 case 'c':
16445 {
2311178e 16446 int col = (int) current_column (); /* iftc */
ac90c44f 16447 w->column_number_displayed = make_number (col);
5f5c8ee5 16448 pint2str (decode_mode_spec_buf, field_width, col);
1af9f229
RS
16449 return decode_mode_spec_buf;
16450 }
16451
16452 case 'F':
16453 /* %F displays the frame name. */
5f5c8ee5 16454 if (!NILP (f->title))
2051c264 16455 return (char *) SDATA (f->title);
fd8ff63d 16456 if (f->explicit_name || ! FRAME_WINDOW_P (f))
2051c264 16457 return (char *) SDATA (f->name);
9c6da96f 16458 return "Emacs";
1af9f229 16459
2311178e 16460 case 'f':
d39b6696 16461 obj = b->filename;
a2889657
JB
16462 break;
16463
525b8b09
LK
16464 case 'i':
16465 {
16466 int size = ZV - BEGV;
16467 pint2str (decode_mode_spec_buf, field_width, size);
16468 return decode_mode_spec_buf;
16469 }
16470
16471 case 'I':
16472 {
16473 int size = ZV - BEGV;
16474 pint2hrstr (decode_mode_spec_buf, field_width, size);
16475 return decode_mode_spec_buf;
16476 }
16477
aa6d10fa
RS
16478 case 'l':
16479 {
12adba34
RS
16480 int startpos = XMARKER (w->start)->charpos;
16481 int startpos_byte = marker_byte_position (w->start);
16482 int line, linepos, linepos_byte, topline;
aa6d10fa 16483 int nlines, junk;
da8b7f4f 16484 int height = WINDOW_TOTAL_LINES (w);
aa6d10fa 16485
2311178e 16486 /* If we decided that this buffer isn't suitable for line numbers,
aa6d10fa
RS
16487 don't forget that too fast. */
16488 if (EQ (w->base_line_pos, w->buffer))
766525bc 16489 goto no_value;
5300fd39
RS
16490 /* But do forget it, if the window shows a different buffer now. */
16491 else if (BUFFERP (w->base_line_pos))
16492 w->base_line_pos = Qnil;
aa6d10fa
RS
16493
16494 /* If the buffer is very big, don't waste time. */
37d034d3 16495 if (INTEGERP (Vline_number_display_limit)
090703f4 16496 && BUF_ZV (b) - BUF_BEGV (b) > XINT (Vline_number_display_limit))
aa6d10fa
RS
16497 {
16498 w->base_line_pos = Qnil;
16499 w->base_line_number = Qnil;
766525bc 16500 goto no_value;
aa6d10fa
RS
16501 }
16502
16503 if (!NILP (w->base_line_number)
16504 && !NILP (w->base_line_pos)
12adba34 16505 && XFASTINT (w->base_line_pos) <= startpos)
aa6d10fa
RS
16506 {
16507 line = XFASTINT (w->base_line_number);
16508 linepos = XFASTINT (w->base_line_pos);
12adba34 16509 linepos_byte = buf_charpos_to_bytepos (b, linepos);
aa6d10fa
RS
16510 }
16511 else
16512 {
16513 line = 1;
d39b6696 16514 linepos = BUF_BEGV (b);
12adba34 16515 linepos_byte = BUF_BEGV_BYTE (b);
aa6d10fa
RS
16516 }
16517
16518 /* Count lines from base line to window start position. */
12adba34
RS
16519 nlines = display_count_lines (linepos, linepos_byte,
16520 startpos_byte,
16521 startpos, &junk);
aa6d10fa
RS
16522
16523 topline = nlines + line;
16524
16525 /* Determine a new base line, if the old one is too close
16526 or too far away, or if we did not have one.
16527 "Too close" means it's plausible a scroll-down would
16528 go back past it. */
d39b6696 16529 if (startpos == BUF_BEGV (b))
aa6d10fa 16530 {
ac90c44f
GM
16531 w->base_line_number = make_number (topline);
16532 w->base_line_pos = make_number (BUF_BEGV (b));
aa6d10fa
RS
16533 }
16534 else if (nlines < height + 25 || nlines > height * 3 + 50
d39b6696 16535 || linepos == BUF_BEGV (b))
aa6d10fa 16536 {
d39b6696 16537 int limit = BUF_BEGV (b);
12adba34 16538 int limit_byte = BUF_BEGV_BYTE (b);
aa6d10fa 16539 int position;
5d121aec 16540 int distance = (height * 2 + 30) * line_number_display_limit_width;
aa6d10fa
RS
16541
16542 if (startpos - distance > limit)
12adba34
RS
16543 {
16544 limit = startpos - distance;
16545 limit_byte = CHAR_TO_BYTE (limit);
16546 }
aa6d10fa 16547
12adba34
RS
16548 nlines = display_count_lines (startpos, startpos_byte,
16549 limit_byte,
16550 - (height * 2 + 30),
aa6d10fa 16551 &position);
2311178e 16552 /* If we couldn't find the lines we wanted within
5d121aec 16553 line_number_display_limit_width chars per line,
aa6d10fa 16554 give up on line numbers for this window. */
12adba34 16555 if (position == limit_byte && limit == startpos - distance)
aa6d10fa
RS
16556 {
16557 w->base_line_pos = w->buffer;
16558 w->base_line_number = Qnil;
766525bc 16559 goto no_value;
aa6d10fa
RS
16560 }
16561
ac90c44f
GM
16562 w->base_line_number = make_number (topline - nlines);
16563 w->base_line_pos = make_number (BYTE_TO_CHAR (position));
aa6d10fa
RS
16564 }
16565
16566 /* Now count lines from the start pos to point. */
12adba34
RS
16567 nlines = display_count_lines (startpos, startpos_byte,
16568 PT_BYTE, PT, &junk);
aa6d10fa
RS
16569
16570 /* Record that we did display the line number. */
16571 line_number_displayed = 1;
16572
16573 /* Make the string to show. */
5f5c8ee5 16574 pint2str (decode_mode_spec_buf, field_width, topline + nlines);
aa6d10fa 16575 return decode_mode_spec_buf;
766525bc
RS
16576 no_value:
16577 {
16578 char* p = decode_mode_spec_buf;
5f5c8ee5
GM
16579 int pad = field_width - 2;
16580 while (pad-- > 0)
16581 *p++ = ' ';
16582 *p++ = '?';
b357b9d4
KR
16583 *p++ = '?';
16584 *p = '\0';
766525bc
RS
16585 return decode_mode_spec_buf;
16586 }
aa6d10fa
RS
16587 }
16588 break;
16589
2311178e 16590 case 'm':
d39b6696 16591 obj = b->mode_name;
a2889657
JB
16592 break;
16593
16594 case 'n':
d39b6696 16595 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
a2889657
JB
16596 return " Narrow";
16597 break;
16598
a2889657
JB
16599 case 'p':
16600 {
16601 int pos = marker_position (w->start);
d39b6696 16602 int total = BUF_ZV (b) - BUF_BEGV (b);
a2889657 16603
d39b6696 16604 if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
a2889657 16605 {
d39b6696 16606 if (pos <= BUF_BEGV (b))
a2889657
JB
16607 return "All";
16608 else
16609 return "Bottom";
16610 }
d39b6696 16611 else if (pos <= BUF_BEGV (b))
a2889657
JB
16612 return "Top";
16613 else
16614 {
3c7d31b9
RS
16615 if (total > 1000000)
16616 /* Do it differently for a large value, to avoid overflow. */
16617 total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
16618 else
16619 total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
a2889657
JB
16620 /* We can't normally display a 3-digit number,
16621 so get us a 2-digit number that is close. */
16622 if (total == 100)
16623 total = 99;
16624 sprintf (decode_mode_spec_buf, "%2d%%", total);
16625 return decode_mode_spec_buf;
16626 }
16627 }
16628
8ffcb79f
RS
16629 /* Display percentage of size above the bottom of the screen. */
16630 case 'P':
16631 {
16632 int toppos = marker_position (w->start);
d39b6696
KH
16633 int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
16634 int total = BUF_ZV (b) - BUF_BEGV (b);
8ffcb79f 16635
d39b6696 16636 if (botpos >= BUF_ZV (b))
8ffcb79f 16637 {
d39b6696 16638 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
16639 return "All";
16640 else
16641 return "Bottom";
16642 }
16643 else
16644 {
3c7d31b9
RS
16645 if (total > 1000000)
16646 /* Do it differently for a large value, to avoid overflow. */
16647 total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
16648 else
16649 total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
8ffcb79f
RS
16650 /* We can't normally display a 3-digit number,
16651 so get us a 2-digit number that is close. */
16652 if (total == 100)
16653 total = 99;
d39b6696 16654 if (toppos <= BUF_BEGV (b))
8ffcb79f
RS
16655 sprintf (decode_mode_spec_buf, "Top%2d%%", total);
16656 else
16657 sprintf (decode_mode_spec_buf, "%2d%%", total);
16658 return decode_mode_spec_buf;
16659 }
16660 }
16661
1af9f229
RS
16662 case 's':
16663 /* status of process */
16664 obj = Fget_buffer_process (w->buffer);
16665 if (NILP (obj))
16666 return "no process";
16667#ifdef subprocesses
16668 obj = Fsymbol_name (Fprocess_status (obj));
16669#endif
16670 break;
d39b6696 16671
1af9f229
RS
16672 case 't': /* indicate TEXT or BINARY */
16673#ifdef MODE_LINE_BINARY_TEXT
16674 return MODE_LINE_BINARY_TEXT (b);
16675#else
16676 return "T";
16677#endif
1c9241f5
KH
16678
16679 case 'z':
16680 /* coding-system (not including end-of-line format) */
16681 case 'Z':
16682 /* coding-system (including end-of-line type) */
16683 {
16684 int eol_flag = (c == 'Z');
539b4d41 16685 char *p = decode_mode_spec_buf;
1c9241f5 16686
d30e754b 16687 if (! FRAME_WINDOW_P (f))
1c9241f5 16688 {
11c52c4f
RS
16689 /* No need to mention EOL here--the terminal never needs
16690 to do EOL conversion. */
16691 p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
16692 p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
1c9241f5 16693 }
f13c925f 16694 p = decode_mode_spec_coding (b->buffer_file_coding_system,
539b4d41 16695 p, eol_flag);
f13c925f 16696
11c52c4f 16697#if 0 /* This proves to be annoying; I think we can do without. -- rms. */
1c9241f5
KH
16698#ifdef subprocesses
16699 obj = Fget_buffer_process (Fcurrent_buffer ());
16700 if (PROCESSP (obj))
16701 {
16702 p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
16703 p, eol_flag);
16704 p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
16705 p, eol_flag);
16706 }
16707#endif /* subprocesses */
11c52c4f 16708#endif /* 0 */
1c9241f5
KH
16709 *p = 0;
16710 return decode_mode_spec_buf;
16711 }
a2889657 16712 }
d39b6696 16713
e24c997d 16714 if (STRINGP (obj))
72f62cb5
GM
16715 {
16716 *multibyte = STRING_MULTIBYTE (obj);
2051c264 16717 return (char *) SDATA (obj);
72f62cb5 16718 }
a2889657
JB
16719 else
16720 return "";
16721}
5f5c8ee5
GM
16722
16723
12adba34
RS
16724/* Count up to COUNT lines starting from START / START_BYTE.
16725 But don't go beyond LIMIT_BYTE.
16726 Return the number of lines thus found (always nonnegative).
59b49f63 16727
12adba34 16728 Set *BYTE_POS_PTR to 1 if we found COUNT lines, 0 if we hit LIMIT. */
59b49f63
RS
16729
16730static int
12adba34
RS
16731display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
16732 int start, start_byte, limit_byte, count;
16733 int *byte_pos_ptr;
59b49f63 16734{
59b49f63
RS
16735 register unsigned char *cursor;
16736 unsigned char *base;
16737
16738 register int ceiling;
16739 register unsigned char *ceiling_addr;
12adba34 16740 int orig_count = count;
59b49f63
RS
16741
16742 /* If we are not in selective display mode,
16743 check only for newlines. */
12adba34
RS
16744 int selective_display = (!NILP (current_buffer->selective_display)
16745 && !INTEGERP (current_buffer->selective_display));
59b49f63
RS
16746
16747 if (count > 0)
12adba34
RS
16748 {
16749 while (start_byte < limit_byte)
16750 {
16751 ceiling = BUFFER_CEILING_OF (start_byte);
16752 ceiling = min (limit_byte - 1, ceiling);
16753 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
16754 base = (cursor = BYTE_POS_ADDR (start_byte));
16755 while (1)
16756 {
16757 if (selective_display)
16758 while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
16759 ;
16760 else
16761 while (*cursor != '\n' && ++cursor != ceiling_addr)
16762 ;
16763
16764 if (cursor != ceiling_addr)
16765 {
16766 if (--count == 0)
16767 {
16768 start_byte += cursor - base + 1;
16769 *byte_pos_ptr = start_byte;
16770 return orig_count;
16771 }
16772 else
16773 if (++cursor == ceiling_addr)
16774 break;
16775 }
16776 else
16777 break;
16778 }
16779 start_byte += cursor - base;
16780 }
16781 }
59b49f63
RS
16782 else
16783 {
12adba34
RS
16784 while (start_byte > limit_byte)
16785 {
16786 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
16787 ceiling = max (limit_byte, ceiling);
16788 ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
16789 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
59b49f63
RS
16790 while (1)
16791 {
12adba34
RS
16792 if (selective_display)
16793 while (--cursor != ceiling_addr
16794 && *cursor != '\n' && *cursor != 015)
16795 ;
16796 else
16797 while (--cursor != ceiling_addr && *cursor != '\n')
16798 ;
16799
59b49f63
RS
16800 if (cursor != ceiling_addr)
16801 {
16802 if (++count == 0)
16803 {
12adba34
RS
16804 start_byte += cursor - base + 1;
16805 *byte_pos_ptr = start_byte;
16806 /* When scanning backwards, we should
16807 not count the newline posterior to which we stop. */
16808 return - orig_count - 1;
59b49f63
RS
16809 }
16810 }
16811 else
16812 break;
16813 }
12adba34
RS
16814 /* Here we add 1 to compensate for the last decrement
16815 of CURSOR, which took it past the valid range. */
16816 start_byte += cursor - base + 1;
59b49f63
RS
16817 }
16818 }
16819
12adba34 16820 *byte_pos_ptr = limit_byte;
aa6d10fa 16821
12adba34
RS
16822 if (count < 0)
16823 return - orig_count + count;
16824 return orig_count - count;
aa6d10fa 16825
12adba34 16826}
a2889657 16827
a2889657 16828
5f5c8ee5
GM
16829\f
16830/***********************************************************************
16831 Displaying strings
16832 ***********************************************************************/
278feba9 16833
5f5c8ee5 16834/* Display a NUL-terminated string, starting with index START.
a3788d53 16835
5f5c8ee5
GM
16836 If STRING is non-null, display that C string. Otherwise, the Lisp
16837 string LISP_STRING is displayed.
a2889657 16838
5f5c8ee5
GM
16839 If FACE_STRING is not nil, FACE_STRING_POS is a position in
16840 FACE_STRING. Display STRING or LISP_STRING with the face at
16841 FACE_STRING_POS in FACE_STRING:
a2889657 16842
5f5c8ee5
GM
16843 Display the string in the environment given by IT, but use the
16844 standard display table, temporarily.
a3788d53 16845
5f5c8ee5
GM
16846 FIELD_WIDTH is the minimum number of output glyphs to produce.
16847 If STRING has fewer characters than FIELD_WIDTH, pad to the right
16848 with spaces. If STRING has more characters, more than FIELD_WIDTH
16849 glyphs will be produced. FIELD_WIDTH <= 0 means don't pad.
2311178e 16850
5f5c8ee5
GM
16851 PRECISION is the maximum number of characters to output from
16852 STRING. PRECISION < 0 means don't truncate the string.
a2889657 16853
5f5c8ee5 16854 This is roughly equivalent to printf format specifiers:
a2889657 16855
5f5c8ee5
GM
16856 FIELD_WIDTH PRECISION PRINTF
16857 ----------------------------------------
16858 -1 -1 %s
16859 -1 10 %.10s
16860 10 -1 %10s
16861 20 10 %20.10s
a2889657 16862
5f5c8ee5
GM
16863 MULTIBYTE zero means do not display multibyte chars, > 0 means do
16864 display them, and < 0 means obey the current buffer's value of
16865 enable_multibyte_characters.
278feba9 16866
5f5c8ee5 16867 Value is the number of glyphs produced. */
b1d1124b 16868
5f5c8ee5
GM
16869static int
16870display_string (string, lisp_string, face_string, face_string_pos,
16871 start, it, field_width, precision, max_x, multibyte)
16872 unsigned char *string;
16873 Lisp_Object lisp_string;
68c45bf0
PE
16874 Lisp_Object face_string;
16875 int face_string_pos;
5f5c8ee5
GM
16876 int start;
16877 struct it *it;
16878 int field_width, precision, max_x;
16879 int multibyte;
16880{
16881 int hpos_at_start = it->hpos;
16882 int saved_face_id = it->face_id;
16883 struct glyph_row *row = it->glyph_row;
16884
16885 /* Initialize the iterator IT for iteration over STRING beginning
e719f5ae 16886 with index START. */
5f5c8ee5
GM
16887 reseat_to_string (it, string, lisp_string, start,
16888 precision, field_width, multibyte);
16889
16890 /* If displaying STRING, set up the face of the iterator
16891 from LISP_STRING, if that's given. */
16892 if (STRINGP (face_string))
16893 {
16894 int endptr;
16895 struct face *face;
2311178e 16896
5f5c8ee5
GM
16897 it->face_id
16898 = face_at_string_position (it->w, face_string, face_string_pos,
16899 0, it->region_beg_charpos,
16900 it->region_end_charpos,
5de7c6f2 16901 &endptr, it->base_face_id, 0);
5f5c8ee5
GM
16902 face = FACE_FROM_ID (it->f, it->face_id);
16903 it->face_box_p = face->box != FACE_NO_BOX;
b1d1124b 16904 }
a2889657 16905
5f5c8ee5
GM
16906 /* Set max_x to the maximum allowed X position. Don't let it go
16907 beyond the right edge of the window. */
16908 if (max_x <= 0)
16909 max_x = it->last_visible_x;
16910 else
16911 max_x = min (max_x, it->last_visible_x);
efc63ef0 16912
5f5c8ee5
GM
16913 /* Skip over display elements that are not visible. because IT->w is
16914 hscrolled. */
16915 if (it->current_x < it->first_visible_x)
16916 move_it_in_display_line_to (it, 100000, it->first_visible_x,
16917 MOVE_TO_POS | MOVE_TO_X);
a2889657 16918
5f5c8ee5
GM
16919 row->ascent = it->max_ascent;
16920 row->height = it->max_ascent + it->max_descent;
312246d1
GM
16921 row->phys_ascent = it->max_phys_ascent;
16922 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
1c9241f5 16923
5f5c8ee5
GM
16924 /* This condition is for the case that we are called with current_x
16925 past last_visible_x. */
16926 while (it->current_x < max_x)
a2889657 16927 {
5f5c8ee5 16928 int x_before, x, n_glyphs_before, i, nglyphs;
1c9241f5 16929
5f5c8ee5
GM
16930 /* Get the next display element. */
16931 if (!get_next_display_element (it))
90adcf20 16932 break;
1c9241f5 16933
5f5c8ee5
GM
16934 /* Produce glyphs. */
16935 x_before = it->current_x;
16936 n_glyphs_before = it->glyph_row->used[TEXT_AREA];
16937 PRODUCE_GLYPHS (it);
90adcf20 16938
5f5c8ee5
GM
16939 nglyphs = it->glyph_row->used[TEXT_AREA] - n_glyphs_before;
16940 i = 0;
16941 x = x_before;
16942 while (i < nglyphs)
a2889657 16943 {
5f5c8ee5 16944 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
2311178e 16945
5f5c8ee5
GM
16946 if (!it->truncate_lines_p
16947 && x + glyph->pixel_width > max_x)
16948 {
16949 /* End of continued line or max_x reached. */
37be86f2
KH
16950 if (CHAR_GLYPH_PADDING_P (*glyph))
16951 {
16952 /* A wide character is unbreakable. */
16953 it->glyph_row->used[TEXT_AREA] = n_glyphs_before;
16954 it->current_x = x_before;
16955 }
16956 else
16957 {
16958 it->glyph_row->used[TEXT_AREA] = n_glyphs_before + i;
16959 it->current_x = x;
16960 }
5f5c8ee5
GM
16961 break;
16962 }
16963 else if (x + glyph->pixel_width > it->first_visible_x)
16964 {
16965 /* Glyph is at least partially visible. */
16966 ++it->hpos;
16967 if (x < it->first_visible_x)
16968 it->glyph_row->x = x - it->first_visible_x;
16969 }
16970 else
a2889657 16971 {
5f5c8ee5
GM
16972 /* Glyph is off the left margin of the display area.
16973 Should not happen. */
16974 abort ();
a2889657 16975 }
5f5c8ee5
GM
16976
16977 row->ascent = max (row->ascent, it->max_ascent);
16978 row->height = max (row->height, it->max_ascent + it->max_descent);
312246d1
GM
16979 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
16980 row->phys_height = max (row->phys_height,
16981 it->max_phys_ascent + it->max_phys_descent);
5f5c8ee5
GM
16982 x += glyph->pixel_width;
16983 ++i;
a2889657 16984 }
5f5c8ee5
GM
16985
16986 /* Stop if max_x reached. */
16987 if (i < nglyphs)
16988 break;
16989
16990 /* Stop at line ends. */
16991 if (ITERATOR_AT_END_OF_LINE_P (it))
a2889657 16992 {
5f5c8ee5
GM
16993 it->continuation_lines_width = 0;
16994 break;
a2889657 16995 }
1c9241f5 16996
cafafe0b 16997 set_iterator_to_next (it, 1);
a688bb24 16998
5f5c8ee5
GM
16999 /* Stop if truncating at the right edge. */
17000 if (it->truncate_lines_p
17001 && it->current_x >= it->last_visible_x)
17002 {
17003 /* Add truncation mark, but don't do it if the line is
17004 truncated at a padding space. */
17005 if (IT_CHARPOS (*it) < it->string_nchars)
1c9241f5 17006 {
5f5c8ee5 17007 if (!FRAME_WINDOW_P (it->f))
37be86f2
KH
17008 {
17009 int i, n;
17010
9299cb15 17011 if (it->current_x > it->last_visible_x)
37be86f2 17012 {
9299cb15
KH
17013 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
17014 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
17015 break;
17016 for (n = row->used[TEXT_AREA]; i < n; ++i)
17017 {
17018 row->used[TEXT_AREA] = i;
17019 produce_special_glyphs (it, IT_TRUNCATION);
17020 }
37be86f2 17021 }
9299cb15 17022 produce_special_glyphs (it, IT_TRUNCATION);
37be86f2 17023 }
5f5c8ee5 17024 it->glyph_row->truncated_on_right_p = 1;
1c9241f5 17025 }
5f5c8ee5 17026 break;
1c9241f5 17027 }
a2889657
JB
17028 }
17029
5f5c8ee5
GM
17030 /* Maybe insert a truncation at the left. */
17031 if (it->first_visible_x
17032 && IT_CHARPOS (*it) > 0)
a2889657 17033 {
5f5c8ee5
GM
17034 if (!FRAME_WINDOW_P (it->f))
17035 insert_left_trunc_glyphs (it);
17036 it->glyph_row->truncated_on_left_p = 1;
a2889657
JB
17037 }
17038
5f5c8ee5 17039 it->face_id = saved_face_id;
2311178e 17040
5f5c8ee5
GM
17041 /* Value is number of columns displayed. */
17042 return it->hpos - hpos_at_start;
17043}
a2889657 17044
a2889657 17045
a2889657 17046\f
3b6b6db7 17047/* This is like a combination of memq and assq. Return 1/2 if PROPVAL
5f5c8ee5
GM
17048 appears as an element of LIST or as the car of an element of LIST.
17049 If PROPVAL is a list, compare each element against LIST in that
3b6b6db7
SM
17050 way, and return 1/2 if any element of PROPVAL is found in LIST.
17051 Otherwise return 0. This function cannot quit.
17052 The return value is 2 if the text is invisible but with an ellipsis
17053 and 1 if it's invisible and without an ellipsis. */
642eefc6
RS
17054
17055int
17056invisible_p (propval, list)
17057 register Lisp_Object propval;
17058 Lisp_Object list;
17059{
3b6b6db7 17060 register Lisp_Object tail, proptail;
2311178e 17061
3b6b6db7
SM
17062 for (tail = list; CONSP (tail); tail = XCDR (tail))
17063 {
17064 register Lisp_Object tem;
17065 tem = XCAR (tail);
17066 if (EQ (propval, tem))
17067 return 1;
17068 if (CONSP (tem) && EQ (propval, XCAR (tem)))
17069 return NILP (XCDR (tem)) ? 1 : 2;
17070 }
2311178e 17071
3b6b6db7
SM
17072 if (CONSP (propval))
17073 {
17074 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
17075 {
17076 Lisp_Object propelt;
17077 propelt = XCAR (proptail);
17078 for (tail = list; CONSP (tail); tail = XCDR (tail))
17079 {
17080 register Lisp_Object tem;
17081 tem = XCAR (tail);
17082 if (EQ (propelt, tem))
17083 return 1;
17084 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
17085 return NILP (XCDR (tem)) ? 1 : 2;
17086 }
17087 }
17088 }
2311178e 17089
3b6b6db7 17090 return 0;
642eefc6 17091}
5f5c8ee5 17092
642eefc6 17093\f
133c764e
KS
17094/***********************************************************************
17095 Glyph Display
17096 ***********************************************************************/
17097
79fa9e0f
KS
17098#ifdef HAVE_WINDOW_SYSTEM
17099
133c764e
KS
17100#if GLYPH_DEBUG
17101
17102void
17103dump_glyph_string (s)
17104 struct glyph_string *s;
17105{
17106 fprintf (stderr, "glyph string\n");
17107 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
17108 s->x, s->y, s->width, s->height);
17109 fprintf (stderr, " ybase = %d\n", s->ybase);
17110 fprintf (stderr, " hl = %d\n", s->hl);
17111 fprintf (stderr, " left overhang = %d, right = %d\n",
17112 s->left_overhang, s->right_overhang);
17113 fprintf (stderr, " nchars = %d\n", s->nchars);
17114 fprintf (stderr, " extends to end of line = %d\n",
17115 s->extends_to_end_of_line_p);
17116 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
17117 fprintf (stderr, " bg width = %d\n", s->background_width);
17118}
17119
17120#endif /* GLYPH_DEBUG */
17121
17122/* Initialize glyph string S. CHAR2B is a suitably allocated vector
17123 of XChar2b structures for S; it can't be allocated in
17124 init_glyph_string because it must be allocated via `alloca'. W
17125 is the window on which S is drawn. ROW and AREA are the glyph row
17126 and area within the row from which S is constructed. START is the
17127 index of the first glyph structure covered by S. HL is a
17128 face-override for drawing S. */
17129
17130#ifdef HAVE_NTGUI
17131#define OPTIONAL_HDC(hdc) hdc,
17132#define DECLARE_HDC(hdc) HDC hdc;
17133#define ALLOCATE_HDC(hdc, f) hdc = get_frame_dc ((f))
17134#define RELEASE_HDC(hdc, f) release_frame_dc ((f), (hdc))
17135#endif
17136
17137#ifndef OPTIONAL_HDC
17138#define OPTIONAL_HDC(hdc)
17139#define DECLARE_HDC(hdc)
17140#define ALLOCATE_HDC(hdc, f)
17141#define RELEASE_HDC(hdc, f)
17142#endif
17143
17144static void
17145init_glyph_string (s, OPTIONAL_HDC (hdc) char2b, w, row, area, start, hl)
17146 struct glyph_string *s;
17147 DECLARE_HDC (hdc)
17148 XChar2b *char2b;
17149 struct window *w;
17150 struct glyph_row *row;
17151 enum glyph_row_area area;
17152 int start;
17153 enum draw_glyphs_face hl;
17154{
17155 bzero (s, sizeof *s);
17156 s->w = w;
17157 s->f = XFRAME (w->frame);
17158#ifdef HAVE_NTGUI
17159 s->hdc = hdc;
17160#endif
17161 s->display = FRAME_X_DISPLAY (s->f);
17162 s->window = FRAME_X_WINDOW (s->f);
17163 s->char2b = char2b;
17164 s->hl = hl;
17165 s->row = row;
17166 s->area = area;
17167 s->first_glyph = row->glyphs[area] + start;
17168 s->height = row->height;
17169 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
17170
17171 /* Display the internal border below the tool-bar window. */
17172 if (s->w == XWINDOW (s->f->tool_bar_window))
17173 s->y -= FRAME_INTERNAL_BORDER_WIDTH (s->f);
17174
17175 s->ybase = s->y + row->ascent;
17176}
17177
17178
17179/* Append the list of glyph strings with head H and tail T to the list
17180 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
17181
17182static INLINE void
17183append_glyph_string_lists (head, tail, h, t)
17184 struct glyph_string **head, **tail;
17185 struct glyph_string *h, *t;
17186{
17187 if (h)
17188 {
17189 if (*head)
17190 (*tail)->next = h;
17191 else
17192 *head = h;
17193 h->prev = *tail;
17194 *tail = t;
17195 }
17196}
17197
17198
17199/* Prepend the list of glyph strings with head H and tail T to the
17200 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
17201 result. */
17202
17203static INLINE void
17204prepend_glyph_string_lists (head, tail, h, t)
17205 struct glyph_string **head, **tail;
17206 struct glyph_string *h, *t;
17207{
17208 if (h)
17209 {
17210 if (*head)
17211 (*head)->prev = t;
17212 else
17213 *tail = t;
17214 t->next = *head;
17215 *head = h;
17216 }
17217}
17218
17219
17220/* Append glyph string S to the list with head *HEAD and tail *TAIL.
17221 Set *HEAD and *TAIL to the resulting list. */
17222
17223static INLINE void
17224append_glyph_string (head, tail, s)
17225 struct glyph_string **head, **tail;
17226 struct glyph_string *s;
17227{
17228 s->next = s->prev = NULL;
17229 append_glyph_string_lists (head, tail, s, s);
17230}
17231
17232
17233/* Get face and two-byte form of character glyph GLYPH on frame F.
17234 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
17235 a pointer to a realized face that is ready for display. */
17236
17237static INLINE struct face *
17238get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
17239 struct frame *f;
17240 struct glyph *glyph;
17241 XChar2b *char2b;
17242 int *two_byte_p;
17243{
17244 struct face *face;
17245
17246 xassert (glyph->type == CHAR_GLYPH);
17247 face = FACE_FROM_ID (f, glyph->face_id);
17248
17249 if (two_byte_p)
17250 *two_byte_p = 0;
17251
17252 if (!glyph->multibyte_p)
17253 {
17254 /* Unibyte case. We don't have to encode, but we have to make
17255 sure to use a face suitable for unibyte. */
17256 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
17257 }
17258 else if (glyph->u.ch < 128
17259 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
17260 {
17261 /* Case of ASCII in a face known to fit ASCII. */
17262 STORE_XCHAR2B (char2b, 0, glyph->u.ch);
17263 }
17264 else
17265 {
17266 int c1, c2, charset;
17267
17268 /* Split characters into bytes. If c2 is -1 afterwards, C is
17269 really a one-byte character so that byte1 is zero. */
17270 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
17271 if (c2 > 0)
17272 STORE_XCHAR2B (char2b, c1, c2);
17273 else
17274 STORE_XCHAR2B (char2b, 0, c1);
17275
17276 /* Maybe encode the character in *CHAR2B. */
17277 if (charset != CHARSET_ASCII)
17278 {
17279 struct font_info *font_info
17280 = FONT_INFO_FROM_ID (f, face->font_info_id);
17281 if (font_info)
17282 glyph->font_type
17283 = rif->encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
17284 }
17285 }
17286
17287 /* Make sure X resources of the face are allocated. */
17288 xassert (face != NULL);
17289 PREPARE_FACE_FOR_DISPLAY (f, face);
17290 return face;
17291}
17292
17293
17294/* Fill glyph string S with composition components specified by S->cmp.
17295
17296 FACES is an array of faces for all components of this composition.
17297 S->gidx is the index of the first component for S.
17298 OVERLAPS_P non-zero means S should draw the foreground only, and
17299 use its physical height for clipping.
17300
17301 Value is the index of a component not in S. */
17302
17303static int
17304fill_composite_glyph_string (s, faces, overlaps_p)
17305 struct glyph_string *s;
17306 struct face **faces;
17307 int overlaps_p;
17308{
17309 int i;
17310
17311 xassert (s);
17312
17313 s->for_overlaps_p = overlaps_p;
17314
17315 s->face = faces[s->gidx];
17316 s->font = s->face->font;
17317 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17318
17319 /* For all glyphs of this composition, starting at the offset
17320 S->gidx, until we reach the end of the definition or encounter a
17321 glyph that requires the different face, add it to S. */
17322 ++s->nchars;
17323 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
17324 ++s->nchars;
17325
17326 /* All glyph strings for the same composition has the same width,
17327 i.e. the width set for the first component of the composition. */
17328
17329 s->width = s->first_glyph->pixel_width;
17330
17331 /* If the specified font could not be loaded, use the frame's
17332 default font, but record the fact that we couldn't load it in
17333 the glyph string so that we can draw rectangles for the
17334 characters of the glyph string. */
17335 if (s->font == NULL)
17336 {
17337 s->font_not_found_p = 1;
17338 s->font = FRAME_FONT (s->f);
17339 }
17340
17341 /* Adjust base line for subscript/superscript text. */
17342 s->ybase += s->first_glyph->voffset;
17343
17344 xassert (s->face && s->face->gc);
17345
17346 /* This glyph string must always be drawn with 16-bit functions. */
17347 s->two_byte_p = 1;
17348
17349 return s->gidx + s->nchars;
17350}
17351
17352
17353/* Fill glyph string S from a sequence of character glyphs.
17354
17355 FACE_ID is the face id of the string. START is the index of the
17356 first glyph to consider, END is the index of the last + 1.
17357 OVERLAPS_P non-zero means S should draw the foreground only, and
17358 use its physical height for clipping.
17359
17360 Value is the index of the first glyph not in S. */
17361
17362static int
17363fill_glyph_string (s, face_id, start, end, overlaps_p)
17364 struct glyph_string *s;
17365 int face_id;
17366 int start, end, overlaps_p;
17367{
17368 struct glyph *glyph, *last;
17369 int voffset;
17370 int glyph_not_available_p;
17371
17372 xassert (s->f == XFRAME (s->w->frame));
17373 xassert (s->nchars == 0);
17374 xassert (start >= 0 && end > start);
17375
17376 s->for_overlaps_p = overlaps_p,
17377 glyph = s->row->glyphs[s->area] + start;
17378 last = s->row->glyphs[s->area] + end;
17379 voffset = glyph->voffset;
17380
17381 glyph_not_available_p = glyph->glyph_not_available_p;
17382
17383 while (glyph < last
17384 && glyph->type == CHAR_GLYPH
17385 && glyph->voffset == voffset
17386 /* Same face id implies same font, nowadays. */
17387 && glyph->face_id == face_id
17388 && glyph->glyph_not_available_p == glyph_not_available_p)
17389 {
17390 int two_byte_p;
17391
17392 s->face = get_glyph_face_and_encoding (s->f, glyph,
17393 s->char2b + s->nchars,
17394 &two_byte_p);
17395 s->two_byte_p = two_byte_p;
17396 ++s->nchars;
17397 xassert (s->nchars <= end - start);
17398 s->width += glyph->pixel_width;
17399 ++glyph;
17400 }
17401
17402 s->font = s->face->font;
17403 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17404
17405 /* If the specified font could not be loaded, use the frame's font,
17406 but record the fact that we couldn't load it in
17407 S->font_not_found_p so that we can draw rectangles for the
17408 characters of the glyph string. */
17409 if (s->font == NULL || glyph_not_available_p)
17410 {
17411 s->font_not_found_p = 1;
17412 s->font = FRAME_FONT (s->f);
17413 }
17414
17415 /* Adjust base line for subscript/superscript text. */
17416 s->ybase += voffset;
17417
17418 xassert (s->face && s->face->gc);
17419 return glyph - s->row->glyphs[s->area];
17420}
17421
17422
17423/* Fill glyph string S from image glyph S->first_glyph. */
17424
17425static void
17426fill_image_glyph_string (s)
17427 struct glyph_string *s;
17428{
17429 xassert (s->first_glyph->type == IMAGE_GLYPH);
17430 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
17431 xassert (s->img);
17432 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
17433 s->font = s->face->font;
17434 s->width = s->first_glyph->pixel_width;
17435
17436 /* Adjust base line for subscript/superscript text. */
17437 s->ybase += s->first_glyph->voffset;
17438}
17439
17440
17441/* Fill glyph string S from a sequence of stretch glyphs.
17442
17443 ROW is the glyph row in which the glyphs are found, AREA is the
17444 area within the row. START is the index of the first glyph to
17445 consider, END is the index of the last + 1.
17446
17447 Value is the index of the first glyph not in S. */
17448
17449static int
17450fill_stretch_glyph_string (s, row, area, start, end)
17451 struct glyph_string *s;
17452 struct glyph_row *row;
17453 enum glyph_row_area area;
17454 int start, end;
17455{
17456 struct glyph *glyph, *last;
17457 int voffset, face_id;
17458
17459 xassert (s->first_glyph->type == STRETCH_GLYPH);
17460
17461 glyph = s->row->glyphs[s->area] + start;
17462 last = s->row->glyphs[s->area] + end;
17463 face_id = glyph->face_id;
17464 s->face = FACE_FROM_ID (s->f, face_id);
17465 s->font = s->face->font;
17466 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
17467 s->width = glyph->pixel_width;
17468 voffset = glyph->voffset;
17469
17470 for (++glyph;
17471 (glyph < last
17472 && glyph->type == STRETCH_GLYPH
17473 && glyph->voffset == voffset
17474 && glyph->face_id == face_id);
17475 ++glyph)
17476 s->width += glyph->pixel_width;
17477
17478 /* Adjust base line for subscript/superscript text. */
17479 s->ybase += voffset;
17480
17481 /* The case that face->gc == 0 is handled when drawing the glyph
17482 string by calling PREPARE_FACE_FOR_DISPLAY. */
17483 xassert (s->face);
17484 return glyph - s->row->glyphs[s->area];
17485}
17486
17487
17488/* EXPORT for RIF:
17489 Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
17490 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
17491 assumed to be zero. */
17492
17493void
17494x_get_glyph_overhangs (glyph, f, left, right)
17495 struct glyph *glyph;
17496 struct frame *f;
17497 int *left, *right;
17498{
17499 *left = *right = 0;
17500
17501 if (glyph->type == CHAR_GLYPH)
17502 {
17503 XFontStruct *font;
17504 struct face *face;
17505 struct font_info *font_info;
17506 XChar2b char2b;
17507 XCharStruct *pcm;
17508
17509 face = get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
17510 font = face->font;
17511 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
17512 if (font /* ++KFS: Should this be font_info ? */
17513 && (pcm = rif->per_char_metric (font, &char2b, glyph->font_type)))
17514 {
17515 if (pcm->rbearing > pcm->width)
17516 *right = pcm->rbearing - pcm->width;
17517 if (pcm->lbearing < 0)
17518 *left = -pcm->lbearing;
17519 }
17520 }
17521}
17522
17523
17524/* Return the index of the first glyph preceding glyph string S that
17525 is overwritten by S because of S's left overhang. Value is -1
17526 if no glyphs are overwritten. */
17527
17528static int
17529left_overwritten (s)
17530 struct glyph_string *s;
17531{
17532 int k;
17533
17534 if (s->left_overhang)
17535 {
17536 int x = 0, i;
17537 struct glyph *glyphs = s->row->glyphs[s->area];
17538 int first = s->first_glyph - glyphs;
17539
17540 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
17541 x -= glyphs[i].pixel_width;
17542
17543 k = i + 1;
17544 }
17545 else
17546 k = -1;
17547
17548 return k;
17549}
17550
17551
17552/* Return the index of the first glyph preceding glyph string S that
17553 is overwriting S because of its right overhang. Value is -1 if no
17554 glyph in front of S overwrites S. */
17555
17556static int
17557left_overwriting (s)
17558 struct glyph_string *s;
17559{
17560 int i, k, x;
17561 struct glyph *glyphs = s->row->glyphs[s->area];
17562 int first = s->first_glyph - glyphs;
17563
17564 k = -1;
17565 x = 0;
17566 for (i = first - 1; i >= 0; --i)
17567 {
17568 int left, right;
17569 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
17570 if (x + right > 0)
17571 k = i;
17572 x -= glyphs[i].pixel_width;
17573 }
17574
17575 return k;
17576}
17577
17578
17579/* Return the index of the last glyph following glyph string S that is
17580 not overwritten by S because of S's right overhang. Value is -1 if
17581 no such glyph is found. */
17582
17583static int
17584right_overwritten (s)
17585 struct glyph_string *s;
17586{
17587 int k = -1;
17588
17589 if (s->right_overhang)
17590 {
17591 int x = 0, i;
17592 struct glyph *glyphs = s->row->glyphs[s->area];
17593 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
17594 int end = s->row->used[s->area];
17595
17596 for (i = first; i < end && s->right_overhang > x; ++i)
17597 x += glyphs[i].pixel_width;
17598
17599 k = i;
17600 }
17601
17602 return k;
17603}
17604
17605
17606/* Return the index of the last glyph following glyph string S that
17607 overwrites S because of its left overhang. Value is negative
17608 if no such glyph is found. */
17609
17610static int
17611right_overwriting (s)
17612 struct glyph_string *s;
17613{
17614 int i, k, x;
17615 int end = s->row->used[s->area];
17616 struct glyph *glyphs = s->row->glyphs[s->area];
17617 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
17618
17619 k = -1;
17620 x = 0;
17621 for (i = first; i < end; ++i)
17622 {
17623 int left, right;
17624 x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
17625 if (x - left < 0)
17626 k = i;
17627 x += glyphs[i].pixel_width;
17628 }
17629
17630 return k;
17631}
17632
17633
17634/* Get face and two-byte form of character C in face FACE_ID on frame
17635 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
17636 means we want to display multibyte text. DISPLAY_P non-zero means
17637 make sure that X resources for the face returned are allocated.
17638 Value is a pointer to a realized face that is ready for display if
17639 DISPLAY_P is non-zero. */
17640
17641static INLINE struct face *
17642get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p, display_p)
17643 struct frame *f;
17644 int c, face_id;
17645 XChar2b *char2b;
17646 int multibyte_p, display_p;
17647{
17648 struct face *face = FACE_FROM_ID (f, face_id);
17649
17650 if (!multibyte_p)
17651 {
17652 /* Unibyte case. We don't have to encode, but we have to make
17653 sure to use a face suitable for unibyte. */
17654 STORE_XCHAR2B (char2b, 0, c);
17655 face_id = FACE_FOR_CHAR (f, face, c);
17656 face = FACE_FROM_ID (f, face_id);
17657 }
17658 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
17659 {
17660 /* Case of ASCII in a face known to fit ASCII. */
17661 STORE_XCHAR2B (char2b, 0, c);
17662 }
17663 else
17664 {
17665 int c1, c2, charset;
17666
17667 /* Split characters into bytes. If c2 is -1 afterwards, C is
17668 really a one-byte character so that byte1 is zero. */
17669 SPLIT_CHAR (c, charset, c1, c2);
17670 if (c2 > 0)
17671 STORE_XCHAR2B (char2b, c1, c2);
17672 else
17673 STORE_XCHAR2B (char2b, 0, c1);
17674
17675 /* Maybe encode the character in *CHAR2B. */
17676 if (face->font != NULL)
17677 {
17678 struct font_info *font_info
17679 = FONT_INFO_FROM_ID (f, face->font_info_id);
17680 if (font_info)
17681 rif->encode_char (c, char2b, font_info, 0);
17682 }
17683 }
17684
17685 /* Make sure X resources of the face are allocated. */
17686#ifdef HAVE_X_WINDOWS
17687 if (display_p)
17688#endif
17689 {
17690 xassert (face != NULL);
17691 PREPARE_FACE_FOR_DISPLAY (f, face);
17692 }
17693
17694 return face;
17695}
17696
17697
17698/* Set background width of glyph string S. START is the index of the
17699 first glyph following S. LAST_X is the right-most x-position + 1
17700 in the drawing area. */
17701
17702static INLINE void
17703set_glyph_string_background_width (s, start, last_x)
17704 struct glyph_string *s;
17705 int start;
17706 int last_x;
17707{
17708 /* If the face of this glyph string has to be drawn to the end of
17709 the drawing area, set S->extends_to_end_of_line_p. */
17710 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
17711
17712 if (start == s->row->used[s->area]
17713 && s->area == TEXT_AREA
17714 && ((s->hl == DRAW_NORMAL_TEXT
17715 && (s->row->fill_line_p
17716 || s->face->background != default_face->background
17717 || s->face->stipple != default_face->stipple
17718 || s->row->mouse_face_p))
17719 || s->hl == DRAW_MOUSE_FACE
17720 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
17721 && s->row->fill_line_p)))
17722 s->extends_to_end_of_line_p = 1;
17723
17724 /* If S extends its face to the end of the line, set its
17725 background_width to the distance to the right edge of the drawing
17726 area. */
17727 if (s->extends_to_end_of_line_p)
17728 s->background_width = last_x - s->x + 1;
17729 else
17730 s->background_width = s->width;
17731}
17732
17733
17734/* Compute overhangs and x-positions for glyph string S and its
17735 predecessors, or successors. X is the starting x-position for S.
17736 BACKWARD_P non-zero means process predecessors. */
17737
17738static void
17739compute_overhangs_and_x (s, x, backward_p)
17740 struct glyph_string *s;
17741 int x;
17742 int backward_p;
17743{
17744 if (backward_p)
17745 {
17746 while (s)
17747 {
17748 if (rif->compute_glyph_string_overhangs)
17749 rif->compute_glyph_string_overhangs (s);
17750 x -= s->width;
17751 s->x = x;
17752 s = s->prev;
17753 }
17754 }
17755 else
17756 {
17757 while (s)
17758 {
17759 if (rif->compute_glyph_string_overhangs)
17760 rif->compute_glyph_string_overhangs (s);
17761 s->x = x;
17762 x += s->width;
17763 s = s->next;
17764 }
17765 }
17766}
17767
17768
17769
fa3c6b4d 17770/* The following macros are only called from draw_glyphs below.
133c764e
KS
17771 They reference the following parameters of that function directly:
17772 `w', `row', `area', and `overlap_p'
17773 as well as the following local variables:
17774 `s', `f', and `hdc' (in W32) */
17775
17776#ifdef HAVE_NTGUI
17777/* On W32, silently add local `hdc' variable to argument list of
17778 init_glyph_string. */
17779#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17780 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
17781#else
17782#define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
17783 init_glyph_string (s, char2b, w, row, area, start, hl)
17784#endif
17785
17786/* Add a glyph string for a stretch glyph to the list of strings
17787 between HEAD and TAIL. START is the index of the stretch glyph in
17788 row area AREA of glyph row ROW. END is the index of the last glyph
17789 in that glyph row area. X is the current output position assigned
17790 to the new glyph string constructed. HL overrides that face of the
17791 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17792 is the right-most x-position of the drawing area. */
17793
17794/* SunOS 4 bundled cc, barfed on continuations in the arg lists here
17795 and below -- keep them on one line. */
17796#define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17797 do \
17798 { \
17799 s = (struct glyph_string *) alloca (sizeof *s); \
17800 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17801 START = fill_stretch_glyph_string (s, row, area, START, END); \
17802 append_glyph_string (&HEAD, &TAIL, s); \
17803 s->x = (X); \
17804 } \
17805 while (0)
17806
17807
17808/* Add a glyph string for an image glyph to the list of strings
17809 between HEAD and TAIL. START is the index of the image glyph in
17810 row area AREA of glyph row ROW. END is the index of the last glyph
17811 in that glyph row area. X is the current output position assigned
17812 to the new glyph string constructed. HL overrides that face of the
17813 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
17814 is the right-most x-position of the drawing area. */
17815
17816#define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17817 do \
17818 { \
17819 s = (struct glyph_string *) alloca (sizeof *s); \
17820 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
17821 fill_image_glyph_string (s); \
17822 append_glyph_string (&HEAD, &TAIL, s); \
17823 ++START; \
17824 s->x = (X); \
17825 } \
17826 while (0)
17827
17828
17829/* Add a glyph string for a sequence of character glyphs to the list
17830 of strings between HEAD and TAIL. START is the index of the first
17831 glyph in row area AREA of glyph row ROW that is part of the new
17832 glyph string. END is the index of the last glyph in that glyph row
17833 area. X is the current output position assigned to the new glyph
17834 string constructed. HL overrides that face of the glyph; e.g. it
17835 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
17836 right-most x-position of the drawing area. */
17837
17838#define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17839 do \
17840 { \
17841 int c, face_id; \
17842 XChar2b *char2b; \
17843 \
17844 c = (row)->glyphs[area][START].u.ch; \
17845 face_id = (row)->glyphs[area][START].face_id; \
17846 \
17847 s = (struct glyph_string *) alloca (sizeof *s); \
17848 char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
17849 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
17850 append_glyph_string (&HEAD, &TAIL, s); \
17851 s->x = (X); \
17852 START = fill_glyph_string (s, face_id, START, END, overlaps_p); \
17853 } \
17854 while (0)
17855
17856
17857/* Add a glyph string for a composite sequence to the list of strings
17858 between HEAD and TAIL. START is the index of the first glyph in
17859 row area AREA of glyph row ROW that is part of the new glyph
17860 string. END is the index of the last glyph in that glyph row area.
17861 X is the current output position assigned to the new glyph string
17862 constructed. HL overrides that face of the glyph; e.g. it is
17863 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
17864 x-position of the drawing area. */
17865
17866#define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
17867 do { \
17868 int cmp_id = (row)->glyphs[area][START].u.cmp_id; \
17869 int face_id = (row)->glyphs[area][START].face_id; \
17870 struct face *base_face = FACE_FROM_ID (f, face_id); \
17871 struct composition *cmp = composition_table[cmp_id]; \
17872 int glyph_len = cmp->glyph_len; \
17873 XChar2b *char2b; \
17874 struct face **faces; \
17875 struct glyph_string *first_s = NULL; \
17876 int n; \
17877 \
17878 base_face = base_face->ascii_face; \
17879 char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
17880 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
17881 /* At first, fill in `char2b' and `faces'. */ \
17882 for (n = 0; n < glyph_len; n++) \
17883 { \
17884 int c = COMPOSITION_GLYPH (cmp, n); \
17885 int this_face_id = FACE_FOR_CHAR (f, base_face, c); \
17886 faces[n] = FACE_FROM_ID (f, this_face_id); \
17887 get_char_face_and_encoding (f, c, this_face_id, \
17888 char2b + n, 1, 1); \
17889 } \
17890 \
17891 /* Make glyph_strings for each glyph sequence that is drawable by \
17892 the same face, and append them to HEAD/TAIL. */ \
17893 for (n = 0; n < cmp->glyph_len;) \
17894 { \
17895 s = (struct glyph_string *) alloca (sizeof *s); \
17896 INIT_GLYPH_STRING (s, char2b + n, w, row, area, START, HL); \
17897 append_glyph_string (&(HEAD), &(TAIL), s); \
17898 s->cmp = cmp; \
17899 s->gidx = n; \
17900 s->x = (X); \
17901 \
17902 if (n == 0) \
17903 first_s = s; \
17904 \
17905 n = fill_composite_glyph_string (s, faces, overlaps_p); \
17906 } \
17907 \
17908 ++START; \
17909 s = first_s; \
17910 } while (0)
17911
17912
17913/* Build a list of glyph strings between HEAD and TAIL for the glyphs
17914 of AREA of glyph row ROW on window W between indices START and END.
17915 HL overrides the face for drawing glyph strings, e.g. it is
17916 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
17917 x-positions of the drawing area.
17918
17919 This is an ugly monster macro construct because we must use alloca
fa3c6b4d 17920 to allocate glyph strings (because draw_glyphs can be called
133c764e
KS
17921 asynchronously). */
17922
17923#define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
17924 do \
17925 { \
17926 HEAD = TAIL = NULL; \
17927 while (START < END) \
17928 { \
17929 struct glyph *first_glyph = (row)->glyphs[area] + START; \
17930 switch (first_glyph->type) \
17931 { \
17932 case CHAR_GLYPH: \
17933 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
17934 HL, X, LAST_X); \
17935 break; \
17936 \
17937 case COMPOSITE_GLYPH: \
17938 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
17939 HL, X, LAST_X); \
17940 break; \
17941 \
17942 case STRETCH_GLYPH: \
17943 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
17944 HL, X, LAST_X); \
17945 break; \
17946 \
17947 case IMAGE_GLYPH: \
17948 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
17949 HL, X, LAST_X); \
17950 break; \
17951 \
17952 default: \
17953 abort (); \
17954 } \
17955 \
17956 set_glyph_string_background_width (s, START, LAST_X); \
17957 (X) += s->width; \
17958 } \
17959 } \
17960 while (0)
17961
17962
17963/* Draw glyphs between START and END in AREA of ROW on window W,
17964 starting at x-position X. X is relative to AREA in W. HL is a
17965 face-override with the following meaning:
17966
17967 DRAW_NORMAL_TEXT draw normally
17968 DRAW_CURSOR draw in cursor face
17969 DRAW_MOUSE_FACE draw in mouse face.
17970 DRAW_INVERSE_VIDEO draw in mode line face
17971 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
17972 DRAW_IMAGE_RAISED draw an image with a raised relief around it
17973
17974 If OVERLAPS_P is non-zero, draw only the foreground of characters
17975 and clip to the physical height of ROW.
17976
17977 Value is the x-position reached, relative to AREA of W. */
17978
fa3c6b4d
KS
17979static int
17980draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
133c764e
KS
17981 struct window *w;
17982 int x;
17983 struct glyph_row *row;
17984 enum glyph_row_area area;
17985 int start, end;
17986 enum draw_glyphs_face hl;
17987 int overlaps_p;
17988{
17989 struct glyph_string *head, *tail;
17990 struct glyph_string *s;
17991 int last_x, area_width;
17992 int x_reached;
17993 int i, j;
17994 struct frame *f = XFRAME (WINDOW_FRAME (w));
17995 DECLARE_HDC (hdc);
17996
17997 ALLOCATE_HDC (hdc, f);
17998
17999 /* Let's rather be paranoid than getting a SEGV. */
18000 end = min (end, row->used[area]);
18001 start = max (0, start);
18002 start = min (end, start);
18003
18004 /* Translate X to frame coordinates. Set last_x to the right
18005 end of the drawing area. */
18006 if (row->full_width_p)
18007 {
18008 /* X is relative to the left edge of W, without scroll bars
18009 or fringes. */
da8b7f4f
KS
18010 x += WINDOW_LEFT_EDGE_X (w);
18011 last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
133c764e
KS
18012 }
18013 else
18014 {
da8b7f4f
KS
18015 int area_left = window_box_left (w, area);
18016 x += area_left;
133c764e 18017 area_width = window_box_width (w, area);
da8b7f4f 18018 last_x = area_left + area_width;
133c764e
KS
18019 }
18020
18021 /* Build a doubly-linked list of glyph_string structures between
18022 head and tail from what we have to draw. Note that the macro
18023 BUILD_GLYPH_STRINGS will modify its start parameter. That's
18024 the reason we use a separate variable `i'. */
18025 i = start;
18026 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
18027 if (tail)
18028 x_reached = tail->x + tail->background_width;
18029 else
18030 x_reached = x;
18031
18032 /* If there are any glyphs with lbearing < 0 or rbearing > width in
18033 the row, redraw some glyphs in front or following the glyph
18034 strings built above. */
18035 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
18036 {
18037 int dummy_x = 0;
18038 struct glyph_string *h, *t;
18039
18040 /* Compute overhangs for all glyph strings. */
18041 if (rif->compute_glyph_string_overhangs)
18042 for (s = head; s; s = s->next)
18043 rif->compute_glyph_string_overhangs (s);
18044
18045 /* Prepend glyph strings for glyphs in front of the first glyph
18046 string that are overwritten because of the first glyph
18047 string's left overhang. The background of all strings
18048 prepended must be drawn because the first glyph string
18049 draws over it. */
18050 i = left_overwritten (head);
18051 if (i >= 0)
18052 {
18053 j = i;
18054 BUILD_GLYPH_STRINGS (j, start, h, t,
18055 DRAW_NORMAL_TEXT, dummy_x, last_x);
18056 start = i;
18057 compute_overhangs_and_x (t, head->x, 1);
18058 prepend_glyph_string_lists (&head, &tail, h, t);
18059 }
18060
18061 /* Prepend glyph strings for glyphs in front of the first glyph
18062 string that overwrite that glyph string because of their
18063 right overhang. For these strings, only the foreground must
18064 be drawn, because it draws over the glyph string at `head'.
18065 The background must not be drawn because this would overwrite
18066 right overhangs of preceding glyphs for which no glyph
18067 strings exist. */
18068 i = left_overwriting (head);
18069 if (i >= 0)
18070 {
18071 BUILD_GLYPH_STRINGS (i, start, h, t,
18072 DRAW_NORMAL_TEXT, dummy_x, last_x);
18073 for (s = h; s; s = s->next)
18074 s->background_filled_p = 1;
18075 compute_overhangs_and_x (t, head->x, 1);
18076 prepend_glyph_string_lists (&head, &tail, h, t);
18077 }
18078
18079 /* Append glyphs strings for glyphs following the last glyph
18080 string tail that are overwritten by tail. The background of
18081 these strings has to be drawn because tail's foreground draws
18082 over it. */
18083 i = right_overwritten (tail);
18084 if (i >= 0)
18085 {
18086 BUILD_GLYPH_STRINGS (end, i, h, t,
18087 DRAW_NORMAL_TEXT, x, last_x);
18088 compute_overhangs_and_x (h, tail->x + tail->width, 0);
18089 append_glyph_string_lists (&head, &tail, h, t);
18090 }
18091
18092 /* Append glyph strings for glyphs following the last glyph
18093 string tail that overwrite tail. The foreground of such
18094 glyphs has to be drawn because it writes into the background
18095 of tail. The background must not be drawn because it could
18096 paint over the foreground of following glyphs. */
18097 i = right_overwriting (tail);
18098 if (i >= 0)
18099 {
18100 BUILD_GLYPH_STRINGS (end, i, h, t,
18101 DRAW_NORMAL_TEXT, x, last_x);
18102 for (s = h; s; s = s->next)
18103 s->background_filled_p = 1;
18104 compute_overhangs_and_x (h, tail->x + tail->width, 0);
18105 append_glyph_string_lists (&head, &tail, h, t);
18106 }
18107 }
18108
18109 /* Draw all strings. */
18110 for (s = head; s; s = s->next)
18111 rif->draw_glyph_string (s);
18112
18113 if (area == TEXT_AREA
18114 && !row->full_width_p
18115 /* When drawing overlapping rows, only the glyph strings'
18116 foreground is drawn, which doesn't erase a cursor
18117 completely. */
18118 && !overlaps_p)
18119 {
18120 int x0 = head ? head->x : x;
18121 int x1 = tail ? tail->x + tail->background_width : x;
18122
da8b7f4f
KS
18123 int text_left = window_box_left (w, TEXT_AREA);
18124 x0 -= text_left;
18125 x1 -= text_left;
133c764e 18126
da8b7f4f 18127 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
133c764e
KS
18128 row->y, MATRIX_ROW_BOTTOM_Y (row));
18129 }
18130
18131 /* Value is the x-position up to which drawn, relative to AREA of W.
18132 This doesn't include parts drawn because of overhangs. */
da8b7f4f
KS
18133 if (row->full_width_p)
18134 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
18135 else
18136 x_reached -= window_box_left (w, area);
133c764e
KS
18137
18138 RELEASE_HDC (hdc, f);
18139
18140 return x_reached;
18141}
18142
18143
18144/* Store one glyph for IT->char_to_display in IT->glyph_row.
18145 Called from x_produce_glyphs when IT->glyph_row is non-null. */
18146
18147static INLINE void
18148append_glyph (it)
18149 struct it *it;
18150{
18151 struct glyph *glyph;
18152 enum glyph_row_area area = it->area;
18153
18154 xassert (it->glyph_row);
18155 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
18156
18157 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18158 if (glyph < it->glyph_row->glyphs[area + 1])
18159 {
18160 glyph->charpos = CHARPOS (it->position);
18161 glyph->object = it->object;
18162 glyph->pixel_width = it->pixel_width;
493fdc3c
KS
18163 glyph->ascent = it->ascent;
18164 glyph->descent = it->descent;
133c764e
KS
18165 glyph->voffset = it->voffset;
18166 glyph->type = CHAR_GLYPH;
18167 glyph->multibyte_p = it->multibyte_p;
18168 glyph->left_box_line_p = it->start_of_box_run_p;
18169 glyph->right_box_line_p = it->end_of_box_run_p;
18170 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
18171 || it->phys_descent > it->descent);
18172 glyph->padding_p = 0;
18173 glyph->glyph_not_available_p = it->glyph_not_available_p;
18174 glyph->face_id = it->face_id;
18175 glyph->u.ch = it->char_to_display;
18176 glyph->font_type = FONT_TYPE_UNKNOWN;
18177 ++it->glyph_row->used[area];
18178 }
18179}
18180
18181/* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
18182 Called from x_produce_glyphs when IT->glyph_row is non-null. */
18183
18184static INLINE void
18185append_composite_glyph (it)
18186 struct it *it;
18187{
18188 struct glyph *glyph;
18189 enum glyph_row_area area = it->area;
18190
18191 xassert (it->glyph_row);
18192
18193 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18194 if (glyph < it->glyph_row->glyphs[area + 1])
18195 {
18196 glyph->charpos = CHARPOS (it->position);
18197 glyph->object = it->object;
18198 glyph->pixel_width = it->pixel_width;
493fdc3c
KS
18199 glyph->ascent = it->ascent;
18200 glyph->descent = it->descent;
133c764e
KS
18201 glyph->voffset = it->voffset;
18202 glyph->type = COMPOSITE_GLYPH;
18203 glyph->multibyte_p = it->multibyte_p;
18204 glyph->left_box_line_p = it->start_of_box_run_p;
18205 glyph->right_box_line_p = it->end_of_box_run_p;
18206 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
18207 || it->phys_descent > it->descent);
18208 glyph->padding_p = 0;
18209 glyph->glyph_not_available_p = 0;
18210 glyph->face_id = it->face_id;
18211 glyph->u.cmp_id = it->cmp_id;
18212 glyph->font_type = FONT_TYPE_UNKNOWN;
18213 ++it->glyph_row->used[area];
18214 }
18215}
18216
18217
18218/* Change IT->ascent and IT->height according to the setting of
18219 IT->voffset. */
18220
18221static INLINE void
18222take_vertical_position_into_account (it)
18223 struct it *it;
18224{
18225 if (it->voffset)
18226 {
18227 if (it->voffset < 0)
18228 /* Increase the ascent so that we can display the text higher
18229 in the line. */
18230 it->ascent += abs (it->voffset);
18231 else
18232 /* Increase the descent so that we can display the text lower
18233 in the line. */
18234 it->descent += it->voffset;
18235 }
18236}
18237
18238
18239/* Produce glyphs/get display metrics for the image IT is loaded with.
18240 See the description of struct display_iterator in dispextern.h for
18241 an overview of struct display_iterator. */
18242
18243static void
18244produce_image_glyph (it)
18245 struct it *it;
18246{
18247 struct image *img;
18248 struct face *face;
493fdc3c 18249 int face_ascent, glyph_ascent;
133c764e
KS
18250
18251 xassert (it->what == IT_IMAGE);
18252
18253 face = FACE_FROM_ID (it->f, it->face_id);
18254 img = IMAGE_FROM_ID (it->f, it->image_id);
18255 xassert (img);
18256
18257 /* Make sure X resources of the face and image are loaded. */
18258 PREPARE_FACE_FOR_DISPLAY (it->f, face);
18259 prepare_image_for_display (it->f, img);
18260
493fdc3c 18261 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face);
133c764e
KS
18262 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
18263 it->pixel_width = img->width + 2 * img->hmargin;
18264
493fdc3c
KS
18265 /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */
18266 face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f);
18267 if (face_ascent > it->ascent)
18268 it->ascent = it->phys_ascent = face_ascent;
18269
133c764e
KS
18270 it->nglyphs = 1;
18271
18272 if (face->box != FACE_NO_BOX)
18273 {
18274 if (face->box_line_width > 0)
18275 {
18276 it->ascent += face->box_line_width;
18277 it->descent += face->box_line_width;
18278 }
18279
18280 if (it->start_of_box_run_p)
18281 it->pixel_width += abs (face->box_line_width);
18282 if (it->end_of_box_run_p)
18283 it->pixel_width += abs (face->box_line_width);
18284 }
18285
18286 take_vertical_position_into_account (it);
18287
18288 if (it->glyph_row)
18289 {
18290 struct glyph *glyph;
18291 enum glyph_row_area area = it->area;
18292
18293 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18294 if (glyph < it->glyph_row->glyphs[area + 1])
18295 {
18296 glyph->charpos = CHARPOS (it->position);
18297 glyph->object = it->object;
18298 glyph->pixel_width = it->pixel_width;
493fdc3c
KS
18299 glyph->ascent = glyph_ascent;
18300 glyph->descent = it->descent;
133c764e
KS
18301 glyph->voffset = it->voffset;
18302 glyph->type = IMAGE_GLYPH;
18303 glyph->multibyte_p = it->multibyte_p;
18304 glyph->left_box_line_p = it->start_of_box_run_p;
18305 glyph->right_box_line_p = it->end_of_box_run_p;
18306 glyph->overlaps_vertically_p = 0;
18307 glyph->padding_p = 0;
18308 glyph->glyph_not_available_p = 0;
18309 glyph->face_id = it->face_id;
18310 glyph->u.img_id = img->id;
18311 glyph->font_type = FONT_TYPE_UNKNOWN;
18312 ++it->glyph_row->used[area];
18313 }
18314 }
18315}
18316
18317
18318/* Append a stretch glyph to IT->glyph_row. OBJECT is the source
18319 of the glyph, WIDTH and HEIGHT are the width and height of the
f65536fa 18320 stretch. ASCENT is the ascent of the glyph (0 <= ASCENT <= HEIGHT). */
133c764e
KS
18321
18322static void
18323append_stretch_glyph (it, object, width, height, ascent)
18324 struct it *it;
18325 Lisp_Object object;
18326 int width, height;
f65536fa 18327 int ascent;
133c764e
KS
18328{
18329 struct glyph *glyph;
18330 enum glyph_row_area area = it->area;
18331
f65536fa 18332 xassert (ascent >= 0 && ascent <= height);
133c764e
KS
18333
18334 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
18335 if (glyph < it->glyph_row->glyphs[area + 1])
18336 {
18337 glyph->charpos = CHARPOS (it->position);
18338 glyph->object = object;
18339 glyph->pixel_width = width;
493fdc3c
KS
18340 glyph->ascent = ascent;
18341 glyph->descent = height - ascent;
133c764e
KS
18342 glyph->voffset = it->voffset;
18343 glyph->type = STRETCH_GLYPH;
18344 glyph->multibyte_p = it->multibyte_p;
18345 glyph->left_box_line_p = it->start_of_box_run_p;
18346 glyph->right_box_line_p = it->end_of_box_run_p;
18347 glyph->overlaps_vertically_p = 0;
18348 glyph->padding_p = 0;
18349 glyph->glyph_not_available_p = 0;
18350 glyph->face_id = it->face_id;
f65536fa 18351 glyph->u.stretch.ascent = ascent;
133c764e
KS
18352 glyph->u.stretch.height = height;
18353 glyph->font_type = FONT_TYPE_UNKNOWN;
18354 ++it->glyph_row->used[area];
18355 }
18356}
18357
18358
f65536fa
KS
18359/* Calculate a width or height in pixels from a specification using
18360 the following elements:
18361
18362 SPEC ::=
18363 NUM - a (fractional) multiple of the default font width/height
18364 (NUM) - specifies exactly NUM pixels
18365 UNIT - a fixed number of pixels, see below.
18366 ELEMENT - size of a display element in pixels, see below.
18367 (NUM . SPEC) - equals NUM * SPEC
18368 (+ SPEC SPEC ...) - add pixel values
18369 (- SPEC SPEC ...) - subtract pixel values
18370 (- SPEC) - negate pixel value
18371
18372 NUM ::=
18373 INT or FLOAT - a number constant
18374 SYMBOL - use symbol's (buffer local) variable binding.
18375
18376 UNIT ::=
18377 in - pixels per inch *)
18378 mm - pixels per 1/1000 meter *)
18379 cm - pixels per 1/100 meter *)
18380 width - width of current font in pixels.
18381 height - height of current font in pixels.
18382
18383 *) using the ratio(s) defined in display-pixels-per-inch.
18384
18385 ELEMENT ::=
18386
18387 left-fringe - left fringe width in pixels
18388 (left-fringe . nil) - left fringe width if inside margins, else 0
18389 (left-fringe . t) - left fringe width if outside margins, else 0
18390
18391 right-fringe - right fringe width in pixels
18392 (right-fringe . nil) - right fringe width if inside margins, else 0
18393 (right-fringe . t) - right fringe width if outside margins, else 0
18394
18395 left-margin - left margin width in pixels
18396 right-margin - right margin width in pixels
18397
18398 scroll-bar - scroll-bar area width in pixels
18399 (scroll-bar . left) - scroll-bar width if on left, else 0
18400 (scroll-bar . right) - scroll-bar width if on right, else 0
18401
18402 Examples:
18403
18404 Pixels corresponding to 5 inches:
18405 (5 . in)
18406
18407 Total width of non-text areas on left side of window:
18408 (+ left-fringe left-margin (scroll-bar . left))
18409
18410 Total width of fringes if inside display margins:
18411 (+ (left-fringe) (right-fringe))
18412
18413 Width of left margin minus width of 1 character in the default font:
18414 (- left-margin 1)
18415
18416 Width of left margin minus width of 2 characters in the current font:
18417 (- left-margin (2 . width))
18418
18419 Width of left fringe plus left margin minus one pixel:
18420 (- (+ left-fringe left-margin) (1))
18421 (+ left-fringe left-margin (- (1)))
18422 (+ left-fringe left-margin (-1))
18423
18424*/
18425
18426#define NUMVAL(X) \
18427 ((INTEGERP (X) || FLOATP (X)) \
18428 ? XFLOATINT (X) \
18429 : - 1)
18430
18431static int
18432calc_pixel_width_or_height (res, it, prop, font, width_p)
18433 double *res;
18434 struct it *it;
18435 Lisp_Object prop;
18436 XFontStruct *font;
18437 int width_p;
18438{
18439 double pixels;
18440
18441#define OK_PIXELS(val) ((*res = (val)), 1)
18442
18443 if (SYMBOLP (prop))
18444 {
18445 if (SCHARS (SYMBOL_NAME (prop)) == 2)
18446 {
18447 char *unit = SDATA (SYMBOL_NAME (prop));
18448
18449 if (unit[0] == 'i' && unit[1] == 'n')
18450 pixels = 1.0;
18451 else if (unit[0] == 'm' && unit[1] == 'm')
18452 pixels = 25.4;
18453 else if (unit[0] == 'c' && unit[1] == 'm')
18454 pixels = 2.54;
18455 else
18456 pixels = 0;
18457 if (pixels > 0)
18458 {
18459 double ppi;
18460 if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
18461 || (CONSP (Vdisplay_pixels_per_inch)
18462 && (ppi = (width_p
18463 ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
18464 : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
18465 ppi > 0)))
18466 return OK_PIXELS (ppi / pixels);
18467
18468 return 0;
18469 }
18470 }
18471
18472 if (EQ (prop, Qheight))
18473 return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
18474 if (EQ (prop, Qwidth))
18475 return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
18476 if (EQ (prop, Qleft_fringe))
18477 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
18478 if (EQ (prop, Qright_fringe))
18479 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
18480 if (EQ (prop, Qleft_margin))
18481 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
18482 if (EQ (prop, Qright_margin))
18483 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
18484 if (EQ (prop, Qscroll_bar))
18485 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
18486
18487 prop = Fbuffer_local_value (prop, it->w->buffer);
18488 }
18489
18490 if (INTEGERP (prop) || FLOATP (prop))
18491 {
18492 int base_unit = (width_p
18493 ? FRAME_COLUMN_WIDTH (it->f)
18494 : FRAME_LINE_HEIGHT (it->f));
18495 return OK_PIXELS (XFLOATINT (prop) * base_unit);
18496 }
18497
18498 if (CONSP (prop))
18499 {
18500 Lisp_Object car = XCAR (prop);
18501 Lisp_Object cdr = XCDR (prop);
18502
18503 if (SYMBOLP (car))
18504 {
18505 if (EQ (car, Qplus) || EQ (car, Qminus))
18506 {
18507 int first = 1;
18508 double px;
18509
18510 pixels = 0;
18511 while (CONSP (cdr))
18512 {
18513 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), font, width_p))
18514 return 0;
18515 if (first)
18516 pixels = (EQ (car, Qplus) ? px : -px), first = 0;
18517 else
18518 pixels += px;
18519 cdr = XCDR (cdr);
18520 }
18521 if (EQ (car, Qminus))
18522 pixels = -pixels;
18523 return OK_PIXELS (pixels);
18524 }
18525
18526 if (EQ (car, Qleft_fringe))
18527 return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
18528 == !NILP (cdr))
18529 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
18530 : 0);
18531 if (EQ (car, Qright_fringe))
18532 return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
18533 == !NILP (cdr))
18534 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
18535 : 0);
18536 if (EQ (car, Qscroll_bar))
18537 return OK_PIXELS ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
18538 == EQ (cdr, Qleft))
18539 ? WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)
18540 : 0);
18541
18542 car = Fbuffer_local_value (car, it->w->buffer);
18543 }
18544
18545 if (INTEGERP (car) || FLOATP (car))
18546 {
18547 double fact;
18548 pixels = XFLOATINT (car);
18549 if (NILP (cdr))
18550 return OK_PIXELS (pixels);
18551 if (calc_pixel_width_or_height (&fact, it, cdr, font, width_p))
18552 return OK_PIXELS (pixels * fact);
18553 return 0;
18554 }
18555
18556 return 0;
18557 }
18558
18559 return 0;
18560}
18561
133c764e
KS
18562/* Produce a stretch glyph for iterator IT. IT->object is the value
18563 of the glyph property displayed. The value must be a list
18564 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
18565 being recognized:
18566
18567 1. `:width WIDTH' specifies that the space should be WIDTH *
18568 canonical char width wide. WIDTH may be an integer or floating
18569 point number.
18570
18571 2. `:relative-width FACTOR' specifies that the width of the stretch
18572 should be computed from the width of the first character having the
18573 `glyph' property, and should be FACTOR times that width.
18574
18575 3. `:align-to HPOS' specifies that the space should be wide enough
18576 to reach HPOS, a value in canonical character units.
18577
18578 Exactly one of the above pairs must be present.
18579
18580 4. `:height HEIGHT' specifies that the height of the stretch produced
18581 should be HEIGHT, measured in canonical character units.
18582
18583 5. `:relative-height FACTOR' specifies that the height of the
18584 stretch should be FACTOR times the height of the characters having
18585 the glyph property.
18586
18587 Either none or exactly one of 4 or 5 must be present.
18588
18589 6. `:ascent ASCENT' specifies that ASCENT percent of the height
18590 of the stretch should be used for the ascent of the stretch.
18591 ASCENT must be in the range 0 <= ASCENT <= 100. */
18592
133c764e
KS
18593static void
18594produce_stretch_glyph (it)
18595 struct it *it;
18596{
f65536fa 18597 /* (space :width WIDTH :height HEIGHT ...) */
133c764e
KS
18598 Lisp_Object prop, plist;
18599 int width = 0, height = 0;
f65536fa
KS
18600 int zero_width_ok_p = 0, zero_height_ok_p = 0;
18601 int ascent = 0;
18602 double tem;
133c764e
KS
18603 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18604 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
18605
18606 PREPARE_FACE_FOR_DISPLAY (it->f, face);
18607
18608 /* List should start with `space'. */
18609 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
18610 plist = XCDR (it->object);
18611
18612 /* Compute the width of the stretch. */
f65536fa
KS
18613 if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
18614 && calc_pixel_width_or_height (&tem, it, prop, font, 1))
18615 {
18616 /* Absolute width `:width WIDTH' specified and valid. */
18617 zero_width_ok_p = 1;
18618 width = (int)tem;
18619 }
133c764e
KS
18620 else if (prop = Fplist_get (plist, QCrelative_width),
18621 NUMVAL (prop) > 0)
18622 {
18623 /* Relative width `:relative-width FACTOR' specified and valid.
18624 Compute the width of the characters having the `glyph'
18625 property. */
18626 struct it it2;
18627 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
18628
18629 it2 = *it;
18630 if (it->multibyte_p)
18631 {
18632 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
18633 - IT_BYTEPOS (*it));
18634 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
18635 }
18636 else
18637 it2.c = *p, it2.len = 1;
18638
18639 it2.glyph_row = NULL;
18640 it2.what = IT_CHARACTER;
18641 x_produce_glyphs (&it2);
18642 width = NUMVAL (prop) * it2.pixel_width;
18643 }
f65536fa
KS
18644 else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
18645 && calc_pixel_width_or_height (&tem, it, prop, font, 1))
18646 {
18647 width = max (0, (int)tem - it->current_x);
18648 zero_width_ok_p = 1;
18649 }
133c764e
KS
18650 else
18651 /* Nothing specified -> width defaults to canonical char width. */
da8b7f4f 18652 width = FRAME_COLUMN_WIDTH (it->f);
133c764e 18653
f65536fa
KS
18654 if (width <= 0 && (width < 0 || !zero_width_ok_p))
18655 width = 1;
18656
133c764e 18657 /* Compute height. */
f65536fa
KS
18658 if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
18659 && calc_pixel_width_or_height (&tem, it, prop, font, 0))
18660 {
18661 height = (int)tem;
18662 zero_height_ok_p = 1;
18663 }
133c764e
KS
18664 else if (prop = Fplist_get (plist, QCrelative_height),
18665 NUMVAL (prop) > 0)
18666 height = FONT_HEIGHT (font) * NUMVAL (prop);
18667 else
18668 height = FONT_HEIGHT (font);
18669
f65536fa
KS
18670 if (height <= 0 && (height < 0 || !zero_height_ok_p))
18671 height = 1;
18672
133c764e
KS
18673 /* Compute percentage of height used for ascent. If
18674 `:ascent ASCENT' is present and valid, use that. Otherwise,
18675 derive the ascent from the font in use. */
18676 if (prop = Fplist_get (plist, QCascent),
18677 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
f65536fa
KS
18678 ascent = height * NUMVAL (prop) / 100.0;
18679 else if (!NILP (prop)
18680 && calc_pixel_width_or_height (&tem, it, prop, font, 0))
18681 ascent = min (max (0, (int)tem), height);
133c764e 18682 else
f65536fa 18683 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
133c764e 18684
f65536fa 18685 if (width > 0 && height > 0 && it->glyph_row)
133c764e
KS
18686 {
18687 Lisp_Object object = it->stack[it->sp - 1].string;
18688 if (!STRINGP (object))
18689 object = it->w->buffer;
18690 append_stretch_glyph (it, object, width, height, ascent);
18691 }
18692
18693 it->pixel_width = width;
f65536fa 18694 it->ascent = it->phys_ascent = ascent;
133c764e 18695 it->descent = it->phys_descent = height - it->ascent;
f65536fa 18696 it->nglyphs = width > 0 && height > 0 ? 1 : 0;
133c764e 18697
f65536fa 18698 if (width > 0 && height > 0 && face->box != FACE_NO_BOX)
133c764e
KS
18699 {
18700 if (face->box_line_width > 0)
18701 {
18702 it->ascent += face->box_line_width;
18703 it->descent += face->box_line_width;
18704 }
18705
18706 if (it->start_of_box_run_p)
18707 it->pixel_width += abs (face->box_line_width);
18708 if (it->end_of_box_run_p)
18709 it->pixel_width += abs (face->box_line_width);
18710 }
18711
18712 take_vertical_position_into_account (it);
18713}
18714
18715/* RIF:
18716 Produce glyphs/get display metrics for the display element IT is
18717 loaded with. See the description of struct display_iterator in
18718 dispextern.h for an overview of struct display_iterator. */
18719
18720void
18721x_produce_glyphs (it)
18722 struct it *it;
18723{
18724 it->glyph_not_available_p = 0;
18725
18726 if (it->what == IT_CHARACTER)
18727 {
18728 XChar2b char2b;
18729 XFontStruct *font;
18730 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18731 XCharStruct *pcm;
18732 int font_not_found_p;
18733 struct font_info *font_info;
18734 int boff; /* baseline offset */
18735 /* We may change it->multibyte_p upon unibyte<->multibyte
18736 conversion. So, save the current value now and restore it
18737 later.
18738
18739 Note: It seems that we don't have to record multibyte_p in
18740 struct glyph because the character code itself tells if or
18741 not the character is multibyte. Thus, in the future, we must
18742 consider eliminating the field `multibyte_p' in the struct
18743 glyph. */
18744 int saved_multibyte_p = it->multibyte_p;
18745
18746 /* Maybe translate single-byte characters to multibyte, or the
18747 other way. */
18748 it->char_to_display = it->c;
18749 if (!ASCII_BYTE_P (it->c))
18750 {
18751 if (unibyte_display_via_language_environment
18752 && SINGLE_BYTE_CHAR_P (it->c)
18753 && (it->c >= 0240
18754 || !NILP (Vnonascii_translation_table)))
18755 {
18756 it->char_to_display = unibyte_char_to_multibyte (it->c);
18757 it->multibyte_p = 1;
18758 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
18759 face = FACE_FROM_ID (it->f, it->face_id);
18760 }
18761 else if (!SINGLE_BYTE_CHAR_P (it->c)
18762 && !it->multibyte_p)
18763 {
18764 it->multibyte_p = 1;
18765 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
18766 face = FACE_FROM_ID (it->f, it->face_id);
18767 }
18768 }
18769
18770 /* Get font to use. Encode IT->char_to_display. */
18771 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
18772 &char2b, it->multibyte_p, 0);
18773 font = face->font;
18774
18775 /* When no suitable font found, use the default font. */
18776 font_not_found_p = font == NULL;
18777 if (font_not_found_p)
18778 {
18779 font = FRAME_FONT (it->f);
18780 boff = FRAME_BASELINE_OFFSET (it->f);
18781 font_info = NULL;
18782 }
18783 else
18784 {
18785 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
18786 boff = font_info->baseline_offset;
18787 if (font_info->vertical_centering)
18788 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
18789 }
18790
18791 if (it->char_to_display >= ' '
18792 && (!it->multibyte_p || it->char_to_display < 128))
18793 {
18794 /* Either unibyte or ASCII. */
18795 int stretched_p;
18796
18797 it->nglyphs = 1;
18798
18799 pcm = rif->per_char_metric (font, &char2b,
18800 FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
18801 it->ascent = FONT_BASE (font) + boff;
18802 it->descent = FONT_DESCENT (font) - boff;
18803
18804 if (pcm)
18805 {
18806 it->phys_ascent = pcm->ascent + boff;
18807 it->phys_descent = pcm->descent - boff;
18808 it->pixel_width = pcm->width;
18809 }
18810 else
18811 {
18812 it->glyph_not_available_p = 1;
18813 it->phys_ascent = FONT_BASE (font) + boff;
18814 it->phys_descent = FONT_DESCENT (font) - boff;
18815 it->pixel_width = FONT_WIDTH (font);
18816 }
18817
18818 /* If this is a space inside a region of text with
18819 `space-width' property, change its width. */
18820 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
18821 if (stretched_p)
18822 it->pixel_width *= XFLOATINT (it->space_width);
18823
18824 /* If face has a box, add the box thickness to the character
18825 height. If character has a box line to the left and/or
18826 right, add the box line width to the character's width. */
18827 if (face->box != FACE_NO_BOX)
18828 {
18829 int thick = face->box_line_width;
18830
18831 if (thick > 0)
18832 {
18833 it->ascent += thick;
18834 it->descent += thick;
18835 }
18836 else
18837 thick = -thick;
18838
18839 if (it->start_of_box_run_p)
18840 it->pixel_width += thick;
18841 if (it->end_of_box_run_p)
18842 it->pixel_width += thick;
18843 }
18844
18845 /* If face has an overline, add the height of the overline
18846 (1 pixel) and a 1 pixel margin to the character height. */
18847 if (face->overline_p)
18848 it->ascent += 2;
18849
18850 take_vertical_position_into_account (it);
18851
18852 /* If we have to actually produce glyphs, do it. */
18853 if (it->glyph_row)
18854 {
18855 if (stretched_p)
18856 {
18857 /* Translate a space with a `space-width' property
18858 into a stretch glyph. */
f65536fa
KS
18859 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
18860 / FONT_HEIGHT (font));
133c764e
KS
18861 append_stretch_glyph (it, it->object, it->pixel_width,
18862 it->ascent + it->descent, ascent);
18863 }
18864 else
18865 append_glyph (it);
18866
18867 /* If characters with lbearing or rbearing are displayed
18868 in this line, record that fact in a flag of the
18869 glyph row. This is used to optimize X output code. */
18870 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
18871 it->glyph_row->contains_overlapping_glyphs_p = 1;
18872 }
18873 }
18874 else if (it->char_to_display == '\n')
18875 {
18876 /* A newline has no width but we need the height of the line. */
18877 it->pixel_width = 0;
18878 it->nglyphs = 0;
18879 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
18880 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
18881
18882 if (face->box != FACE_NO_BOX
18883 && face->box_line_width > 0)
18884 {
18885 it->ascent += face->box_line_width;
18886 it->descent += face->box_line_width;
18887 }
18888 }
18889 else if (it->char_to_display == '\t')
18890 {
da8b7f4f 18891 int tab_width = it->tab_width * FRAME_COLUMN_WIDTH (it->f);
133c764e
KS
18892 int x = it->current_x + it->continuation_lines_width;
18893 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
18894
18895 /* If the distance from the current position to the next tab
18896 stop is less than a canonical character width, use the
18897 tab stop after that. */
da8b7f4f 18898 if (next_tab_x - x < FRAME_COLUMN_WIDTH (it->f))
133c764e
KS
18899 next_tab_x += tab_width;
18900
18901 it->pixel_width = next_tab_x - x;
18902 it->nglyphs = 1;
18903 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
18904 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
18905
18906 if (it->glyph_row)
18907 {
133c764e 18908 append_stretch_glyph (it, it->object, it->pixel_width,
f65536fa 18909 it->ascent + it->descent, it->ascent);
133c764e
KS
18910 }
18911 }
18912 else
18913 {
18914 /* A multi-byte character. Assume that the display width of the
18915 character is the width of the character multiplied by the
18916 width of the font. */
18917
18918 /* If we found a font, this font should give us the right
18919 metrics. If we didn't find a font, use the frame's
18920 default font and calculate the width of the character
18921 from the charset width; this is what old redisplay code
18922 did. */
18923
18924 pcm = rif->per_char_metric (font, &char2b,
18925 FONT_TYPE_FOR_MULTIBYTE (font, it->c));
18926
18927 if (font_not_found_p || !pcm)
18928 {
18929 int charset = CHAR_CHARSET (it->char_to_display);
18930
18931 it->glyph_not_available_p = 1;
da8b7f4f 18932 it->pixel_width = (FRAME_COLUMN_WIDTH (it->f)
133c764e
KS
18933 * CHARSET_WIDTH (charset));
18934 it->phys_ascent = FONT_BASE (font) + boff;
18935 it->phys_descent = FONT_DESCENT (font) - boff;
18936 }
18937 else
18938 {
18939 it->pixel_width = pcm->width;
18940 it->phys_ascent = pcm->ascent + boff;
18941 it->phys_descent = pcm->descent - boff;
18942 if (it->glyph_row
18943 && (pcm->lbearing < 0
18944 || pcm->rbearing > pcm->width))
18945 it->glyph_row->contains_overlapping_glyphs_p = 1;
18946 }
18947 it->nglyphs = 1;
18948 it->ascent = FONT_BASE (font) + boff;
18949 it->descent = FONT_DESCENT (font) - boff;
18950 if (face->box != FACE_NO_BOX)
18951 {
18952 int thick = face->box_line_width;
18953
18954 if (thick > 0)
18955 {
18956 it->ascent += thick;
18957 it->descent += thick;
18958 }
18959 else
18960 thick = - thick;
18961
18962 if (it->start_of_box_run_p)
18963 it->pixel_width += thick;
18964 if (it->end_of_box_run_p)
18965 it->pixel_width += thick;
18966 }
18967
18968 /* If face has an overline, add the height of the overline
18969 (1 pixel) and a 1 pixel margin to the character height. */
18970 if (face->overline_p)
18971 it->ascent += 2;
18972
18973 take_vertical_position_into_account (it);
18974
18975 if (it->glyph_row)
18976 append_glyph (it);
18977 }
18978 it->multibyte_p = saved_multibyte_p;
18979 }
18980 else if (it->what == IT_COMPOSITION)
18981 {
18982 /* Note: A composition is represented as one glyph in the
18983 glyph matrix. There are no padding glyphs. */
18984 XChar2b char2b;
18985 XFontStruct *font;
18986 struct face *face = FACE_FROM_ID (it->f, it->face_id);
18987 XCharStruct *pcm;
18988 int font_not_found_p;
18989 struct font_info *font_info;
18990 int boff; /* baseline offset */
18991 struct composition *cmp = composition_table[it->cmp_id];
18992
18993 /* Maybe translate single-byte characters to multibyte. */
18994 it->char_to_display = it->c;
18995 if (unibyte_display_via_language_environment
18996 && SINGLE_BYTE_CHAR_P (it->c)
18997 && (it->c >= 0240
18998 || (it->c >= 0200
18999 && !NILP (Vnonascii_translation_table))))
19000 {
19001 it->char_to_display = unibyte_char_to_multibyte (it->c);
19002 }
19003
19004 /* Get face and font to use. Encode IT->char_to_display. */
19005 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
19006 face = FACE_FROM_ID (it->f, it->face_id);
19007 get_char_face_and_encoding (it->f, it->char_to_display, it->face_id,
19008 &char2b, it->multibyte_p, 0);
19009 font = face->font;
19010
19011 /* When no suitable font found, use the default font. */
19012 font_not_found_p = font == NULL;
19013 if (font_not_found_p)
19014 {
19015 font = FRAME_FONT (it->f);
19016 boff = FRAME_BASELINE_OFFSET (it->f);
19017 font_info = NULL;
19018 }
19019 else
19020 {
19021 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
19022 boff = font_info->baseline_offset;
19023 if (font_info->vertical_centering)
19024 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
19025 }
19026
19027 /* There are no padding glyphs, so there is only one glyph to
19028 produce for the composition. Important is that pixel_width,
19029 ascent and descent are the values of what is drawn by
19030 draw_glyphs (i.e. the values of the overall glyphs composed). */
19031 it->nglyphs = 1;
19032
19033 /* If we have not yet calculated pixel size data of glyphs of
19034 the composition for the current face font, calculate them
19035 now. Theoretically, we have to check all fonts for the
19036 glyphs, but that requires much time and memory space. So,
19037 here we check only the font of the first glyph. This leads
19038 to incorrect display very rarely, and C-l (recenter) can
19039 correct the display anyway. */
19040 if (cmp->font != (void *) font)
19041 {
19042 /* Ascent and descent of the font of the first character of
19043 this composition (adjusted by baseline offset). Ascent
19044 and descent of overall glyphs should not be less than
19045 them respectively. */
19046 int font_ascent = FONT_BASE (font) + boff;
19047 int font_descent = FONT_DESCENT (font) - boff;
19048 /* Bounding box of the overall glyphs. */
19049 int leftmost, rightmost, lowest, highest;
19050 int i, width, ascent, descent;
19051
19052 cmp->font = (void *) font;
19053
19054 /* Initialize the bounding box. */
19055 if (font_info
19056 && (pcm = rif->per_char_metric (font, &char2b,
19057 FONT_TYPE_FOR_MULTIBYTE (font, it->c))))
19058 {
19059 width = pcm->width;
19060 ascent = pcm->ascent;
19061 descent = pcm->descent;
19062 }
19063 else
19064 {
19065 width = FONT_WIDTH (font);
19066 ascent = FONT_BASE (font);
19067 descent = FONT_DESCENT (font);
19068 }
19069
19070 rightmost = width;
19071 lowest = - descent + boff;
19072 highest = ascent + boff;
19073 leftmost = 0;
19074
19075 if (font_info
19076 && font_info->default_ascent
19077 && CHAR_TABLE_P (Vuse_default_ascent)
19078 && !NILP (Faref (Vuse_default_ascent,
19079 make_number (it->char_to_display))))
19080 highest = font_info->default_ascent + boff;
19081
19082 /* Draw the first glyph at the normal position. It may be
19083 shifted to right later if some other glyphs are drawn at
19084 the left. */
19085 cmp->offsets[0] = 0;
19086 cmp->offsets[1] = boff;
19087
19088 /* Set cmp->offsets for the remaining glyphs. */
19089 for (i = 1; i < cmp->glyph_len; i++)
19090 {
19091 int left, right, btm, top;
19092 int ch = COMPOSITION_GLYPH (cmp, i);
19093 int face_id = FACE_FOR_CHAR (it->f, face, ch);
19094
19095 face = FACE_FROM_ID (it->f, face_id);
19096 get_char_face_and_encoding (it->f, ch, face->id,
19097 &char2b, it->multibyte_p, 0);
19098 font = face->font;
19099 if (font == NULL)
19100 {
19101 font = FRAME_FONT (it->f);
2a6d0874 19102 boff = FRAME_BASELINE_OFFSET (it->f);
133c764e
KS
19103 font_info = NULL;
19104 }
19105 else
19106 {
19107 font_info
19108 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
19109 boff = font_info->baseline_offset;
19110 if (font_info->vertical_centering)
19111 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
19112 }
19113
19114 if (font_info
2a6d0874 19115 && (pcm = rif->per_char_metric (font, &char2b,
133c764e
KS
19116 FONT_TYPE_FOR_MULTIBYTE (font, ch))))
19117 {
19118 width = pcm->width;
19119 ascent = pcm->ascent;
19120 descent = pcm->descent;
19121 }
19122 else
19123 {
19124 width = FONT_WIDTH (font);
19125 ascent = 1;
19126 descent = 0;
19127 }
19128
19129 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
19130 {
19131 /* Relative composition with or without
19132 alternate chars. */
19133 left = (leftmost + rightmost - width) / 2;
19134 btm = - descent + boff;
19135 if (font_info && font_info->relative_compose
19136 && (! CHAR_TABLE_P (Vignore_relative_composition)
19137 || NILP (Faref (Vignore_relative_composition,
19138 make_number (ch)))))
19139 {
19140
19141 if (- descent >= font_info->relative_compose)
19142 /* One extra pixel between two glyphs. */
19143 btm = highest + 1;
19144 else if (ascent <= 0)
19145 /* One extra pixel between two glyphs. */
19146 btm = lowest - 1 - ascent - descent;
19147 }
19148 }
19149 else
19150 {
19151 /* A composition rule is specified by an integer
19152 value that encodes global and new reference
19153 points (GREF and NREF). GREF and NREF are
19154 specified by numbers as below:
19155
19156 0---1---2 -- ascent
19157 | |
19158 | |
19159 | |
19160 9--10--11 -- center
19161 | |
19162 ---3---4---5--- baseline
19163 | |
19164 6---7---8 -- descent
19165 */
19166 int rule = COMPOSITION_RULE (cmp, i);
19167 int gref, nref, grefx, grefy, nrefx, nrefy;
19168
19169 COMPOSITION_DECODE_RULE (rule, gref, nref);
19170 grefx = gref % 3, nrefx = nref % 3;
19171 grefy = gref / 3, nrefy = nref / 3;
19172
19173 left = (leftmost
19174 + grefx * (rightmost - leftmost) / 2
19175 - nrefx * width / 2);
19176 btm = ((grefy == 0 ? highest
19177 : grefy == 1 ? 0
19178 : grefy == 2 ? lowest
19179 : (highest + lowest) / 2)
19180 - (nrefy == 0 ? ascent + descent
19181 : nrefy == 1 ? descent - boff
19182 : nrefy == 2 ? 0
19183 : (ascent + descent) / 2));
19184 }
19185
19186 cmp->offsets[i * 2] = left;
19187 cmp->offsets[i * 2 + 1] = btm + descent;
19188
19189 /* Update the bounding box of the overall glyphs. */
19190 right = left + width;
19191 top = btm + descent + ascent;
19192 if (left < leftmost)
19193 leftmost = left;
19194 if (right > rightmost)
19195 rightmost = right;
19196 if (top > highest)
19197 highest = top;
19198 if (btm < lowest)
19199 lowest = btm;
19200 }
19201
19202 /* If there are glyphs whose x-offsets are negative,
19203 shift all glyphs to the right and make all x-offsets
19204 non-negative. */
19205 if (leftmost < 0)
19206 {
19207 for (i = 0; i < cmp->glyph_len; i++)
19208 cmp->offsets[i * 2] -= leftmost;
19209 rightmost -= leftmost;
19210 }
19211
19212 cmp->pixel_width = rightmost;
19213 cmp->ascent = highest;
19214 cmp->descent = - lowest;
19215 if (cmp->ascent < font_ascent)
19216 cmp->ascent = font_ascent;
19217 if (cmp->descent < font_descent)
19218 cmp->descent = font_descent;
19219 }
19220
19221 it->pixel_width = cmp->pixel_width;
19222 it->ascent = it->phys_ascent = cmp->ascent;
19223 it->descent = it->phys_descent = cmp->descent;
19224
19225 if (face->box != FACE_NO_BOX)
19226 {
19227 int thick = face->box_line_width;
19228
19229 if (thick > 0)
19230 {
19231 it->ascent += thick;
19232 it->descent += thick;
19233 }
19234 else
19235 thick = - thick;
19236
19237 if (it->start_of_box_run_p)
19238 it->pixel_width += thick;
19239 if (it->end_of_box_run_p)
19240 it->pixel_width += thick;
19241 }
19242
19243 /* If face has an overline, add the height of the overline
19244 (1 pixel) and a 1 pixel margin to the character height. */
19245 if (face->overline_p)
19246 it->ascent += 2;
19247
19248 take_vertical_position_into_account (it);
19249
19250 if (it->glyph_row)
19251 append_composite_glyph (it);
19252 }
19253 else if (it->what == IT_IMAGE)
19254 produce_image_glyph (it);
19255 else if (it->what == IT_STRETCH)
19256 produce_stretch_glyph (it);
19257
19258 /* Accumulate dimensions. Note: can't assume that it->descent > 0
19259 because this isn't true for images with `:ascent 100'. */
19260 xassert (it->ascent >= 0 && it->descent >= 0);
19261 if (it->area == TEXT_AREA)
19262 it->current_x += it->pixel_width;
19263
19264 it->descent += it->extra_line_spacing;
19265
19266 it->max_ascent = max (it->max_ascent, it->ascent);
19267 it->max_descent = max (it->max_descent, it->descent);
19268 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
19269 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
19270}
19271
fa3c6b4d
KS
19272/* EXPORT for RIF:
19273 Output LEN glyphs starting at START at the nominal cursor position.
19274 Advance the nominal cursor over the text. The global variable
19275 updated_window contains the window being updated, updated_row is
19276 the glyph row being updated, and updated_area is the area of that
19277 row being updated. */
133c764e 19278
fa3c6b4d
KS
19279void
19280x_write_glyphs (start, len)
19281 struct glyph *start;
19282 int len;
19283{
19284 int x, hpos;
133c764e 19285
fa3c6b4d
KS
19286 xassert (updated_window && updated_row);
19287 BLOCK_INPUT;
133c764e 19288
fa3c6b4d 19289 /* Write glyphs. */
cfe03a41 19290
fa3c6b4d
KS
19291 hpos = start - updated_row->glyphs[updated_area];
19292 x = draw_glyphs (updated_window, output_cursor.x,
19293 updated_row, updated_area,
19294 hpos, hpos + len,
19295 DRAW_NORMAL_TEXT, 0);
cfe03a41 19296
fa3c6b4d
KS
19297 /* Invalidate old phys cursor if the glyph at its hpos is redrawn. */
19298 if (updated_area == TEXT_AREA
19299 && updated_window->phys_cursor_on_p
19300 && updated_window->phys_cursor.vpos == output_cursor.vpos
19301 && updated_window->phys_cursor.hpos >= hpos
19302 && updated_window->phys_cursor.hpos < hpos + len)
19303 updated_window->phys_cursor_on_p = 0;
cfe03a41 19304
fa3c6b4d 19305 UNBLOCK_INPUT;
cfe03a41 19306
fa3c6b4d
KS
19307 /* Advance the output cursor. */
19308 output_cursor.hpos += len;
19309 output_cursor.x = x;
19310}
cfe03a41 19311
cfe03a41 19312
fa3c6b4d
KS
19313/* EXPORT for RIF:
19314 Insert LEN glyphs from START at the nominal cursor position. */
19315
19316void
19317x_insert_glyphs (start, len)
19318 struct glyph *start;
19319 int len;
19320{
19321 struct frame *f;
19322 struct window *w;
19323 int line_height, shift_by_width, shifted_region_width;
19324 struct glyph_row *row;
19325 struct glyph *glyph;
19326 int frame_x, frame_y, hpos;
19327
19328 xassert (updated_window && updated_row);
19329 BLOCK_INPUT;
19330 w = updated_window;
19331 f = XFRAME (WINDOW_FRAME (w));
19332
19333 /* Get the height of the line we are in. */
19334 row = updated_row;
19335 line_height = row->height;
19336
19337 /* Get the width of the glyphs to insert. */
19338 shift_by_width = 0;
19339 for (glyph = start; glyph < start + len; ++glyph)
19340 shift_by_width += glyph->pixel_width;
19341
19342 /* Get the width of the region to shift right. */
19343 shifted_region_width = (window_box_width (w, updated_area)
19344 - output_cursor.x
19345 - shift_by_width);
19346
19347 /* Shift right. */
19348 frame_x = window_box_left (w, updated_area) + output_cursor.x;
19349 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
19350
7b7b454e
AS
19351 rif->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
19352 line_height, shift_by_width);
fa3c6b4d
KS
19353
19354 /* Write the glyphs. */
19355 hpos = start - row->glyphs[updated_area];
19356 draw_glyphs (w, output_cursor.x, row, updated_area,
19357 hpos, hpos + len,
19358 DRAW_NORMAL_TEXT, 0);
19359
19360 /* Advance the output cursor. */
19361 output_cursor.hpos += len;
19362 output_cursor.x += shift_by_width;
19363 UNBLOCK_INPUT;
19364}
19365
19366
19367/* EXPORT for RIF:
19368 Erase the current text line from the nominal cursor position
19369 (inclusive) to pixel column TO_X (exclusive). The idea is that
19370 everything from TO_X onward is already erased.
19371
19372 TO_X is a pixel position relative to updated_area of
19373 updated_window. TO_X == -1 means clear to the end of this area. */
19374
19375void
19376x_clear_end_of_line (to_x)
19377 int to_x;
19378{
19379 struct frame *f;
19380 struct window *w = updated_window;
19381 int max_x, min_y, max_y;
19382 int from_x, from_y, to_y;
19383
19384 xassert (updated_window && updated_row);
19385 f = XFRAME (w->frame);
19386
19387 if (updated_row->full_width_p)
da8b7f4f 19388 max_x = WINDOW_TOTAL_WIDTH (w);
fa3c6b4d
KS
19389 else
19390 max_x = window_box_width (w, updated_area);
19391 max_y = window_text_bottom_y (w);
19392
19393 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
19394 of window. For TO_X > 0, truncate to end of drawing area. */
19395 if (to_x == 0)
19396 return;
19397 else if (to_x < 0)
19398 to_x = max_x;
19399 else
19400 to_x = min (to_x, max_x);
19401
19402 to_y = min (max_y, output_cursor.y + updated_row->height);
19403
19404 /* Notice if the cursor will be cleared by this operation. */
19405 if (!updated_row->full_width_p)
19406 notice_overwritten_cursor (w, updated_area,
19407 output_cursor.x, -1,
19408 updated_row->y,
19409 MATRIX_ROW_BOTTOM_Y (updated_row));
19410
19411 from_x = output_cursor.x;
19412
19413 /* Translate to frame coordinates. */
19414 if (updated_row->full_width_p)
19415 {
19416 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
19417 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
19418 }
19419 else
19420 {
da8b7f4f
KS
19421 int area_left = window_box_left (w, updated_area);
19422 from_x += area_left;
19423 to_x += area_left;
fa3c6b4d
KS
19424 }
19425
da8b7f4f 19426 min_y = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
19427 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
19428 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
19429
19430 /* Prevent inadvertently clearing to end of the X window. */
19431 if (to_x > from_x && to_y > from_y)
19432 {
19433 BLOCK_INPUT;
19434 rif->clear_frame_area (f, from_x, from_y,
19435 to_x - from_x, to_y - from_y);
19436 UNBLOCK_INPUT;
19437 }
19438}
19439
19440#endif /* HAVE_WINDOW_SYSTEM */
19441
19442
19443\f
19444/***********************************************************************
19445 Cursor types
19446 ***********************************************************************/
19447
19448/* Value is the internal representation of the specified cursor type
19449 ARG. If type is BAR_CURSOR, return in *WIDTH the specified width
19450 of the bar cursor. */
19451
f65536fa 19452static enum text_cursor_kinds
fa3c6b4d
KS
19453get_specified_cursor_type (arg, width)
19454 Lisp_Object arg;
19455 int *width;
19456{
19457 enum text_cursor_kinds type;
19458
19459 if (NILP (arg))
19460 return NO_CURSOR;
19461
19462 if (EQ (arg, Qbox))
19463 return FILLED_BOX_CURSOR;
19464
19465 if (EQ (arg, Qhollow))
19466 return HOLLOW_BOX_CURSOR;
19467
19468 if (EQ (arg, Qbar))
19469 {
19470 *width = 2;
19471 return BAR_CURSOR;
19472 }
19473
19474 if (CONSP (arg)
19475 && EQ (XCAR (arg), Qbar)
19476 && INTEGERP (XCDR (arg))
19477 && XINT (XCDR (arg)) >= 0)
19478 {
19479 *width = XINT (XCDR (arg));
19480 return BAR_CURSOR;
19481 }
19482
19483 if (EQ (arg, Qhbar))
19484 {
19485 *width = 2;
19486 return HBAR_CURSOR;
19487 }
19488
19489 if (CONSP (arg)
19490 && EQ (XCAR (arg), Qhbar)
19491 && INTEGERP (XCDR (arg))
19492 && XINT (XCDR (arg)) >= 0)
19493 {
19494 *width = XINT (XCDR (arg));
19495 return HBAR_CURSOR;
19496 }
19497
19498 /* Treat anything unknown as "hollow box cursor".
19499 It was bad to signal an error; people have trouble fixing
19500 .Xdefaults with Emacs, when it has something bad in it. */
19501 type = HOLLOW_BOX_CURSOR;
19502
19503 return type;
19504}
19505
19506/* Set the default cursor types for specified frame. */
19507void
19508set_frame_cursor_types (f, arg)
19509 struct frame *f;
19510 Lisp_Object arg;
19511{
19512 int width;
19513 Lisp_Object tem;
19514
19515 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
19516 FRAME_CURSOR_WIDTH (f) = width;
19517
19518 /* By default, set up the blink-off state depending on the on-state. */
19519
19520 tem = Fassoc (arg, Vblink_cursor_alist);
19521 if (!NILP (tem))
19522 {
19523 FRAME_BLINK_OFF_CURSOR (f)
19524 = get_specified_cursor_type (XCDR (tem), &width);
19525 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
19526 }
19527 else
19528 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
19529}
19530
19531
19532/* Return the cursor we want to be displayed in window W. Return
19533 width of bar/hbar cursor through WIDTH arg. Return with
19534 ACTIVE_CURSOR arg set to 1 if cursor in window W is `active'
19535 (i.e. if the `system caret' should track this cursor).
19536
19537 In a mini-buffer window, we want the cursor only to appear if we
19538 are reading input from this window. For the selected window, we
19539 want the cursor type given by the frame parameter or buffer local
19540 setting of cursor-type. If explicitly marked off, draw no cursor.
19541 In all other cases, we want a hollow box cursor. */
19542
f65536fa
KS
19543static enum text_cursor_kinds
19544get_window_cursor_type (w, glyph, width, active_cursor)
fa3c6b4d 19545 struct window *w;
f65536fa 19546 struct glyph *glyph;
fa3c6b4d
KS
19547 int *width;
19548 int *active_cursor;
19549{
19550 struct frame *f = XFRAME (w->frame);
19551 struct buffer *b = XBUFFER (w->buffer);
19552 int cursor_type = DEFAULT_CURSOR;
19553 Lisp_Object alt_cursor;
19554 int non_selected = 0;
19555
19556 *active_cursor = 1;
19557
19558 /* Echo area */
19559 if (cursor_in_echo_area
19560 && FRAME_HAS_MINIBUF_P (f)
19561 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
19562 {
19563 if (w == XWINDOW (echo_area_window))
19564 {
19565 *width = FRAME_CURSOR_WIDTH (f);
19566 return FRAME_DESIRED_CURSOR (f);
19567 }
19568
19569 *active_cursor = 0;
19570 non_selected = 1;
19571 }
19572
19573 /* Nonselected window or nonselected frame. */
19574 else if (w != XWINDOW (f->selected_window)
19575#ifdef HAVE_WINDOW_SYSTEM
19576 || f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame
19577#endif
19578 )
19579 {
19580 *active_cursor = 0;
19581
19582 if (MINI_WINDOW_P (w) && minibuf_level == 0)
19583 return NO_CURSOR;
19584
19585 non_selected = 1;
19586 }
19587
19588 /* Never display a cursor in a window in which cursor-type is nil. */
19589 if (NILP (b->cursor_type))
19590 return NO_CURSOR;
19591
19592 /* Use cursor-in-non-selected-windows for non-selected window or frame. */
19593 if (non_selected)
19594 {
19595 alt_cursor = Fbuffer_local_value (Qcursor_in_non_selected_windows, w->buffer);
19596 return get_specified_cursor_type (alt_cursor, width);
19597 }
19598
19599 /* Get the normal cursor type for this window. */
19600 if (EQ (b->cursor_type, Qt))
19601 {
19602 cursor_type = FRAME_DESIRED_CURSOR (f);
19603 *width = FRAME_CURSOR_WIDTH (f);
19604 }
19605 else
19606 cursor_type = get_specified_cursor_type (b->cursor_type, width);
19607
19608 /* Use normal cursor if not blinked off. */
19609 if (!w->cursor_off_p)
f65536fa
KS
19610 {
19611 if (glyph->type == IMAGE_GLYPH) {
19612 if (cursor_type == FILLED_BOX_CURSOR)
19613 cursor_type = HOLLOW_BOX_CURSOR;
19614 }
19615 return cursor_type;
19616 }
fa3c6b4d
KS
19617
19618 /* Cursor is blinked off, so determine how to "toggle" it. */
19619
19620 /* First look for an entry matching the buffer's cursor-type in blink-cursor-alist. */
19621 if ((alt_cursor = Fassoc (b->cursor_type, Vblink_cursor_alist), !NILP (alt_cursor)))
19622 return get_specified_cursor_type (XCDR (alt_cursor), width);
19623
19624 /* Then see if frame has specified a specific blink off cursor type. */
19625 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
19626 {
19627 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
19628 return FRAME_BLINK_OFF_CURSOR (f);
19629 }
19630
a57dd8b1
KS
19631#if 0
19632 /* Some people liked having a permanently visible blinking cursor,
19633 while others had very strong opinions against it. So it was
19634 decided to remove it. KFS 2003-09-03 */
19635
fa3c6b4d
KS
19636 /* Finally perform built-in cursor blinking:
19637 filled box <-> hollow box
19638 wide [h]bar <-> narrow [h]bar
19639 narrow [h]bar <-> no cursor
19640 other type <-> no cursor */
19641
19642 if (cursor_type == FILLED_BOX_CURSOR)
19643 return HOLLOW_BOX_CURSOR;
19644
19645 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
19646 {
19647 *width = 1;
19648 return cursor_type;
19649 }
a57dd8b1 19650#endif
fa3c6b4d
KS
19651
19652 return NO_CURSOR;
19653}
19654
19655
19656#ifdef HAVE_WINDOW_SYSTEM
19657
19658/* Notice when the text cursor of window W has been completely
19659 overwritten by a drawing operation that outputs glyphs in AREA
19660 starting at X0 and ending at X1 in the line starting at Y0 and
19661 ending at Y1. X coordinates are area-relative. X1 < 0 means all
19662 the rest of the line after X0 has been written. Y coordinates
19663 are window-relative. */
19664
19665static void
19666notice_overwritten_cursor (w, area, x0, x1, y0, y1)
19667 struct window *w;
19668 enum glyph_row_area area;
19669 int x0, y0, x1, y1;
19670{
88e6b646
KS
19671 int cx0, cx1, cy0, cy1;
19672 struct glyph_row *row;
fa3c6b4d 19673
88e6b646
KS
19674 if (!w->phys_cursor_on_p)
19675 return;
19676 if (area != TEXT_AREA)
19677 return;
fa3c6b4d 19678
88e6b646
KS
19679 row = w->current_matrix->rows + w->phys_cursor.vpos;
19680 if (!row->displays_text_p)
19681 return;
fa3c6b4d 19682
88e6b646
KS
19683 if (row->cursor_in_fringe_p)
19684 {
19685 row->cursor_in_fringe_p = 0;
19686 draw_fringe_bitmap (w, row, 0);
19687 w->phys_cursor_on_p = 0;
19688 return;
fa3c6b4d 19689 }
88e6b646
KS
19690
19691 cx0 = w->phys_cursor.x;
19692 cx1 = cx0 + w->phys_cursor_width;
19693 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
19694 return;
19695
19696 /* The cursor image will be completely removed from the
19697 screen if the output area intersects the cursor area in
19698 y-direction. When we draw in [y0 y1[, and some part of
19699 the cursor is at y < y0, that part must have been drawn
19700 before. When scrolling, the cursor is erased before
19701 actually scrolling, so we don't come here. When not
19702 scrolling, the rows above the old cursor row must have
19703 changed, and in this case these rows must have written
19704 over the cursor image.
19705
19706 Likewise if part of the cursor is below y1, with the
19707 exception of the cursor being in the first blank row at
19708 the buffer and window end because update_text_area
19709 doesn't draw that row. (Except when it does, but
19710 that's handled in update_text_area.) */
19711
19712 cy0 = w->phys_cursor.y;
19713 cy1 = cy0 + w->phys_cursor_height;
19714 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
19715 return;
19716
19717 w->phys_cursor_on_p = 0;
fa3c6b4d
KS
19718}
19719
19720#endif /* HAVE_WINDOW_SYSTEM */
19721
19722\f
19723/************************************************************************
19724 Mouse Face
19725 ************************************************************************/
19726
19727#ifdef HAVE_WINDOW_SYSTEM
19728
19729/* EXPORT for RIF:
19730 Fix the display of area AREA of overlapping row ROW in window W. */
19731
19732void
19733x_fix_overlapping_area (w, row, area)
19734 struct window *w;
19735 struct glyph_row *row;
19736 enum glyph_row_area area;
19737{
19738 int i, x;
19739
19740 BLOCK_INPUT;
19741
57dd22f4 19742 x = 0;
fa3c6b4d
KS
19743 for (i = 0; i < row->used[area];)
19744 {
19745 if (row->glyphs[area][i].overlaps_vertically_p)
19746 {
19747 int start = i, start_x = x;
19748
19749 do
19750 {
19751 x += row->glyphs[area][i].pixel_width;
19752 ++i;
19753 }
19754 while (i < row->used[area]
19755 && row->glyphs[area][i].overlaps_vertically_p);
19756
19757 draw_glyphs (w, start_x, row, area,
19758 start, i,
19759 DRAW_NORMAL_TEXT, 1);
19760 }
19761 else
19762 {
19763 x += row->glyphs[area][i].pixel_width;
19764 ++i;
19765 }
19766 }
19767
19768 UNBLOCK_INPUT;
19769}
19770
19771
19772/* EXPORT:
19773 Draw the cursor glyph of window W in glyph row ROW. See the
19774 comment of draw_glyphs for the meaning of HL. */
19775
19776void
19777draw_phys_cursor_glyph (w, row, hl)
19778 struct window *w;
19779 struct glyph_row *row;
19780 enum draw_glyphs_face hl;
19781{
19782 /* If cursor hpos is out of bounds, don't draw garbage. This can
19783 happen in mini-buffer windows when switching between echo area
19784 glyphs and mini-buffer. */
19785 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
19786 {
19787 int on_p = w->phys_cursor_on_p;
19788 int x1;
19789 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
19790 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
19791 hl, 0);
19792 w->phys_cursor_on_p = on_p;
19793
fa3c6b4d
KS
19794 if (hl == DRAW_CURSOR)
19795 w->phys_cursor_width = x1 - w->phys_cursor.x;
fa3c6b4d
KS
19796 /* When we erase the cursor, and ROW is overlapped by other
19797 rows, make sure that these overlapping parts of other rows
19798 are redrawn. */
365fa1b3 19799 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
fa3c6b4d
KS
19800 {
19801 if (row > w->current_matrix->rows
19802 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
19803 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
19804
19805 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
19806 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
19807 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
19808 }
19809 }
19810}
19811
19812
19813/* EXPORT:
19814 Erase the image of a cursor of window W from the screen. */
19815
19816void
19817erase_phys_cursor (w)
19818 struct window *w;
19819{
19820 struct frame *f = XFRAME (w->frame);
19821 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
19822 int hpos = w->phys_cursor.hpos;
19823 int vpos = w->phys_cursor.vpos;
19824 int mouse_face_here_p = 0;
19825 struct glyph_matrix *active_glyphs = w->current_matrix;
19826 struct glyph_row *cursor_row;
19827 struct glyph *cursor_glyph;
19828 enum draw_glyphs_face hl;
19829
19830 /* No cursor displayed or row invalidated => nothing to do on the
19831 screen. */
19832 if (w->phys_cursor_type == NO_CURSOR)
19833 goto mark_cursor_off;
19834
19835 /* VPOS >= active_glyphs->nrows means that window has been resized.
19836 Don't bother to erase the cursor. */
19837 if (vpos >= active_glyphs->nrows)
19838 goto mark_cursor_off;
19839
19840 /* If row containing cursor is marked invalid, there is nothing we
19841 can do. */
19842 cursor_row = MATRIX_ROW (active_glyphs, vpos);
19843 if (!cursor_row->enabled_p)
19844 goto mark_cursor_off;
19845
19846 /* If row is completely invisible, don't attempt to delete a cursor which
19847 isn't there. This can happen if cursor is at top of a window, and
19848 we switch to a buffer with a header line in that window. */
19849 if (cursor_row->visible_height <= 0)
19850 goto mark_cursor_off;
19851
88e6b646
KS
19852 /* If cursor is in the fringe, erase by drawing actual bitmap there. */
19853 if (cursor_row->cursor_in_fringe_p)
19854 {
19855 cursor_row->cursor_in_fringe_p = 0;
19856 draw_fringe_bitmap (w, cursor_row, 0);
19857 goto mark_cursor_off;
19858 }
19859
fa3c6b4d
KS
19860 /* This can happen when the new row is shorter than the old one.
19861 In this case, either draw_glyphs or clear_end_of_line
19862 should have cleared the cursor. Note that we wouldn't be
19863 able to erase the cursor in this case because we don't have a
19864 cursor glyph at hand. */
19865 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
19866 goto mark_cursor_off;
19867
19868 /* If the cursor is in the mouse face area, redisplay that when
19869 we clear the cursor. */
19870 if (! NILP (dpyinfo->mouse_face_window)
19871 && w == XWINDOW (dpyinfo->mouse_face_window)
19872 && (vpos > dpyinfo->mouse_face_beg_row
19873 || (vpos == dpyinfo->mouse_face_beg_row
19874 && hpos >= dpyinfo->mouse_face_beg_col))
19875 && (vpos < dpyinfo->mouse_face_end_row
19876 || (vpos == dpyinfo->mouse_face_end_row
19877 && hpos < dpyinfo->mouse_face_end_col))
19878 /* Don't redraw the cursor's spot in mouse face if it is at the
19879 end of a line (on a newline). The cursor appears there, but
19880 mouse highlighting does not. */
19881 && cursor_row->used[TEXT_AREA] > hpos)
19882 mouse_face_here_p = 1;
19883
19884 /* Maybe clear the display under the cursor. */
19885 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
19886 {
19887 int x, y;
da8b7f4f 19888 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
fa3c6b4d
KS
19889
19890 cursor_glyph = get_phys_cursor_glyph (w);
19891 if (cursor_glyph == NULL)
19892 goto mark_cursor_off;
19893
19894 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
19895 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, cursor_row->y));
19896
19897 rif->clear_frame_area (f, x, y,
19898 cursor_glyph->pixel_width, cursor_row->visible_height);
19899 }
19900
19901 /* Erase the cursor by redrawing the character underneath it. */
19902 if (mouse_face_here_p)
19903 hl = DRAW_MOUSE_FACE;
19904 else
19905 hl = DRAW_NORMAL_TEXT;
19906 draw_phys_cursor_glyph (w, cursor_row, hl);
19907
19908 mark_cursor_off:
19909 w->phys_cursor_on_p = 0;
19910 w->phys_cursor_type = NO_CURSOR;
19911}
19912
19913
19914/* EXPORT:
19915 Display or clear cursor of window W. If ON is zero, clear the
19916 cursor. If it is non-zero, display the cursor. If ON is nonzero,
19917 where to put the cursor is specified by HPOS, VPOS, X and Y. */
19918
19919void
19920display_and_set_cursor (w, on, hpos, vpos, x, y)
19921 struct window *w;
19922 int on, hpos, vpos, x, y;
19923{
19924 struct frame *f = XFRAME (w->frame);
19925 int new_cursor_type;
19926 int new_cursor_width;
19927 int active_cursor;
19928 struct glyph_matrix *current_glyphs;
19929 struct glyph_row *glyph_row;
19930 struct glyph *glyph;
19931
19932 /* This is pointless on invisible frames, and dangerous on garbaged
19933 windows and frames; in the latter case, the frame or window may
19934 be in the midst of changing its size, and x and y may be off the
19935 window. */
19936 if (! FRAME_VISIBLE_P (f)
19937 || FRAME_GARBAGED_P (f)
19938 || vpos >= w->current_matrix->nrows
19939 || hpos >= w->current_matrix->matrix_w)
19940 return;
19941
19942 /* If cursor is off and we want it off, return quickly. */
19943 if (!on && !w->phys_cursor_on_p)
19944 return;
19945
19946 current_glyphs = w->current_matrix;
19947 glyph_row = MATRIX_ROW (current_glyphs, vpos);
19948 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
19949
19950 /* If cursor row is not enabled, we don't really know where to
19951 display the cursor. */
19952 if (!glyph_row->enabled_p)
19953 {
19954 w->phys_cursor_on_p = 0;
19955 return;
19956 }
19957
19958 xassert (interrupt_input_blocked);
19959
19960 /* Set new_cursor_type to the cursor we want to be displayed. */
f65536fa
KS
19961 new_cursor_type = get_window_cursor_type (w, glyph,
19962 &new_cursor_width, &active_cursor);
fa3c6b4d
KS
19963
19964 /* If cursor is currently being shown and we don't want it to be or
19965 it is in the wrong place, or the cursor type is not what we want,
19966 erase it. */
19967 if (w->phys_cursor_on_p
19968 && (!on
19969 || w->phys_cursor.x != x
19970 || w->phys_cursor.y != y
19971 || new_cursor_type != w->phys_cursor_type
19972 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
19973 && new_cursor_width != w->phys_cursor_width)))
19974 erase_phys_cursor (w);
19975
19976 /* Don't check phys_cursor_on_p here because that flag is only set
19977 to zero in some cases where we know that the cursor has been
19978 completely erased, to avoid the extra work of erasing the cursor
19979 twice. In other words, phys_cursor_on_p can be 1 and the cursor
19980 still not be visible, or it has only been partly erased. */
19981 if (on)
19982 {
19983 w->phys_cursor_ascent = glyph_row->ascent;
19984 w->phys_cursor_height = glyph_row->height;
19985
19986 /* Set phys_cursor_.* before x_draw_.* is called because some
19987 of them may need the information. */
19988 w->phys_cursor.x = x;
19989 w->phys_cursor.y = glyph_row->y;
19990 w->phys_cursor.hpos = hpos;
19991 w->phys_cursor.vpos = vpos;
19992 }
19993
b4ebbb12
KS
19994 rif->draw_window_cursor (w, glyph_row, x, y,
19995 new_cursor_type, new_cursor_width,
19996 on, active_cursor);
fa3c6b4d
KS
19997}
19998
19999
20000/* Switch the display of W's cursor on or off, according to the value
20001 of ON. */
20002
20003static void
20004update_window_cursor (w, on)
20005 struct window *w;
20006 int on;
20007{
20008 /* Don't update cursor in windows whose frame is in the process
20009 of being deleted. */
20010 if (w->current_matrix)
20011 {
20012 BLOCK_INPUT;
20013 display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
20014 w->phys_cursor.x, w->phys_cursor.y);
20015 UNBLOCK_INPUT;
20016 }
20017}
20018
20019
20020/* Call update_window_cursor with parameter ON_P on all leaf windows
20021 in the window tree rooted at W. */
20022
20023static void
20024update_cursor_in_window_tree (w, on_p)
20025 struct window *w;
20026 int on_p;
20027{
20028 while (w)
20029 {
20030 if (!NILP (w->hchild))
20031 update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
20032 else if (!NILP (w->vchild))
20033 update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
20034 else
20035 update_window_cursor (w, on_p);
20036
20037 w = NILP (w->next) ? 0 : XWINDOW (w->next);
20038 }
20039}
20040
20041
20042/* EXPORT:
20043 Display the cursor on window W, or clear it, according to ON_P.
20044 Don't change the cursor's position. */
20045
20046void
20047x_update_cursor (f, on_p)
20048 struct frame *f;
20049 int on_p;
20050{
20051 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
20052}
20053
20054
20055/* EXPORT:
20056 Clear the cursor of window W to background color, and mark the
20057 cursor as not shown. This is used when the text where the cursor
20058 is is about to be rewritten. */
20059
20060void
20061x_clear_cursor (w)
20062 struct window *w;
20063{
20064 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
20065 update_window_cursor (w, 0);
20066}
20067
20068
20069/* EXPORT:
20070 Display the active region described by mouse_face_* according to DRAW. */
20071
20072void
20073show_mouse_face (dpyinfo, draw)
20074 Display_Info *dpyinfo;
20075 enum draw_glyphs_face draw;
20076{
20077 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
20078 struct frame *f = XFRAME (WINDOW_FRAME (w));
20079
20080 if (/* If window is in the process of being destroyed, don't bother
20081 to do anything. */
20082 w->current_matrix != NULL
20083 /* Don't update mouse highlight if hidden */
20084 && (draw != DRAW_MOUSE_FACE || !dpyinfo->mouse_face_hidden)
20085 /* Recognize when we are called to operate on rows that don't exist
20086 anymore. This can happen when a window is split. */
20087 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
20088 {
20089 int phys_cursor_on_p = w->phys_cursor_on_p;
20090 struct glyph_row *row, *first, *last;
20091
20092 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
20093 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
20094
20095 for (row = first; row <= last && row->enabled_p; ++row)
20096 {
20097 int start_hpos, end_hpos, start_x;
20098
20099 /* For all but the first row, the highlight starts at column 0. */
20100 if (row == first)
20101 {
20102 start_hpos = dpyinfo->mouse_face_beg_col;
20103 start_x = dpyinfo->mouse_face_beg_x;
20104 }
20105 else
20106 {
20107 start_hpos = 0;
20108 start_x = 0;
20109 }
20110
20111 if (row == last)
20112 end_hpos = dpyinfo->mouse_face_end_col;
20113 else
20114 end_hpos = row->used[TEXT_AREA];
20115
20116 if (end_hpos > start_hpos)
20117 {
20118 draw_glyphs (w, start_x, row, TEXT_AREA,
20119 start_hpos, end_hpos,
20120 draw, 0);
20121
20122 row->mouse_face_p
20123 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
20124 }
20125 }
20126
20127 /* When we've written over the cursor, arrange for it to
20128 be displayed again. */
20129 if (phys_cursor_on_p && !w->phys_cursor_on_p)
20130 {
20131 BLOCK_INPUT;
20132 display_and_set_cursor (w, 1,
20133 w->phys_cursor.hpos, w->phys_cursor.vpos,
20134 w->phys_cursor.x, w->phys_cursor.y);
20135 UNBLOCK_INPUT;
20136 }
20137 }
20138
20139 /* Change the mouse cursor. */
20140 if (draw == DRAW_NORMAL_TEXT)
20141 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->text_cursor);
20142 else if (draw == DRAW_MOUSE_FACE)
20143 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->hand_cursor);
20144 else
20145 rif->define_frame_cursor (f, FRAME_X_OUTPUT (f)->nontext_cursor);
20146}
20147
20148/* EXPORT:
20149 Clear out the mouse-highlighted active region.
20150 Redraw it un-highlighted first. Value is non-zero if mouse
20151 face was actually drawn unhighlighted. */
20152
20153int
20154clear_mouse_face (dpyinfo)
20155 Display_Info *dpyinfo;
20156{
20157 int cleared = 0;
20158
20159 if (!NILP (dpyinfo->mouse_face_window))
20160 {
20161 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
20162 cleared = 1;
20163 }
20164
20165 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
20166 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
20167 dpyinfo->mouse_face_window = Qnil;
20168 dpyinfo->mouse_face_overlay = Qnil;
20169 return cleared;
20170}
20171
20172
20173/* EXPORT:
20174 Non-zero if physical cursor of window W is within mouse face. */
20175
20176int
20177cursor_in_mouse_face_p (w)
20178 struct window *w;
20179{
20180 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
20181 int in_mouse_face = 0;
20182
20183 if (WINDOWP (dpyinfo->mouse_face_window)
20184 && XWINDOW (dpyinfo->mouse_face_window) == w)
20185 {
20186 int hpos = w->phys_cursor.hpos;
20187 int vpos = w->phys_cursor.vpos;
20188
20189 if (vpos >= dpyinfo->mouse_face_beg_row
20190 && vpos <= dpyinfo->mouse_face_end_row
20191 && (vpos > dpyinfo->mouse_face_beg_row
20192 || hpos >= dpyinfo->mouse_face_beg_col)
20193 && (vpos < dpyinfo->mouse_face_end_row
20194 || hpos < dpyinfo->mouse_face_end_col
20195 || dpyinfo->mouse_face_past_end))
20196 in_mouse_face = 1;
20197 }
20198
20199 return in_mouse_face;
20200}
20201
20202
20203
20204\f
20205/* Find the glyph matrix position of buffer position CHARPOS in window
20206 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
20207 current glyphs must be up to date. If CHARPOS is above window
20208 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
20209 of last line in W. In the row containing CHARPOS, stop before glyphs
20210 having STOP as object. */
20211
9c3521e0 20212#if 1 /* This is a version of fast_find_position that's more correct
fa3c6b4d
KS
20213 in the presence of hscrolling, for example. I didn't install
20214 it right away because the problem fixed is minor, it failed
20215 in 20.x as well, and I think it's too risky to install
20216 so near the release of 21.1. 2001-09-25 gerd. */
20217
20218static int
20219fast_find_position (w, charpos, hpos, vpos, x, y, stop)
20220 struct window *w;
20221 int charpos;
20222 int *hpos, *vpos, *x, *y;
20223 Lisp_Object stop;
20224{
20225 struct glyph_row *row, *first;
20226 struct glyph *glyph, *end;
b19a5b64 20227 int past_end = 0;
fa3c6b4d
KS
20228
20229 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20230 row = row_containing_pos (w, charpos, first, NULL, 0);
20231 if (row == NULL)
20232 {
20233 if (charpos < MATRIX_ROW_START_CHARPOS (first))
20234 {
20235 *x = *y = *hpos = *vpos = 0;
20236 return 0;
20237 }
20238 else
20239 {
20240 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
20241 past_end = 1;
20242 }
20243 }
20244
20245 *x = row->x;
20246 *y = row->y;
20247 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
20248
20249 glyph = row->glyphs[TEXT_AREA];
20250 end = glyph + row->used[TEXT_AREA];
20251
20252 /* Skip over glyphs not having an object at the start of the row.
20253 These are special glyphs like truncation marks on terminal
20254 frames. */
20255 if (row->displays_text_p)
20256 while (glyph < end
20257 && INTEGERP (glyph->object)
20258 && !EQ (stop, glyph->object)
20259 && glyph->charpos < 0)
20260 {
20261 *x += glyph->pixel_width;
20262 ++glyph;
20263 }
20264
20265 while (glyph < end
20266 && !INTEGERP (glyph->object)
20267 && !EQ (stop, glyph->object)
20268 && (!BUFFERP (glyph->object)
20269 || glyph->charpos < charpos))
20270 {
20271 *x += glyph->pixel_width;
20272 ++glyph;
20273 }
20274
20275 *hpos = glyph - row->glyphs[TEXT_AREA];
20276 return past_end;
20277}
20278
9c3521e0 20279#else /* not 1 */
fa3c6b4d
KS
20280
20281static int
20282fast_find_position (w, pos, hpos, vpos, x, y, stop)
20283 struct window *w;
20284 int pos;
20285 int *hpos, *vpos, *x, *y;
20286 Lisp_Object stop;
20287{
20288 int i;
20289 int lastcol;
20290 int maybe_next_line_p = 0;
20291 int line_start_position;
20292 int yb = window_text_bottom_y (w);
20293 struct glyph_row *row, *best_row;
20294 int row_vpos, best_row_vpos;
20295 int current_x;
20296
20297 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20298 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
20299
20300 while (row->y < yb)
20301 {
20302 if (row->used[TEXT_AREA])
20303 line_start_position = row->glyphs[TEXT_AREA]->charpos;
20304 else
20305 line_start_position = 0;
20306
20307 if (line_start_position > pos)
20308 break;
20309 /* If the position sought is the end of the buffer,
20310 don't include the blank lines at the bottom of the window. */
20311 else if (line_start_position == pos
20312 && pos == BUF_ZV (XBUFFER (w->buffer)))
20313 {
20314 maybe_next_line_p = 1;
20315 break;
20316 }
20317 else if (line_start_position > 0)
20318 {
20319 best_row = row;
20320 best_row_vpos = row_vpos;
20321 }
20322
20323 if (row->y + row->height >= yb)
20324 break;
20325
20326 ++row;
20327 ++row_vpos;
20328 }
20329
20330 /* Find the right column within BEST_ROW. */
20331 lastcol = 0;
20332 current_x = best_row->x;
20333 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
20334 {
20335 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
20336 int charpos = glyph->charpos;
20337
20338 if (BUFFERP (glyph->object))
20339 {
20340 if (charpos == pos)
20341 {
20342 *hpos = i;
20343 *vpos = best_row_vpos;
20344 *x = current_x;
20345 *y = best_row->y;
20346 return 1;
20347 }
20348 else if (charpos > pos)
20349 break;
20350 }
20351 else if (EQ (glyph->object, stop))
20352 break;
20353
20354 if (charpos > 0)
20355 lastcol = i;
20356 current_x += glyph->pixel_width;
20357 }
20358
20359 /* If we're looking for the end of the buffer,
20360 and we didn't find it in the line we scanned,
20361 use the start of the following line. */
20362 if (maybe_next_line_p)
20363 {
20364 ++best_row;
20365 ++best_row_vpos;
20366 lastcol = 0;
20367 current_x = best_row->x;
20368 }
20369
20370 *vpos = best_row_vpos;
20371 *hpos = lastcol + 1;
20372 *x = current_x;
20373 *y = best_row->y;
20374 return 0;
20375}
20376
9c3521e0 20377#endif /* not 1 */
fa3c6b4d
KS
20378
20379
20380/* Find the position of the glyph for position POS in OBJECT in
20381 window W's current matrix, and return in *X, *Y the pixel
20382 coordinates, and return in *HPOS, *VPOS the column/row of the glyph.
20383
20384 RIGHT_P non-zero means return the position of the right edge of the
20385 glyph, RIGHT_P zero means return the left edge position.
20386
20387 If no glyph for POS exists in the matrix, return the position of
20388 the glyph with the next smaller position that is in the matrix, if
20389 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
20390 exists in the matrix, return the position of the glyph with the
20391 next larger position in OBJECT.
20392
20393 Value is non-zero if a glyph was found. */
20394
20395static int
20396fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
20397 struct window *w;
20398 int pos;
20399 Lisp_Object object;
20400 int *hpos, *vpos, *x, *y;
20401 int right_p;
20402{
20403 int yb = window_text_bottom_y (w);
20404 struct glyph_row *r;
20405 struct glyph *best_glyph = NULL;
20406 struct glyph_row *best_row = NULL;
20407 int best_x = 0;
20408
20409 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20410 r->enabled_p && r->y < yb;
20411 ++r)
20412 {
20413 struct glyph *g = r->glyphs[TEXT_AREA];
20414 struct glyph *e = g + r->used[TEXT_AREA];
20415 int gx;
20416
20417 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
20418 if (EQ (g->object, object))
20419 {
20420 if (g->charpos == pos)
20421 {
20422 best_glyph = g;
20423 best_x = gx;
20424 best_row = r;
20425 goto found;
20426 }
20427 else if (best_glyph == NULL
20428 || ((abs (g->charpos - pos)
20429 < abs (best_glyph->charpos - pos))
20430 && (right_p
20431 ? g->charpos < pos
20432 : g->charpos > pos)))
20433 {
20434 best_glyph = g;
20435 best_x = gx;
20436 best_row = r;
20437 }
20438 }
20439 }
20440
20441 found:
20442
20443 if (best_glyph)
20444 {
20445 *x = best_x;
20446 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
20447
20448 if (right_p)
20449 {
20450 *x += best_glyph->pixel_width;
20451 ++*hpos;
20452 }
20453
20454 *y = best_row->y;
20455 *vpos = best_row - w->current_matrix->rows;
20456 }
20457
20458 return best_glyph != NULL;
20459}
20460
20461
493fdc3c
KS
20462/* See if position X, Y is within a hot-spot of an image. */
20463
20464static int
20465on_hot_spot_p (hot_spot, x, y)
20466 Lisp_Object hot_spot;
20467 int x, y;
20468{
20469 if (!CONSP (hot_spot))
20470 return 0;
20471
20472 if (EQ (XCAR (hot_spot), Qrect))
20473 {
20474 /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1)) */
20475 Lisp_Object rect = XCDR (hot_spot);
20476 Lisp_Object tem;
20477 if (!CONSP (rect))
20478 return 0;
20479 if (!CONSP (XCAR (rect)))
20480 return 0;
20481 if (!CONSP (XCDR (rect)))
20482 return 0;
20483 if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem)))
20484 return 0;
20485 if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem)))
20486 return 0;
20487 if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem)))
20488 return 0;
20489 if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem)))
20490 return 0;
20491 return 1;
20492 }
20493 else if (EQ (XCAR (hot_spot), Qcircle))
20494 {
20495 /* CDR is (Center . Radius) = ((x0 . y0) . r) */
20496 Lisp_Object circ = XCDR (hot_spot);
20497 Lisp_Object lr, lx0, ly0;
20498 if (CONSP (circ)
20499 && CONSP (XCAR (circ))
20500 && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr))
20501 && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0))
20502 && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0)))
20503 {
20504 double r = XFLOATINT (lr);
20505 double dx = XINT (lx0) - x;
20506 double dy = XINT (ly0) - y;
20507 return (dx * dx + dy * dy <= r * r);
20508 }
20509 }
20510 else if (EQ (XCAR (hot_spot), Qpoly))
20511 {
20512 /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */
20513 if (VECTORP (XCDR (hot_spot)))
20514 {
20515 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
20516 Lisp_Object *poly = v->contents;
20517 int n = v->size;
20518 int i;
20519 int inside = 0;
20520 Lisp_Object lx, ly;
20521 int x0, y0;
20522
20523 /* Need an even number of coordinates, and at least 3 edges. */
20524 if (n < 6 || n & 1)
20525 return 0;
20526
20527 /* Count edge segments intersecting line from (X,Y) to (X,infinity).
20528 If count is odd, we are inside polygon. Pixels on edges
20529 may or may not be included depending on actual geometry of the
20530 polygon. */
20531 if ((lx = poly[n-2], !INTEGERP (lx))
20532 || (ly = poly[n-1], !INTEGERP (lx)))
20533 return 0;
20534 x0 = XINT (lx), y0 = XINT (ly);
20535 for (i = 0; i < n; i += 2)
20536 {
20537 int x1 = x0, y1 = y0;
20538 if ((lx = poly[i], !INTEGERP (lx))
20539 || (ly = poly[i+1], !INTEGERP (ly)))
20540 return 0;
20541 x0 = XINT (lx), y0 = XINT (ly);
20542
20543 /* Does this segment cross the X line? */
20544 if (x0 >= x)
20545 {
20546 if (x1 >= x)
20547 continue;
20548 }
20549 else if (x1 < x)
20550 continue;
20551 if (y > y0 && y > y1)
20552 continue;
20553 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
20554 inside = !inside;
20555 }
20556 return inside;
20557 }
20558 }
20559 else
20560 return 0;
20561}
20562
20563Lisp_Object
20564find_hot_spot (map, x, y)
20565 Lisp_Object map;
20566 int x, y;
20567{
20568 while (CONSP (map))
20569 {
20570 if (CONSP (XCAR (map))
20571 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
20572 return XCAR (map);
20573 map = XCDR (map);
20574 }
20575
20576 return Qnil;
20577}
20578
20579DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
20580 3, 3, 0,
20581 doc: /* Lookup in image map MAP coordinates X and Y.
20582An image map is an alist where each element has the format (AREA ID PLIST).
20583An AREA is specified as either a rectangle, a circle, or a polygon:
20584A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the
20585pixel coordinates of the upper left and bottom right corners.
20586A circle is a cons (circle . ((x0 . y0) . r)) specifying the center
20587and the radius of the circle; r may be a float or integer.
20588A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the
20589vector describes one corner in the polygon.
20590Returns the alist element for the first matching AREA in MAP. */)
20591 (map, x, y)
20592 Lisp_Object map;
20593 Lisp_Object x, y;
20594{
20595 int ix, iy;
20596 if (NILP (map))
20597 return Qnil;
20598
20599 if (!INTEGERP (x))
20600 wrong_type_argument (Qintegerp, x);
20601 if (!INTEGERP (y))
20602 wrong_type_argument (Qintegerp, y);
20603
20604 return find_hot_spot (map, XINT (x), XINT (y));
20605}
20606
20607
20608/* Display frame CURSOR, optionally using shape defined by POINTER. */
20609static void
20610define_frame_cursor1 (f, cursor, pointer)
20611 struct frame *f;
20612 Cursor cursor;
20613 Lisp_Object pointer;
20614{
20615 if (!NILP (pointer))
20616 {
20617 if (EQ (pointer, Qarrow))
20618 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20619 else if (EQ (pointer, Qhand))
20620 cursor = FRAME_X_OUTPUT (f)->hand_cursor;
20621 else if (EQ (pointer, Qtext))
20622 cursor = FRAME_X_OUTPUT (f)->text_cursor;
20623 else if (EQ (pointer, intern ("hdrag")))
20624 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
20625#ifdef HAVE_X_WINDOWS
20626 else if (EQ (pointer, intern ("vdrag")))
20627 cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
20628#endif
20629 else if (EQ (pointer, intern ("hourglass")))
20630 cursor = FRAME_X_OUTPUT (f)->hourglass_cursor;
20631 else if (EQ (pointer, Qmodeline))
20632 cursor = FRAME_X_OUTPUT (f)->modeline_cursor;
20633 else
20634 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20635 }
20636
20637#ifndef HAVE_CARBON
20638 if (cursor != No_Cursor)
20639#else
20640 if (bcmp (&cursor, &No_Cursor, sizeof (Cursor)))
20641#endif
20642 rif->define_frame_cursor (f, cursor);
20643}
20644
fa3c6b4d
KS
20645/* Take proper action when mouse has moved to the mode or header line
20646 or marginal area AREA of window W, x-position X and y-position Y.
20647 X is relative to the start of the text display area of W, so the
20648 width of bitmap areas and scroll bars must be subtracted to get a
20649 position relative to the start of the mode line. */
20650
20651static void
20652note_mode_line_or_margin_highlight (w, x, y, area)
20653 struct window *w;
20654 int x, y;
20655 enum window_part area;
20656{
20657 struct frame *f = XFRAME (w->frame);
20658 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
f65536fa 20659 Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
493fdc3c 20660 Lisp_Object pointer = Qnil;
349c653e
KS
20661 int charpos, dx, dy, width, height;
20662 Lisp_Object string, object = Qnil;
493fdc3c 20663 Lisp_Object pos, help, image;
fa3c6b4d
KS
20664
20665 if (area == ON_MODE_LINE || area == ON_HEADER_LINE)
349c653e
KS
20666 string = mode_line_string (w, area, &x, &y, &charpos,
20667 &object, &dx, &dy, &width, &height);
fa3c6b4d 20668 else
493fdc3c
KS
20669 {
20670 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
349c653e
KS
20671 string = marginal_area_string (w, area, &x, &y, &charpos,
20672 &object, &dx, &dy, &width, &height);
493fdc3c
KS
20673 }
20674
20675 help = Qnil;
fa3c6b4d 20676
349c653e 20677 if (IMAGEP (object))
493fdc3c
KS
20678 {
20679 Lisp_Object image_map, hotspot;
349c653e 20680 if ((image_map = Fplist_get (XCDR (object), QCmap),
493fdc3c
KS
20681 !NILP (image_map))
20682 && (hotspot = find_hot_spot (image_map, dx, dy),
20683 CONSP (hotspot))
20684 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20685 {
20686 Lisp_Object area_id, plist;
fa3c6b4d 20687
493fdc3c
KS
20688 area_id = XCAR (hotspot);
20689 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20690 If so, we could look for mouse-enter, mouse-leave
20691 properties in PLIST (and do something...). */
20692 if ((plist = XCDR (hotspot), CONSP (plist)))
20693 {
20694 pointer = Fplist_get (plist, Qpointer);
20695 if (NILP (pointer))
20696 pointer = Qhand;
20697 help = Fplist_get (plist, Qhelp_echo);
20698 if (!NILP (help))
20699 {
20700 help_echo_string = help;
20701 /* Is this correct? ++kfs */
20702 XSETWINDOW (help_echo_window, w);
20703 help_echo_object = w->buffer;
20704 help_echo_pos = charpos;
20705 }
20706 }
20707 if (NILP (pointer))
349c653e
KS
20708 pointer = Fplist_get (XCDR (object), QCpointer);
20709 }
20710 }
20711
20712 if (STRINGP (string))
20713 {
20714 pos = make_number (charpos);
20715 /* If we're on a string with `help-echo' text property, arrange
20716 for the help to be displayed. This is done by setting the
20717 global variable help_echo_string to the help string. */
20718 help = Fget_text_property (pos, Qhelp_echo, string);
20719 if (!NILP (help))
20720 {
20721 help_echo_string = help;
20722 XSETWINDOW (help_echo_window, w);
20723 help_echo_object = string;
20724 help_echo_pos = charpos;
20725 }
20726
20727 if (NILP (pointer))
20728 pointer = Fget_text_property (pos, Qpointer, string);
20729
20730 /* Change the mouse pointer according to what is under X/Y. */
20731 if (NILP (pointer) && area == ON_MODE_LINE)
20732 {
20733 Lisp_Object map;
20734 map = Fget_text_property (pos, Qlocal_map, string);
20735 if (!KEYMAPP (map))
20736 map = Fget_text_property (pos, Qkeymap, string);
20737 if (!KEYMAPP (map))
20738 cursor = dpyinfo->vertical_scroll_bar_cursor;
493fdc3c
KS
20739 }
20740 }
20741
20742 define_frame_cursor1 (f, cursor, pointer);
fa3c6b4d
KS
20743}
20744
fa3c6b4d
KS
20745
20746/* EXPORT:
20747 Take proper action when the mouse has moved to position X, Y on
20748 frame F as regards highlighting characters that have mouse-face
20749 properties. Also de-highlighting chars where the mouse was before.
20750 X and Y can be negative or out of range. */
20751
20752void
20753note_mouse_highlight (f, x, y)
20754 struct frame *f;
20755 int x, y;
20756{
20757 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
20758 enum window_part part;
20759 Lisp_Object window;
20760 struct window *w;
20761 Cursor cursor = No_Cursor;
493fdc3c 20762 Lisp_Object pointer = Qnil; /* Takes precedence over cursor! */
fa3c6b4d
KS
20763 struct buffer *b;
20764
20765 /* When a menu is active, don't highlight because this looks odd. */
20766#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI)
20767 if (popup_activated ())
20768 return;
20769#endif
20770
20771 if (NILP (Vmouse_highlight)
20772 || !f->glyphs_initialized_p)
20773 return;
20774
20775 dpyinfo->mouse_face_mouse_x = x;
20776 dpyinfo->mouse_face_mouse_y = y;
20777 dpyinfo->mouse_face_mouse_frame = f;
20778
20779 if (dpyinfo->mouse_face_defer)
20780 return;
20781
20782 if (gc_in_progress)
20783 {
20784 dpyinfo->mouse_face_deferred_gc = 1;
20785 return;
20786 }
20787
20788 /* Which window is that in? */
da8b7f4f 20789 window = window_from_coordinates (f, x, y, &part, 0, 0, 1);
fa3c6b4d
KS
20790
20791 /* If we were displaying active text in another window, clear that. */
20792 if (! EQ (window, dpyinfo->mouse_face_window))
20793 clear_mouse_face (dpyinfo);
20794
20795 /* Not on a window -> return. */
20796 if (!WINDOWP (window))
20797 return;
20798
20799 /* Reset help_echo_string. It will get recomputed below. */
fa3c6b4d
KS
20800 help_echo_string = Qnil;
20801
20802 /* Convert to window-relative pixel coordinates. */
20803 w = XWINDOW (window);
20804 frame_to_window_pixel_xy (w, &x, &y);
20805
20806 /* Handle tool-bar window differently since it doesn't display a
20807 buffer. */
20808 if (EQ (window, f->tool_bar_window))
20809 {
20810 note_tool_bar_highlight (f, x, y);
20811 return;
20812 }
20813
fa3c6b4d
KS
20814 /* Mouse is on the mode, header line or margin? */
20815 if (part == ON_MODE_LINE || part == ON_HEADER_LINE
20816 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
20817 {
20818 note_mode_line_or_margin_highlight (w, x, y, part);
20819 return;
20820 }
fa3c6b4d
KS
20821
20822 if (part == ON_VERTICAL_BORDER)
20823 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
f65536fa
KS
20824 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE)
20825 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
fa3c6b4d
KS
20826 else
20827 cursor = FRAME_X_OUTPUT (f)->text_cursor;
20828
20829 /* Are we in a window whose display is up to date?
20830 And verify the buffer's text has not changed. */
20831 b = XBUFFER (w->buffer);
20832 if (part == ON_TEXT
20833 && EQ (w->window_end_valid, w->buffer)
20834 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
20835 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
20836 {
493fdc3c 20837 int hpos, vpos, pos, i, dx, dy, area;
fa3c6b4d
KS
20838 struct glyph *glyph;
20839 Lisp_Object object;
20840 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
20841 Lisp_Object *overlay_vec = NULL;
20842 int len, noverlays;
20843 struct buffer *obuf;
20844 int obegv, ozv, same_region;
20845
20846 /* Find the glyph under X/Y. */
493fdc3c
KS
20847 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
20848
20849 /* Look for :pointer property on image. */
20850 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
20851 {
20852 struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id);
20853 if (img != NULL && IMAGEP (img->spec))
20854 {
20855 Lisp_Object image_map, hotspot;
20856 if ((image_map = Fplist_get (XCDR (img->spec), QCmap),
20857 !NILP (image_map))
20858 && (hotspot = find_hot_spot (image_map, dx, dy),
20859 CONSP (hotspot))
20860 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
20861 {
20862 Lisp_Object area_id, plist;
20863
20864 area_id = XCAR (hotspot);
20865 /* Could check AREA_ID to see if we enter/leave this hot-spot.
20866 If so, we could look for mouse-enter, mouse-leave
20867 properties in PLIST (and do something...). */
20868 if ((plist = XCDR (hotspot), CONSP (plist)))
20869 {
20870 pointer = Fplist_get (plist, Qpointer);
20871 if (NILP (pointer))
20872 pointer = Qhand;
20873 help_echo_string = Fplist_get (plist, Qhelp_echo);
20874 if (!NILP (help_echo_string))
20875 {
20876 help_echo_window = window;
20877 help_echo_object = glyph->object;
20878 help_echo_pos = glyph->charpos;
20879 }
20880 }
20881 }
20882 if (NILP (pointer))
20883 pointer = Fplist_get (XCDR (img->spec), QCpointer);
20884 }
20885 }
fa3c6b4d
KS
20886
20887 /* Clear mouse face if X/Y not over text. */
20888 if (glyph == NULL
20889 || area != TEXT_AREA
20890 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
20891 {
fa3c6b4d
KS
20892 if (clear_mouse_face (dpyinfo))
20893 cursor = No_Cursor;
493fdc3c
KS
20894 if (NILP (pointer))
20895 {
20896 if (area != TEXT_AREA)
20897 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
20898 else
20899 pointer = Vvoid_text_area_pointer;
20900 }
fa3c6b4d
KS
20901 goto set_cursor;
20902 }
20903
20904 pos = glyph->charpos;
20905 object = glyph->object;
20906 if (!STRINGP (object) && !BUFFERP (object))
20907 goto set_cursor;
20908
20909 /* If we get an out-of-range value, return now; avoid an error. */
20910 if (BUFFERP (object) && pos > BUF_Z (b))
20911 goto set_cursor;
20912
20913 /* Make the window's buffer temporarily current for
20914 overlays_at and compute_char_face. */
20915 obuf = current_buffer;
20916 current_buffer = b;
20917 obegv = BEGV;
20918 ozv = ZV;
20919 BEGV = BEG;
20920 ZV = Z;
20921
20922 /* Is this char mouse-active or does it have help-echo? */
20923 position = make_number (pos);
20924
20925 if (BUFFERP (object))
20926 {
20927 /* Put all the overlays we want in a vector in overlay_vec.
20928 Store the length in len. If there are more than 10, make
20929 enough space for all, and try again. */
20930 len = 10;
20931 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
20932 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
20933 if (noverlays > len)
20934 {
20935 len = noverlays;
20936 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
20937 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
20938 }
20939
20940 /* Sort overlays into increasing priority order. */
20941 noverlays = sort_overlays (overlay_vec, noverlays, w);
20942 }
20943 else
20944 noverlays = 0;
20945
20946 same_region = (EQ (window, dpyinfo->mouse_face_window)
20947 && vpos >= dpyinfo->mouse_face_beg_row
20948 && vpos <= dpyinfo->mouse_face_end_row
20949 && (vpos > dpyinfo->mouse_face_beg_row
20950 || hpos >= dpyinfo->mouse_face_beg_col)
20951 && (vpos < dpyinfo->mouse_face_end_row
20952 || hpos < dpyinfo->mouse_face_end_col
20953 || dpyinfo->mouse_face_past_end));
20954
20955 if (same_region)
20956 cursor = No_Cursor;
20957
20958 /* Check mouse-face highlighting. */
20959 if (! same_region
20960 /* If there exists an overlay with mouse-face overlapping
20961 the one we are currently highlighting, we have to
20962 check if we enter the overlapping overlay, and then
20963 highlight only that. */
20964 || (OVERLAYP (dpyinfo->mouse_face_overlay)
20965 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
20966 {
20967 /* Find the highest priority overlay that has a mouse-face
20968 property. */
20969 overlay = Qnil;
20970 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
20971 {
20972 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
20973 if (!NILP (mouse_face))
20974 overlay = overlay_vec[i];
20975 }
20976
20977 /* If we're actually highlighting the same overlay as
20978 before, there's no need to do that again. */
20979 if (!NILP (overlay)
20980 && EQ (overlay, dpyinfo->mouse_face_overlay))
20981 goto check_help_echo;
20982
20983 dpyinfo->mouse_face_overlay = overlay;
20984
20985 /* Clear the display of the old active region, if any. */
20986 if (clear_mouse_face (dpyinfo))
20987 cursor = No_Cursor;
20988
20989 /* If no overlay applies, get a text property. */
20990 if (NILP (overlay))
20991 mouse_face = Fget_text_property (position, Qmouse_face, object);
20992
20993 /* Handle the overlay case. */
20994 if (!NILP (overlay))
20995 {
20996 /* Find the range of text around this char that
20997 should be active. */
20998 Lisp_Object before, after;
20999 int ignore;
21000
21001 before = Foverlay_start (overlay);
21002 after = Foverlay_end (overlay);
21003 /* Record this as the current active region. */
21004 fast_find_position (w, XFASTINT (before),
21005 &dpyinfo->mouse_face_beg_col,
21006 &dpyinfo->mouse_face_beg_row,
21007 &dpyinfo->mouse_face_beg_x,
21008 &dpyinfo->mouse_face_beg_y, Qnil);
21009
21010 dpyinfo->mouse_face_past_end
21011 = !fast_find_position (w, XFASTINT (after),
21012 &dpyinfo->mouse_face_end_col,
21013 &dpyinfo->mouse_face_end_row,
21014 &dpyinfo->mouse_face_end_x,
21015 &dpyinfo->mouse_face_end_y, Qnil);
21016 dpyinfo->mouse_face_window = window;
21017
21018 dpyinfo->mouse_face_face_id
21019 = face_at_buffer_position (w, pos, 0, 0,
21020 &ignore, pos + 1,
21021 !dpyinfo->mouse_face_hidden);
21022
21023 /* Display it as active. */
21024 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
21025 cursor = No_Cursor;
21026 }
21027 /* Handle the text property case. */
21028 else if (!NILP (mouse_face) && BUFFERP (object))
21029 {
21030 /* Find the range of text around this char that
21031 should be active. */
21032 Lisp_Object before, after, beginning, end;
21033 int ignore;
21034
21035 beginning = Fmarker_position (w->start);
21036 end = make_number (BUF_Z (XBUFFER (object))
21037 - XFASTINT (w->window_end_pos));
21038 before
21039 = Fprevious_single_property_change (make_number (pos + 1),
21040 Qmouse_face,
21041 object, beginning);
21042 after
21043 = Fnext_single_property_change (position, Qmouse_face,
21044 object, end);
21045
21046 /* Record this as the current active region. */
21047 fast_find_position (w, XFASTINT (before),
21048 &dpyinfo->mouse_face_beg_col,
21049 &dpyinfo->mouse_face_beg_row,
21050 &dpyinfo->mouse_face_beg_x,
21051 &dpyinfo->mouse_face_beg_y, Qnil);
21052 dpyinfo->mouse_face_past_end
21053 = !fast_find_position (w, XFASTINT (after),
21054 &dpyinfo->mouse_face_end_col,
21055 &dpyinfo->mouse_face_end_row,
21056 &dpyinfo->mouse_face_end_x,
21057 &dpyinfo->mouse_face_end_y, Qnil);
21058 dpyinfo->mouse_face_window = window;
21059
21060 if (BUFFERP (object))
21061 dpyinfo->mouse_face_face_id
21062 = face_at_buffer_position (w, pos, 0, 0,
21063 &ignore, pos + 1,
21064 !dpyinfo->mouse_face_hidden);
21065
21066 /* Display it as active. */
21067 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
21068 cursor = No_Cursor;
21069 }
21070 else if (!NILP (mouse_face) && STRINGP (object))
21071 {
21072 Lisp_Object b, e;
21073 int ignore;
21074
21075 b = Fprevious_single_property_change (make_number (pos + 1),
21076 Qmouse_face,
21077 object, Qnil);
21078 e = Fnext_single_property_change (position, Qmouse_face,
21079 object, Qnil);
21080 if (NILP (b))
21081 b = make_number (0);
21082 if (NILP (e))
21083 e = make_number (SCHARS (object) - 1);
21084 fast_find_string_pos (w, XINT (b), object,
21085 &dpyinfo->mouse_face_beg_col,
21086 &dpyinfo->mouse_face_beg_row,
21087 &dpyinfo->mouse_face_beg_x,
21088 &dpyinfo->mouse_face_beg_y, 0);
21089 fast_find_string_pos (w, XINT (e), object,
21090 &dpyinfo->mouse_face_end_col,
21091 &dpyinfo->mouse_face_end_row,
21092 &dpyinfo->mouse_face_end_x,
21093 &dpyinfo->mouse_face_end_y, 1);
21094 dpyinfo->mouse_face_past_end = 0;
21095 dpyinfo->mouse_face_window = window;
21096 dpyinfo->mouse_face_face_id
21097 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
21098 glyph->face_id, 1);
21099 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
21100 cursor = No_Cursor;
21101 }
21102 else if (STRINGP (object) && NILP (mouse_face))
21103 {
21104 /* A string which doesn't have mouse-face, but
21105 the text ``under'' it might have. */
21106 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
21107 int start = MATRIX_ROW_START_CHARPOS (r);
21108
21109 pos = string_buffer_position (w, object, start);
21110 if (pos > 0)
21111 mouse_face = get_char_property_and_overlay (make_number (pos),
21112 Qmouse_face,
21113 w->buffer,
21114 &overlay);
21115 if (!NILP (mouse_face) && !NILP (overlay))
21116 {
21117 Lisp_Object before = Foverlay_start (overlay);
21118 Lisp_Object after = Foverlay_end (overlay);
21119 int ignore;
21120
21121 /* Note that we might not be able to find position
21122 BEFORE in the glyph matrix if the overlay is
21123 entirely covered by a `display' property. In
21124 this case, we overshoot. So let's stop in
21125 the glyph matrix before glyphs for OBJECT. */
21126 fast_find_position (w, XFASTINT (before),
21127 &dpyinfo->mouse_face_beg_col,
21128 &dpyinfo->mouse_face_beg_row,
21129 &dpyinfo->mouse_face_beg_x,
21130 &dpyinfo->mouse_face_beg_y,
21131 object);
21132
21133 dpyinfo->mouse_face_past_end
21134 = !fast_find_position (w, XFASTINT (after),
21135 &dpyinfo->mouse_face_end_col,
21136 &dpyinfo->mouse_face_end_row,
21137 &dpyinfo->mouse_face_end_x,
21138 &dpyinfo->mouse_face_end_y,
21139 Qnil);
21140 dpyinfo->mouse_face_window = window;
21141 dpyinfo->mouse_face_face_id
21142 = face_at_buffer_position (w, pos, 0, 0,
21143 &ignore, pos + 1,
21144 !dpyinfo->mouse_face_hidden);
21145
21146 /* Display it as active. */
21147 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
21148 cursor = No_Cursor;
21149 }
21150 }
21151 }
21152
21153 check_help_echo:
21154
21155 /* Look for a `help-echo' property. */
493fdc3c 21156 if (NILP (help_echo_string)) {
fa3c6b4d
KS
21157 Lisp_Object help, overlay;
21158
21159 /* Check overlays first. */
21160 help = overlay = Qnil;
21161 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
21162 {
21163 overlay = overlay_vec[i];
21164 help = Foverlay_get (overlay, Qhelp_echo);
21165 }
21166
21167 if (!NILP (help))
21168 {
21169 help_echo_string = help;
21170 help_echo_window = window;
21171 help_echo_object = overlay;
21172 help_echo_pos = pos;
21173 }
21174 else
21175 {
21176 Lisp_Object object = glyph->object;
21177 int charpos = glyph->charpos;
21178
21179 /* Try text properties. */
21180 if (STRINGP (object)
21181 && charpos >= 0
21182 && charpos < SCHARS (object))
21183 {
21184 help = Fget_text_property (make_number (charpos),
21185 Qhelp_echo, object);
21186 if (NILP (help))
21187 {
21188 /* If the string itself doesn't specify a help-echo,
21189 see if the buffer text ``under'' it does. */
21190 struct glyph_row *r
21191 = MATRIX_ROW (w->current_matrix, vpos);
21192 int start = MATRIX_ROW_START_CHARPOS (r);
21193 int pos = string_buffer_position (w, object, start);
21194 if (pos > 0)
21195 {
21196 help = Fget_char_property (make_number (pos),
21197 Qhelp_echo, w->buffer);
21198 if (!NILP (help))
21199 {
21200 charpos = pos;
21201 object = w->buffer;
21202 }
21203 }
21204 }
21205 }
21206 else if (BUFFERP (object)
21207 && charpos >= BEGV
21208 && charpos < ZV)
21209 help = Fget_text_property (make_number (charpos), Qhelp_echo,
21210 object);
21211
21212 if (!NILP (help))
21213 {
21214 help_echo_string = help;
21215 help_echo_window = window;
21216 help_echo_object = object;
21217 help_echo_pos = charpos;
21218 }
21219 }
21220 }
21221
493fdc3c
KS
21222 /* Look for a `pointer' property. */
21223 if (NILP (pointer))
21224 {
21225 /* Check overlays first. */
21226 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
21227 pointer = Foverlay_get (overlay_vec[i], Qpointer);
21228
21229 if (NILP (pointer))
21230 {
21231 Lisp_Object object = glyph->object;
21232 int charpos = glyph->charpos;
21233
21234 /* Try text properties. */
21235 if (STRINGP (object)
21236 && charpos >= 0
21237 && charpos < SCHARS (object))
21238 {
21239 pointer = Fget_text_property (make_number (charpos),
21240 Qpointer, object);
21241 if (NILP (pointer))
21242 {
21243 /* If the string itself doesn't specify a pointer,
21244 see if the buffer text ``under'' it does. */
21245 struct glyph_row *r
21246 = MATRIX_ROW (w->current_matrix, vpos);
21247 int start = MATRIX_ROW_START_CHARPOS (r);
21248 int pos = string_buffer_position (w, object, start);
21249 if (pos > 0)
21250 pointer = Fget_char_property (make_number (pos),
21251 Qpointer, w->buffer);
21252 }
21253 }
21254 else if (BUFFERP (object)
21255 && charpos >= BEGV
21256 && charpos < ZV)
21257 pointer = Fget_text_property (make_number (charpos),
21258 Qpointer, object);
21259 }
21260 }
21261
fa3c6b4d
KS
21262 BEGV = obegv;
21263 ZV = ozv;
21264 current_buffer = obuf;
21265 }
21266
21267 set_cursor:
21268
493fdc3c 21269 define_frame_cursor1 (f, cursor, pointer);
fa3c6b4d
KS
21270}
21271
21272
21273/* EXPORT for RIF:
21274 Clear any mouse-face on window W. This function is part of the
21275 redisplay interface, and is called from try_window_id and similar
21276 functions to ensure the mouse-highlight is off. */
21277
21278void
21279x_clear_window_mouse_face (w)
21280 struct window *w;
21281{
21282 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (XFRAME (w->frame));
21283 Lisp_Object window;
21284
21285 BLOCK_INPUT;
21286 XSETWINDOW (window, w);
21287 if (EQ (window, dpyinfo->mouse_face_window))
21288 clear_mouse_face (dpyinfo);
21289 UNBLOCK_INPUT;
21290}
21291
21292
21293/* EXPORT:
21294 Just discard the mouse face information for frame F, if any.
21295 This is used when the size of F is changed. */
21296
21297void
21298cancel_mouse_face (f)
21299 struct frame *f;
21300{
21301 Lisp_Object window;
21302 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
21303
21304 window = dpyinfo->mouse_face_window;
21305 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
21306 {
21307 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
21308 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
21309 dpyinfo->mouse_face_window = Qnil;
21310 }
21311}
21312
21313
21314#endif /* HAVE_WINDOW_SYSTEM */
21315
21316\f
21317/***********************************************************************
21318 Exposure Events
21319 ***********************************************************************/
21320
21321#ifdef HAVE_WINDOW_SYSTEM
21322
21323/* Redraw the part of glyph row area AREA of glyph row ROW on window W
21324 which intersects rectangle R. R is in window-relative coordinates. */
21325
21326static void
21327expose_area (w, row, r, area)
21328 struct window *w;
21329 struct glyph_row *row;
21330 XRectangle *r;
21331 enum glyph_row_area area;
21332{
21333 struct glyph *first = row->glyphs[area];
21334 struct glyph *end = row->glyphs[area] + row->used[area];
21335 struct glyph *last;
21336 int first_x, start_x, x;
21337
21338 if (area == TEXT_AREA && row->fill_line_p)
21339 /* If row extends face to end of line write the whole line. */
21340 draw_glyphs (w, 0, row, area,
21341 0, row->used[area],
21342 DRAW_NORMAL_TEXT, 0);
21343 else
21344 {
21345 /* Set START_X to the window-relative start position for drawing glyphs of
21346 AREA. The first glyph of the text area can be partially visible.
21347 The first glyphs of other areas cannot. */
da8b7f4f 21348 start_x = window_box_left_offset (w, area);
fa3c6b4d 21349 x = start_x;
29b3ea63
KS
21350 if (area == TEXT_AREA)
21351 x += row->x;
fa3c6b4d
KS
21352
21353 /* Find the first glyph that must be redrawn. */
21354 while (first < end
21355 && x + first->pixel_width < r->x)
21356 {
21357 x += first->pixel_width;
21358 ++first;
21359 }
21360
21361 /* Find the last one. */
21362 last = first;
21363 first_x = x;
21364 while (last < end
21365 && x < r->x + r->width)
21366 {
21367 x += last->pixel_width;
21368 ++last;
21369 }
21370
21371 /* Repaint. */
21372 if (last > first)
21373 draw_glyphs (w, first_x - start_x, row, area,
21374 first - row->glyphs[area], last - row->glyphs[area],
21375 DRAW_NORMAL_TEXT, 0);
21376 }
21377}
21378
21379
21380/* Redraw the parts of the glyph row ROW on window W intersecting
21381 rectangle R. R is in window-relative coordinates. Value is
21382 non-zero if mouse-face was overwritten. */
21383
21384static int
21385expose_line (w, row, r)
21386 struct window *w;
21387 struct glyph_row *row;
21388 XRectangle *r;
21389{
21390 xassert (row->enabled_p);
21391
21392 if (row->mode_line_p || w->pseudo_window_p)
21393 draw_glyphs (w, 0, row, TEXT_AREA,
21394 0, row->used[TEXT_AREA],
21395 DRAW_NORMAL_TEXT, 0);
21396 else
21397 {
21398 if (row->used[LEFT_MARGIN_AREA])
21399 expose_area (w, row, r, LEFT_MARGIN_AREA);
21400 if (row->used[TEXT_AREA])
21401 expose_area (w, row, r, TEXT_AREA);
21402 if (row->used[RIGHT_MARGIN_AREA])
21403 expose_area (w, row, r, RIGHT_MARGIN_AREA);
21404 draw_row_fringe_bitmaps (w, row);
cfe03a41
KS
21405 }
21406
fa3c6b4d
KS
21407 return row->mouse_face_p;
21408}
21409
21410
21411/* Redraw those parts of glyphs rows during expose event handling that
21412 overlap other rows. Redrawing of an exposed line writes over parts
21413 of lines overlapping that exposed line; this function fixes that.
21414
21415 W is the window being exposed. FIRST_OVERLAPPING_ROW is the first
21416 row in W's current matrix that is exposed and overlaps other rows.
21417 LAST_OVERLAPPING_ROW is the last such row. */
21418
21419static void
21420expose_overlaps (w, first_overlapping_row, last_overlapping_row)
21421 struct window *w;
21422 struct glyph_row *first_overlapping_row;
21423 struct glyph_row *last_overlapping_row;
21424{
21425 struct glyph_row *row;
21426
21427 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
21428 if (row->overlapping_p)
21429 {
21430 xassert (row->enabled_p && !row->mode_line_p);
21431
21432 if (row->used[LEFT_MARGIN_AREA])
21433 x_fix_overlapping_area (w, row, LEFT_MARGIN_AREA);
cfe03a41 21434
fa3c6b4d
KS
21435 if (row->used[TEXT_AREA])
21436 x_fix_overlapping_area (w, row, TEXT_AREA);
21437
21438 if (row->used[RIGHT_MARGIN_AREA])
21439 x_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA);
21440 }
21441}
21442
21443
21444/* Return non-zero if W's cursor intersects rectangle R. */
21445
21446static int
21447phys_cursor_in_rect_p (w, r)
21448 struct window *w;
21449 XRectangle *r;
21450{
21451 XRectangle cr, result;
21452 struct glyph *cursor_glyph;
21453
21454 cursor_glyph = get_phys_cursor_glyph (w);
21455 if (cursor_glyph)
cfe03a41 21456 {
aecf50d2
KS
21457 /* r is relative to W's box, but w->phys_cursor.x is relative
21458 to left edge of W's TEXT area. Adjust it. */
21459 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
fa3c6b4d
KS
21460 cr.y = w->phys_cursor.y;
21461 cr.width = cursor_glyph->pixel_width;
21462 cr.height = w->phys_cursor_height;
21463 /* ++KFS: W32 version used W32-specific IntersectRect here, but
21464 I assume the effect is the same -- and this is portable. */
21465 return x_intersect_rectangles (&cr, r, &result);
cfe03a41 21466 }
fa3c6b4d
KS
21467 else
21468 return 0;
21469}
cfe03a41 21470
cfe03a41 21471
fa3c6b4d
KS
21472/* EXPORT:
21473 Draw a vertical window border to the right of window W if W doesn't
21474 have vertical scroll bars. */
cfe03a41 21475
cfe03a41 21476void
fa3c6b4d
KS
21477x_draw_vertical_border (w)
21478 struct window *w;
cfe03a41 21479{
da8b7f4f
KS
21480 /* We could do better, if we knew what type of scroll-bar the adjacent
21481 windows (on either side) have... But we don't :-(
21482 However, I think this works ok. ++KFS 2003-04-25 */
21483
fa3c6b4d
KS
21484 /* Redraw borders between horizontally adjacent windows. Don't
21485 do it for frames with vertical scroll bars because either the
21486 right scroll bar of a window, or the left scroll bar of its
21487 neighbor will suffice as a border. */
21488 if (!WINDOW_RIGHTMOST_P (w)
da8b7f4f 21489 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
fa3c6b4d
KS
21490 {
21491 int x0, x1, y0, y1;
cfe03a41 21492
fa3c6b4d 21493 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
fa3c6b4d 21494 y1 -= 1;
cfe03a41 21495
fa3c6b4d 21496 rif->draw_vertical_window_border (w, x1, y0, y1);
cfe03a41 21497 }
da8b7f4f
KS
21498 else if (!WINDOW_LEFTMOST_P (w)
21499 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
21500 {
21501 int x0, x1, y0, y1;
21502
21503 window_box_edges (w, -1, &x0, &y0, &x1, &y1);
21504 y1 -= 1;
21505
21506 rif->draw_vertical_window_border (w, x0, y0, y1);
21507 }
cfe03a41
KS
21508}
21509
21510
fa3c6b4d
KS
21511/* Redraw the part of window W intersection rectangle FR. Pixel
21512 coordinates in FR are frame-relative. Call this function with
21513 input blocked. Value is non-zero if the exposure overwrites
21514 mouse-face. */
cfe03a41 21515
fa3c6b4d
KS
21516static int
21517expose_window (w, fr)
cfe03a41 21518 struct window *w;
fa3c6b4d 21519 XRectangle *fr;
cfe03a41
KS
21520{
21521 struct frame *f = XFRAME (w->frame);
fa3c6b4d
KS
21522 XRectangle wr, r;
21523 int mouse_face_overwritten_p = 0;
21524
21525 /* If window is not yet fully initialized, do nothing. This can
21526 happen when toolkit scroll bars are used and a window is split.
21527 Reconfiguring the scroll bar will generate an expose for a newly
21528 created window. */
21529 if (w->current_matrix == NULL)
21530 return 0;
cfe03a41 21531
fa3c6b4d
KS
21532 /* When we're currently updating the window, display and current
21533 matrix usually don't agree. Arrange for a thorough display
21534 later. */
21535 if (w == updated_window)
21536 {
21537 SET_FRAME_GARBAGED (f);
21538 return 0;
21539 }
e9c99027 21540
fa3c6b4d 21541 /* Frame-relative pixel rectangle of W. */
da8b7f4f
KS
21542 wr.x = WINDOW_LEFT_EDGE_X (w);
21543 wr.y = WINDOW_TOP_EDGE_Y (w);
21544 wr.width = WINDOW_TOTAL_WIDTH (w);
21545 wr.height = WINDOW_TOTAL_HEIGHT (w);
fa3c6b4d
KS
21546
21547 if (x_intersect_rectangles (fr, &wr, &r))
cfe03a41 21548 {
fa3c6b4d
KS
21549 int yb = window_text_bottom_y (w);
21550 struct glyph_row *row;
21551 int cursor_cleared_p;
21552 struct glyph_row *first_overlapping_row, *last_overlapping_row;
21553
21554 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
21555 r.x, r.y, r.width, r.height));
21556
21557 /* Convert to window coordinates. */
cc8549df
KS
21558 r.x -= WINDOW_LEFT_EDGE_X (w);
21559 r.y -= WINDOW_TOP_EDGE_Y (w);
fa3c6b4d
KS
21560
21561 /* Turn off the cursor. */
21562 if (!w->pseudo_window_p
21563 && phys_cursor_in_rect_p (w, &r))
cfe03a41 21564 {
fa3c6b4d
KS
21565 x_clear_cursor (w);
21566 cursor_cleared_p = 1;
cfe03a41 21567 }
fa3c6b4d
KS
21568 else
21569 cursor_cleared_p = 0;
cfe03a41 21570
fa3c6b4d
KS
21571 /* Update lines intersecting rectangle R. */
21572 first_overlapping_row = last_overlapping_row = NULL;
21573 for (row = w->current_matrix->rows;
21574 row->enabled_p;
21575 ++row)
21576 {
21577 int y0 = row->y;
21578 int y1 = MATRIX_ROW_BOTTOM_Y (row);
cfe03a41 21579
fa3c6b4d
KS
21580 if ((y0 >= r.y && y0 < r.y + r.height)
21581 || (y1 > r.y && y1 < r.y + r.height)
21582 || (r.y >= y0 && r.y < y1)
21583 || (r.y + r.height > y0 && r.y + r.height < y1))
21584 {
21585 if (row->overlapping_p)
21586 {
21587 if (first_overlapping_row == NULL)
21588 first_overlapping_row = row;
21589 last_overlapping_row = row;
21590 }
e9c99027 21591
fa3c6b4d
KS
21592 if (expose_line (w, row, &r))
21593 mouse_face_overwritten_p = 1;
21594 }
cfe03a41 21595
fa3c6b4d
KS
21596 if (y1 >= yb)
21597 break;
21598 }
cfe03a41 21599
fa3c6b4d
KS
21600 /* Display the mode line if there is one. */
21601 if (WINDOW_WANTS_MODELINE_P (w)
21602 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
21603 row->enabled_p)
21604 && row->y < r.y + r.height)
21605 {
21606 if (expose_line (w, row, &r))
21607 mouse_face_overwritten_p = 1;
21608 }
cfe03a41 21609
fa3c6b4d
KS
21610 if (!w->pseudo_window_p)
21611 {
21612 /* Fix the display of overlapping rows. */
21613 if (first_overlapping_row)
21614 expose_overlaps (w, first_overlapping_row, last_overlapping_row);
21615
21616 /* Draw border between windows. */
21617 x_draw_vertical_border (w);
21618
21619 /* Turn the cursor on again. */
21620 if (cursor_cleared_p)
21621 update_window_cursor (w, 1);
21622 }
21623 }
21624
21625#ifdef HAVE_CARBON
21626 /* Display scroll bar for this window. */
21627 if (!NILP (w->vertical_scroll_bar))
cfe03a41 21628 {
fa3c6b4d
KS
21629 /* ++KFS:
21630 If this doesn't work here (maybe some header files are missing),
21631 make a function in macterm.c and call it to do the job! */
21632 ControlHandle ch
21633 = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
21634
21635 Draw1Control (ch);
cfe03a41 21636 }
fa3c6b4d 21637#endif
cfe03a41 21638
fa3c6b4d
KS
21639 return mouse_face_overwritten_p;
21640}
21641
21642
21643
21644/* Redraw (parts) of all windows in the window tree rooted at W that
21645 intersect R. R contains frame pixel coordinates. Value is
21646 non-zero if the exposure overwrites mouse-face. */
21647
21648static int
21649expose_window_tree (w, r)
21650 struct window *w;
21651 XRectangle *r;
21652{
21653 struct frame *f = XFRAME (w->frame);
21654 int mouse_face_overwritten_p = 0;
21655
21656 while (w && !FRAME_GARBAGED_P (f))
cfe03a41 21657 {
fa3c6b4d
KS
21658 if (!NILP (w->hchild))
21659 mouse_face_overwritten_p
21660 |= expose_window_tree (XWINDOW (w->hchild), r);
21661 else if (!NILP (w->vchild))
21662 mouse_face_overwritten_p
21663 |= expose_window_tree (XWINDOW (w->vchild), r);
21664 else
21665 mouse_face_overwritten_p |= expose_window (w, r);
21666
21667 w = NILP (w->next) ? NULL : XWINDOW (w->next);
cfe03a41 21668 }
cfe03a41 21669
fa3c6b4d
KS
21670 return mouse_face_overwritten_p;
21671}
cfe03a41 21672
cfe03a41 21673
fa3c6b4d
KS
21674/* EXPORT:
21675 Redisplay an exposed area of frame F. X and Y are the upper-left
21676 corner of the exposed rectangle. W and H are width and height of
21677 the exposed area. All are pixel values. W or H zero means redraw
21678 the entire frame. */
cfe03a41 21679
fa3c6b4d
KS
21680void
21681expose_frame (f, x, y, w, h)
21682 struct frame *f;
21683 int x, y, w, h;
21684{
21685 XRectangle r;
21686 int mouse_face_overwritten_p = 0;
21687
21688 TRACE ((stderr, "expose_frame "));
21689
21690 /* No need to redraw if frame will be redrawn soon. */
21691 if (FRAME_GARBAGED_P (f))
cfe03a41 21692 {
fa3c6b4d
KS
21693 TRACE ((stderr, " garbaged\n"));
21694 return;
cfe03a41 21695 }
7d0393cf 21696
fa3c6b4d
KS
21697#ifdef HAVE_CARBON
21698 /* MAC_TODO: this is a kludge, but if scroll bars are not activated
21699 or deactivated here, for unknown reasons, activated scroll bars
21700 are shown in deactivated frames in some instances. */
21701 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
21702 activate_scroll_bars (f);
21703 else
21704 deactivate_scroll_bars (f);
21705#endif
cfe03a41 21706
fa3c6b4d
KS
21707 /* If basic faces haven't been realized yet, there is no point in
21708 trying to redraw anything. This can happen when we get an expose
21709 event while Emacs is starting, e.g. by moving another window. */
21710 if (FRAME_FACE_CACHE (f) == NULL
21711 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
21712 {
21713 TRACE ((stderr, " no faces\n"));
21714 return;
21715 }
cfe03a41 21716
fa3c6b4d 21717 if (w == 0 || h == 0)
cfe03a41 21718 {
fa3c6b4d 21719 r.x = r.y = 0;
da8b7f4f
KS
21720 r.width = FRAME_COLUMN_WIDTH (f) * FRAME_COLS (f);
21721 r.height = FRAME_LINE_HEIGHT (f) * FRAME_LINES (f);
fa3c6b4d
KS
21722 }
21723 else
21724 {
21725 r.x = x;
21726 r.y = y;
21727 r.width = w;
21728 r.height = h;
cfe03a41
KS
21729 }
21730
fa3c6b4d
KS
21731 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.x, r.y, r.width, r.height));
21732 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
21733
21734 if (WINDOWP (f->tool_bar_window))
21735 mouse_face_overwritten_p
21736 |= expose_window (XWINDOW (f->tool_bar_window), &r);
21737
21738#ifdef HAVE_X_WINDOWS
21739#ifndef MSDOS
21740#ifndef USE_X_TOOLKIT
21741 if (WINDOWP (f->menu_bar_window))
21742 mouse_face_overwritten_p
21743 |= expose_window (XWINDOW (f->menu_bar_window), &r);
21744#endif /* not USE_X_TOOLKIT */
21745#endif
21746#endif
21747
21748 /* Some window managers support a focus-follows-mouse style with
21749 delayed raising of frames. Imagine a partially obscured frame,
21750 and moving the mouse into partially obscured mouse-face on that
21751 frame. The visible part of the mouse-face will be highlighted,
21752 then the WM raises the obscured frame. With at least one WM, KDE
21753 2.1, Emacs is not getting any event for the raising of the frame
21754 (even tried with SubstructureRedirectMask), only Expose events.
21755 These expose events will draw text normally, i.e. not
21756 highlighted. Which means we must redo the highlight here.
21757 Subsume it under ``we love X''. --gerd 2001-08-15 */
21758 /* Included in Windows version because Windows most likely does not
21759 do the right thing if any third party tool offers
21760 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
21761 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
21762 {
21763 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
21764 if (f == dpyinfo->mouse_face_mouse_frame)
21765 {
21766 int x = dpyinfo->mouse_face_mouse_x;
21767 int y = dpyinfo->mouse_face_mouse_y;
21768 clear_mouse_face (dpyinfo);
21769 note_mouse_highlight (f, x, y);
21770 }
21771 }
cfe03a41
KS
21772}
21773
133c764e 21774
fa3c6b4d
KS
21775/* EXPORT:
21776 Determine the intersection of two rectangles R1 and R2. Return
21777 the intersection in *RESULT. Value is non-zero if RESULT is not
21778 empty. */
133c764e 21779
fa3c6b4d
KS
21780int
21781x_intersect_rectangles (r1, r2, result)
21782 XRectangle *r1, *r2, *result;
133c764e 21783{
fa3c6b4d
KS
21784 XRectangle *left, *right;
21785 XRectangle *upper, *lower;
21786 int intersection_p = 0;
21787
21788 /* Rearrange so that R1 is the left-most rectangle. */
21789 if (r1->x < r2->x)
21790 left = r1, right = r2;
21791 else
21792 left = r2, right = r1;
21793
21794 /* X0 of the intersection is right.x0, if this is inside R1,
21795 otherwise there is no intersection. */
21796 if (right->x <= left->x + left->width)
133c764e 21797 {
fa3c6b4d 21798 result->x = right->x;
133c764e 21799
fa3c6b4d
KS
21800 /* The right end of the intersection is the minimum of the
21801 the right ends of left and right. */
21802 result->width = (min (left->x + left->width, right->x + right->width)
21803 - result->x);
133c764e 21804
fa3c6b4d
KS
21805 /* Same game for Y. */
21806 if (r1->y < r2->y)
21807 upper = r1, lower = r2;
21808 else
21809 upper = r2, lower = r1;
133c764e 21810
fa3c6b4d
KS
21811 /* The upper end of the intersection is lower.y0, if this is inside
21812 of upper. Otherwise, there is no intersection. */
21813 if (lower->y <= upper->y + upper->height)
21814 {
21815 result->y = lower->y;
21816
21817 /* The lower end of the intersection is the minimum of the lower
21818 ends of upper and lower. */
21819 result->height = (min (lower->y + lower->height,
21820 upper->y + upper->height)
21821 - result->y);
21822 intersection_p = 1;
133c764e
KS
21823 }
21824 }
fa3c6b4d
KS
21825
21826 return intersection_p;
133c764e
KS
21827}
21828
fa3c6b4d
KS
21829#endif /* HAVE_WINDOW_SYSTEM */
21830
cfe03a41 21831\f
5f5c8ee5
GM
21832/***********************************************************************
21833 Initialization
21834 ***********************************************************************/
21835
a2889657
JB
21836void
21837syms_of_xdisp ()
21838{
c6e89d6c
GM
21839 Vwith_echo_area_save_vector = Qnil;
21840 staticpro (&Vwith_echo_area_save_vector);
5f5c8ee5 21841
c6e89d6c
GM
21842 Vmessage_stack = Qnil;
21843 staticpro (&Vmessage_stack);
2311178e 21844
735c094c 21845 Qinhibit_redisplay = intern ("inhibit-redisplay");
c6e89d6c 21846 staticpro (&Qinhibit_redisplay);
735c094c 21847
b14bc55e
RS
21848 message_dolog_marker1 = Fmake_marker ();
21849 staticpro (&message_dolog_marker1);
21850 message_dolog_marker2 = Fmake_marker ();
21851 staticpro (&message_dolog_marker2);
21852 message_dolog_marker3 = Fmake_marker ();
21853 staticpro (&message_dolog_marker3);
21854
5f5c8ee5 21855#if GLYPH_DEBUG
7d4cc828 21856 defsubr (&Sdump_frame_glyph_matrix);
5f5c8ee5
GM
21857 defsubr (&Sdump_glyph_matrix);
21858 defsubr (&Sdump_glyph_row);
e037b9ec 21859 defsubr (&Sdump_tool_bar_row);
62397849 21860 defsubr (&Strace_redisplay);
bf9249e3 21861 defsubr (&Strace_to_stderr);
5f5c8ee5 21862#endif
99a5de87 21863#ifdef HAVE_WINDOW_SYSTEM
57c28064 21864 defsubr (&Stool_bar_lines_needed);
493fdc3c 21865 defsubr (&Slookup_image_map);
99a5de87 21866#endif
8143e6ab 21867 defsubr (&Sformat_mode_line);
5f5c8ee5 21868
cf074754
RS
21869 staticpro (&Qmenu_bar_update_hook);
21870 Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
21871
d46fb96a 21872 staticpro (&Qoverriding_terminal_local_map);
7079aefa 21873 Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
d46fb96a 21874
399164b4
KH
21875 staticpro (&Qoverriding_local_map);
21876 Qoverriding_local_map = intern ("overriding-local-map");
21877
75c43375
RS
21878 staticpro (&Qwindow_scroll_functions);
21879 Qwindow_scroll_functions = intern ("window-scroll-functions");
21880
e0bfbde6
RS
21881 staticpro (&Qredisplay_end_trigger_functions);
21882 Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
2311178e 21883
2e54982e
RS
21884 staticpro (&Qinhibit_point_motion_hooks);
21885 Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
21886
9499d71b
GM
21887 QCdata = intern (":data");
21888 staticpro (&QCdata);
5f5c8ee5 21889 Qdisplay = intern ("display");
f3751a65 21890 staticpro (&Qdisplay);
5f5c8ee5
GM
21891 Qspace_width = intern ("space-width");
21892 staticpro (&Qspace_width);
5f5c8ee5
GM
21893 Qraise = intern ("raise");
21894 staticpro (&Qraise);
21895 Qspace = intern ("space");
21896 staticpro (&Qspace);
f3751a65
GM
21897 Qmargin = intern ("margin");
21898 staticpro (&Qmargin);
493fdc3c
KS
21899 Qpointer = intern ("pointer");
21900 staticpro (&Qpointer);
5f5c8ee5 21901 Qleft_margin = intern ("left-margin");
f3751a65 21902 staticpro (&Qleft_margin);
5f5c8ee5 21903 Qright_margin = intern ("right-margin");
f3751a65 21904 staticpro (&Qright_margin);
5f5c8ee5
GM
21905 QCalign_to = intern (":align-to");
21906 staticpro (&QCalign_to);
5f5c8ee5
GM
21907 QCrelative_width = intern (":relative-width");
21908 staticpro (&QCrelative_width);
21909 QCrelative_height = intern (":relative-height");
21910 staticpro (&QCrelative_height);
21911 QCeval = intern (":eval");
21912 staticpro (&QCeval);
0fcf414f
RS
21913 QCpropertize = intern (":propertize");
21914 staticpro (&QCpropertize);
886bd6f2
GM
21915 QCfile = intern (":file");
21916 staticpro (&QCfile);
5f5c8ee5
GM
21917 Qfontified = intern ("fontified");
21918 staticpro (&Qfontified);
21919 Qfontification_functions = intern ("fontification-functions");
21920 staticpro (&Qfontification_functions);
5f5c8ee5
GM
21921 Qtrailing_whitespace = intern ("trailing-whitespace");
21922 staticpro (&Qtrailing_whitespace);
21923 Qimage = intern ("image");
21924 staticpro (&Qimage);
493fdc3c
KS
21925 QCmap = intern (":map");
21926 staticpro (&QCmap);
21927 QCpointer = intern (":pointer");
21928 staticpro (&QCpointer);
21929 Qrect = intern ("rect");
21930 staticpro (&Qrect);
21931 Qcircle = intern ("circle");
21932 staticpro (&Qcircle);
21933 Qpoly = intern ("poly");
21934 staticpro (&Qpoly);
ad4f174e
GM
21935 Qmessage_truncate_lines = intern ("message-truncate-lines");
21936 staticpro (&Qmessage_truncate_lines);
af79bccb
RS
21937 Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows");
21938 staticpro (&Qcursor_in_non_selected_windows);
6422c1d7
GM
21939 Qgrow_only = intern ("grow-only");
21940 staticpro (&Qgrow_only);
e1477f43
GM
21941 Qinhibit_menubar_update = intern ("inhibit-menubar-update");
21942 staticpro (&Qinhibit_menubar_update);
30a3f61c
GM
21943 Qinhibit_eval_during_redisplay = intern ("inhibit-eval-during-redisplay");
21944 staticpro (&Qinhibit_eval_during_redisplay);
b384d6f8
GM
21945 Qposition = intern ("position");
21946 staticpro (&Qposition);
21947 Qbuffer_position = intern ("buffer-position");
21948 staticpro (&Qbuffer_position);
21949 Qobject = intern ("object");
21950 staticpro (&Qobject);
cfe03a41
KS
21951 Qbar = intern ("bar");
21952 staticpro (&Qbar);
21953 Qhbar = intern ("hbar");
21954 staticpro (&Qhbar);
21955 Qbox = intern ("box");
21956 staticpro (&Qbox);
21957 Qhollow = intern ("hollow");
21958 staticpro (&Qhollow);
493fdc3c
KS
21959 Qhand = intern ("hand");
21960 staticpro (&Qhand);
21961 Qarrow = intern ("arrow");
21962 staticpro (&Qarrow);
21963 Qtext = intern ("text");
21964 staticpro (&Qtext);
c53a1624
RS
21965 Qrisky_local_variable = intern ("risky-local-variable");
21966 staticpro (&Qrisky_local_variable);
26683087
RS
21967 Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces");
21968 staticpro (&Qinhibit_free_realized_faces);
5f5c8ee5 21969
7033d6df
RS
21970 list_of_error = Fcons (intern ("error"), Qnil);
21971 staticpro (&list_of_error);
21972
a2889657
JB
21973 last_arrow_position = Qnil;
21974 last_arrow_string = Qnil;
f3751a65
GM
21975 staticpro (&last_arrow_position);
21976 staticpro (&last_arrow_string);
2311178e 21977
c6e89d6c
GM
21978 echo_buffer[0] = echo_buffer[1] = Qnil;
21979 staticpro (&echo_buffer[0]);
21980 staticpro (&echo_buffer[1]);
21981
21982 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
21983 staticpro (&echo_area_buffer[0]);
21984 staticpro (&echo_area_buffer[1]);
a2889657 21985
6a94510a
GM
21986 Vmessages_buffer_name = build_string ("*Messages*");
21987 staticpro (&Vmessages_buffer_name);
0fcf414f
RS
21988
21989 mode_line_proptrans_alist = Qnil;
21990 staticpro (&mode_line_proptrans_alist);
2311178e 21991
fec8f23e
KS
21992 mode_line_string_list = Qnil;
21993 staticpro (&mode_line_string_list);
21994
fa3c6b4d
KS
21995 help_echo_string = Qnil;
21996 staticpro (&help_echo_string);
21997 help_echo_object = Qnil;
21998 staticpro (&help_echo_object);
21999 help_echo_window = Qnil;
22000 staticpro (&help_echo_window);
22001 previous_help_echo_string = Qnil;
22002 staticpro (&previous_help_echo_string);
22003 help_echo_pos = -1;
22004
22005#ifdef HAVE_WINDOW_SYSTEM
22006 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
22007 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
22008For example, if a block cursor is over a tab, it will be drawn as
22009wide as that tab on the display. */);
22010 x_stretch_cursor_p = 0;
22011#endif
22012
7ee72033 22013 DEFVAR_LISP ("show-trailing-whitespace", &Vshow_trailing_whitespace,
88e6b646 22014 doc: /* *Non-nil means highlight trailing whitespace.
228299fa 22015The face used for trailing whitespace is `trailing-whitespace'. */);
8f897821
GM
22016 Vshow_trailing_whitespace = Qnil;
22017
7af0e8d7 22018#ifdef HAVE_WINDOW_SYSTEM
88e6b646
KS
22019 DEFVAR_LISP ("overflow-newline-into-fringe", &Voverflow_newline_into_fringe,
22020 doc: /* *Non-nil means that newline may flow into the right fringe.
22021This means that display lines which are exactly as wide as the window
22022(not counting the final newline) will only occupy one screen line, by
22023showing (or hiding) the final newline in the right fringe; when point
22024is at the final newline, the cursor is shown in the right fringe.
22025If nil, also continue lines which are exactly as wide as the window. */);
22026 Voverflow_newline_into_fringe = Qt;
7af0e8d7 22027#endif
88e6b646 22028
493fdc3c 22029 DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer,
88e6b646 22030 doc: /* *The pointer shape to show in void text areas.
493fdc3c
KS
22031Nil means to show the text pointer. Other options are `arrow', `text',
22032`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */);
22033 Vvoid_text_area_pointer = Qarrow;
f65536fa 22034
7ee72033
MB
22035 DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
22036 doc: /* Non-nil means don't actually do any redisplay.
228299fa 22037This is used for internal purposes. */);
735c094c
KH
22038 Vinhibit_redisplay = Qnil;
22039
7ee72033
MB
22040 DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
22041 doc: /* String (or mode line construct) included (normally) in `mode-line-format'. */);
a2889657
JB
22042 Vglobal_mode_string = Qnil;
22043
7ee72033
MB
22044 DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
22045 doc: /* Marker for where to display an arrow on top of the buffer text.
228299fa
GM
22046This must be the beginning of a line in order to work.
22047See also `overlay-arrow-string'. */);
a2889657
JB
22048 Voverlay_arrow_position = Qnil;
22049
7ee72033
MB
22050 DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
22051 doc: /* String to display as an arrow. See also `overlay-arrow-position'. */);
a2889657
JB
22052 Voverlay_arrow_string = Qnil;
22053
7ee72033
MB
22054 DEFVAR_INT ("scroll-step", &scroll_step,
22055 doc: /* *The number of lines to try scrolling a window by when point moves out.
228299fa
GM
22056If that fails to bring point back on frame, point is centered instead.
22057If this is zero, point is always centered after it moves off frame.
22058If you want scrolling to always be a line at a time, you should set
22059`scroll-conservatively' to a large value rather than set this to 1. */);
22060
7ee72033
MB
22061 DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
22062 doc: /* *Scroll up to this many lines, to bring point back on screen.
228299fa
GM
22063A value of zero means to scroll the text to center point vertically
22064in the window. */);
0789adb2
RS
22065 scroll_conservatively = 0;
22066
7ee72033
MB
22067 DEFVAR_INT ("scroll-margin", &scroll_margin,
22068 doc: /* *Number of lines of margin at the top and bottom of a window.
228299fa
GM
22069Recenter the window whenever point gets within this many lines
22070of the top or bottom of the window. */);
9afd2168
RS
22071 scroll_margin = 0;
22072
f65536fa
KS
22073 DEFVAR_LISP ("display-pixels-per-inch", &Vdisplay_pixels_per_inch,
22074 doc: /* Pixels per inch on current display.
22075Value is a number or a cons (WIDTH-DPI . HEIGHT-DPI). */);
22076 Vdisplay_pixels_per_inch = make_float (72.0);
22077
5f5c8ee5 22078#if GLYPH_DEBUG
7ee72033 22079 DEFVAR_INT ("debug-end-pos", &debug_end_pos, doc: /* Don't ask. */);
5f5c8ee5 22080#endif
a2889657
JB
22081
22082 DEFVAR_BOOL ("truncate-partial-width-windows",
7ee72033
MB
22083 &truncate_partial_width_windows,
22084 doc: /* *Non-nil means truncate lines in all windows less than full frame wide. */);
a2889657
JB
22085 truncate_partial_width_windows = 1;
22086
7ee72033
MB
22087 DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
22088 doc: /* nil means display the mode-line/header-line/menu-bar in the default face.
228299fa 22089Any other value means to use the appropriate face, `mode-line',
ccfe8f57 22090`header-line', or `menu' respectively. */);
1862a24e 22091 mode_line_inverse_video = 1;
aa6d10fa 22092
7ee72033
MB
22093 DEFVAR_LISP ("line-number-display-limit", &Vline_number_display_limit,
22094 doc: /* *Maximum buffer size for which line number should be displayed.
228299fa
GM
22095If the buffer is bigger than this, the line number does not appear
22096in the mode line. A value of nil means no limit. */);
090703f4 22097 Vline_number_display_limit = Qnil;
fba9ce76 22098
090703f4 22099 DEFVAR_INT ("line-number-display-limit-width",
7ee72033
MB
22100 &line_number_display_limit_width,
22101 doc: /* *Maximum line width (in characters) for line number display.
228299fa
GM
22102If the average length of the lines near point is bigger than this, then the
22103line number may be omitted from the mode line. */);
5d121aec
KH
22104 line_number_display_limit_width = 200;
22105
7ee72033
MB
22106 DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
22107 doc: /* *Non-nil means highlight region even in nonselected windows. */);
293a54ce 22108 highlight_nonselected_windows = 0;
d39b6696 22109
7ee72033
MB
22110 DEFVAR_BOOL ("multiple-frames", &multiple_frames,
22111 doc: /* Non-nil if more than one frame is visible on this display.
228299fa
GM
22112Minibuffer-only frames don't count, but iconified frames do.
22113This variable is not guaranteed to be accurate except while processing
22114`frame-title-format' and `icon-title-format'. */);
22115
7ee72033
MB
22116 DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
22117 doc: /* Template for displaying the title bar of visible frames.
228299fa
GM
22118\(Assuming the window manager supports this feature.)
22119This variable has the same structure as `mode-line-format' (which see),
22120and is used only on frames for which no explicit name has been set
22121\(see `modify-frame-parameters'). */);
f65536fa 22122
7ee72033
MB
22123 DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
22124 doc: /* Template for displaying the title bar of an iconified frame.
228299fa
GM
22125\(Assuming the window manager supports this feature.)
22126This variable has the same structure as `mode-line-format' (which see),
22127and is used only on frames for which no explicit name has been set
22128\(see `modify-frame-parameters'). */);
d39b6696
KH
22129 Vicon_title_format
22130 = Vframe_title_format
22131 = Fcons (intern ("multiple-frames"),
22132 Fcons (build_string ("%b"),
3ebf0ea9 22133 Fcons (Fcons (empty_string,
d39b6696
KH
22134 Fcons (intern ("invocation-name"),
22135 Fcons (build_string ("@"),
22136 Fcons (intern ("system-name"),
22137 Qnil)))),
22138 Qnil)));
5992c4f7 22139
7ee72033
MB
22140 DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
22141 doc: /* Maximum number of lines to keep in the message log buffer.
228299fa
GM
22142If nil, disable message logging. If t, log messages but don't truncate
22143the buffer when it becomes large. */);
ac90c44f 22144 Vmessage_log_max = make_number (50);
08b610e4 22145
7ee72033
MB
22146 DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
22147 doc: /* Functions called before redisplay, if window sizes have changed.
228299fa
GM
22148The value should be a list of functions that take one argument.
22149Just before redisplay, for each frame, if any of its windows have changed
22150size since the last redisplay, or have been split or deleted,
22151all the functions in the list are called, with the frame as argument. */);
08b610e4 22152 Vwindow_size_change_functions = Qnil;
75c43375 22153
7ee72033
MB
22154 DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
22155 doc: /* List of Functions to call before redisplaying a window with scrolling.
228299fa
GM
22156Each function is called with two arguments, the window
22157and its new display-start position. Note that the value of `window-end'
22158is not valid when these functions are called. */);
75c43375 22159 Vwindow_scroll_functions = Qnil;
2311178e 22160
fa3c6b4d
KS
22161 DEFVAR_BOOL ("mouse-autoselect-window", &mouse_autoselect_window,
22162 doc: /* *Non-nil means autoselect window with mouse pointer. */);
22163 mouse_autoselect_window = 0;
22164
7ee72033
MB
22165 DEFVAR_BOOL ("auto-resize-tool-bars", &auto_resize_tool_bars_p,
22166 doc: /* *Non-nil means automatically resize tool-bars.
228299fa
GM
22167This increases a tool-bar's height if not all tool-bar items are visible.
22168It decreases a tool-bar's height when it would display blank lines
22169otherwise. */);
e037b9ec 22170 auto_resize_tool_bars_p = 1;
2311178e 22171
7ee72033
MB
22172 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", &auto_raise_tool_bar_buttons_p,
22173 doc: /* *Non-nil means raise tool-bar buttons when the mouse moves over them. */);
e037b9ec 22174 auto_raise_tool_bar_buttons_p = 1;
5f5c8ee5 22175
7ee72033
MB
22176 DEFVAR_LISP ("tool-bar-button-margin", &Vtool_bar_button_margin,
22177 doc: /* *Margin around tool-bar buttons in pixels.
228299fa 22178If an integer, use that for both horizontal and vertical margins.
f6c89f27 22179Otherwise, value should be a pair of integers `(HORZ . VERT)' with
228299fa
GM
22180HORZ specifying the horizontal margin, and VERT specifying the
22181vertical margin. */);
c3d76173 22182 Vtool_bar_button_margin = make_number (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
5f5c8ee5 22183
7ee72033 22184 DEFVAR_INT ("tool-bar-button-relief", &tool_bar_button_relief,
6da3c85b 22185 doc: /* *Relief thickness of tool-bar buttons. */);
c3d76173 22186 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
5f5c8ee5 22187
7ee72033
MB
22188 DEFVAR_LISP ("fontification-functions", &Vfontification_functions,
22189 doc: /* List of functions to call to fontify regions of text.
228299fa
GM
22190Each function is called with one argument POS. Functions must
22191fontify a region starting at POS in the current buffer, and give
22192fontified regions the property `fontified'. */);
5f5c8ee5 22193 Vfontification_functions = Qnil;
6b9f0906 22194 Fmake_variable_buffer_local (Qfontification_functions);
7bbe686f
AI
22195
22196 DEFVAR_BOOL ("unibyte-display-via-language-environment",
7ee72033
MB
22197 &unibyte_display_via_language_environment,
22198 doc: /* *Non-nil means display unibyte text according to language environment.
228299fa
GM
22199Specifically this means that unibyte non-ASCII characters
22200are displayed by converting them to the equivalent multibyte characters
22201according to the current language environment. As a result, they are
22202displayed according to the current fontset. */);
7bbe686f 22203 unibyte_display_via_language_environment = 0;
c6e89d6c 22204
7ee72033
MB
22205 DEFVAR_LISP ("max-mini-window-height", &Vmax_mini_window_height,
22206 doc: /* *Maximum height for resizing mini-windows.
228299fa
GM
22207If a float, it specifies a fraction of the mini-window frame's height.
22208If an integer, it specifies a number of lines. */);
c6e89d6c 22209 Vmax_mini_window_height = make_float (0.25);
6422c1d7 22210
7ee72033
MB
22211 DEFVAR_LISP ("resize-mini-windows", &Vresize_mini_windows,
22212 doc: /* *How to resize mini-windows.
228299fa
GM
22213A value of nil means don't automatically resize mini-windows.
22214A value of t means resize them to fit the text displayed in them.
22215A value of `grow-only', the default, means let mini-windows grow
22216only, until their display becomes empty, at which point the windows
22217go back to their normal size. */);
6422c1d7
GM
22218 Vresize_mini_windows = Qgrow_only;
22219
cfe03a41
KS
22220 DEFVAR_LISP ("cursor-in-non-selected-windows",
22221 &Vcursor_in_non_selected_windows,
22222 doc: /* *Cursor type to display in non-selected windows.
22223t means to use hollow box cursor. See `cursor-type' for other values. */);
22224 Vcursor_in_non_selected_windows = Qt;
22225
cfe03a41
KS
22226 DEFVAR_LISP ("blink-cursor-alist", &Vblink_cursor_alist,
22227 doc: /* Alist specifying how to blink the cursor off.
22228Each element has the form (ON-STATE . OFF-STATE). Whenever the
22229`cursor-type' frame-parameter or variable equals ON-STATE,
22230comparing using `equal', Emacs uses OFF-STATE to specify
22231how to blink it off. */);
22232 Vblink_cursor_alist = Qnil;
2311178e 22233
e76d28d5 22234 DEFVAR_BOOL ("auto-hscroll-mode", &automatic_hscrolling_p,
7ee72033 22235 doc: /* *Non-nil means scroll the display automatically to make point visible. */);
d475bcb8 22236 automatic_hscrolling_p = 1;
1df7e8f0 22237
e76d28d5 22238 DEFVAR_INT ("hscroll-margin", &hscroll_margin,
1df7e8f0
EZ
22239 doc: /* *How many columns away from the window edge point is allowed to get
22240before automatic hscrolling will horizontally scroll the window. */);
e76d28d5 22241 hscroll_margin = 5;
1df7e8f0 22242
e76d28d5 22243 DEFVAR_LISP ("hscroll-step", &Vhscroll_step,
1df7e8f0
EZ
22244 doc: /* *How many columns to scroll the window when point gets too close to the edge.
22245When point is less than `automatic-hscroll-margin' columns from the window
22246edge, automatic hscrolling will scroll the window by the amount of columns
22247determined by this variable. If its value is a positive integer, scroll that
22248many columns. If it's a positive floating-point number, it specifies the
22249fraction of the window's width to scroll. If it's nil or zero, point will be
22250centered horizontally after the scroll. Any other value, including negative
22251numbers, are treated as if the value were zero.
22252
22253Automatic hscrolling always moves point outside the scroll margin, so if
22254point was more than scroll step columns inside the margin, the window will
22255scroll more than the value given by the scroll step.
22256
22257Note that the lower bound for automatic hscrolling specified by `scroll-left'
22258and `scroll-right' overrides this variable's effect. */);
e76d28d5 22259 Vhscroll_step = make_number (0);
2311178e 22260
7ee72033
MB
22261 DEFVAR_LISP ("image-types", &Vimage_types,
22262 doc: /* List of supported image types.
228299fa 22263Each element of the list is a symbol for a supported image type. */);
e00daaa0 22264 Vimage_types = Qnil;
2311178e 22265
7ee72033
MB
22266 DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines,
22267 doc: /* If non-nil, messages are truncated instead of resizing the echo area.
228299fa 22268Bind this around calls to `message' to let it take effect. */);
ad4f174e 22269 message_truncate_lines = 0;
0bca8940 22270
7ee72033
MB
22271 DEFVAR_LISP ("menu-bar-update-hook", &Vmenu_bar_update_hook,
22272 doc: /* Normal hook run for clicks on menu bar, before displaying a submenu.
228299fa 22273Can be used to update submenus whose contents should vary. */);
6422c1d7 22274 Vmenu_bar_update_hook = Qnil;
2311178e 22275
7ee72033
MB
22276 DEFVAR_BOOL ("inhibit-menubar-update", &inhibit_menubar_update,
22277 doc: /* Non-nil means don't update menu bars. Internal use only. */);
e1477f43 22278 inhibit_menubar_update = 0;
30a3f61c 22279
7ee72033
MB
22280 DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
22281 doc: /* Non-nil means don't eval Lisp during redisplay. */);
30a3f61c 22282 inhibit_eval_during_redisplay = 0;
76cb5e06 22283
26683087
RS
22284 DEFVAR_BOOL ("inhibit-free-realized-faces", &inhibit_free_realized_faces,
22285 doc: /* Non-nil means don't free realized faces. Internal use only. */);
22286 inhibit_free_realized_faces = 0;
22287
69d1f7c9 22288#if GLYPH_DEBUG
76cb5e06
GM
22289 DEFVAR_BOOL ("inhibit-try-window-id", &inhibit_try_window_id,
22290 doc: /* Inhibit try_window_id display optimization. */);
22291 inhibit_try_window_id = 0;
22292
22293 DEFVAR_BOOL ("inhibit-try-window-reusing", &inhibit_try_window_reusing,
22294 doc: /* Inhibit try_window_reusing display optimization. */);
22295 inhibit_try_window_reusing = 0;
22296
22297 DEFVAR_BOOL ("inhibit-try-cursor-movement", &inhibit_try_cursor_movement,
22298 doc: /* Inhibit try_cursor_movement display optimization. */);
22299 inhibit_try_cursor_movement = 0;
22300#endif /* GLYPH_DEBUG */
a2889657
JB
22301}
22302
5f5c8ee5
GM
22303
22304/* Initialize this module when Emacs starts. */
22305
dfcf069d 22306void
a2889657
JB
22307init_xdisp ()
22308{
22309 Lisp_Object root_window;
5f5c8ee5 22310 struct window *mini_w;
a2889657 22311
04612a64
GM
22312 current_header_line_height = current_mode_line_height = -1;
22313
5f5c8ee5 22314 CHARPOS (this_line_start_pos) = 0;
a2889657
JB
22315
22316 mini_w = XWINDOW (minibuf_window);
11e82b76 22317 root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
a2889657 22318
a2889657
JB
22319 if (!noninteractive)
22320 {
5f5c8ee5
GM
22321 struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
22322 int i;
22323
da8b7f4f 22324 XWINDOW (root_window)->top_line = make_number (FRAME_TOP_MARGIN (f));
12c226c5 22325 set_window_height (root_window,
da8b7f4f 22326 FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f),
12c226c5 22327 0);
da8b7f4f 22328 mini_w->top_line = make_number (FRAME_LINES (f) - 1);
a2889657
JB
22329 set_window_height (minibuf_window, 1, 0);
22330
da8b7f4f
KS
22331 XWINDOW (root_window)->total_cols = make_number (FRAME_COLS (f));
22332 mini_w->total_cols = make_number (FRAME_COLS (f));
5f5c8ee5
GM
22333
22334 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
22335 scratch_glyph_row.glyphs[TEXT_AREA + 1]
22336 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
22337
2311178e 22338 /* The default ellipsis glyphs `...'. */
5f5c8ee5 22339 for (i = 0; i < 3; ++i)
ac90c44f 22340 default_invis_vector[i] = make_number ('.');
a2889657 22341 }
5f5c8ee5 22342
5f5c8ee5 22343 {
93da8435
SM
22344 /* Allocate the buffer for frame titles.
22345 Also used for `format-mode-line'. */
5f5c8ee5
GM
22346 int size = 100;
22347 frame_title_buf = (char *) xmalloc (size);
22348 frame_title_buf_end = frame_title_buf + size;
22349 frame_title_ptr = NULL;
22350 }
2311178e 22351
21fdfb65 22352 help_echo_showing_p = 0;
a2889657 22353}
5f5c8ee5
GM
22354
22355
ab5796a9
MB
22356/* arch-tag: eacc864d-bb6a-4b74-894a-1a4399a1358b
22357 (do not change this comment) */